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

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
 
@@ -25201,23 +25218,54 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
25201
25218
  const jobId = readRefineJobId({ metadataEvent: args.metadataEvent });
25202
25219
  const result = readRecord(args.metadataEvent.result);
25203
25220
  const validationSummary = readRecord(result?.validationSummary);
25221
+ const patchEquivalence = readRecord(result?.patchEquivalence);
25222
+ const finalConvergence = readRecord(result?.finalBranchConvergenceState);
25204
25223
  const validationStatus = readNonEmptyString2(validationSummary?.status);
25224
+ const patchStatus = readNonEmptyString2(patchEquivalence?.status) || (patchEquivalence?.equivalent === true ? "passed" : "");
25205
25225
  const into = readNonEmptyString2(result?.into);
25206
25226
  const branch = readNonEmptyString2(result?.branch);
25227
+ const mergeStatus = result?.merged === true ? "merged" : readNonEmptyString2(finalConvergence?.status);
25228
+ const convergenceStatus = readNonEmptyString2(finalConvergence?.status);
25229
+ const nextStep = readNonEmptyString2(result?.nextStep) || readNonEmptyString2(finalConvergence?.nextStep) || "Continue from the updated mesh state.";
25207
25230
  const details = [
25208
25231
  jobId ? `job_id=${jobId}` : "",
25209
25232
  branch && into ? `${branch}\u2192${into}` : "",
25210
- validationStatus ? `validation=${validationStatus}` : ""
25233
+ validationStatus ? `validation=${validationStatus}` : "",
25234
+ patchStatus ? `patch_equivalence=${patchStatus}` : "",
25235
+ mergeStatus ? `merge=${mergeStatus}` : "",
25236
+ convergenceStatus ? `final_convergence=${convergenceStatus}` : ""
25211
25237
  ].filter(Boolean).join("; ");
25212
- return `[System] Refinery async job for ${args.nodeLabel} completed successfully${details ? ` (${details})` : ""}. The worktree was merged and cleanup completed; continue from the updated mesh state.`;
25238
+ return `[System] Refinery async job for ${args.nodeLabel} completed successfully${details ? ` (${details})` : ""}.
25239
+ Next step: ${nextStep}`;
25213
25240
  }
