@adhdev/daemon-standalone 0.9.82-rc.350 → 0.9.82-rc.352

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
@@ -30036,10 +30036,10 @@ var require_dist3 = __commonJS({
30036
30036
  }
30037
30037
  function getDaemonBuildInfo() {
30038
30038
  if (cached2) return cached2;
30039
- const commit = readInjected(true ? "f066449c7e758daf63ad40d431a5e97fc8d79a0e" : void 0) ?? "unknown";
30040
- const commitShort = readInjected(true ? "f066449c" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
30041
- const version2 = readInjected(true ? "0.9.82-rc.350" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
30042
- const builtAt = readInjected(true ? "2026-06-21T19:33:42.557Z" : void 0);
30039
+ const commit = readInjected(true ? "ca5f944b7763a621357fc28a9f62ac398b0ced6c" : void 0) ?? "unknown";
30040
+ const commitShort = readInjected(true ? "ca5f944b" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
30041
+ const version2 = readInjected(true ? "0.9.82-rc.352" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
30042
+ const builtAt = readInjected(true ? "2026-06-22T07:17:32.309Z" : void 0);
30043
30043
  cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
30044
30044
  return cached2;
30045
30045
  }
@@ -32936,6 +32936,7 @@ Follow these recovery rules:
32936
32936
  var LEVEL_NUM;
32937
32937
  var LEVEL_LABEL;
32938
32938
  var currentLevel;
32939
+ var ADHDEV_HOME;
32939
32940
  var LOG_DIR;
32940
32941
  var MAX_LOG_SIZE;
32941
32942
  var MAX_LOG_DAYS;
@@ -32961,7 +32962,8 @@ Follow these recovery rules:
32961
32962
  LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
32962
32963
  LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
32963
32964
  currentLevel = "info";
32964
- LOG_DIR = process.platform === "win32" ? path9.join(process.env.LOCALAPPDATA || process.env.APPDATA || path9.join(os32.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path9.join(os32.homedir(), "Library", "Logs", "adhdev") : path9.join(os32.homedir(), ".local", "share", "adhdev", "logs");
32965
+ ADHDEV_HOME = process.env.ADHDEV_CONFIG_DIR && process.env.ADHDEV_CONFIG_DIR.trim() ? process.env.ADHDEV_CONFIG_DIR.trim() : path9.join(os32.homedir(), ".adhdev");
32966
+ LOG_DIR = path9.join(ADHDEV_HOME, "logs");
32965
32967
  MAX_LOG_SIZE = 5 * 1024 * 1024;
32966
32968
  MAX_LOG_DAYS = 7;
32967
32969
  try {
@@ -33774,6 +33776,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
33774
33776
  nodeSatisfiesRequiredTags: () => nodeSatisfiesRequiredTags,
33775
33777
  normalizeMeshCapabilityTags: () => normalizeMeshCapabilityTags,
33776
33778
  normalizeMeshTaskMode: () => normalizeMeshTaskMode,
33779
+ reclaimStrandedAssignedTask: () => reclaimStrandedAssignedTask,
33777
33780
  recordDirectDispatchTask: () => recordDirectDispatchTask,
33778
33781
  recordMeshToolCall: () => recordMeshToolCall,
33779
33782
  recordTaskAutoLaunch: () => recordTaskAutoLaunch,
@@ -34209,6 +34212,52 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
34209
34212
  return entry;
34210
34213
  });
34211
34214
  }
34215
+ function reclaimStrandedAssignedTask(meshId, taskId, opts) {
34216
+ requireMeshHostQueueOwner(opts);
34217
+ return withQueueLock(meshId, () => {
34218
+ const entry = MeshRuntimeStore.getInstance().findQueueEntryById(meshId, taskId);
34219
+ if (!entry) return null;
34220
+ if (entry.status !== "assigned") return null;
34221
+ const now = (/* @__PURE__ */ new Date()).toISOString();
34222
+ const reason = opts?.reason || "assigned_stranded_dispatch_unconfirmed";
34223
+ const reclaims = (entry.strandedReclaimCount || 0) + 1;
34224
+ const prevNode = entry.assignedNodeId;
34225
+ const prevSession = entry.assignedSessionId;
34226
+ delete entry.assignedNodeId;
34227
+ delete entry.assignedSessionId;
34228
+ delete entry.assignedProviderType;
34229
+ delete entry.dispatchTimestamp;
34230
+ entry.strandedReclaimCount = reclaims;
34231
+ entry.updatedAt = now;
34232
+ if (reclaims > MAX_STRANDED_RECLAIMS) {
34233
+ entry.status = "failed";
34234
+ entry.cancelReason = `stranded_dispatch_unrecovered: reclaimed ${reclaims - 1} time(s) without a confirmed dispatch`;
34235
+ MeshRuntimeStore.getInstance().updateQueueEntry(entry);
34236
+ propagateDependencyFailure(meshId, taskId);
34237
+ } else {
34238
+ entry.status = "pending";
34239
+ entry.requeuedAt = now;
34240
+ entry.requeueReason = reason;
34241
+ MeshRuntimeStore.getInstance().updateQueueEntry(entry);
34242
+ }
34243
+ try {
34244
+ appendLedgerEntry(meshId, {
34245
+ kind: "task_reclaimed",
34246
+ nodeId: prevNode,
34247
+ sessionId: prevSession,
34248
+ payload: {
34249
+ taskId,
34250
+ reason,
34251
+ ...typeof opts?.ageMs === "number" ? { ageMs: opts.ageMs } : {},
34252
+ reclaimCount: reclaims,
34253
+ outcome: entry.status
34254
+ }
34255
+ });
34256
+ } catch {
34257
+ }
34258
+ return entry;
34259
+ });
34260
+ }
34212
34261
  function updateSessionTaskStatus(meshId, sessionId, status, opts) {
34213
34262
  return withQueueLock(meshId, () => {
34214
34263
  const store = MeshRuntimeStore.getInstance();
@@ -34332,6 +34381,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
34332
34381
  var GIT_MUTATION_SUBCOMMANDS;
34333
34382
  var GIT_STASH_READONLY_SUBCOMMANDS;
34334
34383
  var DEPENDENCY_FAILURE_TERMINALS;
34384
+ var MAX_STRANDED_RECLAIMS;
34335
34385
  var init_mesh_work_queue = __esm2({
34336
34386
  "src/mesh/mesh-work-queue.ts"() {
34337
34387
  "use strict";
@@ -34341,6 +34391,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
34341
34391
  init_mesh_runtime_store();
34342
34392
  init_mesh_config();
34343
34393
  init_logger();
34394
+ init_mesh_ledger();
34344
34395
  ACTIVE_MESH_QUEUE_STATUSES = ["pending", "assigned"];
34345
34396
  HISTORICAL_MESH_QUEUE_STATUSES = ["completed", "failed", "cancelled"];
34346
34397
  MESH_TASK_MODES = ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"];
@@ -34393,6 +34444,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
34393
34444
  ]);
34394
34445
  GIT_STASH_READONLY_SUBCOMMANDS = /* @__PURE__ */ new Set(["list", "show"]);
34395
34446
  DEPENDENCY_FAILURE_TERMINALS = /* @__PURE__ */ new Set(["failed", "cancelled"]);
34447
+ MAX_STRANDED_RECLAIMS = 3;
34396
34448
  }
34397
34449
  });
34398
34450
  function loadDatabaseCtor() {
@@ -34454,6 +34506,10 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
34454
34506
  migratedMeshIds = /* @__PURE__ */ new Set();
34455
34507
  fingerprintSweepCounter = 0;
34456
34508
  walWriteCounter = 0;
34509
+ // Independent cadence for the tool-call-log sweep. Must NOT share walWriteCounter:
34510
+ // sharing makes each store's threshold drift by the other's write volume (WAL
34511
+ // checkpoint at 500 vs tool-log sweep at 200 would interfere arbitrarily).
34512
+ toolCallLogCounter = 0;
34457
34513
  static WAL_CHECK_INTERVAL = 500;
34458
34514
  static WAL_MAX_BYTES = 50 * 1024 * 1024;
34459
34515
  // 50 MB
@@ -35276,6 +35332,22 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
35276
35332
  updatedAt: r.updated_at
35277
35333
  }));
35278
35334
  }
35335
+ /**
35336
+ * Bug B watchdog support: true when at least one delivery record for the task has
35337
+ * reached a confirmed-handed-off status (delivered / acked / completed). The
35338
+ * assigned-stranded watchdog uses this to distinguish a dispatch that was never
35339
+ * confirmed (reclaimable) from one that WAS handed to the worker (a genuinely
35340
+ * in-flight or completion-lost task, which is PHASE 4's responsibility, not this
35341
+ * watchdog's). Indexed by (mesh_id, task_id).
35342
+ */
35343
+ taskHasConfirmedDelivery(meshId, taskId) {
35344
+ const row = this.db.prepare(`
35345
+ SELECT 1 FROM mesh_session_delivery
35346
+ WHERE mesh_id = ? AND task_id = ? AND status IN ('delivered','acked','completed')
35347
+ LIMIT 1
35348
+ `).get(meshId, taskId);
35349
+ return !!row;
35350
+ }
35279
35351
  expireStaleSessionDeliveries(meshId) {
35280
35352
  const now = (/* @__PURE__ */ new Date()).toISOString();
35281
35353
  this.db.prepare(`
@@ -35347,7 +35419,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
35347
35419
  "SELECT COUNT(*) as cnt FROM mesh_tool_call_log WHERE mesh_id = ? AND tool = ? AND called_at >= ?"
35348
35420
  ).get(meshId, tool, windowStart);
35349
35421
  const callsInWindow = row?.cnt ?? 0;
35350
- if (++this.walWriteCounter % 200 === 0) {
35422
+ if (++this.toolCallLogCounter % 200 === 0) {
35351
35423
  this.db.prepare(
35352
35424
  "DELETE FROM mesh_tool_call_log WHERE called_at < ?"
35353
35425
  ).run(now - Math.max(windowMs * 10, 6e4));
@@ -35800,9 +35872,9 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
35800
35872
  }
35801
35873
  return targetIds.map((taskId) => {
35802
35874
  const queueEntry = queueById.get(taskId);
35803
- const status = queueEntry?.status ?? "unknown";
35804
35875
  const dispatch = dispatches.get(taskId);
35805
35876
  const terminal = terminals.get(taskId);
35877
+ const status = queueEntry?.status ?? (terminal ? terminal.kind === "task_completed" ? "completed" : "failed" : "unknown");
35806
35878
  const isTerminalStatus = status === "completed" || status === "failed" || status === "cancelled";
35807
35879
  const dispatchTime = parseTime(dispatch?.first ?? queueEntry?.dispatchTimestamp);
35808
35880
  const terminalTime = parseTime(terminal?.at);
@@ -37700,6 +37772,35 @@ ${rendered}`, "utf-8");
37700
37772
  if (!trimmed) return false;
37701
37773
  return normalizeMeshNodeId(node) === trimmed;
37702
37774
  }
37775
+ function machineCoreFromDaemonId(id) {
37776
+ const trimmed = readString5(id);
37777
+ if (!trimmed) return void 0;
37778
+ for (const prefix of DAEMON_ID_PREFIXES) {
37779
+ if (trimmed.startsWith(prefix)) {
37780
+ const core = trimmed.slice(prefix.length).trim();
37781
+ return core || void 0;
37782
+ }
37783
+ }
37784
+ return trimmed;
37785
+ }
37786
+ function expandDaemonIdForms(ids) {
37787
+ const list = Array.isArray(ids) ? ids : ids != null ? [ids] : [];
37788
+ const out = [];
37789
+ const seen = /* @__PURE__ */ new Set();
37790
+ const add = (value) => {
37791
+ if (!value || seen.has(value)) return;
37792
+ seen.add(value);
37793
+ out.push(value);
37794
+ };
37795
+ for (const raw of list) add(readString5(raw));
37796
+ for (const raw of list) {
37797
+ const core = machineCoreFromDaemonId(readString5(raw));
37798
+ if (!core || !core.startsWith("mach_")) continue;
37799
+ add(core);
37800
+ for (const prefix of DAEMON_ID_PREFIXES) add(`${prefix}${core}`);
37801
+ }
37802
+ return out;
37803
+ }
37703
37804
  function summarizeGitShape(status) {
37704
37805
  const record2 = readRecord3(status);
37705
37806
  if (!Object.keys(record2).length) return null;
@@ -37734,9 +37835,11 @@ ${rendered}`, "utf-8");
37734
37835
  submodules
37735
37836
  };
37736
37837
  }
37838
+ var DAEMON_ID_PREFIXES;
37737
37839
  var init_dist = __esm2({
37738
37840
  "../mesh-shared/dist/index.mjs"() {
37739
37841
  "use strict";
37842
+ DAEMON_ID_PREFIXES = ["daemon_", "standalone_"];
37740
37843
  }
37741
37844
  });
37742
37845
  function readString6(value) {
@@ -37812,6 +37915,14 @@ ${rendered}`, "utf-8");
37812
37915
  if (entry.kind === "task_completed") return "idle";
37813
37916
  return "failed";
37814
37917
  }
37918
+ function classifyDirectDispatch(params) {
37919
+ const { status, isTerminalRow, hasTerminalStatus, liveStatus, liveStaleReason, dispatchedToIdleSession } = params;
37920
+ const isNoTransition = !hasTerminalStatus && !liveStatus;
37921
+ const isIdleUnacknowledged = status === "idle";
37922
+ const ledgerOnlyStaleReason = !isTerminalRow && (isIdleUnacknowledged || isNoTransition || dispatchedToIdleSession && isIdleUnacknowledged) ? LEDGER_ONLY_STALE_REASON : void 0;
37923
+ const isFreshUnacknowledged = Boolean(ledgerOnlyStaleReason && !liveStaleReason);
37924
+ return { ledgerOnlyStaleReason, isFreshUnacknowledged };
37925
+ }
37815
37926
  function buildMeshActiveWorkSummary(activeWork) {
37816
37927
  const statusCounts = {
37817
37928
  pending: 0,
@@ -37874,10 +37985,14 @@ ${rendered}`, "utf-8");
37874
37985
  const dbStatus = dispatch.status;
37875
37986
  const isTerminal = dbStatus === "completed" || dbStatus === "failed" || dbStatus === "stale";
37876
37987
  const status = isTerminal ? dbStatus === "completed" ? "idle" : "failed" : live.status || (dbStatus === "acked" ? "generating" : "assigned");
37877
- const isNoTransition = !isTerminal && !live.status;
37878
- const isIdleUnacknowledged = status === "idle" && !isTerminal;
37879
- const ledgerOnlyStaleReason = !isTerminal && (isIdleUnacknowledged || isNoTransition || dispatch.dispatchedToIdleSession && isIdleUnacknowledged) ? "direct task dispatch has no provider acknowledgement, transcript append, or active runtime transition" : void 0;
37880
- const isFreshUnacknowledged = Boolean(ledgerOnlyStaleReason && !live.staleReason);
37988
+ const { ledgerOnlyStaleReason, isFreshUnacknowledged } = classifyDirectDispatch({
37989
+ status,
37990
+ isTerminalRow: isTerminal,
37991
+ hasTerminalStatus: isTerminal,
37992
+ liveStatus: live.status,
37993
+ liveStaleReason: live.staleReason,
37994
+ dispatchedToIdleSession: dispatch.dispatchedToIdleSession === true
37995
+ });
37881
37996
  const { title, summary: summary2 } = summarizeMessage(dispatch.message || "");
37882
37997
  const record2 = {
37883
37998
  taskId: dispatch.taskId,
@@ -37920,13 +38035,16 @@ ${rendered}`, "utf-8");
37920
38035
  const live = sessionStatusFromNodes(opts.nodes, dispatch.nodeId, dispatch.sessionId);
37921
38036
  const status = terminalStatus || live.status || "assigned";
37922
38037
  const terminalRow = Boolean(terminal && terminal.kind !== "task_approval_needed");
37923
- const dispatchedToIdleSession = dispatch.payload?.dispatchedToIdleSession === true;
37924
- const isNoTransition = !terminalStatus && !live.status;
37925
- const isIdleUnacknowledged = status === "idle";
37926
- const ledgerOnlyStaleReason = !terminalRow && (isIdleUnacknowledged || isNoTransition || dispatchedToIdleSession && isIdleUnacknowledged) ? "direct task dispatch has no provider acknowledgement, transcript append, or active runtime transition" : void 0;
38038
+ const { ledgerOnlyStaleReason, isFreshUnacknowledged } = classifyDirectDispatch({
38039
+ status,
38040
+ isTerminalRow: terminalRow,
38041
+ hasTerminalStatus: Boolean(terminalStatus),
38042
+ liveStatus: live.status,
38043
+ liveStaleReason: live.staleReason,
38044
+ dispatchedToIdleSession: dispatch.payload?.dispatchedToIdleSession === true
38045
+ });
37927
38046
  const message = readString6(dispatch.payload?.message) || readString6(dispatch.payload?.summary) || "";
37928
38047
  const { title, summary: summary2 } = summarizeMessage(message);
37929
- const isFreshUnacknowledged = Boolean(ledgerOnlyStaleReason && !live.staleReason);
37930
38048
  const record2 = {
37931
38049
  taskId,
37932
38050
  source: "direct",
@@ -37968,13 +38086,16 @@ ${rendered}`, "utf-8");
37968
38086
  const live = sessionStatusFromNodes(opts.nodes, dispatch.nodeId, dispatch.sessionId);
37969
38087
  const status = terminalStatus || live.status || "assigned";
37970
38088
  const terminalRow = Boolean(terminal && terminal.kind !== "task_approval_needed");
37971
- const dispatchedToIdleSession = dispatch.payload?.dispatchedToIdleSession === true;
37972
- const isNoTransition = !terminalStatus && !live.status;
37973
- const isIdleUnacknowledged = status === "idle";
37974
- const ledgerOnlyStaleReason = !terminalRow && (isIdleUnacknowledged || isNoTransition || dispatchedToIdleSession && isIdleUnacknowledged) ? "direct task dispatch has no provider acknowledgement, transcript append, or active runtime transition" : void 0;
38089
+ const { ledgerOnlyStaleReason, isFreshUnacknowledged } = classifyDirectDispatch({
38090
+ status,
38091
+ isTerminalRow: terminalRow,
38092
+ hasTerminalStatus: Boolean(terminalStatus),
38093
+ liveStatus: live.status,
38094
+ liveStaleReason: live.staleReason,
38095
+ dispatchedToIdleSession: dispatch.payload?.dispatchedToIdleSession === true
38096
+ });
37975
38097
  const message = readString6(dispatch.payload?.message) || readString6(dispatch.payload?.summary) || "";
37976
38098
  const { title, summary: summary2 } = summarizeMessage(message);
37977
- const isFreshUnacknowledged = Boolean(ledgerOnlyStaleReason && !live.staleReason);
37978
38099
  const record2 = {
37979
38100
  taskId,
37980
38101
  source: "direct",
@@ -38127,6 +38248,7 @@ ${rendered}`, "utf-8");
38127
38248
  }
38128
38249
  var DIRECT_DISPATCH_VIA;
38129
38250
  var TERMINAL_LEDGER_KINDS;
38251
+ var LEDGER_ONLY_STALE_REASON;
38130
38252
  var PRUNABLE_ORPHAN_STALE_REASONS;
38131
38253
  var init_mesh_active_work = __esm2({
38132
38254
  "src/mesh/mesh-active-work.ts"() {
@@ -38136,6 +38258,7 @@ ${rendered}`, "utf-8");
38136
38258
  init_dist();
38137
38259
  DIRECT_DISPATCH_VIA = /* @__PURE__ */ new Set(["p2p_direct", "local_direct", "mesh_send_task"]);
38138
38260
  TERMINAL_LEDGER_KINDS = /* @__PURE__ */ new Set(["task_completed", "task_failed", "task_stalled"]);
38261
+ LEDGER_ONLY_STALE_REASON = "direct task dispatch has no provider acknowledgement, transcript append, or active runtime transition";
38139
38262
  PRUNABLE_ORPHAN_STALE_REASONS = /* @__PURE__ */ new Set([
38140
38263
  "direct task node is no longer in the live mesh",
38141
38264
  "direct task session is not present in live session records",
@@ -38371,17 +38494,7 @@ Next step: ${nextStep}`;
38371
38494
  }
38372
38495
  });
38373
38496
  function normalizeCoordinatorDaemonIds(coordinatorDaemonId) {
38374
- const raw = Array.isArray(coordinatorDaemonId) ? coordinatorDaemonId : coordinatorDaemonId != null ? [coordinatorDaemonId] : [];
38375
- const seen = /* @__PURE__ */ new Set();
38376
- const out = [];
38377
- for (const id of raw) {
38378
- if (typeof id !== "string") continue;
38379
- const trimmed = id.trim();
38380
- if (!trimmed || seen.has(trimmed)) continue;
38381
- seen.add(trimmed);
38382
- out.push(trimmed);
38383
- }
38384
- return out;
38497
+ return expandDaemonIdForms(coordinatorDaemonId);
38385
38498
  }
38386
38499
  function readRefineJobId2(event) {
38387
38500
  const metadata = readRecord4(event.metadataEvent) || event;
@@ -38569,6 +38682,7 @@ Next step: ${nextStep}`;
38569
38682
  return true;
38570
38683
  }
38571
38684
  const fingerprint = buildPendingEventFingerprint(event);
38685
+ let sqliteOk = false;
38572
38686
  try {
38573
38687
  MeshRuntimeStore.getInstance().insertPendingEvent({
38574
38688
  id: (0, import_crypto7.randomUUID)(),
@@ -38579,11 +38693,17 @@ Next step: ${nextStep}`;
38579
38693
  fingerprint: fingerprint || null,
38580
38694
  queuedAt: event.queuedAt
38581
38695
  });
38696
+ sqliteOk = true;
38582
38697
  } catch {
38583
38698
  }
