@adhdev/daemon-standalone 1.0.18-rc.10 → 1.0.18-rc.11

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
@@ -30265,10 +30265,10 @@ var require_dist3 = __commonJS({
30265
30265
  }
30266
30266
  function getDaemonBuildInfo() {
30267
30267
  if (cached2) return cached2;
30268
- const commit = readInjected(true ? "36bb91235b40db3d3fb1587850f0a213d040bcef" : void 0) ?? "unknown";
30269
- const commitShort = readInjected(true ? "36bb9123" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
30270
- const version2 = readInjected(true ? "1.0.18-rc.10" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
30271
- const builtAt = readInjected(true ? "2026-07-22T07:21:47.865Z" : void 0);
30268
+ const commit = readInjected(true ? "99f9c20bcf4ceec1e7ab2bfe6c8f641ca88da360" : void 0) ?? "unknown";
30269
+ const commitShort = readInjected(true ? "99f9c20b" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
30270
+ const version2 = readInjected(true ? "1.0.18-rc.11" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
30271
+ const builtAt = readInjected(true ? "2026-07-22T10:19:28.847Z" : void 0);
30272
30272
  cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
30273
30273
  return cached2;
30274
30274
  }
@@ -32474,6 +32474,51 @@ ${error48.message || ""}`;
32474
32474
  import_node_crypto = require("crypto");
32475
32475
  }
32476
32476
  });
32477
+ var dist_exports = {};
32478
+ __export2(dist_exports, {
32479
+ CANONICAL_MESH_TOOL_COUNT: () => CANONICAL_MESH_TOOL_COUNT,
32480
+ CANONICAL_MESH_TOOL_NAMES: () => CANONICAL_MESH_TOOL_NAMES,
32481
+ DEFAULT_DIFFICULTY_BRAINS: () => DEFAULT_DIFFICULTY_BRAINS,
32482
+ MAGI_RAW_ANSWER_CAP: () => MAGI_RAW_ANSWER_CAP,
32483
+ MESH_TASK_DIFFICULTIES: () => MESH_TASK_DIFFICULTIES,
32484
+ STATUS_PROBE_ARG_KEY: () => STATUS_PROBE_ARG_KEY,
32485
+ argsCarryStatusProbeMarker: () => argsCarryStatusProbeMarker,
32486
+ canonicalDaemonId: () => canonicalDaemonId,
32487
+ daemonIdsEquivalent: () => daemonIdsEquivalent,
32488
+ deriveSlotsFromLegacy: () => deriveSlotsFromLegacy,
32489
+ expandDaemonIdForms: () => expandDaemonIdForms,
32490
+ hasGitStatusEvidence: () => hasGitStatusEvidence,
32491
+ interpolateArgs: () => interpolateArgs,
32492
+ interpolateString: () => interpolateString,
32493
+ isMeshTaskDifficulty: () => isMeshTaskDifficulty,
32494
+ joinRepoPath: () => joinRepoPath,
32495
+ machineCoreFromDaemonId: () => machineCoreFromDaemonId,
32496
+ meshNodeIdMatches: () => meshNodeIdMatches,
32497
+ meshWorkspacesEquivalent: () => meshWorkspacesEquivalent,
32498
+ normalizeBrainSlot: () => normalizeBrainSlot,
32499
+ normalizeDifficultyBrainMap: () => normalizeDifficultyBrainMap,
32500
+ normalizeGitStatus: () => normalizeGitStatus,
32501
+ normalizeMeshNodeId: () => normalizeMeshNodeId,
32502
+ normalizeMeshSessionRecord: () => normalizeMeshSessionRecord,
32503
+ normalizeMeshWorkspaceForCompare: () => normalizeMeshWorkspaceForCompare,
32504
+ normalizeNodeCapabilitySlot: () => normalizeNodeCapabilitySlot,
32505
+ normalizeNodeCapabilitySlots: () => normalizeNodeCapabilitySlots,
32506
+ normalizeThinkingLevel: () => normalizeThinkingLevel,
32507
+ parseJsonRecord: () => parseJsonRecord,
32508
+ pickBestTransitGitStatus: () => pickBestTransitGitStatus,
32509
+ readBoolean: () => readBoolean,
32510
+ readGitSubmodules: () => readGitSubmodules,
32511
+ readNumber: () => readNumber,
32512
+ readRecord: () => readRecord,
32513
+ readString: () => readString2,
32514
+ readStringArray: () => readStringArray2,
32515
+ scoreGitStatusCandidate: () => scoreGitStatusCandidate,
32516
+ scoreGitUpstreamFreshness: () => scoreGitUpstreamFreshness,
32517
+ sessionIdsEquivalent: () => sessionIdsEquivalent,
32518
+ stripStatusProbeMarker: () => stripStatusProbeMarker,
32519
+ summarizeGitShape: () => summarizeGitShape,
32520
+ withStatusProbeMarker: () => withStatusProbeMarker
32521
+ });
32477
32522
  function readRecord(value) {
32478
32523
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
32479
32524
  }
@@ -32497,6 +32542,21 @@ ${error48.message || ""}`;
32497
32542
  }
32498
32543
  return void 0;
32499
32544
  }
32545
+ function readStringArray2(value) {
32546
+ return Array.isArray(value) ? value.filter((entry) => typeof entry === "string" && entry.trim().length > 0) : [];
32547
+ }
32548
+ function parseJsonRecord(value) {
32549
+ if (!value) return {};
32550
+ if (typeof value === "object") return readRecord(value);
32551
+ if (typeof value !== "string") return {};
32552
+ const trimmed = value.trim();
32553
+ if (!trimmed) return {};
32554
+ try {
32555
+ return readRecord(JSON.parse(trimmed));
32556
+ } catch {
32557
+ return {};
32558
+ }
32559
+ }
32500
32560
  function joinRepoPath(root, relativePath) {
32501
32561
  const normalizedRoot = typeof root === "string" ? root.trim().replace(/[\\/]+$/, "") : "";
32502
32562
  const normalizedPath = typeof relativePath === "string" ? relativePath.trim() : "";
@@ -32637,12 +32697,48 @@ ${error48.message || ""}`;
32637
32697
  }
32638
32698
  return best?.git;
32639
32699
  }
32700
+ function deriveSyntheticSessionId(record2) {
32701
+ const parts = [
32702
+ readString2(record2.workspace),
32703
+ readString2(record2.providerType, record2.provider),
32704
+ readString2(record2.role),
32705
+ readString2(record2.state, record2.status),
32706
+ readString2(record2.title),
32707
+ readString2(record2.createdAt, record2.created_at),
32708
+ readString2(record2.startedAt, record2.started_at)
32709
+ ].filter((part) => Boolean(part));
32710
+ if (parts.length === 0) return void 0;
32711
+ return `synthetic:${parts.join("|")}`;
32712
+ }
32640
32713
  function sessionIdsEquivalent(a, b) {
32641
32714
  const idA = readString2(a);
32642
32715
  const idB = readString2(b);
32643
32716
  if (!idA || !idB) return false;
32644
32717
  return idA === idB;
32645
32718
  }
32719
+ function normalizeMeshSessionRecord(entry) {
32720
+ const record2 = readRecord(entry);
32721
+ const sessionId = readString2(record2.sessionId, record2.session_id, record2.id) ?? deriveSyntheticSessionId(record2);
32722
+ if (!sessionId) return null;
32723
+ return {
32724
+ sessionId,
32725
+ ...readString2(record2.providerType, record2.provider) ? { providerType: readString2(record2.providerType, record2.provider) } : {},
32726
+ ...readString2(record2.state, record2.status) ? { state: readString2(record2.state, record2.status) } : {},
32727
+ ...readString2(record2.chatStatus, record2.chat_status) ? { chatStatus: readString2(record2.chatStatus, record2.chat_status) } : {},
32728
+ ...readString2(record2.lifecycle) ? { lifecycle: readString2(record2.lifecycle) } : {},
32729
+ ...readString2(record2.surfaceKind, record2.surface_kind) ? { surfaceKind: readString2(record2.surfaceKind, record2.surface_kind) } : {},
32730
+ ...readString2(record2.recoveryState, record2.recovery_state) ? { recoveryState: readString2(record2.recoveryState, record2.recovery_state) } : {},
32731
+ ...readString2(record2.workspace) ? { workspace: readString2(record2.workspace) } : {},
32732
+ ...readString2(record2.title) ? { title: readString2(record2.title) } : {},
32733
+ ...readString2(record2.role) ? { role: readString2(record2.role) } : {},
32734
+ ...readBoolean(record2.isSelfCoordinator, record2.is_self_coordinator) !== void 0 ? { isSelfCoordinator: readBoolean(record2.isSelfCoordinator, record2.is_self_coordinator) } : {},
32735
+ ...readString2(record2.statusNote, record2.status_note) ? { statusNote: readString2(record2.statusNote, record2.status_note) } : {},
32736
+ ...readString2(record2.createdAt, record2.created_at) ? { createdAt: readString2(record2.createdAt, record2.created_at) } : {},
32737
+ ...readString2(record2.startedAt, record2.started_at) ? { startedAt: readString2(record2.startedAt, record2.started_at) } : {},
32738
+ ...readString2(record2.lastActivityAt, record2.last_activity_at) ? { lastActivityAt: readString2(record2.lastActivityAt, record2.last_activity_at) } : {},
32739
+ ...readBoolean(record2.isCached, record2.is_cached) !== void 0 ? { isCached: readBoolean(record2.isCached, record2.is_cached) } : {}
32740
+ };
32741
+ }
32646
32742
  function normalizeMeshNodeId(node) {
32647
32743
  const record2 = node && typeof node === "object" ? node : {};
32648
32744
  return readString2(record2.id, record2.nodeId, record2.node_id);
@@ -32825,9 +32921,30 @@ ${error48.message || ""}`;
32825
32921
  };
32826
32922
  });
32827
32923
  }
