@adhdev/daemon-standalone 0.9.82-rc.77 → 0.9.82-rc.78

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
@@ -23254,25 +23254,42 @@ ${userInstruction}`);
23254
23254
  return sections.join("\n\n");
23255
23255
  }
23256
23256
  function buildNodeStatusSection(nodes) {
23257
- const lines = ["## Current Node Status", ""];
23257
+ const lines = [
23258
+ "## Current Node Status",
23259
+ "",
23260
+ "Node labels are display context, not aliases. Use exact `nodeId` values in mesh tool calls; do not invent shorthand names such as M1/M2 unless they are explicitly configured labels.",
23261
+ ""
23262
+ ];
23258
23263
  for (const n of nodes) {
23259
23264
  const healthIcon = n.health === "online" ? "\u{1F7E2}" : n.health === "dirty" ? "\u{1F7E1}" : n.health === "offline" ? "\u26AB" : "\u{1F534}";
23260
23265
  const sessions = n.activeSessions.length > 0 ? `sessions: ${n.activeSessions.join(", ")}` : "no active sessions";
23261
23266
  const branch = n.git?.branch ? `branch: \`${n.git.branch}\`` : "";
23262
- lines.push(`- ${healthIcon} **${n.machineLabel}** (${n.nodeId})`);
23263
- lines.push(` workspace: \`${n.workspace}\` | ${branch} | ${sessions}`);
23267
+ const context = [
23268
+ n.daemonId ? `daemon: \`${n.daemonId}\`` : "",
23269
+ n.providers?.length ? `providers: ${n.providers.join(", ")}` : ""
23270
+ ].filter(Boolean).join(" | ");
23271
+ lines.push(`- ${healthIcon} **${n.machineLabel}** (nodeId: \`${n.nodeId}\`)`);
23272
+ lines.push(` workspace: \`${n.workspace}\`${context ? ` | ${context}` : ""} | ${branch} | ${sessions}`);
23264
23273
  if (n.error) lines.push(` \u26A0\uFE0F ${n.error}`);
23265
23274
  }
23266
23275
  return lines.join("\n");
23267
23276
  }