38584
- const path422 = getPendingEventsPath(event.meshId, event.targetCoordinatorDaemonId);
38585
- trimPendingEventsIfNeeded(path422);
38586
- (0, import_fs10.appendFileSync)(path422, JSON.stringify(event) + "\n", "utf-8");
38699
+ try {
38700
+ const path422 = getPendingEventsPath(event.meshId, event.targetCoordinatorDaemonId);
38701
+ trimPendingEventsIfNeeded(path422);
38702
+ (0, import_fs10.appendFileSync)(path422, JSON.stringify(event) + "\n", "utf-8");
38703
+ } catch (e) {
38704
+ if (!sqliteOk) throw e;
38705
+ LOG2.warn("MeshEvents", `JSONL append failed for mesh ${event.meshId}; SQLite holds the event: ${e?.message || e}`);
38706
+ }
38587
38707
  return true;
38588
38708
  } catch (e) {
38589
38709
  LOG2.warn("MeshEvents", `Failed to persist pending coordinator event: ${e?.message || e}`);
@@ -38769,6 +38889,7 @@ Next step: ${nextStep}`;
38769
38889
  init_mesh_ledger();
38770
38890
  init_mesh_runtime_store();
38771
38891
  init_mesh_events_utils();
38892
+ init_dist();
38772
38893
  REFINE_TERMINAL_EVENTS = /* @__PURE__ */ new Set(["refine:completed", "refine:failed"]);
38773
38894
  MAX_PENDING_EVENTS_BYTES = 100 * 1024;
38774
38895
  MAX_PENDING_EVENTS_KEEP = 50;
@@ -38986,6 +39107,12 @@ Next step: ${nextStep}`;
38986
39107
  }