32924
+ function interpolateArgs(args, context) {
32925
+ const result = {};
32926
+ for (const [k, v] of Object.entries(args)) {
32927
+ result[k] = typeof v === "string" ? interpolateString(v, context) : v;
32928
+ }
32929
+ return result;
32930
+ }
32931
+ function interpolateString(template, ctx) {
32932
+ return template.replace(/\{\{(\w+)\}\}/g, (_, key2) => {
32933
+ const val = ctx[key2];
32934
+ return val !== void 0 ? String(val) : `{{${key2}}}`;
32935
+ });
32936
+ }
32828
32937
  function withStatusProbeMarker(args = {}) {
32829
32938
  return { ...args, [STATUS_PROBE_ARG_KEY]: true };
32830
32939
  }
32940
+ function argsCarryStatusProbeMarker(args) {
32941
+ return !!args && typeof args === "object" && args[STATUS_PROBE_ARG_KEY] === true;
32942
+ }
32943
+ function stripStatusProbeMarker(args) {
32944
+ if (!argsCarryStatusProbeMarker(args)) return args;
32945
+ const { [STATUS_PROBE_ARG_KEY]: _drop, ...rest } = args;
32946
+ return rest;
32947
+ }
32831
32948
  var DAEMON_ID_PREFIXES;
32832
32949
  var MAGI_RAW_ANSWER_CAP;
32833
32950
  var MESH_TASK_DIFFICULTIES;
@@ -32865,6 +32982,7 @@ ${error48.message || ""}`;
32865
32982
  "mesh_restart_daemon",
32866
32983
  "mesh_checkpoint",
32867
32984
  "mesh_approve",
32985
+ "mesh_answer_question",
32868
32986
  "mesh_list_pending_approvals",
32869
32987
  "mesh_clone_node",
32870
32988
  "mesh_remove_node",
@@ -34314,6 +34432,42 @@ ${surfaced}`;
34314
34432
  if (args.event === "agent:waiting_approval") {
34315
34433
  return `[System] ${args.nodeLabel} is waiting for approval to proceed${metadata}. You may use mesh_read_chat and mesh_approve to handle it.`;
34316
34434
  }
34435
+ if (args.event === "agent:waiting_choice") {
34436
+ const prompt = args.metadataEvent.interactivePrompt;
34437
+ const promptId = readNonEmptyString(args.metadataEvent.promptId) || prompt && readNonEmptyString(prompt.promptId);
34438
+ const lines = [
34439
+ `[System] ${args.nodeLabel} is asking a question and is waiting for your answer${metadata}.`
34440
+ ];
34441
+ const questions = Array.isArray(prompt?.questions) ? prompt.questions : [];
34442
+ if (questions.length > 0) {
34443
+ for (const q of questions) {
34444
+ const header = readNonEmptyString(q.header);
34445
+ const question = readNonEmptyString(q.question);
34446
+ const multiSelect = q.multiSelect === true;
34447
+ if (question) {
34448
+ lines.push(`
34449
+ **${header ? `${header}: ` : ""}${question}**${multiSelect ? " (select one or more)" : ""}`);
34450
+ }
34451
+ const options = Array.isArray(q.options) ? q.options : [];
34452
+ options.forEach((opt, i) => {
34453
+ const record2 = opt && typeof opt === "object" ? opt : {};
34454
+ const label = readNonEmptyString(record2.label);
34455
+ if (!label) return;
34456
+ const description = readNonEmptyString(record2.description);
34457
+ lines.push(` ${i + 1}. ${label}${description ? ` \u2014 ${description}` : ""}`);
34458
+ });
34459
+ }
34460
+ } else {
34461
+ const modalMessage = readNonEmptyString(args.metadataEvent.modalMessage);
34462
+ if (modalMessage) lines.push(`
34463
+ ${modalMessage}`);
34464
+ }
34465
+ lines.push(
34466
+ `
34467
+ Answer with mesh_answer_question(node_id, session_id${promptId ? `, promptId: "${promptId}"` : ""}, answers). Do NOT use mesh_approve \u2014 that only resolves yes/no consent modals, not a question. Use mesh_read_chat once if you need the full context first.`
34468
+ );
34469
+ return lines.join("\n");
34470
+ }
34317
34471
  if (args.event === "agent:stopped") {
34318
34472
  const rc = args.recoveryContext;
34319
34473
  if (rc && rc.consecutiveNodeFailures > 0) {
@@ -35831,6 +35985,7 @@ Next step: ${nextStep}`;
35831
35985
  requeueTask: () => requeueTask,
35832
35986
  resolveConvergeRequiredTags: () => resolveConvergeRequiredTags,
35833
35987
  resolveNotBefore: () => resolveNotBefore,
35988
+ takeCancelledTaskAssignment: () => takeCancelledTaskAssignment,
35834
35989
  taskDependenciesSatisfied: () => taskDependenciesSatisfied,
35835
35990
  updateDirectDispatchStatus: () => updateDirectDispatchStatus,
35836
35991
  updateSessionTaskStatus: () => updateSessionTaskStatus,
@@ -36390,6 +36545,10 @@ Next step: ${nextStep}`;
36390
36545
  const result = withQueueLock(meshId, () => {
36391
36546
  const entry = MeshRuntimeStore.getInstance().findQueueEntryById(meshId, taskId);
36392
36547
  if (!entry) return null;
36548
+ if (!opts?.force && TERMINAL_TASK_STATUSES.has(entry.status) && !TERMINAL_TASK_STATUSES.has(status)) {
36549
+ LOG2.debug("MeshQueue", `Refusing updateTaskStatus(${taskId} \u2192 ${status}) on mesh ${meshId}: row is terminal (${entry.status}). A late writer (e.g. dispatch-failure requeue) must not resurrect a cancelled/completed/failed task. Pass force to override.`);
36550
+ return { entry, cascaded: [] };
36551
+ }
36393
36552
  entry.status = status;
36394
36553
  MeshRuntimeStore.getInstance().updateQueueEntry(entry);
36395
36554
  if (status !== "assigned") endTaskDispatchInFlight(meshId, taskId);
@@ -36415,17 +36574,34 @@ Next step: ${nextStep}`;
36415
36574
  const entry = MeshRuntimeStore.getInstance().findQueueEntryById(meshId, taskId);
36416
36575
  if (!entry) return null;
36417
36576
  const now = (/* @__PURE__ */ new Date()).toISOString();
36577
+ const priorAssignment = entry.assignedSessionId ? {
36578
+ sessionId: entry.assignedSessionId,
36579
+ nodeId: entry.assignedNodeId,
36580
+ providerType: entry.assignedProviderType
36581
+ } : void 0;
36418
36582
  entry.status = "cancelled";
36419
36583
  entry.cancelledAt = now;
36420
36584
  if (opts?.reason) entry.cancelReason = opts.reason;
36585
+ delete entry.assignedNodeId;
36586
+ delete entry.assignedSessionId;
36587
+ delete entry.assignedProviderType;
36588
+ delete entry.dispatchTimestamp;
36589
+ entry.dispatchNonce = (entry.dispatchNonce || 0) + 1;
36421
36590
  MeshRuntimeStore.getInstance().updateQueueEntry(entry);
36422
36591
  endTaskDispatchInFlight(meshId, taskId);
36423
36592
  const cascaded = propagateDependencyFailure(meshId, taskId);
36424
- return { entry, cascaded };
36593
+ return { entry, cascaded, priorAssignment };
36425
36594
  });
36426
36595
  if (result) scheduleMissionCloseCandidateCheck(meshId, [result.entry, ...result.cascaded]);
36596
+ if (result?.priorAssignment) lastCancelledTaskAssignment.set(`${meshId}::${taskId}`, result.priorAssignment);
36427
36597
  return result ? result.entry : null;
36428
36598
  }
36599
+ function takeCancelledTaskAssignment(meshId, taskId) {
36600
+ const key2 = `${meshId}::${taskId}`;
36601
+ const value = lastCancelledTaskAssignment.get(key2);
36602
+ if (value) lastCancelledTaskAssignment.delete(key2);
36603
+ return value;
36604
+ }
36429
36605
  function requeueTask(meshId, taskId, opts) {
36430
36606
  requireMeshHostQueueOwner(opts);
36431
36607
  const result = withQueueLock(meshId, () => {
@@ -36652,6 +36828,8 @@ Next step: ${nextStep}`;
36652
36828
  var GIT_MUTATION_SUBCOMMANDS;
36653
36829
  var GIT_STASH_READONLY_SUBCOMMANDS;
36654
36830
  var DEPENDENCY_FAILURE_TERMINALS;
36831
+ var TERMINAL_TASK_STATUSES;
36832
+ var lastCancelledTaskAssignment;
36655
36833
  var MAX_STRANDED_RECLAIMS;
36656
36834
  var REDRIVE_RECLAIM_REASONS;
36657
36835
  var REDRIVE_SUPERSEDE_WINDOW_MS;
@@ -36722,6 +36900,8 @@ Next step: ${nextStep}`;
36722
36900
  ]);
36723
36901
  GIT_STASH_READONLY_SUBCOMMANDS = /* @__PURE__ */ new Set(["list", "show"]);
36724
36902
  DEPENDENCY_FAILURE_TERMINALS = /* @__PURE__ */ new Set(["failed", "cancelled"]);
36903
+ TERMINAL_TASK_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
36904
+ lastCancelledTaskAssignment = /* @__PURE__ */ new Map();
36725
36905
  MAX_STRANDED_RECLAIMS = 3;
36726
36906
  REDRIVE_RECLAIM_REASONS = /* @__PURE__ */ new Set([
36727
36907
  "delivered_no_turn_deadline",
@@ -38822,7 +39002,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
38822
39002
  function readNonEmptyString2(value) {
38823
39003
  return typeof value === "string" && value.trim() ? value.trim() : void 0;
38824
39004
  }
38825
- function readStringArray2(value) {
39005
+ function readStringArray3(value) {
38826
39006
  if (!Array.isArray(value)) return [];
38827
39007
  return value.map((item) => readNonEmptyString2(item)).filter(Boolean);
38828
39008
  }
@@ -38882,11 +39062,11 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
38882
39062
  return {
38883
39063
  status,
38884
39064
  ...readNonEmptyString2(raw.classification) ? { classification: readNonEmptyString2(raw.classification) } : {},
38885
- changedFiles: readStringArray2(raw.changedFiles),
39065
+ changedFiles: readStringArray3(raw.changedFiles),
38886
39066
  validationResults: normalizeValidationResults(raw.validationResults),
38887
39067
  ...gitStatus ? { gitStatus } : {},
38888
39068
  processArtifacts: normalizeProcessArtifacts(raw.processArtifacts),
38889
- errors: readStringArray2(raw.errors),
39069
+ errors: readStringArray3(raw.errors),
38890
39070
  ...readNonEmptyString2(raw.nextAction) ? { nextAction: readNonEmptyString2(raw.nextAction) } : {},
38891
39071
  requiresUserAction: raw.requiresUserAction === true,
38892
39072
  source
@@ -40065,7 +40245,8 @@ When you compose the task message you dispatch to a node, include these requirem
40065
40245
  | \`mesh_fast_forward_node\` | Safely dry-run or explicitly execute an obvious clean fast-forward without launching an agent session |
40066
40246
  | \`mesh_restart_daemon\` | Update a node's daemon to the latest published version on its channel and restart it (the dashboard "preview update" path, as a mesh command) |
40067
40247
  | \`mesh_checkpoint\` | Create a git checkpoint on a node |
40068
- | \`mesh_approve\` | Approve/reject a pending agent action |
40248
+ | \`mesh_approve\` | Approve/reject a pending agent action (a yes/no tool-consent modal) |
40249
+ | \`mesh_answer_question\` | Answer a delegated session's multi-choice QUESTION (AskUserQuestion / status awaiting_choice). NOT an approval \u2014 it offers labelled options (possibly multi-select or freeform). Pass the promptId from the agent:waiting_choice event + one answer per question (select by option label or 1-based index). Use this, never mesh_approve, for a question |
40069
40250
  | \`mesh_list_pending_approvals\` | List every session across the mesh awaiting an approval decision (the approval inbox) \u2014 read-only; enumerate all blocked sessions at once, then drive a mesh_approve for each |
40070
40251
  | \`mesh_clone_node\` | Create a worktree node for isolated parallel branch work |
40071
40252
  | \`mesh_refine_node\` | Validate and merge a completed worktree node back into its base branch |
@@ -40301,7 +40482,7 @@ When the user asks to **set up / configure / onboard** this repo for Repo Mesh (
40301
40482
  function readRecord4(value) {
40302
40483
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
40303
40484
  }
40304
- function readStringArray3(value, max) {
40485
+ function readStringArray4(value, max) {
40305
40486
  if (!Array.isArray(value)) return { values: [], truncated: false };
40306
40487
  const values = value.filter((item) => typeof item === "string" && item.trim().length > 0);
40307
40488
  return { values: values.slice(0, max), truncated: values.length > max };
@@ -40331,14 +40512,14 @@ When the user asks to **set up / configure / onboard** this repo for Repo Mesh (
40331
40512
  function readWorkerArtifact(value) {
40332
40513
  const worker = readRecord4(value);
40333
40514
  if (!worker) return null;
40334
- const changed = readStringArray3(worker.changedFiles, MAX_CHANGED_FILES);
40515
+ const changed = readStringArray4(worker.changedFiles, MAX_CHANGED_FILES);
40335
40516
  return {
40336
40517
  status: readString5(worker.status) ?? "unknown",
40337
40518
  ...readString5(worker.classification) ? { classification: readString5(worker.classification) } : {},
40338
40519
  changedFiles: changed.values,
40339
40520
  ...changed.truncated ? { changedFilesTruncated: true } : {},
40340
40521
  validationResults: Array.isArray(worker.validationResults) ? worker.validationResults.map((item) => readRecord4(item)).filter((item) => item !== null) : [],
40341
- errors: readStringArray3(worker.errors, 20).values,
40522
+ errors: readStringArray4(worker.errors, 20).values,
40342
40523
  requiresUserAction: worker.requiresUserAction === true
40343
40524
  };
40344
40525
  }
@@ -43503,6 +43684,61 @@ ${rendered}`, "utf-8");
43503
43684
  );
43504
43685
  }
43505
43686
  });
