@adhdev/daemon-core 0.9.82-rc.291 → 0.9.82-rc.293

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -275,10 +275,10 @@ function readInjected(value) {
275
275
  }
276
276
  function getDaemonBuildInfo() {
277
277
  if (cached) return cached;
278
- const commit = readInjected(true ? "396cb9c4084ea658cd3606b76948987cd875f138" : void 0) ?? "unknown";
279
- const commitShort = readInjected(true ? "396cb9c4" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
280
- const version = readInjected(true ? "0.9.82-rc.291" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
281
- const builtAt = readInjected(true ? "2026-06-16T06:42:37.821Z" : void 0);
278
+ const commit = readInjected(true ? "88f97abcc85d83fe5d5313b229d32a7d76b1208a" : void 0) ?? "unknown";
279
+ const commitShort = readInjected(true ? "88f97abc" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
280
+ const version = readInjected(true ? "0.9.82-rc.293" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
281
+ const builtAt = readInjected(true ? "2026-06-16T11:13:51.625Z" : void 0);
282
282
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
283
283
  return cached;
284
284
  }
@@ -349,6 +349,15 @@ async function getGitRepoStatus(workspace, options = {}) {
349
349
  );
350
350
  }
351
351
  }
352
+ function isNonRuntimeRootFile(file) {
353
+ const base = file.slice(file.lastIndexOf("/") + 1);
354
+ if (/^\.(?:verify|marker|converge|ff-verify|patch-equiv|live-verify)\b/i.test(base)) return true;
355
+ if (/(?:^|\/)docs\//i.test(file)) return true;
356
+ if (/^(?:README|CHANGELOG|LICENSE|NOTICE|AUTHORS|CONTRIBUTING|CODEOWNERS)(?:\.[A-Za-z0-9]+)?$/i.test(base)) {
357
+ return true;
358
+ }
359
+ return false;
360
+ }
352
361
  async function classifyDaemonBuildChange(repoPath, buildCommit, options) {
353
362
  try {
354
363
  const diff = await runGit(repoPath, ["diff", "--name-only", `${buildCommit}..HEAD`], options);
@@ -357,18 +366,18 @@ async function classifyDaemonBuildChange(repoPath, buildCommit, options) {
357
366
  return { isDaemonAffecting: true, affectedPackages: [] };
358
367
  }
359
368
  const pkgs = /* @__PURE__ */ new Set();
360
- let sawNonPackageOrUnknown = false;
369
+ let sawRuntimeAmbiguousNonPackage = false;
361
370
  for (const file of files) {
362
371
  const match = file.match(/(?:^|\/)packages\/([^/]+)\//);
363
372
  if (!match) {
364
- sawNonPackageOrUnknown = true;
373
+ if (!isNonRuntimeRootFile(file)) sawRuntimeAmbiguousNonPackage = true;
365
374
  continue;
366
375
  }
367
376
  pkgs.add(match[1]);
368
377
  }
369
378
  const affectedPackages = [...pkgs].sort();
370
- const allWebOnly = !sawNonPackageOrUnknown && affectedPackages.length > 0 && affectedPackages.every((p) => WEB_ONLY_PACKAGES.has(p) && !DAEMON_RUNTIME_PACKAGES.has(p));
371
- return { isDaemonAffecting: !allWebOnly, affectedPackages };
379
+ const allBenign = !sawRuntimeAmbiguousNonPackage && affectedPackages.every((p) => WEB_ONLY_PACKAGES.has(p) && !DAEMON_RUNTIME_PACKAGES.has(p));
380
+ return { isDaemonAffecting: !allBenign, affectedPackages };
372
381
  } catch {
373
382
  return { isDaemonAffecting: true, affectedPackages: [] };
374
383
  }
@@ -395,7 +404,8 @@ async function detectDaemonBuildBehind(repo, submodules, options) {
395
404
  options
396
405
  );
397
406
  const scopeLabel = scope === "root" ? "workspace" : scope;
398
- const warning = isDaemonAffecting ? `Live daemon was built from ${build.commitShort} which is behind ${scopeLabel} HEAD ${head.slice(0, 7)}. Merged code is NOT live until the daemon is rebuilt/redeployed and restarted \u2014 a local dist rebuild alone does not update a cloud daemon.` : `Live daemon was built from ${build.commitShort} which is behind ${scopeLabel} HEAD ${head.slice(0, 7)}, but only web packages changed (${(affectedPackages || []).join(", ") || "web"}). Daemon restart NOT required \u2014 redeploy the web app to reflect the change.`;
407
+ const benignDetail = affectedPackages.length > 0 ? `only web packages changed (${affectedPackages.join(", ")})` : "only non-runtime files changed (markers/docs)";
408
+ const warning = isDaemonAffecting ? `Live daemon was built from ${build.commitShort} which is behind ${scopeLabel} HEAD ${head.slice(0, 7)}. Merged code is NOT live until the daemon is rebuilt/redeployed and restarted \u2014 a local dist rebuild alone does not update a cloud daemon.` : `Live daemon was built from ${build.commitShort} which is behind ${scopeLabel} HEAD ${head.slice(0, 7)}, but ${benignDetail}. Daemon restart NOT required \u2014 redeploy the web app to reflect the change.`;
399
409
  return {
400
410
  buildCommit: build.commit,
401
411
  buildCommitShort: build.commitShort,
@@ -1997,7 +2007,7 @@ function buildRulesSection(coordinatorCliType) {
1997
2007
  - **Reuse idle sessions.** For follow-up, retry, commit/push, or cleanup on the same issue, send only the delta to the existing idle session. Start fresh only for independent work, provider mismatch, transcript contamination, or required worktree isolation.
1998
2008
  - **Respect explicit provider requests.** Map: Hermes \u2192 \`hermes-cli\`, Claude/Claude Code \u2192 \`claude-cli\`, Codex \u2192 \`codex-cli\`, Gemini \u2192 \`gemini-cli\`, Antigravity \u2192 \`antigravity-cli\`. Never substitute the coordinator's own runtime.
1999
2009
  - **Verify via git, not source.** Use \`mesh_git_status\` to confirm side effects. Treat agent summaries as self-reports, not verification.
2000
- - **Limit parallelism.** Start with 1\u20132 tasks; scale only on success. Never duplicate a session because \`mesh_read_chat\` shows no final message while tool/terminal activity is ongoing.
2010
+ - **Limit parallelism.** Start with 1\u20132 tasks; scale only on success. Never duplicate a session because \`mesh_read_chat\` shows no final message while tool/terminal activity is ongoing. This caps *concurrent* load \u2014 it does not mean serialize independent work: when a new, independent request arrives and there is headroom under \`maxParallelTasks\`, dispatch it right away rather than waiting for an in-flight task or a user nudge (read-only diagnosis especially, since it has no merge cost).
2001
2011
  - **Check history first.** Call \`mesh_task_history\` at session start to avoid duplicate work and inform recovery. On failure, read task history before retrying.
2002
2012
  - **Converge branches.** After worktree tasks: refine/fast-forward, or classify as \`pushed_feature_branch_needs_merge\` / \`blocked_review\` / \`cleanup_candidate\` / \`not_mergeable\`. Clean up with \`mesh_remove_node\`.
2003
2013
  - **Refinery is config-driven.** \`mesh_refine_node\` must run validation from \`.adhdev/refine.{json,yaml,yml}\` or \`repo-mesh.refine.*\`. Heuristics are scaffolding only.
@@ -2051,7 +2061,7 @@ Before doing any coordinator work, confirm that the actual callable tool list in
2051
2061
  c. **Targeted Tasks**: Use \`mesh_send_task\` only when you need to bypass the queue and force a specific node to execute a task immediately.
2052
2062
  d. For the first dispatch of a new task, provide a **complete, self-contained** instruction that includes all context the agent needs (file paths, line numbers, what to change, why). Do not send partial instructions expecting future follow-up.
2053
2063
  e. For a continuation of the same issue in an existing session, send a concise **delta instruction**: current verified state, the exact failed/blocked step, the newly approved action, and final reporting requirements. Do not resend the full original task or open a new chat solely to continue the same work; that wastes coordinator and worker context.
2054
- 4. **Monitor** \u2014 Prefer event-driven completion/status notifications. Do **not** poll \`mesh_read_chat\` repeatedly. Do **not** repeatedly call \`mesh_status\` or \`mesh_view_queue\` just to wait for assigned/generating work. After dispatching a direct or queued task, send one progress update with the task/session handle, then stop. Wait for \`pendingCoordinatorEvents\` or another completion/approval/status signal, an explicit user status request, or a real timeout/stall signal before reading status/chat/queue again. Use at most one compact \`mesh_read_chat\` check after a terminal signal. Handle approvals via \`mesh_approve\`.
2064
+ 4. **Monitor** \u2014 Prefer event-driven completion/status notifications. Do **not** poll \`mesh_read_chat\` repeatedly. Do **not** repeatedly call \`mesh_status\` or \`mesh_view_queue\` just to wait for assigned/generating work. After dispatching a direct or queued task, send one progress update with the task/session handle, then stop. Wait for \`pendingCoordinatorEvents\` or another completion/approval/status signal, an explicit user status request, or a real timeout/stall signal before reading status/chat/queue again. Use at most one compact \`mesh_read_chat\` check after a terminal signal. Handle approvals via \`mesh_approve\`. **Proactively parallelize new work.** When the user reports a new bug or asks for new work, start it immediately if it is independent of in-flight tasks and there is headroom under \`maxParallelTasks\` \u2014 do not wait for a current task to finish or for the user to prompt you to parallelize. Read-only diagnosis (\`live_debug_readonly\`) has no isolation or merge cost, so dispatch it in parallel right away. The no-polling / concurrency-limit rules constrain *re-checking or duplicating already-dispatched work*; they are **not** a reason to defer starting a new, independent task.
2055
2065
  5. **Verify** \u2014 When a task reports completion or git work is visible, call \`mesh_git_status\` to verify changes were made.
2056
2066
  6. **Checkpoint** \u2014 Call \`mesh_checkpoint\` to save the work.
2057
2067
  7. **Converge branches** \u2014 Before marking any task complete, classify every touched node/branch into exactly one final state: \`merged_to_main\`, \`pushed_feature_branch_needs_merge\`, \`blocked_review\`, \`cleanup_candidate\`, or \`not_mergeable\`. Use \`mesh_status\` branchConvergenceSummary. For obvious clean branch catch-up (ahead 0, behind > 0, upstream fresh, no dirty/stash/submodule issues), use \`mesh_fast_forward_node\` dry-run first and execute only when explicitly safe/approved; this avoids consuming an agent session. Use \`mesh_refine_node\` for clean worktree branches when safe. Before/refine merging root commits that contain submodule gitlink changes, require each submodule commit to be reachable from the configured submodule remote main branch, not merely present on a feature ref or local checkout. If \`mesh_refine_node\` returns \`submodule_reachability_failed\` or publish-required evidence, keep the public convergence bucket as \`blocked_review\`; unless \`allowAutoPublishSubmoduleMainCommits\` is explicitly enabled and Refinery reports successful non-force publish plus post-publish verification, ask the user for explicit approval to push/publish the unreachable submodule commit(s) to submodule main, then rerun \`mesh_refine_node\`. Do not merge the root branch until the submodule commit(s) are reachable from submodule origin/main. A task that remains on a non-main branch is not fully complete unless the final report names the follow-up state and next step.
@@ -4395,6 +4405,34 @@ var init_mesh_runtime_store = __esm({
4395
4405
  ).get(meshId);
4396
4406
  return row?.cnt ?? 0;
4397
4407
  }
4408
+ /**
4409
+ * Mark specific pending-event rows drained by id (ack). Used by the
4410
+ * unresolved-delegate durable-forward outbox: an event is peeked (not drained)
4411
+ * while its push to the coordinator is unconfirmed, then marked drained ONLY
4412
+ * after the push is acked. A failed push leaves the row undrained so the next
4413
+ * reconcile tick retries it. Returns the number of rows newly marked drained.
4414
+ */
4415
+ markPendingEventsDrainedById(ids) {
4416
+ const idList = ids.filter((id) => typeof id === "string" && id.length > 0);
4417
+ if (idList.length === 0) return 0;
4418
+ const now = Date.now();
4419
+ return this.db.prepare(
4420
+ `UPDATE mesh_pending_events SET drained = 1, drained_at = ? WHERE drained = 0 AND id IN (${idList.map(() => "?").join(",")})`
4421
+ ).run(now, ...idList).changes;
4422
+ }
4423
+ /**
4424
+ * Hard-delete pending-event rows by id (including the dedup fingerprint history).
4425
+ * Used to expire an unresolved-delegate outbox entry that has exhausted its retry
4426
+ * budget — fully removing it frees the fingerprint so a genuinely new completion
4427
+ * for the same task could be re-queued later. Returns the number of rows deleted.
4428
+ */
4429
+ deletePendingEventsById(ids) {
4430
+ const idList = ids.filter((id) => typeof id === "string" && id.length > 0);
4431
+ if (idList.length === 0) return 0;
4432
+ return this.db.prepare(
4433
+ `DELETE FROM mesh_pending_events WHERE id IN (${idList.map(() => "?").join(",")})`
4434
+ ).run(...idList).changes;
4435
+ }
4398
4436
  };
4399
4437
  }
4400
4438
  });
@@ -4402,6 +4440,7 @@ var init_mesh_runtime_store = __esm({
4402
4440
  // src/mesh/mesh-missions.ts
4403
4441
  var mesh_missions_exports = {};
4404
4442
  __export(mesh_missions_exports, {
4443
+ GOAL_PREVIEW_MAX: () => GOAL_PREVIEW_MAX,
4405
4444
  MESH_MISSION_STATUSES: () => MESH_MISSION_STATUSES,
4406
4445
  buildMissionPromptSection: () => buildMissionPromptSection,
4407
4446
  getActiveMeshMissionSummaries: () => getActiveMeshMissionSummaries,
@@ -4473,12 +4512,23 @@ function summarizeMeshMission(meshId, mission) {
4473
4512
  function getActiveMeshMissionSummaries(meshId) {
4474
4513
  return getMeshMissions(meshId, ["active"]).map((mission) => summarizeMeshMission(meshId, mission));
4475
4514
  }
4515
+ function slimMissionSummary(summary) {
4516
+ const goal = typeof summary.goal === "string" ? summary.goal : "";
4517
+ const goalTruncated = goal.length > GOAL_PREVIEW_MAX;
4518
+ const { goal: _omitGoal, ...rest } = summary;
4519
+ return {
4520
+ ...rest,
4521
+ goalPreview: goalTruncated ? goal.slice(0, GOAL_PREVIEW_MAX) : goal,
4522
+ goalTruncated
4523
+ };
4524
+ }
4476
4525
  function getMeshStatusMissionSummaries(meshId, options) {
4477
4526
  const historyLimit = Math.max(0, options?.historyLimit ?? 10);
4478
4527
  const all = getMeshMissions(meshId);
4479
4528
  const live = all.filter((m) => m.status === "active" || m.status === "paused");
4480
4529
  const history = all.filter((m) => m.status === "completed" || m.status === "abandoned").sort((a, b) => (b.updatedAt || "").localeCompare(a.updatedAt || "")).slice(0, historyLimit);
4481
- return [...live, ...history].map((mission) => summarizeMeshMission(meshId, mission));
4530
+ const full = [...live, ...history].map((mission) => summarizeMeshMission(meshId, mission));
4531
+ return options?.verbose ? full : full.map(slimMissionSummary);
4482
4532
  }
4483
4533
  function buildMissionPromptSection(meshId) {
4484
4534
  const summaries = getActiveMeshMissionSummaries(meshId);
@@ -4498,7 +4548,7 @@ function buildMissionPromptSection(meshId) {
4498
4548
  );
4499
4549
  return lines.join("\n");
4500
4550
  }
4501
- var import_crypto6, MESH_MISSION_STATUSES;
4551
+ var import_crypto6, MESH_MISSION_STATUSES, GOAL_PREVIEW_MAX;
4502
4552
  var init_mesh_missions = __esm({
4503
4553
  "src/mesh/mesh-missions.ts"() {
4504
4554
  "use strict";
@@ -4506,6 +4556,7 @@ var init_mesh_missions = __esm({
4506
4556
  init_mesh_runtime_store();
4507
4557
  init_mesh_work_queue();
4508
4558
  MESH_MISSION_STATUSES = ["active", "paused", "completed", "abandoned"];
4559
+ GOAL_PREVIEW_MAX = 120;
4509
4560
  }
4510
4561
  });
4511
4562
 
@@ -6184,11 +6235,225 @@ var init_mesh_fast_forward = __esm({
6184
6235
  }
6185
6236
  });
6186
6237
 
6238
+ // ../mesh-shared/dist/index.mjs
6239
+ function readRecord3(value) {
6240
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
6241
+ }
6242
+ function readString5(...values) {
6243
+ for (const value of values) {
6244
+ if (typeof value !== "string") continue;
6245
+ const trimmed = value.trim();
6246
+ if (trimmed) return trimmed;
6247
+ }
6248
+ return void 0;
6249
+ }
6250
+ function readNumber(...values) {
6251
+ for (const value of values) {
6252
+ if (typeof value === "number" && Number.isFinite(value)) return value;
6253
+ }
6254
+ return void 0;
6255
+ }
6256
+ function readBoolean(...values) {
6257
+ for (const value of values) {
6258
+ if (typeof value === "boolean") return value;
6259
+ }
6260
+ return void 0;
6261
+ }
6262
+ function joinRepoPath(root, relativePath) {
6263
+ const normalizedRoot = typeof root === "string" ? root.trim().replace(/[\\/]+$/, "") : "";
6264
+ const normalizedPath = typeof relativePath === "string" ? relativePath.trim() : "";
6265
+ if (!normalizedPath) return void 0;
6266
+ if (/^(?:[A-Za-z]:[\\/]|\/)/.test(normalizedPath)) return normalizedPath;
6267
+ if (!normalizedRoot) return void 0;
6268
+ return `${normalizedRoot}/${normalizedPath.replace(/^[\\/]+/, "")}`;
6269
+ }
6270
+ function scoreGitUpstreamFreshness(status) {
6271
+ switch (status) {
6272
+ case "fresh":
6273
+ return 30;
6274
+ case "no_upstream":
6275
+ return 4;
6276
+ case "unchecked":
6277
+ case void 0:
6278
+ return 0;
6279
+ case "stale":
6280
+ return -10;
6281
+ case "unavailable":
6282
+ return -15;
6283
+ default:
6284
+ return 0;
6285
+ }
6286
+ }
6287
+ function readGitSubmodules(value, parentRepoRoot) {
6288
+ if (!Array.isArray(value)) return void 0;
6289
+ const submodules = value.map((entry) => {
6290
+ const submodule = readRecord3(entry);
6291
+ const path40 = readString5(submodule.path);
6292
+ const commit = readString5(submodule.commit);
6293
+ const repoPath = readString5(submodule.repoPath, submodule.repo_root) ?? joinRepoPath(parentRepoRoot, path40);
6294
+ if (!path40 || !commit) return null;
6295
+ const result = {
6296
+ path: path40,
6297
+ commit,
6298
+ dirty: readBoolean(submodule.dirty) ?? false,
6299
+ outOfSync: readBoolean(submodule.outOfSync, submodule.out_of_sync) ?? false,
6300
+ lastCheckedAt: readNumber(submodule.lastCheckedAt, submodule.last_checked_at) ?? Date.now()
6301
+ };
6302
+ if (repoPath) result.repoPath = repoPath;
6303
+ const error = readString5(submodule.error);
6304
+ if (error) result.error = error;
6305
+ return result;
6306
+ }).filter((entry) => entry !== null);
6307
+ return submodules.length > 0 ? submodules : void 0;
6308
+ }
6309
+ function hasGitStatusEvidence(status) {
6310
+ return readBoolean(status.isGitRepo) !== void 0 || Boolean(readString5(status.branch, status.upstream, status.upstreamStatus, status.upstream_status, status.headCommit)) || Boolean(readString5(status.repoRoot, status.repo_root, status.workspace)) || readNumber(
6311
+ status.ahead,
6312
+ status.behind,
6313
+ status.staged,
6314
+ status.modified,
6315
+ status.untracked,
6316
+ status.deleted,
6317
+ status.renamed,
6318
+ status.lastCheckedAt,
6319
+ status.last_checked_at
6320
+ ) !== void 0 || Array.isArray(status.submodules) && status.submodules.length > 0;
6321
+ }
6322
+ function normalizeGitStatus(status, node, options) {
6323
+ const explicitIsGitRepo = readBoolean(status.isGitRepo);
6324
+ if (!Object.keys(status).length || !hasGitStatusEvidence(status)) return void 0;
6325
+ const isGitRepo = explicitIsGitRepo ?? true;
6326
+ const conflictFiles = Array.isArray(status.conflictFiles) ? status.conflictFiles.filter((entry) => typeof entry === "string") : [];
6327
+ const conflictCount = readNumber(status.conflicts) ?? conflictFiles.length;
6328
+ const hasConflicts = readBoolean(status.hasConflicts) ?? conflictCount > 0;
6329
+ const repoRoot = readString5(status.repoRoot, status.repo_root, node.repoRoot, node.repo_root, status.workspace, node.workspace) || void 0;
6330
+ const submodules = readGitSubmodules(status.submodules, repoRoot);
6331
+ const upstreamStatus = readString5(status.upstreamStatus, status.upstream_status);
6332
+ const upstreamFetchedAt = readNumber(status.upstreamFetchedAt, status.upstream_fetched_at);
6333
+ const upstreamFetchError = readString5(status.upstreamFetchError, status.upstream_fetch_error);
6334
+ const error = readString5(status.error);
6335
+ const staged = readNumber(status.staged) ?? 0;
6336
+ const modified = readNumber(status.modified) ?? 0;
6337
+ const untracked = readNumber(status.untracked) ?? 0;
6338
+ const deleted = readNumber(status.deleted) ?? 0;
6339
+ const renamed = readNumber(status.renamed) ?? 0;
6340
+ return {
6341
+ workspace: readString5(status.workspace, node.workspace) || "",
6342
+ repoRoot: repoRoot ?? null,
6343
+ isGitRepo,
6344
+ branch: readString5(status.branch) ?? null,
6345
+ headCommit: readString5(status.headCommit) ?? null,
6346
+ headMessage: readString5(status.headMessage) ?? null,
6347
+ upstream: readString5(status.upstream) ?? null,
6348
+ upstreamStatus: upstreamStatus ?? "unchecked",
6349
+ ...upstreamFetchedAt !== void 0 ? { upstreamFetchedAt } : {},
6350
+ ...upstreamFetchError ? { upstreamFetchError } : {},
6351
+ ahead: readNumber(status.ahead) ?? 0,
6352
+ behind: readNumber(status.behind) ?? 0,
6353
+ staged,
6354
+ modified,
6355
+ untracked,
6356
+ deleted,
6357
+ renamed,
6358
+ dirty: readBoolean(status.dirty, status.isDirty, status.is_dirty) ?? (staged + modified + untracked + deleted + renamed > 0 || hasConflicts),
6359
+ hasConflicts,
6360
+ conflictFiles,
6361
+ stashCount: readNumber(status.stashCount, status.stash_count) ?? 0,
6362
+ lastCheckedAt: options?.lastCheckedAt ?? readNumber(status.lastCheckedAt, status.last_checked_at) ?? Date.now(),
6363
+ ...submodules ? { submodules } : {},
6364
+ ...error ? { error } : {}
6365
+ };
6366
+ }
6367
+ function scoreGitStatusCandidate(git) {
6368
+ if (!git) return Number.NEGATIVE_INFINITY;
6369
+ let score = 0;
6370
+ if (git.isGitRepo === true) score += 50;
6371
+ if (git.isGitRepo === false) score -= 10;
6372
+ if (git.branch) score += 20;
6373
+ if (git.headCommit) score += 20;
6374
+ if (git.upstream) score += 10;
6375
+ score += scoreGitUpstreamFreshness(git.upstreamStatus);
6376
+ if (typeof git.ahead === "number") score += 2;
6377
+ if (typeof git.behind === "number") score += 2;
6378
+ if (Array.isArray(git.submodules) && git.submodules.length > 0) score += 4 + git.submodules.length;
6379
+ if (git.error) score -= 20;
6380
+ return score;
6381
+ }
6382
+ function pickBestTransitGitStatus(node, options) {
6383
+ const rawGit = readRecord3(node.lastGit ?? node.last_git);
6384
+ const gitResult = readRecord3(rawGit.result);
6385
+ const directStatus = readRecord3(rawGit.status);
6386
+ const nestedStatus = readRecord3(gitResult.status);
6387
+ const rawProbe = readRecord3(node.lastProbe ?? node.last_probe);
6388
+ const probeGit = readRecord3(rawProbe.git);
6389
+ const probeGitResult = readRecord3(probeGit.result);
6390
+ const probeDirectStatus = readRecord3(probeGit.status);
6391
+ const probeNestedStatus = readRecord3(probeGitResult.status);
6392
+ const lastCheckedAt = options?.lastCheckedAt;
6393
+ let best = null;
6394
+ for (const status of [directStatus, nestedStatus, probeDirectStatus, probeNestedStatus]) {
6395
+ const normalized = normalizeGitStatus(status, node, { lastCheckedAt: lastCheckedAt ?? Date.now() });
6396
+ if (!normalized) continue;
6397
+ const score = scoreGitStatusCandidate(normalized);
6398
+ if (!best || score > best.score) best = { git: normalized, score };
6399
+ }
6400
+ return best?.git;
6401
+ }
6402
+ function normalizeMeshNodeId(node) {
6403
+ const record = node && typeof node === "object" ? node : {};
6404
+ return readString5(record.id, record.nodeId, record.node_id);
6405
+ }
6406
+ function meshNodeIdMatches(node, candidateId) {
6407
+ if (!candidateId) return false;
6408
+ const trimmed = candidateId.trim();
6409
+ if (!trimmed) return false;
6410
+ return normalizeMeshNodeId(node) === trimmed;
6411
+ }
6412
+ function summarizeGitShape(status) {
6413
+ const record = readRecord3(status);
6414
+ if (!Object.keys(record).length) return null;
6415
+ const submodules = Array.isArray(record.submodules) ? record.submodules.map((entry) => {
6416
+ const sub = readRecord3(entry);
6417
+ return {
6418
+ path: readString5(sub.path) ?? null,
6419
+ commit: readString5(sub.commit)?.slice(0, 12) ?? null,
6420
+ dirty: readBoolean(sub.dirty) ?? false,
6421
+ outOfSync: readBoolean(sub.outOfSync, sub.out_of_sync) ?? false
6422
+ };
6423
+ }) : [];
6424
+ return {
6425
+ isGitRepo: readBoolean(record.isGitRepo),
6426
+ workspace: readString5(record.workspace) ?? null,
6427
+ repoRoot: readString5(record.repoRoot, record.repo_root) ?? null,
6428
+ branch: readString5(record.branch) ?? null,
6429
+ upstream: readString5(record.upstream) ?? null,
6430
+ upstreamStatus: readString5(record.upstreamStatus, record.upstream_status) ?? null,
6431
+ headCommit: readString5(record.headCommit, record.head_commit)?.slice(0, 12) ?? null,
6432
+ ahead: readNumber(record.ahead) ?? null,
6433
+ behind: readNumber(record.behind) ?? null,
6434
+ dirtyCounts: {
6435
+ staged: readNumber(record.staged) ?? 0,
6436
+ modified: readNumber(record.modified) ?? 0,
6437
+ untracked: readNumber(record.untracked) ?? 0,
6438
+ deleted: readNumber(record.deleted) ?? 0,
6439
+ renamed: readNumber(record.renamed) ?? 0
6440
+ },
6441
+ lastCheckedAt: readNumber(record.lastCheckedAt, record.last_checked_at) ?? null,
6442
+ submoduleCount: submodules.length,
6443
+ submodules
6444
+ };
6445
+ }
6446
+ var init_dist = __esm({
6447
+ "../mesh-shared/dist/index.mjs"() {
6448
+ "use strict";
6449
+ }
6450
+ });
6451
+
6187
6452
  // src/mesh/mesh-events-utils.ts
6188
6453
  function readNonEmptyString2(value) {
6189
6454
  return typeof value === "string" && value.trim() ? value.trim() : "";
6190
6455
  }
6191
- function readRecord3(value) {
6456
+ function readRecord4(value) {
6192
6457
  return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
6193
6458
  }
6194
6459
  function buildMeshWorkerRelayStamp(currentSettings, meshContext) {
@@ -6212,13 +6477,13 @@ function resolveEventSessionId(event, fallback) {
6212
6477
  return readNonEmptyString2(event.targetSessionId) || readNonEmptyString2(event.sessionId) || readNonEmptyString2(event.instanceId) || readNonEmptyString2(fallback);
6213
6478
  }
6214
6479
  function readRefineJobId(event) {
6215
- const metadata = readRecord3(event.metadataEvent) || event;
6216
- const result = readRecord3(metadata.result);
6217
- const refineJob = readRecord3(result?.refineJob);
6480
+ const metadata = readRecord4(event.metadataEvent) || event;
6481
+ const result = readRecord4(metadata.result);
6482
+ const refineJob = readRecord4(result?.refineJob);
6218
6483
  return readNonEmptyString2(metadata.jobId) || readNonEmptyString2(refineJob?.jobId);
6219
6484
  }
6220
6485
  function readWorkerResultMetadata(event) {
6221
- return readRecord3(event.workerResult) || readRecord3(event.meshWorkerResult) || readRecord3(event.structuredResult);
6486
+ return readRecord4(event.workerResult) || readRecord4(event.meshWorkerResult) || readRecord4(event.structuredResult);
6222
6487
  }
6223
6488
  function formatCompletionMetadata(event) {
6224
6489
  const completionDiagnostic = event.completionDiagnostic && typeof event.completionDiagnostic === "object" ? event.completionDiagnostic : null;
@@ -6296,10 +6561,10 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
6296
6561
  }
6297
6562
  if (args.event === "refine:completed") {
6298
6563
  const jobId = readRefineJobId({ metadataEvent: args.metadataEvent });
6299
- const result = readRecord3(args.metadataEvent.result);
6300
- const validationSummary = readRecord3(result?.validationSummary);
6301
- const patchEquivalence = readRecord3(result?.patchEquivalence);
6302
- const finalConvergence = readRecord3(result?.finalBranchConvergenceState);
6564
+ const result = readRecord4(args.metadataEvent.result);
6565
+ const validationSummary = readRecord4(result?.validationSummary);
6566
+ const patchEquivalence = readRecord4(result?.patchEquivalence);
6567
+ const finalConvergence = readRecord4(result?.finalBranchConvergenceState);
6303
6568
  const validationStatus = readNonEmptyString2(validationSummary?.status);
6304
6569
  const patchStatus = readNonEmptyString2(patchEquivalence?.status) || (patchEquivalence?.equivalent === true ? "passed" : "");
6305
6570
  const into = readNonEmptyString2(result?.into);
@@ -6320,10 +6585,10 @@ Next step: ${nextStep}`;
6320
6585
  }
6321
6586
  if (args.event === "refine:failed") {
6322
6587
  const jobId = readRefineJobId({ metadataEvent: args.metadataEvent });
6323
- const result = readRecord3(args.metadataEvent.result);
6324
- const validationSummary = readRecord3(result?.validationSummary);
6325
- const patchEquivalence = readRecord3(result?.patchEquivalence);
6326
- const finalConvergence = readRecord3(result?.finalBranchConvergenceState);
6588
+ const result = readRecord4(args.metadataEvent.result);
6589
+ const validationSummary = readRecord4(result?.validationSummary);
6590
+ const patchEquivalence = readRecord4(result?.patchEquivalence);
6591
+ const finalConvergence = readRecord4(result?.finalBranchConvergenceState);
6327
6592
  const code = readNonEmptyString2(result?.code);
6328
6593
  const error = readNonEmptyString2(result?.error);
6329
6594
  const validationStatus = readNonEmptyString2(validationSummary?.status);
@@ -6370,9 +6635,9 @@ function normalizeCoordinatorDaemonIds(coordinatorDaemonId) {
6370
6635
  return out;
6371
6636
  }
6372
6637
  function readRefineJobId2(event) {
6373
- const metadata = readRecord3(event.metadataEvent) || event;
6374
- const result = readRecord3(metadata.result);
6375
- const refineJob = readRecord3(result?.refineJob);
6638
+ const metadata = readRecord4(event.metadataEvent) || event;
6639
+ const result = readRecord4(metadata.result);
6640
+ const refineJob = readRecord4(result?.refineJob);
6376
6641
  return readNonEmptyString2(metadata.jobId) || readNonEmptyString2(refineJob?.jobId);
6377
6642
  }
6378
6643
  function hasPendingRefineTerminalEventDuplicate(event) {
@@ -6384,13 +6649,13 @@ function hasPendingRefineTerminalEventDuplicate(event) {
6384
6649
  );
6385
6650
  }
6386
6651
  function buildPendingEventFingerprint(event) {
6387
- const metadata = readRecord3(event.metadataEvent) || {};
6652
+ const metadata = readRecord4(event.metadataEvent) || {};
6388
6653
  if (event.event === "worktree_bootstrap_complete" || event.event === "worktree_bootstrap_failed") {
6389
6654
  return [event.meshId, event.event, event.nodeId || ""].join("::");
6390
6655
  }
6391
6656
  const sessionId = resolveEventSessionId(metadata);
6392
6657
  const providerSessionId = readNonEmptyString2(metadata.providerSessionId);
6393
- const taskId = readNonEmptyString2(metadata.taskId) || readNonEmptyString2(readRecord3(metadata.payload)?.taskId);
6658
+ const taskId = readNonEmptyString2(metadata.taskId) || readNonEmptyString2(readRecord4(metadata.payload)?.taskId);
6394
6659
  const jobId = readRefineJobId2(event);
6395
6660
  const timestamp = metadata.timestamp !== void 0 && metadata.timestamp !== null ? String(metadata.timestamp) : "";
6396
6661
  return [
@@ -6458,15 +6723,15 @@ function refineTerminalEventFromLedger(meshId, pending) {
6458
6723
  for (let i = entries.length - 1; i >= 0; i--) {
6459
6724
  const entry = entries[i];
6460
6725
  if (entry.kind !== "task_completed" && entry.kind !== "task_failed") continue;
6461
- const payload = readRecord3(entry.payload);
6726
+ const payload = readRecord4(entry.payload);
6462
6727
  if (payload?.source !== "refine_mesh_node_async_job") continue;
6463
- const refineJob = readRecord3(payload.refineJob);
6728
+ const refineJob = readRecord4(payload.refineJob);
6464
6729
  const jobId = readNonEmptyString2(refineJob?.jobId);
6465
6730
  if (!jobId || !acceptedJobIds.has(jobId)) continue;
6466
6731
  const eventName = entry.kind === "task_completed" ? "refine:completed" : "refine:failed";
6467
6732
  if (existingTerminalJobIds.has(`${eventName}:${jobId}`)) continue;
6468
6733
  existingTerminalJobIds.add(`${eventName}:${jobId}`);
6469
- const result = readRecord3(payload.result);
6734
+ const result = readRecord4(payload.result);
6470
6735
  const metadataEvent = {
6471
6736
  source: "refine_mesh_node_async_job",
6472
6737
  jobId,
@@ -7074,7 +7339,7 @@ function buildLongGeneratingCompletionReconciliation(args) {
7074
7339
  const providerType = readNonEmptyString2(args.metadataEvent.providerType);
7075
7340
  const providerSessionId = readNonEmptyString2(args.metadataEvent.providerSessionId);
7076
7341
  const workerResult = readWorkerResultMetadata(args.metadataEvent);
7077
- const completionDiagnostic = readRecord3(args.metadataEvent.completionDiagnostic);
7342
+ const completionDiagnostic = readRecord4(args.metadataEvent.completionDiagnostic);
7078
7343
  const finalSummary = readNonEmptyString2(args.metadataEvent.finalSummary);
7079
7344
  const status = readNonEmptyString2(args.metadataEvent.status).toLowerCase();
7080
7345
  const explicitCompletionEvidence = Boolean(
@@ -7390,6 +7655,111 @@ var init_mesh_routing = __esm({
7390
7655
  }
7391
7656
  });
7392
7657
 
7658
+ // src/mesh/mesh-unresolved-forward-outbox.ts
7659
+ function getStore() {
7660
+ try {
7661
+ return MeshRuntimeStore.getInstance();
7662
+ } catch {
7663
+ return void 0;
7664
+ }
7665
+ }
7666
+ function enqueueUnresolvedDelegateForward(coordinatorDaemonId, eventName, forwardPayload) {
7667
+ const target = readNonEmptyString2(coordinatorDaemonId);
7668
+ const event = readNonEmptyString2(eventName);
7669
+ if (!target || !event) return false;
7670
+ const store = getStore();
7671
+ if (!store) return false;
7672
+ const queuedAt = Date.now();
7673
+ const fingerprintSource = {
7674
+ event,
7675
+ meshId: UNRESOLVED_FORWARD_OUTBOX_MESH_ID,
7676
+ nodeLabel: readNonEmptyString2(forwardPayload.nodeId) || readNonEmptyString2(forwardPayload.workspace) || "unresolved-delegate",
7677
+ nodeId: readNonEmptyString2(forwardPayload.nodeId) || void 0,
7678
+ workspace: readNonEmptyString2(forwardPayload.workspace) || void 0,
7679
+ metadataEvent: forwardPayload,
7680
+ queuedAt,
7681
+ targetCoordinatorDaemonId: target
7682
+ };
7683
+ const fingerprint = `${target}::${buildPendingEventFingerprint(fingerprintSource)}`;
7684
+ try {
7685
+ const inserted = store.insertPendingEvent({
7686
+ id: (0, import_crypto9.randomUUID)(),
7687
+ meshId: UNRESOLVED_FORWARD_OUTBOX_MESH_ID,
7688
+ coordinatorDaemonId: target,
7689
+ event,
7690
+ // Store the flat forward payload + the queue timestamp so the retry tick can
7691
+ // rebuild the push args and apply age-based expiry without a schema change.
7692
+ payload: { forwardPayload, coordinatorDaemonId: target, queuedAt },
7693
+ fingerprint,
7694
+ queuedAt
7695
+ });
7696
+ if (inserted) {
7697
+ LOG.info("MeshEvents", `Durably queued unresolved-delegate ${event} for coordinator ${target} (outbox)`);
7698
+ }
7699
+ return true;
7700
+ } catch (e) {
7701
+ LOG.warn("MeshEvents", `Failed to persist unresolved-delegate forward to outbox: ${e?.message || e}`);
7702
+ return false;
7703
+ }
7704
+ }
7705
+ function peekUnresolvedDelegateForwards() {
7706
+ const store = getStore();
7707
+ if (!store) return [];
7708
+ let rows;
7709
+ try {
7710
+ rows = store.peekPendingEvents(UNRESOLVED_FORWARD_OUTBOX_MESH_ID);
7711
+ } catch {
7712
+ return [];
7713
+ }
7714
+ const out = [];
7715
+ for (const row of rows) {
7716
+ const stored = row.payload && typeof row.payload === "object" ? row.payload : {};
7717
+ const coordinatorDaemonId = readNonEmptyString2(stored.coordinatorDaemonId);
7718
+ const forwardPayload = stored.forwardPayload && typeof stored.forwardPayload === "object" ? stored.forwardPayload : void 0;
7719
+ if (!coordinatorDaemonId || !forwardPayload) continue;
7720
+ const queuedAt = typeof stored.queuedAt === "number" ? stored.queuedAt : 0;
7721
+ out.push({ id: row.id, coordinatorDaemonId, payload: forwardPayload, queuedAt });
7722
+ }
7723
+ return out;
7724
+ }
7725
+ function ackUnresolvedDelegateForward(id) {
7726
+ const store = getStore();
7727
+ if (!store) return;
7728
+ try {
7729
+ store.markPendingEventsDrainedById([id]);
7730
+ } catch {
7731
+ }
7732
+ }
7733
+ function expireStaleUnresolvedDelegateForwards(nowMs = Date.now()) {
7734
+ const entries = peekUnresolvedDelegateForwards();
7735
+ const staleIds = entries.filter((e) => e.queuedAt > 0 && nowMs - e.queuedAt >= UNRESOLVED_FORWARD_MAX_AGE_MS).map((e) => e.id);
7736
+ if (staleIds.length === 0) return 0;
7737
+ const store = getStore();
7738
+ if (!store) return 0;
7739
+ try {
7740
+ const removed = store.deletePendingEventsById(staleIds);
7741
+ if (removed > 0) {
7742
+ LOG.warn("MeshEvents", `Expired ${removed} unresolved-delegate forward(s) after ${Math.round(UNRESOLVED_FORWARD_MAX_AGE_MS / 6e4)}m of failed retries \u2014 coordinator unreachable, completion dropped`);
7743
+ }
7744
+ return removed;
7745
+ } catch {
7746
+ return 0;
7747
+ }
7748
+ }
7749
+ var import_crypto9, UNRESOLVED_FORWARD_OUTBOX_MESH_ID, UNRESOLVED_FORWARD_MAX_AGE_MS;
7750
+ var init_mesh_unresolved_forward_outbox = __esm({
7751
+ "src/mesh/mesh-unresolved-forward-outbox.ts"() {
7752
+ "use strict";
7753
+ import_crypto9 = require("crypto");
7754
+ init_logger();
7755
+ init_mesh_runtime_store();
7756
+ init_mesh_events_pending();
7757
+ init_mesh_events_utils();
7758
+ UNRESOLVED_FORWARD_OUTBOX_MESH_ID = "__unresolved_forward_outbox__";
7759
+ UNRESOLVED_FORWARD_MAX_AGE_MS = 30 * 60 * 1e3;
7760
+ }
7761
+ });
7762
+
7393
7763
  // src/mesh/mesh-events-coordinator.ts
7394
7764
  function resolveCoordinatorDrainDaemonIds(components) {
7395
7765
  const ids = /* @__PURE__ */ new Set();
@@ -7794,7 +8164,7 @@ async function resolveUsableProvider(components, nodeId, node, requiredTags) {
7794
8164
  return { reason: `provider_priority_unusable: ${failed.join("; ") || nodeId}` };
7795
8165
  }
7796
8166
  function readMeshNodeId(node) {
7797
- return readNonEmptyString2(node?.id) || readNonEmptyString2(node?.nodeId) || readNonEmptyString2(node?.node_id);
8167
+ return normalizeMeshNodeId(node) ?? "";
7798
8168
  }
7799
8169
  async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
7800
8170
  const queue = getQueue(meshId);
@@ -8023,7 +8393,7 @@ async function triggerMeshQueue(components, meshId) {
8023
8393
  }
8024
8394
  async function maybeAutoFastForwardIdleNode(components, args) {
8025
8395
  const mesh = getMeshWithCache(components, args.meshId);
8026
- const node = mesh?.nodes?.find((candidate) => candidate?.id === args.nodeId || candidate?.nodeId === args.nodeId);
8396
+ const node = mesh?.nodes?.find((candidate) => meshNodeIdMatches(candidate, args.nodeId));
8027
8397
  const workspace = readNonEmptyString2(node?.workspace);
8028
8398
  if (!workspace) return;
8029
8399
  if (!(0, import_fs10.existsSync)(workspace)) return;
@@ -8524,12 +8894,25 @@ function forwardUnresolvedDelegateEvent(components, routing, event) {
8524
8894
  nodeId: readNonEmptyString2(routing.nodeId) || readNonEmptyString2(event.meshNodeId) || void 0,
8525
8895
  workspace: readNonEmptyString2(routing.workspace) || readNonEmptyString2(event.workspace) || void 0
8526
8896
  };
8527
- Promise.resolve(components.dispatchMeshCommand(coordinatorDaemonId, "mesh_forward_event", payload)).catch((e) => {
8528
- LOG.warn("MeshEvents", `Fallback forward of ${eventName} to coordinator ${coordinatorDaemonId} failed: ${e?.message || e}`);
8897
+ const persisted = enqueueUnresolvedDelegateForward(coordinatorDaemonId, eventName, payload);
8898
+ Promise.resolve(components.dispatchMeshCommand(coordinatorDaemonId, "mesh_forward_event", payload)).then((result) => {
8899
+ if (result && result.success === false) {
8900
+ LOG.warn("MeshEvents", `Immediate forward of ${eventName} to coordinator ${coordinatorDaemonId} rejected (${readNonEmptyString2(result.error) || "no reason"}) \u2014 left queued for retry`);
8901
+ return;
8902
+ }
8903
+ if (persisted) ackUnresolvedDelegateForwardByFingerprint(coordinatorDaemonId, eventName, payload);
8904
+ }).catch((e) => {
8905
+ LOG.warn("MeshEvents", `Immediate forward of ${eventName} to coordinator ${coordinatorDaemonId} failed: ${e?.message || e} \u2014 left queued for retry`);
8529
8906
  });
8530
- LOG.info("MeshEvents", `Fallback-forwarded ${eventName} for unresolved-mesh worker at ${routing.workspace || "(no workspace)"} to coordinator daemon ${coordinatorDaemonId}`);
8907
+ LOG.info("MeshEvents", `Durably forwarded ${eventName} for unresolved-mesh worker at ${routing.workspace || "(no workspace)"} to coordinator daemon ${coordinatorDaemonId}`);
8531
8908
  return true;
8532
8909
  }
8910
+ function ackUnresolvedDelegateForwardByFingerprint(coordinatorDaemonId, eventName, payload) {
8911
+ const match = peekUnresolvedDelegateForwards().find(
8912
+ (entry) => entry.coordinatorDaemonId === coordinatorDaemonId && readNonEmptyString2(entry.payload.event) === eventName && readNonEmptyString2(entry.payload.targetSessionId || entry.payload.sessionId || entry.payload.instanceId) === readNonEmptyString2(payload.targetSessionId || payload.sessionId || payload.instanceId) && readNonEmptyString2(entry.payload.workspace) === readNonEmptyString2(payload.workspace)
8913
+ );
8914
+ if (match) ackUnresolvedDelegateForward(match.id);
8915
+ }
8533
8916
  function setupMeshEventForwarding(components) {
8534
8917
  components.instanceManager.onEvent((event) => {
8535
8918
  if (event.event === "agent:ready" || event.event === "agent:generating_completed") {
@@ -8611,7 +8994,9 @@ var init_mesh_events_coordinator = __esm({
8611
8994
  init_mesh_runtime_store();
8612
8995
  init_mesh_events_pending();
8613
8996
  init_mesh_routing();
8997
+ init_mesh_unresolved_forward_outbox();
8614
8998
  init_repo_mesh_types();
8999
+ init_dist();
8615
9000
  init_mesh_events_stale();
8616
9001
  init_mesh_events_utils();
8617
9002
  REMOTE_IDLE_SESSION_TTL_MS = 5 * 60 * 1e3;
@@ -8725,6 +9110,13 @@ async function runMeshReconcileTick(components) {
8725
9110
  return void 0;
8726
9111
  }
8727
9112
  })();
9113
+ if (dispatchMeshCommand) {
9114
+ try {
9115
+ await retryUnresolvedDelegateForwards(components);
9116
+ } catch (e) {
9117
+ LOG.warn("MeshReconcile", `Unresolved-delegate forward retry failed: ${e?.message || e}`);
9118
+ }
9119
+ }
8728
9120
  if (dispatchMeshCommand) {
8729
9121
  for (const mesh of listMeshes()) {
8730
9122
  const selfIds = resolveCoordinatorSelfIds(mesh, drainDaemonIds);
@@ -8778,6 +9170,28 @@ async function runMeshReconcileTick(components) {
8778
9170
  }
8779
9171
  }
8780
9172
  }
9173
+ async function retryUnresolvedDelegateForwards(components) {
9174
+ const dispatchMeshCommand = components.dispatchMeshCommand;
9175
+ if (!dispatchMeshCommand) return;
9176
+ expireStaleUnresolvedDelegateForwards();
9177
+ const entries = peekUnresolvedDelegateForwards();
9178
+ if (entries.length === 0) return;
9179
+ for (const entry of entries) {
9180
+ let result;
9181
+ try {
9182
+ result = await dispatchMeshCommand(entry.coordinatorDaemonId, "mesh_forward_event", entry.payload);
9183
+ } catch (e) {
9184
+ LOG.warn("MeshReconcile", `Retry forward to coordinator ${entry.coordinatorDaemonId} failed: ${e?.message || e} \u2014 left queued`);
9185
+ continue;
9186
+ }
9187
+ if (result && result.success === false) {
9188
+ LOG.warn("MeshReconcile", `Retry forward to coordinator ${entry.coordinatorDaemonId} rejected (${readNonEmptyString2(result.error) || "no reason"}) \u2014 left queued`);
9189
+ continue;
9190
+ }
9191
+ ackUnresolvedDelegateForward(entry.id);
9192
+ LOG.info("MeshReconcile", `Retried+delivered unresolved-delegate ${readNonEmptyString2(entry.payload.event)} to coordinator ${entry.coordinatorDaemonId}`);
9193
+ }
9194
+ }
8781
9195
  async function pullRemoteNodeQueues(components, mesh, localDaemonId, candidateDaemonIds) {
8782
9196
  const dispatchMeshCommand = components.dispatchMeshCommand;
8783
9197
  if (!dispatchMeshCommand) return;
@@ -8854,6 +9268,7 @@ var init_mesh_reconcile_loop = __esm({
8854
9268
  init_mesh_events_pending();
8855
9269
  init_mesh_runtime_store();
8856
9270
  init_mesh_events_coordinator();
9271
+ init_mesh_unresolved_forward_outbox();
8857
9272
  init_mesh_events_utils();
8858
9273
  DEFAULT_RECONCILE_INTERVAL_MS = 4e3;
8859
9274
  }
@@ -17532,9 +17947,10 @@ function buildMeshLedgerReconciliationEvidence(meshId, replicas) {
17532
17947
  init_mesh_work_queue();
17533
17948
 
17534
17949
  // src/mesh/mesh-active-work.ts
17950
+ init_dist();
17535
17951
  var DIRECT_DISPATCH_VIA = /* @__PURE__ */ new Set(["p2p_direct", "local_direct", "mesh_send_task"]);
17536
17952
  var TERMINAL_LEDGER_KINDS = /* @__PURE__ */ new Set(["task_completed", "task_failed", "task_stalled"]);
17537
- function readString5(value) {
17953
+ function readString6(value) {
17538
17954
  return typeof value === "string" && value.trim() ? value.trim() : void 0;
17539
17955
  }
17540
17956
  function summarizeMessage(message) {
@@ -17549,7 +17965,7 @@ function elapsedSince(value, now) {
17549
17965
  function sessionStatusFromNodes(nodes, nodeId, sessionId) {
17550
17966
  if (!Array.isArray(nodes)) return {};
17551
17967
  if (!nodeId) return { staleReason: "direct task has no node id" };
17552
- const node = nodes.find((item) => readString5(item?.id) === nodeId || readString5(item?.nodeId) === nodeId || readString5(item?.node_id) === nodeId);
17968
+ const node = nodes.find((item) => meshNodeIdMatches(item, nodeId));
17553
17969
  if (!node) return { staleReason: "direct task node is no longer in the live mesh" };
17554
17970
  if (!sessionId) return {};
17555
17971
  const candidates = [];
@@ -17573,12 +17989,12 @@ function sessionStatusFromNodes(nodes, nodeId, sessionId) {
17573
17989
  }
17574
17990
  const session = candidates.find((item) => {
17575
17991
  if (typeof item === "string") return item === sessionId;
17576
- const id = readString5(item?.id) || readString5(item?.sessionId) || readString5(item?.session_id) || readString5(item?.runtimeSessionId) || readString5(item?.instanceId);
17992
+ const id = readString6(item?.id) || readString6(item?.sessionId) || readString6(item?.session_id) || readString6(item?.runtimeSessionId) || readString6(item?.instanceId);
17577
17993
  return id === sessionId;
17578
17994
  });
17579
17995
  if (!session) return { staleReason: "direct task session is not present in live session records" };
17580
17996
  if (typeof session === "string") return {};
17581
- const raw = `${readString5(session.status) || ""} ${readString5(session.lifecycle) || ""} ${readString5(session.state) || ""} ${readString5(session.activeChat?.status) || ""}`.toLowerCase();
17997
+ const raw = `${readString6(session.status) || ""} ${readString6(session.lifecycle) || ""} ${readString6(session.state) || ""} ${readString6(session.activeChat?.status) || ""}`.toLowerCase();
17582
17998
  if (raw.includes("approval")) return { status: "awaiting_approval" };
17583
17999
  if (raw.includes("generating") || raw.includes("running") || raw.includes("busy")) return { status: "generating" };
17584
18000
  if (raw.includes("failed") || raw.includes("stopped") || raw.includes("terminated") || raw.includes("exited")) return { status: "failed" };
@@ -17589,14 +18005,14 @@ function isDirectDispatch(entry) {
17589
18005
  if (entry.kind !== "task_dispatched") return false;
17590
18006
  const payload = entry.payload || {};
17591
18007
  if (payload.source === "direct") return true;
17592
- const via = readString5(payload.via);
18008
+ const via = readString6(payload.via);
17593
18009
  return Boolean(via && DIRECT_DISPATCH_VIA.has(via) && payload.source !== "queue");
17594
18010
  }
17595
18011
  function directDispatchTaskId(entry) {
17596
- return readString5(entry.payload?.taskId) || entry.id;
18012
+ return readString6(entry.payload?.taskId) || entry.id;
17597
18013
  }
17598
18014
  function terminalMatchesDispatch(terminal, dispatch, taskId) {
17599
- const terminalTaskId = readString5(terminal.payload?.taskId);
18015
+ const terminalTaskId = readString6(terminal.payload?.taskId);
17600
18016
  if (terminalTaskId && terminalTaskId === taskId) return true;
17601
18017
  if (terminalTaskId && terminalTaskId !== taskId) return false;
17602
18018
  if (dispatch.sessionId && terminal.sessionId === dispatch.sessionId) return true;
@@ -17719,7 +18135,7 @@ function buildMeshActiveWork(opts) {
17719
18135
  const isNoTransition = !terminalStatus && !live.status;
17720
18136
  const isIdleUnacknowledged = status === "idle";
17721
18137
  const ledgerOnlyStaleReason = !terminalRow && (isIdleUnacknowledged || isNoTransition || dispatchedToIdleSession && isIdleUnacknowledged) ? "direct task dispatch has no provider acknowledgement, transcript append, or active runtime transition" : void 0;
17722
- const message = readString5(dispatch.payload?.message) || readString5(dispatch.payload?.summary) || "";
18138
+ const message = readString6(dispatch.payload?.message) || readString6(dispatch.payload?.summary) || "";
17723
18139
  const { title, summary: summary2 } = summarizeMessage(message);
17724
18140
  const isFreshUnacknowledged = Boolean(ledgerOnlyStaleReason && !live.staleReason);
17725
18141
  const record = {
@@ -17728,11 +18144,11 @@ function buildMeshActiveWork(opts) {
17728
18144
  status,
17729
18145
  nodeId: dispatch.nodeId,
17730
18146
  sessionId: dispatch.sessionId,
17731
- providerType: dispatch.providerType || readString5(dispatch.payload?.providerType),
17732
- taskTitle: readString5(dispatch.payload?.taskTitle) || title,
17733
- taskSummary: readString5(dispatch.payload?.taskSummary) || summary2,
18147
+ providerType: dispatch.providerType || readString6(dispatch.payload?.providerType),
18148
+ taskTitle: readString6(dispatch.payload?.taskTitle) || title,
18149
+ taskSummary: readString6(dispatch.payload?.taskSummary) || summary2,
17734
18150
  message,
17735
- taskMode: readString5(dispatch.payload?.taskMode),
18151
+ taskMode: readString6(dispatch.payload?.taskMode),
17736
18152
  createdAt: dispatch.timestamp,
17737
18153
  updatedAt: terminal?.timestamp || dispatch.timestamp,
17738
18154
  dispatchedAt: dispatch.timestamp,
@@ -17767,7 +18183,7 @@ function buildMeshActiveWork(opts) {
17767
18183
  const isNoTransition = !terminalStatus && !live.status;
17768
18184
  const isIdleUnacknowledged = status === "idle";
17769
18185
  const ledgerOnlyStaleReason = !terminalRow && (isIdleUnacknowledged || isNoTransition || dispatchedToIdleSession && isIdleUnacknowledged) ? "direct task dispatch has no provider acknowledgement, transcript append, or active runtime transition" : void 0;
17770
- const message = readString5(dispatch.payload?.message) || readString5(dispatch.payload?.summary) || "";
18186
+ const message = readString6(dispatch.payload?.message) || readString6(dispatch.payload?.summary) || "";
17771
18187
  const { title, summary: summary2 } = summarizeMessage(message);
17772
18188
  const isFreshUnacknowledged = Boolean(ledgerOnlyStaleReason && !live.staleReason);
17773
18189
  const record = {
@@ -17776,11 +18192,11 @@ function buildMeshActiveWork(opts) {
17776
18192
  status,
17777
18193
  nodeId: dispatch.nodeId,
17778
18194
  sessionId: dispatch.sessionId,
17779
- providerType: dispatch.providerType || readString5(dispatch.payload?.providerType),
17780
- taskTitle: readString5(dispatch.payload?.taskTitle) || title,
17781
- taskSummary: readString5(dispatch.payload?.taskSummary) || summary2,
18195
+ providerType: dispatch.providerType || readString6(dispatch.payload?.providerType),
18196
+ taskTitle: readString6(dispatch.payload?.taskTitle) || title,
18197
+ taskSummary: readString6(dispatch.payload?.taskSummary) || summary2,
17782
18198
  message,
17783
- taskMode: readString5(dispatch.payload?.taskMode),
18199
+ taskMode: readString6(dispatch.payload?.taskMode),
17784
18200
  createdAt: dispatch.timestamp,
17785
18201
  updatedAt: terminal?.timestamp || dispatch.timestamp,
17786
18202
  dispatchedAt: dispatch.timestamp,
@@ -22124,7 +22540,7 @@ var ExtensionProviderInstance = class {
22124
22540
  this.runtimeMessages = [];
22125
22541
  }
22126
22542
  updateSettings(newSettings) {
22127
- this.settings = { ...newSettings };
22543
+ this.settings = { ...this.settings, ...newSettings };
22128
22544
  this.monitor.updateConfig({
22129
22545
  approvalAlert: this.settings.approvalAlert !== false,
22130
22546
  longGeneratingAlert: this.settings.longGeneratingAlert !== false,
@@ -22791,7 +23207,7 @@ var IdeProviderInstance = class {
22791
23207
  this.extensions.clear();
22792
23208
  }
22793
23209
  updateSettings(newSettings) {
22794
- this.settings = { ...newSettings };
23210
+ this.settings = { ...this.settings, ...newSettings };
22795
23211
  this.monitor.updateConfig({
22796
23212
  approvalAlert: this.settings.approvalAlert !== false,
22797
23213
  longGeneratingAlert: this.settings.longGeneratingAlert !== false,
@@ -32339,22 +32755,7 @@ var CliProviderInstance = class _CliProviderInstance {
32339
32755
  };
32340
32756
  }
32341
32757
  updateSettings(newSettings) {
32342
- const runtimeMeshSettings = {};
32343
- for (const key of [
32344
- "meshNodeFor",
32345
- "meshNodeId",
32346
- "meshActiveTaskId",
32347
- "meshCoordinatorFor",
32348
- "meshCoordinatorDaemonId",
32349
- "meshCoordinatorNodeId",
32350
- "spawnedSessionVisibility",
32351
- "launchedByCoordinator"
32352
- ]) {
32353
- if (this.settings[key] !== void 0 && newSettings[key] === void 0) {
32354
- runtimeMeshSettings[key] = this.settings[key];
32355
- }
32356
- }
32357
- this.settings = { ...newSettings, ...runtimeMeshSettings };
32758
+ this.settings = { ...this.settings, ...newSettings };
32358
32759
  this.adapter.updateRuntimeSettings?.(this.settings);
32359
32760
  this.monitor.updateConfig({
32360
32761
  approvalAlert: this.settings.approvalAlert !== false,
@@ -39681,207 +40082,7 @@ function getAvailableIdeIds() {
39681
40082
  init_config();
39682
40083
  init_cli_detector();
39683
40084
  init_git_status();
39684
-
39685
- // ../mesh-shared/dist/index.mjs
39686
- function readRecord5(value) {
39687
- return value && typeof value === "object" && !Array.isArray(value) ? value : {};
39688
- }
39689
- function readString6(...values) {
39690
- for (const value of values) {
39691
- if (typeof value !== "string") continue;
39692
- const trimmed = value.trim();
39693
- if (trimmed) return trimmed;
39694
- }
39695
- return void 0;
39696
- }
39697
- function readNumber(...values) {
39698
- for (const value of values) {
39699
- if (typeof value === "number" && Number.isFinite(value)) return value;
39700
- }
39701
- return void 0;
39702
- }
39703
- function readBoolean(...values) {
39704
- for (const value of values) {
39705
- if (typeof value === "boolean") return value;
39706
- }
39707
- return void 0;
39708
- }
39709
- function joinRepoPath(root, relativePath) {
39710
- const normalizedRoot = typeof root === "string" ? root.trim().replace(/[\\/]+$/, "") : "";
39711
- const normalizedPath = typeof relativePath === "string" ? relativePath.trim() : "";
39712
- if (!normalizedPath) return void 0;
39713
- if (/^(?:[A-Za-z]:[\\/]|\/)/.test(normalizedPath)) return normalizedPath;
39714
- if (!normalizedRoot) return void 0;
39715
- return `${normalizedRoot}/${normalizedPath.replace(/^[\\/]+/, "")}`;
39716
- }
39717
- function scoreGitUpstreamFreshness(status) {
39718
- switch (status) {
39719
- case "fresh":
39720
- return 30;
39721
- case "no_upstream":
39722
- return 4;
39723
- case "unchecked":
39724
- case void 0:
39725
- return 0;
39726
- case "stale":
39727
- return -10;
39728
- case "unavailable":
39729
- return -15;
39730
- default:
39731
- return 0;
39732
- }
39733
- }
39734
- function readGitSubmodules(value, parentRepoRoot) {
39735
- if (!Array.isArray(value)) return void 0;
39736
- const submodules = value.map((entry) => {
39737
- const submodule = readRecord5(entry);
39738
- const path40 = readString6(submodule.path);
39739
- const commit = readString6(submodule.commit);
39740
- const repoPath = readString6(submodule.repoPath, submodule.repo_root) ?? joinRepoPath(parentRepoRoot, path40);
39741
- if (!path40 || !commit) return null;
39742
- const result = {
39743
- path: path40,
39744
- commit,
39745
- dirty: readBoolean(submodule.dirty) ?? false,
39746
- outOfSync: readBoolean(submodule.outOfSync, submodule.out_of_sync) ?? false,
39747
- lastCheckedAt: readNumber(submodule.lastCheckedAt, submodule.last_checked_at) ?? Date.now()
39748
- };
39749
- if (repoPath) result.repoPath = repoPath;
39750
- const error = readString6(submodule.error);
39751
- if (error) result.error = error;
39752
- return result;
39753
- }).filter((entry) => entry !== null);
39754
- return submodules.length > 0 ? submodules : void 0;
39755
- }
39756
- function hasGitStatusEvidence(status) {
39757
- return readBoolean(status.isGitRepo) !== void 0 || Boolean(readString6(status.branch, status.upstream, status.upstreamStatus, status.upstream_status, status.headCommit)) || Boolean(readString6(status.repoRoot, status.repo_root, status.workspace)) || readNumber(
39758
- status.ahead,
39759
- status.behind,
39760
- status.staged,
39761
- status.modified,
39762
- status.untracked,
39763
- status.deleted,
39764
- status.renamed,
39765
- status.lastCheckedAt,
39766
- status.last_checked_at
39767
- ) !== void 0 || Array.isArray(status.submodules) && status.submodules.length > 0;
39768
- }
39769
- function normalizeGitStatus(status, node, options) {
39770
- const explicitIsGitRepo = readBoolean(status.isGitRepo);
39771
- if (!Object.keys(status).length || !hasGitStatusEvidence(status)) return void 0;
39772
- const isGitRepo = explicitIsGitRepo ?? true;
39773
- const conflictFiles = Array.isArray(status.conflictFiles) ? status.conflictFiles.filter((entry) => typeof entry === "string") : [];
39774
- const conflictCount = readNumber(status.conflicts) ?? conflictFiles.length;
39775
- const hasConflicts = readBoolean(status.hasConflicts) ?? conflictCount > 0;
39776
- const repoRoot = readString6(status.repoRoot, status.repo_root, node.repoRoot, node.repo_root, status.workspace, node.workspace) || void 0;
39777
- const submodules = readGitSubmodules(status.submodules, repoRoot);
39778
- const upstreamStatus = readString6(status.upstreamStatus, status.upstream_status);
39779
- const upstreamFetchedAt = readNumber(status.upstreamFetchedAt, status.upstream_fetched_at);
39780
- const upstreamFetchError = readString6(status.upstreamFetchError, status.upstream_fetch_error);
39781
- const error = readString6(status.error);
39782
- const staged = readNumber(status.staged) ?? 0;
39783
- const modified = readNumber(status.modified) ?? 0;
39784
- const untracked = readNumber(status.untracked) ?? 0;
39785
- const deleted = readNumber(status.deleted) ?? 0;
39786
- const renamed = readNumber(status.renamed) ?? 0;
39787
- return {
39788
- workspace: readString6(status.workspace, node.workspace) || "",
39789
- repoRoot: repoRoot ?? null,
39790
- isGitRepo,
39791
- branch: readString6(status.branch) ?? null,
39792
- headCommit: readString6(status.headCommit) ?? null,
39793
- headMessage: readString6(status.headMessage) ?? null,
39794
- upstream: readString6(status.upstream) ?? null,
39795
- upstreamStatus: upstreamStatus ?? "unchecked",
39796
- ...upstreamFetchedAt !== void 0 ? { upstreamFetchedAt } : {},
39797
- ...upstreamFetchError ? { upstreamFetchError } : {},
39798
- ahead: readNumber(status.ahead) ?? 0,
39799
- behind: readNumber(status.behind) ?? 0,
39800
- staged,
39801
- modified,
39802
- untracked,
39803
- deleted,
39804
- renamed,
39805
- dirty: readBoolean(status.dirty, status.isDirty, status.is_dirty) ?? (staged + modified + untracked + deleted + renamed > 0 || hasConflicts),
39806
- hasConflicts,
39807
- conflictFiles,
39808
- stashCount: readNumber(status.stashCount, status.stash_count) ?? 0,
39809
- lastCheckedAt: options?.lastCheckedAt ?? readNumber(status.lastCheckedAt, status.last_checked_at) ?? Date.now(),
39810
- ...submodules ? { submodules } : {},
39811
- ...error ? { error } : {}
39812
- };
39813
- }
39814
- function scoreGitStatusCandidate(git) {
39815
- if (!git) return Number.NEGATIVE_INFINITY;
39816
- let score = 0;
39817
- if (git.isGitRepo === true) score += 50;
39818
- if (git.isGitRepo === false) score -= 10;
39819
- if (git.branch) score += 20;
39820
- if (git.headCommit) score += 20;
39821
- if (git.upstream) score += 10;
39822
- score += scoreGitUpstreamFreshness(git.upstreamStatus);
39823
- if (typeof git.ahead === "number") score += 2;
39824
- if (typeof git.behind === "number") score += 2;
39825
- if (Array.isArray(git.submodules) && git.submodules.length > 0) score += 4 + git.submodules.length;
39826
- if (git.error) score -= 20;
39827
- return score;
39828
- }
39829
- function pickBestTransitGitStatus(node, options) {
39830
- const rawGit = readRecord5(node.lastGit ?? node.last_git);
39831
- const gitResult = readRecord5(rawGit.result);
39832
- const directStatus = readRecord5(rawGit.status);
39833
- const nestedStatus = readRecord5(gitResult.status);
39834
- const rawProbe = readRecord5(node.lastProbe ?? node.last_probe);
39835
- const probeGit = readRecord5(rawProbe.git);
39836
- const probeGitResult = readRecord5(probeGit.result);
39837
- const probeDirectStatus = readRecord5(probeGit.status);
39838
- const probeNestedStatus = readRecord5(probeGitResult.status);
39839
- const lastCheckedAt = options?.lastCheckedAt;
39840
- let best = null;
39841
- for (const status of [directStatus, nestedStatus, probeDirectStatus, probeNestedStatus]) {
39842
- const normalized = normalizeGitStatus(status, node, { lastCheckedAt: lastCheckedAt ?? Date.now() });
39843
- if (!normalized) continue;
39844
- const score = scoreGitStatusCandidate(normalized);
39845
- if (!best || score > best.score) best = { git: normalized, score };
39846
- }
39847
- return best?.git;
39848
- }
39849
- function summarizeGitShape(status) {
39850
- const record = readRecord5(status);
39851
- if (!Object.keys(record).length) return null;
39852
- const submodules = Array.isArray(record.submodules) ? record.submodules.map((entry) => {
39853
- const sub = readRecord5(entry);
39854
- return {
39855
- path: readString6(sub.path) ?? null,
39856
- commit: readString6(sub.commit)?.slice(0, 12) ?? null,
39857
- dirty: readBoolean(sub.dirty) ?? false,
39858
- outOfSync: readBoolean(sub.outOfSync, sub.out_of_sync) ?? false
39859
- };
39860
- }) : [];
39861
- return {
39862
- isGitRepo: readBoolean(record.isGitRepo),
39863
- workspace: readString6(record.workspace) ?? null,
39864
- repoRoot: readString6(record.repoRoot, record.repo_root) ?? null,
39865
- branch: readString6(record.branch) ?? null,
39866
- upstream: readString6(record.upstream) ?? null,
39867
- upstreamStatus: readString6(record.upstreamStatus, record.upstream_status) ?? null,
39868
- headCommit: readString6(record.headCommit, record.head_commit)?.slice(0, 12) ?? null,
39869
- ahead: readNumber(record.ahead) ?? null,
39870
- behind: readNumber(record.behind) ?? null,
39871
- dirtyCounts: {
39872
- staged: readNumber(record.staged) ?? 0,
39873
- modified: readNumber(record.modified) ?? 0,
39874
- untracked: readNumber(record.untracked) ?? 0,
39875
- deleted: readNumber(record.deleted) ?? 0,
39876
- renamed: readNumber(record.renamed) ?? 0
39877
- },
39878
- lastCheckedAt: readNumber(record.lastCheckedAt, record.last_checked_at) ?? null,
39879
- submoduleCount: submodules.length,
39880
- submodules
39881
- };
39882
- }
39883
-
39884
- // src/commands/router.ts
40085
+ init_dist();
39885
40086
  init_logger();
39886
40087
 
39887
40088
  // src/logging/command-log.ts
@@ -40961,7 +41162,10 @@ function summarizeRepoMeshStatusDebug(status) {
40961
41162
  branchConvergenceSummary: status?.branchConvergenceSummary ?? status?.branch_convergence_summary ?? null,
40962
41163
  nodeCount: nodes.length,
40963
41164
  nodes: nodes.map((node) => ({
40964
- nodeId: readStringValue(node?.nodeId, node?.id) ?? null,
41165
+ // Status emits the id under `nodeId` (3-way input absorbed). The
41166
+ // inline cache keeps `id` and `nodeId` equal, so this serialized form
41167
+ // round-trips back through the cache without flipping shape.
41168
+ nodeId: normalizeMeshNodeId(node) ?? null,
40965
41169
  daemonId: readStringValue(node?.daemonId, node?.daemon_id) ?? null,
40966
41170
  workspace: readStringValue(node?.workspace, node?.git?.workspace) ?? null,
40967
41171
  health: readStringValue(node?.health) ?? null,
@@ -41206,7 +41410,23 @@ function inlineMeshCarriesTransientNodeTruth(inlineMesh) {
41206
41410
  return inlineMesh.nodes.some((node) => hasInlineMeshTransientNodeState(node));
41207
41411
  }
41208
41412
  function readInlineMeshNodeId(node) {
41209
- return readStringValue(node?.id, node?.nodeId) || "";
41413
+ return normalizeMeshNodeId(node) ?? "";
41414
+ }
41415
+ function foldMeshNodeIdentityToCanonical(node) {
41416
+ if (!node || typeof node !== "object" || Array.isArray(node)) return node;
41417
+ const canonical = normalizeMeshNodeId(node);
41418
+ if (canonical === void 0) return node;
41419
+ if (node.id === canonical && node.nodeId === canonical && node.node_id === void 0) return node;
41420
+ node.id = canonical;
41421
+ node.nodeId = canonical;
41422
+ if ("node_id" in node) delete node.node_id;
41423
+ return node;
41424
+ }
41425
+ function normalizeInlineMeshNodeIdentity(inlineMesh) {
41426
+ if (!inlineMesh || typeof inlineMesh !== "object" || Array.isArray(inlineMesh)) return inlineMesh;
41427
+ if (!Array.isArray(inlineMesh.nodes) || inlineMesh.nodes.length === 0) return inlineMesh;
41428
+ for (const node of inlineMesh.nodes) foldMeshNodeIdentityToCanonical(node);
41429
+ return inlineMesh;
41210
41430
  }
41211
41431
  function sanitizeInlineMesh(inlineMesh) {
41212
41432
  if (!inlineMesh || typeof inlineMesh !== "object" || Array.isArray(inlineMesh)) return inlineMesh;
@@ -41308,7 +41528,7 @@ function deriveMeshNodeHealthFromGit(git) {
41308
41528
  return "online";
41309
41529
  }
41310
41530
  function readMeshNodeLabel(status, node) {
41311
- return readStringValue(status.nodeId, node?.id, node?.nodeId) ?? "unknown";
41531
+ return readStringValue(status.nodeId, normalizeMeshNodeId(node)) ?? "unknown";
41312
41532
  }
41313
41533
  function buildInlineMeshBranchConvergence(args) {
41314
41534
  const git = readObjectRecord(args.status.git);
@@ -41587,7 +41807,7 @@ async function hydrateInlineMeshDirectTruth(args) {
41587
41807
  let peerConfirmedCount = 0;
41588
41808
  const unavailableNodeIds = [];
41589
41809
  for (const [nodeIndex, node] of nodes.entries()) {
41590
- const nodeId = readStringValue(node?.id, node?.nodeId) || `node_${nodeIndex}`;
41810
+ const nodeId = normalizeMeshNodeId(node) || `node_${nodeIndex}`;
41591
41811
  const workspace = readStringValue(node?.workspace);
41592
41812
  const daemonId = readStringValue(node?.daemonId);
41593
41813
  const isSelfNode = Boolean(
@@ -41718,7 +41938,7 @@ function buildHistoricalMeshSessions(args) {
41718
41938
  const liveWorkspaces = /* @__PURE__ */ new Set();
41719
41939
  const missingLocalWorktreeNodeIds = /* @__PURE__ */ new Set();
41720
41940
  for (const node of args.nodes || []) {
41721
- const nodeId = readStringValue(node?.id, node?.nodeId);
41941
+ const nodeId = normalizeMeshNodeId(node);
41722
41942
  const workspace = readStringValue(node?.workspace);
41723
41943
  if (nodeId) liveNodeIds.add(nodeId);
41724
41944
  if (workspace) liveWorkspaces.add(workspace);
@@ -41843,9 +42063,13 @@ function resolveRefineryAutoPublishSubmoduleMainCommits(mesh, workspace) {
41843
42063
  }
41844
42064
  return { enabled: false };
41845
42065
  }
41846
- async function computeGitPatchId(cwd, fromRef, toRef) {
42066
+ async function computeGitPatchId(cwd, fromRef, toRef, excludePaths = []) {
41847
42067
  const { execFileSync: execFileSync6 } = await import("child_process");
41848
- const diff = execFileSync6("git", ["diff", "--patch", "--full-index", fromRef, toRef], {
42068
+ const diffArgs = ["diff", "--patch", "--full-index", fromRef, toRef];
42069
+ if (excludePaths.length > 0) {
42070
+ diffArgs.push("--", ".", ...excludePaths.map((path40) => `:(exclude)${path40}`));
42071
+ }
42072
+ const diff = execFileSync6("git", diffArgs, {
41849
42073
  cwd,
41850
42074
  encoding: "utf8",
41851
42075
  maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
@@ -41914,8 +42138,9 @@ ${mergeTreeErr?.stderr || ""}`;
41914
42138
  gitlinkTrivialFastForward
41915
42139
  };
41916
42140
  }
41917
- const expectedPatchId = await computeGitPatchId(repoRoot, mergeBase, branchHead);
41918
- const actualPatchId = await computeGitPatchId(repoRoot, baseHead, mergedTree);
42141
+ const ffGitlinkExcludePaths = collectFastForwardGitlinkPaths(repoRoot, baseHead, branchHead);
42142
+ const expectedPatchId = await computeGitPatchId(repoRoot, mergeBase, branchHead, ffGitlinkExcludePaths);
42143
+ const actualPatchId = await computeGitPatchId(repoRoot, baseHead, mergedTree, ffGitlinkExcludePaths);
41919
42144
  const equivalent = expectedPatchId === actualPatchId;
41920
42145
  return {
41921
42146
  status: equivalent ? "passed" : "failed",
@@ -42111,6 +42336,14 @@ function readChangedPathKinds(repoRoot, fromRef, toRef) {
42111
42336
  return [];
42112
42337
  }
42113
42338
  }
42339
+ function collectFastForwardGitlinkPaths(repoRoot, baseHead, branchHead) {
42340
+ return readChangedGitlinkPaths(repoRoot, baseHead, branchHead).filter((path40) => {
42341
+ const baseCommit = readTreeObject(repoRoot, baseHead, path40);
42342
+ const branchCommit = readTreeObject(repoRoot, branchHead, path40);
42343
+ if (!baseCommit || !branchCommit) return false;
42344
+ return isSubmoduleFastForward((0, import_path10.resolve)(repoRoot, path40), baseCommit, branchCommit);
42345
+ });
42346
+ }
42114
42347
  function evaluateGitlinkTrivialFastForward(repoRoot, baseHead, branchHead) {
42115
42348
  const changedGitlinks = readChangedGitlinkPaths(repoRoot, baseHead, branchHead).map((path40) => {
42116
42349
  const baseCommit = readTreeObject(repoRoot, baseHead, path40);
@@ -42160,20 +42393,95 @@ function evaluateGitlinkTrivialFastForward(repoRoot, baseHead, branchHead) {
42160
42393
  }
42161
42394
  return { trivial: true, gitlinks: changedGitlinks };
42162
42395
  }
42396
+ function buildTreeWithGitlinksEqualized(repoRoot, commitish, paths, placeholderCommit) {
42397
+ try {
42398
+ const tree = (0, import_node_child_process6.execFileSync)("git", ["rev-parse", `${commitish}^{tree}`], {
42399
+ cwd: repoRoot,
42400
+ encoding: "utf8",
42401
+ maxBuffer: 1024 * 1024
42402
+ }).trim();
42403
+ if (!tree) return void 0;
42404
+ const updates = paths.map((path40) => `160000 commit ${placeholderCommit} ${path40}`).join("\n");
42405
+ if (!updates) return tree;
42406
+ const tmpIndex = (0, import_path10.join)(resolveGitDir(repoRoot), `adhdev-refine-eq-${commitish.slice(0, 12)}.index`);
42407
+ const env = { ...process.env, GIT_INDEX_FILE: tmpIndex };
42408
+ try {
42409
+ (0, import_node_child_process6.execFileSync)("git", ["read-tree", tree], { cwd: repoRoot, env, stdio: "ignore" });
42410
+ (0, import_node_child_process6.execFileSync)("git", ["update-index", "--index-info"], {
42411
+ cwd: repoRoot,
42412
+ env,
42413
+ input: `${updates}
42414
+ `,
42415
+ encoding: "utf8",
42416
+ stdio: ["pipe", "ignore", "ignore"]
42417
+ });
42418
+ const newTree = (0, import_node_child_process6.execFileSync)("git", ["write-tree"], { cwd: repoRoot, env, encoding: "utf8" }).trim();
42419
+ return newTree || void 0;
42420
+ } finally {
42421
+ try {
42422
+ fs24.rmSync(tmpIndex, { force: true });
42423
+ } catch {
42424
+ }
42425
+ }
42426
+ } catch {
42427
+ return void 0;
42428
+ }
42429
+ }
42163
42430
  function synthesizeTrivialFastForwardMergeTree(repoRoot, baseHead, branchHead, gitlinks) {
42164
42431
  try {
42165
- const baseTree = (0, import_node_child_process6.execFileSync)("git", ["rev-parse", `${baseHead}^{tree}`], {
42432
+ const branchGitlinks = gitlinks.filter((entry) => entry.branchCommit);
42433
+ const gitlinkPaths = branchGitlinks.map((entry) => entry.path);
42434
+ const mergeBase = (0, import_node_child_process6.execFileSync)("git", ["merge-base", baseHead, branchHead], {
42435
+ cwd: repoRoot,
42436
+ encoding: "utf8",
42437
+ maxBuffer: 1024 * 1024
42438
+ }).trim();
42439
+ let mergedContentTree;
42440
+ if (mergeBase && gitlinkPaths.length > 0) {
42441
+ const placeholder = readTreeObject(repoRoot, mergeBase, gitlinkPaths[0]) || branchGitlinks[0].branchCommit;
42442
+ const baseEqTree = buildTreeWithGitlinksEqualized(repoRoot, mergeBase, gitlinkPaths, placeholder);
42443
+ const oursEqTree = buildTreeWithGitlinksEqualized(repoRoot, baseHead, gitlinkPaths, placeholder);
42444
+ const theirsEqTree = buildTreeWithGitlinksEqualized(repoRoot, branchHead, gitlinkPaths, placeholder);
42445
+ if (baseEqTree && oursEqTree && theirsEqTree) {
42446
+ try {
42447
+ const baseEqCommit = (0, import_node_child_process6.execFileSync)("git", ["commit-tree", baseEqTree, "-m", "refine-ff-base"], {
42448
+ cwd: repoRoot,
42449
+ encoding: "utf8",
42450
+ maxBuffer: 1024 * 1024
42451
+ }).trim();
42452
+ const oursEqCommit = (0, import_node_child_process6.execFileSync)("git", ["commit-tree", oursEqTree, "-p", baseEqCommit, "-m", "refine-ff-ours"], {
42453
+ cwd: repoRoot,
42454
+ encoding: "utf8",
42455
+ maxBuffer: 1024 * 1024
42456
+ }).trim();
42457
+ const theirsEqCommit = (0, import_node_child_process6.execFileSync)("git", ["commit-tree", theirsEqTree, "-p", baseEqCommit, "-m", "refine-ff-theirs"], {
42458
+ cwd: repoRoot,
42459
+ encoding: "utf8",
42460
+ maxBuffer: 1024 * 1024
42461
+ }).trim();
42462
+ const mergeOut = (0, import_node_child_process6.execFileSync)("git", ["merge-tree", "--write-tree", oursEqCommit, theirsEqCommit], {
42463
+ cwd: repoRoot,
42464
+ encoding: "utf8",
42465
+ maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
42466
+ }).trim();
42467
+ mergedContentTree = mergeOut.split(/\s+/)[0] || void 0;
42468
+ } catch {
42469
+ mergedContentTree = void 0;
42470
+ }
42471
+ }
42472
+ }
42473
+ const contentTree = mergedContentTree || (0, import_node_child_process6.execFileSync)("git", ["rev-parse", `${baseHead}^{tree}`], {
42166
42474
  cwd: repoRoot,
42167
42475
  encoding: "utf8",
42168
42476
  maxBuffer: 1024 * 1024
42169
42477
  }).trim();
42170
- if (!baseTree) return void 0;
42171
- const updates = gitlinks.filter((entry) => entry.branchCommit).map((entry) => `160000 commit ${entry.branchCommit} ${entry.path}`).join("\n");
42172
- if (!updates) return baseTree;
42478
+ if (!contentTree) return void 0;
42479
+ const updates = branchGitlinks.map((entry) => `160000 commit ${entry.branchCommit} ${entry.path}`).join("\n");
42480
+ if (!updates) return contentTree;
42173
42481
  const tmpIndex = (0, import_path10.join)(resolveGitDir(repoRoot), `adhdev-refine-ff-${baseHead.slice(0, 12)}-${branchHead.slice(0, 12)}.index`);
42174
42482
  const env = { ...process.env, GIT_INDEX_FILE: tmpIndex };
42175
42483
  try {
42176
- (0, import_node_child_process6.execFileSync)("git", ["read-tree", baseTree], { cwd: repoRoot, env, stdio: "ignore" });
42484
+ (0, import_node_child_process6.execFileSync)("git", ["read-tree", contentTree], { cwd: repoRoot, env, stdio: "ignore" });
42177
42485
  (0, import_node_child_process6.execFileSync)("git", ["update-index", "--index-info"], {
42178
42486
  cwd: repoRoot,
42179
42487
  env,
@@ -42833,7 +43141,7 @@ function normalizeStandaloneHostCommandUrl(hostAddress) {
42833
43141
  function buildMemberJoinNode(mesh, args, fallbackDaemonId) {
42834
43142
  const requestedNodeId = typeof args?.memberNodeId === "string" ? args.memberNodeId.trim() : "";
42835
43143
  const explicit = args?.memberNode && typeof args.memberNode === "object" && !Array.isArray(args.memberNode) ? args.memberNode : null;
42836
- const configured = Array.isArray(mesh?.nodes) ? requestedNodeId ? mesh.nodes.find((node) => node?.id === requestedNodeId || node?.nodeId === requestedNodeId) : mesh.nodes[0] : null;
43144
+ const configured = Array.isArray(mesh?.nodes) ? requestedNodeId ? mesh.nodes.find((node) => meshNodeIdMatches(node, requestedNodeId)) : mesh.nodes[0] : null;
42837
43145
  const source = explicit || configured;
42838
43146
  const workspace = typeof source?.workspace === "string" && source.workspace.trim() ? source.workspace.trim() : typeof args?.workspace === "string" && args.workspace.trim() ? args.workspace.trim() : process.cwd();
42839
43147
  if (!workspace) return null;
@@ -42889,7 +43197,7 @@ var DaemonCommandRouter = class {
42889
43197
  if (nodeId) unavailableNodeIds.add(nodeId);
42890
43198
  }
42891
43199
  const nodes = snapshot.nodes.map((statusNode) => {
42892
- const nodeId = readStringValue(statusNode?.nodeId, statusNode?.id);
43200
+ const nodeId = normalizeMeshNodeId(statusNode);
42893
43201
  const inlineNode = nodeId ? inlineNodesById.get(nodeId) : void 0;
42894
43202
  if (!inlineNode) return statusNode;
42895
43203
  const liveGit = buildInlineMeshTransitGitStatus(inlineNode);
@@ -43002,7 +43310,7 @@ var DaemonCommandRouter = class {
43002
43310
  }
43003
43311
  warmInlineMeshCache(meshId, inlineMesh) {
43004
43312
  if (!inlineMesh || typeof inlineMesh !== "object") return void 0;
43005
- const sanitizedInlineMesh = sanitizeInlineMesh(inlineMesh);
43313
+ const sanitizedInlineMesh = sanitizeInlineMesh(normalizeInlineMeshNodeIdentity(inlineMesh));
43006
43314
  const cached2 = this.inlineMeshCache.get(meshId);
43007
43315
  if (cached2) {
43008
43316
  const merged = reconcileInlineMeshCache(cached2, sanitizedInlineMesh);
@@ -43019,7 +43327,7 @@ var DaemonCommandRouter = class {
43019
43327
  if (cached3) {
43020
43328
  if (inlineMeshCarriesTransientNodeTruth(inlineMesh)) {
43021
43329
  const merged = reconcileInlineMeshCache(cached3, inlineMesh);
43022
- this.inlineMeshCache.set(meshId, sanitizeInlineMesh(merged));
43330
+ this.inlineMeshCache.set(meshId, sanitizeInlineMesh(normalizeInlineMeshNodeIdentity(merged)));
43023
43331
  return { mesh: merged, inline: true, source: "inline_cache" };
43024
43332
  }
43025
43333
  return { mesh: cached3, inline: true, source: "inline_cache" };
@@ -43055,17 +43363,19 @@ var DaemonCommandRouter = class {
43055
43363
  return null;
43056
43364
  }
43057
43365
  updateInlineMeshNode(meshId, mesh, node) {
43058
- if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
43059
- const idx = mesh.nodes.findIndex((entry) => entry?.id === node.id || entry?.nodeId === node.id);
43366
+ const incomingId = normalizeMeshNodeId(node);
43367
+ if (!mesh || !Array.isArray(mesh.nodes) || !incomingId) return;
43368
+ const idx = mesh.nodes.findIndex((entry) => meshNodeIdMatches(entry, incomingId));
43060
43369
  if (idx >= 0) mesh.nodes[idx] = node;
43061
43370
  else mesh.nodes.push(node);
43062
43371
  mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
43372
+ for (const entry of mesh.nodes) foldMeshNodeIdentityToCanonical(entry);
43063
43373
  this.inlineMeshCache.set(meshId, mesh);
43064
43374
  this.invalidateAggregateMeshStatus(meshId);
43065
43375
  }
43066
43376
  removeInlineMeshNode(meshId, mesh, nodeId) {
43067
43377
  if (!mesh || !Array.isArray(mesh.nodes)) return false;
43068
- const idx = mesh.nodes.findIndex((entry) => entry?.id === nodeId || entry?.nodeId === nodeId);
43378
+ const idx = mesh.nodes.findIndex((entry) => meshNodeIdMatches(entry, nodeId));
43069
43379
  if (idx === -1) return false;
43070
43380
  mesh.nodes.splice(idx, 1);
43071
43381
  mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -43096,7 +43406,7 @@ var DaemonCommandRouter = class {
43096
43406
  };
43097
43407
  }
43098
43408
  const worktreeExists = fs24.existsSync(workspace);
43099
- const sourceNode = args.node?.clonedFromNodeId ? args.mesh?.nodes?.find((n) => n.id === args.node.clonedFromNodeId || n.nodeId === args.node.clonedFromNodeId) : args.mesh?.nodes?.find((n) => !n.isLocalWorktree);
43409
+ const sourceNode = args.node?.clonedFromNodeId ? args.mesh?.nodes?.find((n) => meshNodeIdMatches(n, args.node.clonedFromNodeId)) : args.mesh?.nodes?.find((n) => !n.isLocalWorktree);
43100
43410
  const repoRoot = typeof sourceNode?.repoRoot === "string" && sourceNode.repoRoot.trim() ? sourceNode.repoRoot.trim() : typeof sourceNode?.workspace === "string" && sourceNode.workspace.trim() ? sourceNode.workspace.trim() : "";
43101
43411
  if (!worktreeExists) {
43102
43412
  return { success: true, skipped: true, removedPath: workspace, repoRoot: repoRoot || void 0, reason: "worktree_path_missing" };
@@ -43739,12 +44049,12 @@ var DaemonCommandRouter = class {
43739
44049
  try {
43740
44050
  const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
43741
44051
  const mesh = meshRecord?.mesh;
43742
- const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
44052
+ const node = mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
43743
44053
  if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh`, refineStages };
43744
44054
  if (!node.isLocalWorktree || !node.workspace) {
43745
44055
  return { success: false, error: `Refinery requires a local worktree node`, refineStages };
43746
44056
  }
43747
- const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
44057
+ const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => meshNodeIdMatches(n, node.clonedFromNodeId)) : mesh?.nodes.find((n) => !n.isLocalWorktree);
43748
44058
  const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
43749
44059
  if (!repoRoot) return { success: false, error: "Source node repoRoot not found", refineStages };
43750
44060
  const { execFile: execFile5 } = await import("child_process");
@@ -44379,7 +44689,7 @@ ${hintLines.join("\n")}` : "",
44379
44689
  const missing = [];
44380
44690
  const nonWorktree = [];
44381
44691
  for (const nodeId of requestedNodeIds) {
44382
- const node = allNodes.find((n) => n.id === nodeId || n.nodeId === nodeId);
44692
+ const node = allNodes.find((n) => meshNodeIdMatches(n, nodeId));
44383
44693
  if (!node) {
44384
44694
  missing.push(nodeId);
44385
44695
  continue;
@@ -44408,7 +44718,7 @@ ${hintLines.join("\n")}` : "",
44408
44718
  const { promisify: promisify8 } = await import("util");
44409
44719
  const execFileAsync4 = promisify8(execFile5);
44410
44720
  const resolveRepoRootFor = (node) => {
44411
- const sourceNode = node.clonedFromNodeId ? allNodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : allNodes.find((n) => !n.isLocalWorktree);
44721
+ const sourceNode = node.clonedFromNodeId ? allNodes.find((n) => meshNodeIdMatches(n, node.clonedFromNodeId)) : allNodes.find((n) => !n.isLocalWorktree);
44412
44722
  return sourceNode?.repoRoot || sourceNode?.workspace;
44413
44723
  };
44414
44724
  const repoRootBaseRef = /* @__PURE__ */ new Map();
@@ -44497,7 +44807,7 @@ ${hintLines.join("\n")}` : "",
44497
44807
  }));
44498
44808
  }
44499
44809
  const ordering = orderMeshRefineBatchNodes(changeAreas);
44500
- const orderedNodes = ordering.order.map((nodeId) => targetNodes.find((n) => n.id === nodeId || n.nodeId === nodeId)).filter((n) => !!n);
44810
+ const orderedNodes = ordering.order.map((nodeId) => targetNodes.find((n) => meshNodeIdMatches(n, nodeId))).filter((n) => !!n);
44501
44811
  const dryRun = args?.dryRun !== false && args?.execute !== true;
44502
44812
  if (dryRun) {
44503
44813
  return {
@@ -44756,7 +45066,7 @@ ${hintLines.join("\n")}` : "",
44756
45066
  const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
44757
45067
  const mesh = meshRecord?.mesh;
44758
45068
  const allNodes = Array.isArray(mesh?.nodes) ? mesh.nodes : [];
44759
- const orderedNodes = nodeIds.map((id) => allNodes.find((n) => n.id === id || n.nodeId === id)).filter((n) => !!n);
45069
+ const orderedNodes = nodeIds.map((id) => allNodes.find((n) => meshNodeIdMatches(n, id))).filter((n) => !!n);
44760
45070
  if (orderedNodes.length === 0) {
44761
45071
  return { success: false, error: "Batch nodes no longer resolvable in mesh", batch: true };
44762
45072
  }
@@ -44862,7 +45172,7 @@ ${hintLines.join("\n")}` : "",
44862
45172
  const terminal = this.terminalRefineJobs.get(key);
44863
45173
  const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
44864
45174
  const mesh = meshRecord?.mesh;
44865
- const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
45175
+ const node = mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
44866
45176
  if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
44867
45177
  if (!node.isLocalWorktree || !node.workspace) return { success: false, error: `Refinery requires a local worktree node` };
44868
45178
  const coordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : this.deps.statusInstanceId || void 0;
@@ -44909,7 +45219,7 @@ ${hintLines.join("\n")}` : "",
44909
45219
  try {
44910
45220
  const { getMesh: getMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
44911
45221
  const meshObj = getMesh2(meshId) ?? this.getCachedInlineMesh(meshId);
44912
- const nodeObj = Array.isArray(meshObj?.nodes) ? meshObj.nodes.find((n) => n.id === meshNodeId || n.nodeId === meshNodeId) : void 0;
45222
+ const nodeObj = Array.isArray(meshObj?.nodes) ? meshObj.nodes.find((n) => meshNodeIdMatches(n, meshNodeId)) : void 0;
44913
45223
  const bootstrapStatus = readStringValue(nodeObj?.worktreeBootstrap?.status);
44914
45224
  if (bootstrapStatus === "running") {
44915
45225
  return { success: true, ...launchResult, bootstrapPending: true };
@@ -44954,7 +45264,7 @@ ${hintLines.join("\n")}` : "",
44954
45264
  try {
44955
45265
  const { getMesh: getMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
44956
45266
  const meshObj = getMesh2(dispatchMeshId) ?? this.getCachedInlineMesh(dispatchMeshId);
44957
- const nodeObj = Array.isArray(meshObj?.nodes) ? meshObj.nodes.find((n) => n.id === dispatchNodeId || n.nodeId === dispatchNodeId) : void 0;
45267
+ const nodeObj = Array.isArray(meshObj?.nodes) ? meshObj.nodes.find((n) => meshNodeIdMatches(n, dispatchNodeId)) : void 0;
44958
45268
  const bootstrapStatus = readStringValue(nodeObj?.worktreeBootstrap?.status);
44959
45269
  if (bootstrapStatus === "running") {
44960
45270
  return {
@@ -46219,7 +46529,7 @@ ${hintLines.join("\n")}` : "",
46219
46529
  const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
46220
46530
  const mesh = meshRecord?.mesh;
46221
46531
  if (!mesh) return { success: false, error: "Mesh not found" };
46222
- const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
46532
+ const node = mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
46223
46533
  if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
46224
46534
  const mode = this.normalizeMeshSessionCleanupMode(args?.mode ?? mesh?.policy?.sessionCleanupOnNodeRemove);
46225
46535
  const sessionIds = Array.isArray(args?.sessionIds) ? args.sessionIds.map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean) : void 0;
@@ -46274,7 +46584,7 @@ ${hintLines.join("\n")}` : "",
46274
46584
  if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
46275
46585
  const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
46276
46586
  const mesh = meshRecord?.mesh;
46277
- const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
46587
+ const node = mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
46278
46588
  if (!node?.workspace) return { success: false, error: `Node '${nodeId}' workspace not found` };
46279
46589
  return {
46280
46590
  success: true,
@@ -46296,7 +46606,7 @@ ${hintLines.join("\n")}` : "",
46296
46606
  if (meshId && nodeId) {
46297
46607
  const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
46298
46608
  const mesh = meshRecord?.mesh;
46299
- const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
46609
+ const node = mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
46300
46610
  if (!workspace) {
46301
46611
  workspace = typeof node?.workspace === "string" ? node.workspace.trim() : "";
46302
46612
  }
@@ -46339,7 +46649,7 @@ ${hintLines.join("\n")}` : "",
46339
46649
  if (isDryRun) {
46340
46650
  const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
46341
46651
  const mesh = meshRecord?.mesh;
46342
- const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
46652
+ const node = mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
46343
46653
  if (!node?.workspace) return { success: false, error: `Node '${nodeId}' workspace not found` };
46344
46654
  return {
46345
46655
  success: true,
@@ -46369,7 +46679,7 @@ ${hintLines.join("\n")}` : "",
46369
46679
  try {
46370
46680
  const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
46371
46681
  const mesh = meshRecord?.mesh;
46372
- const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
46682
+ const node = mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
46373
46683
  if (node && !args?._meshDirectDispatch && node.isLocalWorktree !== true && args?.force !== true) {
46374
46684
  const nodeDaemonId = typeof node.daemonId === "string" ? node.daemonId.trim() : "";
46375
46685
  const nodeMachineId = readMeshNodeMachineId(node) || "";
@@ -46483,7 +46793,7 @@ ${hintLines.join("\n")}` : "",
46483
46793
  const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
46484
46794
  const mesh = meshRecord?.mesh;
46485
46795
  if (!mesh) return { success: false, error: "Mesh not found" };
46486
- const sourceNode = mesh.nodes?.find((n) => n.id === sourceNodeId || n.nodeId === sourceNodeId);
46796
+ const sourceNode = mesh.nodes?.find((n) => meshNodeIdMatches(n, sourceNodeId));
46487
46797
  if (!sourceNode) return { success: false, error: `Source node '${sourceNodeId}' not found in mesh` };
46488
46798
  const sourceDaemonId = typeof sourceNode.daemonId === "string" ? sourceNode.daemonId.trim() : void 0;
46489
46799
  if (sourceDaemonId && sourceDaemonId !== this.deps.statusInstanceId && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
@@ -46503,9 +46813,9 @@ ${hintLines.join("\n")}` : "",
46503
46813
  });
46504
46814
  let node;
46505
46815
  if (meshRecord.inline) {
46506
- const { randomUUID: randomUUID14 } = await import("crypto");
46816
+ const { randomUUID: randomUUID15 } = await import("crypto");
46507
46817
  node = {
46508
- id: `node_${randomUUID14().replace(/-/g, "")}`,
46818
+ id: `node_${randomUUID15().replace(/-/g, "")}`,
46509
46819
  workspace: result.worktreePath,
46510
46820
  repoRoot: result.worktreePath,
46511
46821
  daemonId: sourceNode.daemonId,
@@ -46724,7 +47034,7 @@ ${hintLines.join("\n")}` : "",
46724
47034
  const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
46725
47035
  const mesh = meshRecord?.mesh;
46726
47036
  if (!mesh) return { success: false, error: "Mesh not found" };
46727
- const node = mesh.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
47037
+ const node = mesh.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
46728
47038
  if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
46729
47039
  if (!node.isLocalWorktree) return { success: false, error: "Node is not a local worktree node" };
46730
47040
  const nodeDaemonId = typeof node.daemonId === "string" ? node.daemonId.trim() : void 0;
@@ -46861,14 +47171,14 @@ ${hintLines.join("\n")}` : "",
46861
47171
  const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
46862
47172
  const workspace = readLiveMeshNodeWorkspace({
46863
47173
  meshId,
46864
- nodeId: String(coordinatorNode.id || coordinatorNode.nodeId || preferredCoordinatorNodeId || ""),
47174
+ nodeId: String(normalizeMeshNodeId(coordinatorNode) || preferredCoordinatorNodeId || ""),
46865
47175
  liveSessionRecords: liveMeshSessions,
46866
47176
  allowCoordinatorSession: true
46867
47177
  }) || (typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "");
46868
47178
  if (!workspace) return { success: false, error: "Coordinator node workspace required", meshId, cliType };
46869
47179
  if (!cliType) {
46870
47180
  const resolved = await resolveProviderTypeFromPriority({
46871
- nodeId: String(coordinatorNode.id || coordinatorNode.nodeId || preferredCoordinatorNodeId || "coordinator"),
47181
+ nodeId: String(normalizeMeshNodeId(coordinatorNode) || preferredCoordinatorNodeId || "coordinator"),
46872
47182
  providerPriority: readProviderPriorityFromPolicy(coordinatorNode.policy),
46873
47183
  providerLoader: this.deps.providerLoader,
46874
47184
  onStatusChange: this.deps.onStatusChange
@@ -47279,10 +47589,11 @@ ${ptyResult.output.slice(-2e3)}`);
47279
47589
  if (!mesh) return { success: false, error: "Mesh not found" };
47280
47590
  const meshHost = resolveMeshHostStatus(mesh);
47281
47591
  const refreshRequested = args?.refresh === true || args?.forceRefresh === true;
47592
+ const verboseMissions = args?.verbose === true || args?.compact === false;
47282
47593
  const peekScope = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : this.deps.statusInstanceId || void 0;
47283
47594
  const pendingCoordinatorEventCount = getPendingMeshCoordinatorEvents(meshId, peekScope).length;
47284
47595
  const hadAggregateCache = this.aggregateMeshStatusCache.has(meshId);
47285
- if (!refreshRequested && pendingCoordinatorEventCount === 0) {
47596
+ if (!refreshRequested && !verboseMissions && pendingCoordinatorEventCount === 0) {
47286
47597
  const cachedStatus = this.getCachedAggregateMeshStatus(meshId, mesh, { requireDirectPeerTruth: args?.requireDirectPeerTruth === true });
47287
47598
  if (cachedStatus) {
47288
47599
  logRepoMeshStatusDebug("return_cached", {
@@ -47322,7 +47633,7 @@ ${ptyResult.output.slice(-2e3)}`);
47322
47633
  const passivePeerTruthNotAttempted = requireDirectPeerTruth && !refreshRequested && directTruth.directEvidenceCount > 0 && directTruth.peerAttemptedCount === 0;
47323
47634
  const effectiveDirectTruth = passivePeerTruthNotAttempted ? { ...directTruth, unavailableNodeIds: [] } : directTruth;
47324
47635
  const unavailableDirectTruthNodeIds = new Set(effectiveDirectTruth.unavailableNodeIds);
47325
- const unavailableNodesAreOnlyRemovedWorktrees = unavailableDirectTruthNodeIds.size > 0 && Array.isArray(mesh.nodes) && mesh.nodes.filter((node) => unavailableDirectTruthNodeIds.has(String(node.id || node.nodeId || ""))).every((node) => node?.isLocalWorktree === true);
47636
+ const unavailableNodesAreOnlyRemovedWorktrees = unavailableDirectTruthNodeIds.size > 0 && Array.isArray(mesh.nodes) && mesh.nodes.filter((node) => unavailableDirectTruthNodeIds.has(normalizeMeshNodeId(node) ?? "")).every((node) => node?.isLocalWorktree === true);
47326
47637
  const directTruthSatisfied = !requireDirectPeerTruth || effectiveDirectTruth.directEvidenceCount > 0 && (effectiveDirectTruth.unavailableNodeIds.length === 0 || unavailableNodesAreOnlyRemovedWorktrees);
47327
47638
  if (requireDirectPeerTruth && !directTruthSatisfied) {
47328
47639
  const failureResult = {
@@ -47357,14 +47668,13 @@ ${ptyResult.output.slice(-2e3)}`);
47357
47668
  const coordinatorHostname = (0, import_os3.hostname)();
47358
47669
  const selectedCoordinatorNodeId = readStringValue(
47359
47670
  mesh.coordinator?.preferredNodeId,
47360
- mesh.nodes?.[0]?.id,
47361
- mesh.nodes?.[0]?.nodeId
47671
+ normalizeMeshNodeId(mesh.nodes?.[0])
47362
47672
  );
47363
47673
  const inlineCoordinatorNodeId = meshRecord?.inline && Array.isArray(mesh.nodes) ? selectedCoordinatorNodeId : void 0;
47364
47674
  const refreshedAt = (/* @__PURE__ */ new Date()).toISOString();
47365
47675
  const nodeStatuses = [];
47366
47676
  for (const [nodeIndex, node] of (mesh.nodes || []).entries()) {
47367
- const nodeId = String(node.id || node.nodeId || "");
47677
+ const nodeId = normalizeMeshNodeId(node) ?? "";
47368
47678
  const daemonId = readStringValue(node.daemonId);
47369
47679
  const nodeMachineId = readMeshNodeMachineId(node);
47370
47680
  const nodeHostname = readMeshNodeHostname(node);
@@ -47586,7 +47896,7 @@ ${ptyResult.output.slice(-2e3)}`);
47586
47896
  liveSessionRecords: liveMeshSessions
47587
47897
  });
47588
47898
  const { getMeshStatusMissionSummaries: getMeshStatusMissionSummaries2 } = await Promise.resolve().then(() => (init_mesh_missions(), mesh_missions_exports));
47589
- const missions = getMeshStatusMissionSummaries2(meshId);
47899
+ const missions = getMeshStatusMissionSummaries2(meshId, { verbose: verboseMissions });
47590
47900
  const statusResult = {
47591
47901
  success: true,
47592
47902
  meshId: mesh.id,
@@ -47640,7 +47950,7 @@ ${ptyResult.output.slice(-2e3)}`);
47640
47950
  }))
47641
47951
  };
47642
47952
  const { pendingCoordinatorEvents: _pendingCoordinatorEvents, unroutableDeliveries: _unroutableDeliveries, ...cacheableStatusResult } = statusResult;
47643
- const rememberedStatus = this.rememberAggregateMeshStatus(meshId, cacheableStatusResult, refreshReason);
47953
+ const rememberedStatus = verboseMissions ? cacheableStatusResult : this.rememberAggregateMeshStatus(meshId, cacheableStatusResult, refreshReason);
47644
47954
  const returnedStatus = {
47645
47955
  ...rememberedStatus,
47646
47956
  ...pendingCoordinatorEvents.length > 0 ? { pendingCoordinatorEvents } : {},
@@ -55194,7 +55504,7 @@ var SessionHostPtyTransportFactory = class {
55194
55504
  };
55195
55505
 
55196
55506
  // src/cli-adapters/raw-terminal-io.ts
55197
- var import_crypto9 = require("crypto");
55507
+ var import_crypto10 = require("crypto");
55198
55508
  var import_session_host_core10 = require("@adhdev/session-host-core");
55199
55509
  var BASE_KEY_SEQUENCES = {
55200
55510
  enter: "\r",
@@ -55292,7 +55602,7 @@ var RawTerminalAttachment = class _RawTerminalAttachment {
55292
55602
  const sessionId = String(options.sessionId || "").trim();
55293
55603
  if (!sessionId) throw new Error("sessionId is required");
55294
55604
  const mode = options.mode || "read";
55295
- const clientId = options.clientId || `raw-terminal-${process.pid}-${(0, import_crypto9.randomUUID)().slice(0, 8)}`;
55605
+ const clientId = options.clientId || `raw-terminal-${process.pid}-${(0, import_crypto10.randomUUID)().slice(0, 8)}`;
55296
55606
  const client = options.client || new import_session_host_core10.SessionHostClient({ endpoint: options.endpoint });
55297
55607
  await client.connect();
55298
55608
  const attachResponse = await client.request({