25214
25241
  if (args.event === "refine:failed") {
25215
25242
  const jobId = readRefineJobId({ metadataEvent: args.metadataEvent });
25216
25243
  const result = readRecord(args.metadataEvent.result);
25244
+ const validationSummary = readRecord(result?.validationSummary);
25245
+ const patchEquivalence = readRecord(result?.patchEquivalence);
25246
+ const finalConvergence = readRecord(result?.finalBranchConvergenceState);
25217
25247
  const code = readNonEmptyString2(result?.code);
25218
25248
  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.`;
25249
+ const validationStatus = readNonEmptyString2(validationSummary?.status);
25250
+ const patchStatus = readNonEmptyString2(patchEquivalence?.status) || (patchEquivalence?.equivalent === true ? "passed" : "");
25251
+ const mergeStatus = result?.merged === true ? "merged" : finalConvergence?.merged === false ? "not_merged" : "";
25252
+ const convergenceStatus = readNonEmptyString2(result?.convergenceStatus) || readNonEmptyString2(finalConvergence?.status);
25253
+ const blockedReason = readNonEmptyString2(result?.blockedReason);
25254
+ const nextStep = readNonEmptyString2(result?.nextStep) || readNonEmptyString2(finalConvergence?.nextStep);
25255
+ const details = [
25256
+ jobId ? `job_id=${jobId}` : "",
25257
+ code ? `code=${code}` : "",
25258
+ validationStatus ? `validation=${validationStatus}` : "",
25259
+ patchStatus ? `patch_equivalence=${patchStatus}` : "",
25260
+ mergeStatus ? `merge=${mergeStatus}` : "",
25261
+ convergenceStatus ? `convergence=${convergenceStatus}` : "",
25262
+ blockedReason ? `reason=${blockedReason}` : ""
25263
+ ].filter(Boolean).join("; ");
25264
+ const parts = [
25265
+ `[System] Refinery async job for ${args.nodeLabel} failed${details ? ` (${details})` : ""}${error48 ? `: ${error48}` : "."}`,
25266
+ nextStep ? `Next step: ${nextStep}` : "Review the terminal refine event/ledger before retrying."
25267
+ ];
25268
+ return parts.join("\n");
25221
25269
  }
25222
25270
  return "";
25223
25271
  }
@@ -25339,7 +25387,8 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
25339
25387
  remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
25340
25388
  }
25341
25389
  if (sessionId) {
25342
- updateSessionTaskStatus(args.meshId, sessionId, "failed");
25390
+ const failedTask = updateSessionTaskStatus(args.meshId, sessionId, "failed");
25391
+ completedTaskForLedger = failedTask ? { id: failedTask.id } : null;
25343
25392
  }
25344
25393
  }
25345
25394
  const ledgerKind = EVENT_TO_LEDGER_KIND[args.event];
@@ -25434,6 +25483,13 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
25434
25483
  LOG2.warn("MeshRecovery", `Failed to build recovery context: ${e?.message || e}`);
25435
25484
  }
25436
25485
  }
25486
+ const messageText = buildMeshSystemMessage({
25487
+ event: args.event,
25488
+ nodeLabel: args.nodeLabel,
25489
+ metadataEvent: args.metadataEvent,
25490
+ recoveryContext
25491
+ });
25492
+ if (!messageText) return { success: false, error: "unsupported mesh event" };
25437
25493
  const coordinatorInstances = components.instanceManager.getByCategory("cli").filter((inst) => {
25438
25494
  const instState = inst.getState();
25439
25495
  if (instState.settings?.meshCoordinatorFor !== args.meshId) return false;
@@ -25451,19 +25507,13 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
25451
25507
  ...args.metadataEvent,
25452
25508
  ...recoveryContext ? { recoveryContext } : {}
25453
25509
  },
25510
+ coordinatorMessage: messageText,
25454
25511
  queuedAt: Date.now()
25455
25512
  })) {
25456
25513
  LOG2.info("MeshEvents", `Queued ${args.event} for MCP coordinator (mesh ${args.meshId})`);
25457
25514
  }
25458
25515
  return { success: true, forwarded: 0 };
25459
25516
  }
25460
- const messageText = buildMeshSystemMessage({
25461
- event: args.event,
25462
- nodeLabel: args.nodeLabel,
25463
- metadataEvent: args.metadataEvent,
25464
- recoveryContext
25465
- });
25466
- if (!messageText) return { success: false, error: "unsupported mesh event" };
25467
25517
  for (const coord of coordinatorInstances) {
25468
25518
  const coordState = coord.getState();
25469
25519
  LOG2.info("MeshEvents", `Forwarding mesh event to coordinator ${coordState.instanceId}`);
@@ -31389,9 +31439,11 @@ ${lastSnapshot}`;
31389
31439
  return Number.isFinite(started) ? Math.max(0, now - started) : 0;
31390
31440
  }