38987
39108
  return false;
38988
39109
  }
39110
+ function isWeakCompletionLedgerPayload(payload) {
39111
+ if (!payload) return false;
39112
+ if (payload.evidenceLevel === "insufficient" || payload.reviewRecommended === true) return true;
39113
+ const diag = readRecord4(payload.completionDiagnostic);
39114
+ return diag?.finalAssistantPresent === false || diag?.blockReason === "missing_final_assistant";
39115
+ }
38989
39116
  function findDirectDispatchLedgerEntry(args) {
38990
39117
  const entries = readLedgerEntries(args.meshId, { tail: 500 });
38991
39118
  for (let i = entries.length - 1; i >= 0; i--) {
@@ -39022,6 +39149,7 @@ Next step: ${nextStep}`;
39022
39149
  if (!afterDispatch) continue;
39023
39150
  }
39024
39151
  if (entry.kind !== "task_completed" && entry.kind !== "task_failed" && entry.kind !== "task_stalled") continue;
39152
+ if (entry.kind === "task_completed" && isWeakCompletionLedgerPayload(entry.payload)) continue;
39025
39153
  const terminalTaskId = readNonEmptyString2(entry.payload?.taskId);
39026
39154
  if (terminalTaskId && terminalTaskId === args.taskId) return true;
39027
39155
  if (terminalTaskId && terminalTaskId !== args.taskId) continue;
@@ -42219,12 +42347,9 @@ ${cleanBody}`;
42219
42347
  }
42220
42348
  });
42221
42349
  function resolveCoordinatorDrainDaemonIds(components) {
42222
- const ids = /* @__PURE__ */ new Set();
42223
42350
  const statusInstanceId = readNonEmptyString2(components.statusInstanceId);
42224
- if (statusInstanceId) ids.add(statusInstanceId);
42225
42351
  const machineId = readNonEmptyString2(loadConfig2().machineId);
42226
- if (machineId) ids.add(machineId);
42227
- return [...ids];
42352
+ return expandDaemonIdForms([statusInstanceId, machineId]);
42228
42353
  }