23268
23277
  function buildNodeConfigSection(mesh) {
23269
- const lines = ["## Configured Nodes", ""];
23278
+ const lines = [
23279
+ "## Configured Nodes",
23280
+ "",
23281
+ "Node labels are display context, not aliases. Use exact `nodeId` values in mesh tool calls; do not invent shorthand names such as M1/M2 unless they are explicitly configured labels.",
23282
+ ""
23283
+ ];
23270
23284
  for (const n of mesh.nodes) {
23271
23285
  const labels = [];
23272
23286
  if (n.isLocalWorktree) labels.push("worktree");
23273
23287
  if (n.policy?.readOnly) labels.push("read-only");
23274
23288
  const suffix = labels.length ? ` [${labels.join(", ")}]` : "";
23275
- lines.push(`- **${n.workspace}** (${n.id})${suffix}`);
23289
+ const explicitMachineLabel = typeof n.machineLabel === "string" ? n.machineLabel : "";
23290
+ const explicitLabel = explicitMachineLabel ? ` label: **${explicitMachineLabel}** |` : "";
23291
+ const providerPriority = n.policy?.providerPriority?.length ? ` | providers: ${n.policy.providerPriority.join(", ")}` : "";
23292
+ lines.push(`- ${explicitLabel} nodeId: \`${n.id}\` | workspace: \`${n.workspace}\`${n.daemonId ? ` | daemon: \`${n.daemonId}\`` : ""}${providerPriority}${suffix}`);
23276
23293
  }
23277
23294
  lines.push("", "_Use `mesh_status` to probe live health before delegating work._");
23278
23295
  return lines.join("\n");
@@ -23313,7 +23330,7 @@ ${rules.join("\n")}`;
23313
23330
  - **Clean up worktree nodes.** After a worktree task completes and its changes are merged or checkpointed, call \`mesh_remove_node\` to free resources.
23314
23331
  - **Do not strand completed branches.** A checkpointed or clean feature/worktree branch is not done by itself. Merge/refine it to the mesh default branch, fast-forward obvious clean behind-only branches with \`mesh_fast_forward_node\`, or explicitly report one of \`pushed_feature_branch_needs_merge\`, \`blocked_review\`, \`cleanup_candidate\`, or \`not_mergeable\` with the next action.
23315
23332
  - **Keep Refinery validation project-configurable.** \`mesh_refine_node\` must execute validation from repo mesh/refine config (for example \`.adhdev/refine.{json,yaml,yml}\`, \`.adhdev/repo-mesh-refine.*\`, or \`repo-mesh.refine.*\`). Heuristics are suggestions/scaffolding only, not the execution path.
23316
- - **Treat submodule reachability as publish-needed.** A \`submodule_reachability_failed\` refine result means the root gitlink points at a submodule commit that is not reachable from the configured submodule remote. Do not retry validation blindly or start code review first. Classify it as \`blocked_review\`, request user approval to push/publish the submodule commit, then rerun \`mesh_refine_node\`.
23333
+ - **Treat submodule main reachability as publish-needed.** A \`submodule_reachability_failed\` refine result means the root gitlink points at a submodule commit that is not reachable from the configured submodule remote main branch. Do not treat feature-branch reachability as complete, retry validation blindly, or start code review first. Classify it as \`blocked_review\`, request user approval to push/publish the submodule commit to submodule main, then rerun \`mesh_refine_node\`.
23317
23334
  - **Name worktree branches meaningfully.** Use descriptive names like \`feat/auth-refactor\` or \`fix/build-123\`.${coordinatorNote}`;
23318
23335
  }
23319
23336
  var TOOLS_SECTION;
@@ -23362,7 +23379,7 @@ Before doing any coordinator work, confirm that the actual callable tool list in
23362
23379
  4. **Monitor** \u2014 Prefer event-driven completion/status notifications. Do **not** poll \`mesh_read_chat\` repeatedly. Use \`mesh_view_queue\` to see the status of all pending, assigned, completed, and failed tasks. Do not call \`mesh_read_chat\` again within a few seconds for the same generating session. Use at most one compact \`mesh_read_chat\` check after a completion/approval signal. Handle approvals via \`mesh_approve\`.
23363
23380
  5. **Verify** \u2014 When a task reports completion or git work is visible, call \`mesh_git_status\` to verify changes were made.
23364
23381
  6. **Checkpoint** \u2014 Call \`mesh_checkpoint\` to save the work.
23365
- 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 its configured remote. If \`mesh_refine_node\` returns \`submodule_reachability_failed\` or publish-required evidence, keep the public convergence bucket as \`blocked_review\`, ask the user for explicit approval to push/publish the unreachable submodule commit(s), then rerun \`mesh_refine_node\`; do not merge the root branch until the submodule commit(s) are reachable. 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.
23382
+ 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\`, 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.
23366
23383
  8. **Clean up** \u2014 Remove worktree nodes via \`mesh_remove_node\` after their work is merged or no longer needed.
23367
23384
  9. **Report** \u2014 Summarize what was done, what changed, any issues, and the branch convergence state.
23368
23385
 
@@ -25216,8 +25233,20 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
25216
25233
  const result = readRecord(args.metadataEvent.result);
25217
25234
  const code = readNonEmptyString2(result?.code);
25218
25235
  const error48 = readNonEmptyString2(result?.error);
25219
- const details = [jobId ? `job_id=${jobId}` : "", code ? `code=${code}` : ""].filter(Boolean).join("; ");
25220
- return `[System] Refinery async job for ${args.nodeLabel} failed${details ? ` (${details})` : ""}${error48 ? `: ${error48}` : "."} Review the terminal refine event/ledger before retrying.`;
25236
+ const convergenceStatus = readNonEmptyString2(result?.convergenceStatus);
25237
+ const blockedReason = readNonEmptyString2(result?.blockedReason);
25238
+ const nextStep = readNonEmptyString2(result?.nextStep) || readNonEmptyString2(readRecord(result?.finalBranchConvergenceState)?.nextStep);
25239
+ const details = [
25240
+ jobId ? `job_id=${jobId}` : "",
25241
+ code ? `code=${code}` : "",
25242
+ convergenceStatus ? `convergence=${convergenceStatus}` : "",
25243
+ blockedReason ? `reason=${blockedReason}` : ""
25244
+ ].filter(Boolean).join("; ");
25245
+ const parts = [
25246
+ `[System] Refinery async job for ${args.nodeLabel} failed${details ? ` (${details})` : ""}${error48 ? `: ${error48}` : "."}`,
25247
+ nextStep ? `Next step: ${nextStep}` : "Review the terminal refine event/ledger before retrying."
25248
+ ];
25249
+ return parts.join("\n");
25221
25250
  }
25222
25251
  return "";
25223
25252
  }
@@ -25339,7 +25368,8 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
25339
25368
  remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
25340
25369
  }
25341
25370
  if (sessionId) {
25342
- updateSessionTaskStatus(args.meshId, sessionId, "failed");
25371
+ const failedTask = updateSessionTaskStatus(args.meshId, sessionId, "failed");
25372
+ completedTaskForLedger = failedTask ? { id: failedTask.id } : null;
25343
25373
  }
25344
25374
  }
25345
25375
  const ledgerKind = EVENT_TO_LEDGER_KIND[args.event];
@@ -31389,9 +31419,11 @@ ${lastSnapshot}`;
31389
31419
  return Number.isFinite(started) ? Math.max(0, now - started) : 0;
31390
31420
  }