31391
31441
  function sessionStatusFromNodes(nodes, nodeId, sessionId) {
31392
- if (!nodeId || !sessionId || !Array.isArray(nodes)) return void 0;
31442
+ if (!Array.isArray(nodes)) return {};
31443
+ if (!nodeId) return { staleReason: "direct task has no node id" };
31393
31444
  const node = nodes.find((item) => readString2(item?.id) === nodeId || readString2(item?.nodeId) === nodeId || readString2(item?.node_id) === nodeId);
31394
- if (!node) return void 0;
31445
+ if (!node) return { staleReason: "direct task node is no longer in the live mesh" };
31446
+ if (!sessionId) return {};
31395
31447
  const candidates = [];
31396
31448
  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
31449
  if (Array.isArray(value)) candidates.push(...value);
@@ -31400,16 +31452,18 @@ ${lastSnapshot}`;
31400
31452
  if (value && typeof value === "object") candidates.push(value);
31401
31453
  }
31402
31454
  const session = candidates.find((item) => {
31455
+ if (typeof item === "string") return item === sessionId;
31403
31456
  const id = readString2(item?.id) || readString2(item?.sessionId) || readString2(item?.session_id) || readString2(item?.runtimeSessionId) || readString2(item?.instanceId);
31404
31457
  return id === sessionId;
31405
31458
  });
31406
- if (!session) return void 0;
31459
+ if (!session) return { staleReason: "direct task session is not present in live session records" };
31460
+ if (typeof session === "string") return {};
31407
31461
  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;
31462
+ if (raw.includes("approval")) return { status: "awaiting_approval" };
31463
+ if (raw.includes("generating") || raw.includes("running") || raw.includes("busy")) return { status: "generating" };
31464
+ if (raw.includes("failed") || raw.includes("stopped") || raw.includes("terminated") || raw.includes("exited")) return { status: "failed" };
31465
+ if (raw.includes("idle") || raw.includes("waiting_input") || raw.includes("ready")) return { status: "idle" };
31466
+ return {};
31413
31467
  }
31414
31468
  function isDirectDispatch(entry) {
31415
31469
  if (entry.kind !== "task_dispatched") return false;
@@ -31456,15 +31510,17 @@ ${lastSnapshot}`;
31456
31510
  failedCount: statusCounts.failed,
31457
31511
  idleCount: statusCounts.idle,
31458
31512
  sourceCounts,
31459
- statusCounts
31513
+ statusCounts,
31514
+ staleDirectCount: activeWork.filter((item) => item.source === "direct" && item.staleReason).length
31460
31515
  };
31461
31516
  }