42229
42354
  function getCachedMeshByWorkspace(workspace) {
42230
42355
  const now = Date.now();
@@ -42351,6 +42476,79 @@ ${cleanBody}`;
42351
42476
  recordFingerprintSeen(fingerprint);
42352
42477
  return false;
42353
42478
  }
42479
+ function isFalseIdleCompletion(metadataEvent) {
42480
+ const diag = readRecord4(metadataEvent.completionDiagnostic);
42481
+ if (!diag) return false;
42482
+ return diag.finalAssistantPresent === false || diag.blockReason === "missing_final_assistant";
42483
+ }
42484
+ function isGenuineCompletionEvidence(metadataEvent) {
42485
+ if (isFalseIdleCompletion(metadataEvent)) return false;
42486
+ return !!readWorkerResultMetadata(metadataEvent) || !!readNonEmptyString2(metadataEvent.finalSummary);
42487
+ }
42488
+ function isWeakTerminalLedgerPayload(payload) {
42489
+ if (!payload) return false;
42490
+ if (payload.evidenceLevel === "insufficient" || payload.reviewRecommended === true) return true;
42491
+ const diag = readRecord4(payload.completionDiagnostic);
42492
+ return diag?.finalAssistantPresent === false || diag?.blockReason === "missing_final_assistant";
42493
+ }
42494
+ function resolveActiveDirectDispatchTaskId(meshId, sessionId) {
42495
+ try {
42496
+ const matches = getActiveDirectDispatches(meshId).filter((d) => d.sessionId === sessionId);
42497
+ if (!matches.length) return void 0;
42498
+ return readNonEmptyString2(matches[matches.length - 1].taskId) || void 0;
42499
+ } catch {
42500
+ return void 0;
42501
+ }
42502
+ }
42503
+ function deliverTaskToSession(dispatchThunk, ctx) {
42504
+ const delivery = createSessionDelivery({
42505
+ meshId: ctx.meshId,
42506
+ nodeId: ctx.nodeId,
42507
+ sessionId: ctx.sessionId,
42508
+ providerType: ctx.providerType,
42509
+ taskId: ctx.task.id,
42510
+ kind: "task",
42511
+ message: ctx.task.message,
42512
+ status: "delivering",
42513
+ ...ctx.sourceCoordinatorSessionId ? { sourceCoordinatorSessionId: ctx.sourceCoordinatorSessionId } : {},
42514
+ ...ctx.sourceCoordinatorDaemonId ? { sourceCoordinatorDaemonId: ctx.sourceCoordinatorDaemonId } : {}
42515
+ });
42516
+ let dispatchPromise;
42517
+ try {
42518
+ dispatchPromise = Promise.resolve(dispatchThunk());
42519
+ } catch (e) {
42520
+ dispatchPromise = Promise.reject(e);
42521
+ }
42522
+ let timer;
42523
+ const guarded = Promise.race([
42524
+ dispatchPromise,
42525
+ new Promise((_, reject) => {
42526
+ timer = setTimeout(
42527
+ () => reject(new Error(`dispatch_confirm_timeout after ${DISPATCH_CONFIRM_TIMEOUT_MS}ms`)),
42528
+ DISPATCH_CONFIRM_TIMEOUT_MS
42529
+ );
42530
+ if (typeof timer?.unref === "function") timer.unref();
42531
+ })
42532
+ ]);
42533
+ guarded.then(() => {
42534
+ if (timer) clearTimeout(timer);
42535
+ updateSessionDeliveryStatus(delivery.id, "delivered");
42536
+ }).catch((e) => {
42537
+ if (timer) clearTimeout(timer);
42538
+ LOG2.error("MeshQueue", `Failed to dispatch task via ${ctx.transport} to node ${ctx.nodeId}: ${e?.message}`);
42539
+ updateSessionDeliveryStatus(delivery.id, "failed", { lastError: e?.message, incrementAttempt: true });
42540
+ updateTaskStatus(ctx.meshId, ctx.task.id, "pending");
42541
+ try {
42542
+ appendLedgerEntry(ctx.meshId, {
42543
+ kind: "dispatch_failed",
42544
+ nodeId: ctx.nodeId,
42545
+ sessionId: ctx.sessionId,
42546
+ payload: { taskId: ctx.task.id, deliveryId: delivery.id, error: e?.message, retryable: true, transport: ctx.transport }
42547
+ });
42548
+ } catch {
42549
+ }
42550
+ });
42551
+ }
42354
42552
  function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType) {
42355
42553
  const mesh = getMeshWithCache(components, meshId);
42356
42554
  const node = mesh?.nodes.find((n) => readMeshNodeId(n) === nodeId);
@@ -42369,46 +42567,33 @@ ${cleanBody}`;
42369
42567
  if (!isLocalNode) {
42370
42568
  const localDaemonIdForDispatch = readNonEmptyString2(loadConfig2().machineId) || void 0;
42371
42569
  const sourceCoordinatorSessionId = readNonEmptyString2(task.sourceCoordinatorSessionId) || void 0;
42372
- const delivery2 = createSessionDelivery({
42373
- meshId,
42374
- nodeId,
42375
- sessionId,
42376
- providerType,
42377
- taskId: task.id,
42378
- kind: "task",
42379
- message: task.message,
42380
- status: "delivering",
42381
- ...sourceCoordinatorSessionId ? { sourceCoordinatorSessionId } : {},
42382
- ...localDaemonIdForDispatch ? { sourceCoordinatorDaemonId: localDaemonIdForDispatch } : {}
42383
- });
42384
- components.dispatchMeshCommand(node.daemonId, "agent_command", {
42385
- targetSessionId: sessionId,
42386
- cliType: providerType,
42387
- action: "send_chat",
42388
- message: task.message,
42389
- meshContext: {
42570
+ const dispatchMeshCommand = components.dispatchMeshCommand;
42571
+ const remoteDaemonId = node.daemonId;
42572
+ deliverTaskToSession(
42573
+ () => dispatchMeshCommand(remoteDaemonId, "agent_command", {
42574
+ targetSessionId: sessionId,
42575
+ cliType: providerType,
42576
+ action: "send_chat",
42577
+ message: task.message,
42578
+ meshContext: {
42579
+ meshId,
42580
+ nodeId,
42581
+ taskId: task.id,
42582
+ ...localDaemonIdForDispatch ? { coordinatorDaemonId: localDaemonIdForDispatch } : {},
42583
+ ...sourceCoordinatorSessionId ? { coordinatorSessionId: sourceCoordinatorSessionId } : {}
42584
+ }
42585
+ }),
42586
+ {
42390
42587
  meshId,
42391
42588
  nodeId,
42392
- taskId: task.id,
42393
- ...localDaemonIdForDispatch ? { coordinatorDaemonId: localDaemonIdForDispatch } : {},
42394
- ...sourceCoordinatorSessionId ? { coordinatorSessionId: sourceCoordinatorSessionId } : {}
42395
- }
42396
- }).then(() => {
42397
- updateSessionDeliveryStatus(delivery2.id, "delivered");
42398
- }).catch((e) => {
42399
- LOG2.error("MeshQueue", `Failed to dispatch task via P2P to remote node ${nodeId}: ${e?.message}`);
42400
- updateSessionDeliveryStatus(delivery2.id, "failed", { lastError: e?.message, incrementAttempt: true });
42401
- updateTaskStatus(meshId, task.id, "pending");
42402
- try {
42403
- appendLedgerEntry(meshId, {
42404
- kind: "dispatch_failed",
42405
- nodeId,
42406
- sessionId,
42407
- payload: { taskId: task.id, deliveryId: delivery2.id, error: e?.message, retryable: true }
42408
- });
42409
- } catch {
42589
+ sessionId,
42590
+ providerType,
42591
+ task,
42592
+ transport: "remote",
42593
+ ...sourceCoordinatorSessionId ? { sourceCoordinatorSessionId } : {},
42594
+ ...localDaemonIdForDispatch ? { sourceCoordinatorDaemonId: localDaemonIdForDispatch } : {}
42410
42595
  }
42411
- });
42596
+ );
42412
42597
  return true;
42413
42598
  }
42414
42599
  }
@@ -42430,39 +42615,24 @@ ${cleanBody}`;
42430
42615
  }
42431
42616
  } catch {
42432
42617
  }
42433
- const delivery = createSessionDelivery({
42434
- meshId,
42435
- nodeId,
42436
- sessionId,
42437
- providerType,
42438
- taskId: task.id,
42439
- kind: "task",
42440
- message: task.message,
42441
- status: "delivering",
42442
- ...readNonEmptyString2(task.sourceCoordinatorSessionId) ? { sourceCoordinatorSessionId: readNonEmptyString2(task.sourceCoordinatorSessionId) } : {},
42443
- ...readNonEmptyString2(loadConfig2().machineId) ? { sourceCoordinatorDaemonId: readNonEmptyString2(loadConfig2().machineId) } : {}
42444
- });
42445
- components.cliManager.handleCliCommand("agent_command", {
42446
- targetSessionId: sessionId,
42447
- cliType: providerType,
42448
- action: "send_chat",
42449
- message: task.message
42450
- }).then(() => {
42451
- updateSessionDeliveryStatus(delivery.id, "delivered");
42452
- }).catch((e) => {
42453
- LOG2.error("MeshQueue", `Failed to dispatch task locally to node ${nodeId}: ${e?.message}`);
42454
- updateSessionDeliveryStatus(delivery.id, "failed", { lastError: e?.message, incrementAttempt: true });
42455
- updateTaskStatus(meshId, task.id, "pending");
42456
- try {
42457
- appendLedgerEntry(meshId, {
42458
- kind: "dispatch_failed",
42459
- nodeId,
42460
- sessionId,
42461
- payload: { taskId: task.id, deliveryId: delivery.id, error: e?.message, retryable: true }
42462
- });
42463
- } catch {
42618
+ deliverTaskToSession(
42619
+ () => components.cliManager.handleCliCommand("agent_command", {
42620
+ targetSessionId: sessionId,
42621
+ cliType: providerType,
42622
+ action: "send_chat",
42623
+ message: task.message
42624
+ }),
42625
+ {
42626
+ meshId,
42627
+ nodeId,
42628
+ sessionId,
42629
+ providerType,
42630
+ task,
42631
+ transport: "local",
42632
+ ...readNonEmptyString2(task.sourceCoordinatorSessionId) ? { sourceCoordinatorSessionId: readNonEmptyString2(task.sourceCoordinatorSessionId) } : {},
42633
+ ...readNonEmptyString2(loadConfig2().machineId) ? { sourceCoordinatorDaemonId: readNonEmptyString2(loadConfig2().machineId) } : {}
42464
42634
  }
42465
- });
42635
+ );
42466
42636
  return true;
42467
42637
  }
42468
42638
  function sweepExpiredCooldowns() {
@@ -42727,7 +42897,7 @@ ${cleanBody}`;
42727
42897
  }
42728
42898
  }