31391
31421
  function sessionStatusFromNodes(nodes, nodeId, sessionId) {
31392
- if (!nodeId || !sessionId || !Array.isArray(nodes)) return void 0;
31422
+ if (!Array.isArray(nodes)) return {};
31423
+ if (!nodeId) return { staleReason: "direct task has no node id" };
31393
31424
  const node = nodes.find((item) => readString2(item?.id) === nodeId || readString2(item?.nodeId) === nodeId || readString2(item?.node_id) === nodeId);
31394
- if (!node) return void 0;
31425
+ if (!node) return { staleReason: "direct task node is no longer in the live mesh" };
31426
+ if (!sessionId) return {};
31395
31427
  const candidates = [];
31396
31428
  for (const value of [node.sessions, node.activeSessions, node.active_sessions, node.lastProbe?.sessions, node.last_probe?.sessions, node.lastProbe?.status?.sessions, node.last_probe?.status?.sessions]) {
31397
31429
  if (Array.isArray(value)) candidates.push(...value);
@@ -31400,16 +31432,18 @@ ${lastSnapshot}`;
31400
31432
  if (value && typeof value === "object") candidates.push(value);
31401
31433
  }
31402
31434
  const session = candidates.find((item) => {
31435
+ if (typeof item === "string") return item === sessionId;
31403
31436
  const id = readString2(item?.id) || readString2(item?.sessionId) || readString2(item?.session_id) || readString2(item?.runtimeSessionId) || readString2(item?.instanceId);
31404
31437
  return id === sessionId;
31405
31438
  });
31406
- if (!session) return void 0;
31439
+ if (!session) return { staleReason: "direct task session is not present in live session records" };
31440
+ if (typeof session === "string") return {};
31407
31441
  const raw = `${readString2(session.status) || ""} ${readString2(session.lifecycle) || ""} ${readString2(session.state) || ""} ${readString2(session.activeChat?.status) || ""}`.toLowerCase();
31408
- if (raw.includes("approval")) return "awaiting_approval";
31409
- if (raw.includes("generating") || raw.includes("running") || raw.includes("busy")) return "generating";
31410
- if (raw.includes("failed") || raw.includes("stopped") || raw.includes("terminated") || raw.includes("exited")) return "failed";
31411
- if (raw.includes("idle") || raw.includes("waiting_input") || raw.includes("ready")) return "idle";
31412
- return void 0;
31442
+ if (raw.includes("approval")) return { status: "awaiting_approval" };
31443
+ if (raw.includes("generating") || raw.includes("running") || raw.includes("busy")) return { status: "generating" };
31444
+ if (raw.includes("failed") || raw.includes("stopped") || raw.includes("terminated") || raw.includes("exited")) return { status: "failed" };
31445
+ if (raw.includes("idle") || raw.includes("waiting_input") || raw.includes("ready")) return { status: "idle" };
31446
+ return {};
31413
31447
  }
31414
31448
  function isDirectDispatch(entry) {
31415
31449
  if (entry.kind !== "task_dispatched") return false;
@@ -31456,15 +31490,17 @@ ${lastSnapshot}`;
31456
31490
  failedCount: statusCounts.failed,
31457
31491
  idleCount: statusCounts.idle,
31458
31492
  sourceCounts,
31459
- statusCounts
31493
+ statusCounts,
31494
+ staleDirectCount: activeWork.filter((item) => item.source === "direct" && item.staleReason).length
31460
31495
  };
31461
31496
  }