43687
+ var mesh_node_identity_exports = {};
43688
+ __export2(mesh_node_identity_exports, {
43689
+ MESH_DIRECT_PROBE_CONNECT_TIMEOUT_MS: () => MESH_DIRECT_PROBE_CONNECT_TIMEOUT_MS,
43690
+ MESH_DIRECT_PROBE_RETRY_TIMEOUT_MS: () => MESH_DIRECT_PROBE_RETRY_TIMEOUT_MS,
43691
+ MESH_DIRECT_PROBE_REUSE_MS: () => MESH_DIRECT_PROBE_REUSE_MS,
43692
+ MESH_DIRECT_PROBE_TIMEOUT_MS: () => MESH_DIRECT_PROBE_TIMEOUT_MS,
43693
+ MESH_NODE_LIVE_TRUTH_MARKER: () => MESH_NODE_LIVE_TRUTH_MARKER,
43694
+ MeshGitProbeCache: () => MeshGitProbeCache,
43695
+ applyCachedInlineMeshNodeStatus: () => applyCachedInlineMeshNodeStatus,
43696
+ applyInlineMeshBranchConvergence: () => applyInlineMeshBranchConvergence,
43697
+ awaitWithWarmupDeadline: () => awaitWithWarmupDeadline,
43698
+ buildHistoricalMeshSessions: () => buildHistoricalMeshSessions,
43699
+ buildInlineMeshTransitGitStatus: () => buildInlineMeshTransitGitStatus,
43700
+ buildLivePeerGitConnection: () => buildLivePeerGitConnection,
43701
+ buildMeshNodeDataFreshness: () => buildMeshNodeDataFreshness,
43702
+ buildMeshNodeDisplayLabel: () => buildMeshNodeDisplayLabel,
43703
+ buildMeshNodeMachineIdentity: () => buildMeshNodeMachineIdentity,
43704
+ buildMeshNodeProbeFreshness: () => buildMeshNodeProbeFreshness,
43705
+ collectLiveMeshSessionRecords: () => collectLiveMeshSessionRecords,
43706
+ collectMeshNodeHostedSessionIds: () => collectMeshNodeHostedSessionIds,
43707
+ deriveMeshNodeHealthFromGit: () => deriveMeshNodeHealthFromGit,
43708
+ finalizeMeshNodeStatus: () => finalizeMeshNodeStatus,
43709
+ foldMeshNodeIdentityToCanonical: () => foldMeshNodeIdentityToCanonical,
43710
+ hydrateInlineMeshDirectTruth: () => hydrateInlineMeshDirectTruth,
43711
+ inlineMeshCarriesTransientNodeTruth: () => inlineMeshCarriesTransientNodeTruth,
43712
+ isDeadLocalWorktreeNode: () => isDeadLocalWorktreeNode,
43713
+ isMeshNodeFreshEnoughToLaunch: () => isMeshNodeFreshEnoughToLaunch,
43714
+ isMeshNodeHealthLaunchable: () => isMeshNodeHealthLaunchable,
43715
+ logRepoMeshStatusDebug: () => logRepoMeshStatusDebug,
43716
+ normalizeInlineMeshNodeIdentity: () => normalizeInlineMeshNodeIdentity,
43717
+ normalizeProviderRoles: () => normalizeProviderRoles,
43718
+ persistNodeReporterPlatform: () => persistNodeReporterPlatform,
43719
+ probeRemoteMeshGitStatusWithRetry: () => probeRemoteMeshGitStatusWithRetry,
43720
+ readBooleanValue: () => readBooleanValue,
43721
+ readCachedInlineMeshActiveSessionDetails: () => readCachedInlineMeshActiveSessionDetails2,
43722
+ readCachedInlineMeshActiveSessions: () => readCachedInlineMeshActiveSessions,
43723
+ readInlineMeshNodeId: () => readInlineMeshNodeId,
43724
+ readLiveMeshNodeWorkspace: () => readLiveMeshNodeWorkspace,
43725
+ readMeshNodeDaemonId: () => readMeshNodeDaemonId,
43726
+ readMeshNodeHostname: () => readMeshNodeHostname,
43727
+ readMeshNodeMachineId: () => readMeshNodeMachineId,
43728
+ readObjectRecord: () => readObjectRecord,
43729
+ readProviderPriorityFromPolicy: () => readProviderPriorityFromPolicy,
43730
+ readStringValue: () => readStringValue,
43731
+ reconcileInlineMeshCache: () => reconcileInlineMeshCache,
43732
+ recordInlineMeshDirectGitTruth: () => recordInlineMeshDirectGitTruth,
43733
+ resolveEffectiveMeshNodeHealth: () => resolveEffectiveMeshNodeHealth,
43734
+ resolveMeshNodeAttribution: () => resolveMeshNodeAttribution,
43735
+ resolveProviderTypeFromPriority: () => resolveProviderTypeFromPriority,
43736
+ sanitizeInlineMesh: () => sanitizeInlineMesh,
43737
+ shouldRefreshStalePendingAggregate: () => shouldRefreshStalePendingAggregate,
43738
+ summarizeInlineMeshBranchConvergence: () => summarizeInlineMeshBranchConvergence,
43739
+ summarizeMeshSessionRecord: () => summarizeMeshSessionRecord,
43740
+ summarizeRepoMeshStatusDebug: () => summarizeRepoMeshStatusDebug
43741
+ });
43506
43742
  function readProviderPriorityFromPolicy(policy) {
43507
43743
  const record2 = policy && typeof policy === "object" && !Array.isArray(policy) ? policy : {};
43508
43744
  const raw = record2.providerPriority;
@@ -44066,6 +44302,23 @@ ${rendered}`, "utf-8");
44066
44302
  const health = resolveEffectiveMeshNodeHealth(node);
44067
44303
  return health === "online" || health === "unknown";
44068
44304
  }
44305
+ function resolveEffectiveNodeGit(node) {
44306
+ const git = readObjectRecord(node?.git);
44307
+ if (Object.keys(git).length > 0) return git;
44308
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
44309
+ return readObjectRecord(cachedStatus.git);
44310
+ }
44311
+ function isMeshNodeFreshEnoughToLaunch(node, opts) {
44312
+ const git = resolveEffectiveNodeGit(node);
44313
+ if (Object.keys(git).length === 0) return true;
44314
+ if (readBooleanValue(git.isGitRepo) === false) return true;
44315
+ const submoduleDrift = getGitSubmoduleDriftState(git);
44316
+ if (submoduleDrift.outOfSync) return false;
44317
+ const behind = readNumberValue(git.behind);
44318
+ if (behind === void 0) return true;
44319
+ const maxBehind = Number.isFinite(opts?.maxBehind) && opts?.maxBehind >= 0 ? Math.floor(opts.maxBehind) : 0;
44320
+ return behind <= maxBehind;
44321
+ }
44069
44322
  function readMeshNodeLabel(status, node) {
44070
44323
  return readStringValue(status.nodeId, normalizeMeshNodeId(node)) ?? "unknown";
44071
44324
  }
@@ -44970,6 +45223,7 @@ ${rendered}`, "utf-8");
44970
45223
  if (!session) return { staleReason: "direct task session is not present in live session records" };