42729
42899
  const candidateNodes = Array.isArray(mesh?.nodes) ? mesh.nodes.filter((node) => {
42730
- if (task.targetNodeId && readMeshNodeId(node) !== task.targetNodeId) return false;
42900
+ if (task.targetNodeId && !meshNodeIdMatches(node, task.targetNodeId)) return false;
42731
42901
  if (task.requiredTags?.length) {
42732
42902
  const priorities = normalizeProviderPriority(node?.policy);
42733
42903
  const providerCandidates = priorities.length ? priorities : [void 0];
@@ -42738,7 +42908,12 @@ ${cleanBody}`;
42738
42908
  return true;
42739
42909
  }) : [];
42740
42910
  if (!candidateNodes.length) {
42741
- markAutoLaunch(meshId, task.id, { status: "skipped", reason: "no_node_satisfies_required_tags", nodeId: task.targetNodeId });
42911
+ const targetPinUnmatched = !!task.targetNodeId && !(Array.isArray(mesh?.nodes) && mesh.nodes.some((n) => meshNodeIdMatches(n, task.targetNodeId)));
42912
+ markAutoLaunch(meshId, task.id, {
42913
+ status: "skipped",
42914
+ reason: targetPinUnmatched ? "target_node_id_unmatched" : "no_node_satisfies_required_tags",
42915
+ nodeId: task.targetNodeId
42916
+ });
42742
42917
  continue;
42743
42918
  }
42744
42919
  const strategy = resolveSchedulingStrategy(mesh);
@@ -43195,7 +43370,8 @@ ${cleanBody}`;
43195
43370
  });
43196
43371
  if (terminal?.kind === "task_completed" && !sessionHasActiveAssignment(args.meshId, eventSessionId)) {
43197
43372
  const newDispatchAfterTerminal = hasDispatchAfterTerminal(args.meshId, eventSessionId, terminal.id);
43198
- if (!newDispatchAfterTerminal) {
43373
+ const supersedesWeakTerminal = isWeakTerminalLedgerPayload(terminal.payload) && isGenuineCompletionEvidence(args.metadataEvent);
43374
+ if (!newDispatchAfterTerminal && !supersedesWeakTerminal) {
43199
43375
  const terminalProviderSessionId = readNonEmptyString2(terminal.payload.providerSessionId);
43200
43376
  const terminalFinalSummary = readNonEmptyString2(terminal.payload.finalSummary);
43201
43377
  const eventProviderSessionId = readNonEmptyString2(args.metadataEvent.providerSessionId);
@@ -43241,24 +43417,30 @@ ${cleanBody}`;
43241
43417
  return { success: true, forwarded: 0, suppressed: true, duplicateStopped: true };
43242
43418
  }
43243
43419
  }
43244
- function markSessionTerminal(sessionId, outcome, occurredAtMs) {
43420
+ function markSessionTerminal(sessionId, outcome, occurredAtMs, opts) {
43245
43421
  const eventTaskId = readNonEmptyString2(args.metadataEvent.taskId) || void 0;
43246
43422
  const task = updateSessionTaskStatus(args.meshId, sessionId, outcome, {
43247
43423
  occurredAt: occurredAtMs != null ? new Date(occurredAtMs).toISOString() : void 0,
43248
43424
  taskId: eventTaskId
43249
43425
  });
43250
- updateDirectDispatchStatus(args.meshId, sessionId, outcome);
43426
+ const leaveDirectDispatchActive = !task && opts?.tentativeIfDirect === true;
43427
+ if (!leaveDirectDispatchActive) {
43428
+ updateDirectDispatchStatus(args.meshId, sessionId, outcome);
43429
+ }
43251
43430
  markSessionDeliveriesTerminal(args.meshId, sessionId, outcome);
43252
43431
  setImmediate(() => cleanupTerminalDirectDispatches());
43253
43432
  return task ? { id: task.id } : null;
43254
43433
  }
43255
43434
  let completedTaskForLedger = null;
43435
+ let directDispatchTaskIdForLedger;
43256
43436
  if (args.event === "agent:generating_completed") {
43257
43437
  const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
43258
43438
  const nodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
43259
43439
  const providerType = readNonEmptyString2(args.metadataEvent.providerType);
43260
43440
  if (sessionId) {
43261
- completedTaskForLedger = markSessionTerminal(sessionId, "completed", eventTimestamp);
43441
+ directDispatchTaskIdForLedger = resolveActiveDirectDispatchTaskId(args.meshId, sessionId);
43442
+ const isFalseIdle = isFalseIdleCompletion(args.metadataEvent);
43443
+ completedTaskForLedger = markSessionTerminal(sessionId, "completed", eventTimestamp, { tentativeIfDirect: isFalseIdle });
43262
43444
  if (nodeId && providerType) {
43263
43445
  runIdleMaintenanceThenAssignQueue(components, { meshId: args.meshId, nodeId, sessionId, providerType });
43264
43446
  }
@@ -43361,6 +43543,7 @@ ${cleanBody}`;
43361
43543
  }
43362
43544
  }
43363
43545
  if (sessionId) {
43546
+ directDispatchTaskIdForLedger = resolveActiveDirectDispatchTaskId(args.meshId, sessionId);
43364
43547
  completedTaskForLedger = markSessionTerminal(sessionId, "failed");
43365
43548
  }
43366
43549
  }
@@ -43390,7 +43573,10 @@ ${cleanBody}`;
43390
43573
  payload: {
43391
43574
  event: args.event,
43392
43575
  nodeLabel: args.nodeLabel,
43393
- taskId: completedTaskForLedger?.id || void 0,
43576
+ // Fix B: fall back to the direct-dispatch taskId when no work-queue row
43577
+ // matched, so the terminal entry is attributable in mesh task-stats
43578
+ // (otherwise the direct task shows status='unknown' / terminalKind=null).
43579
+ taskId: completedTaskForLedger?.id || directDispatchTaskIdForLedger || void 0,
43394
43580
  providerSessionId,
43395
43581
  finalSummary,
43396
43582
  workerResult,
@@ -43686,6 +43872,7 @@ ${cleanBody}`;
43686
43872
  var idleAutoFastForwardLastAttempt;
43687
43873
  var INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS;
43688
43874
  var RECENT_COMPLETION_FINGERPRINT_TTL_MS;
43875
+ var DISPATCH_CONFIRM_TIMEOUT_MS;
43689
43876
  var autoLaunchInProgress;
43690
43877
  var autoLaunchCooldownUntil;
43691
43878
  var AUTO_LAUNCH_COOLDOWN_MS;
@@ -43723,6 +43910,7 @@ ${cleanBody}`;
43723
43910
  idleAutoFastForwardLastAttempt = /* @__PURE__ */ new Map();
43724
43911
  INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS = 30 * 60 * 1e3;
43725
43912
  RECENT_COMPLETION_FINGERPRINT_TTL_MS = 10 * 60 * 1e3;
43913
+ DISPATCH_CONFIRM_TIMEOUT_MS = 12e4;
43726
43914
  autoLaunchInProgress = /* @__PURE__ */ new Set();
43727
43915
  autoLaunchCooldownUntil = /* @__PURE__ */ new Map();
43728
43916
  AUTO_LAUNCH_COOLDOWN_MS = 5e3;
@@ -43776,12 +43964,9 @@ ${cleanBody}`;
43776
43964
  return DEFAULT_RECONCILE_INTERVAL_MS;
43777
43965
  }
43778
43966
  function resolveCoordinatorDaemonIds(components) {
43779
- const ids = /* @__PURE__ */ new Set();
43780
43967
  const statusInstanceId = readNonEmptyString2(components.statusInstanceId);
43781
- if (statusInstanceId) ids.add(statusInstanceId);
43782
43968
  const machineId = readNonEmptyString2(loadConfig2().machineId);
43783
- if (machineId) ids.add(machineId);
43784
- return [...ids];
43969
+ return expandDaemonIdForms([statusInstanceId, machineId]);
43785
43970
  }
43786
43971
  function daemonHostsMesh(mesh, daemonIds) {
43787
43972
  const host = mesh.meshHost;
@@ -43865,6 +44050,24 @@ ${cleanBody}`;
43865
44050
  }
43866
44051
  }
43867
44052
  }
44053
+ function recoverStrandedAssignedDispatches(meshId, store) {
44054
+ const assigned = getQueue(meshId, { status: ["assigned"] });
44055
+ if (!assigned.length) return;
44056
+ const nowMs = Date.now();
44057
+ for (const row of assigned) {
44058
+ const dispatchedAtMs = Date.parse(row.dispatchTimestamp ?? "");
44059
+ if (!Number.isFinite(dispatchedAtMs)) continue;
44060
+ if (nowMs - dispatchedAtMs < ASSIGNED_STRANDED_DEADLINE_MS) continue;
44061
+ if (store.taskHasConfirmedDelivery(meshId, row.id)) continue;
44062
+ const reclaimed = reclaimStrandedAssignedTask(meshId, row.id, {
44063
+ reason: "assigned_stranded_dispatch_unconfirmed",
44064
+ ageMs: nowMs - dispatchedAtMs
44065
+ });
44066
+ if (reclaimed) {
44067
+ LOG2.warn("MeshReconcile", `Reclaimed stranded assigned task ${row.id} on mesh ${meshId} (node=${row.assignedNodeId ?? "?"} session=${row.assignedSessionId ?? "?"}, dispatched ${Math.round((nowMs - dispatchedAtMs) / 1e3)}s ago, never confirmed delivered \u2192 ${reclaimed.status})`);
44068
+ }
44069
+ }
44070
+ }
43868
44071
  async function runMeshReconcileTick(components) {
43869
44072
  const localDaemonId = readNonEmptyString2(loadConfig2().machineId) || void 0;
43870
44073
  const drainDaemonIds = resolveCoordinatorDaemonIds(components);
@@ -43894,6 +44097,17 @@ ${cleanBody}`;
43894
44097
  }
43895
44098
  }
43896
44099
  }
44100
+ if (store) {
44101
+ for (const mesh of listMeshes()) {
44102
+ const selfIds = resolveCoordinatorSelfIds(mesh, drainDaemonIds);
44103
+ if (!daemonHostsMesh(mesh, selfIds)) continue;
44104
+ try {
44105
+ recoverStrandedAssignedDispatches(mesh.id, store);
44106
+ } catch (e) {
44107
+ LOG2.warn("MeshReconcile", `Assigned-stranded watchdog failed for mesh ${mesh.id}: ${e?.message || e}`);
44108
+ }
44109
+ }
44110
+ }
43897
44111
  for (const mesh of listMeshes()) {
43898
44112
  const selfIds = resolveCoordinatorSelfIds(mesh, drainDaemonIds);
43899
44113
  if (!daemonHostsMesh(mesh, selfIds)) continue;
@@ -44284,6 +44498,7 @@ ${cleanBody}`;
44284
44498
  var DEFAULT_RECONCILE_INTERVAL_MS;
44285
44499
  var DEFAULT_AUTO_PRUNE_MIN_AGE_MS;
44286
44500
  var heldEventLedgerRecorded;
44501
+ var ASSIGNED_STRANDED_DEADLINE_MS;
44287
44502
  var STRICT_SESSION_MATCH_TTL_MS;
44288
44503
  var init_mesh_reconcile_loop = __esm2({
44289
44504
  "src/mesh/mesh-reconcile-loop.ts"() {
@@ -44297,6 +44512,7 @@ ${cleanBody}`;
44297
44512
  init_mesh_events_coordinator();
44298
44513
  init_mesh_unresolved_forward_outbox();
44299
44514
  init_mesh_events_utils();
44515
+ init_dist();
44300
44516
  init_mesh_work_queue();
44301
44517
  init_mesh_ledger();
44302
44518
  init_mesh_active_work();
@@ -44305,6 +44521,7 @@ ${cleanBody}`;
44305
44521
  DEFAULT_RECONCILE_INTERVAL_MS = 4e3;
44306
44522
  DEFAULT_AUTO_PRUNE_MIN_AGE_MS = 24 * 60 * 6e4;
44307
44523
  heldEventLedgerRecorded = /* @__PURE__ */ new Set();
44524
+ ASSIGNED_STRANDED_DEADLINE_MS = 5 * 6e4;
44308
44525
  STRICT_SESSION_MATCH_TTL_MS = 6e4;
44309
44526
  }
44310
44527
  });
@@ -44334,6 +44551,82 @@ ${cleanBody}`;
44334
44551
  init_mesh_events_coordinator();
44335
44552
  }
