@adhdev/daemon-core 0.9.82-rc.354 → 0.9.82-rc.355

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
@@ -316,10 +316,10 @@ function readInjected(value) {
316
316
  }
317
317
  function getDaemonBuildInfo() {
318
318
  if (cached) return cached;
319
- const commit = readInjected(true ? "5d100a177f412ae29a58048f0a211c3928b06910" : void 0) ?? "unknown";
320
- const commitShort = readInjected(true ? "5d100a17" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
321
- const version = readInjected(true ? "0.9.82-rc.354" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
322
- const builtAt = readInjected(true ? "2026-06-22T11:32:05.389Z" : void 0);
319
+ const commit = readInjected(true ? "a45106605e2ae1c10c0bc6cbe48c2cac4e862ded" : void 0) ?? "unknown";
320
+ const commitShort = readInjected(true ? "a4510660" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
321
+ const version = readInjected(true ? "0.9.82-rc.355" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
322
+ const builtAt = readInjected(true ? "2026-06-22T15:21:19.981Z" : void 0);
323
323
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
324
324
  return cached;
325
325
  }
@@ -4827,9 +4827,12 @@ function getActiveDirectDispatches(meshId) {
4827
4827
  return [];
4828
4828
  }
4829
4829
  }
4830
- function updateDirectDispatchStatus(meshId, sessionId, status) {
4830
+ function updateDirectDispatchStatus(meshId, sessionId, status, taskId) {
4831
4831
  try {
4832
- MeshRuntimeStore.getInstance().updateDirectDispatchStatus(meshId, sessionId, status);
4832
+ if (!taskId) {
4833
+ LOG.warn("MeshQueue", `updateDirectDispatchStatus(${status}) for mesh ${meshId} session ${sessionId} has no taskId \u2014 falling back to session_id match (may flip a sibling dispatch row)`);
4834
+ }
4835
+ MeshRuntimeStore.getInstance().updateDirectDispatchStatus(meshId, sessionId, status, taskId);
4833
4836
  } catch {
4834
4837
  }
4835
4838
  }
@@ -5662,9 +5665,25 @@ var init_mesh_runtime_store = __esm({
5662
5665
  updatedAt: r.updated_at
5663
5666
  }));
5664
5667
  }
5665
- updateDirectDispatchStatus(meshId, sessionId, status) {
5666
- if (!sessionId) return;
5668
+ // CANON-B (dispatch identity): mesh_direct_dispatches is keyed by task_id (PK), but a
5669
+ // single session can host several sequential direct dispatches (re-dispatch / nudge), so
5670
+ // matching a status flip by session_id alone hits EVERY non-terminal row for that session
5671
+ // — flipping a sibling task's row and stranding the one whose event actually fired (the
5672
+ // assigned-stranded watchdog then requeues a task that is really still generating). When
5673
+ // the firing event carries a taskId, target the single PK row; the session_id match is the
5674
+ // legacy fallback only for events that arrive without a taskId.
5675
+ updateDirectDispatchStatus(meshId, sessionId, status, taskId) {
5667
5676
  const now = (/* @__PURE__ */ new Date()).toISOString();
5677
+ if (taskId) {
5678
+ this.db.prepare(`
5679
+ UPDATE mesh_direct_dispatches
5680
+ SET status = @status, updated_at = @updatedAt
5681
+ WHERE mesh_id = @meshId AND task_id = @taskId
5682
+ AND status NOT IN ('completed', 'failed')
5683
+ `).run({ status, meshId, taskId, updatedAt: now });
5684
+ return;
5685
+ }
5686
+ if (!sessionId) return;
5668
5687
  this.db.prepare(`
5669
5688
  UPDATE mesh_direct_dispatches
5670
5689
  SET status = @status, updated_at = @updatedAt
@@ -7390,7 +7409,7 @@ function resolveWin32Executable(command) {
7390
7409
  windowsHide: true
7391
7410
  }).trim();
7392
7411
  if (out) {
7393
- const matches = out.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
7412
+ const matches = out.split(/\r?\n/).map((s2) => s2.trim()).filter(Boolean);
7394
7413
  const direct = matches.find((m) => DIRECT_EXEC_EXT.has(path10.extname(m).toLowerCase()));
7395
7414
  return direct || matches[0] || command;
7396
7415
  }
@@ -8742,11 +8761,29 @@ function hasPendingRefineTerminalEventDuplicate(event) {
8742
8761
  (pending) => pending.event === event.event && readRefineJobId2(pending) === jobId
8743
8762
  );
8744
8763
  }
8764
+ function isWeakCompletionMetadata(metadata) {
8765
+ const evidenceLevel = readNonEmptyString2(metadata.evidenceLevel);
8766
+ if (evidenceLevel === "insufficient" || evidenceLevel === "weak") return true;
8767
+ if (metadata.reviewRecommended === true) return true;
8768
+ const diag = readRecord4(metadata.completionDiagnostic);
8769
+ return diag?.finalAssistantPresent === false || diag?.blockReason === "missing_final_assistant";
8770
+ }
8745
8771
  function buildPendingEventFingerprint(event) {
8746
8772
  const metadata = readRecord4(event.metadataEvent) || {};
8747
8773
  if (event.event === "worktree_bootstrap_complete" || event.event === "worktree_bootstrap_failed") {
8748
8774
  return [event.meshId, event.event, event.nodeId || ""].join("::");
8749
8775
  }
8776
+ if (TERMINAL_COMPLETION_EVENTS.has(event.event)) {
8777
+ const terminalTaskId = readNonEmptyString2(metadata.taskId) || readNonEmptyString2(readRecord4(metadata.payload)?.taskId);
8778
+ if (terminalTaskId) {
8779
+ return [
8780
+ event.meshId,
8781
+ event.event,
8782
+ terminalTaskId,
8783
+ isWeakCompletionMetadata(metadata) ? "weak" : "genuine"
8784
+ ].join("::");
8785
+ }
8786
+ }
8750
8787
  const sessionId = resolveEventSessionId(metadata);
8751
8788
  const providerSessionId = readNonEmptyString2(metadata.providerSessionId);
8752
8789
  const taskId = readNonEmptyString2(metadata.taskId) || readNonEmptyString2(readRecord4(metadata.payload)?.taskId);
@@ -9105,7 +9142,7 @@ function clearPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
9105
9142
  }
9106
9143
  }
9107
9144
  }
9108
- var import_fs10, import_path9, import_crypto7, REFINE_TERMINAL_EVENTS, MAX_PENDING_EVENTS_BYTES, MAX_PENDING_EVENTS_KEEP;
9145
+ var import_fs10, import_path9, import_crypto7, REFINE_TERMINAL_EVENTS, TERMINAL_COMPLETION_EVENTS, MAX_PENDING_EVENTS_BYTES, MAX_PENDING_EVENTS_KEEP;
9109
9146
  var init_mesh_events_pending = __esm({
9110
9147
  "src/mesh/mesh-events-pending.ts"() {
9111
9148
  "use strict";
@@ -9118,6 +9155,7 @@ var init_mesh_events_pending = __esm({
9118
9155
  init_mesh_events_utils();
9119
9156
  init_dist();
9120
9157
  REFINE_TERMINAL_EVENTS = /* @__PURE__ */ new Set(["refine:completed", "refine:failed"]);
9158
+ TERMINAL_COMPLETION_EVENTS = /* @__PURE__ */ new Set(["agent:generating_completed", "agent:stopped"]);
9121
9159
  MAX_PENDING_EVENTS_BYTES = 100 * 1024;
9122
9160
  MAX_PENDING_EVENTS_KEEP = 50;
9123
9161
  }
@@ -9447,7 +9485,7 @@ function reconcileDirectDispatchCompletionFromTranscript(args) {
9447
9485
  evidence
9448
9486
  }
9449
9487
  });
9450
- updateDirectDispatchStatus(args.meshId, args.sessionId, kind === "task_completed" ? "completed" : "failed");
9488
+ updateDirectDispatchStatus(args.meshId, args.sessionId, kind === "task_completed" ? "completed" : "failed", args.taskId);
9451
9489
  markSessionDeliveriesTerminal(args.meshId, args.sessionId, kind === "task_completed" ? "completed" : "failed");
9452
9490
  setImmediate(() => cleanupTerminalDirectDispatches());
9453
9491
  queuePendingMeshCoordinatorEvent({
@@ -9737,8 +9775,8 @@ function parsePatternEntry(x) {
9737
9775
  if (x instanceof RegExp) return x;
9738
9776
  if (x && typeof x === "object" && typeof x.source === "string") {
9739
9777
  try {
9740
- const s = x;
9741
- return new RegExp(s.source, s.flags || "");
9778
+ const s2 = x;
9779
+ return new RegExp(s2.source, s2.flags || "");
9742
9780
  } catch {
9743
9781
  return null;
9744
9782
  }
@@ -10309,6 +10347,38 @@ var init_mesh_unresolved_forward_outbox = __esm({
10309
10347
  }
10310
10348
  });
10311
10349
 
10350
+ // src/mesh/mesh-event-trace.ts
10351
+ function s(v) {
10352
+ return typeof v === "string" && v.trim() ? v.trim() : "";
10353
+ }
10354
+ function meshEventTraceKey(ctx) {
10355
+ const segs = [`task=${s(ctx.taskId) || "-"}`];
10356
+ const eventId = s(ctx.eventId);
10357
+ if (eventId) segs.push(`evt=${eventId}`);
10358
+ segs.push(`sess=${s(ctx.sessionId) || "-"}`);
10359
+ const nodeId = s(ctx.nodeId);
10360
+ if (nodeId) segs.push(`node=${nodeId}`);
10361
+ const meshId = s(ctx.meshId);
10362
+ if (meshId) segs.push(`mesh=${meshId}`);
10363
+ const event = s(ctx.event);
10364
+ if (event) segs.push(`event=${event}`);
10365
+ return segs.join(" ");
10366
+ }
10367
+ function traceMeshEventStage(stage, ctx, detail) {
10368
+ LOG.info(CAT, `[stage:${stage}] ${meshEventTraceKey(ctx)}${detail ? ` \u2014 ${detail}` : ""}`);
10369
+ }
10370
+ function traceMeshEventDrop(reason, ctx, detail) {
10371
+ LOG.warn(CAT, `[drop:${reason}] ${meshEventTraceKey(ctx)}${detail ? ` \u2014 ${detail}` : ""}`);
10372
+ }
10373
+ var CAT;
10374
+ var init_mesh_event_trace = __esm({
10375
+ "src/mesh/mesh-event-trace.ts"() {
10376
+ "use strict";
10377
+ init_logger();
10378
+ CAT = "EvtTrace";
10379
+ }
10380
+ });
10381
+
10312
10382
  // src/config/state-store.ts
10313
10383
  function isPlainObject2(value) {
10314
10384
  return !!value && typeof value === "object" && !Array.isArray(value);
@@ -12094,9 +12164,9 @@ function buildAcpSession(state, options) {
12094
12164
  }
12095
12165
  function buildSessionEntries(allStates, cdpManagers, options = {}) {
12096
12166
  const sessions = [];
12097
- const ideStates = allStates.filter((s) => s.category === "ide");
12098
- const cliStates = allStates.filter((s) => s.category === "cli");
12099
- const acpStates = allStates.filter((s) => s.category === "acp");
12167
+ const ideStates = allStates.filter((s2) => s2.category === "ide");
12168
+ const cliStates = allStates.filter((s2) => s2.category === "cli");
12169
+ const acpStates = allStates.filter((s2) => s2.category === "acp");
12100
12170
  for (const state of ideStates) {
12101
12171
  sessions.push(buildWorkspaceSession(state, cdpManagers, options));
12102
12172
  for (const ext of state.extensions) {
@@ -12580,6 +12650,15 @@ function getCachedMeshByWorkspace(workspace) {
12580
12650
  meshByWorkspaceCache.set(workspace, { mesh, cachedAt: now });
12581
12651
  return mesh;
12582
12652
  }
12653
+ function recoverMeshIdByNodeId(nodeId) {
12654
+ if (!nodeId) return "";
12655
+ for (const mesh of listMeshes()) {
12656
+ if (Array.isArray(mesh.nodes) && mesh.nodes.some((n) => meshNodeIdMatches(n, nodeId))) {
12657
+ return readNonEmptyString2(mesh.id);
12658
+ }
12659
+ }
12660
+ return "";
12661
+ }
12583
12662
  function __resetIdleAutoFastForwardForTests() {
12584
12663
  idleAutoFastForwardLastAttempt.clear();
12585
12664
  }
@@ -13482,6 +13561,13 @@ function shouldForceInjectMeshEvent(eventName) {
13482
13561
  function injectMeshSystemMessage(components, args) {
13483
13562
  const eventSessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
13484
13563
  const eventNodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
13564
+ const traceCtx = {
13565
+ taskId: args.metadataEvent.taskId,
13566
+ sessionId: eventSessionId,
13567
+ nodeId: eventNodeId,
13568
+ meshId: args.meshId,
13569
+ event: args.event
13570
+ };
13485
13571
  const sourceSession = args.sourceInstanceId ? components.instanceManager.getInstance(args.sourceInstanceId) : void 0;
13486
13572
  const workerCoordinatorDaemonId = readNonEmptyString2(
13487
13573
  sourceSession?.getState()?.settings?.meshCoordinatorDaemonId
@@ -13535,6 +13621,7 @@ function injectMeshSystemMessage(components, args) {
13535
13621
  }
13536
13622
  }
13537
13623
  LOG.info("MeshEvents", `Suppressed ${args.event} for intentionally cleanup-stopped session ${eventSessionId || "(unknown session)"}`);
13624
+ traceMeshEventDrop("intentional_cleanup_stop", traceCtx);
13538
13625
  return { success: true, forwarded: 0, suppressed: true, intentionalCleanupStop: true };
13539
13626
  }
13540
13627
  if (args.event === "monitor:no_progress") {
@@ -13555,6 +13642,7 @@ function injectMeshSystemMessage(components, args) {
13555
13642
  }
13556
13643
  if (reconciledCompletion?.source === "no_progress_terminal_ledger_suppression") {
13557
13644
  LOG.info("MeshEvents", `Suppressed no-progress monitor because terminal ledger evidence already exists for session ${eventSessionId || "(unknown session)"}`);
13645
+ traceMeshEventDrop("no_progress_terminal_ledger_suppression", traceCtx, `terminalKind=${reconciledCompletion.terminalLedgerKind}`);
13558
13646
  return {
13559
13647
  success: true,
13560
13648
  forwarded: 0,
@@ -13566,6 +13654,7 @@ function injectMeshSystemMessage(components, args) {
13566
13654
  }
13567
13655
  if (isDuplicateRefineTerminalEvent(args.meshId, args.event, args.metadataEvent)) {
13568
13656
  LOG.info("MeshEvents", `Suppressed duplicate ${args.event} for refine job ${readRefineJobId({ metadataEvent: args.metadataEvent })}`);
13657
+ traceMeshEventDrop("duplicate_refine_terminal", traceCtx);
13569
13658
  return { success: true, forwarded: 0, suppressed: true, duplicateRefineTerminalEvent: true };
13570
13659
  }
13571
13660
  const eventTimestamp = readEventTimestamp(args.metadataEvent.timestamp);
@@ -13580,6 +13669,7 @@ function injectMeshSystemMessage(components, args) {
13580
13669
  });
13581
13670
  if (duplicateApproval) {
13582
13671
  LOG.info("MeshEvents", `Suppressed duplicate approval event for mesh ${args.meshId} session ${eventSessionId}`);
13672
+ traceMeshEventDrop("duplicate_approval", traceCtx);
13583
13673
  return { success: true, forwarded: 0, suppressed: true, duplicateApproval: true };
13584
13674
  }
13585
13675
  }
@@ -13599,6 +13689,7 @@ function injectMeshSystemMessage(components, args) {
13599
13689
  const eventFinalSummary = readNonEmptyString2(args.metadataEvent.finalSummary);
13600
13690
  if (terminalProviderSessionId && terminalProviderSessionId === eventProviderSessionId || terminalFinalSummary && terminalFinalSummary === eventFinalSummary || args.metadataEvent.source === "no_progress_reconciliation") {
13601
13691
  LOG.info("MeshEvents", `Suppressed duplicate completion with existing terminal ledger evidence for mesh ${args.meshId} session ${eventSessionId}`);
13692
+ traceMeshEventDrop("duplicate_completion_terminal_ledger", traceCtx);
13602
13693
  return { success: true, forwarded: 0, suppressed: true, duplicateCompletion: true, terminalLedgerEvidence: true };
13603
13694
  }
13604
13695
  }
@@ -13617,6 +13708,7 @@ function injectMeshSystemMessage(components, args) {
13617
13708
  });
13618
13709
  if (duplicateCompletion) {
13619
13710
  LOG.info("MeshEvents", `Suppressed duplicate completion for mesh ${args.meshId} session ${eventSessionId}`);
13711
+ traceMeshEventDrop("duplicate_completion", traceCtx);
13620
13712
  return { success: true, forwarded: 0, suppressed: true, duplicateCompletion: true };
13621
13713
  }
13622
13714
  }
@@ -13635,6 +13727,7 @@ function injectMeshSystemMessage(components, args) {
13635
13727
  });
13636
13728
  if (duplicateStopped) {
13637
13729
  LOG.info("MeshEvents", `Suppressed duplicate stopped event for mesh ${args.meshId} session ${eventSessionId}`);
13730
+ traceMeshEventDrop("duplicate_stopped", traceCtx);
13638
13731
  return { success: true, forwarded: 0, suppressed: true, duplicateStopped: true };
13639
13732
  }
13640
13733
  }
@@ -13646,7 +13739,7 @@ function injectMeshSystemMessage(components, args) {
13646
13739
  });
13647
13740
  const leaveDirectDispatchActive = !task && opts?.tentativeIfDirect === true;
13648
13741
  if (!leaveDirectDispatchActive) {
13649
- updateDirectDispatchStatus(args.meshId, sessionId, outcome);
13742
+ updateDirectDispatchStatus(args.meshId, sessionId, outcome, eventTaskId);
13650
13743
  }
13651
13744
  markSessionDeliveriesTerminal(args.meshId, sessionId, outcome);
13652
13745
  setImmediate(() => cleanupTerminalDirectDispatches());
@@ -13659,7 +13752,7 @@ function injectMeshSystemMessage(components, args) {
13659
13752
  const nodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
13660
13753
  const providerType = readNonEmptyString2(args.metadataEvent.providerType);
13661
13754
  if (sessionId) {
13662
- directDispatchTaskIdForLedger = resolveActiveDirectDispatchTaskId(args.meshId, sessionId);
13755
+ directDispatchTaskIdForLedger = readNonEmptyString2(args.metadataEvent.taskId) || resolveActiveDirectDispatchTaskId(args.meshId, sessionId);
13663
13756
  const isFalseIdle = isFalseIdleCompletion(args.metadataEvent);
13664
13757
  completedTaskForLedger = markSessionTerminal(sessionId, "completed", eventTimestamp, { tentativeIfDirect: isFalseIdle });
13665
13758
  if (nodeId && providerType) {
@@ -13742,7 +13835,8 @@ function injectMeshSystemMessage(components, args) {
13742
13835
  }
13743
13836
  }
13744
13837
  if (sessionId) {
13745
- updateDirectDispatchStatus(args.meshId, sessionId, "acked");
13838
+ const startedTaskId = readNonEmptyString2(args.metadataEvent.taskId) || void 0;
13839
+ updateDirectDispatchStatus(args.meshId, sessionId, "acked", startedTaskId);
13746
13840
  const activeDeliveries = (() => {
13747
13841
  try {
13748
13842
  return MeshRuntimeStore.getInstance().getActiveSessionDeliveries(args.meshId, sessionId);
@@ -13750,7 +13844,8 @@ function injectMeshSystemMessage(components, args) {
13750
13844
  return [];
13751
13845
  }
13752
13846
  })();
13753
- for (const d of activeDeliveries) {
13847
+ const deliveriesToAck = startedTaskId ? activeDeliveries.filter((d) => d.taskId === startedTaskId) : activeDeliveries;
13848
+ for (const d of deliveriesToAck) {
13754
13849
  updateSessionDeliveryStatus(d.id, "acked");
13755
13850
  }
13756
13851
  }
@@ -13764,7 +13859,7 @@ function injectMeshSystemMessage(components, args) {
13764
13859
  }
13765
13860
  }
13766
13861
  if (sessionId) {
13767
- directDispatchTaskIdForLedger = resolveActiveDirectDispatchTaskId(args.meshId, sessionId);
13862
+ directDispatchTaskIdForLedger = readNonEmptyString2(args.metadataEvent.taskId) || resolveActiveDirectDispatchTaskId(args.meshId, sessionId);
13768
13863
  completedTaskForLedger = markSessionTerminal(sessionId, "failed");
13769
13864
  }
13770
13865
  }
@@ -13910,6 +14005,9 @@ function injectMeshSystemMessage(components, args) {
13910
14005
  };
13911
14006
  if (queuePendingMeshCoordinatorEvent(pendingEvent)) {
13912
14007
  LOG.info("MeshEvents", `Queued ${args.event} for coordinator (mesh ${args.meshId}${workerCoordinatorDaemonId ? `, coordinator daemon ${workerCoordinatorDaemonId}` : ""}${workerCoordinatorSessionId ? `, coordinator session ${workerCoordinatorSessionId}` : ""})`);
14008
+ traceMeshEventStage("queued", traceCtx, workerCoordinatorDaemonId ? `coordinatorDaemon=${workerCoordinatorDaemonId}` : "broadcast");
14009
+ } else {
14010
+ traceMeshEventDrop("queue_dedup", traceCtx);
13913
14011
  }
13914
14012
  return { success: true, forwarded: 0 };
13915
14013
  }
@@ -13920,8 +14018,23 @@ function handleMeshForwardEvent(components, payload) {
13920
14018
  }
13921
14019
  const nodeId = readNonEmptyString2(payload.nodeId);
13922
14020
  const workspace = readNonEmptyString2(payload.workspace);
13923
- const meshId = readNonEmptyString2(payload.meshId) || (workspace ? readNonEmptyString2(getCachedMeshByWorkspace(workspace)?.id) : "");
13924
- if (!meshId) return { success: false, error: "meshId required" };
14021
+ const meshId = readNonEmptyString2(payload.meshId) || (workspace ? readNonEmptyString2(getCachedMeshByWorkspace(workspace)?.id) : "") || recoverMeshIdByNodeId(nodeId);
14022
+ if (!meshId) {
14023
+ traceMeshEventDrop("meshId_required", {
14024
+ taskId: payload.taskId,
14025
+ sessionId: readNonEmptyString2(payload.targetSessionId) || readNonEmptyString2(payload.sessionId),
14026
+ nodeId,
14027
+ event: eventName
14028
+ }, workspace ? `workspace=${workspace} unresolved` : "no workspace/nodeId");
14029
+ return { success: false, error: "meshId required" };
14030
+ }
14031
+ traceMeshEventStage("received", {
14032
+ taskId: payload.taskId,
14033
+ sessionId: readNonEmptyString2(payload.targetSessionId) || readNonEmptyString2(payload.sessionId),
14034
+ nodeId,
14035
+ meshId,
14036
+ event: eventName
14037
+ });
13925
14038
  const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
13926
14039
  const relayModalMessage = readNonEmptyString2(payload.modalMessage);
13927
14040
  const relayModalButtons = Array.isArray(payload.modalButtons) ? payload.modalButtons.filter((b) => typeof b === "string" && b.trim().length > 0) : null;
@@ -14002,9 +14115,18 @@ function forwardUnresolvedDelegateEvent(components, routing, event) {
14002
14115
  workspace: readNonEmptyString2(routing.workspace) || readNonEmptyString2(event.workspace) || void 0
14003
14116
  };
14004
14117
  const persisted = enqueueUnresolvedDelegateForward(coordinatorDaemonId, eventName, payload);
14118
+ const fwdTraceCtx = {
14119
+ taskId: payload.taskId,
14120
+ sessionId: readNonEmptyString2(payload.targetSessionId) || readNonEmptyString2(payload.sessionId),
14121
+ nodeId: readNonEmptyString2(routing.nodeId) || readNonEmptyString2(event.meshNodeId),
14122
+ event: eventName
14123
+ };
14124
+ traceMeshEventStage("outbox_enqueue", fwdTraceCtx, `coordinatorDaemon=${coordinatorDaemonId} meshId=absent`);
14125
+ traceMeshEventStage("forward_send", fwdTraceCtx, "immediate push");
14005
14126
  Promise.resolve(components.dispatchMeshCommand(coordinatorDaemonId, "mesh_forward_event", payload)).then((result) => {
14006
14127
  if (result && result.success === false) {
14007
14128
  LOG.warn("MeshEvents", `Immediate forward of ${eventName} to coordinator ${coordinatorDaemonId} rejected (${readNonEmptyString2(result.error) || "no reason"}) \u2014 left queued for retry`);
14129
+ traceMeshEventDrop("immediate_forward_rejected", fwdTraceCtx, readNonEmptyString2(result.error) || "no reason");
14008
14130
  return;
14009
14131
  }
14010
14132
  if (persisted) ackUnresolvedDelegateForwardByFingerprint(coordinatorDaemonId, eventName, payload);
@@ -14072,6 +14194,14 @@ function setupMeshEventForwarding(components) {
14072
14194
  if (isUnroutableDelegateRejection(routing) && forwardUnresolvedDelegateEvent(components, routing, event)) {
14073
14195
  return;
14074
14196
  }
14197
+ if (isUnroutableDelegateRejection(routing)) {
14198
+ traceMeshEventDrop("unroutable", {
14199
+ taskId: event.meshActiveTaskId ?? event.taskId,
14200
+ sessionId: routing.sessionId,
14201
+ nodeId: routing.nodeId,
14202
+ event: event.event
14203
+ }, "no coordinator anchor / mesh_unresolved");
14204
+ }
14075
14205
  recordUnroutableDelegateEvent(routing, event.event);
14076
14206
  return;
14077
14207
  }
@@ -14102,6 +14232,7 @@ var init_mesh_events_coordinator = __esm({
14102
14232
  init_mesh_events_pending();
14103
14233
  init_mesh_routing();
14104
14234
  init_mesh_unresolved_forward_outbox();
14235
+ init_mesh_event_trace();
14105
14236
  init_snapshot();
14106
14237
  init_repo_mesh_types();
14107
14238
  init_dist();
@@ -14213,6 +14344,13 @@ function findLiveCoordinators(components) {
14213
14344
  function injectPendingIntoCoordinator(coordinator, pending) {
14214
14345
  if (!coordinator || !pending.coordinatorMessage) return;
14215
14346
  const force = shouldForceInjectMeshEvent(pending.event);
14347
+ traceMeshEventStage("surfaced", {
14348
+ taskId: pending.metadataEvent?.taskId,
14349
+ sessionId: pending.metadataEvent?.targetSessionId ?? pending.targetCoordinatorSessionId,
14350
+ nodeId: pending.nodeId,
14351
+ meshId: pending.meshId,
14352
+ event: pending.event
14353
+ }, force ? "force-inject" : "inject");
14216
14354
  coordinator.onEvent("send_message", {
14217
14355
  input: { text: pending.coordinatorMessage, textFallback: pending.coordinatorMessage },
14218
14356
  ...force ? { force: true } : {}
@@ -14271,6 +14409,13 @@ function recoverStrandedAssignedDispatches(meshId, store) {
14271
14409
  });
14272
14410
  if (reclaimed) {
14273
14411
  LOG.warn("MeshReconcile", `Reclaimed stranded assigned task ${row.id} on mesh ${meshId} (node=${row.assignedNodeId ?? "?"} session=${row.assignedSessionId ?? "?"}, dispatched ${Math.round((nowMs - dispatchedAtMs) / 1e3)}s ago, never confirmed delivered \u2192 ${reclaimed.status})`);
14412
+ traceMeshEventDrop("assigned_stranded_reclaim", {
14413
+ taskId: row.id,
14414
+ sessionId: row.assignedSessionId,
14415
+ nodeId: row.assignedNodeId,
14416
+ meshId,
14417
+ event: "agent:generating_completed"
14418
+ }, `unconfirmed ${Math.round((nowMs - dispatchedAtMs) / 1e3)}s \u2192 ${reclaimed.status}`);
14274
14419
  }
14275
14420
  }
14276
14421
  }
@@ -14430,6 +14575,13 @@ function holdOrExpireStrictUnmatchedEvent(pending, wantSession, meshId) {
14430
14575
  try {
14431
14576
  queuePendingMeshCoordinatorEvent(pending);
14432
14577
  LOG.info("MeshReconcile", `Strict route hold: coordinator session ${wantSession} not live on mesh ${meshId} \u2014 re-queued (${pending.event})`);
14578
+ traceMeshEventDrop("strict_route_hold", {
14579
+ taskId: pending.metadataEvent?.taskId,
14580
+ sessionId: pending.metadataEvent?.targetSessionId ?? wantSession,
14581
+ nodeId: pending.nodeId,
14582
+ meshId,
14583
+ event: pending.event
14584
+ }, `coordinatorSession=${wantSession} not live`);
14433
14585
  } catch (e) {
14434
14586
  LOG.warn("MeshReconcile", `Strict route re-queue failed for ${pending.event} on mesh ${meshId}: ${e?.message || e}`);
14435
14587
  }
@@ -14453,6 +14605,13 @@ function holdOrExpireStrictUnmatchedEvent(pending, wantSession, meshId) {
14453
14605
  }
14454
14606
  });
14455
14607
  LOG.warn("MeshReconcile", `Strict route expire: coordinator session ${wantSession} never returned for mesh ${meshId} \u2014 recorded to ledger (recoverable), dropped (${pending.event})`);
14608
+ traceMeshEventDrop("strict_route_expired", {
14609
+ taskId: pending.metadataEvent?.taskId,
14610
+ sessionId: pending.metadataEvent?.targetSessionId ?? wantSession,
14611
+ nodeId: pending.nodeId,
14612
+ meshId,
14613
+ event: pending.event
14614
+ }, `coordinatorSession=${wantSession} never returned`);
14456
14615
  } catch (e) {
14457
14616
  LOG.warn("MeshReconcile", `Failed to ledger-expire strict-unmatched ${pending.event} for mesh ${meshId}: ${e?.message || e}`);
14458
14617
  }
@@ -14464,15 +14623,24 @@ async function retryUnresolvedDelegateForwards(components) {
14464
14623
  const entries = peekUnresolvedDelegateForwards();
14465
14624
  if (entries.length === 0) return;
14466
14625
  for (const entry of entries) {
14626
+ const entryTraceCtx = {
14627
+ taskId: entry.payload.taskId,
14628
+ sessionId: readNonEmptyString2(entry.payload.targetSessionId) || readNonEmptyString2(entry.payload.sessionId),
14629
+ nodeId: readNonEmptyString2(entry.payload.nodeId),
14630
+ event: readNonEmptyString2(entry.payload.event)
14631
+ };
14467
14632
  let result;
14468
14633
  try {
14634
+ traceMeshEventStage("forward_send", entryTraceCtx, `retry \u2192 ${entry.coordinatorDaemonId}`);
14469
14635
  result = await dispatchMeshCommand(entry.coordinatorDaemonId, "mesh_forward_event", entry.payload);
14470
14636
  } catch (e) {
14471
14637
  LOG.warn("MeshReconcile", `Retry forward to coordinator ${entry.coordinatorDaemonId} failed: ${e?.message || e} \u2014 left queued`);
14638
+ traceMeshEventDrop("retry_forward_failed", entryTraceCtx, e?.message || String(e));
14472
14639
  continue;
14473
14640
  }
14474
14641
  if (result && result.success === false) {
14475
14642
  LOG.warn("MeshReconcile", `Retry forward to coordinator ${entry.coordinatorDaemonId} rejected (${readNonEmptyString2(result.error) || "no reason"}) \u2014 left queued`);
14643
+ traceMeshEventDrop("retry_forward_rejected", entryTraceCtx, readNonEmptyString2(result.error) || "no reason");
14476
14644
  continue;
14477
14645
  }
14478
14646
  ackUnresolvedDelegateForward(entry.id);
@@ -14714,6 +14882,7 @@ var init_mesh_reconcile_loop = __esm({
14714
14882
  init_mesh_events_coordinator();
14715
14883
  init_mesh_unresolved_forward_outbox();
14716
14884
  init_mesh_events_utils();
14885
+ init_mesh_event_trace();
14717
14886
  init_dist();
14718
14887
  init_mesh_work_queue();
14719
14888
  init_mesh_ledger();
@@ -15549,8 +15718,8 @@ function saveProvidersActive(file) {
15549
15718
  }
15550
15719
  function isValidSource(x) {
15551
15720
  if (!x || typeof x !== "object") return false;
15552
- const s = x;
15553
- return typeof s.name === "string" && s.name.length > 0 && typeof s.url === "string" && s.url.length > 0 && typeof s.ref === "string" && s.ref.length > 0 && typeof s.addedAt === "string";
15721
+ const s2 = x;
15722
+ return typeof s2.name === "string" && s2.name.length > 0 && typeof s2.url === "string" && s2.url.length > 0 && typeof s2.ref === "string" && s2.ref.length > 0 && typeof s2.addedAt === "string";
15554
15723
  }
15555
15724
  function deriveSourceName(url) {
15556
15725
  const m = url.match(/[/:]([^/:]+)\/([^/]+?)(?:\.git)?$/);
@@ -15606,7 +15775,7 @@ function inventoryExternalSources() {
15606
15775
  }
15607
15776
  function sourcesProviding(category, type) {
15608
15777
  const inventory = inventoryExternalSources();
15609
- return inventory.filter((s) => (s.providers[category] || []).includes(type)).map((s) => s.sourceName);
15778
+ return inventory.filter((s2) => (s2.providers[category] || []).includes(type)).map((s2) => s2.sourceName);
15610
15779
  }
15611
15780
  function resolveActiveSource(category, type, activeFile) {
15612
15781
  const candidates = sourcesProviding(category, type);
@@ -15813,10 +15982,10 @@ function compileSettledPromptMatchers(spec) {
15813
15982
  const footers = (spec.withFooter ?? []).map((f) => {
15814
15983
  if (f.kind === "regex") {
15815
15984
  const re = compile2(f.pattern, f.flags ?? "i");
15816
- return { test: (s) => re.test(s) };
15985
+ return { test: (s2) => re.test(s2) };
15817
15986
  }
15818
15987
  const needle = f.pattern.toLowerCase();
15819
- return { test: (s) => s.toLowerCase().includes(needle) };
15988
+ return { test: (s2) => s2.toLowerCase().includes(needle) };
15820
15989
  });
15821
15990
  return { prompt, footers };
15822
15991
  }
@@ -16690,7 +16859,7 @@ var init_cli_state_engine = __esm({
16690
16859
  }
16691
16860
  resolveModal(buttonIndex) {
16692
16861
  const snap = this.transport.getSnapshot();
16693
- const parseApproval = typeof this.transport.runParseApproval === "function" ? (s) => this.transport.runParseApproval(s.recentOutputBuffer.slice(-500)) : (s) => this.runParseApproval(s);
16862
+ const parseApproval = typeof this.transport.runParseApproval === "function" ? (s2) => this.transport.runParseApproval(s2.recentOutputBuffer.slice(-500)) : (s2) => this.runParseApproval(s2);
16694
16863
  let modal = this.activeModal ?? parseApproval(snap);
16695
16864
  if (!modal && this.runner.hasParseSession()) {
16696
16865
  try {
@@ -19379,22 +19548,23 @@ function resolveSections(sectionsObj, lines) {
19379
19548
  const matchesCandidate = (c, i) => c.re.test(lines[i]) && (c.prevRe === null || i > 0 && c.prevRe.test(lines[i - 1])) && (c.nextRe === null || i < total - 1 && c.nextRe.test(lines[i + 1]));
19380
19549
  let idx = -1;
19381
19550
  for (const c of candidates) {
19551
+ let candIdx = -1;
19382
19552
  if (sec.anchor_last) {
19383
19553
  for (let i = total - 1; i >= 0; i--) {
19384
19554
  if (matchesCandidate(c, i)) {
19385
- idx = i;
19555
+ candIdx = i;
19386
19556
  break;
19387
19557
  }
19388
19558
  }
19389
19559
  } else {
19390
19560
  for (let i = 0; i < total; i++) {
19391
19561
  if (matchesCandidate(c, i)) {
19392
- idx = i;
19562
+ candIdx = i;
19393
19563
  break;
19394
19564
  }
19395
19565
  }
19396
19566
  }
19397
- if (idx !== -1) break;
19567
+ if (candIdx !== -1 && (idx === -1 || candIdx < idx)) idx = candIdx;
19398
19568
  }
19399
19569
  if (idx !== -1) {
19400
19570
  from = idx;
@@ -19446,7 +19616,7 @@ function resolveSections(sectionsObj, lines) {
19446
19616
  }
19447
19617
  function sectionText(sections, sectionId, fullScreen) {
19448
19618
  if (!sectionId) return fullScreen;
19449
- const found = sections.find((s) => s.id === sectionId);
19619
+ const found = sections.find((s2) => s2.id === sectionId);
19450
19620
  return found ? found.text : "";
19451
19621
  }
19452
19622
  function isRegexCondition(c) {
@@ -19614,10 +19784,10 @@ function isV4Spec(raw) {
19614
19784
  return !!raw && typeof raw === "object" && raw.$schema === "adhdev:cli/spec@4";
19615
19785
  }
19616
19786
  function initialState(spec) {
19617
- return spec.states.find((s) => s.initial) ?? spec.states[0];
19787
+ return spec.states.find((s2) => s2.initial) ?? spec.states[0];
19618
19788
  }
19619
19789
  function stateById(spec, id) {
19620
- return spec.states.find((s) => s.id === id);
19790
+ return spec.states.find((s2) => s2.id === id);
19621
19791
  }
19622
19792
  function outgoingTransitions(spec, stateId) {
19623
19793
  const matches = spec.transitions.filter((t) => {
@@ -19706,7 +19876,17 @@ function evalCond(cond, sections, fullScreen, cursor, prevLines, clock, legacyTr
19706
19876
  const result = evaluateCondition(cond, sections, fullScreen, cursor, prevLines, legacyTrace, stateId);
19707
19877
  const kind = isRegex(cond) ? "regex" : "changed";
19708
19878
  const detail = isRegex(cond) ? `${cond.section ?? "*"}~/${cond.matches}/` : `cursor_above=${cond.cursor_above} changed=${cond.changed}`;
19709
- return { kind, result, detail };
19879
+ let matchedText;
19880
+ if (result && isRegex(cond)) {
19881
+ try {
19882
+ const hay = sectionText(sections, cond.section, fullScreen);
19883
+ const re = new RegExp(cond.matches, cond.flags ?? "i");
19884
+ const m = re.exec(hay);
19885
+ if (m && m[0]) matchedText = m[0].replace(/\s+/g, " ").trim().slice(0, 160);
19886
+ } catch {
19887
+ }
19888
+ }
19889
+ return matchedText ? { kind, result, detail, matchedText } : { kind, result, detail };
19710
19890
  }
19711
19891
  return { kind: "all", result: false, detail: "unknown condition" };
19712
19892
  }
@@ -19821,17 +20001,17 @@ function validateFsmSpec(raw) {
19821
20001
  }
19822
20002
  const ids = /* @__PURE__ */ new Set();
19823
20003
  let initialCount = 0;
19824
- for (const [i, s] of spec.states.entries()) {
19825
- if (!s.id) {
20004
+ for (const [i, s2] of spec.states.entries()) {
20005
+ if (!s2.id) {
19826
20006
  errs.push(`states[${i}].id is required`);
19827
20007
  continue;
19828
20008
  }
19829
- if (ids.has(s.id)) errs.push(`states[${i}].id "${s.id}" is duplicated`);
19830
- ids.add(s.id);
19831
- if (!s.label) errs.push(`states[${i}].label is required`);
19832
- if (s.initial) initialCount += 1;
19833
- if (s.status && !["idle", "generating", "approval"].includes(s.status)) {
19834
- errs.push(`states[${i}].status "${s.status}" must be idle|generating|approval`);
20009
+ if (ids.has(s2.id)) errs.push(`states[${i}].id "${s2.id}" is duplicated`);
20010
+ ids.add(s2.id);
20011
+ if (!s2.label) errs.push(`states[${i}].label is required`);
20012
+ if (s2.initial) initialCount += 1;
20013
+ if (s2.status && !["idle", "generating", "approval"].includes(s2.status)) {
20014
+ errs.push(`states[${i}].status "${s2.status}" must be idle|generating|approval`);
19835
20015
  }
19836
20016
  }
19837
20017
  if (initialCount === 0) errs.push("exactly one state must have initial:true (none found)");
@@ -19847,10 +20027,10 @@ function validateFsmSpec(raw) {
19847
20027
  else if (!ids.has(t.to)) errs.push(`transitions[${i}].to references unknown state "${t.to}"`);
19848
20028
  if (t.when) errs.push(...validateCondition(t.when, sectionIds, `transitions[${i}].when`));
19849
20029
  }
19850
- for (const [i, s] of spec.states.entries()) {
19851
- const sec = s.extract?.title?.section;
20030
+ for (const [i, s2] of spec.states.entries()) {
20031
+ const sec = s2.extract?.title?.section;
19852
20032
  if (sec && !sectionIds.has(sec)) errs.push(`states[${i}].extract.title.section "${sec}" unknown`);
19853
- const bsec = s.extract?.buttons?.section;
20033
+ const bsec = s2.extract?.buttons?.section;
19854
20034
  if (bsec && !sectionIds.has(bsec)) errs.push(`states[${i}].extract.buttons.section "${bsec}" unknown`);
19855
20035
  }
19856
20036
  return errs;
@@ -32586,10 +32766,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
32586
32766
  const path42 = require("path");
32587
32767
  const { spawnSync: spawnSync2 } = require("child_process");
32588
32768
  const file = ext.loadExternalSources();
32589
- if (file.sources.some((s) => s.name === requestedName)) {
32769
+ if (file.sources.some((s2) => s2.name === requestedName)) {
32590
32770
  return { success: false, error: `source name "${requestedName}" is already registered` };
32591
32771
  }
32592
- if (file.sources.some((s) => s.url === url && s.ref === ref)) {
32772
+ if (file.sources.some((s2) => s2.url === url && s2.ref === ref)) {
32593
32773
  return { success: false, error: `source url+ref already registered (use a different name to track another ref)` };
32594
32774
  }
32595
32775
  const sourceDir = path42.join(ext.externalRoot(), requestedName);
@@ -32651,7 +32831,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
32651
32831
  const fs32 = require("fs");
32652
32832
  const path42 = require("path");
32653
32833
  const file = ext.loadExternalSources();
32654
- const match = file.sources.find((s) => s.name === name);
32834
+ const match = file.sources.find((s2) => s2.name === name);
32655
32835
  if (!match) return { success: false, error: `source "${name}" not registered` };
32656
32836
  const sourceDir = path42.join(ext.externalRoot(), name);
32657
32837
  if (fs32.existsSync(sourceDir)) {
@@ -32663,7 +32843,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
32663
32843
  }
32664
32844
  ext.saveExternalSources({
32665
32845
  schema: 1,
32666
- sources: file.sources.filter((s) => s.name !== name)
32846
+ sources: file.sources.filter((s2) => s2.name !== name)
32667
32847
  });
32668
32848
  const active = ext.loadProvidersActive();
32669
32849
  const filteredActive = {};
@@ -32687,10 +32867,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
32687
32867
  const file = ext.loadExternalSources();
32688
32868
  const inventory = ext.inventoryExternalSources();
32689
32869
  const active = ext.loadProvidersActive();
32690
- const sources = file.sources.map((s) => {
32691
- const inv = inventory.find((e) => e.sourceName === s.name);
32870
+ const sources = file.sources.map((s2) => {
32871
+ const inv = inventory.find((e) => e.sourceName === s2.name);
32692
32872
  return {
32693
- ...s,
32873
+ ...s2,
32694
32874
  providers: inv?.providers ?? {}
32695
32875
  };
32696
32876
  });
@@ -32867,6 +33047,21 @@ var path21 = __toESM(require("path"));
32867
33047
  // src/providers/spec/adapter.ts
32868
33048
  init_terminal_screen();
32869
33049
  var import_session_host_core6 = require("@adhdev/session-host-core");
33050
+ var MAX_PTY_EVENTS = 300;
33051
+ var EVENT_CONTENT_CAP = 240;
33052
+ function escapeControl(text) {
33053
+ return String(text).replace(/[\x00-\x1f\x7f]/g, (ch) => {
33054
+ const code = ch.charCodeAt(0);
33055
+ if (ch === "\r") return "\\r";
33056
+ if (ch === "\n") return "\\n";
33057
+ if (ch === " ") return "\\t";
33058
+ if (code === 27) return "\\x1b";
33059
+ return "\\x" + code.toString(16).padStart(2, "0");
33060
+ });
33061
+ }
33062
+ function capPreview(text) {
33063
+ return text.length > EVENT_CONTENT_CAP ? text.slice(0, EVENT_CONTENT_CAP) + `\u2026(+${text.length - EVENT_CONTENT_CAP})` : text;
33064
+ }
32870
33065
  var TerminalAdapter = class {
32871
33066
  constructor(opts, handlers) {
32872
33067
  this.opts = opts;
@@ -32893,6 +33088,9 @@ var TerminalAdapter = class {
32893
33088
  screenTimer = null;
32894
33089
  tickTimer = null;
32895
33090
  lastScreen = "";
33091
+ /** Debug-only ring buffer of PTY input/output/resize/cursor events. */
33092
+ events = [];
33093
+ lastCursorKey = "";
32896
33094
  start() {
32897
33095
  const env = this.opts.envIsComplete ? this.opts.env ?? {} : { ...process.env, ...this.opts.env ?? {} };
32898
33096
  this.pty = this.factory.spawn(this.opts.binary, this.opts.args ?? [], {
@@ -32901,10 +33099,12 @@ var TerminalAdapter = class {
32901
33099
  cols: this.cols,
32902
33100
  rows: this.rows
32903
33101
  });
33102
+ this.recordEvent("spawn", `${this.opts.binary} (${this.cols}x${this.rows})`);
32904
33103
  this.handlers.init?.({ pid: this.pty.pid });
32905
33104
  this.pty.onData((chunk) => this.onChunk(chunk));
32906
33105
  this.pty.onExit((info) => {
32907
33106
  this.stopTimers();
33107
+ this.recordEvent("exit", `exitCode=${typeof info.exitCode === "number" ? info.exitCode : 0}`);
32908
33108
  this.handlers.on_exit?.({ exitCode: typeof info.exitCode === "number" ? info.exitCode : 0 });
32909
33109
  this.pty = null;
32910
33110
  });
@@ -32915,6 +33115,7 @@ var TerminalAdapter = class {
32915
33115
  resize(cols, rows) {
32916
33116
  this.cols = cols;
32917
33117
  this.rows = rows;
33118
+ this.recordEvent("resize", `${cols}x${rows}`);
32918
33119
  this.pty?.resize(cols, rows);
32919
33120
  this.screen.resize(rows, cols);
32920
33121
  }
@@ -32935,8 +33136,21 @@ var TerminalAdapter = class {
32935
33136
  return { row: pos.row, col: pos.col };
32936
33137
  }
32937
33138
  send_keys(text) {
33139
+ this.recordEvent("input", capPreview(escapeControl(text)), text.length);
32938
33140
  this.pty?.write(text);
32939
33141
  }
33142
+ /** Debug-only: most-recent PTY input/output/resize/cursor events, oldest
33143
+ * first. Pure observation — never consulted by the FSM. */
33144
+ getEventTimeline(limit = MAX_PTY_EVENTS) {
33145
+ const n = Math.max(0, Math.min(limit, this.events.length));
33146
+ return this.events.slice(this.events.length - n);
33147
+ }
33148
+ recordEvent(kind, content, bytes) {
33149
+ const ev = { ts: Date.now(), kind, content };
33150
+ if (typeof bytes === "number") ev.bytes = bytes;
33151
+ this.events.push(ev);
33152
+ if (this.events.length > MAX_PTY_EVENTS) this.events.splice(0, this.events.length - MAX_PTY_EVENTS);
33153
+ }
32940
33154
  kill() {
32941
33155
  this.stopTimers();
32942
33156
  try {
@@ -32947,6 +33161,7 @@ var TerminalAdapter = class {
32947
33161
  this.screen.dispose();
32948
33162
  }
32949
33163
  onChunk(chunk) {
33164
+ this.recordEvent("output", capPreview(escapeControl(chunk)), chunk.length);
32950
33165
  try {
32951
33166
  this.handlers.on_pty_data?.(chunk);
32952
33167
  } catch {
@@ -32956,6 +33171,12 @@ var TerminalAdapter = class {
32956
33171
  this.screenTimer = setTimeout(() => {
32957
33172
  this.screenTimer = null;
32958
33173
  const snap = this.computeScreen();
33174
+ const cur = this.screen.getCursorPosition();
33175
+ const curKey = `${cur.row},${cur.col}`;
33176
+ if (curKey !== this.lastCursorKey) {
33177
+ this.lastCursorKey = curKey;
33178
+ this.recordEvent("cursor", `(${cur.row},${cur.col})`);
33179
+ }
32959
33180
  if (snap === this.lastScreen) return;
32960
33181
  this.lastScreen = snap;
32961
33182
  try {
@@ -33040,20 +33261,40 @@ function applyPreLaunchTrust(trust, workingDir) {
33040
33261
 
33041
33262
  // src/providers/spec/fsm-driver.ts
33042
33263
  init_logger();
33043
- function countNewlines(s) {
33264
+ function countNewlines(s2) {
33044
33265
  let n = 0;
33045
- for (let i = 0; i < s.length; i += 1) if (s.charCodeAt(i) === 10) n += 1;
33266
+ for (let i = 0; i < s2.length; i += 1) if (s2.charCodeAt(i) === 10) n += 1;
33046
33267
  return n;
33047
33268
  }
33048
33269
  var SUBMIT_DELAY_FLOOR_MS = 200;
33049
33270
  var WIN32_SUBMIT_RESEND_GAP_MS = 350;
33050
33271
  var WIN32_SUBMIT_MAX_RESENDS = 14;
33272
+ var WIN32_SUBMIT_SETTLE_MS = 500;
33273
+ var WIN32_SUBMIT_MAX_SETTLE_WAIT_MS = 1e4;
33274
+ var WIN32_SUBMIT_SETTLE_POLL_MS = 120;
33275
+ var WIN32_PTY_WRITE_CHUNK_CHARS = 1024;
33276
+ var WIN32_PTY_WRITE_CHUNK_GAP_MS = 8;
33051
33277
  function resolveSubmitDelayMs(specBeforeSubmit, text) {
33052
33278
  const lines = countNewlines(text);
33053
33279
  const linesBonus = Math.min(800, lines * 80);
33054
33280
  const spec = typeof specBeforeSubmit === "number" && specBeforeSubmit > 0 ? specBeforeSubmit : 0;
33055
33281
  return Math.max(spec, SUBMIT_DELAY_FLOOR_MS + linesBonus);
33056
33282
  }
33283
+ function chunkPreservingSurrogates(text, size) {
33284
+ const chunks = [];
33285
+ let offset = 0;
33286
+ while (offset < text.length) {
33287
+ let end = Math.min(text.length, offset + size);
33288
+ if (end < text.length) {
33289
+ const code = text.charCodeAt(end - 1);
33290
+ if (code >= 55296 && code <= 56319) end -= 1;
33291
+ }
33292
+ if (end <= offset) end = Math.min(text.length, offset + size);
33293
+ chunks.push(text.slice(offset, end));
33294
+ offset = end;
33295
+ }
33296
+ return chunks;
33297
+ }
33057
33298
  function guessExt(mime) {
33058
33299
  if (/png/i.test(mime)) return ".png";
33059
33300
  if (/jpe?g/i.test(mime)) return ".jpg";
@@ -33069,7 +33310,10 @@ var FsmDriver = class {
33069
33310
  this.buildAdapterOpts(),
33070
33311
  {
33071
33312
  init: () => this.emitInitialState(),
33072
- on_pty_data: (chunk) => this.emit({ kind: "pty_data", chunk }),
33313
+ on_pty_data: (chunk) => {
33314
+ this.lastPtyDataAt = Date.now();
33315
+ this.emit({ kind: "pty_data", chunk });
33316
+ },
33073
33317
  on_screen_changed: () => this.reevaluate(),
33074
33318
  on_exit: ({ exitCode }) => this.handleExit(exitCode)
33075
33319
  }
@@ -33103,6 +33347,16 @@ var FsmDriver = class {
33103
33347
  * WIN32_SUBMIT_* and scheduleWin32Submit). Re-arms itself until the FSM
33104
33348
  * leaves idle (submitted) or the resend budget is spent. */
33105
33349
  win32SubmitTimer = null;
33350
+ /** Wall-clock (ms) of the most recent raw PTY output chunk. Advances on every
33351
+ * on_pty_data — including the echo of text written into the composer — so the
33352
+ * win32 submit settle-gate can tell when input has finished landing. */
33353
+ lastPtyDataAt = 0;
33354
+ /** Wall-clock (ms) of the most recent win32 message-body input write. Bridges
33355
+ * the gap between writing a chunk and its echo so the settle-gate does not
33356
+ * declare "quiet" mid-write. */
33357
+ lastWin32WriteAt = 0;
33358
+ /** Pending paced chunk-write timer for a large win32 body (see writeWin32Body). */
33359
+ win32WriteTimer = null;
33106
33360
  currentEval = null;
33107
33361
  stateHistory = [];
33108
33362
  prevStateAt = 0;
@@ -33223,6 +33477,10 @@ var FsmDriver = class {
33223
33477
  clearTimeout(this.win32SubmitTimer);
33224
33478
  this.win32SubmitTimer = null;
33225
33479
  }
33480
+ if (this.win32WriteTimer) {
33481
+ clearTimeout(this.win32WriteTimer);
33482
+ this.win32WriteTimer = null;
33483
+ }
33226
33484
  this.specWatcher?.close();
33227
33485
  this.adapter.kill();
33228
33486
  }
@@ -33253,11 +33511,15 @@ var FsmDriver = class {
33253
33511
  getFsmSnapshotHistory() {
33254
33512
  return this.fsmSnapshotHistory;
33255
33513
  }
33514
+ /** Debug-only PTY input/output/resize/cursor timeline from the adapter. */
33515
+ getEventTimeline(limit) {
33516
+ return this.adapter.getEventTimeline(limit);
33517
+ }
33256
33518
  getSections() {
33257
33519
  try {
33258
33520
  const screen = this.adapter.snapshot();
33259
33521
  const lines = screen.split("\n").map((l) => l.endsWith("\r") ? l.slice(0, -1) : l);
33260
- return resolveSections(this.spec.sections ?? {}, lines).map((s) => ({ id: s.id, text: s.text }));
33522
+ return resolveSections(this.spec.sections ?? {}, lines).map((s2) => ({ id: s2.id, text: s2.text }));
33261
33523
  } catch {
33262
33524
  return null;
33263
33525
  }
@@ -33635,7 +33897,7 @@ var FsmDriver = class {
33635
33897
  const perChar = sm.delay_ms_per_char ?? 0;
33636
33898
  const beforeSubmit = resolveSubmitDelayMs(sm.delay_ms_before_submit, text);
33637
33899
  if (process.platform === "win32") {
33638
- this.adapter.send_keys(text);
33900
+ this.writeWin32Body(text);
33639
33901
  this.scheduleWin32Submit(sm.submit_key, beforeSubmit);
33640
33902
  return;
33641
33903
  }
@@ -33661,20 +33923,72 @@ var FsmDriver = class {
33661
33923
  const st = stateById(this.spec, this.currentStateId);
33662
33924
  return st ? statusForState(st) : "idle";
33663
33925
  }
33926
+ /** Record a win32 body write so the settle-gate counts it as input activity
33927
+ * even before the echo arrives. */
33928
+ markWin32Write() {
33929
+ this.lastWin32WriteAt = Date.now();
33930
+ }
33931
+ /** Most recent win32 input activity — a write we issued OR a PTY output chunk
33932
+ * (echo). The submit settle-gate waits for this to go quiet. */
33933
+ lastWin32InputActivityAt() {
33934
+ return Math.max(this.lastPtyDataAt, this.lastWin32WriteAt);
33935
+ }
33664
33936
  /**
33665
- * win32 verification-based submit. Sends the submit key, waits a gap, and if
33666
- * the FSM is still 'idle' (the prompt did not submit — the CR was absorbed as
33667
- * a multiline-paste newline) resends, up to WIN32_SUBMIT_MAX_RESENDS. The
33668
- * first CR always fires (so a stale/edge status never suppresses the submit);
33669
- * subsequent resends are gated on still being idle, and stop the instant the
33670
- * agent leaves idle (submitted generating / approval). This converges the
33671
- * nondeterministic multiline window without spamming Enter into the next turn.
33937
+ * Write the message body to the PTY for win32, paced into bounded chunks. A
33938
+ * single unbounded ConPTY write can overflow the input pipe and drop leading
33939
+ * bytes; splitting it with a short inter-chunk gap keeps the console input
33940
+ * buffer from overflowing. Small bodies still go out in a single write. Each
33941
+ * chunk advances lastWin32WriteAt so the submit settle-gate keeps waiting until
33942
+ * the final chunk is out and echoed.
33943
+ */
33944
+ writeWin32Body(text) {
33945
+ if (this.win32WriteTimer) {
33946
+ clearTimeout(this.win32WriteTimer);
33947
+ this.win32WriteTimer = null;
33948
+ }
33949
+ if (text.length <= WIN32_PTY_WRITE_CHUNK_CHARS) {
33950
+ this.markWin32Write();
33951
+ this.adapter.send_keys(text);
33952
+ return;
33953
+ }
33954
+ const chunks = chunkPreservingSurrogates(text, WIN32_PTY_WRITE_CHUNK_CHARS);
33955
+ let idx = 0;
33956
+ const writeNext = () => {
33957
+ this.win32WriteTimer = null;
33958
+ if (idx >= chunks.length) return;
33959
+ this.markWin32Write();
33960
+ this.adapter.send_keys(chunks[idx]);
33961
+ idx += 1;
33962
+ if (idx < chunks.length) {
33963
+ this.win32WriteTimer = setTimeout(writeNext, WIN32_PTY_WRITE_CHUNK_GAP_MS);
33964
+ }
33965
+ };
33966
+ writeNext();
33967
+ }
33968
+ /**
33969
+ * win32 submit. Two phases:
33970
+ *
33971
+ * Phase 1 (settle-gate): hold the first CR until the PTY output has been quiet
33972
+ * for WIN32_SUBMIT_SETTLE_MS after the last input write — i.e. the full
33973
+ * (possibly multi-KB / multiline) body has finished arriving in the composer
33974
+ * and echoing. Honors an initial minimum delay and is bounded by
33975
+ * WIN32_SUBMIT_MAX_SETTLE_WAIT_MS so a noisy screen can never hang the submit.
33976
+ * This is what stops a long message from being submitted half-arrived (its
33977
+ * leading lines lost). A short message settles almost immediately.
33978
+ *
33979
+ * Phase 2 (verified resend — unchanged): send the submit key, wait a gap, and
33980
+ * if the FSM is still 'idle' (the CR was absorbed as a multiline-paste
33981
+ * newline) resend, up to WIN32_SUBMIT_MAX_RESENDS. The first CR always fires
33982
+ * (a stale/edge status never suppresses it); resends are gated on still being
33983
+ * idle and stop the instant the agent leaves idle (submitted → generating /
33984
+ * approval). This preserves the win32 lone-CR-swallow handling.
33672
33985
  */
33673
33986
  scheduleWin32Submit(submitKey, initialDelayMs) {
33674
33987
  if (this.win32SubmitTimer) {
33675
33988
  clearTimeout(this.win32SubmitTimer);
33676
33989
  this.win32SubmitTimer = null;
33677
33990
  }
33991
+ const startedAt = Date.now();
33678
33992
  const fire = (attempt) => {
33679
33993
  this.win32SubmitTimer = null;
33680
33994
  this.adapter.send_keys(submitKey);
@@ -33687,8 +34001,20 @@ var FsmDriver = class {
33687
34001
  fire(attempt + 1);
33688
34002
  }, WIN32_SUBMIT_RESEND_GAP_MS);
33689
34003
  };
33690
- if (initialDelayMs > 0) this.win32SubmitTimer = setTimeout(() => fire(0), initialDelayMs);
33691
- else fire(0);
34004
+ const waitForSettle = () => {
34005
+ this.win32SubmitTimer = null;
34006
+ const now = Date.now();
34007
+ const quietFor = now - this.lastWin32InputActivityAt();
34008
+ const waited = now - startedAt;
34009
+ if (quietFor >= WIN32_SUBMIT_SETTLE_MS || waited >= WIN32_SUBMIT_MAX_SETTLE_WAIT_MS) {
34010
+ fire(0);
34011
+ return;
34012
+ }
34013
+ const recheckIn = Math.min(WIN32_SUBMIT_SETTLE_MS - quietFor, WIN32_SUBMIT_SETTLE_POLL_MS);
34014
+ this.win32SubmitTimer = setTimeout(waitForSettle, Math.max(recheckIn, 30));
34015
+ };
34016
+ if (initialDelayMs > 0) this.win32SubmitTimer = setTimeout(waitForSettle, initialDelayMs);
34017
+ else waitForSettle();
33692
34018
  }
33693
34019
  handleClickControl(controlId, payload) {
33694
34020
  const ctl = (this.spec.control_bar ?? []).find((c) => c.id === controlId);
@@ -33801,7 +34127,8 @@ function summarizeTransition(t) {
33801
34127
  return out;
33802
34128
  }
33803
34129
  function flattenCond(c, out, depth) {
33804
- out.push(`${" ".repeat(depth)}${c.kind} ${c.detail} = ${c.result}${c.remainingMs ? ` (${c.remainingMs}ms left)` : ""}`);
34130
+ const matched = c.matchedText ? ` matched=${JSON.stringify(c.matchedText)}` : "";
34131
+ out.push(`${" ".repeat(depth)}${c.kind} ${c.detail} = ${c.result}${c.remainingMs ? ` (${c.remainingMs}ms left)` : ""}${matched}`);
33805
34132
  for (const child of c.children ?? []) flattenCond(child, out, depth + 1);
33806
34133
  }
33807
34134
  function findStable(c) {
@@ -34519,8 +34846,8 @@ function projectToolBlock(block2, role, tmap) {
34519
34846
  }
34520
34847
  return null;
34521
34848
  }
34522
- function oneLine(s, max) {
34523
- const flat = s.replace(/\s+/g, " ").trim();
34849
+ function oneLine(s2, max) {
34850
+ const flat = s2.replace(/\s+/g, " ").trim();
34524
34851
  return flat.length > max ? flat.slice(0, max - 1) + "\u2026" : flat;
34525
34852
  }
34526
34853
  function parseTimestamp(v) {
@@ -34540,10 +34867,10 @@ function parseTimestamp(v) {
34540
34867
  return null;
34541
34868
  }
34542
34869
  function normalizeRole(r) {
34543
- const s = String(r ?? "").toLowerCase();
34544
- if (s === "user" || s === "human" || s === "user_explicit") return "user";
34545
- if (s === "assistant" || s === "ai" || s === "model") return "assistant";
34546
- if (s === "tool" || s === "tool_result" || s === "function") return "assistant";
34870
+ const s2 = String(r ?? "").toLowerCase();
34871
+ if (s2 === "user" || s2 === "human" || s2 === "user_explicit") return "user";
34872
+ if (s2 === "assistant" || s2 === "ai" || s2 === "model") return "assistant";
34873
+ if (s2 === "tool" || s2 === "tool_result" || s2 === "function") return "assistant";
34547
34874
  return "system";
34548
34875
  }
34549
34876
  function stringifyContent(v) {
@@ -34591,18 +34918,18 @@ function compileWhere(src) {
34591
34918
  return (record) => ors.some((ands) => ands.every((t) => evalTerm(t, record)));
34592
34919
  }
34593
34920
  function parseTerm(src) {
34594
- let s = src.trim();
34921
+ let s2 = src.trim();
34595
34922
  let negate = false;
34596
- if (s.startsWith("!")) {
34923
+ if (s2.startsWith("!")) {
34597
34924
  negate = true;
34598
- s = s.slice(1).trim();
34925
+ s2 = s2.slice(1).trim();
34599
34926
  }
34600
- const fnMatch = s.match(/^(startsWith|endsWith|contains)\s*\(\s*(.+?)\s*,\s*(.+?)\s*\)$/);
34927
+ const fnMatch = s2.match(/^(startsWith|endsWith|contains)\s*\(\s*(.+?)\s*,\s*(.+?)\s*\)$/);
34601
34928
  if (fnMatch) {
34602
34929
  const [, op2, pathExpr, litExpr] = fnMatch;
34603
34930
  return { path: pathExpr, op: op2, lit: parseLiteral(litExpr), negate };
34604
34931
  }
34605
- const opMatch = s.match(/^(.+?)\s*(==|!=|>=|<=|>|<)\s*(.+)$/);
34932
+ const opMatch = s2.match(/^(.+?)\s*(==|!=|>=|<=|>|<)\s*(.+)$/);
34606
34933
  if (!opMatch) return null;
34607
34934
  const [, lhs, op, rhsRaw] = opMatch;
34608
34935
  return { path: lhs.trim(), op, lit: parseLiteral(rhsRaw.trim()), negate };
@@ -35034,7 +35361,7 @@ var SpecCliAdapter = class _SpecCliAdapter {
35034
35361
  try {
35035
35362
  const sections = this.driver.getSections();
35036
35363
  if (sectionId && sections) {
35037
- const hit = sections.find((s) => s.id === sectionId);
35364
+ const hit = sections.find((s2) => s2.id === sectionId);
35038
35365
  if (hit) return hit.text;
35039
35366
  }
35040
35367
  return this.driver.getScreen();
@@ -35049,7 +35376,7 @@ var SpecCliAdapter = class _SpecCliAdapter {
35049
35376
  screen = this.driver.snapshot();
35050
35377
  const driverSections = this.driver.getSections?.();
35051
35378
  if (driverSections) {
35052
- sections = Object.fromEntries(driverSections.map((s) => [s.id, s.text]));
35379
+ sections = Object.fromEntries(driverSections.map((s2) => [s2.id, s2.text]));
35053
35380
  } else {
35054
35381
  sections = this.readCurrentScreenSections(screen);
35055
35382
  }
@@ -35095,6 +35422,10 @@ var SpecCliAdapter = class _SpecCliAdapter {
35095
35422
  // answers "why did this rule fire" after the fact, unlike the live
35096
35423
  // `fsm` field which only reflects the current instant.
35097
35424
  fsmHistory: this.driver.getFsmSnapshotHistory?.() ?? null,
35425
+ // PTY input/output/resize/cursor event timeline (debug-only) so the
35426
+ // snapshot shows what we typed / what the PTY printed around each
35427
+ // status transition. Null for drivers without the timeline.
35428
+ eventTimeline: this.driver.getEventTimeline?.() ?? null,
35098
35429
  // Extended fields
35099
35430
  name: this.cliName,
35100
35431
  status: this.getStatus().status,
@@ -35459,6 +35790,8 @@ var SpecCliAdapter = class _SpecCliAdapter {
35459
35790
  // v4 FSM transition snapshot history — the captured pre-transition
35460
35791
  // evaluation table at each transition (null for v3 specs).
35461
35792
  fsmHistory: this.driver.getFsmSnapshotHistory?.() ?? null,
35793
+ // PTY input/output/resize/cursor event timeline (debug-only).
35794
+ eventTimeline: this.driver.getEventTimeline?.() ?? null,
35462
35795
  messages,
35463
35796
  committedMessages: messages
35464
35797
  };
@@ -35503,6 +35836,7 @@ function createCliAdapter(provider, workingDir, cliArgs, extraEnv, transportFact
35503
35836
 
35504
35837
  // src/providers/cli-provider-instance.ts
35505
35838
  init_logger();
35839
+ init_mesh_event_trace();
35506
35840
  init_control_effects();
35507
35841
  init_approval_utils();
35508
35842
  init_provider_patch_state();
@@ -36554,6 +36888,23 @@ var CliProviderInstance = class _CliProviderInstance {
36554
36888
  if (this.completedDebounceTimer) clearTimeout(this.completedDebounceTimer);
36555
36889
  this.completedDebounceTimer = setTimeout(() => this.flushCompletedDebounceIfFinalized(), delayMs);
36556
36890
  }
36891
+ // EVTTRACE (observation-only): is this a mesh worker session whose completion
36892
+ // events must route to a coordinator? Used purely to gate trace logging so a
36893
+ // non-mesh CLI session's completions don't add EvtTrace noise. No decision logic.
36894
+ isMeshWorkerSession() {
36895
+ return !!(this.settings.meshNodeFor || this.settings.meshActiveTaskId || this.settings.meshNodeId || this.settings.launchedByCoordinator);
36896
+ }
36897
+ // EVTTRACE correlation context for this session's completion lifecycle. taskId is
36898
+ // the primary grep anchor; instanceId is the session fallback.
36899
+ meshTraceCtx(event = "agent:generating_completed") {
36900
+ return {
36901
+ taskId: this.settings.meshActiveTaskId,
36902
+ sessionId: this.instanceId,
36903
+ nodeId: this.settings.meshNodeId,
36904
+ meshId: this.settings.meshNodeFor,
36905
+ event
36906
+ };
36907
+ }
36557
36908
  flushCompletedDebounceIfFinalized() {
36558
36909
  const pending = this.completedDebouncePending;
36559
36910
  if (!pending) {
@@ -36574,24 +36925,33 @@ var CliProviderInstance = class _CliProviderInstance {
36574
36925
  if (block2) {
36575
36926
  const blockReason = block2.reason;
36576
36927
  const waitedMs = Date.now() - pending.firstObservedAt;
36577
- LOG.debug("CLI", `[${this.type}] finalization block: reason=${blockReason} terminal=${block2.terminal} waitedMs=${waitedMs} maxWait=${COMPLETED_FINALIZATION_MAX_WAIT_MS}`);
36578
- if (block2.terminal && !block2.allowTimeout || waitedMs < COMPLETED_FINALIZATION_MAX_WAIT_MS) {
36928
+ const isTranscriptEvidenceGate = block2.allowTimeout === true;
36929
+ LOG.debug("CLI", `[${this.type}] finalization block: reason=${blockReason} terminal=${block2.terminal} allowTimeout=${isTranscriptEvidenceGate} waitedMs=${waitedMs} maxWait=${COMPLETED_FINALIZATION_MAX_WAIT_MS}`);
36930
+ if (!isTranscriptEvidenceGate && (block2.terminal || waitedMs < COMPLETED_FINALIZATION_MAX_WAIT_MS)) {
36579
36931
  if (pending.loggedBlockReason !== blockReason) {
36580
36932
  LOG.info("CLI", `[${this.type}] waiting to emit completed until transcript finalizes (${blockReason})`);
36933
+ if (this.isMeshWorkerSession()) {
36934
+ traceMeshEventDrop("completion_gate_hold", this.meshTraceCtx(), `${blockReason} waited=${waitedMs}ms`);
36935
+ }
36581
36936
  pending.loggedBlockReason = blockReason;
36582
36937
  }
36583
36938
  this.scheduleCompletedDebounceFlush(COMPLETED_FINALIZATION_RETRY_MS);
36584
36939
  return;
36585
36940
  }
36941
+ const emittedAfterFinalizationTimeout = waitedMs >= COMPLETED_FINALIZATION_MAX_WAIT_MS;
36586
36942
  const completionDiagnostic = this.buildCompletedFinalizationDiagnostic({
36587
36943
  blockReason,
36588
36944
  latestStatus,
36589
36945
  latestVisibleStatus,
36590
36946
  waitedMs,
36591
36947
  pending,
36592
- emittedAfterFinalizationTimeout: true
36948
+ emittedAfterFinalizationTimeout
36593
36949
  });
36594
- LOG.warn("CLI", `[${this.type}] emitting completed event after ${waitedMs}ms without finalized assistant turn (${blockReason})`);
36950
+ completionDiagnostic.decoupledImmediateEmit = isTranscriptEvidenceGate && !emittedAfterFinalizationTimeout;
36951
+ LOG.warn("CLI", `[${this.type}] emitting completed event (${isTranscriptEvidenceGate && !emittedAfterFinalizationTimeout ? "CANON-C decoupled-immediate, transcript pending" : `after ${waitedMs}ms`}) without finalized assistant turn (${blockReason})`);
36952
+ if (this.isMeshWorkerSession()) {
36953
+ traceMeshEventStage("fired", this.meshTraceCtx(), `forced after ${waitedMs}ms (${blockReason})`);
36954
+ }
36595
36955
  this.pushEvent({
36596
36956
  event: "agent:generating_completed",
36597
36957
  chatTitle: pending.chatTitle,
@@ -36614,6 +36974,9 @@ var CliProviderInstance = class _CliProviderInstance {
36614
36974
  return;
36615
36975
  }
36616
36976
  LOG.info("CLI", `[${this.type}] completed in ${pending.duration}s`);
36977
+ if (this.isMeshWorkerSession()) {
36978
+ traceMeshEventStage("fired", this.meshTraceCtx(), `duration=${pending.duration}s`);
36979
+ }
36617
36980
  this.pushEvent({
36618
36981
  event: "agent:generating_completed",
36619
36982
  chatTitle: pending.chatTitle,
@@ -36852,6 +37215,9 @@ var CliProviderInstance = class _CliProviderInstance {
36852
37215
  if (missingEvidence && !hasMeshContext) {
36853
37216
  LOG.info("CLI", `[${this.type}] short completion suppressed: missing final assistant evidence, no mesh context (source=${shortEvidenceSource})`);
36854
37217
  } else {
37218
+ if (this.isMeshWorkerSession()) {
37219
+ traceMeshEventStage("fired", this.meshTraceCtx(), `short-generating idle (source=${shortEvidenceSource})`);
37220
+ }
36855
37221
  this.pushEvent({
36856
37222
  event: "agent:generating_completed",
36857
37223
  chatTitle,
@@ -36928,6 +37294,9 @@ var CliProviderInstance = class _CliProviderInstance {
36928
37294
  const monitorParsedStatus = parsedStatus;
36929
37295
  for (const me of monitorEvents) {
36930
37296
  if (me.type === "monitor:no_progress" && this.completionHasFinalAssistantMessage(monitorParsedStatus?.messages) && !this.hasAdapterPendingResponse() && !hasNonEmptyCliModalButtons(monitorParsedStatus?.activeModal ?? monitorParsedStatus?.modal)) {
37297
+ if (this.isMeshWorkerSession()) {
37298
+ traceMeshEventStage("fired", this.meshTraceCtx(), "no_progress_monitor_final_summary");
37299
+ }
36931
37300
  this.pushEvent({
36932
37301
  event: "agent:generating_completed",
36933
37302
  chatTitle,
@@ -40791,7 +41160,7 @@ function parsePbFile(filePath, sessionId) {
40791
41160
  }
40792
41161
  if (buf.length === 0) return null;
40793
41162
  const strings = extractStringsFromBuffer(buf);
40794
- const meaningful = strings.filter((s) => s.length >= MIN_PRINTABLE_RUN && /\w/.test(s));
41163
+ const meaningful = strings.filter((s2) => s2.length >= MIN_PRINTABLE_RUN && /\w/.test(s2));
40795
41164
  if (meaningful.length === 0) return null;
40796
41165
  const content = meaningful.join("\n");
40797
41166
  const sourceMtimeMs = statMtimeMs3(filePath);
@@ -40999,10 +41368,10 @@ function readSession4(sessionPath) {
40999
41368
  };
41000
41369
  }
41001
41370
  function normalizeHermesRole(r) {
41002
- const s = String(r ?? "").toLowerCase();
41003
- if (s === "user" || s === "human") return "user";
41004
- if (s === "assistant" || s === "ai" || s === "model") return "assistant";
41005
- if (s === "tool" || s === "tool_result" || s === "function") return "assistant";
41371
+ const s2 = String(r ?? "").toLowerCase();
41372
+ if (s2 === "user" || s2 === "human") return "user";
41373
+ if (s2 === "assistant" || s2 === "ai" || s2 === "model") return "assistant";
41374
+ if (s2 === "tool" || s2 === "tool_result" || s2 === "function") return "assistant";
41006
41375
  return "system";
41007
41376
  }
41008
41377
 
@@ -41228,10 +41597,10 @@ function safeMtime(p) {
41228
41597
  }
41229
41598
  }
41230
41599
  function normalizeRole2(r) {
41231
- const s = String(r ?? "").toLowerCase();
41232
- if (s === "user" || s === "human") return "user";
41233
- if (s === "assistant" || s === "ai" || s === "model") return "assistant";
41234
- if (s === "tool" || s === "tool_result" || s === "function") return "assistant";
41600
+ const s2 = String(r ?? "").toLowerCase();
41601
+ if (s2 === "user" || s2 === "human") return "user";
41602
+ if (s2 === "assistant" || s2 === "ai" || s2 === "model") return "assistant";
41603
+ if (s2 === "tool" || s2 === "tool_result" || s2 === "function") return "assistant";
41235
41604
  return "system";
41236
41605
  }
41237
41606
 
@@ -41251,7 +41620,7 @@ function synthesizeControlsFromControlBar(specControls) {
41251
41620
  const actionType = ctl?.action?.type;
41252
41621
  if (!id || !actionType) return;
41253
41622
  const label = typeof ctl?.label === "string" && ctl.label.trim() ? ctl.label : id;
41254
- const visibleWhenState = Array.isArray(ctl?.visible_when_state) ? ctl.visible_when_state.filter((s) => typeof s === "string") : void 0;
41623
+ const visibleWhenState = Array.isArray(ctl?.visible_when_state) ? ctl.visible_when_state.filter((s2) => typeof s2 === "string") : void 0;
41255
41624
  if (actionType === "open_picker") {
41256
41625
  out.push({
41257
41626
  id,
@@ -48167,7 +48536,7 @@ var DaemonCommandRouter = class {
48167
48536
  const base = validationSummary.failureCode === "missing_dependencies" ? "Refinery validation dependencies are missing; merge/refine was not attempted. Configure validation.bootstrapCommands if Refinery should bootstrap dependencies before validation." : validationSummary.failureCode === "dependency_bootstrap_failed" ? "Refinery dependency/bootstrap command failed; merge/refine was not attempted." : validationSummary.failureCode === "spawn_resolution_failed" ? validationSummary.spawnResolutionError || "Refinery validation command could not be spawned (executable not found); merge/refine was not attempted." : "Refinery validation gate failed; merge/refine was not attempted.";
48168
48537
  if (!firstFailedCmd) return base;
48169
48538
  const cmdName = typeof firstFailedCmd.displayCommand === "string" ? firstFailedCmd.displayCommand : typeof firstFailedCmd.command === "string" ? [firstFailedCmd.command, ...Array.isArray(firstFailedCmd.args) ? firstFailedCmd.args : []].join(" ").trim() : typeof firstFailedCmd.cmd === "string" ? firstFailedCmd.cmd : "";
48170
- const rawOutput = [firstFailedCmd.stdout, firstFailedCmd.stderr, firstFailedCmd.output].filter((s) => typeof s === "string" && s.length > 0).join("\n");
48539
+ const rawOutput = [firstFailedCmd.stdout, firstFailedCmd.stderr, firstFailedCmd.output].filter((s2) => typeof s2 === "string" && s2.length > 0).join("\n");
48171
48540
  const tail = rawOutput.length > 800 ? rawOutput.slice(-800) : rawOutput;
48172
48541
  return [
48173
48542
  base,
@@ -48918,7 +49287,7 @@ ${hintLines.join("\n")}` : "",
48918
49287
  convergence = "blocked_review";
48919
49288
  }
48920
49289
  const fbcs = result.finalBranchConvergenceState && typeof result.finalBranchConvergenceState === "object" ? result.finalBranchConvergenceState : void 0;
48921
- const stage = Array.isArray(result.refineStages) ? result.refineStages.filter((s) => s.status === "failed").map((s) => s.stage).filter(Boolean).pop() : void 0;
49290
+ const stage = Array.isArray(result.refineStages) ? result.refineStages.filter((s2) => s2.status === "failed").map((s2) => s2.stage).filter(Boolean).pop() : void 0;
48922
49291
  results.push({
48923
49292
  nodeId: node.id,
48924
49293
  workspace: node.workspace,
@@ -49915,7 +50284,7 @@ ${hintLines.join("\n")}` : "",
49915
50284
  return {
49916
50285
  success: true,
49917
50286
  screenLineCount: lines.length,
49918
- sections: resolved.map((s) => ({ id: s.id, fromLine: s.fromLine, toLine: s.toLine, text: s.text }))
50287
+ sections: resolved.map((s2) => ({ id: s2.id, fromLine: s2.fromLine, toLine: s2.toLine, text: s2.text }))
49919
50288
  };
49920
50289
  } catch (e) {
49921
50290
  return { success: false, error: `resolve failed: ${e.message}` };
@@ -50484,7 +50853,7 @@ ${hintLines.join("\n")}` : "",
50484
50853
  if (!meshId) return { success: false, error: "meshId required" };
50485
50854
  try {
50486
50855
  const { getMeshQueueStats: getMeshQueueStats2, getQueue: getQueue2, describeTaskDependencyState: describeTaskDependencyState2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
50487
- const status = Array.isArray(args?.status) ? args.status.map((s) => typeof s === "string" ? s.trim() : "").filter(Boolean) : void 0;
50856
+ const status = Array.isArray(args?.status) ? args.status.map((s2) => typeof s2 === "string" ? s2.trim() : "").filter(Boolean) : void 0;
50488
50857
  const rawQueue = getQueue2(meshId, { status });
50489
50858
  const statusById = new Map(getQueue2(meshId).map((task) => [task.id, task.status]));
50490
50859
  const queue = rawQueue.map((task) => Array.isArray(task.dependsOn) && task.dependsOn.length > 0 ? { ...task, ...describeTaskDependencyState2(task, statusById) } : task);
@@ -50765,7 +51134,7 @@ ${hintLines.join("\n")}` : "",
50765
51134
  nodeDaemonId = typeof node?.daemonId === "string" ? node.daemonId.trim() : void 0;
50766
51135
  }
50767
51136
  const selfDaemonId = this.deps.statusInstanceId;
50768
- const isRemote = nodeDaemonId && selfDaemonId && nodeDaemonId !== selfDaemonId;
51137
+ const isRemote = nodeDaemonId && selfDaemonId && !daemonIdsEquivalent(nodeDaemonId, selfDaemonId);
50769
51138
  if (isRemote && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
50770
51139
  const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "fast_forward_mesh_node", {
50771
51140
  ...typeof args === "object" && args !== null ? args : {},
@@ -50799,7 +51168,7 @@ ${hintLines.join("\n")}` : "",
50799
51168
  nodeDaemonId = typeof node?.daemonId === "string" ? node.daemonId.trim() : void 0;
50800
51169
  }
50801
51170
  const selfDaemonId = this.deps.statusInstanceId;
50802
- const isRemote = nodeDaemonId && selfDaemonId && nodeDaemonId !== selfDaemonId;
51171
+ const isRemote = nodeDaemonId && selfDaemonId && !daemonIdsEquivalent(nodeDaemonId, selfDaemonId);
50803
51172
  if (isRemote && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
50804
51173
  const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "get_mesh_node_logs", {
50805
51174
  ...typeof args === "object" && args !== null ? args : {},
@@ -50847,7 +51216,7 @@ ${hintLines.join("\n")}` : "",
50847
51216
  const forwardNode = meshRecordForForward?.mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
50848
51217
  const nodeDaemonId = typeof forwardNode?.daemonId === "string" ? forwardNode.daemonId.trim() : void 0;
50849
51218
  const selfDaemonId = this.deps.statusInstanceId;
50850
- const isRemote = nodeDaemonId && selfDaemonId && nodeDaemonId !== selfDaemonId;
51219
+ const isRemote = nodeDaemonId && selfDaemonId && !daemonIdsEquivalent(nodeDaemonId, selfDaemonId);
50851
51220
  if (isRemote && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
50852
51221
  const callerCoordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : void 0;
50853
51222
  const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "refine_mesh_node", {
@@ -50934,7 +51303,7 @@ ${hintLines.join("\n")}` : "",
50934
51303
  let worktreeCleanup;
50935
51304
  if (node?.isLocalWorktree) {
50936
51305
  const nodeDaemonId = typeof node.daemonId === "string" ? node.daemonId.trim() : void 0;
50937
- const isRemoteWorktree = nodeDaemonId && nodeDaemonId !== this.deps.statusInstanceId && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch;
51306
+ const isRemoteWorktree = nodeDaemonId && !daemonIdsEquivalent(nodeDaemonId, this.deps.statusInstanceId) && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch;
50938
51307
  if (isRemoteWorktree) {
50939
51308
  const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "remove_mesh_node", {
50940
51309
  ...typeof args === "object" && args !== null ? args : {},
@@ -51016,7 +51385,7 @@ ${hintLines.join("\n")}` : "",
51016
51385
  const sourceNode = mesh.nodes?.find((n) => meshNodeIdMatches(n, sourceNodeId));
51017
51386
  if (!sourceNode) return { success: false, error: `Source node '${sourceNodeId}' not found in mesh` };
51018
51387
  const sourceDaemonId = typeof sourceNode.daemonId === "string" ? sourceNode.daemonId.trim() : void 0;
51019
- if (sourceDaemonId && sourceDaemonId !== this.deps.statusInstanceId && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
51388
+ if (sourceDaemonId && !daemonIdsEquivalent(sourceDaemonId, this.deps.statusInstanceId) && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
51020
51389
  const forwarded = await this.deps.dispatchMeshCommand(sourceDaemonId, "clone_mesh_node", {
51021
51390
  ...typeof args === "object" && args !== null ? args : {},
51022
51391
  _meshDirectDispatch: true
@@ -51258,7 +51627,7 @@ ${hintLines.join("\n")}` : "",
51258
51627
  if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
51259
51628
  if (!node.isLocalWorktree) return { success: false, error: "Node is not a local worktree node" };
51260
51629
  const nodeDaemonId = typeof node.daemonId === "string" ? node.daemonId.trim() : void 0;
51261
- if (nodeDaemonId && nodeDaemonId !== this.deps.statusInstanceId && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
51630
+ if (nodeDaemonId && !daemonIdsEquivalent(nodeDaemonId, this.deps.statusInstanceId) && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
51262
51631
  const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "retry_mesh_node_bootstrap", {
51263
51632
  ...typeof args === "object" && args !== null ? args : {},
51264
51633
  _meshDirectDispatch: true
@@ -52468,16 +52837,16 @@ var DaemonStatusReporter = class {
52468
52837
  const now = this.lastStatusSentAt;
52469
52838
  const target = opts?.p2pOnly ? "P2P" : serverConnected ? "P2P+Server" : "P2P";
52470
52839
  const allStates = this.deps.instanceManager.collectAllStates();
52471
- const ideStates = allStates.filter((s) => s.category === "ide");
52472
- const cliStates = allStates.filter((s) => s.category === "cli");
52473
- const acpStates = allStates.filter((s) => s.category === "acp");
52474
- const ideSummary = ideStates.map((s) => {
52475
- const msgs = s.activeChat?.messages?.length || 0;
52476
- const exts = s.extensions.length;
52477
- return `${s.type}(${s.status},${msgs}msg,${exts}ext)`;
52840
+ const ideStates = allStates.filter((s2) => s2.category === "ide");
52841
+ const cliStates = allStates.filter((s2) => s2.category === "cli");
52842
+ const acpStates = allStates.filter((s2) => s2.category === "acp");
52843
+ const ideSummary = ideStates.map((s2) => {
52844
+ const msgs = s2.activeChat?.messages?.length || 0;
52845
+ const exts = s2.extensions.length;
52846
+ return `${s2.type}(${s2.status},${msgs}msg,${exts}ext)`;
52478
52847
  }).join(", ");
52479
- const cliSummary = cliStates.map((s) => `${s.type}(${s.status})`).join(", ");
52480
- const acpSummary = acpStates.map((s) => `${s.type}(${s.status})`).join(", ");
52848
+ const cliSummary = cliStates.map((s2) => `${s2.type}(${s2.status})`).join(", ");
52849
+ const acpSummary = acpStates.map((s2) => `${s2.type}(${s2.status})`).join(", ");
52481
52850
  const logLevel = opts?.p2pOnly ? "debug" : "info";
52482
52851
  const baseSummary = `IDE: ${ideStates.length} [${ideSummary}] CLI: ${cliStates.length} [${cliSummary}] ACP: ${acpStates.length} [${acpSummary}]`;
52483
52852
  const summaryChanged = baseSummary !== this.lastStatusSummary;
@@ -52588,10 +52957,10 @@ var DaemonStatusReporter = class {
52588
52957
  }
52589
52958
  return false;
52590
52959
  }
52591
- simpleHash(s) {
52960
+ simpleHash(s2) {
52592
52961
  let h = 2166136261;
52593
- for (let i = 0; i < s.length; i++) {
52594
- h ^= s.charCodeAt(i);
52962
+ for (let i = 0; i < s2.length; i++) {
52963
+ h ^= s2.charCodeAt(i);
52595
52964
  h = h * 16777619 >>> 0;
52596
52965
  }
52597
52966
  return h.toString(36);
@@ -53817,7 +54186,7 @@ var ProviderInstanceManager = class {
53817
54186
  * Per-category status collect
53818
54187
  */
53819
54188
  collectStatesByCategory(category) {
53820
- return this.collectAllStates().filter((s) => s.category === category);
54189
+ return this.collectAllStates().filter((s2) => s2.category === category);
53821
54190
  }
53822
54191
  // ─── Tick engine ─────────────────────────────────
53823
54192
  /**
@@ -55717,9 +56086,9 @@ function getCliProviderResolutionMeta(ctx, type, adapter) {
55717
56086
  function findCliTarget(ctx, type, instanceId) {
55718
56087
  if (!ctx.instanceManager) return null;
55719
56088
  const cliStates = ctx.instanceManager.collectAllStates().filter(isCliTargetState);
55720
- if (instanceId) return cliStates.find((s) => s.instanceId === instanceId) || null;
56089
+ if (instanceId) return cliStates.find((s2) => s2.instanceId === instanceId) || null;
55721
56090
  if (!type) return cliStates[cliStates.length - 1] || null;
55722
- const matches = cliStates.filter((s) => s.type === type);
56091
+ const matches = cliStates.filter((s2) => s2.type === type);
55723
56092
  return matches[matches.length - 1] || null;
55724
56093
  }
55725
56094
  function getCliTargetBundle(ctx, type, instanceId) {
@@ -56082,20 +56451,20 @@ async function handleCliStatus(ctx, _req, res) {
56082
56451
  return;
56083
56452
  }
56084
56453
  const allStates = ctx.instanceManager.collectAllStates();
56085
- const cliStates = allStates.filter((s) => s.category === "cli" || s.category === "acp");
56086
- const result = cliStates.map((s) => ({
56087
- instanceId: s.instanceId,
56088
- type: s.type,
56089
- name: s.name,
56090
- category: s.category,
56091
- status: s.status,
56092
- mode: s.mode,
56093
- workspace: s.workspace,
56094
- messageCount: s.activeChat?.messages?.length || 0,
56095
- lastMessage: s.activeChat?.messages?.slice(-1)[0] || null,
56096
- activeModal: s.activeChat?.activeModal || null,
56097
- pendingEvents: s.pendingEvents || [],
56098
- settings: s.settings
56454
+ const cliStates = allStates.filter((s2) => s2.category === "cli" || s2.category === "acp");
56455
+ const result = cliStates.map((s2) => ({
56456
+ instanceId: s2.instanceId,
56457
+ type: s2.type,
56458
+ name: s2.name,
56459
+ category: s2.category,
56460
+ status: s2.status,
56461
+ mode: s2.mode,
56462
+ workspace: s2.workspace,
56463
+ messageCount: s2.activeChat?.messages?.length || 0,
56464
+ lastMessage: s2.activeChat?.messages?.slice(-1)[0] || null,
56465
+ activeModal: s2.activeChat?.activeModal || null,
56466
+ pendingEvents: s2.pendingEvents || [],
56467
+ settings: s2.settings
56099
56468
  }));
56100
56469
  ctx.json(res, 200, { instances: result, count: result.length });
56101
56470
  }
@@ -56184,9 +56553,9 @@ function handleCliSSE(ctx, cliSSEClients, _req, res) {
56184
56553
  }
56185
56554
  if (ctx.instanceManager) {
56186
56555
  const allStates = ctx.instanceManager.collectAllStates();
56187
- const cliStates = allStates.filter((s) => s.category === "cli" || s.category === "acp");
56188
- for (const s of cliStates) {
56189
- ctx.sendCliSSE({ event: "snapshot", providerType: s.type, status: s.status, instanceId: s.instanceId });
56556
+ const cliStates = allStates.filter((s2) => s2.category === "cli" || s2.category === "acp");
56557
+ for (const s2 of cliStates) {
56558
+ ctx.sendCliSSE({ event: "snapshot", providerType: s2.type, status: s2.status, instanceId: s2.instanceId });
56190
56559
  }
56191
56560
  }
56192
56561
  _req.on("close", () => {
@@ -56202,7 +56571,7 @@ async function handleCliDebug(ctx, type, _req, res) {
56202
56571
  const target = findCliTarget(ctx, type);
56203
56572
  if (!target) {
56204
56573
  const allStates = ctx.instanceManager.collectAllStates();
56205
- ctx.json(res, 404, { error: `No running instance for: ${type}`, available: allStates.filter((s) => s.category === "cli" || s.category === "acp").map((s) => s.type) });
56574
+ ctx.json(res, 404, { error: `No running instance for: ${type}`, available: allStates.filter((s2) => s2.category === "cli" || s2.category === "acp").map((s2) => s2.type) });
56206
56575
  return;
56207
56576
  }
56208
56577
  const instance = ctx.instanceManager.getInstance(target.instanceId);
@@ -56248,7 +56617,7 @@ async function handleCliTrace(ctx, type, req, res) {
56248
56617
  const allStates = ctx.instanceManager.collectAllStates();
56249
56618
  ctx.json(res, 404, {
56250
56619
  error: `No running instance for: ${type}`,
56251
- available: allStates.filter((s) => s.category === "cli" || s.category === "acp").map((s) => s.type)
56620
+ available: allStates.filter((s2) => s2.category === "cli" || s2.category === "acp").map((s2) => s2.type)
56252
56621
  });
56253
56622
  return;
56254
56623
  }
@@ -57053,7 +57422,7 @@ async function handleAutoImplement(ctx, type, req, res) {
57053
57422
  child.write("\x1B[12;1R");
57054
57423
  ctx.log("Terminal CPR request (\\x1b[6n) intercepted in PTY, responding with dummy coordinates [12;1R]");
57055
57424
  }
57056
- checkAutoApproval(data, (s) => child.write(s));
57425
+ checkAutoApproval(data, (s2) => child.write(s2));
57057
57426
  sendAutoImplSSE(ctx, { event: "output", data: { chunk: data, stream: "stdout" } });
57058
57427
  scheduleAutoStopForVerification();
57059
57428
  });
@@ -57066,7 +57435,7 @@ async function handleAutoImplement(ctx, type, req, res) {
57066
57435
  stdout += chunk;
57067
57436
  clearAutoStopTimer();
57068
57437
  if (chunk.includes("\x1B[6n")) child.stdin?.write("\x1B[1;1R");
57069
- checkAutoApproval(chunk, (s) => child.stdin?.write(s));
57438
+ checkAutoApproval(chunk, (s2) => child.stdin?.write(s2));
57070
57439
  sendAutoImplSSE(ctx, { event: "output", data: { chunk, stream: "stdout" } });
57071
57440
  scheduleAutoStopForVerification();
57072
57441
  });
@@ -57074,7 +57443,7 @@ async function handleAutoImplement(ctx, type, req, res) {
57074
57443
  const chunk = d.toString();
57075
57444
  stderr += chunk;
57076
57445
  clearAutoStopTimer();
57077
- checkAutoApproval(chunk, (s) => child.stdin?.write(s));
57446
+ checkAutoApproval(chunk, (s2) => child.stdin?.write(s2));
57078
57447
  sendAutoImplSSE(ctx, { event: "output", data: { chunk, stream: "stderr" } });
57079
57448
  scheduleAutoStopForVerification();
57080
57449
  });
@@ -57889,59 +58258,59 @@ var DevServer = class _DevServer {
57889
58258
  // ─── Route Table ─────────────────────────────────────
57890
58259
  routes = [
57891
58260
  // Static routes
57892
- { method: "GET", pattern: "/api/providers", handler: (q, s) => this.handleListProviders(q, s) },
57893
- { method: "GET", pattern: "/api/providers/source-config", handler: (q, s) => this.handleGetProviderSourceConfig(q, s) },
57894
- { method: "POST", pattern: "/api/providers/source-config", handler: (q, s) => this.handleSetProviderSourceConfig(q, s) },
57895
- { method: "GET", pattern: "/api/providers/versions", handler: (q, s) => this.handleDetectVersions(q, s) },
57896
- { method: "POST", pattern: "/api/providers/reload", handler: (q, s) => this.handleReload(q, s) },
57897
- { method: "POST", pattern: "/api/cdp/evaluate", handler: (q, s) => this.handleCdpEvaluate(q, s) },
57898
- { method: "POST", pattern: "/api/cdp/click", handler: (q, s) => this.handleCdpClick(q, s) },
57899
- { method: "POST", pattern: "/api/cdp/dom/query", handler: (q, s) => this.handleCdpDomQuery(q, s) },
57900
- { method: "POST", pattern: "/api/cdp/dom/inspect", handler: (q, s) => this.handleDomInspect(q, s) },
57901
- { method: "POST", pattern: "/api/cdp/dom/children", handler: (q, s) => this.handleDomChildren(q, s) },
57902
- { method: "POST", pattern: "/api/cdp/dom/analyze", handler: (q, s) => this.handleDomAnalyze(q, s) },
57903
- { method: "POST", pattern: "/api/cdp/dom/find-text", handler: (q, s) => this.handleFindByText(q, s) },
57904
- { method: "POST", pattern: "/api/cdp/dom/find-common", handler: (q, s) => this.handleFindCommon(q, s) },
57905
- { method: "GET", pattern: "/api/cdp/screenshot", handler: (q, s) => this.handleScreenshot(q, s) },
57906
- { method: "GET", pattern: "/api/cdp/targets", handler: (q, s) => this.handleCdpTargets(q, s) },
57907
- { method: "POST", pattern: "/api/scripts/run", handler: (q, s) => this.handleScriptsRun(q, s) },
57908
- { method: "GET", pattern: "/api/status", handler: (q, s) => this.handleStatus(q, s) },
57909
- { method: "POST", pattern: "/api/watch/start", handler: (q, s) => this.handleWatchStart(q, s) },
57910
- { method: "POST", pattern: "/api/watch/stop", handler: (q, s) => this.handleWatchStop(q, s) },
57911
- { method: "GET", pattern: "/api/watch/events", handler: (q, s) => this.handleSSE(q, s) },
57912
- { method: "POST", pattern: "/api/scaffold", handler: (q, s) => this.handleScaffold(q, s) },
58261
+ { method: "GET", pattern: "/api/providers", handler: (q, s2) => this.handleListProviders(q, s2) },
58262
+ { method: "GET", pattern: "/api/providers/source-config", handler: (q, s2) => this.handleGetProviderSourceConfig(q, s2) },
58263
+ { method: "POST", pattern: "/api/providers/source-config", handler: (q, s2) => this.handleSetProviderSourceConfig(q, s2) },
58264
+ { method: "GET", pattern: "/api/providers/versions", handler: (q, s2) => this.handleDetectVersions(q, s2) },
58265
+ { method: "POST", pattern: "/api/providers/reload", handler: (q, s2) => this.handleReload(q, s2) },
58266
+ { method: "POST", pattern: "/api/cdp/evaluate", handler: (q, s2) => this.handleCdpEvaluate(q, s2) },
58267
+ { method: "POST", pattern: "/api/cdp/click", handler: (q, s2) => this.handleCdpClick(q, s2) },
58268
+ { method: "POST", pattern: "/api/cdp/dom/query", handler: (q, s2) => this.handleCdpDomQuery(q, s2) },
58269
+ { method: "POST", pattern: "/api/cdp/dom/inspect", handler: (q, s2) => this.handleDomInspect(q, s2) },
58270
+ { method: "POST", pattern: "/api/cdp/dom/children", handler: (q, s2) => this.handleDomChildren(q, s2) },
58271
+ { method: "POST", pattern: "/api/cdp/dom/analyze", handler: (q, s2) => this.handleDomAnalyze(q, s2) },
58272
+ { method: "POST", pattern: "/api/cdp/dom/find-text", handler: (q, s2) => this.handleFindByText(q, s2) },
58273
+ { method: "POST", pattern: "/api/cdp/dom/find-common", handler: (q, s2) => this.handleFindCommon(q, s2) },
58274
+ { method: "GET", pattern: "/api/cdp/screenshot", handler: (q, s2) => this.handleScreenshot(q, s2) },
58275
+ { method: "GET", pattern: "/api/cdp/targets", handler: (q, s2) => this.handleCdpTargets(q, s2) },
58276
+ { method: "POST", pattern: "/api/scripts/run", handler: (q, s2) => this.handleScriptsRun(q, s2) },
58277
+ { method: "GET", pattern: "/api/status", handler: (q, s2) => this.handleStatus(q, s2) },
58278
+ { method: "POST", pattern: "/api/watch/start", handler: (q, s2) => this.handleWatchStart(q, s2) },
58279
+ { method: "POST", pattern: "/api/watch/stop", handler: (q, s2) => this.handleWatchStop(q, s2) },
58280
+ { method: "GET", pattern: "/api/watch/events", handler: (q, s2) => this.handleSSE(q, s2) },
58281
+ { method: "POST", pattern: "/api/scaffold", handler: (q, s2) => this.handleScaffold(q, s2) },
57913
58282
  // CLI Debug routes
57914
- { method: "GET", pattern: "/api/cli/status", handler: (q, s) => this.handleCliStatus(q, s) },
57915
- { method: "POST", pattern: "/api/cli/launch", handler: (q, s) => this.handleCliLaunch(q, s) },
57916
- { method: "POST", pattern: "/api/cli/send", handler: (q, s) => this.handleCliSend(q, s) },
57917
- { method: "POST", pattern: "/api/cli/exercise", handler: (q, s) => this.handleCliExercise(q, s) },
57918
- { method: "POST", pattern: "/api/cli/fixture/capture", handler: (q, s) => this.handleCliFixtureCapture(q, s) },
57919
- { method: "POST", pattern: "/api/cli/fixture/replay", handler: (q, s) => this.handleCliFixtureReplay(q, s) },
57920
- { method: "POST", pattern: "/api/cli/resolve", handler: (q, s) => this.handleCliResolve(q, s) },
57921
- { method: "POST", pattern: "/api/cli/raw", handler: (q, s) => this.handleCliRaw(q, s) },
57922
- { method: "POST", pattern: "/api/cli/stop", handler: (q, s) => this.handleCliStop(q, s) },
57923
- { method: "GET", pattern: "/api/cli/events", handler: (q, s) => this.handleCliSSE(q, s) },
57924
- { method: "GET", pattern: /^\/api\/cli\/debug\/([^/]+)$/, handler: (q, s, p) => this.handleCliDebug(p[0], q, s) },
57925
- { method: "GET", pattern: /^\/api\/cli\/trace\/([^/]+)$/, handler: (q, s, p) => this.handleCliTrace(p[0], q, s) },
57926
- { method: "GET", pattern: /^\/api\/cli\/fixtures\/([^/]+)$/, handler: (q, s, p) => this.handleCliFixtureList(p[0], q, s) },
58283
+ { method: "GET", pattern: "/api/cli/status", handler: (q, s2) => this.handleCliStatus(q, s2) },
58284
+ { method: "POST", pattern: "/api/cli/launch", handler: (q, s2) => this.handleCliLaunch(q, s2) },
58285
+ { method: "POST", pattern: "/api/cli/send", handler: (q, s2) => this.handleCliSend(q, s2) },
58286
+ { method: "POST", pattern: "/api/cli/exercise", handler: (q, s2) => this.handleCliExercise(q, s2) },
58287
+ { method: "POST", pattern: "/api/cli/fixture/capture", handler: (q, s2) => this.handleCliFixtureCapture(q, s2) },
58288
+ { method: "POST", pattern: "/api/cli/fixture/replay", handler: (q, s2) => this.handleCliFixtureReplay(q, s2) },
58289
+ { method: "POST", pattern: "/api/cli/resolve", handler: (q, s2) => this.handleCliResolve(q, s2) },
58290
+ { method: "POST", pattern: "/api/cli/raw", handler: (q, s2) => this.handleCliRaw(q, s2) },
58291
+ { method: "POST", pattern: "/api/cli/stop", handler: (q, s2) => this.handleCliStop(q, s2) },
58292
+ { method: "GET", pattern: "/api/cli/events", handler: (q, s2) => this.handleCliSSE(q, s2) },
58293
+ { method: "GET", pattern: /^\/api\/cli\/debug\/([^/]+)$/, handler: (q, s2, p) => this.handleCliDebug(p[0], q, s2) },
58294
+ { method: "GET", pattern: /^\/api\/cli\/trace\/([^/]+)$/, handler: (q, s2, p) => this.handleCliTrace(p[0], q, s2) },
58295
+ { method: "GET", pattern: /^\/api\/cli\/fixtures\/([^/]+)$/, handler: (q, s2, p) => this.handleCliFixtureList(p[0], q, s2) },
57927
58296
  // Dynamic routes (provider :type param)
57928
- { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/script$/, handler: (q, s, p) => this.handleRunScript(p[0], q, s) },
57929
- { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/files$/, handler: (q, s, p) => this.handleListFiles(p[0], q, s) },
57930
- { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q, s, p) => this.handleReadFile(p[0], q, s) },
57931
- { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q, s, p) => this.handleWriteFile(p[0], q, s) },
57932
- { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/source$/, handler: (q, s, p) => this.handleSource(p[0], q, s) },
57933
- { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/save$/, handler: (q, s, p) => this.handleSave(p[0], q, s) },
57934
- { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/typeAndSend$/, handler: (q, s, p) => this.handleTypeAndSend(p[0], q, s) },
57935
- { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/typeAndSendAt$/, handler: (q, s, p) => this.handleTypeAndSendAt(p[0], q, s) },
57936
- { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/config$/, handler: (q, s, p) => this.handleProviderConfig(p[0], q, s) },
57937
- { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/dom-context$/, handler: (q, s, p) => this.handleDomContext(p[0], q, s) },
57938
- { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement$/, handler: (q, s, p) => this.handleAutoImplement(p[0], q, s) },
57939
- { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/cancel$/, handler: (q, s, p) => this.handleAutoImplCancel(p[0], q, s) },
57940
- { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/status$/, handler: (q, s, p) => this.handleAutoImplSSE(p[0], q, s) },
57941
- { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/spawn-test$/, handler: (q, s, p) => this.handleSpawnTest(p[0], q, s) },
57942
- { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/validate$/, handler: (q, s, p) => this.handleValidate(p[0], q, s) },
57943
- { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/acp-chat$/, handler: (q, s, p) => this.handleAcpChat(p[0], q, s) },
57944
- { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/script-hints$/, handler: (q, s, p) => this.handleScriptHints(p[0], q, s) }
58297
+ { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/script$/, handler: (q, s2, p) => this.handleRunScript(p[0], q, s2) },
58298
+ { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/files$/, handler: (q, s2, p) => this.handleListFiles(p[0], q, s2) },
58299
+ { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q, s2, p) => this.handleReadFile(p[0], q, s2) },
58300
+ { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q, s2, p) => this.handleWriteFile(p[0], q, s2) },
58301
+ { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/source$/, handler: (q, s2, p) => this.handleSource(p[0], q, s2) },
58302
+ { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/save$/, handler: (q, s2, p) => this.handleSave(p[0], q, s2) },
58303
+ { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/typeAndSend$/, handler: (q, s2, p) => this.handleTypeAndSend(p[0], q, s2) },
58304
+ { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/typeAndSendAt$/, handler: (q, s2, p) => this.handleTypeAndSendAt(p[0], q, s2) },
58305
+ { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/config$/, handler: (q, s2, p) => this.handleProviderConfig(p[0], q, s2) },
58306
+ { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/dom-context$/, handler: (q, s2, p) => this.handleDomContext(p[0], q, s2) },
58307
+ { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement$/, handler: (q, s2, p) => this.handleAutoImplement(p[0], q, s2) },
58308
+ { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/cancel$/, handler: (q, s2, p) => this.handleAutoImplCancel(p[0], q, s2) },
58309
+ { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/status$/, handler: (q, s2, p) => this.handleAutoImplSSE(p[0], q, s2) },
58310
+ { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/spawn-test$/, handler: (q, s2, p) => this.handleSpawnTest(p[0], q, s2) },
58311
+ { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/validate$/, handler: (q, s2, p) => this.handleValidate(p[0], q, s2) },
58312
+ { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/acp-chat$/, handler: (q, s2, p) => this.handleAcpChat(p[0], q, s2) },
58313
+ { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/script-hints$/, handler: (q, s2, p) => this.handleScriptHints(p[0], q, s2) }
57945
58314
  ];
57946
58315
  matchRoute(method, pathname) {
57947
58316
  for (const route of this.routes) {
@@ -58536,14 +58905,14 @@ var DevServer = class _DevServer {
58536
58905
  warnings.push(...validation.warnings);
58537
58906
  if (config.settings) {
58538
58907
  for (const [key, val] of Object.entries(config.settings)) {
58539
- const s = val;
58540
- if (!s.type) errors.push(`settings.${key}: missing type`);
58541
- else if (!["boolean", "number", "string", "select"].includes(s.type))
58542
- errors.push(`settings.${key}: invalid type '${s.type}'`);
58543
- if (s.default === void 0) warnings.push(`settings.${key}: no default value`);
58544
- if (s.type === "number" && s.min !== void 0 && s.max !== void 0 && s.min > s.max)
58545
- errors.push(`settings.${key}: min (${s.min}) > max (${s.max})`);
58546
- if (s.type === "select" && (!s.options || !Array.isArray(s.options) || s.options.length === 0))
58908
+ const s2 = val;
58909
+ if (!s2.type) errors.push(`settings.${key}: missing type`);
58910
+ else if (!["boolean", "number", "string", "select"].includes(s2.type))
58911
+ errors.push(`settings.${key}: invalid type '${s2.type}'`);
58912
+ if (s2.default === void 0) warnings.push(`settings.${key}: no default value`);
58913
+ if (s2.type === "number" && s2.min !== void 0 && s2.max !== void 0 && s2.min > s2.max)
58914
+ errors.push(`settings.${key}: min (${s2.min}) > max (${s2.max})`);
58915
+ if (s2.type === "select" && (!s2.options || !Array.isArray(s2.options) || s2.options.length === 0))
58547
58916
  errors.push(`settings.${key}: select type requires options[]`);
58548
58917
  }
58549
58918
  }