44971
45224
  if (typeof session === "string") return {};
44972
45225
  const raw = `${readString6(session.status) || ""} ${readString6(session.lifecycle) || ""} ${readString6(session.state) || ""} ${readString6(session.activeChat?.status) || ""}`.toLowerCase();
45226
+ if (raw.includes("waiting_choice") || raw.includes("choice")) return { status: "awaiting_choice" };
44973
45227
  if (raw.includes("approval")) return { status: "awaiting_approval" };
44974
45228
  if (raw.includes("generating") || raw.includes("running") || raw.includes("busy")) return { status: "generating" };
44975
45229
  if (raw.includes("failed") || raw.includes("stopped") || raw.includes("terminated") || raw.includes("exited")) return { status: "failed" };
@@ -44995,6 +45249,7 @@ ${rendered}`, "utf-8");
44995
45249
  }
44996
45250
  function statusFromTerminal(entry) {
44997
45251
  if (entry.kind === "task_approval_needed") return "awaiting_approval";
45252
+ if (entry.kind === "task_question_pending") return "awaiting_choice";
44998
45253
  if (entry.kind === "task_completed") return "idle";
44999
45254
  return "failed";
45000
45255
  }
@@ -45073,7 +45328,8 @@ ${rendered}`, "utf-8");
45073
45328
  generating: 0,
45074
45329
  idle: 0,
45075
45330
  failed: 0,
45076
- awaiting_approval: 0
45331
+ awaiting_approval: 0,
45332
+ awaiting_choice: 0
45077
45333
  };
45078
45334
  const sourceCounts = { queue: 0, direct: 0 };
45079
45335
  for (const item of activeWork) {
@@ -45108,7 +45364,7 @@ ${rendered}`, "utf-8");
45108
45364
  const queueNodeId = task.assignedNodeId || task.targetNodeId;
45109
45365
  const queueSessionId = task.assignedSessionId || task.targetSessionId;
45110
45366
  const queueLive = task.status === "assigned" ? sessionStatusFromNodes(opts.nodes, queueNodeId ?? void 0, queueSessionId ?? void 0) : {};
45111
- const queueStatus = queueLive.status === "awaiting_approval" || queueLive.status === "generating" ? queueLive.status : task.status;
45367
+ const queueStatus = queueLive.status === "awaiting_approval" || queueLive.status === "awaiting_choice" || queueLive.status === "generating" ? queueLive.status : task.status;
45112
45368
  records.push({
45113
45369
  taskId: task.id,
45114
45370
  source: "queue",
@@ -46104,6 +46360,11 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
46104
46360
  "agent:generating_started",
46105
46361
  "agent:generating_completed",
46106
46362
  "agent:waiting_approval",
46363
+ // A worker parked on an AskUserQuestion multi-choice prompt. DISTINCT from
46364
+ // agent:waiting_approval (a yes/no tool-consent modal): a question is answered
46365
+ // with mesh_answer_question, never mesh_approve (mission f1d25e11). Carries the
46366
+ // full InteractivePrompt payload so the coordinator can render + answer.
46367
+ "agent:waiting_choice",
46107
46368
  "agent:stopped",
46108
46369
  "agent:ready",
46109
46370
  "monitor:no_progress",
@@ -46121,6 +46382,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
46121
46382
  EVENT_TO_LEDGER_KIND = {
46122
46383
  "agent:generating_completed": "task_completed",
46123
46384
  "agent:waiting_approval": "task_approval_needed",
46385
+ "agent:waiting_choice": "task_question_pending",
46124
46386
  "agent:stopped": "task_failed",
46125
46387
  "monitor:no_progress": "task_stalled"
46126
46388
  };
@@ -46128,13 +46390,26 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
46128
46390
  "agent:generating_completed",
46129
46391
  "agent:stopped",
46130
46392
  "agent:waiting_approval",
46393
+ // A worker's question (waiting_choice) is real-time and the coordinator may be
46394
+ // generating when it arrives; force-inject it like approval so the busy coordinator
46395
+ // learns it must answer (mesh_answer_question) rather than the nudge sitting in the
46396
+ // adapter's outbound queue until the coordinator idles on its own (mission f1d25e11).
46397
+ "agent:waiting_choice",
46131
46398
  "refine:completed",
46132
46399
  "refine:failed",
46133
46400
  "worktree_bootstrap_complete",
46134
46401
  "worktree_bootstrap_failed"
46135
46402
  ]);
46136
46403
  MESH_APPROVAL_EVENTS = /* @__PURE__ */ new Set([
46137
- "agent:waiting_approval"
46404
+ "agent:waiting_approval",
46405
+ // agent:waiting_choice (a worker's AskUserQuestion) shares the approval class's
46406
+ // real-time-nudge / level-backed contract: its authoritative state is recorded at
46407
+ // LEVEL the moment it is processed (task_question_pending → mesh_status
46408
+ // awaiting_choice), so the pending event is only a NUDGE and can be delivered to a
46409
+ // busy coordinator's inbox (and dropped) without data loss — the level state
46410
+ // re-derives it. It is therefore exempt from the idle-edge hold completions require,
46411
+ // exactly like an approval nudge (mission f1d25e11).
46412
+ "agent:waiting_choice"
46138
46413
  ]);
46139
46414
  }
46140
46415
  });
@@ -47117,6 +47392,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
47117
47392
  }
47118
47393
  }
47119
47394
  if (!pending.length) return false;
47395
+ const freshnessGate = { maxBehind: resolveAutoFastForwardPolicy(mesh).maxBehind };
47120
47396
  const maxParallelTasks = resolveMaxParallelTasks(mesh?.policy?.maxParallelTasks);
47121
47397
  const maxReadonlyParallelTasks = resolveMaxReadonlyParallelTasks(maxParallelTasks);
47122
47398
  for (const task of pending) {
@@ -47231,6 +47507,10 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
47231
47507
  markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_not_launch_ready", nodeId });
47232
47508
  continue;
47233
47509
  }
47510
+ if (!isMeshNodeFreshEnoughToLaunch(node, freshnessGate)) {
47511
+ markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_stale_behind_upstream", nodeId });
47512
+ continue;
47513
+ }
47234
47514
  const launchTarget = resolveAutoLaunchTarget(components, node);
47235
47515
  if (launchTarget.mode === "skip") {
47236
47516
  markAutoLaunch(meshId, task.id, { status: "skipped", reason: launchTarget.reason || "auto_launch_unavailable", nodeId });
@@ -50964,10 +51244,19 @@ ${cleanBody}`;
50964
51244
  }