44336
44553
  });
44554
+ function normalizeApprovalLabel(value) {
44555
+ return String(value || "").toLowerCase().replace(/^[\s\[(<{]*\d+(?:\s*[.)\]}>:-]|\s)+/, "").replace(/[^\p{L}\p{N}]+/gu, " ").trim();
44556
+ }
44557
+ function isNegativeApprovalLabel(value) {
44558
+ const label = normalizeApprovalLabel(value);
44559
+ return /^(no|deny|reject|cancel|skip|exit|stop)\b/.test(label) || /\bwithout\b/.test(label) || /\bdo not\b/.test(label);
44560
+ }
44561
+ function hasNegativeApprovalOption(buttons) {
44562
+ return (buttons || []).some((button) => isNegativeApprovalLabel(String(button || "")));
44563
+ }
44564
+ function getApprovalPositiveHints(provider) {
44565
+ const customHints = Array.isArray(provider?.approvalPositiveHints) ? provider.approvalPositiveHints.map((hint) => normalizeApprovalLabel(String(hint || ""))).filter(Boolean) : [];
44566
+ return customHints.length > 0 ? customHints : DEFAULT_APPROVAL_POSITIVE_HINTS;
44567
+ }
44568
+ function pickApprovalButton(buttons, provider) {
44569
+ const labels = (buttons || []).map((button) => String(button || "").trim()).filter(Boolean);
44570
+ if (labels.length === 0) {
44571
+ return { index: -1, label: "" };
44572
+ }
44573
+ const normalizedButtons = labels.map((label) => normalizeApprovalLabel(label));
44574
+ const hints = getApprovalPositiveHints(provider);
44575
+ for (const hint of hints) {
44576
+ const exactIndex = normalizedButtons.findIndex((label, index) => label === hint && !isNegativeApprovalLabel(labels[index]));
44577
+ if (exactIndex >= 0) return { index: exactIndex, label: labels[exactIndex] };
44578
+ const prefixIndex = normalizedButtons.findIndex((label, index) => label.startsWith(hint) && !isNegativeApprovalLabel(labels[index]));
44579
+ if (prefixIndex >= 0) return { index: prefixIndex, label: labels[prefixIndex] };
44580
+ const includeIndex = normalizedButtons.findIndex((label, index) => label.includes(hint) && !isNegativeApprovalLabel(labels[index]));
44581
+ if (includeIndex >= 0) return { index: includeIndex, label: labels[includeIndex] };
44582
+ }
44583
+ return { index: -1, label: "" };
44584
+ }
44585
+ function pickAutoApprovalButton(buttons) {
44586
+ const labels = (buttons || []).map((button) => String(button || "").trim());
44587
+ const index = labels.findIndex(Boolean);
44588
+ return index >= 0 ? { index, label: labels[index] } : { index: -1, label: "" };
44589
+ }
44590
+ function formatAutoApprovalMessage(modalMessage, buttonLabel) {
44591
+ const lines = [`Auto-approved${buttonLabel ? `: ${buttonLabel}` : ""}`];
44592
+ const cleanMessage = String(modalMessage || "").trim();
44593
+ if (cleanMessage) lines.push(cleanMessage);
44594
+ return lines.join("\n");
44595
+ }
44596
+ function looksLikeActiveApprovalPromptText(content) {
44597
+ const text = content.trim();
44598
+ if (!text || text.length > 2e3) return false;
44599
+ const hasApprovalQuestion = /do you want to (?:proceed|allow|run|make this edit|create)/i.test(text) || /this command requires approval/i.test(text) || /quick safety check/i.test(text) || /is this a project you trust/i.test(text);
44600
+ const hasNumberedChoices = /^\s*[❯›>]?\s*1[.)]\s+(?:yes|allow|proceed|run)/im.test(text) || /^\s*1[.)]\s+yes\b/im.test(text);
44601
+ if (hasApprovalQuestion && hasNumberedChoices) return true;
44602
+ const lastLines = text.split(/\r?\n/).slice(-12).join("\n");
44603
+ const hasDontAskAgain = /yes.*don'?t ask again/i.test(lastLines) || /yes.*always allow/i.test(lastLines);
44604
+ const hasNoOption = /^\s*[❯›>]?\s*\d+[.)]\s+no\b/im.test(lastLines);
44605
+ if (hasDontAskAgain && hasNoOption) return true;
44606
+ if (/what do you want to do\?/i.test(text) && /^\s*\d+[.)]\s+\S/m.test(text)) return true;
44607
+ return false;
44608
+ }
44609
+ var DEFAULT_APPROVAL_POSITIVE_HINTS;
44610
+ var init_approval_utils = __esm2({
44611
+ "src/providers/approval-utils.ts"() {
44612
+ "use strict";
44613
+ DEFAULT_APPROVAL_POSITIVE_HINTS = [
44614
+ "yes",
44615
+ "allow once",
44616
+ "approve",
44617
+ "accept",
44618
+ "continue",
44619
+ "run",
44620
+ "proceed",
44621
+ "confirm",
44622
+ "save",
44623
+ "ok",
44624
+ "trust",
44625
+ "allow",
44626
+ "always allow"
44627
+ ];
44628
+ }
44629
+ });
44337
44630
  function normalizeCategories(categories) {
44338
44631
  if (!Array.isArray(categories)) return [];
44339
44632
  return categories.map((category) => String(category || "").trim()).filter(Boolean);
@@ -45320,6 +45613,27 @@ ${cleanBody}`;
45320
45613
  });
45321
45614
  return { prompt, footers };
45322
45615
  }
45616
+ function extractButtonLabels(spec, text) {
45617
+ if (!text) return [];
45618
+ const flags = spec.buttonFlags && spec.buttonFlags.includes("m") ? spec.buttonFlags : `${spec.buttonFlags ?? ""}m`;
45619
+ const buttonRe = compile2(spec.buttonPattern, flags);
45620
+ const labelGroup = Number.isInteger(spec.buttonLabelGroup) && (spec.buttonLabelGroup ?? 0) > 0 ? spec.buttonLabelGroup : 1;
45621
+ const out = [];
45622
+ for (const line of text.split("\n")) {
45623
+ buttonRe.lastIndex = 0;
45624
+ const m = buttonRe.exec(line);
45625
+ if (!m) continue;
45626
+ const captured = m[labelGroup] ?? (labelGroup === 1 && m.length > 2 ? m[m.length - 1] : void 0);
45627
+ if (captured && captured.trim()) out.push(captured.trim());
45628
+ }
45629
+ return out;
45630
+ }
45631
+ function buttonBlockApprovalCue(spec, text) {
45632
+ const labels = extractButtonLabels(spec, text);
45633
+ if (labels.length < 2) return false;
45634
+ if (pickApprovalButton(labels).index < 0) return false;
45635
+ return hasNegativeApprovalOption(labels);
45636
+ }
45323
45637
  function modalMatches(spec, input) {
45324
45638
  const text = input.screenText ?? "";
45325
45639
  const question = compile2(spec.questionPattern, spec.questionFlags ?? "i");
@@ -45328,6 +45642,7 @@ ${cleanBody}`;
45328
45642
  const re = compile2(variant.regex, variant.flags ?? "i");
45329
45643
  if (re.test(text)) return true;
45330
45644
  }
45645
+ if (buttonBlockApprovalCue(spec, text)) return true;
45331
45646
  return false;
45332
45647
  }