31462
31517
  function buildMeshActiveWork(opts) {
31463
31518
  const now = opts.now ?? Date.now();
31464
31519
  const records = [];
31520
+ const staleDirectWork = [];
31465
31521
  for (const task of opts.queue || []) {
31466
31522
  if (task.status !== "pending" && task.status !== "assigned") continue;
31467
- const { title, summary } = summarizeMessage(task.message || "");
31523
+ const { title, summary: summary2 } = summarizeMessage(task.message || "");
31468
31524
  records.push({
31469
31525
  taskId: task.id,
31470
31526
  source: "queue",
@@ -31472,7 +31528,7 @@ ${lastSnapshot}`;
31472
31528
  nodeId: task.assignedNodeId || task.targetNodeId,
31473
31529
  sessionId: task.assignedSessionId || task.targetSessionId,
31474
31530
  taskTitle: title,
31475
- taskSummary: summary,
31531
+ taskSummary: summary2,
31476
31532
  message: task.message,
31477
31533
  taskMode: task.taskMode,
31478
31534
  createdAt: task.createdAt,
@@ -31487,13 +31543,13 @@ ${lastSnapshot}`;
31487
31543
  const taskId = directDispatchTaskId(dispatch);
31488
31544
  const terminal = terminals.filter((entry) => new Date(entry.timestamp).getTime() >= new Date(dispatch.timestamp).getTime()).find((entry) => terminalMatchesDispatch(entry, dispatch, taskId));
31489
31545
  const terminalStatus = terminal ? statusFromTerminal(terminal) : void 0;
31490
- const liveStatus = sessionStatusFromNodes(opts.nodes, dispatch.nodeId, dispatch.sessionId);
31491
- const status = terminalStatus || liveStatus || "assigned";
31546
+ const live = sessionStatusFromNodes(opts.nodes, dispatch.nodeId, dispatch.sessionId);
31547
+ const status = terminalStatus || live.status || "assigned";
31492
31548
  const terminalRow = Boolean(terminal && terminal.kind !== "task_approval_needed");
31493
31549
  if (terminalRow && opts.includeTerminalDirect !== true) continue;
31494
31550
  const message = readString2(dispatch.payload?.message) || readString2(dispatch.payload?.summary) || "";
31495
- const { title, summary } = summarizeMessage(message);
31496
- records.push({
31551
+ const { title, summary: summary2 } = summarizeMessage(message);
31552
+ const record2 = {
31497
31553
  taskId,
31498
31554
  source: "direct",
31499
31555
  status,
@@ -31501,7 +31557,7 @@ ${lastSnapshot}`;
31501
31557
  sessionId: dispatch.sessionId,
31502
31558
  providerType: dispatch.providerType || readString2(dispatch.payload?.providerType),
31503
31559
  taskTitle: readString2(dispatch.payload?.taskTitle) || title,
31504
- taskSummary: readString2(dispatch.payload?.taskSummary) || summary,
31560
+ taskSummary: readString2(dispatch.payload?.taskSummary) || summary2,
31505
31561
  message,
31506
31562
  taskMode: readString2(dispatch.payload?.taskMode),
31507
31563
  createdAt: dispatch.timestamp,
@@ -31510,11 +31566,20 @@ ${lastSnapshot}`;
31510
31566
  elapsedMs: elapsedSince(dispatch.timestamp, now),
31511
31567
  terminal: terminalRow,
31512
31568
  terminalKind: terminal?.kind,
31513
- terminalAt: terminal?.timestamp
31514
- });
31569
+ terminalAt: terminal?.timestamp,
31570
+ staleReason: live.staleReason
31571
+ };
31572
+ if (live.staleReason && !terminalRow) {
31573
+ staleDirectWork.push(record2);
31574
+ continue;
31575
+ }
31576
+ records.push(record2);
31515
31577
  }
31516
31578
  records.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
31517
- return { activeWork: records, summary: buildMeshActiveWorkSummary(records) };
31579
+ staleDirectWork.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
31580
+ const summary = buildMeshActiveWorkSummary(records);
31581
+ summary.staleDirectCount = staleDirectWork.length;
31582
+ return { activeWork: records, staleDirectWork, summary };
31518
31583
  }
31519
31584
  init_mesh_host_ownership();
31520
31585
  init_mesh_events();
@@ -41699,23 +41764,28 @@ ${effect.notification.body || ""}`.trim();
41699
41764
  if (hasNonEmptyCliModalButtons(parsedStatus?.activeModal ?? parsedStatus?.modal)) return false;
41700
41765
  return !this.hasAdapterPendingResponse();
41701
41766
  }
41702
- getCompletedFinalizationBlockReason(latestVisibleStatus) {
41703
- if (latestVisibleStatus !== "idle") return `status:${latestVisibleStatus}`;
41767
+ getCompletedFinalizationBlock(latestVisibleStatus) {
41768
+ if (latestVisibleStatus !== "idle") return { reason: `status:${latestVisibleStatus}`, terminal: true };
41704
41769
  const adapterAny = this.adapter;
41705
- if (adapterAny?.isWaitingForResponse === true) return "adapter_waiting_for_response";
41706
- if (adapterAny?.currentTurnScope) return "adapter_turn_scope_active";
41770
+ if (adapterAny?.isWaitingForResponse === true) return { reason: "adapter_waiting_for_response", terminal: true };
41771
+ if (adapterAny?.currentTurnScope) return { reason: "adapter_turn_scope_active", terminal: true };
41772
+ if (this.hasAdapterPendingResponse()) return { reason: "adapter_pending_response", terminal: true };
41707
41773
  const partial2 = typeof this.adapter.getPartialResponse === "function" ? this.adapter.getPartialResponse() : "";
41708
- if (typeof partial2 === "string" && partial2.trim()) return "partial_response_pending";
41774
+ if (typeof partial2 === "string" && partial2.trim()) return { reason: "partial_response_pending", terminal: true };
41709
41775
  let parsed;
41710
41776
  try {
41711
41777
  parsed = this.adapter.getScriptParsedStatus();
41712
41778
  } catch (error48) {
41713
- return `parse_error:${error48?.message || String(error48)}`;
41779
+ return { reason: `parse_error:${error48?.message || String(error48)}` };
41714
41780
  }
41715
41781
  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";
41782
+ if (parsedStatus !== "idle") {
41783
+ const adapterStatus = this.adapter.getStatus({ allowParse: false });
41784
+ if (this.shouldSuppressStaleParsedBusyStatus(parsed, adapterStatus)) return null;
41785
+ return { reason: `parsed_status:${parsedStatus}`, terminal: isCliGeneratingLikeStatus(parsedStatus) };
41786
+ }
41787
+ if (parsed?.activeModal || parsed?.modal) return { reason: "parsed_modal_active", terminal: true };
41788
+ if (!this.completionHasFinalAssistantMessage(parsed?.messages)) return { reason: "missing_final_assistant" };
41719
41789
  return null;
41720
41790
  }
41721
41791
  scheduleCompletedDebounceFlush(delayMs) {
@@ -41737,10 +41807,11 @@ ${effect.notification.body || ""}`.trim();
41737
41807
  this.completedDebounceTimer = null;
41738
41808
  return;
41739
41809
  }
41740
- const blockReason = this.getCompletedFinalizationBlockReason(latestVisibleStatus);
41741
- if (blockReason) {
41810
+ const block2 = this.getCompletedFinalizationBlock(latestVisibleStatus);
41811
+ if (block2) {
41812
+ const blockReason = block2.reason;
41742
41813
  const waitedMs = Date.now() - pending.firstObservedAt;
41743
- if (waitedMs < COMPLETED_FINALIZATION_MAX_WAIT_MS) {
41814
+ if (block2.terminal || waitedMs < COMPLETED_FINALIZATION_MAX_WAIT_MS) {
41744
41815
  if (pending.loggedBlockReason !== blockReason) {
41745
41816
  LOG2.info("CLI", `[${this.type}] waiting to emit completed until transcript finalizes (${blockReason})`);
41746
41817
  pending.loggedBlockReason = blockReason;
@@ -43596,6 +43667,47 @@ ${rawInput}` : rawInput;
43596
43667
  function normalizeAgentStatus(value) {
43597
43668
  return typeof value === "string" ? value.trim().toLowerCase() : "";
43598
43669
  }
43670
+ function hasNonEmptyModalButtons2(activeModal) {
43671
+ const buttons = activeModal?.buttons;
43672
+ return Array.isArray(buttons) && buttons.some((button) => String(button || "").trim().length > 0);
43673
+ }
43674
+ function hasAdapterPendingResponse(adapter) {
43675
+ if (adapter?.isWaitingForResponse === true) return true;
43676
+ if (adapter?.currentTurnScope) return true;
43677
+ try {
43678
+ if (typeof adapter?.isProcessing === "function" && adapter.isProcessing()) return true;
43679
+ } catch {
43680
+ }
43681
+ try {
43682
+ const partial2 = typeof adapter?.getPartialResponse === "function" ? adapter.getPartialResponse() : "";
43683
+ if (typeof partial2 === "string" && partial2.trim()) return true;
43684
+ } catch {
43685
+ }
43686
+ return false;
43687
+ }
43688
+ function shouldSuppressStaleParsedBusyStatus(adapterStatus, parsedStatus, adapter) {
43689
+ const parsedRawStatus = normalizeAgentStatus(parsedStatus?.status);
43690
+ if (!BUSY_AGENT_STATUSES.has(parsedRawStatus)) return false;
43691
+ if (adapterStatus !== "idle") return false;
43692
+ if (hasNonEmptyModalButtons2(parsedStatus?.activeModal ?? parsedStatus?.modal)) return false;
43693
+ return !hasAdapterPendingResponse(adapter);
43694
+ }
43695
+ function getEffectiveAgentSendStatus(adapter) {
43696
+ const adapterStatus = normalizeAgentStatus(adapter?.getStatus?.({ allowParse: false })?.status ?? adapter?.getStatus?.()?.status);
43697
+ if (adapterStatus && adapterStatus !== "idle") return adapterStatus;
43698
+ if (adapterStatus !== "idle") return adapterStatus;
43699
+ if (typeof adapter?.getScriptParsedStatus !== "function") return adapterStatus;
43700
+ try {
43701
+ const parsedStatus = adapter.getScriptParsedStatus();
43702
+ const parsedRawStatus = normalizeAgentStatus(parsedStatus?.status);
43703
+ if (BUSY_AGENT_STATUSES.has(parsedRawStatus) && !shouldSuppressStaleParsedBusyStatus(adapterStatus, parsedStatus, adapter)) {
43704
+ return parsedRawStatus;
43705
+ }
43706
+ } catch {
43707
+ return adapterStatus;
43708
+ }
43709
+ return adapterStatus;
43710
+ }
43599
43711
  var chalkModule = import_chalk.default;
43600
43712
  var chalkApi = typeof chalkModule.yellow === "function" ? chalkModule : chalkModule.default || null;
43601
43713
  function colorize(color, text) {
@@ -44370,7 +44482,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
44370
44482
  if (!found) throw new Error(`CLI agent not running: ${agentType}`);
44371
44483
  const { adapter, key } = found;
44372
44484
  if (action === "send_chat") {
44373
- const currentStatus = normalizeAgentStatus(adapter.getStatus?.()?.status);
44485
+ const currentStatus = getEffectiveAgentSendStatus(adapter);
44374
44486
  if (BUSY_AGENT_STATUSES.has(currentStatus)) {
44375
44487
  return {
44376
44488
  success: false,
@@ -47831,6 +47943,17 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
47831
47943
  }).filter((entry) => entry !== null);
47832
47944
  return submodules.length > 0 ? submodules : void 0;
47833
47945
  }
47946
+ function buildMeshNodeDisplayLabel(node, nodeId, providerPriority) {
47947
+ const explicit = readStringValue(node.machineLabel, node.machine_label, node.machineNickname, node.machine_nickname, node.alias);
47948
+ if (explicit) return explicit;
47949
+ const workspace = readStringValue(node.workspace, node.repoRoot, node.repo_root);
47950
+ const workspaceName = workspace ? (0, import_path8.basename)(workspace) : void 0;
47951
+ const host = readStringValue(node.hostname, node.host, node.daemonId, node.daemon_id, node.machineId, node.machine_id);
47952
+ const provider = providerPriority[0] || (Array.isArray(node.providers) ? readStringValue(...node.providers) : void 0);
47953
+ const parts = [workspaceName, host, provider].filter(Boolean);
47954
+ if (parts.length > 0) return parts.join(" \xB7 ");
47955
+ return nodeId || "unidentified mesh node";
47956
+ }
47834
47957
  function normalizeInlineMeshGitStatus(status, node, options) {
47835
47958
  const isGitRepo = readBooleanValue(status.isGitRepo);
47836
47959
  if (!Object.keys(status).length || isGitRepo === void 0) return void 0;
@@ -48501,7 +48624,7 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
48501
48624
  }
48502
48625
  function buildSubmodulePublishRequiredNextStep(entries) {
48503
48626
  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.`;
48627
+ 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
48628
  }
48506
48629
  async function computeGitPatchId(cwd, fromRef, toRef) {
48507
48630
  const { execFileSync: execFileSync3 } = await import("child_process");
@@ -48588,15 +48711,9 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
48588
48711
  });
48589
48712
  return String(stdout || "");
48590
48713
  };
48591
- const verifyRemoteCommitReachable = async (remoteUrl, commit) => {
48592
- const probeDir = fs11.mkdtempSync((0, import_path8.join)((0, import_os3.tmpdir)(), "adhdev-submodule-reachability-"));
48593
- try {
48594
- await runGit2(probeDir, ["init", "-q"]);
48595
- await runGit2(probeDir, ["-c", "protocol.file.allow=always", "fetch", "--depth=1", remoteUrl, commit]);
48596
- await runGit2(probeDir, ["cat-file", "-e", `${commit}^{commit}`]);
48597
- } finally {
48598
- fs11.rmSync(probeDir, { recursive: true, force: true });
48599
- }
48714
+ const verifyRemoteMainContainsCommit = async (submodulePath, commit, branch = "main") => {
48715
+ await runGit2(submodulePath, ["-c", "protocol.file.allow=always", "fetch", "origin", `refs/heads/${branch}:refs/remotes/origin/${branch}`]);
48716
+ await runGit2(submodulePath, ["merge-base", "--is-ancestor", commit, `refs/remotes/origin/${branch}`]);
48600
48717
  };
48601
48718
  const treeOutput = await runGit2(repoRoot, ["ls-tree", "-r", "-z", mergedTree]);
48602
48719
  const gitlinks = treeOutput.split("\0").filter(Boolean).map((record2) => {
@@ -48637,15 +48754,18 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
48637
48754
  entries.push(entry);
48638
48755
  continue;
48639
48756
  }
48640
- await verifyRemoteCommitReachable(remoteUrl, gitlink.commit);
48757
+ entry.remoteMainBranch = "main";
48758
+ await verifyRemoteMainContainsCommit(submodulePath, gitlink.commit, "main");
48641
48759
  entry.fetchedFromOrigin = true;
48642
48760
  entry.remoteReachable = true;
48761
+ entry.remoteMainReachable = true;
48643
48762
  entry.reachable = true;
48644
48763
  } catch (e) {
48645
48764
  entry.remoteReachable = false;
48765
+ entry.remoteMainReachable = false;
48646
48766
  entry.publishRequired = true;
48647
48767
  const details = truncateValidationOutput(e?.stderr || e?.message || String(e));
48648
- entry.error = `Submodule remote reachability check failed for origin: ${details}`;
48768
+ entry.error = `Submodule remote main reachability check failed for origin/main: ${details}`;
48649
48769
  }
48650
48770
  } catch (e) {
48651
48771
  entry.error = truncateValidationOutput(e?.message || String(e));
@@ -49620,28 +49740,51 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
49620
49740
  };
49621
49741
  }
49622
49742
  queueRefineJobEvent(event, handle, result) {
49623
- queuePendingMeshCoordinatorEvent({
49743
+ const metadataEvent = {
49744
+ source: "refine_mesh_node_async_job",
49745
+ jobId: handle.jobId,
49746
+ interactionId: handle.interactionId,
49747
+ meshId: handle.meshId,
49748
+ nodeId: handle.targetNodeId,
49749
+ targetDaemonId: handle.targetDaemonId,
49750
+ workspace: handle.workspace,
49751
+ status: handle.status,
49752
+ startedAt: handle.startedAt,
49753
+ completedAt: handle.completedAt,
49754
+ retryOfJobId: handle.retryOfJobId,
49755
+ ...result ? { result } : {}
49756
+ };
49757
+ const eventPayload = {
49624
49758
  event,
49625
49759
  meshId: handle.meshId,
49626
49760
  nodeLabel: handle.targetNodeId,
49627
49761
  nodeId: handle.targetNodeId,
49628
49762
  workspace: handle.workspace,
49629
- metadataEvent: {
49630
- source: "refine_mesh_node_async_job",
49631
- jobId: handle.jobId,
49632
- interactionId: handle.interactionId,
49633
- meshId: handle.meshId,
49634
- nodeId: handle.targetNodeId,
49635
- targetDaemonId: handle.targetDaemonId,
49636
- workspace: handle.workspace,
49637
- status: handle.status,
49638
- startedAt: handle.startedAt,
49639
- completedAt: handle.completedAt,
49640
- retryOfJobId: handle.retryOfJobId,
49641
- ...result ? { result } : {}
49642
- },
49763
+ metadataEvent,
49643
49764
  queuedAt: Date.now()
49644
- });
49765
+ };
49766
+ if (typeof this.deps.instanceManager?.getByCategory === "function") {
49767
+ const forwarded = handleMeshForwardEvent(
49768
+ { instanceManager: this.deps.instanceManager },
49769
+ {
49770
+ event,
49771
+ meshId: handle.meshId,
49772
+ nodeId: handle.targetNodeId,
49773
+ workspace: handle.workspace,
49774
+ jobId: handle.jobId,
49775
+ interactionId: handle.interactionId,
49776
+ status: handle.status,
49777
+ targetDaemonId: handle.targetDaemonId,
49778
+ startedAt: handle.startedAt,
49779
+ completedAt: handle.completedAt,
49780
+ retryOfJobId: handle.retryOfJobId,
49781
+ ...result ? { result } : {}
49782
+ }
49783
+ );
49784
+ if (forwarded?.success === true) return;
49785
+ LOG2.warn("Mesh", `[Refinery] Failed to forward async refine event ${event}: ${forwarded?.error || "unknown error"}`);
49786
+ }
49787
+ queuePendingMeshCoordinatorEvent(eventPayload);
49645
49788
  }
49646
49789
  async appendRefineJobLedger(kind, handle, result) {
49647
49790
  try {
@@ -49793,6 +49936,8 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
49793
49936
  remote: entry.remote,
49794
49937
  remoteUrl: entry.remoteUrl,
49795
49938
  remoteReachable: entry.remoteReachable,
49939
+ remoteMainBranch: entry.remoteMainBranch,
49940
+ remoteMainReachable: entry.remoteMainReachable,
49796
49941
  error: entry.error
49797
49942
  })),
49798
49943
  error: submoduleReachability.error
@@ -49805,13 +49950,13 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
49805
49950
  convergenceStatus: "blocked_review",
49806
49951
  publishRequired: true,
49807
49952
  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.",
49953
+ 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
49954
  nextStep,
49810
49955
  nextSteps: [
49811
49956
  "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.",
49957
+ "Push/publish each unreachable submodule commit to the configured submodule remote main branch shown in the evidence.",
49813
49958
  "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."
49959
+ "Do not merge the root branch until every submodule gitlink commit is reachable from submodule origin/main."
49815
49960
  ],
49816
49961
  unreachableSubmoduleCommits: submoduleReachability.unreachable.map((entry) => ({
49817
49962
  path: entry.path,
@@ -49819,6 +49964,8 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
49819
49964
  remote: entry.remote,
49820
49965
  remoteUrl: entry.remoteUrl,
49821
49966
  remoteReachable: entry.remoteReachable,
49967
+ remoteMainBranch: entry.remoteMainBranch,
49968
+ remoteMainReachable: entry.remoteMainReachable,
49822
49969
  error: entry.error
49823
49970
  })),
49824
49971
  branch,
@@ -51693,7 +51840,8 @@ ${block2}`);
51693
51840
  ) || Boolean(meshRecord?.inline && nodeIndex === 0);
51694
51841
  const status = {
51695
51842
  nodeId,
51696
- machineLabel: node.machineLabel || node.id || node.nodeId,
51843
+ machineLabel: buildMeshNodeDisplayLabel(node, nodeId, providerPriority),
51844
+ labelSource: readStringValue(node.machineLabel, node.machine_label, node.machineNickname, node.machine_nickname, node.alias) ? "explicit_metadata" : "workspace_host_provider_context",
51697
51845
  workspace: node.workspace,
51698
51846
  repoRoot: node.repoRoot,
51699
51847
  isLocalWorktree: node.isLocalWorktree,