50965
51245
  function markSessionTerminal(sessionId, outcome, occurredAtMs, opts) {
50966
51246
  const eventTaskId = readNonEmptyString(args.metadataEvent.taskId) || void 0;
50967
- const task = updateSessionTaskStatus(args.meshId, sessionId, outcome, {
51247
+ const completionDiagnostic = args.metadataEvent.completionDiagnostic && typeof args.metadataEvent.completionDiagnostic === "object" ? args.metadataEvent.completionDiagnostic : void 0;
51248
+ const emittedAfterFinalizationTimeout = completionDiagnostic?.emittedAfterFinalizationTimeout === true;
51249
+ const weakCompleted = outcome === "completed" && isWeakCompletionEvidence(args.metadataEvent) && !emittedAfterFinalizationTimeout;
51250
+ const task = weakCompleted ? updateSessionTaskStatus(args.meshId, sessionId, "assigned", {
51251
+ occurredAt: occurredAtMs != null ? new Date(occurredAtMs).toISOString() : void 0,
51252
+ taskId: eventTaskId
51253
+ }) : updateSessionTaskStatus(args.meshId, sessionId, outcome, {
50968
51254
  occurredAt: occurredAtMs != null ? new Date(occurredAtMs).toISOString() : void 0,
50969
51255
  taskId: eventTaskId
50970
51256
  });
51257
+ if (weakCompleted && task) {
51258
+ LOG2.info("MeshQueue", `Weak completion (${readNonEmptyString(args.metadataEvent.evidenceLevel) || "missing_final_assistant"}) kept queue task ${task.id} tentative (session ${sessionId}); reconcile owns the genuine terminal`);
51259
+ }
50971
51260
  const leaveDirectDispatchActive = !task && opts?.tentativeIfDirect === true || !eventTaskId && !sessionHasActiveAssignment(args.meshId, sessionId);
50972
51261
  if (!leaveDirectDispatchActive) {
50973
51262
  updateDirectDispatchStatus(args.meshId, sessionId, outcome, eventTaskId);
@@ -51424,6 +51713,14 @@ ${cleanBody}`;
51424
51713
  retryOfJobId: readNonEmptyString(payload.retryOfJobId),
51425
51714
  ...relayModalMessage ? { modalMessage: relayModalMessage } : {},
51426
51715
  ...relayModalButtons && relayModalButtons.length > 0 ? { modalButtons: relayModalButtons } : {},
51716
+ // agent:waiting_choice (mission f1d25e11): carry the FULL structured question
51717
+ // payload across the machine boundary so a REMOTE worker's AskUserQuestion reaches
51718
+ // the coordinator with every question + option intact — the coordinator renders
51719
+ // these and answers with mesh_answer_question. The local in-process forward path
51720
+ // preserves the whole event for free; this mirrors the fields for the remote relay.
51721
+ ...payload.interactivePrompt && typeof payload.interactivePrompt === "object" && !Array.isArray(payload.interactivePrompt) ? { interactivePrompt: payload.interactivePrompt } : {},
51722
+ ...readNonEmptyString(payload.promptId) ? { promptId: readNonEmptyString(payload.promptId) } : {},
51723
+ ...payload.multiSelect === true ? { multiSelect: true } : {},
51427
51724
  ...payload.result && typeof payload.result === "object" && !Array.isArray(payload.result) ? { result: payload.result } : {},
51428
51725
  ...payload.completionDiagnostic && typeof payload.completionDiagnostic === "object" && !Array.isArray(payload.completionDiagnostic) ? { completionDiagnostic: payload.completionDiagnostic } : {},
51429
51726
  ...payload.workerResult && typeof payload.workerResult === "object" && !Array.isArray(payload.workerResult) ? { workerResult: payload.workerResult } : {},
@@ -52842,7 +53139,8 @@ ${cleanBody}`;
52842
53139
  function assignedRowLiveStatusIsAwaitingApproval(mesh, nodeId, sessionId) {
52843
53140
  if (!nodeId || !sessionId) return false;
52844
53141
  try {
52845
- return sessionStatusFromNodes(mesh.nodes, nodeId, sessionId).status === "awaiting_approval";
53142
+ const liveStatus = sessionStatusFromNodes(mesh.nodes, nodeId, sessionId).status;
53143
+ return liveStatus === "awaiting_approval" || liveStatus === "awaiting_choice";
52846
53144
  } catch {
52847
53145
  return false;
52848
53146
  }
@@ -55324,8 +55622,15 @@ ${cleanBody}`;
55324
55622
  if (pickApprovalButton(labels).index < 0) return false;
55325
55623
  return hasNegativeApprovalOption(labels);
55326
55624
  }
55625
+ function isAskUserQuestionPickerSignature(text) {
55626
+ if (!text) return false;
55627
+ const hasSelectFooter = /Enter to select/i.test(text) && /Esc to cancel/i.test(text);
55628
+ if (!hasSelectFooter) return false;
55629
+ return /Type something\.?|Chat about this/i.test(text);
55630
+ }
55327
55631
  function modalMatches(spec, input) {
55328
55632
  const text = input.screenText ?? "";
55633
+ if (isAskUserQuestionPickerSignature(text)) return false;
55329
55634
  const question = compile2(spec.questionPattern, spec.questionFlags ?? "i");
55330
55635
  if (question.test(text)) return true;
55331
55636
  for (const variant of spec.questionVariants ?? []) {
@@ -55465,6 +55770,12 @@ ${cleanBody}`;
55465
55770
  throw new Error(`Invalid regex /${re}/${flags ?? ""}: ${e.message}`);
55466
55771
  }
55467
55772
  }
55773
+ function isAskUserQuestionPickerSignature2(text) {
55774
+ if (!text) return false;
55775
+ const hasSelectFooter = /Enter to select/i.test(text) && /Esc to cancel/i.test(text);
55776
+ if (!hasSelectFooter) return false;
55777
+ return /Type something\.?|Chat about this/i.test(text);
55778
+ }
55468
55779
  function findQuestionLineIndex(spec, lines) {
55469
55780
  const primary = compile3(spec.questionPattern, spec.questionFlags ?? "i");
55470
55781
  const buttonFlags = spec.buttonFlags && spec.buttonFlags.includes("m") ? spec.buttonFlags : `${spec.buttonFlags ?? ""}m`;
@@ -55589,6 +55900,7 @@ ${cleanBody}`;
55589
55900
  return function parseApproval(input) {
55590
55901
  const rawText = input.screenText ?? input.buffer ?? "";
55591
55902
  if (!rawText) return null;
55903
+ if (isAskUserQuestionPickerSignature2(rawText)) return null;
55592
55904
  const text = visibleRegion ? applyVisibleRegion(visibleRegion, rawText) : rawText;
55593
55905
  const lines = text.split("\n");
55594
55906
  const question = findQuestionLineIndex(spec, lines);
@@ -60413,6 +60725,57 @@ ${lastSnapshot}`;
60413
60725
  }
60414
60726
  return { promptId, answers };
60415
60727
  }
60728
+ function resolveInteractivePromptResponse(prompt, raw) {
60729
+ if (!raw || typeof raw !== "object") throw new Error("Interactive prompt response must be an object");
60730
+ const record2 = raw;
60731
+ const promptId = readString(record2.promptId);
60732
+ if (!promptId) throw new Error("promptId must be a non-empty string");
60733
+ if (promptId !== prompt.promptId) throw new Error("Interactive prompt response does not match active prompt");
60734
+ if (record2.answers && typeof record2.answers === "object" && !Array.isArray(record2.answers)) {
60735
+ return normalizeInteractivePromptResponse2(record2);
60736
+ }
60737
+ if (!Array.isArray(record2.answers)) throw new Error("answers must be an array or a questionId-keyed object");
60738
+ const resolveOneLabel = (question, sel) => {
60739
+ if (typeof sel === "number" && Number.isFinite(sel)) {
60740
+ const idx = Math.trunc(sel) - 1;
60741
+ const option = question.options[idx];
60742
+ if (!option) throw new Error(`Option index ${sel} out of range for ${question.questionId}`);
60743
+ return option.label;
60744
+ }
60745
+ const label = readString(sel);
60746
+ if (!label) throw new Error(`Empty selection for ${question.questionId}`);
60747
+ const exact = question.options.find((o) => o.label === label);
60748
+ if (exact) return exact.label;
60749
+ const asIndex = Number(label);
60750
+ if (Number.isInteger(asIndex)) {
60751
+ const option = question.options[asIndex - 1];
60752
+ if (option) return option.label;
60753
+ }
60754
+ throw new Error(`Unknown option for ${question.questionId}: ${label}`);
60755
+ };
60756
+ const answers = {};
60757
+ const entries = record2.answers;
60758
+ entries.forEach((entryRaw, index) => {
60759
+ if (!entryRaw || typeof entryRaw !== "object" || Array.isArray(entryRaw)) return;
60760
+ const entry = entryRaw;
60761
+ const questionId = readString(entry.questionId);
60762
+ const question = (questionId ? prompt.questions.find((q) => q.questionId === questionId) : void 0) ?? prompt.questions[index];
60763
+ if (!question) throw new Error(`No matching question for answer entry ${index}`);
60764
+ const freeformText = readString(entry.freeform) ?? readString(entry.freeformText);
60765
+ const selectedLabels = [];
60766
+ const select = entry.select;
60767
+ if (Array.isArray(select)) {
60768
+ for (const sel of select) selectedLabels.push(resolveOneLabel(question, sel));
60769
+ } else if (select !== void 0 && select !== null) {
60770
+ selectedLabels.push(resolveOneLabel(question, select));
60771
+ }
60772
+ answers[question.questionId] = {
60773
+ selectedLabels,
60774
+ ...freeformText ? { freeformText } : {}
60775
+ };
60776
+ });
60777
+ return { promptId, answers };
60778
+ }
60416
60779
  function buildClaudeInteractiveToolResult(response) {
60417
60780
  return JSON.stringify({
60418
60781
  type: "user",
@@ -78593,6 +78956,7 @@ ${body}
78593
78956
  var STATUS_HYDRATION_TAIL_LIMIT = 200;
78594
78957
  var COMPLETED_FINALIZATION_RETRY_MS = 1e3;
78595
78958
  var COMPLETED_FINALIZATION_MAX_WAIT_MS = 3e4;
78959
+ var CANON_C_MISSING_ASSISTANT_MIN_ELAPSED_MS = 2e4;
78596
78960
  var NATIVE_HISTORY_MESH_IDLE_SETTLE_MS = 4e3;
78597
78961
  var PTY_PARSED_FINAL_ASSISTANT_QUIET_DWELL_MS = 1200;
78598
78962
  var ANTIGRAVITY_HOLD_QUIET_DWELL_MS = 3e3;
@@ -79007,10 +79371,12 @@ ${body}
79007
79371
  // `waiting_choice` overlay in getState(); the raw adapter status stays idle/generating,
79008
79372
  // so detectStatusTransition()'s status-keyed arms never fire and no push-worthy
79009
79373
  // agent:* event is emitted — the owner misses the "ACTION REQUIRED" prompt when the
79010
- // app is backgrounded. We emit one agent:waiting_approval on ENTRY into the prompt
79011
- // state (reusing the existing server push path, no cloud change) and dedupe on this
79012
- // key so repeated status ticks with the same prompt do not re-fire. '' means no
79013
- // prompt is currently active (cleared when the prompt is answered/gone).
79374
+ // app is backgrounded. We emit one agent:waiting_choice on ENTRY into the prompt
79375
+ // state (its own coordinator event, NOT the approval channel a multi-choice
79376
+ // question is answered with mesh_answer_question, never mesh_approve) carrying the
79377
+ // FULL InteractivePrompt payload, and dedupe on this key so repeated status ticks
79378
+ // with the same prompt do not re-fire. '' means no prompt is currently active
79379
+ // (cleared when the prompt is answered/gone).
79014
79380
  lastInteractivePromptEventKey = "";
79015
79381
  autoApproveBusy = false;
79016
79382
  autoApproveBusyTimer = null;
@@ -79655,7 +80021,7 @@ ${body}
79655
80021
  }
79656
80022
  } else if (event === "interactive_prompt_response" && data) {
79657
80023
  try {
79658
- const response = normalizeInteractivePromptResponse2(data);
80024
+ const response = this.activeInteractivePrompt && this.activeInteractivePrompt.promptId === data?.promptId && Array.isArray(data?.answers) ? resolveInteractivePromptResponse(this.activeInteractivePrompt, data) : normalizeInteractivePromptResponse2(data);
79659
80025
  if (this.activeInteractivePrompt?.promptId === response.promptId) {
79660
80026
  this.activeInteractivePrompt = null;
79661
80027
  }
@@ -80194,7 +80560,12 @@ ${body}
80194
80560
  return {
80195
80561
  reason: "missing_final_assistant",
80196
80562
  terminal: this.provider.requiresFinalAssistantBeforeIdle === true,
80197
- allowTimeout: allowMissingAssistantTimeout
80563
+ allowTimeout: allowMissingAssistantTimeout,
80564
+ // PTY-parsed provider (codex-cli): no external transcript trails the idle
80565
+ // transition, so the CANON-C decoupled emit must observe the min-elapsed floor
80566
+ // rather than fire at the first-poll waitedMs. (claude-cli's external-native
80567
+ // branch above is exempt — its transcript legitimately lands moments later.)
80568
+ noExternalTranscriptSource: true
80198
80569
  };
80199
80570
  }
80200
80571
  }
@@ -80692,6 +81063,24 @@ ${body}
80692
81063
  this.scheduleCompletedDebounceFlush(COMPLETED_FINALIZATION_RETRY_MS);
80693
81064
  return;
80694
81065
  }
81066
+ if (isTranscriptEvidenceGate && blockReason === "missing_final_assistant" && block2.noExternalTranscriptSource === true && waitedMs < CANON_C_MISSING_ASSISTANT_MIN_ELAPSED_MS) {
81067
+ if (pending.loggedBlockReason !== "canon_c_min_elapsed_floor") {
81068
+ LOG2.info("CLI", `[${this.type}] holding CANON-C decoupled emit until min-elapsed floor (waitedMs=${waitedMs} floor=${CANON_C_MISSING_ASSISTANT_MIN_ELAPSED_MS}); no final assistant yet (${blockReason})`);
81069
+ if (this.isMeshWorkerSession()) {
81070
+ traceMeshEventDrop("completion_gate_hold", this.meshTraceCtx(), `canon_c_min_elapsed_floor waited=${waitedMs}ms`);
81071
+ }
81072
+ if (this.completionTraceOn()) this.recordCompletionGateTrace("hold", {
81073
+ blockReason,
81074
+ latestVisibleStatus,
81075
+ terminal: block2.terminal === true,
81076
+ canonCMinElapsedFloor: true,
81077
+ waitedMs
81078
+ });
81079
+ pending.loggedBlockReason = "canon_c_min_elapsed_floor";
81080
+ }
81081
+ this.scheduleCompletedDebounceFlush(COMPLETED_FINALIZATION_RETRY_MS);
81082
+ return;
81083
+ }
80695
81084
  if (this.type === "antigravity-cli" && block2.holdForTranscript === true && waitedMs < ANTIGRAVITY_HOLD_HARD_CAP_MS && this.antigravityHoldPtyStillActive()) {
80696
81085
  if (pending.loggedBlockReason !== "antigravity_hold_pty_active") {
80697
81086
  LOG2.info("CLI", `[${this.type}] 30s cap reached but PTY still generating; holding antigravity completion past cap (waitedMs=${waitedMs} hardCap=${ANTIGRAVITY_HOLD_HARD_CAP_MS}) (${blockReason})`);
@@ -81391,9 +81780,16 @@ ${buttons.join("\n")}`;
81391
81780
  const modalMessage = firstQuestion ? firstQuestion.header ? `${firstQuestion.header}: ${firstQuestion.question}` : firstQuestion.question : void 0;
81392
81781
  const modalButtons = firstQuestion?.options?.map((option) => option.label);
81393
81782
  this.pushEvent({
81394
- event: "agent:waiting_approval",
81783
+ event: "agent:waiting_choice",
81395
81784
  chatTitle,
81396
81785
  timestamp: now,
81786
+ // Structured, authoritative payload — the coordinator renders these and
81787
+ // answers via mesh_answer_question. Carried whole (all questions, all
81788
+ // options) so multi-question / multi-select prompts round-trip fully.
81789
+ interactivePrompt,
81790
+ promptId: interactivePrompt.promptId,
81791
+ multiSelect: firstQuestion?.multiSelect === true,
81792
+ // Push-notification-friendly projection (server push path reads these).
81397
81793
  modalMessage,
81398
81794
  modalButtons
81399
81795
  });
@@ -90261,6 +90657,50 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
90261
90657
  }
90262
90658
  }
90263
90659
  };
90660
+ init_logger();
90661
+ async function stopCancelledTaskWorker(ctx, meshId, prior) {
90662
+ const { sessionId, nodeId, providerType } = prior;
90663
+ const stopArgs = {
90664
+ targetSessionId: sessionId,
90665
+ ...providerType ? { cliType: providerType } : {},
90666
+ mode: "hard",
90667
+ reason: "mesh_task_cancelled"
90668
+ };
90669
+ try {
90670
+ const cliManager = ctx.deps.cliManager;
90671
+ const isLocal = cliManager?.adapters?.has?.(sessionId) === true;
90672
+ if (isLocal) {
90673
+ if (!stopArgs.cliType) {
90674
+ const localType = cliManager?.adapters?.get?.(sessionId)?.cliType;
90675
+ if (localType) stopArgs.cliType = localType;
90676
+ }
90677
+ await Promise.resolve(cliManager?.handleCliCommand?.("stop_cli", stopArgs)).catch((e) => LOG2.warn("MeshQueue", `Local stop of cancelled worker ${sessionId} failed: ${e?.message || e}`));
90678
+ return;
90679
+ }
90680
+ const dispatch = ctx.deps.dispatchMeshCommand;
90681
+ let daemonId;
90682
+ if (nodeId) {
90683
+ try {
90684
+ const [{ getMesh: getMesh2 }, { meshNodeIdMatches: meshNodeIdMatches2 }, { readMeshNodeDaemonId: readMeshNodeDaemonId2 }] = await Promise.all([
90685
+ Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports)),
90686
+ Promise.resolve().then(() => (init_dist(), dist_exports)),
90687
+ Promise.resolve().then(() => (init_mesh_node_identity(), mesh_node_identity_exports))
90688
+ ]);
90689
+ const mesh = getMesh2(meshId);
90690
+ const node = mesh?.nodes?.find((n) => meshNodeIdMatches2(n, nodeId));
90691
+ daemonId = node ? readMeshNodeDaemonId2(node) || void 0 : void 0;
90692
+ } catch {
90693
+ }
90694
+ }
90695
+ if (daemonId && dispatch) {
90696
+ await Promise.resolve(dispatch(daemonId, "stop_cli", stopArgs)).catch((e) => LOG2.warn("MeshQueue", `Remote stop of cancelled worker ${sessionId} on daemon ${daemonId} failed: ${e?.message || e}`));
90697
+ } else {
90698
+ LOG2.warn("MeshQueue", `Cannot stop cancelled worker ${sessionId}: no local adapter and no resolvable remote daemon id (node ${nodeId ?? "?"}). Row is already terminal; if the worker completes it strand-fails harmlessly.`);
90699
+ }
90700
+ } catch (e) {
90701
+ LOG2.warn("MeshQueue", `stopCancelledTaskWorker error for ${sessionId}: ${e?.message || e}`);
90702
+ }
90703
+ }
90264
90704
  var meshQueueHandlers = {
90265
90705
  get_mesh_queue: async (_ctx, args) => {
90266
90706
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
@@ -90294,10 +90734,14 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
90294
90734
  const ownerFailure = await ctx.requireMeshHostMutationOwner(meshId, args?.inlineMesh, "queue cancellation");
90295
90735
  if (ownerFailure) return ownerFailure;
90296
90736
  try {
90297
- const { cancelTask: cancelTask2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
90737
+ const { cancelTask: cancelTask2, takeCancelledTaskAssignment: takeCancelledTaskAssignment2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
90298
90738
  const reason = typeof args?.reason === "string" ? args.reason : void 0;
90299
90739
  const task = cancelTask2(meshId, taskId, { reason });
90300
90740
  if (!task) return { success: false, error: `Queue task '${taskId}' not found` };
90741
+ const prior = takeCancelledTaskAssignment2(meshId, taskId);
90742
+ if (prior?.sessionId) {
90743
+ void stopCancelledTaskWorker(ctx, meshId, prior);
90744
+ }
90301
90745
  return { success: true, task };
90302
90746
  } catch (e) {
90303
90747
  return { success: false, error: e.message };
@@ -90764,10 +91208,12 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
90764
91208
  interactive_prompt_response: async (ctx, args) => {
90765
91209
  const sessionId = typeof args?.targetSessionId === "string" && args.targetSessionId.trim() ? args.targetSessionId.trim() : typeof args?.sessionId === "string" && args.sessionId.trim() ? args.sessionId.trim() : "";
90766
91210
  if (!sessionId) return { success: false, error: "targetSessionId required" };
90767
- const response = normalizeInteractivePromptResponse2(args?.response ?? args);
91211
+ const rawResponse = args?.response ?? args;
90768
91212
  const instance = ctx.deps.instanceManager.getInstance(sessionId);
90769
91213
  if (!instance) return { success: false, error: `No running instance for session ${sessionId}` };
90770
- ctx.deps.instanceManager.sendEvent(sessionId, "interactive_prompt_response", response);
91214
+ const isFriendlyArrayForm = rawResponse && typeof rawResponse === "object" && Array.isArray(rawResponse.answers);
91215
+ const payload = isFriendlyArrayForm ? rawResponse : normalizeInteractivePromptResponse2(rawResponse);
91216
+ ctx.deps.instanceManager.sendEvent(sessionId, "interactive_prompt_response", payload);
90771
91217
  return { success: true };
90772
91218
  }
90773
91219
  };
@@ -92808,6 +93254,171 @@ ${mergeTreeErr?.stderr || ""}`;
92808
93254
  return isSubmoduleFastForward((0, import_path15.resolve)(repoRoot, path46), baseCommit, branchCommit);
92809
93255
  });
92810
93256
  }
93257
+ function isSubmoduleDivergedSibling(submoduleRepoPath, baseCommit, branchCommit) {
93258
+ if (!baseCommit || !branchCommit || baseCommit === branchCommit) return false;
93259
+ try {
93260
+ if (!fs34.existsSync(submoduleRepoPath)) return false;
93261
+ (0, import_node_child_process6.execFileSync)(GIT2, ["cat-file", "-e", `${baseCommit}^{commit}`], { cwd: submoduleRepoPath, stdio: "ignore" });
93262
+ (0, import_node_child_process6.execFileSync)(GIT2, ["cat-file", "-e", `${branchCommit}^{commit}`], { cwd: submoduleRepoPath, stdio: "ignore" });
93263
+ } catch {
93264
+ return false;
93265
+ }
93266
+ try {
93267
+ (0, import_node_child_process6.execFileSync)(GIT2, ["merge-base", "--is-ancestor", baseCommit, branchCommit], { cwd: submoduleRepoPath, stdio: "ignore" });
93268
+ return false;
93269
+ } catch {
93270
+ }
93271
+ try {
93272
+ (0, import_node_child_process6.execFileSync)(GIT2, ["merge-base", "--is-ancestor", branchCommit, baseCommit], { cwd: submoduleRepoPath, stdio: "ignore" });
93273
+ return false;
93274
+ } catch {
93275
+ }
93276
+ try {
93277
+ const mb = (0, import_node_child_process6.execFileSync)(GIT2, ["merge-base", baseCommit, branchCommit], { cwd: submoduleRepoPath, encoding: "utf8" }).trim();
93278
+ return !!mb;
93279
+ } catch {
93280
+ return false;
93281
+ }
93282
+ }
93283
+ function ensureSubmoduleCommitLocal(submoduleRepoPath, baseSubmoduleRepoPath, commit) {
93284
+ if (!commit) return;
93285
+ try {
93286
+ (0, import_node_child_process6.execFileSync)(GIT2, ["cat-file", "-e", `${commit}^{commit}`], { cwd: submoduleRepoPath, stdio: "ignore" });
93287
+ return;
93288
+ } catch {
93289
+ }
93290
+ try {
93291
+ if (!fs34.existsSync(submoduleRepoPath) || !fs34.existsSync(baseSubmoduleRepoPath)) return;
93292
+ (0, import_node_child_process6.execFileSync)(GIT2, ["-c", "protocol.file.allow=always", "fetch", "-q", baseSubmoduleRepoPath, "+refs/heads/*:refs/adhdev-refine-base/*"], {
93293
+ cwd: submoduleRepoPath,
93294
+ stdio: ["ignore", "ignore", "pipe"]
93295
+ });
93296
+ } catch {
93297
+ }
93298
+ }
93299
+ function convergeDivergedSubmoduleGitlinks(worktreeRoot, baseRepoRoot, baseHead, branchHead) {
93300
+ const changed = readChangedGitlinkPaths(worktreeRoot, baseHead, branchHead);
93301
+ if (changed.length === 0) {
93302
+ return { converged: false, reason: "no_changed_gitlinks", resolutions: [], gitlinks: [] };
93303
+ }
93304
+ const gitlinks = [];
93305
+ const resolutions = [];
93306
+ let sawDiverged = false;
93307
+ for (const path46 of changed) {
93308
+ const baseCommit = readTreeObject(baseRepoRoot, baseHead, path46);
93309
+ const branchCommit = readTreeObject(worktreeRoot, branchHead, path46);
93310
+ const submoduleRepoPath = (0, import_path15.resolve)(worktreeRoot, path46);
93311
+ if (baseCommit) {
93312
+ ensureSubmoduleCommitLocal(submoduleRepoPath, (0, import_path15.resolve)(baseRepoRoot, path46), baseCommit);
93313
+ }
93314
+ if (!baseCommit || !branchCommit || !isSubmoduleDivergedSibling(submoduleRepoPath, baseCommit, branchCommit)) {
93315
+ gitlinks.push({ path: path46, baseCommit, branchCommit, action: "skipped_not_diverged" });
93316
+ continue;
93317
+ }
93318
+ sawDiverged = true;
93319
+ let rebasedCommit;
93320
+ try {
93321
+ (0, import_node_child_process6.execFileSync)(GIT2, ["checkout", "-q", "--detach", branchCommit], { cwd: submoduleRepoPath, stdio: ["ignore", "ignore", "pipe"] });
93322
+ (0, import_node_child_process6.execFileSync)(GIT2, ["rebase", baseCommit], { cwd: submoduleRepoPath, stdio: ["ignore", "pipe", "pipe"] });
93323
+ rebasedCommit = (0, import_node_child_process6.execFileSync)(GIT2, ["rev-parse", "HEAD"], { cwd: submoduleRepoPath, encoding: "utf8" }).trim();
93324
+ } catch {
93325
+ try {
93326
+ (0, import_node_child_process6.execFileSync)(GIT2, ["rebase", "--abort"], { cwd: submoduleRepoPath, stdio: "ignore" });
93327
+ } catch {
93328
+ }
93329
+ try {
93330
+ (0, import_node_child_process6.execFileSync)(GIT2, ["checkout", "-q", "--detach", branchCommit], { cwd: submoduleRepoPath, stdio: "ignore" });
93331
+ } catch {
93332
+ }
93333
+ gitlinks.push({ path: path46, baseCommit, branchCommit, action: "rebase_conflict" });
93334
+ return { converged: false, reason: "rebase_conflict", resolutions: [], gitlinks };
93335
+ }
93336
+ gitlinks.push({ path: path46, baseCommit, branchCommit, rebasedCommit, action: "rebased" });
93337
+ resolutions.push({ path: path46, baseCommit, branchCommit, rebasedCommit });
93338
+ }
93339
+ if (!sawDiverged) {
93340
+ return { converged: false, reason: "not_diverged", resolutions: [], gitlinks };
93341
+ }
93342
+ return { converged: resolutions.length > 0, resolutions, gitlinks };
93343
+ }
93344
+ function rootRebaseResolvingGitlinks(worktreeRoot, baseHead, resolutions) {
93345
+ const resolveByPath = new Map(resolutions.map((r) => [r.path, r.rebasedCommit]));
93346
+ const runRebase = (args) => {
93347
+ try {
93348
+ (0, import_node_child_process6.execFileSync)(GIT2, args, {
93349
+ cwd: worktreeRoot,
93350
+ stdio: ["ignore", "pipe", "pipe"],
93351
+ // A rebase editor prompt would hang; keep it non-interactive.
93352
+ env: { ...process.env, GIT_EDITOR: "true", GIT_SEQUENCE_EDITOR: "true" }
93353
+ });
93354
+ return { ok: true };
93355
+ } catch {
93356
+ return { ok: false };
93357
+ }
93358
+ };
93359
+ const unmergedPaths = () => {
93360
+ try {
93361
+ return (0, import_node_child_process6.execFileSync)(GIT2, ["diff", "--name-only", "--diff-filter=U"], { cwd: worktreeRoot, encoding: "utf8" }).split("\n").map((s2) => s2.trim()).filter(Boolean);
93362
+ } catch {
93363
+ return [];
93364
+ }
93365
+ };
93366
+ const abort = (reason, conflictPaths) => {
93367
+ try {
93368
+ (0, import_node_child_process6.execFileSync)(GIT2, ["rebase", "--abort"], { cwd: worktreeRoot, stdio: "ignore" });
93369
+ } catch {
93370
+ }
93371
+ return { ok: false, reason, conflictPaths };
93372
+ };
93373
+ let progress = runRebase(["rebase", baseHead]);
93374
+ let guard = 0;
93375
+ while (!progress.ok) {
93376
+ if (guard++ > 100) return abort("rebase_error");
93377
+ const conflicts = unmergedPaths();
93378
+ if (conflicts.length === 0) {
93379
+ return abort("rebase_error");
93380
+ }
93381
+ const unresolvable = conflicts.filter((p) => !resolveByPath.has(p));
93382
+ if (unresolvable.length > 0) {
93383
+ const unresolvableGitlink = unresolvable.some((p) => {
93384
+ try {
93385
+ const staged = (0, import_node_child_process6.execFileSync)(GIT2, ["ls-files", "--stage", "--", p], { cwd: worktreeRoot, encoding: "utf8" });
93386
+ return /^160000\s/m.test(staged);
93387
+ } catch {
93388
+ return false;
93389
+ }
93390
+ });
93391
+ const allGitlink = unresolvable.every((p) => {
93392
+ try {
93393
+ const staged = (0, import_node_child_process6.execFileSync)(GIT2, ["ls-files", "--stage", "--", p], { cwd: worktreeRoot, encoding: "utf8" });
93394
+ return /^160000\s/m.test(staged);
93395
+ } catch {
93396
+ return false;
93397
+ }
93398
+ });
93399
+ return abort(allGitlink && unresolvableGitlink ? "unexpected_gitlink" : "non_gitlink_conflict", conflicts);
93400
+ }
93401
+ for (const p of conflicts) {
93402
+ const commit = resolveByPath.get(p);
93403
+ try {
93404
+ (0, import_node_child_process6.execFileSync)(GIT2, ["checkout", "-q", "--detach", commit], { cwd: (0, import_path15.resolve)(worktreeRoot, p), stdio: "ignore" });
93405
+ } catch {
93406
+ }
93407
+ try {
93408
+ (0, import_node_child_process6.execFileSync)(GIT2, ["add", p], { cwd: worktreeRoot, stdio: "ignore" });
93409
+ } catch {
93410
+ return abort("rebase_error", conflicts);
93411
+ }
93412
+ }
93413
+ progress = runRebase(["rebase", "--continue"]);
93414
+ }
93415
+ let branchHead;
93416
+ try {
93417
+ branchHead = (0, import_node_child_process6.execFileSync)(GIT2, ["rev-parse", "HEAD"], { cwd: worktreeRoot, encoding: "utf8" }).trim();
93418
+ } catch {
93419
+ }
93420
+ return { ok: true, branchHead };
93421
+ }
92811
93422
  function evaluateGitlinkTrivialFastForward(repoRoot, baseHead, branchHead) {
92812
93423
  const changedGitlinks = readChangedGitlinkPaths(repoRoot, baseHead, branchHead).map((path46) => {
92813
93424
  const baseCommit = readTreeObject(repoRoot, baseHead, path46);
@@ -93837,6 +94448,7 @@ ${mergeTreeErr?.stderr || ""}`;
93837
94448
  async function refineSyncBaseStage(self, ctx) {
93838
94449
  const { repoRoot, baseHead, node, branch, baseBranch, refineStages, execFileAsync: execFileAsync4 } = ctx;
93839
94450
  let branchHead = ctx.branchHead;
94451
+ let gitlinkResolutions = [];
93840
94452
  const syncStarted = Date.now();
93841
94453
  const divergence = await computeBranchBaseDivergence(execFileAsync4, node.workspace, baseHead, branchHead);
93842
94454
  if (divergence.behind === 0) {
@@ -93852,24 +94464,61 @@ ${mergeTreeErr?.stderr || ""}`;
93852
94464
  const preRebasePe = await runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead);
93853
94465
  const alreadyMerged = !preRebasePe.actualPatchId && !!preRebasePe.expectedPatchId;
93854
94466
  const submoduleConflict = preRebasePe.actionableHint?.kind === "submodule_conflict";
93855
- if (alreadyMerged || submoduleConflict) {
94467
+ if (alreadyMerged) {
93856
94468
  recordMeshRefineStage(refineStages, "sync_base", "passed", syncStarted, {
93857
94469
  ahead: divergence.ahead,
93858
94470
  behind: divergence.behind,
93859
94471
  rebased: false,
93860
- reason: alreadyMerged ? "already_merged_via_other_path_skip_rebase" : "submodule_conflict_defer_to_patch_equivalence"
94472
+ reason: "already_merged_via_other_path_skip_rebase"
93861
94473
  });
93862
94474
  return { kind: "continue", ctx };
93863
94475
  }
94476
+ if (submoduleConflict) {
94477
+ const converge = convergeDivergedSubmoduleGitlinks(node.workspace, repoRoot, baseHead, branchHead);
94478
+ if (converge.converged) {
94479
+ gitlinkResolutions = converge.resolutions;
94480
+ recordMeshRefineStage(refineStages, "submodule_gitlink_converge", "passed", syncStarted, {
94481
+ reason: "submodule_diverged_auto_rebased",
94482
+ gitlinks: converge.gitlinks
94483
+ });
94484
+ LOG2.info("Mesh", `[Refinery] Auto-converged diverged submodule gitlink(s) onto base for node ${node.id}: ` + converge.resolutions.map((r) => `${r.path}\u2192${r.rebasedCommit.slice(0, 12)}`).join(", "));
94485
+ } else {
94486
+ recordMeshRefineStage(refineStages, "submodule_gitlink_converge", "skipped", syncStarted, {
94487
+ reason: "submodule_conflict_defer_to_patch_equivalence",
94488
+ convergeReason: converge.reason,
94489
+ gitlinks: converge.gitlinks
94490
+ });
94491
+ recordMeshRefineStage(refineStages, "sync_base", "passed", syncStarted, {
94492
+ ahead: divergence.ahead,
94493
+ behind: divergence.behind,
94494
+ rebased: false,
94495
+ reason: "submodule_conflict_defer_to_patch_equivalence"
94496
+ });
94497
+ return { kind: "continue", ctx };
94498
+ }
94499
+ }
93864
94500
  } catch {
93865
94501
  }
93866
94502
  const rebaseStarted = Date.now();
93867
94503
  try {
93868
- (0, import_node_child_process7.execFileSync)("git", ["rebase", baseHead], { cwd: node.workspace, stdio: ["ignore", "pipe", "pipe"] });
94504
+ if (gitlinkResolutions.length > 0) {
94505
+ const gitlinkRebase = rootRebaseResolvingGitlinks(node.workspace, baseHead, gitlinkResolutions);
94506
+ if (!gitlinkRebase.ok) {
94507
+ const err = new Error(`gitlink-aware rebase aborted: ${gitlinkRebase.reason || "unknown"}`);
94508
+ err.gitlinkRebaseReason = gitlinkRebase.reason;
94509
+ err.gitlinkRebaseConflicts = gitlinkRebase.conflictPaths;
94510
+ err.alreadyAborted = true;
94511
+ throw err;
94512
+ }
94513
+ } else {
94514
+ (0, import_node_child_process7.execFileSync)("git", ["rebase", baseHead], { cwd: node.workspace, stdio: ["ignore", "pipe", "pipe"] });
94515
+ }
93869
94516
  } catch (rebaseErr) {
93870
- try {
93871
- (0, import_node_child_process7.execFileSync)("git", ["rebase", "--abort"], { cwd: node.workspace, stdio: "ignore" });
93872
- } catch {
94517
+ if (!rebaseErr?.alreadyAborted) {
94518
+ try {
94519
+ (0, import_node_child_process7.execFileSync)("git", ["rebase", "--abort"], { cwd: node.workspace, stdio: "ignore" });
94520
+ } catch {
94521
+ }
93873
94522
  }
93874
94523
  let submoduleHintPatchEquivalence;
93875
94524
  try {
@@ -96176,7 +96825,15 @@ ${e?.stderr || ""}`;
96176
96825
  // returns 'Session not found' (same class as mission 6938892f). Unlike read_terminal this
96177
96826
  // MUTATES the worker PTY, so forwarding to the real owner (not a wrong local session) is
96178
96827
  // doubly important. The daemon re-enforces the destructive-key confirm gate after the forward.
96179
- "send_keys"
96828
+ "send_keys",
96829
+ // interactive_prompt_response (mesh_answer_question, mission f1d25e11): the coordinator
96830
+ // answers a REMOTE worker's AskUserQuestion (waiting_choice). The answer must reach the
96831
+ // OWNING worker session's live instance — its activeInteractivePrompt (the authoritative
96832
+ // prompt the labels/indexes resolve against) and its adapter.setInteractivePromptResponse
96833
+ // live only there. Without forwarding, the coordinator's local high-family handler returns
96834
+ // 'No running instance for session …' and the question is never answered — the exact
96835
+ // remote-worker forwarding gap of mission 6938892f, now closed for questions too.
96836
+ "interactive_prompt_response"
96180
96837
  ]);
96181
96838
  function normalizeCommandSource(source) {
96182
96839
  switch (source) {