31462
31497
  function buildMeshActiveWork(opts) {
31463
31498
  const now = opts.now ?? Date.now();
31464
31499
  const records = [];
31500
+ const staleDirectWork = [];
31465
31501
  for (const task of opts.queue || []) {
31466
31502
  if (task.status !== "pending" && task.status !== "assigned") continue;
31467
- const { title, summary } = summarizeMessage(task.message || "");
31503
+ const { title, summary: summary2 } = summarizeMessage(task.message || "");
31468
31504
  records.push({
31469
31505
  taskId: task.id,
31470
31506
  source: "queue",
@@ -31472,7 +31508,7 @@ ${lastSnapshot}`;
31472
31508
  nodeId: task.assignedNodeId || task.targetNodeId,
31473
31509
  sessionId: task.assignedSessionId || task.targetSessionId,
31474
31510
  taskTitle: title,
31475
- taskSummary: summary,
31511
+ taskSummary: summary2,
31476
31512
  message: task.message,
31477
31513
  taskMode: task.taskMode,
31478
31514
  createdAt: task.createdAt,
@@ -31487,13 +31523,13 @@ ${lastSnapshot}`;
31487
31523
  const taskId = directDispatchTaskId(dispatch);
31488
31524
  const terminal = terminals.filter((entry) => new Date(entry.timestamp).getTime() >= new Date(dispatch.timestamp).getTime()).find((entry) => terminalMatchesDispatch(entry, dispatch, taskId));
31489
31525
  const terminalStatus = terminal ? statusFromTerminal(terminal) : void 0;
31490
- const liveStatus = sessionStatusFromNodes(opts.nodes, dispatch.nodeId, dispatch.sessionId);
31491
- const status = terminalStatus || liveStatus || "assigned";
31526
+ const live = sessionStatusFromNodes(opts.nodes, dispatch.nodeId, dispatch.sessionId);
31527
+ const status = terminalStatus || live.status || "assigned";
31492
31528
  const terminalRow = Boolean(terminal && terminal.kind !== "task_approval_needed");
31493
31529
  if (terminalRow && opts.includeTerminalDirect !== true) continue;
31494
31530
  const message = readString2(dispatch.payload?.message) || readString2(dispatch.payload?.summary) || "";
31495
- const { title, summary } = summarizeMessage(message);
31496
- records.push({
31531
+ const { title, summary: summary2 } = summarizeMessage(message);
31532
+ const record2 = {
31497
31533
  taskId,
31498
31534
  source: "direct",
31499
31535
  status,
@@ -31501,7 +31537,7 @@ ${lastSnapshot}`;
31501
31537
  sessionId: dispatch.sessionId,
31502
31538
  providerType: dispatch.providerType || readString2(dispatch.payload?.providerType),
31503
31539
  taskTitle: readString2(dispatch.payload?.taskTitle) || title,
31504
- taskSummary: readString2(dispatch.payload?.taskSummary) || summary,
31540
+ taskSummary: readString2(dispatch.payload?.taskSummary) || summary2,
31505
31541
  message,
31506
31542
  taskMode: readString2(dispatch.payload?.taskMode),
31507
31543
  createdAt: dispatch.timestamp,
@@ -31510,11 +31546,20 @@ ${lastSnapshot}`;
31510
31546
  elapsedMs: elapsedSince(dispatch.timestamp, now),
31511
31547
  terminal: terminalRow,
31512
31548
  terminalKind: terminal?.kind,
31513
- terminalAt: terminal?.timestamp
31514
- });
31549
+ terminalAt: terminal?.timestamp,
31550
+ staleReason: live.staleReason
31551
+ };
31552
+ if (live.staleReason && !terminalRow) {
31553
+ staleDirectWork.push(record2);
31554
+ continue;
31555
+ }
31556
+ records.push(record2);
31515
31557
  }
31516
31558
  records.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
31517
- return { activeWork: records, summary: buildMeshActiveWorkSummary(records) };
31559
+ staleDirectWork.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
31560
+ const summary = buildMeshActiveWorkSummary(records);
31561
+ summary.staleDirectCount = staleDirectWork.length;
31562
+ return { activeWork: records, staleDirectWork, summary };
31518
31563
  }
31519
31564
  init_mesh_host_ownership();
31520
31565
  init_mesh_events();
@@ -41699,23 +41744,28 @@ ${effect.notification.body || ""}`.trim();
41699
41744
  if (hasNonEmptyCliModalButtons(parsedStatus?.activeModal ?? parsedStatus?.modal)) return false;
41700
41745
  return !this.hasAdapterPendingResponse();
41701
41746
  }
41702
- getCompletedFinalizationBlockReason(latestVisibleStatus) {
41703
- if (latestVisibleStatus !== "idle") return `status:${latestVisibleStatus}`;
41747
+ getCompletedFinalizationBlock(latestVisibleStatus) {
41748
+ if (latestVisibleStatus !== "idle") return { reason: `status:${latestVisibleStatus}`, terminal: true };
41704
41749
  const adapterAny = this.adapter;
41705
- if (adapterAny?.isWaitingForResponse === true) return "adapter_waiting_for_response";
41706
- if (adapterAny?.currentTurnScope) return "adapter_turn_scope_active";
41750
+ if (adapterAny?.isWaitingForResponse === true) return { reason: "adapter_waiting_for_response", terminal: true };
41751
+ if (adapterAny?.currentTurnScope) return { reason: "adapter_turn_scope_active", terminal: true };
41752
+ if (this.hasAdapterPendingResponse()) return { reason: "adapter_pending_response", terminal: true };
41707
41753
  const partial2 = typeof this.adapter.getPartialResponse === "function" ? this.adapter.getPartialResponse() : "";
41708
- if (typeof partial2 === "string" && partial2.trim()) return "partial_response_pending";
41754
+ if (typeof partial2 === "string" && partial2.trim()) return { reason: "partial_response_pending", terminal: true };
41709
41755
  let parsed;
41710
41756
  try {
41711
41757
  parsed = this.adapter.getScriptParsedStatus();
41712
41758
  } catch (error48) {
41713
- return `parse_error:${error48?.message || String(error48)}`;
41759
+ return { reason: `parse_error:${error48?.message || String(error48)}` };
41714
41760
  }
41715
41761
  const parsedStatus = typeof parsed?.status === "string" ? parsed.status : "unknown";
41716
- if (parsedStatus !== "idle") return `parsed_status:${parsedStatus}`;
41717
- if (parsed?.activeModal || parsed?.modal) return "parsed_modal_active";
41718
- if (!this.completionHasFinalAssistantMessage(parsed?.messages)) return "missing_final_assistant";
41762
+ if (parsedStatus !== "idle") {
41763
+ const adapterStatus = this.adapter.getStatus({ allowParse: false });
41764
+ if (this.shouldSuppressStaleParsedBusyStatus(parsed, adapterStatus)) return null;
41765
+ return { reason: `parsed_status:${parsedStatus}`, terminal: isCliGeneratingLikeStatus(parsedStatus) };
41766
+ }
41767
+ if (parsed?.activeModal || parsed?.modal) return { reason: "parsed_modal_active", terminal: true };
41768
+ if (!this.completionHasFinalAssistantMessage(parsed?.messages)) return { reason: "missing_final_assistant" };
41719
41769
  return null;
41720
41770
  }
41721
41771
  scheduleCompletedDebounceFlush(delayMs) {
@@ -41737,10 +41787,11 @@ ${effect.notification.body || ""}`.trim();
41737
41787
  this.completedDebounceTimer = null;
41738
41788
  return;
41739
41789
  }
41740
- const blockReason = this.getCompletedFinalizationBlockReason(latestVisibleStatus);
41741
- if (blockReason) {
41790
+ const block2 = this.getCompletedFinalizationBlock(latestVisibleStatus);
41791
+ if (block2) {
41792
+ const blockReason = block2.reason;
41742
41793
  const waitedMs = Date.now() - pending.firstObservedAt;
41743
- if (waitedMs < COMPLETED_FINALIZATION_MAX_WAIT_MS) {
41794
+ if (block2.terminal || waitedMs < COMPLETED_FINALIZATION_MAX_WAIT_MS) {
41744
41795
  if (pending.loggedBlockReason !== blockReason) {
41745
41796
  LOG2.info("CLI", `[${this.type}] waiting to emit completed until transcript finalizes (${blockReason})`);
41746
41797
  pending.loggedBlockReason = blockReason;
@@ -43596,6 +43647,47 @@ ${rawInput}` : rawInput;
43596
43647
  function normalizeAgentStatus(value) {
43597
43648
  return typeof value === "string" ? value.trim().toLowerCase() : "";
43598
43649
  }
43650
+ function hasNonEmptyModalButtons2(activeModal) {
43651
+ const buttons = activeModal?.buttons;
43652
+ return Array.isArray(buttons) && buttons.some((button) => String(button || "").trim().length > 0);
43653
+ }
43654
+ function hasAdapterPendingResponse(adapter) {
43655
+ if (adapter?.isWaitingForResponse === true) return true;
43656
+ if (adapter?.currentTurnScope) return true;
43657
+ try {
43658
+ if (typeof adapter?.isProcessing === "function" && adapter.isProcessing()) return true;
43659
+ } catch {
43660
+ }
43661
+ try {
43662
+ const partial2 = typeof adapter?.getPartialResponse === "function" ? adapter.getPartialResponse() : "";
43663
+ if (typeof partial2 === "string" && partial2.trim()) return true;
43664
+ } catch {
43665
+ }
43666
+ return false;
43667
+ }
43668
+ function shouldSuppressStaleParsedBusyStatus(adapterStatus, parsedStatus, adapter) {
43669
+ const parsedRawStatus = normalizeAgentStatus(parsedStatus?.status);
43670
+ if (!BUSY_AGENT_STATUSES.has(parsedRawStatus)) return false;
43671
+ if (adapterStatus !== "idle") return false;
43672
+ if (hasNonEmptyModalButtons2(parsedStatus?.activeModal ?? parsedStatus?.modal)) return false;
43673
+ return !hasAdapterPendingResponse(adapter);
43674
+ }
43675
+ function getEffectiveAgentSendStatus(adapter) {
43676
+ const adapterStatus = normalizeAgentStatus(adapter?.getStatus?.({ allowParse: false })?.status ?? adapter?.getStatus?.()?.status);
43677
+ if (adapterStatus && adapterStatus !== "idle") return adapterStatus;
43678
+ if (adapterStatus !== "idle") return adapterStatus;
43679
+ if (typeof adapter?.getScriptParsedStatus !== "function") return adapterStatus;
43680
+ try {
43681
+ const parsedStatus = adapter.getScriptParsedStatus();
43682
+ const parsedRawStatus = normalizeAgentStatus(parsedStatus?.status);
43683
+ if (BUSY_AGENT_STATUSES.has(parsedRawStatus) && !shouldSuppressStaleParsedBusyStatus(adapterStatus, parsedStatus, adapter)) {
43684
+ return parsedRawStatus;
43685
+ }
43686
+ } catch {
43687
+ return adapterStatus;
43688
+ }
43689
+ return adapterStatus;
43690
+ }
43599
43691
  var chalkModule = import_chalk.default;
43600
43692
  var chalkApi = typeof chalkModule.yellow === "function" ? chalkModule : chalkModule.default || null;
43601
43693
  function colorize(color, text) {
@@ -44370,7 +44462,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
44370
44462
  if (!found) throw new Error(`CLI agent not running: ${agentType}`);
44371
44463
  const { adapter, key } = found;
44372
44464
  if (action === "send_chat") {
44373
- const currentStatus = normalizeAgentStatus(adapter.getStatus?.()?.status);
44465
+ const currentStatus = getEffectiveAgentSendStatus(adapter);
44374
44466
  if (BUSY_AGENT_STATUSES.has(currentStatus)) {
44375
44467
  return {
44376
44468
  success: false,
@@ -47831,6 +47923,17 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
47831
47923
  }).filter((entry) => entry !== null);
47832
47924
  return submodules.length > 0 ? submodules : void 0;
47833
47925
  }
47926
+ function buildMeshNodeDisplayLabel(node, nodeId, providerPriority) {
47927
+ const explicit = readStringValue(node.machineLabel, node.machine_label, node.machineNickname, node.machine_nickname, node.alias);
47928
+ if (explicit) return explicit;
47929
+ const workspace = readStringValue(node.workspace, node.repoRoot, node.repo_root);
47930
+ const workspaceName = workspace ? (0, import_path8.basename)(workspace) : void 0;
47931
+ const host = readStringValue(node.hostname, node.host, node.daemonId, node.daemon_id, node.machineId, node.machine_id);
47932
+ const provider = providerPriority[0] || (Array.isArray(node.providers) ? readStringValue(...node.providers) : void 0);
47933
+ const parts = [workspaceName, host, provider].filter(Boolean);
47934
+ if (parts.length > 0) return parts.join(" \xB7 ");
47935
+ return nodeId || "unidentified mesh node";
47936
+ }
47834
47937
  function normalizeInlineMeshGitStatus(status, node, options) {
47835
47938
  const isGitRepo = readBooleanValue(status.isGitRepo);
47836
47939
  if (!Object.keys(status).length || isGitRepo === void 0) return void 0;
@@ -48501,7 +48604,7 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
48501
48604
  }
48502
48605
  function buildSubmodulePublishRequiredNextStep(entries) {
48503
48606
  const refs = entries.map((entry) => `${entry.path}@${entry.commit}`).join(", ");
48504
- return `Ask the user for explicit approval to push/publish the unreachable submodule commit(s) (${refs}) to their configured submodule remote(s), then rerun mesh_refine_node. Do not merge the root branch until every submodule gitlink commit is reachable from its configured remote.`;
48607
+ return `Ask the user for explicit approval to push/publish the unreachable submodule commit(s) (${refs}) to the configured submodule remote main branch, then rerun mesh_refine_node. Do not merge the root branch until every submodule gitlink commit is reachable from submodule origin/main.`;
48505
48608
  }
48506
48609
  async function computeGitPatchId(cwd, fromRef, toRef) {
48507
48610
  const { execFileSync: execFileSync3 } = await import("child_process");
@@ -48588,12 +48691,13 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
48588
48691
  });
48589
48692
  return String(stdout || "");
48590
48693
  };
48591
- const verifyRemoteCommitReachable = async (remoteUrl, commit) => {
48694
+ const verifyRemoteMainContainsCommit = async (remoteUrl, commit, branch = "main") => {
48592
48695
  const probeDir = fs11.mkdtempSync((0, import_path8.join)((0, import_os3.tmpdir)(), "adhdev-submodule-reachability-"));
48593
48696
  try {
48594
48697
  await runGit2(probeDir, ["init", "-q"]);
48595
- await runGit2(probeDir, ["-c", "protocol.file.allow=always", "fetch", "--depth=1", remoteUrl, commit]);
48698
+ await runGit2(probeDir, ["-c", "protocol.file.allow=always", "fetch", "--depth=1", remoteUrl, `refs/heads/${branch}:refs/remotes/origin/${branch}`]);
48596
48699
  await runGit2(probeDir, ["cat-file", "-e", `${commit}^{commit}`]);
48700
+ await runGit2(probeDir, ["merge-base", "--is-ancestor", commit, `refs/remotes/origin/${branch}`]);
48597
48701
  } finally {
48598
48702
  fs11.rmSync(probeDir, { recursive: true, force: true });
48599
48703
  }
@@ -48637,15 +48741,18 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
48637
48741
  entries.push(entry);
48638
48742
  continue;
48639
48743
  }
48640
- await verifyRemoteCommitReachable(remoteUrl, gitlink.commit);
48744
+ entry.remoteMainBranch = "main";
48745
+ await verifyRemoteMainContainsCommit(remoteUrl, gitlink.commit, "main");
48641
48746
  entry.fetchedFromOrigin = true;
48642
48747
  entry.remoteReachable = true;
48748
+ entry.remoteMainReachable = true;
48643
48749
  entry.reachable = true;
48644
48750
  } catch (e) {
48645
48751
  entry.remoteReachable = false;
48752
+ entry.remoteMainReachable = false;
48646
48753
  entry.publishRequired = true;
48647
48754
  const details = truncateValidationOutput(e?.stderr || e?.message || String(e));
48648
- entry.error = `Submodule remote reachability check failed for origin: ${details}`;
48755
+ entry.error = `Submodule remote main reachability check failed for origin/main: ${details}`;
48649
48756
  }
48650
48757
  } catch (e) {
48651
48758
  entry.error = truncateValidationOutput(e?.message || String(e));
@@ -49793,6 +49900,8 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
49793
49900
  remote: entry.remote,
49794
49901
  remoteUrl: entry.remoteUrl,
49795
49902
  remoteReachable: entry.remoteReachable,
49903
+ remoteMainBranch: entry.remoteMainBranch,
49904
+ remoteMainReachable: entry.remoteMainReachable,
49796
49905
  error: entry.error
49797
49906
  })),
49798
49907
  error: submoduleReachability.error
@@ -49805,13 +49914,13 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
49805
49914
  convergenceStatus: "blocked_review",
49806
49915
  publishRequired: true,
49807
49916
  blockedReason: "submodule_publish_required",
49808
- error: "Refinery submodule reachability preflight failed because one or more submodule gitlink commits are not reachable from their configured remote; merge/refine cleanup was not attempted.",
49917
+ error: "Refinery submodule reachability preflight failed because one or more submodule gitlink commits are not reachable from their configured remote main branch; merge/refine cleanup was not attempted.",
49809
49918
  nextStep,
49810
49919
  nextSteps: [
49811
49920
  "Ask the user for explicit approval before pushing or publishing any submodule commit.",
49812
- "Push/publish each unreachable submodule commit to the configured submodule remote shown in the evidence.",
49921
+ "Push/publish each unreachable submodule commit to the configured submodule remote main branch shown in the evidence.",
49813
49922
  "Rerun mesh_refine_node after remote reachability is confirmed.",
49814
- "Do not merge the root branch until every submodule gitlink commit is reachable from its configured remote."
49923
+ "Do not merge the root branch until every submodule gitlink commit is reachable from submodule origin/main."
49815
49924
  ],
49816
49925
  unreachableSubmoduleCommits: submoduleReachability.unreachable.map((entry) => ({
49817
49926
  path: entry.path,
@@ -49819,6 +49928,8 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
49819
49928
  remote: entry.remote,
49820
49929
  remoteUrl: entry.remoteUrl,
49821
49930
  remoteReachable: entry.remoteReachable,
49931
+ remoteMainBranch: entry.remoteMainBranch,
49932
+ remoteMainReachable: entry.remoteMainReachable,
49822
49933
  error: entry.error
49823
49934
  })),
49824
49935
  branch,
@@ -51693,7 +51804,8 @@ ${block2}`);
51693
51804
  ) || Boolean(meshRecord?.inline && nodeIndex === 0);
51694
51805
  const status = {
51695
51806
  nodeId,
51696
- machineLabel: node.machineLabel || node.id || node.nodeId,
51807
+ machineLabel: buildMeshNodeDisplayLabel(node, nodeId, providerPriority),
51808
+ labelSource: readStringValue(node.machineLabel, node.machine_label, node.machineNickname, node.machine_nickname, node.alias) ? "explicit_metadata" : "workspace_host_provider_context",
51697
51809
  workspace: node.workspace,
51698
51810
  repoRoot: node.repoRoot,
51699
51811
  isLocalWorktree: node.isLocalWorktree,