45333
45648
  function evaluateGroup(group, spec, input, compiled) {
@@ -45382,6 +45697,7 @@ ${cleanBody}`;
45382
45697
  "src/providers/sdk/v1/builders/cli/detect-status.ts"() {
45383
45698
  "use strict";
45384
45699
  init_visible_region();
45700
+ init_approval_utils();
45385
45701
  DEFAULT_ORDER = ["spinner", "modal", "settled-prompt"];
45386
45702
  }
45387
45703
  });
@@ -49980,6 +50296,7 @@ ${lastSnapshot}`;
49980
50296
  readLedgerEntries: () => readLedgerEntries,
49981
50297
  readLedgerSlice: () => readLedgerSlice,
49982
50298
  readLedgerSliceFromStore: () => readLedgerSliceFromStore,
50299
+ readMeshCompletionSummary: () => readMeshCompletionSummary,
49983
50300
  reconcileDirectDispatchCompletionFromTranscript: () => reconcileDirectDispatchCompletionFromTranscript,
49984
50301
  recordCompletionConflict: () => recordCompletionConflict,
49985
50302
  recordDebugTrace: () => recordDebugTrace,
@@ -50005,6 +50322,7 @@ ${lastSnapshot}`;
50005
50322
  resolveMeshHostStatus: () => resolveMeshHostStatus,
50006
50323
  resolveMeshNodeAttribution: () => resolveMeshNodeAttribution,
50007
50324
  resolveMeshRefineValidationPlan: () => resolveMeshRefineValidationPlan,
50325
+ resolveMeshSurfacedSessionPreview: () => resolveMeshSurfacedSessionPreview,
50008
50326
  resolveNodeSchedulingPriority: () => resolveNodeSchedulingPriority,
50009
50327
  resolveSessionHostAppName: () => resolveSessionHostAppName,
50010
50328
  resolveSessionHostAppNameResolution: () => resolveSessionHostAppNameResolution2,
@@ -51889,6 +52207,7 @@ ${lastSnapshot}`;
51889
52207
  init_mesh_refine_status();
51890
52208
  init_mesh_host_ownership();
51891
52209
  init_mesh_events();
52210
+ init_mesh_events_utils();
51892
52211
  init_mesh_delivery_policy();
51893
52212
  var NO_FALLBACK_REASON = "Repo Mesh command/data-plane is P2P-only; WS/REST command fallback is intentionally disabled to preserve the transport boundary.";
51894
52213
  var P2P_NEXT_ACTION = "Check daemon/P2P health, wait briefly for connection establishment, then do one bounded retry or requeue the mesh task after clearing stale target session metadata.";
@@ -55767,73 +56086,7 @@ ${effect.notification.body || ""}`.trim();
55767
56086
  if (raw.coverage === "full" || raw.coverage === "tail" || raw.coverage === "current-turn") normalized.coverage = raw.coverage;
55768
56087
  return normalized;
55769
56088
  }
55770
- var DEFAULT_APPROVAL_POSITIVE_HINTS = [
55771
- "yes",
55772
- "allow once",
55773
- "approve",
55774
- "accept",
55775
- "continue",
55776
- "run",
55777
- "proceed",
55778
- "confirm",
55779
- "save",
55780
- "ok",
55781
- "trust",
55782
- "allow",
55783
- "always allow"
55784
- ];
55785
- function normalizeApprovalLabel(value) {
55786
- return String(value || "").toLowerCase().replace(/^[\s\[(<{]*\d+(?:\s*[.)\]}>:-]|\s)+/, "").replace(/[^\p{L}\p{N}]+/gu, " ").trim();
55787
- }
55788
- function isNegativeApprovalLabel(value) {
55789
- const label = normalizeApprovalLabel(value);
55790
- return /^(no|deny|reject|cancel|skip|exit|stop)\b/.test(label) || /\bwithout\b/.test(label) || /\bdo not\b/.test(label);
55791
- }
55792
- function getApprovalPositiveHints(provider) {
55793
- const customHints = Array.isArray(provider?.approvalPositiveHints) ? provider.approvalPositiveHints.map((hint) => normalizeApprovalLabel(String(hint || ""))).filter(Boolean) : [];
55794
- return customHints.length > 0 ? customHints : DEFAULT_APPROVAL_POSITIVE_HINTS;
55795
- }
55796
- function pickApprovalButton(buttons, provider) {
55797
- const labels = (buttons || []).map((button) => String(button || "").trim()).filter(Boolean);
55798
- if (labels.length === 0) {
55799
- return { index: -1, label: "" };
55800
- }
55801
- const normalizedButtons = labels.map((label) => normalizeApprovalLabel(label));
55802
- const hints = getApprovalPositiveHints(provider);
55803
- for (const hint of hints) {
55804
- const exactIndex = normalizedButtons.findIndex((label, index) => label === hint && !isNegativeApprovalLabel(labels[index]));
55805
- if (exactIndex >= 0) return { index: exactIndex, label: labels[exactIndex] };
55806
- const prefixIndex = normalizedButtons.findIndex((label, index) => label.startsWith(hint) && !isNegativeApprovalLabel(labels[index]));
55807
- if (prefixIndex >= 0) return { index: prefixIndex, label: labels[prefixIndex] };
55808
- const includeIndex = normalizedButtons.findIndex((label, index) => label.includes(hint) && !isNegativeApprovalLabel(labels[index]));
55809
- if (includeIndex >= 0) return { index: includeIndex, label: labels[includeIndex] };
55810
- }
55811
- return { index: -1, label: "" };
55812
- }
55813
- function pickAutoApprovalButton(buttons) {
55814
- const labels = (buttons || []).map((button) => String(button || "").trim());
55815
- const index = labels.findIndex(Boolean);
55816
- return index >= 0 ? { index, label: labels[index] } : { index: -1, label: "" };
55817
- }
55818
- function formatAutoApprovalMessage(modalMessage, buttonLabel) {
55819
- const lines = [`Auto-approved${buttonLabel ? `: ${buttonLabel}` : ""}`];
55820
- const cleanMessage = String(modalMessage || "").trim();
55821
- if (cleanMessage) lines.push(cleanMessage);
55822
- return lines.join("\n");
55823
- }
55824
- function looksLikeActiveApprovalPromptText(content) {
55825
- const text = content.trim();
55826
- if (!text || text.length > 2e3) return false;
55827
- const hasApprovalQuestion = /do you want to (?:proceed|allow|run|make this edit|create)/i.test(text) || /this command requires approval/i.test(text) || /quick safety check/i.test(text) || /is this a project you trust/i.test(text);
55828
- const hasNumberedChoices = /^\s*[❯›>]?\s*1[.)]\s+(?:yes|allow|proceed|run)/im.test(text) || /^\s*1[.)]\s+yes\b/im.test(text);
55829
- if (hasApprovalQuestion && hasNumberedChoices) return true;
55830
- const lastLines = text.split(/\r?\n/).slice(-12).join("\n");
55831
- const hasDontAskAgain = /yes.*don'?t ask again/i.test(lastLines) || /yes.*always allow/i.test(lastLines);
55832
- const hasNoOption = /^\s*[❯›>]?\s*\d+[.)]\s+no\b/im.test(lastLines);
55833
- if (hasDontAskAgain && hasNoOption) return true;
55834
- if (/what do you want to do\?/i.test(text) && /^\s*\d+[.)]\s+\S/m.test(text)) return true;
55835
- return false;
55836
- }
56089
+ init_approval_utils();
55837
56090
  init_provider_patch_state();
55838
56091
  init_chat_message_normalization();
55839
56092
  init_open_panel_support();
@@ -56897,6 +57150,7 @@ ${effect.notification.body || ""}`.trim();
56897
57150
  var import_node_crypto3 = require("crypto");
56898
57151
  init_contracts();
56899
57152
  init_provider_input_support();
57153
+ init_approval_utils();
56900
57154
  init_coordinator_registry();
56901
57155
  init_logger();
56902
57156
  init_debug_config();
@@ -64837,6 +65091,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
64837
65091
  }
64838
65092
  init_logger();
64839
65093
  init_control_effects();
65094
+ init_approval_utils();
64840
65095
  init_provider_patch_state();
64841
65096
  function normalizeProviderSessionId(provider, providerSessionId) {
64842
65097
  const normalizedId = typeof providerSessionId === "string" ? providerSessionId.trim() : "";
@@ -65090,6 +65345,20 @@ ${formatManifestValidationIssues2(validation.issues)}`,
65090
65345
  * keystroke until the modal *content* has settled.
65091
65346
  */
65092
65347
  static AUTO_APPROVE_SETTLE_MS = 600;
65348
+ /**
65349
+ * Busy-side hysteresis for the settle gate. A momentary `generating` flip
65350
+ * while the SAME approval modal's button block is still on screen (its
65351
+ * question line scrolled out of the captured frame, only the buttons + a
65352
+ * residual `esc to interrupt` spinner remain) briefly reports
65353
+ * status!=waiting_approval. Without hysteresis that flip wipes the settle
65354
+ * clock, and the modal→generating→modal flap restarts the 600ms window
65355
+ * every time so auto-approve never fires. We keep the in-progress settle
65356
+ * gate warm across an inactive blip up to this bound; only once the modal
65357
+ * has genuinely stayed gone this long (a real resolution → idle) is the
65358
+ * gate cleared. Bounded so a genuinely new, later approval still re-settles
65359
+ * from scratch rather than firing on a stale timestamp.
65360
+ */
65361
+ static AUTO_APPROVE_GATE_HYSTERESIS_MS = 1500;
65093
65362
  adapter;
65094
65363
  context = null;
65095
65364
  events = [];
@@ -65111,6 +65380,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
65111
65380
  pendingAutoApprovalSignature = "";
65112
65381
  pendingAutoApprovalSince = 0;
65113
65382
  autoApproveSettleTimer = null;
65383
+ // Wall-clock when auto-approve first observed status!=waiting_approval while
65384
+ // a settle gate was in progress. Drives AUTO_APPROVE_GATE_HYSTERESIS_MS so a
65385
+ // brief generating flip does not immediately wipe the settle clock.
65386
+ autoApproveInactiveSince = 0;
65114
65387
  controlValues = {};
65115
65388
  summaryMetadata = void 0;
65116
65389
  appliedEffectKeys = /* @__PURE__ */ new Set();
@@ -65931,14 +66204,28 @@ ${formatManifestValidationIssues2(validation.issues)}`,
65931
66204
  const autoApproveActive = adapterStatus?.status === "waiting_approval" && this.shouldAutoApprove();
65932
66205
  if (!autoApproveActive) {
65933
66206
  this.lastAutoApprovalSignature = "";
66207
+ if (this.pendingAutoApprovalSince) {
66208
+ if (!this.autoApproveInactiveSince) this.autoApproveInactiveSince = now;
66209
+ const goneForMs = now - this.autoApproveInactiveSince;
66210
+ if (goneForMs < _CliProviderInstance.AUTO_APPROVE_GATE_HYSTERESIS_MS) {
66211
+ if (this.autoApproveSettleTimer) clearTimeout(this.autoApproveSettleTimer);
66212
+ this.autoApproveSettleTimer = setTimeout(() => {
66213
+ this.autoApproveSettleTimer = null;
66214
+ this.recheckAutoApproveSettled();
66215
+ }, _CliProviderInstance.AUTO_APPROVE_GATE_HYSTERESIS_MS - goneForMs + 20);
66216
+ return autoApproveActive;
66217
+ }
66218
+ }
65934
66219
  this.pendingAutoApprovalSignature = "";
65935
66220
  this.pendingAutoApprovalSince = 0;
66221
+ this.autoApproveInactiveSince = 0;
65936
66222
  if (this.autoApproveSettleTimer) {
65937
66223
  clearTimeout(this.autoApproveSettleTimer);
65938
66224
  this.autoApproveSettleTimer = null;
65939
66225
  }
65940
66226
  return autoApproveActive;
65941
66227
  }
66228
+ this.autoApproveInactiveSince = 0;
65942
66229
  const modal = adapterStatus.activeModal;
65943
66230
  const buttons = Array.isArray(modal?.buttons) ? modal.buttons.map((b) => String(b || "").trim()).filter(Boolean) : [];
65944
66231
  if (!modal || buttons.length === 0) {
@@ -65948,18 +66235,18 @@ ${formatManifestValidationIssues2(validation.issues)}`,
65948
66235
  if (buttonIndex < 0) {
65949
66236
  return autoApproveActive;
65950
66237
  }
65951
- const approvalEntrySeq = typeof adapterStatus?.approvalEntrySeq === "number" ? adapterStatus.approvalEntrySeq : 0;
65952
- const signature = [
65953
- approvalEntrySeq,
66238
+ const modalSignature = [
65954
66239
  typeof modal?.message === "string" ? modal.message.trim() : "",
65955
66240
  buttons.join("|"),
65956
66241
  buttonIndex
65957
66242
  ].join("::");
65958
- if (this.autoApproveBusy && signature === this.lastAutoApprovalSignature) {
66243
+ const approvalEntrySeq = typeof adapterStatus?.approvalEntrySeq === "number" ? adapterStatus.approvalEntrySeq : 0;
66244
+ const busySignature = `${approvalEntrySeq}::${modalSignature}`;
66245
+ if (this.autoApproveBusy && busySignature === this.lastAutoApprovalSignature) {
65959
66246
  return autoApproveActive;
65960
66247
  }
65961
- if (signature !== this.pendingAutoApprovalSignature) {
65962
- this.pendingAutoApprovalSignature = signature;
66248
+ if (modalSignature !== this.pendingAutoApprovalSignature) {
66249
+ this.pendingAutoApprovalSignature = modalSignature;
65963
66250
  this.pendingAutoApprovalSince = now;
65964
66251
  }
65965
66252
  const settledForMs = now - this.pendingAutoApprovalSince;
@@ -65976,9 +66263,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
65976
66263
  this.autoApproveSettleTimer = null;
65977
66264
  }
65978
66265
  this.autoApproveBusy = true;
65979
- this.lastAutoApprovalSignature = signature;
66266
+ this.lastAutoApprovalSignature = busySignature;
65980
66267
  this.pendingAutoApprovalSignature = "";
65981
66268
  this.pendingAutoApprovalSince = 0;
66269
+ this.autoApproveInactiveSince = 0;
65982
66270
  if (this.autoApproveBusyTimer) clearTimeout(this.autoApproveBusyTimer);
65983
66271
  this.autoApproveBusyTimer = setTimeout(() => {
65984
66272
  this.autoApproveBusy = false;
@@ -72827,7 +73115,8 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
72827
73115
  var fs23 = __toESM2(require("fs"));
72828
73116
  var path35 = __toESM2(require("path"));
72829
73117
  var os26 = __toESM2(require("os"));
72830
- var LOG_DIR2 = process.platform === "win32" ? path35.join(process.env.LOCALAPPDATA || process.env.APPDATA || path35.join(os26.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path35.join(os26.homedir(), "Library", "Logs", "adhdev") : path35.join(os26.homedir(), ".local", "share", "adhdev", "logs");
73118
+ var ADHDEV_HOME2 = process.env.ADHDEV_CONFIG_DIR && process.env.ADHDEV_CONFIG_DIR.trim() ? process.env.ADHDEV_CONFIG_DIR.trim() : path35.join(os26.homedir(), ".adhdev");
73119
+ var LOG_DIR2 = path35.join(ADHDEV_HOME2, "logs");
72831
73120
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
72832
73121
  var MAX_DAYS = 7;
72833
73122
  try {
@@ -73275,7 +73564,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
73275
73564
  return "";
73276
73565
  }
73277
73566
  }
73278
- function readRecord6(repoRoot) {
73567
+ function readRecord5(repoRoot) {
73279
73568
  const path422 = (0, import_node_path2.resolve)(repoRoot, PREVIEW_DEPLOY_RECORD);
73280
73569
  if (!(0, import_node_fs4.existsSync)(path422)) return null;
73281
73570
  try {
@@ -73315,7 +73604,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
73315
73604
  }
73316
73605
  function buildPreviewFreshness(repoRoot) {
73317
73606
  const current = readCurrentMainCommit(repoRoot);
73318
- const record2 = readRecord6(repoRoot);
73607
+ const record2 = readRecord5(repoRoot);
73319
73608
  const lastPreviewCommit = normalizeCommit(record2?.lastPreviewCommit);
73320
73609
  const targets = readTargetFreshness(record2, current.currentMainCommit);
73321
73610
  let status = "unknown";
@@ -73662,13 +73951,14 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
73662
73951
  }
73663
73952
  }
73664
73953
  }
73665
- function stopSessionHostProcesses(appName) {
73954
+ async function stopSessionHostProcesses(appName) {
73666
73955
  const pidFile = path36.join(os27.homedir(), ".adhdev", `${appName}-session-host.pid`);
73956
+ let killedPid = null;
73667
73957
  try {
73668
73958
  if (fs25.existsSync(pidFile)) {
73669
73959
  const pid = Number.parseInt(fs25.readFileSync(pidFile, "utf8").trim(), 10);
73670
73960
  if (Number.isFinite(pid) && pid !== process.pid && isManagedSessionHostPid(pid)) {
73671
- killPid2(pid);
73961
+ if (killPid2(pid)) killedPid = pid;
73672
73962
  }
73673
73963
  }
73674
73964
  } catch {
@@ -73678,6 +73968,15 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
73678
73968
  } catch {
73679
73969
  }
73680
73970
  }
73971
+ if (killedPid !== null) {
73972
+ await waitForPidExit(killedPid, 15e3);
73973
+ }
73974
+ }
73975
+ function isRetriableInstallLockError(error48) {
73976
+ const code = error48?.code;
73977
+ if (code === "EBUSY" || code === "EPERM") return true;
73978
+ const text = `${error48?.message || ""} ${error48?.stderr || ""}`;
73979
+ return /\bEBUSY\b|\bEPERM\b|resource busy or locked/i.test(text);
73681
73980
  }
73682
73981
  function removeDaemonPidFile() {
73683
73982
  const pidFile = path36.join(os27.homedir(), ".adhdev", "daemon.pid");
@@ -73757,22 +74056,37 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
73757
74056
  appendUpgradeLog(`Waiting for parent pid ${payload.parentPid} to exit`);
73758
74057
  await waitForPidExit(payload.parentPid, 15e3);
73759
74058
  }
73760
- stopSessionHostProcesses(sessionHostAppName);
74059
+ await stopSessionHostProcesses(sessionHostAppName);
73761
74060
  removeDaemonPidFile();
73762
74061
  cleanupStaleGlobalInstallDirs(payload.packageName, installCommand.surface);
73763
74062
  const spec = `${payload.packageName}@${payload.targetVersion || "latest"}`;
73764
74063
  appendUpgradeLog(`Installing ${spec}`);
73765
- const installOutput = (0, import_child_process8.execFileSync)(
73766
- installCommand.command,
73767
- installCommand.args,
73768
- {
73769
- encoding: "utf8",
73770
- stdio: "pipe",
73771
- maxBuffer: 20 * 1024 * 1024,
73772
- env: buildInstallEnvWithNodeOnPath(),
73773
- ...installCommand.execOptions
74064
+ const maxInstallAttempts = process.platform === "win32" ? 3 : 1;
74065
+ let installOutput = "";
74066
+ for (let attempt = 1; attempt <= maxInstallAttempts; attempt++) {
74067
+ try {
74068
+ installOutput = String((0, import_child_process8.execFileSync)(
74069
+ installCommand.command,
74070
+ installCommand.args,
74071
+ {
74072
+ encoding: "utf8",
74073
+ stdio: "pipe",
74074
+ maxBuffer: 20 * 1024 * 1024,
74075
+ env: buildInstallEnvWithNodeOnPath(),
74076
+ ...installCommand.execOptions
74077
+ }
74078
+ ));
74079
+ break;
74080
+ } catch (error48) {
74081
+ if (attempt < maxInstallAttempts && isRetriableInstallLockError(error48)) {
74082
+ appendUpgradeLog(`Install attempt ${attempt} hit a file lock (${error48?.code || "lock"}); cleaning staging and retrying after backoff`);
74083
+ cleanupStaleGlobalInstallDirs(payload.packageName, installCommand.surface);
74084
+ await new Promise((resolve24) => setTimeout(resolve24, attempt * 1500));
74085
+ continue;
74086
+ }
74087
+ throw error48;
73774
74088
  }
73775
- );
74089
+ }
73776
74090
  if (installOutput.trim()) {
73777
74091
  appendUpgradeLog(installOutput.trim());
73778
74092
  }
@@ -82516,6 +82830,7 @@ ${ptyResult.output.slice(-2e3)}`);
82516
82830
  }
82517
82831
  };
82518
82832
  init_logger();
82833
+ init_approval_utils();
82519
82834
  init_chat_message_normalization();
82520
82835
  var AgentStreamPoller = class {
82521
82836
  deps;