@adhdev/daemon-standalone 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
@@ -30036,10 +30036,10 @@ var require_dist3 = __commonJS({
30036
30036
  }
30037
30037
  function getDaemonBuildInfo() {
30038
30038
  if (cached2) return cached2;
30039
- const commit = readInjected(true ? "5d100a177f412ae29a58048f0a211c3928b06910" : void 0) ?? "unknown";
30040
- const commitShort = readInjected(true ? "5d100a17" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
30041
- const version2 = readInjected(true ? "0.9.82-rc.354" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
30042
- const builtAt = readInjected(true ? "2026-06-22T11:32:34.147Z" : void 0);
30039
+ const commit = readInjected(true ? "a45106605e2ae1c10c0bc6cbe48c2cac4e862ded" : void 0) ?? "unknown";
30040
+ const commitShort = readInjected(true ? "a4510660" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
30041
+ const version2 = readInjected(true ? "0.9.82-rc.355" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
30042
+ const builtAt = readInjected(true ? "2026-06-22T15:22:12.689Z" : void 0);
30043
30043
  cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
30044
30044
  return cached2;
30045
30045
  }
@@ -34593,9 +34593,12 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
34593
34593
  return [];
34594
34594
  }
34595
34595
  }
34596
- function updateDirectDispatchStatus(meshId, sessionId, status) {
34596
+ function updateDirectDispatchStatus(meshId, sessionId, status, taskId) {
34597
34597
  try {
34598
- MeshRuntimeStore.getInstance().updateDirectDispatchStatus(meshId, sessionId, status);
34598
+ if (!taskId) {
34599
+ LOG2.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)`);
34600
+ }
34601
+ MeshRuntimeStore.getInstance().updateDirectDispatchStatus(meshId, sessionId, status, taskId);
34599
34602
  } catch {
34600
34603
  }
34601
34604
  }
@@ -35440,9 +35443,25 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
35440
35443
  updatedAt: r.updated_at
35441
35444
  }));
35442
35445
  }
35443
- updateDirectDispatchStatus(meshId, sessionId, status) {
35444
- if (!sessionId) return;
35446
+ // CANON-B (dispatch identity): mesh_direct_dispatches is keyed by task_id (PK), but a
35447
+ // single session can host several sequential direct dispatches (re-dispatch / nudge), so
35448
+ // matching a status flip by session_id alone hits EVERY non-terminal row for that session
35449
+ // — flipping a sibling task's row and stranding the one whose event actually fired (the
35450
+ // assigned-stranded watchdog then requeues a task that is really still generating). When
35451
+ // the firing event carries a taskId, target the single PK row; the session_id match is the
35452
+ // legacy fallback only for events that arrive without a taskId.
35453
+ updateDirectDispatchStatus(meshId, sessionId, status, taskId) {
35445
35454
  const now = (/* @__PURE__ */ new Date()).toISOString();
35455
+ if (taskId) {
35456
+ this.db.prepare(`
35457
+ UPDATE mesh_direct_dispatches
35458
+ SET status = @status, updated_at = @updatedAt
35459
+ WHERE mesh_id = @meshId AND task_id = @taskId
35460
+ AND status NOT IN ('completed', 'failed')
35461
+ `).run({ status, meshId, taskId, updatedAt: now });
35462
+ return;
35463
+ }
35464
+ if (!sessionId) return;
35446
35465
  this.db.prepare(`
35447
35466
  UPDATE mesh_direct_dispatches
35448
35467
  SET status = @status, updated_at = @updatedAt
@@ -37169,7 +37188,7 @@ ${rendered}`, "utf-8");
37169
37188
  windowsHide: true
37170
37189
  }).trim();
37171
37190
  if (out) {
37172
- const matches = out.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
37191
+ const matches = out.split(/\r?\n/).map((s2) => s2.trim()).filter(Boolean);
37173
37192
  const direct = matches.find((m) => DIRECT_EXEC_EXT.has(path10.extname(m).toLowerCase()));
37174
37193
  return direct || matches[0] || command;
37175
37194
  }
@@ -38521,11 +38540,29 @@ Next step: ${nextStep}`;
38521
38540
  (pending) => pending.event === event.event && readRefineJobId2(pending) === jobId
38522
38541
  );
38523
38542
  }
38543
+ function isWeakCompletionMetadata(metadata) {
38544
+ const evidenceLevel = readNonEmptyString2(metadata.evidenceLevel);
38545
+ if (evidenceLevel === "insufficient" || evidenceLevel === "weak") return true;
38546
+ if (metadata.reviewRecommended === true) return true;
38547
+ const diag = readRecord4(metadata.completionDiagnostic);
38548
+ return diag?.finalAssistantPresent === false || diag?.blockReason === "missing_final_assistant";
38549
+ }
38524
38550
  function buildPendingEventFingerprint(event) {
38525
38551
  const metadata = readRecord4(event.metadataEvent) || {};
38526
38552
  if (event.event === "worktree_bootstrap_complete" || event.event === "worktree_bootstrap_failed") {
38527
38553
  return [event.meshId, event.event, event.nodeId || ""].join("::");
38528
38554
  }
38555
+ if (TERMINAL_COMPLETION_EVENTS.has(event.event)) {
38556
+ const terminalTaskId = readNonEmptyString2(metadata.taskId) || readNonEmptyString2(readRecord4(metadata.payload)?.taskId);
38557
+ if (terminalTaskId) {
38558
+ return [
38559
+ event.meshId,
38560
+ event.event,
38561
+ terminalTaskId,
38562
+ isWeakCompletionMetadata(metadata) ? "weak" : "genuine"
38563
+ ].join("::");
38564
+ }
38565
+ }
38529
38566
  const sessionId = resolveEventSessionId(metadata);
38530
38567
  const providerSessionId = readNonEmptyString2(metadata.providerSessionId);
38531
38568
  const taskId = readNonEmptyString2(metadata.taskId) || readNonEmptyString2(readRecord4(metadata.payload)?.taskId);
@@ -38888,6 +38925,7 @@ Next step: ${nextStep}`;
38888
38925
  var import_path9;
38889
38926
  var import_crypto7;
38890
38927
  var REFINE_TERMINAL_EVENTS;
38928
+ var TERMINAL_COMPLETION_EVENTS;
38891
38929
  var MAX_PENDING_EVENTS_BYTES;
38892
38930
  var MAX_PENDING_EVENTS_KEEP;
38893
38931
  var init_mesh_events_pending = __esm2({
@@ -38902,6 +38940,7 @@ Next step: ${nextStep}`;
38902
38940
  init_mesh_events_utils();
38903
38941
  init_dist();
38904
38942
  REFINE_TERMINAL_EVENTS = /* @__PURE__ */ new Set(["refine:completed", "refine:failed"]);
38943
+ TERMINAL_COMPLETION_EVENTS = /* @__PURE__ */ new Set(["agent:generating_completed", "agent:stopped"]);
38905
38944
  MAX_PENDING_EVENTS_BYTES = 100 * 1024;
38906
38945
  MAX_PENDING_EVENTS_KEEP = 50;
38907
38946
  }
@@ -39230,7 +39269,7 @@ Next step: ${nextStep}`;
39230
39269
  evidence
39231
39270
  }
39232
39271
  });
39233
- updateDirectDispatchStatus(args.meshId, args.sessionId, kind === "task_completed" ? "completed" : "failed");
39272
+ updateDirectDispatchStatus(args.meshId, args.sessionId, kind === "task_completed" ? "completed" : "failed", args.taskId);
39234
39273
  markSessionDeliveriesTerminal(args.meshId, args.sessionId, kind === "task_completed" ? "completed" : "failed");
39235
39274
  setImmediate(() => cleanupTerminalDirectDispatches());
39236
39275
  queuePendingMeshCoordinatorEvent({
@@ -39516,8 +39555,8 @@ Next step: ${nextStep}`;
39516
39555
  if (x instanceof RegExp) return x;
39517
39556
  if (x && typeof x === "object" && typeof x.source === "string") {
39518
39557
  try {
39519
- const s = x;
39520
- return new RegExp(s.source, s.flags || "");
39558
+ const s2 = x;
39559
+ return new RegExp(s2.source, s2.flags || "");
39521
39560
  } catch {
39522
39561
  return null;
39523
39562
  }
@@ -40091,6 +40130,36 @@ Next step: ${nextStep}`;
40091
40130
  UNRESOLVED_FORWARD_MAX_AGE_MS = 30 * 60 * 1e3;
40092
40131
  }
40093
40132
  });
40133
+ function s(v) {
40134
+ return typeof v === "string" && v.trim() ? v.trim() : "";
40135
+ }
40136
+ function meshEventTraceKey(ctx) {
40137
+ const segs = [`task=${s(ctx.taskId) || "-"}`];
40138
+ const eventId = s(ctx.eventId);
40139
+ if (eventId) segs.push(`evt=${eventId}`);
40140
+ segs.push(`sess=${s(ctx.sessionId) || "-"}`);
40141
+ const nodeId = s(ctx.nodeId);
40142
+ if (nodeId) segs.push(`node=${nodeId}`);
40143
+ const meshId = s(ctx.meshId);
40144
+ if (meshId) segs.push(`mesh=${meshId}`);
40145
+ const event = s(ctx.event);
40146
+ if (event) segs.push(`event=${event}`);
40147
+ return segs.join(" ");
40148
+ }
40149
+ function traceMeshEventStage(stage, ctx, detail) {
40150
+ LOG2.info(CAT, `[stage:${stage}] ${meshEventTraceKey(ctx)}${detail ? ` \u2014 ${detail}` : ""}`);
40151
+ }
40152
+ function traceMeshEventDrop(reason, ctx, detail) {
40153
+ LOG2.warn(CAT, `[drop:${reason}] ${meshEventTraceKey(ctx)}${detail ? ` \u2014 ${detail}` : ""}`);
40154
+ }
40155
+ var CAT;
40156
+ var init_mesh_event_trace = __esm2({
40157
+ "src/mesh/mesh-event-trace.ts"() {
40158
+ "use strict";
40159
+ init_logger();
40160
+ CAT = "EvtTrace";
40161
+ }
40162
+ });
40094
40163
  function isPlainObject22(value) {
40095
40164
  return !!value && typeof value === "object" && !Array.isArray(value);
40096
40165
  }
@@ -41884,9 +41953,9 @@ ${cleanBody}`;
41884
41953
  }
41885
41954
  function buildSessionEntries(allStates, cdpManagers, options = {}) {
41886
41955
  const sessions = [];
41887
- const ideStates = allStates.filter((s) => s.category === "ide");
41888
- const cliStates = allStates.filter((s) => s.category === "cli");
41889
- const acpStates = allStates.filter((s) => s.category === "acp");
41956
+ const ideStates = allStates.filter((s2) => s2.category === "ide");
41957
+ const cliStates = allStates.filter((s2) => s2.category === "cli");
41958
+ const acpStates = allStates.filter((s2) => s2.category === "acp");
41890
41959
  for (const state of ideStates) {
41891
41960
  sessions.push(buildWorkspaceSession(state, cdpManagers, options));
41892
41961
  for (const ext of state.extensions) {
@@ -42370,6 +42439,15 @@ ${cleanBody}`;
42370
42439
  meshByWorkspaceCache.set(workspace, { mesh, cachedAt: now });
42371
42440
  return mesh;
42372
42441
  }
42442
+ function recoverMeshIdByNodeId(nodeId) {
42443
+ if (!nodeId) return "";
42444
+ for (const mesh of listMeshes()) {
42445
+ if (Array.isArray(mesh.nodes) && mesh.nodes.some((n) => meshNodeIdMatches(n, nodeId))) {
42446
+ return readNonEmptyString2(mesh.id);
42447
+ }
42448
+ }
42449
+ return "";
42450
+ }
42373
42451
  function __resetIdleAutoFastForwardForTests() {
42374
42452
  idleAutoFastForwardLastAttempt.clear();
42375
42453
  }
@@ -43272,6 +43350,13 @@ ${cleanBody}`;
43272
43350
  function injectMeshSystemMessage(components, args) {
43273
43351
  const eventSessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
43274
43352
  const eventNodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
43353
+ const traceCtx = {
43354
+ taskId: args.metadataEvent.taskId,
43355
+ sessionId: eventSessionId,
43356
+ nodeId: eventNodeId,
43357
+ meshId: args.meshId,
43358
+ event: args.event
43359
+ };
43275
43360
  const sourceSession = args.sourceInstanceId ? components.instanceManager.getInstance(args.sourceInstanceId) : void 0;
43276
43361
  const workerCoordinatorDaemonId = readNonEmptyString2(
43277
43362
  sourceSession?.getState()?.settings?.meshCoordinatorDaemonId
@@ -43325,6 +43410,7 @@ ${cleanBody}`;
43325
43410
  }
43326
43411
  }
43327
43412
  LOG2.info("MeshEvents", `Suppressed ${args.event} for intentionally cleanup-stopped session ${eventSessionId || "(unknown session)"}`);
43413
+ traceMeshEventDrop("intentional_cleanup_stop", traceCtx);
43328
43414
  return { success: true, forwarded: 0, suppressed: true, intentionalCleanupStop: true };
43329
43415
  }
43330
43416
  if (args.event === "monitor:no_progress") {
@@ -43345,6 +43431,7 @@ ${cleanBody}`;
43345
43431
  }
43346
43432
  if (reconciledCompletion?.source === "no_progress_terminal_ledger_suppression") {
43347
43433
  LOG2.info("MeshEvents", `Suppressed no-progress monitor because terminal ledger evidence already exists for session ${eventSessionId || "(unknown session)"}`);
43434
+ traceMeshEventDrop("no_progress_terminal_ledger_suppression", traceCtx, `terminalKind=${reconciledCompletion.terminalLedgerKind}`);
43348
43435
  return {
43349
43436
  success: true,
43350
43437
  forwarded: 0,
@@ -43356,6 +43443,7 @@ ${cleanBody}`;
43356
43443
  }
43357
43444
  if (isDuplicateRefineTerminalEvent(args.meshId, args.event, args.metadataEvent)) {
43358
43445
  LOG2.info("MeshEvents", `Suppressed duplicate ${args.event} for refine job ${readRefineJobId({ metadataEvent: args.metadataEvent })}`);
43446
+ traceMeshEventDrop("duplicate_refine_terminal", traceCtx);
43359
43447
  return { success: true, forwarded: 0, suppressed: true, duplicateRefineTerminalEvent: true };
43360
43448
  }
43361
43449
  const eventTimestamp = readEventTimestamp(args.metadataEvent.timestamp);
@@ -43370,6 +43458,7 @@ ${cleanBody}`;
43370
43458
  });
43371
43459
  if (duplicateApproval) {
43372
43460
  LOG2.info("MeshEvents", `Suppressed duplicate approval event for mesh ${args.meshId} session ${eventSessionId}`);
43461
+ traceMeshEventDrop("duplicate_approval", traceCtx);
43373
43462
  return { success: true, forwarded: 0, suppressed: true, duplicateApproval: true };
43374
43463
  }
43375
43464
  }
@@ -43389,6 +43478,7 @@ ${cleanBody}`;
43389
43478
  const eventFinalSummary = readNonEmptyString2(args.metadataEvent.finalSummary);
43390
43479
  if (terminalProviderSessionId && terminalProviderSessionId === eventProviderSessionId || terminalFinalSummary && terminalFinalSummary === eventFinalSummary || args.metadataEvent.source === "no_progress_reconciliation") {
43391
43480
  LOG2.info("MeshEvents", `Suppressed duplicate completion with existing terminal ledger evidence for mesh ${args.meshId} session ${eventSessionId}`);
43481
+ traceMeshEventDrop("duplicate_completion_terminal_ledger", traceCtx);
43392
43482
  return { success: true, forwarded: 0, suppressed: true, duplicateCompletion: true, terminalLedgerEvidence: true };
43393
43483
  }
43394
43484
  }
@@ -43407,6 +43497,7 @@ ${cleanBody}`;
43407
43497
  });
43408
43498
  if (duplicateCompletion) {
43409
43499
  LOG2.info("MeshEvents", `Suppressed duplicate completion for mesh ${args.meshId} session ${eventSessionId}`);
43500
+ traceMeshEventDrop("duplicate_completion", traceCtx);
43410
43501
  return { success: true, forwarded: 0, suppressed: true, duplicateCompletion: true };
43411
43502
  }
43412
43503
  }
@@ -43425,6 +43516,7 @@ ${cleanBody}`;
43425
43516
  });
43426
43517
  if (duplicateStopped) {
43427
43518
  LOG2.info("MeshEvents", `Suppressed duplicate stopped event for mesh ${args.meshId} session ${eventSessionId}`);
43519
+ traceMeshEventDrop("duplicate_stopped", traceCtx);
43428
43520
  return { success: true, forwarded: 0, suppressed: true, duplicateStopped: true };
43429
43521
  }
43430
43522
  }
@@ -43436,7 +43528,7 @@ ${cleanBody}`;
43436
43528
  });
43437
43529
  const leaveDirectDispatchActive = !task && opts?.tentativeIfDirect === true;
43438
43530
  if (!leaveDirectDispatchActive) {
43439
- updateDirectDispatchStatus(args.meshId, sessionId, outcome);
43531
+ updateDirectDispatchStatus(args.meshId, sessionId, outcome, eventTaskId);
43440
43532
  }
43441
43533
  markSessionDeliveriesTerminal(args.meshId, sessionId, outcome);
43442
43534
  setImmediate(() => cleanupTerminalDirectDispatches());
@@ -43449,7 +43541,7 @@ ${cleanBody}`;
43449
43541
  const nodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
43450
43542
  const providerType = readNonEmptyString2(args.metadataEvent.providerType);
43451
43543
  if (sessionId) {
43452
- directDispatchTaskIdForLedger = resolveActiveDirectDispatchTaskId(args.meshId, sessionId);
43544
+ directDispatchTaskIdForLedger = readNonEmptyString2(args.metadataEvent.taskId) || resolveActiveDirectDispatchTaskId(args.meshId, sessionId);
43453
43545
  const isFalseIdle = isFalseIdleCompletion(args.metadataEvent);
43454
43546
  completedTaskForLedger = markSessionTerminal(sessionId, "completed", eventTimestamp, { tentativeIfDirect: isFalseIdle });
43455
43547
  if (nodeId && providerType) {
@@ -43532,7 +43624,8 @@ ${cleanBody}`;
43532
43624
  }
43533
43625
  }
43534
43626
  if (sessionId) {
43535
- updateDirectDispatchStatus(args.meshId, sessionId, "acked");
43627
+ const startedTaskId = readNonEmptyString2(args.metadataEvent.taskId) || void 0;
43628
+ updateDirectDispatchStatus(args.meshId, sessionId, "acked", startedTaskId);
43536
43629
  const activeDeliveries = (() => {
43537
43630
  try {
43538
43631
  return MeshRuntimeStore.getInstance().getActiveSessionDeliveries(args.meshId, sessionId);
@@ -43540,7 +43633,8 @@ ${cleanBody}`;
43540
43633
  return [];
43541
43634
  }
43542
43635
  })();
43543
- for (const d of activeDeliveries) {
43636
+ const deliveriesToAck = startedTaskId ? activeDeliveries.filter((d) => d.taskId === startedTaskId) : activeDeliveries;
43637
+ for (const d of deliveriesToAck) {
43544
43638
  updateSessionDeliveryStatus(d.id, "acked");
43545
43639
  }
43546
43640
  }
@@ -43554,7 +43648,7 @@ ${cleanBody}`;
43554
43648
  }
43555
43649
  }
43556
43650
  if (sessionId) {
43557
- directDispatchTaskIdForLedger = resolveActiveDirectDispatchTaskId(args.meshId, sessionId);
43651
+ directDispatchTaskIdForLedger = readNonEmptyString2(args.metadataEvent.taskId) || resolveActiveDirectDispatchTaskId(args.meshId, sessionId);
43558
43652
  completedTaskForLedger = markSessionTerminal(sessionId, "failed");
43559
43653
  }
43560
43654
  }
@@ -43700,6 +43794,9 @@ ${cleanBody}`;
43700
43794
  };
43701
43795
  if (queuePendingMeshCoordinatorEvent(pendingEvent)) {
43702
43796
  LOG2.info("MeshEvents", `Queued ${args.event} for coordinator (mesh ${args.meshId}${workerCoordinatorDaemonId ? `, coordinator daemon ${workerCoordinatorDaemonId}` : ""}${workerCoordinatorSessionId ? `, coordinator session ${workerCoordinatorSessionId}` : ""})`);
43797
+ traceMeshEventStage("queued", traceCtx, workerCoordinatorDaemonId ? `coordinatorDaemon=${workerCoordinatorDaemonId}` : "broadcast");
43798
+ } else {
43799
+ traceMeshEventDrop("queue_dedup", traceCtx);
43703
43800
  }
43704
43801
  return { success: true, forwarded: 0 };
43705
43802
  }
@@ -43710,8 +43807,23 @@ ${cleanBody}`;
43710
43807
  }
43711
43808
  const nodeId = readNonEmptyString2(payload.nodeId);
43712
43809
  const workspace = readNonEmptyString2(payload.workspace);
43713
- const meshId = readNonEmptyString2(payload.meshId) || (workspace ? readNonEmptyString2(getCachedMeshByWorkspace(workspace)?.id) : "");
43714
- if (!meshId) return { success: false, error: "meshId required" };
43810
+ const meshId = readNonEmptyString2(payload.meshId) || (workspace ? readNonEmptyString2(getCachedMeshByWorkspace(workspace)?.id) : "") || recoverMeshIdByNodeId(nodeId);
43811
+ if (!meshId) {
43812
+ traceMeshEventDrop("meshId_required", {
43813
+ taskId: payload.taskId,
43814
+ sessionId: readNonEmptyString2(payload.targetSessionId) || readNonEmptyString2(payload.sessionId),
43815
+ nodeId,
43816
+ event: eventName
43817
+ }, workspace ? `workspace=${workspace} unresolved` : "no workspace/nodeId");
43818
+ return { success: false, error: "meshId required" };
43819
+ }
43820
+ traceMeshEventStage("received", {
43821
+ taskId: payload.taskId,
43822
+ sessionId: readNonEmptyString2(payload.targetSessionId) || readNonEmptyString2(payload.sessionId),
43823
+ nodeId,
43824
+ meshId,
43825
+ event: eventName
43826
+ });
43715
43827
  const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
43716
43828
  const relayModalMessage = readNonEmptyString2(payload.modalMessage);
43717
43829
  const relayModalButtons = Array.isArray(payload.modalButtons) ? payload.modalButtons.filter((b) => typeof b === "string" && b.trim().length > 0) : null;
@@ -43792,9 +43904,18 @@ ${cleanBody}`;
43792
43904
  workspace: readNonEmptyString2(routing.workspace) || readNonEmptyString2(event.workspace) || void 0
43793
43905
  };
43794
43906
  const persisted = enqueueUnresolvedDelegateForward(coordinatorDaemonId, eventName, payload);
43907
+ const fwdTraceCtx = {
43908
+ taskId: payload.taskId,
43909
+ sessionId: readNonEmptyString2(payload.targetSessionId) || readNonEmptyString2(payload.sessionId),
43910
+ nodeId: readNonEmptyString2(routing.nodeId) || readNonEmptyString2(event.meshNodeId),
43911
+ event: eventName
43912
+ };
43913
+ traceMeshEventStage("outbox_enqueue", fwdTraceCtx, `coordinatorDaemon=${coordinatorDaemonId} meshId=absent`);
43914
+ traceMeshEventStage("forward_send", fwdTraceCtx, "immediate push");
43795
43915
  Promise.resolve(components.dispatchMeshCommand(coordinatorDaemonId, "mesh_forward_event", payload)).then((result) => {
43796
43916
  if (result && result.success === false) {
43797
43917
  LOG2.warn("MeshEvents", `Immediate forward of ${eventName} to coordinator ${coordinatorDaemonId} rejected (${readNonEmptyString2(result.error) || "no reason"}) \u2014 left queued for retry`);
43918
+ traceMeshEventDrop("immediate_forward_rejected", fwdTraceCtx, readNonEmptyString2(result.error) || "no reason");
43798
43919
  return;
43799
43920
  }
43800
43921
  if (persisted) ackUnresolvedDelegateForwardByFingerprint(coordinatorDaemonId, eventName, payload);
@@ -43862,6 +43983,14 @@ ${cleanBody}`;
43862
43983
  if (isUnroutableDelegateRejection(routing) && forwardUnresolvedDelegateEvent(components, routing, event)) {
43863
43984
  return;
43864
43985
  }
43986
+ if (isUnroutableDelegateRejection(routing)) {
43987
+ traceMeshEventDrop("unroutable", {
43988
+ taskId: event.meshActiveTaskId ?? event.taskId,
43989
+ sessionId: routing.sessionId,
43990
+ nodeId: routing.nodeId,
43991
+ event: event.event
43992
+ }, "no coordinator anchor / mesh_unresolved");
43993
+ }
43865
43994
  recordUnroutableDelegateEvent(routing, event.event);
43866
43995
  return;
43867
43996
  }
@@ -43909,6 +44038,7 @@ ${cleanBody}`;
43909
44038
  init_mesh_events_pending();
43910
44039
  init_mesh_routing();
43911
44040
  init_mesh_unresolved_forward_outbox();
44041
+ init_mesh_event_trace();
43912
44042
  init_snapshot();
43913
44043
  init_repo_mesh_types();
43914
44044
  init_dist();
@@ -44018,6 +44148,13 @@ ${cleanBody}`;
44018
44148
  function injectPendingIntoCoordinator(coordinator, pending) {
44019
44149
  if (!coordinator || !pending.coordinatorMessage) return;
44020
44150
  const force = shouldForceInjectMeshEvent(pending.event);
44151
+ traceMeshEventStage("surfaced", {
44152
+ taskId: pending.metadataEvent?.taskId,
44153
+ sessionId: pending.metadataEvent?.targetSessionId ?? pending.targetCoordinatorSessionId,
44154
+ nodeId: pending.nodeId,
44155
+ meshId: pending.meshId,
44156
+ event: pending.event
44157
+ }, force ? "force-inject" : "inject");
44021
44158
  coordinator.onEvent("send_message", {
44022
44159
  input: { text: pending.coordinatorMessage, textFallback: pending.coordinatorMessage },
44023
44160
  ...force ? { force: true } : {}
@@ -44076,6 +44213,13 @@ ${cleanBody}`;
44076
44213
  });
44077
44214
  if (reclaimed) {
44078
44215
  LOG2.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})`);
44216
+ traceMeshEventDrop("assigned_stranded_reclaim", {
44217
+ taskId: row.id,
44218
+ sessionId: row.assignedSessionId,
44219
+ nodeId: row.assignedNodeId,
44220
+ meshId,
44221
+ event: "agent:generating_completed"
44222
+ }, `unconfirmed ${Math.round((nowMs - dispatchedAtMs) / 1e3)}s \u2192 ${reclaimed.status}`);
44079
44223
  }
44080
44224
  }
44081
44225
  }
@@ -44235,6 +44379,13 @@ ${cleanBody}`;
44235
44379
  try {
44236
44380
  queuePendingMeshCoordinatorEvent(pending);
44237
44381
  LOG2.info("MeshReconcile", `Strict route hold: coordinator session ${wantSession} not live on mesh ${meshId} \u2014 re-queued (${pending.event})`);
44382
+ traceMeshEventDrop("strict_route_hold", {
44383
+ taskId: pending.metadataEvent?.taskId,
44384
+ sessionId: pending.metadataEvent?.targetSessionId ?? wantSession,
44385
+ nodeId: pending.nodeId,
44386
+ meshId,
44387
+ event: pending.event
44388
+ }, `coordinatorSession=${wantSession} not live`);
44238
44389
  } catch (e) {
44239
44390
  LOG2.warn("MeshReconcile", `Strict route re-queue failed for ${pending.event} on mesh ${meshId}: ${e?.message || e}`);
44240
44391
  }
@@ -44258,6 +44409,13 @@ ${cleanBody}`;
44258
44409
  }
44259
44410
  });
44260
44411
  LOG2.warn("MeshReconcile", `Strict route expire: coordinator session ${wantSession} never returned for mesh ${meshId} \u2014 recorded to ledger (recoverable), dropped (${pending.event})`);
44412
+ traceMeshEventDrop("strict_route_expired", {
44413
+ taskId: pending.metadataEvent?.taskId,
44414
+ sessionId: pending.metadataEvent?.targetSessionId ?? wantSession,
44415
+ nodeId: pending.nodeId,
44416
+ meshId,
44417
+ event: pending.event
44418
+ }, `coordinatorSession=${wantSession} never returned`);
44261
44419
  } catch (e) {
44262
44420
  LOG2.warn("MeshReconcile", `Failed to ledger-expire strict-unmatched ${pending.event} for mesh ${meshId}: ${e?.message || e}`);
44263
44421
  }
@@ -44269,15 +44427,24 @@ ${cleanBody}`;
44269
44427
  const entries = peekUnresolvedDelegateForwards();
44270
44428
  if (entries.length === 0) return;
44271
44429
  for (const entry of entries) {
44430
+ const entryTraceCtx = {
44431
+ taskId: entry.payload.taskId,
44432
+ sessionId: readNonEmptyString2(entry.payload.targetSessionId) || readNonEmptyString2(entry.payload.sessionId),
44433
+ nodeId: readNonEmptyString2(entry.payload.nodeId),
44434
+ event: readNonEmptyString2(entry.payload.event)
44435
+ };
44272
44436
  let result;
44273
44437
  try {
44438
+ traceMeshEventStage("forward_send", entryTraceCtx, `retry \u2192 ${entry.coordinatorDaemonId}`);
44274
44439
  result = await dispatchMeshCommand(entry.coordinatorDaemonId, "mesh_forward_event", entry.payload);
44275
44440
  } catch (e) {
44276
44441
  LOG2.warn("MeshReconcile", `Retry forward to coordinator ${entry.coordinatorDaemonId} failed: ${e?.message || e} \u2014 left queued`);
44442
+ traceMeshEventDrop("retry_forward_failed", entryTraceCtx, e?.message || String(e));
44277
44443
  continue;
44278
44444
  }
44279
44445
  if (result && result.success === false) {
44280
44446
  LOG2.warn("MeshReconcile", `Retry forward to coordinator ${entry.coordinatorDaemonId} rejected (${readNonEmptyString2(result.error) || "no reason"}) \u2014 left queued`);
44447
+ traceMeshEventDrop("retry_forward_rejected", entryTraceCtx, readNonEmptyString2(result.error) || "no reason");
44281
44448
  continue;
44282
44449
  }
44283
44450
  ackUnresolvedDelegateForward(entry.id);
@@ -44523,6 +44690,7 @@ ${cleanBody}`;
44523
44690
  init_mesh_events_coordinator();
44524
44691
  init_mesh_unresolved_forward_outbox();
44525
44692
  init_mesh_events_utils();
44693
+ init_mesh_event_trace();
44526
44694
  init_dist();
44527
44695
  init_mesh_work_queue();
44528
44696
  init_mesh_ledger();
@@ -45352,8 +45520,8 @@ ${cleanBody}`;
45352
45520
  }
45353
45521
  function isValidSource(x) {
45354
45522
  if (!x || typeof x !== "object") return false;
45355
- const s = x;
45356
- 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";
45523
+ const s2 = x;
45524
+ 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";
45357
45525
  }
45358
45526
  function deriveSourceName(url2) {
45359
45527
  const m = url2.match(/[/:]([^/:]+)\/([^/]+?)(?:\.git)?$/);
@@ -45409,7 +45577,7 @@ ${cleanBody}`;
45409
45577
  }
45410
45578
  function sourcesProviding(category, type) {
45411
45579
  const inventory = inventoryExternalSources();
45412
- return inventory.filter((s) => (s.providers[category] || []).includes(type)).map((s) => s.sourceName);
45580
+ return inventory.filter((s2) => (s2.providers[category] || []).includes(type)).map((s2) => s2.sourceName);
45413
45581
  }
45414
45582
  function resolveActiveSource(category, type, activeFile) {
45415
45583
  const candidates = sourcesProviding(category, type);
@@ -45617,10 +45785,10 @@ ${cleanBody}`;
45617
45785
  const footers = (spec.withFooter ?? []).map((f) => {
45618
45786
  if (f.kind === "regex") {
45619
45787
  const re = compile2(f.pattern, f.flags ?? "i");
45620
- return { test: (s) => re.test(s) };
45788
+ return { test: (s2) => re.test(s2) };
45621
45789
  }
45622
45790
  const needle = f.pattern.toLowerCase();
45623
- return { test: (s) => s.toLowerCase().includes(needle) };
45791
+ return { test: (s2) => s2.toLowerCase().includes(needle) };
45624
45792
  });
45625
45793
  return { prompt, footers };
45626
45794
  }
@@ -46495,7 +46663,7 @@ ${cont}` : cont;
46495
46663
  }
46496
46664
  resolveModal(buttonIndex) {
46497
46665
  const snap = this.transport.getSnapshot();
46498
- const parseApproval = typeof this.transport.runParseApproval === "function" ? (s) => this.transport.runParseApproval(s.recentOutputBuffer.slice(-500)) : (s) => this.runParseApproval(s);
46666
+ const parseApproval = typeof this.transport.runParseApproval === "function" ? (s2) => this.transport.runParseApproval(s2.recentOutputBuffer.slice(-500)) : (s2) => this.runParseApproval(s2);
46499
46667
  let modal = this.activeModal ?? parseApproval(snap);
46500
46668
  if (!modal && this.runner.hasParseSession()) {
46501
46669
  try {
@@ -49181,22 +49349,23 @@ ${lastSnapshot}`;
49181
49349
  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]));
49182
49350
  let idx = -1;
49183
49351
  for (const c of candidates) {
49352
+ let candIdx = -1;
49184
49353
  if (sec.anchor_last) {
49185
49354
  for (let i = total - 1; i >= 0; i--) {
49186
49355
  if (matchesCandidate(c, i)) {
49187
- idx = i;
49356
+ candIdx = i;
49188
49357
  break;
49189
49358
  }
49190
49359
  }
49191
49360
  } else {
49192
49361
  for (let i = 0; i < total; i++) {
49193
49362
  if (matchesCandidate(c, i)) {
49194
- idx = i;
49363
+ candIdx = i;
49195
49364
  break;
49196
49365
  }
49197
49366
  }
49198
49367
  }
49199
- if (idx !== -1) break;
49368
+ if (candIdx !== -1 && (idx === -1 || candIdx < idx)) idx = candIdx;
49200
49369
  }
49201
49370
  if (idx !== -1) {
49202
49371
  from = idx;
@@ -49248,7 +49417,7 @@ ${lastSnapshot}`;
49248
49417
  }
49249
49418
  function sectionText(sections, sectionId, fullScreen) {
49250
49419
  if (!sectionId) return fullScreen;
49251
- const found = sections.find((s) => s.id === sectionId);
49420
+ const found = sections.find((s2) => s2.id === sectionId);
49252
49421
  return found ? found.text : "";
49253
49422
  }
49254
49423
  function isRegexCondition(c) {
@@ -49414,10 +49583,10 @@ ${lastSnapshot}`;
49414
49583
  return !!raw && typeof raw === "object" && raw.$schema === "adhdev:cli/spec@4";
49415
49584
  }
49416
49585
  function initialState(spec) {
49417
- return spec.states.find((s) => s.initial) ?? spec.states[0];
49586
+ return spec.states.find((s2) => s2.initial) ?? spec.states[0];
49418
49587
  }
49419
49588
  function stateById(spec, id) {
49420
- return spec.states.find((s) => s.id === id);
49589
+ return spec.states.find((s2) => s2.id === id);
49421
49590
  }
49422
49591
  function outgoingTransitions(spec, stateId) {
49423
49592
  const matches = spec.transitions.filter((t) => {
@@ -49504,7 +49673,17 @@ ${lastSnapshot}`;
49504
49673
  const result = evaluateCondition(cond, sections, fullScreen, cursor, prevLines, legacyTrace, stateId);
49505
49674
  const kind = isRegex(cond) ? "regex" : "changed";
49506
49675
  const detail = isRegex(cond) ? `${cond.section ?? "*"}~/${cond.matches}/` : `cursor_above=${cond.cursor_above} changed=${cond.changed}`;
49507
- return { kind, result, detail };
49676
+ let matchedText;
49677
+ if (result && isRegex(cond)) {
49678
+ try {
49679
+ const hay = sectionText(sections, cond.section, fullScreen);
49680
+ const re = new RegExp(cond.matches, cond.flags ?? "i");
49681
+ const m = re.exec(hay);
49682
+ if (m && m[0]) matchedText = m[0].replace(/\s+/g, " ").trim().slice(0, 160);
49683
+ } catch {
49684
+ }
49685
+ }
49686
+ return matchedText ? { kind, result, detail, matchedText } : { kind, result, detail };
49508
49687
  }
49509
49688
  return { kind: "all", result: false, detail: "unknown condition" };
49510
49689
  }
@@ -49617,17 +49796,17 @@ ${lastSnapshot}`;
49617
49796
  }
49618
49797
  const ids = /* @__PURE__ */ new Set();
49619
49798
  let initialCount = 0;
49620
- for (const [i, s] of spec.states.entries()) {
49621
- if (!s.id) {
49799
+ for (const [i, s2] of spec.states.entries()) {
49800
+ if (!s2.id) {
49622
49801
  errs.push(`states[${i}].id is required`);
49623
49802
  continue;
49624
49803
  }
49625
- if (ids.has(s.id)) errs.push(`states[${i}].id "${s.id}" is duplicated`);
49626
- ids.add(s.id);
49627
- if (!s.label) errs.push(`states[${i}].label is required`);
49628
- if (s.initial) initialCount += 1;
49629
- if (s.status && !["idle", "generating", "approval"].includes(s.status)) {
49630
- errs.push(`states[${i}].status "${s.status}" must be idle|generating|approval`);
49804
+ if (ids.has(s2.id)) errs.push(`states[${i}].id "${s2.id}" is duplicated`);
49805
+ ids.add(s2.id);
49806
+ if (!s2.label) errs.push(`states[${i}].label is required`);
49807
+ if (s2.initial) initialCount += 1;
49808
+ if (s2.status && !["idle", "generating", "approval"].includes(s2.status)) {
49809
+ errs.push(`states[${i}].status "${s2.status}" must be idle|generating|approval`);
49631
49810
  }
49632
49811
  }
49633
49812
  if (initialCount === 0) errs.push("exactly one state must have initial:true (none found)");
@@ -49643,10 +49822,10 @@ ${lastSnapshot}`;
49643
49822
  else if (!ids.has(t.to)) errs.push(`transitions[${i}].to references unknown state "${t.to}"`);
49644
49823
  if (t.when) errs.push(...validateCondition(t.when, sectionIds, `transitions[${i}].when`));
49645
49824
  }
49646
- for (const [i, s] of spec.states.entries()) {
49647
- const sec = s.extract?.title?.section;
49825
+ for (const [i, s2] of spec.states.entries()) {
49826
+ const sec = s2.extract?.title?.section;
49648
49827
  if (sec && !sectionIds.has(sec)) errs.push(`states[${i}].extract.title.section "${sec}" unknown`);
49649
- const bsec = s.extract?.buttons?.section;
49828
+ const bsec = s2.extract?.buttons?.section;
49650
49829
  if (bsec && !sectionIds.has(bsec)) errs.push(`states[${i}].extract.buttons.section "${bsec}" unknown`);
49651
49830
  }
49652
49831
  return errs;
@@ -62273,10 +62452,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
62273
62452
  const path422 = require("path");
62274
62453
  const { spawnSync: spawnSync2 } = require("child_process");
62275
62454
  const file2 = ext.loadExternalSources();
62276
- if (file2.sources.some((s) => s.name === requestedName)) {
62455
+ if (file2.sources.some((s2) => s2.name === requestedName)) {
62277
62456
  return { success: false, error: `source name "${requestedName}" is already registered` };
62278
62457
  }
62279
- if (file2.sources.some((s) => s.url === url2 && s.ref === ref)) {
62458
+ if (file2.sources.some((s2) => s2.url === url2 && s2.ref === ref)) {
62280
62459
  return { success: false, error: `source url+ref already registered (use a different name to track another ref)` };
62281
62460
  }
62282
62461
  const sourceDir = path422.join(ext.externalRoot(), requestedName);
@@ -62338,7 +62517,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
62338
62517
  const fs322 = require("fs");
62339
62518
  const path422 = require("path");
62340
62519
  const file2 = ext.loadExternalSources();
62341
- const match = file2.sources.find((s) => s.name === name);
62520
+ const match = file2.sources.find((s2) => s2.name === name);
62342
62521
  if (!match) return { success: false, error: `source "${name}" not registered` };
62343
62522
  const sourceDir = path422.join(ext.externalRoot(), name);
62344
62523
  if (fs322.existsSync(sourceDir)) {
@@ -62350,7 +62529,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
62350
62529
  }
62351
62530
  ext.saveExternalSources({
62352
62531
  schema: 1,
62353
- sources: file2.sources.filter((s) => s.name !== name)
62532
+ sources: file2.sources.filter((s2) => s2.name !== name)
62354
62533
  });
62355
62534
  const active = ext.loadProvidersActive();
62356
62535
  const filteredActive = {};
@@ -62374,10 +62553,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
62374
62553
  const file2 = ext.loadExternalSources();
62375
62554
  const inventory = ext.inventoryExternalSources();
62376
62555
  const active = ext.loadProvidersActive();
62377
- const sources = file2.sources.map((s) => {
62378
- const inv = inventory.find((e) => e.sourceName === s.name);
62556
+ const sources = file2.sources.map((s2) => {
62557
+ const inv = inventory.find((e) => e.sourceName === s2.name);
62379
62558
  return {
62380
- ...s,
62559
+ ...s2,
62381
62560
  providers: inv?.providers ?? {}
62382
62561
  };
62383
62562
  });
@@ -62544,6 +62723,21 @@ ${formatManifestValidationIssues2(validation.issues)}`,
62544
62723
  var path21 = __toESM2(require("path"));
62545
62724
  init_terminal_screen();
62546
62725
  var import_session_host_core6 = require_dist();
62726
+ var MAX_PTY_EVENTS = 300;
62727
+ var EVENT_CONTENT_CAP = 240;
62728
+ function escapeControl(text) {
62729
+ return String(text).replace(/[\x00-\x1f\x7f]/g, (ch) => {
62730
+ const code = ch.charCodeAt(0);
62731
+ if (ch === "\r") return "\\r";
62732
+ if (ch === "\n") return "\\n";
62733
+ if (ch === " ") return "\\t";
62734
+ if (code === 27) return "\\x1b";
62735
+ return "\\x" + code.toString(16).padStart(2, "0");
62736
+ });
62737
+ }
62738
+ function capPreview(text) {
62739
+ return text.length > EVENT_CONTENT_CAP ? text.slice(0, EVENT_CONTENT_CAP) + `\u2026(+${text.length - EVENT_CONTENT_CAP})` : text;
62740
+ }
62547
62741
  var TerminalAdapter = class {
62548
62742
  constructor(opts, handlers) {
62549
62743
  this.opts = opts;
@@ -62570,6 +62764,9 @@ ${formatManifestValidationIssues2(validation.issues)}`,
62570
62764
  screenTimer = null;
62571
62765
  tickTimer = null;
62572
62766
  lastScreen = "";
62767
+ /** Debug-only ring buffer of PTY input/output/resize/cursor events. */
62768
+ events = [];
62769
+ lastCursorKey = "";
62573
62770
  start() {
62574
62771
  const env2 = this.opts.envIsComplete ? this.opts.env ?? {} : { ...process.env, ...this.opts.env ?? {} };
62575
62772
  this.pty = this.factory.spawn(this.opts.binary, this.opts.args ?? [], {
@@ -62578,10 +62775,12 @@ ${formatManifestValidationIssues2(validation.issues)}`,
62578
62775
  cols: this.cols,
62579
62776
  rows: this.rows
62580
62777
  });
62778
+ this.recordEvent("spawn", `${this.opts.binary} (${this.cols}x${this.rows})`);
62581
62779
  this.handlers.init?.({ pid: this.pty.pid });
62582
62780
  this.pty.onData((chunk) => this.onChunk(chunk));
62583
62781
  this.pty.onExit((info) => {
62584
62782
  this.stopTimers();
62783
+ this.recordEvent("exit", `exitCode=${typeof info.exitCode === "number" ? info.exitCode : 0}`);
62585
62784
  this.handlers.on_exit?.({ exitCode: typeof info.exitCode === "number" ? info.exitCode : 0 });
62586
62785
  this.pty = null;
62587
62786
  });
@@ -62592,6 +62791,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
62592
62791
  resize(cols, rows) {
62593
62792
  this.cols = cols;
62594
62793
  this.rows = rows;
62794
+ this.recordEvent("resize", `${cols}x${rows}`);
62595
62795
  this.pty?.resize(cols, rows);
62596
62796
  this.screen.resize(rows, cols);
62597
62797
  }
@@ -62612,8 +62812,21 @@ ${formatManifestValidationIssues2(validation.issues)}`,
62612
62812
  return { row: pos.row, col: pos.col };
62613
62813
  }
62614
62814
  send_keys(text) {
62815
+ this.recordEvent("input", capPreview(escapeControl(text)), text.length);
62615
62816
  this.pty?.write(text);
62616
62817
  }
62818
+ /** Debug-only: most-recent PTY input/output/resize/cursor events, oldest
62819
+ * first. Pure observation — never consulted by the FSM. */
62820
+ getEventTimeline(limit = MAX_PTY_EVENTS) {
62821
+ const n = Math.max(0, Math.min(limit, this.events.length));
62822
+ return this.events.slice(this.events.length - n);
62823
+ }
62824
+ recordEvent(kind, content, bytes) {
62825
+ const ev = { ts: Date.now(), kind, content };
62826
+ if (typeof bytes === "number") ev.bytes = bytes;
62827
+ this.events.push(ev);
62828
+ if (this.events.length > MAX_PTY_EVENTS) this.events.splice(0, this.events.length - MAX_PTY_EVENTS);
62829
+ }
62617
62830
  kill() {
62618
62831
  this.stopTimers();
62619
62832
  try {
@@ -62624,6 +62837,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
62624
62837
  this.screen.dispose();
62625
62838
  }
62626
62839
  onChunk(chunk) {
62840
+ this.recordEvent("output", capPreview(escapeControl(chunk)), chunk.length);
62627
62841
  try {
62628
62842
  this.handlers.on_pty_data?.(chunk);
62629
62843
  } catch {
@@ -62633,6 +62847,12 @@ ${formatManifestValidationIssues2(validation.issues)}`,
62633
62847
  this.screenTimer = setTimeout(() => {
62634
62848
  this.screenTimer = null;
62635
62849
  const snap = this.computeScreen();
62850
+ const cur = this.screen.getCursorPosition();
62851
+ const curKey = `${cur.row},${cur.col}`;
62852
+ if (curKey !== this.lastCursorKey) {
62853
+ this.lastCursorKey = curKey;
62854
+ this.recordEvent("cursor", `(${cur.row},${cur.col})`);
62855
+ }
62636
62856
  if (snap === this.lastScreen) return;
62637
62857
  this.lastScreen = snap;
62638
62858
  try {
@@ -62711,20 +62931,40 @@ ${formatManifestValidationIssues2(validation.issues)}`,
62711
62931
  }
62712
62932
  }
62713
62933
  init_logger();
62714
- function countNewlines(s) {
62934
+ function countNewlines(s2) {
62715
62935
  let n = 0;
62716
- for (let i = 0; i < s.length; i += 1) if (s.charCodeAt(i) === 10) n += 1;
62936
+ for (let i = 0; i < s2.length; i += 1) if (s2.charCodeAt(i) === 10) n += 1;
62717
62937
  return n;
62718
62938
  }
62719
62939
  var SUBMIT_DELAY_FLOOR_MS = 200;
62720
62940
  var WIN32_SUBMIT_RESEND_GAP_MS = 350;
62721
62941
  var WIN32_SUBMIT_MAX_RESENDS = 14;
62942
+ var WIN32_SUBMIT_SETTLE_MS = 500;
62943
+ var WIN32_SUBMIT_MAX_SETTLE_WAIT_MS = 1e4;
62944
+ var WIN32_SUBMIT_SETTLE_POLL_MS = 120;
62945
+ var WIN32_PTY_WRITE_CHUNK_CHARS = 1024;
62946
+ var WIN32_PTY_WRITE_CHUNK_GAP_MS = 8;
62722
62947
  function resolveSubmitDelayMs(specBeforeSubmit, text) {
62723
62948
  const lines = countNewlines(text);
62724
62949
  const linesBonus = Math.min(800, lines * 80);
62725
62950
  const spec = typeof specBeforeSubmit === "number" && specBeforeSubmit > 0 ? specBeforeSubmit : 0;
62726
62951
  return Math.max(spec, SUBMIT_DELAY_FLOOR_MS + linesBonus);
62727
62952
  }
62953
+ function chunkPreservingSurrogates(text, size) {
62954
+ const chunks = [];
62955
+ let offset = 0;
62956
+ while (offset < text.length) {
62957
+ let end = Math.min(text.length, offset + size);
62958
+ if (end < text.length) {
62959
+ const code = text.charCodeAt(end - 1);
62960
+ if (code >= 55296 && code <= 56319) end -= 1;
62961
+ }
62962
+ if (end <= offset) end = Math.min(text.length, offset + size);
62963
+ chunks.push(text.slice(offset, end));
62964
+ offset = end;
62965
+ }
62966
+ return chunks;
62967
+ }
62728
62968
  function guessExt(mime) {
62729
62969
  if (/png/i.test(mime)) return ".png";
62730
62970
  if (/jpe?g/i.test(mime)) return ".jpg";
@@ -62740,7 +62980,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
62740
62980
  this.buildAdapterOpts(),
62741
62981
  {
62742
62982
  init: () => this.emitInitialState(),
62743
- on_pty_data: (chunk) => this.emit({ kind: "pty_data", chunk }),
62983
+ on_pty_data: (chunk) => {
62984
+ this.lastPtyDataAt = Date.now();
62985
+ this.emit({ kind: "pty_data", chunk });
62986
+ },
62744
62987
  on_screen_changed: () => this.reevaluate(),
62745
62988
  on_exit: ({ exitCode }) => this.handleExit(exitCode)
62746
62989
  }
@@ -62774,6 +63017,16 @@ ${formatManifestValidationIssues2(validation.issues)}`,
62774
63017
  * WIN32_SUBMIT_* and scheduleWin32Submit). Re-arms itself until the FSM
62775
63018
  * leaves idle (submitted) or the resend budget is spent. */
62776
63019
  win32SubmitTimer = null;
63020
+ /** Wall-clock (ms) of the most recent raw PTY output chunk. Advances on every
63021
+ * on_pty_data — including the echo of text written into the composer — so the
63022
+ * win32 submit settle-gate can tell when input has finished landing. */
63023
+ lastPtyDataAt = 0;
63024
+ /** Wall-clock (ms) of the most recent win32 message-body input write. Bridges
63025
+ * the gap between writing a chunk and its echo so the settle-gate does not
63026
+ * declare "quiet" mid-write. */
63027
+ lastWin32WriteAt = 0;
63028
+ /** Pending paced chunk-write timer for a large win32 body (see writeWin32Body). */
63029
+ win32WriteTimer = null;
62777
63030
  currentEval = null;
62778
63031
  stateHistory = [];
62779
63032
  prevStateAt = 0;
@@ -62894,6 +63147,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
62894
63147
  clearTimeout(this.win32SubmitTimer);
62895
63148
  this.win32SubmitTimer = null;
62896
63149
  }
63150
+ if (this.win32WriteTimer) {
63151
+ clearTimeout(this.win32WriteTimer);
63152
+ this.win32WriteTimer = null;
63153
+ }
62897
63154
  this.specWatcher?.close();
62898
63155
  this.adapter.kill();
62899
63156
  }
@@ -62924,11 +63181,15 @@ ${formatManifestValidationIssues2(validation.issues)}`,
62924
63181
  getFsmSnapshotHistory() {
62925
63182
  return this.fsmSnapshotHistory;
62926
63183
  }
63184
+ /** Debug-only PTY input/output/resize/cursor timeline from the adapter. */
63185
+ getEventTimeline(limit) {
63186
+ return this.adapter.getEventTimeline(limit);
63187
+ }
62927
63188
  getSections() {
62928
63189
  try {
62929
63190
  const screen = this.adapter.snapshot();
62930
63191
  const lines = screen.split("\n").map((l) => l.endsWith("\r") ? l.slice(0, -1) : l);
62931
- return resolveSections(this.spec.sections ?? {}, lines).map((s) => ({ id: s.id, text: s.text }));
63192
+ return resolveSections(this.spec.sections ?? {}, lines).map((s2) => ({ id: s2.id, text: s2.text }));
62932
63193
  } catch {
62933
63194
  return null;
62934
63195
  }
@@ -63306,7 +63567,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
63306
63567
  const perChar = sm.delay_ms_per_char ?? 0;
63307
63568
  const beforeSubmit = resolveSubmitDelayMs(sm.delay_ms_before_submit, text);
63308
63569
  if (process.platform === "win32") {
63309
- this.adapter.send_keys(text);
63570
+ this.writeWin32Body(text);
63310
63571
  this.scheduleWin32Submit(sm.submit_key, beforeSubmit);
63311
63572
  return;
63312
63573
  }
@@ -63332,20 +63593,72 @@ ${formatManifestValidationIssues2(validation.issues)}`,
63332
63593
  const st = stateById(this.spec, this.currentStateId);
63333
63594
  return st ? statusForState(st) : "idle";
63334
63595
  }
63596
+ /** Record a win32 body write so the settle-gate counts it as input activity
63597
+ * even before the echo arrives. */
63598
+ markWin32Write() {
63599
+ this.lastWin32WriteAt = Date.now();
63600
+ }
63601
+ /** Most recent win32 input activity — a write we issued OR a PTY output chunk
63602
+ * (echo). The submit settle-gate waits for this to go quiet. */
63603
+ lastWin32InputActivityAt() {
63604
+ return Math.max(this.lastPtyDataAt, this.lastWin32WriteAt);
63605
+ }
63606
+ /**
63607
+ * Write the message body to the PTY for win32, paced into bounded chunks. A
63608
+ * single unbounded ConPTY write can overflow the input pipe and drop leading
63609
+ * bytes; splitting it with a short inter-chunk gap keeps the console input
63610
+ * buffer from overflowing. Small bodies still go out in a single write. Each
63611
+ * chunk advances lastWin32WriteAt so the submit settle-gate keeps waiting until
63612
+ * the final chunk is out and echoed.
63613
+ */
63614
+ writeWin32Body(text) {
63615
+ if (this.win32WriteTimer) {
63616
+ clearTimeout(this.win32WriteTimer);
63617
+ this.win32WriteTimer = null;
63618
+ }
63619
+ if (text.length <= WIN32_PTY_WRITE_CHUNK_CHARS) {
63620
+ this.markWin32Write();
63621
+ this.adapter.send_keys(text);
63622
+ return;
63623
+ }
63624
+ const chunks = chunkPreservingSurrogates(text, WIN32_PTY_WRITE_CHUNK_CHARS);
63625
+ let idx = 0;
63626
+ const writeNext = () => {
63627
+ this.win32WriteTimer = null;
63628
+ if (idx >= chunks.length) return;
63629
+ this.markWin32Write();
63630
+ this.adapter.send_keys(chunks[idx]);
63631
+ idx += 1;
63632
+ if (idx < chunks.length) {
63633
+ this.win32WriteTimer = setTimeout(writeNext, WIN32_PTY_WRITE_CHUNK_GAP_MS);
63634
+ }
63635
+ };
63636
+ writeNext();
63637
+ }
63335
63638
  /**
63336
- * win32 verification-based submit. Sends the submit key, waits a gap, and if
63337
- * the FSM is still 'idle' (the prompt did not submit — the CR was absorbed as
63338
- * a multiline-paste newline) resends, up to WIN32_SUBMIT_MAX_RESENDS. The
63339
- * first CR always fires (so a stale/edge status never suppresses the submit);
63340
- * subsequent resends are gated on still being idle, and stop the instant the
63341
- * agent leaves idle (submitted generating / approval). This converges the
63342
- * nondeterministic multiline window without spamming Enter into the next turn.
63639
+ * win32 submit. Two phases:
63640
+ *
63641
+ * Phase 1 (settle-gate): hold the first CR until the PTY output has been quiet
63642
+ * for WIN32_SUBMIT_SETTLE_MS after the last input write i.e. the full
63643
+ * (possibly multi-KB / multiline) body has finished arriving in the composer
63644
+ * and echoing. Honors an initial minimum delay and is bounded by
63645
+ * WIN32_SUBMIT_MAX_SETTLE_WAIT_MS so a noisy screen can never hang the submit.
63646
+ * This is what stops a long message from being submitted half-arrived (its
63647
+ * leading lines lost). A short message settles almost immediately.
63648
+ *
63649
+ * Phase 2 (verified resend — unchanged): send the submit key, wait a gap, and
63650
+ * if the FSM is still 'idle' (the CR was absorbed as a multiline-paste
63651
+ * newline) resend, up to WIN32_SUBMIT_MAX_RESENDS. The first CR always fires
63652
+ * (a stale/edge status never suppresses it); resends are gated on still being
63653
+ * idle and stop the instant the agent leaves idle (submitted → generating /
63654
+ * approval). This preserves the win32 lone-CR-swallow handling.
63343
63655
  */
63344
63656
  scheduleWin32Submit(submitKey, initialDelayMs) {
63345
63657
  if (this.win32SubmitTimer) {
63346
63658
  clearTimeout(this.win32SubmitTimer);
63347
63659
  this.win32SubmitTimer = null;
63348
63660
  }
63661
+ const startedAt = Date.now();
63349
63662
  const fire = (attempt) => {
63350
63663
  this.win32SubmitTimer = null;
63351
63664
  this.adapter.send_keys(submitKey);
@@ -63358,8 +63671,20 @@ ${formatManifestValidationIssues2(validation.issues)}`,
63358
63671
  fire(attempt + 1);
63359
63672
  }, WIN32_SUBMIT_RESEND_GAP_MS);
63360
63673
  };
63361
- if (initialDelayMs > 0) this.win32SubmitTimer = setTimeout(() => fire(0), initialDelayMs);
63362
- else fire(0);
63674
+ const waitForSettle = () => {
63675
+ this.win32SubmitTimer = null;
63676
+ const now = Date.now();
63677
+ const quietFor = now - this.lastWin32InputActivityAt();
63678
+ const waited = now - startedAt;
63679
+ if (quietFor >= WIN32_SUBMIT_SETTLE_MS || waited >= WIN32_SUBMIT_MAX_SETTLE_WAIT_MS) {
63680
+ fire(0);
63681
+ return;
63682
+ }
63683
+ const recheckIn = Math.min(WIN32_SUBMIT_SETTLE_MS - quietFor, WIN32_SUBMIT_SETTLE_POLL_MS);
63684
+ this.win32SubmitTimer = setTimeout(waitForSettle, Math.max(recheckIn, 30));
63685
+ };
63686
+ if (initialDelayMs > 0) this.win32SubmitTimer = setTimeout(waitForSettle, initialDelayMs);
63687
+ else waitForSettle();
63363
63688
  }
63364
63689
  handleClickControl(controlId, payload) {
63365
63690
  const ctl = (this.spec.control_bar ?? []).find((c) => c.id === controlId);
@@ -63472,7 +63797,8 @@ ${formatManifestValidationIssues2(validation.issues)}`,
63472
63797
  return out;
63473
63798
  }
63474
63799
  function flattenCond(c, out, depth) {
63475
- out.push(`${" ".repeat(depth)}${c.kind} ${c.detail} = ${c.result}${c.remainingMs ? ` (${c.remainingMs}ms left)` : ""}`);
63800
+ const matched = c.matchedText ? ` matched=${JSON.stringify(c.matchedText)}` : "";
63801
+ out.push(`${" ".repeat(depth)}${c.kind} ${c.detail} = ${c.result}${c.remainingMs ? ` (${c.remainingMs}ms left)` : ""}${matched}`);
63476
63802
  for (const child of c.children ?? []) flattenCond(child, out, depth + 1);
63477
63803
  }
63478
63804
  function findStable(c) {
@@ -64188,8 +64514,8 @@ ${formatManifestValidationIssues2(validation.issues)}`,
64188
64514
  }
64189
64515
  return null;
64190
64516
  }
64191
- function oneLine(s, max) {
64192
- const flat = s.replace(/\s+/g, " ").trim();
64517
+ function oneLine(s2, max) {
64518
+ const flat = s2.replace(/\s+/g, " ").trim();
64193
64519
  return flat.length > max ? flat.slice(0, max - 1) + "\u2026" : flat;
64194
64520
  }
64195
64521
  function parseTimestamp(v) {
@@ -64209,10 +64535,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
64209
64535
  return null;
64210
64536
  }
64211
64537
  function normalizeRole(r) {
64212
- const s = String(r ?? "").toLowerCase();
64213
- if (s === "user" || s === "human" || s === "user_explicit") return "user";
64214
- if (s === "assistant" || s === "ai" || s === "model") return "assistant";
64215
- if (s === "tool" || s === "tool_result" || s === "function") return "assistant";
64538
+ const s2 = String(r ?? "").toLowerCase();
64539
+ if (s2 === "user" || s2 === "human" || s2 === "user_explicit") return "user";
64540
+ if (s2 === "assistant" || s2 === "ai" || s2 === "model") return "assistant";
64541
+ if (s2 === "tool" || s2 === "tool_result" || s2 === "function") return "assistant";
64216
64542
  return "system";
64217
64543
  }
64218
64544
  function stringifyContent(v) {
@@ -64260,18 +64586,18 @@ ${formatManifestValidationIssues2(validation.issues)}`,
64260
64586
  return (record2) => ors.some((ands) => ands.every((t) => evalTerm(t, record2)));
64261
64587
  }
64262
64588
  function parseTerm(src) {
64263
- let s = src.trim();
64589
+ let s2 = src.trim();
64264
64590
  let negate = false;
64265
- if (s.startsWith("!")) {
64591
+ if (s2.startsWith("!")) {
64266
64592
  negate = true;
64267
- s = s.slice(1).trim();
64593
+ s2 = s2.slice(1).trim();
64268
64594
  }
64269
- const fnMatch = s.match(/^(startsWith|endsWith|contains)\s*\(\s*(.+?)\s*,\s*(.+?)\s*\)$/);
64595
+ const fnMatch = s2.match(/^(startsWith|endsWith|contains)\s*\(\s*(.+?)\s*,\s*(.+?)\s*\)$/);
64270
64596
  if (fnMatch) {
64271
64597
  const [, op2, pathExpr, litExpr] = fnMatch;
64272
64598
  return { path: pathExpr, op: op2, lit: parseLiteral(litExpr), negate };
64273
64599
  }
64274
- const opMatch = s.match(/^(.+?)\s*(==|!=|>=|<=|>|<)\s*(.+)$/);
64600
+ const opMatch = s2.match(/^(.+?)\s*(==|!=|>=|<=|>|<)\s*(.+)$/);
64275
64601
  if (!opMatch) return null;
64276
64602
  const [, lhs, op, rhsRaw] = opMatch;
64277
64603
  return { path: lhs.trim(), op, lit: parseLiteral(rhsRaw.trim()), negate };
@@ -64701,7 +65027,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
64701
65027
  try {
64702
65028
  const sections = this.driver.getSections();
64703
65029
  if (sectionId && sections) {
64704
- const hit = sections.find((s) => s.id === sectionId);
65030
+ const hit = sections.find((s2) => s2.id === sectionId);
64705
65031
  if (hit) return hit.text;
64706
65032
  }
64707
65033
  return this.driver.getScreen();
@@ -64716,7 +65042,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
64716
65042
  screen = this.driver.snapshot();
64717
65043
  const driverSections = this.driver.getSections?.();
64718
65044
  if (driverSections) {
64719
- sections = Object.fromEntries(driverSections.map((s) => [s.id, s.text]));
65045
+ sections = Object.fromEntries(driverSections.map((s2) => [s2.id, s2.text]));
64720
65046
  } else {
64721
65047
  sections = this.readCurrentScreenSections(screen);
64722
65048
  }
@@ -64762,6 +65088,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
64762
65088
  // answers "why did this rule fire" after the fact, unlike the live
64763
65089
  // `fsm` field which only reflects the current instant.
64764
65090
  fsmHistory: this.driver.getFsmSnapshotHistory?.() ?? null,
65091
+ // PTY input/output/resize/cursor event timeline (debug-only) so the
65092
+ // snapshot shows what we typed / what the PTY printed around each
65093
+ // status transition. Null for drivers without the timeline.
65094
+ eventTimeline: this.driver.getEventTimeline?.() ?? null,
64765
65095
  // Extended fields
64766
65096
  name: this.cliName,
64767
65097
  status: this.getStatus().status,
@@ -65126,6 +65456,8 @@ ${formatManifestValidationIssues2(validation.issues)}`,
65126
65456
  // v4 FSM transition snapshot history — the captured pre-transition
65127
65457
  // evaluation table at each transition (null for v3 specs).
65128
65458
  fsmHistory: this.driver.getFsmSnapshotHistory?.() ?? null,
65459
+ // PTY input/output/resize/cursor event timeline (debug-only).
65460
+ eventTimeline: this.driver.getEventTimeline?.() ?? null,
65129
65461
  messages,
65130
65462
  committedMessages: messages
65131
65463
  };
@@ -65166,6 +65498,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
65166
65498
  return new ProviderCliAdapter(provider, workingDir, cliArgs, extraEnv, transportFactory);
65167
65499
  }
65168
65500
  init_logger();
65501
+ init_mesh_event_trace();
65169
65502
  init_control_effects();
65170
65503
  init_approval_utils();
65171
65504
  init_provider_patch_state();
@@ -66209,6 +66542,23 @@ ${formatManifestValidationIssues2(validation.issues)}`,
66209
66542
  if (this.completedDebounceTimer) clearTimeout(this.completedDebounceTimer);
66210
66543
  this.completedDebounceTimer = setTimeout(() => this.flushCompletedDebounceIfFinalized(), delayMs);
66211
66544
  }
66545
+ // EVTTRACE (observation-only): is this a mesh worker session whose completion
66546
+ // events must route to a coordinator? Used purely to gate trace logging so a
66547
+ // non-mesh CLI session's completions don't add EvtTrace noise. No decision logic.
66548
+ isMeshWorkerSession() {
66549
+ return !!(this.settings.meshNodeFor || this.settings.meshActiveTaskId || this.settings.meshNodeId || this.settings.launchedByCoordinator);
66550
+ }
66551
+ // EVTTRACE correlation context for this session's completion lifecycle. taskId is
66552
+ // the primary grep anchor; instanceId is the session fallback.
66553
+ meshTraceCtx(event = "agent:generating_completed") {
66554
+ return {
66555
+ taskId: this.settings.meshActiveTaskId,
66556
+ sessionId: this.instanceId,
66557
+ nodeId: this.settings.meshNodeId,
66558
+ meshId: this.settings.meshNodeFor,
66559
+ event
66560
+ };
66561
+ }
66212
66562
  flushCompletedDebounceIfFinalized() {
66213
66563
  const pending = this.completedDebouncePending;
66214
66564
  if (!pending) {
@@ -66229,24 +66579,33 @@ ${formatManifestValidationIssues2(validation.issues)}`,
66229
66579
  if (block2) {
66230
66580
  const blockReason = block2.reason;
66231
66581
  const waitedMs = Date.now() - pending.firstObservedAt;
66232
- LOG2.debug("CLI", `[${this.type}] finalization block: reason=${blockReason} terminal=${block2.terminal} waitedMs=${waitedMs} maxWait=${COMPLETED_FINALIZATION_MAX_WAIT_MS}`);
66233
- if (block2.terminal && !block2.allowTimeout || waitedMs < COMPLETED_FINALIZATION_MAX_WAIT_MS) {
66582
+ const isTranscriptEvidenceGate = block2.allowTimeout === true;
66583
+ LOG2.debug("CLI", `[${this.type}] finalization block: reason=${blockReason} terminal=${block2.terminal} allowTimeout=${isTranscriptEvidenceGate} waitedMs=${waitedMs} maxWait=${COMPLETED_FINALIZATION_MAX_WAIT_MS}`);
66584
+ if (!isTranscriptEvidenceGate && (block2.terminal || waitedMs < COMPLETED_FINALIZATION_MAX_WAIT_MS)) {
66234
66585
  if (pending.loggedBlockReason !== blockReason) {
66235
66586
  LOG2.info("CLI", `[${this.type}] waiting to emit completed until transcript finalizes (${blockReason})`);
66587
+ if (this.isMeshWorkerSession()) {
66588
+ traceMeshEventDrop("completion_gate_hold", this.meshTraceCtx(), `${blockReason} waited=${waitedMs}ms`);
66589
+ }
66236
66590
  pending.loggedBlockReason = blockReason;
66237
66591
  }
66238
66592
  this.scheduleCompletedDebounceFlush(COMPLETED_FINALIZATION_RETRY_MS);
66239
66593
  return;
66240
66594
  }
66595
+ const emittedAfterFinalizationTimeout = waitedMs >= COMPLETED_FINALIZATION_MAX_WAIT_MS;
66241
66596
  const completionDiagnostic = this.buildCompletedFinalizationDiagnostic({
66242
66597
  blockReason,
66243
66598
  latestStatus,
66244
66599
  latestVisibleStatus,
66245
66600
  waitedMs,
66246
66601
  pending,
66247
- emittedAfterFinalizationTimeout: true
66602
+ emittedAfterFinalizationTimeout
66248
66603
  });
66249
- LOG2.warn("CLI", `[${this.type}] emitting completed event after ${waitedMs}ms without finalized assistant turn (${blockReason})`);
66604
+ completionDiagnostic.decoupledImmediateEmit = isTranscriptEvidenceGate && !emittedAfterFinalizationTimeout;
66605
+ LOG2.warn("CLI", `[${this.type}] emitting completed event (${isTranscriptEvidenceGate && !emittedAfterFinalizationTimeout ? "CANON-C decoupled-immediate, transcript pending" : `after ${waitedMs}ms`}) without finalized assistant turn (${blockReason})`);
66606
+ if (this.isMeshWorkerSession()) {
66607
+ traceMeshEventStage("fired", this.meshTraceCtx(), `forced after ${waitedMs}ms (${blockReason})`);
66608
+ }
66250
66609
  this.pushEvent({
66251
66610
  event: "agent:generating_completed",
66252
66611
  chatTitle: pending.chatTitle,
@@ -66269,6 +66628,9 @@ ${formatManifestValidationIssues2(validation.issues)}`,
66269
66628
  return;
66270
66629
  }
66271
66630
  LOG2.info("CLI", `[${this.type}] completed in ${pending.duration}s`);
66631
+ if (this.isMeshWorkerSession()) {
66632
+ traceMeshEventStage("fired", this.meshTraceCtx(), `duration=${pending.duration}s`);
66633
+ }
66272
66634
  this.pushEvent({
66273
66635
  event: "agent:generating_completed",
66274
66636
  chatTitle: pending.chatTitle,
@@ -66507,6 +66869,9 @@ ${formatManifestValidationIssues2(validation.issues)}`,
66507
66869
  if (missingEvidence && !hasMeshContext) {
66508
66870
  LOG2.info("CLI", `[${this.type}] short completion suppressed: missing final assistant evidence, no mesh context (source=${shortEvidenceSource})`);
66509
66871
  } else {
66872
+ if (this.isMeshWorkerSession()) {
66873
+ traceMeshEventStage("fired", this.meshTraceCtx(), `short-generating idle (source=${shortEvidenceSource})`);
66874
+ }
66510
66875
  this.pushEvent({
66511
66876
  event: "agent:generating_completed",
66512
66877
  chatTitle,
@@ -66583,6 +66948,9 @@ ${formatManifestValidationIssues2(validation.issues)}`,
66583
66948
  const monitorParsedStatus = parsedStatus;
66584
66949
  for (const me of monitorEvents) {
66585
66950
  if (me.type === "monitor:no_progress" && this.completionHasFinalAssistantMessage(monitorParsedStatus?.messages) && !this.hasAdapterPendingResponse() && !hasNonEmptyCliModalButtons(monitorParsedStatus?.activeModal ?? monitorParsedStatus?.modal)) {
66951
+ if (this.isMeshWorkerSession()) {
66952
+ traceMeshEventStage("fired", this.meshTraceCtx(), "no_progress_monitor_final_summary");
66953
+ }
66586
66954
  this.pushEvent({
66587
66955
  event: "agent:generating_completed",
66588
66956
  chatTitle,
@@ -70422,7 +70790,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
70422
70790
  }
70423
70791
  if (buf.length === 0) return null;
70424
70792
  const strings = extractStringsFromBuffer(buf);
70425
- const meaningful = strings.filter((s) => s.length >= MIN_PRINTABLE_RUN && /\w/.test(s));
70793
+ const meaningful = strings.filter((s2) => s2.length >= MIN_PRINTABLE_RUN && /\w/.test(s2));
70426
70794
  if (meaningful.length === 0) return null;
70427
70795
  const content = meaningful.join("\n");
70428
70796
  const sourceMtimeMs = statMtimeMs3(filePath);
@@ -70628,10 +70996,10 @@ Run 'adhdev doctor' for detailed diagnostics.`
70628
70996
  };
70629
70997
  }
70630
70998
  function normalizeHermesRole(r) {
70631
- const s = String(r ?? "").toLowerCase();
70632
- if (s === "user" || s === "human") return "user";
70633
- if (s === "assistant" || s === "ai" || s === "model") return "assistant";
70634
- if (s === "tool" || s === "tool_result" || s === "function") return "assistant";
70999
+ const s2 = String(r ?? "").toLowerCase();
71000
+ if (s2 === "user" || s2 === "human") return "user";
71001
+ if (s2 === "assistant" || s2 === "ai" || s2 === "model") return "assistant";
71002
+ if (s2 === "tool" || s2 === "tool_result" || s2 === "function") return "assistant";
70635
71003
  return "system";
70636
71004
  }
70637
71005
  function createNativeHistoryDispatcher(reader) {
@@ -70855,10 +71223,10 @@ Run 'adhdev doctor' for detailed diagnostics.`
70855
71223
  }
70856
71224
  }
70857
71225
  function normalizeRole2(r) {
70858
- const s = String(r ?? "").toLowerCase();
70859
- if (s === "user" || s === "human") return "user";
70860
- if (s === "assistant" || s === "ai" || s === "model") return "assistant";
70861
- if (s === "tool" || s === "tool_result" || s === "function") return "assistant";
71226
+ const s2 = String(r ?? "").toLowerCase();
71227
+ if (s2 === "user" || s2 === "human") return "user";
71228
+ if (s2 === "assistant" || s2 === "ai" || s2 === "model") return "assistant";
71229
+ if (s2 === "tool" || s2 === "tool_result" || s2 === "function") return "assistant";
70862
71230
  return "system";
70863
71231
  }
70864
71232
  function registerProviderScriptRootSafely(root) {
@@ -70876,7 +71244,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
70876
71244
  const actionType = ctl?.action?.type;
70877
71245
  if (!id || !actionType) return;
70878
71246
  const label = typeof ctl?.label === "string" && ctl.label.trim() ? ctl.label : id;
70879
- const visibleWhenState = Array.isArray(ctl?.visible_when_state) ? ctl.visible_when_state.filter((s) => typeof s === "string") : void 0;
71247
+ const visibleWhenState = Array.isArray(ctl?.visible_when_state) ? ctl.visible_when_state.filter((s2) => typeof s2 === "string") : void 0;
70880
71248
  if (actionType === "open_picker") {
70881
71249
  out.push({
70882
71250
  id,
@@ -77762,7 +78130,7 @@ ${mergeTreeErr?.stderr || ""}`;
77762
78130
  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.";
77763
78131
  if (!firstFailedCmd) return base;
77764
78132
  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 : "";
77765
- const rawOutput = [firstFailedCmd.stdout, firstFailedCmd.stderr, firstFailedCmd.output].filter((s) => typeof s === "string" && s.length > 0).join("\n");
78133
+ const rawOutput = [firstFailedCmd.stdout, firstFailedCmd.stderr, firstFailedCmd.output].filter((s2) => typeof s2 === "string" && s2.length > 0).join("\n");
77766
78134
  const tail = rawOutput.length > 800 ? rawOutput.slice(-800) : rawOutput;
77767
78135
  return [
77768
78136
  base,
@@ -78513,7 +78881,7 @@ ${hintLines.join("\n")}` : "",
78513
78881
  convergence = "blocked_review";
78514
78882
  }
78515
78883
  const fbcs = result.finalBranchConvergenceState && typeof result.finalBranchConvergenceState === "object" ? result.finalBranchConvergenceState : void 0;
78516
- const stage = Array.isArray(result.refineStages) ? result.refineStages.filter((s) => s.status === "failed").map((s) => s.stage).filter(Boolean).pop() : void 0;
78884
+ const stage = Array.isArray(result.refineStages) ? result.refineStages.filter((s2) => s2.status === "failed").map((s2) => s2.stage).filter(Boolean).pop() : void 0;
78517
78885
  results.push({
78518
78886
  nodeId: node.id,
78519
78887
  workspace: node.workspace,
@@ -79510,7 +79878,7 @@ ${hintLines.join("\n")}` : "",
79510
79878
  return {
79511
79879
  success: true,
79512
79880
  screenLineCount: lines.length,
79513
- sections: resolved.map((s) => ({ id: s.id, fromLine: s.fromLine, toLine: s.toLine, text: s.text }))
79881
+ sections: resolved.map((s2) => ({ id: s2.id, fromLine: s2.fromLine, toLine: s2.toLine, text: s2.text }))
79514
79882
  };
79515
79883
  } catch (e) {
79516
79884
  return { success: false, error: `resolve failed: ${e.message}` };
@@ -80079,7 +80447,7 @@ ${hintLines.join("\n")}` : "",
80079
80447
  if (!meshId) return { success: false, error: "meshId required" };
80080
80448
  try {
80081
80449
  const { getMeshQueueStats: getMeshQueueStats2, getQueue: getQueue2, describeTaskDependencyState: describeTaskDependencyState2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
80082
- const status = Array.isArray(args?.status) ? args.status.map((s) => typeof s === "string" ? s.trim() : "").filter(Boolean) : void 0;
80450
+ const status = Array.isArray(args?.status) ? args.status.map((s2) => typeof s2 === "string" ? s2.trim() : "").filter(Boolean) : void 0;
80083
80451
  const rawQueue = getQueue2(meshId, { status });
80084
80452
  const statusById = new Map(getQueue2(meshId).map((task) => [task.id, task.status]));
80085
80453
  const queue = rawQueue.map((task) => Array.isArray(task.dependsOn) && task.dependsOn.length > 0 ? { ...task, ...describeTaskDependencyState2(task, statusById) } : task);
@@ -80360,7 +80728,7 @@ ${hintLines.join("\n")}` : "",
80360
80728
  nodeDaemonId = typeof node?.daemonId === "string" ? node.daemonId.trim() : void 0;
80361
80729
  }
80362
80730
  const selfDaemonId = this.deps.statusInstanceId;
80363
- const isRemote = nodeDaemonId && selfDaemonId && nodeDaemonId !== selfDaemonId;
80731
+ const isRemote = nodeDaemonId && selfDaemonId && !daemonIdsEquivalent(nodeDaemonId, selfDaemonId);
80364
80732
  if (isRemote && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
80365
80733
  const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "fast_forward_mesh_node", {
80366
80734
  ...typeof args === "object" && args !== null ? args : {},
@@ -80394,7 +80762,7 @@ ${hintLines.join("\n")}` : "",
80394
80762
  nodeDaemonId = typeof node?.daemonId === "string" ? node.daemonId.trim() : void 0;
80395
80763
  }
80396
80764
  const selfDaemonId = this.deps.statusInstanceId;
80397
- const isRemote = nodeDaemonId && selfDaemonId && nodeDaemonId !== selfDaemonId;
80765
+ const isRemote = nodeDaemonId && selfDaemonId && !daemonIdsEquivalent(nodeDaemonId, selfDaemonId);
80398
80766
  if (isRemote && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
80399
80767
  const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "get_mesh_node_logs", {
80400
80768
  ...typeof args === "object" && args !== null ? args : {},
@@ -80442,7 +80810,7 @@ ${hintLines.join("\n")}` : "",
80442
80810
  const forwardNode = meshRecordForForward?.mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
80443
80811
  const nodeDaemonId = typeof forwardNode?.daemonId === "string" ? forwardNode.daemonId.trim() : void 0;
80444
80812
  const selfDaemonId = this.deps.statusInstanceId;
80445
- const isRemote = nodeDaemonId && selfDaemonId && nodeDaemonId !== selfDaemonId;
80813
+ const isRemote = nodeDaemonId && selfDaemonId && !daemonIdsEquivalent(nodeDaemonId, selfDaemonId);
80446
80814
  if (isRemote && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
80447
80815
  const callerCoordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : void 0;
80448
80816
  const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "refine_mesh_node", {
@@ -80529,7 +80897,7 @@ ${hintLines.join("\n")}` : "",
80529
80897
  let worktreeCleanup;
80530
80898
  if (node?.isLocalWorktree) {
80531
80899
  const nodeDaemonId = typeof node.daemonId === "string" ? node.daemonId.trim() : void 0;
80532
- const isRemoteWorktree = nodeDaemonId && nodeDaemonId !== this.deps.statusInstanceId && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch;
80900
+ const isRemoteWorktree = nodeDaemonId && !daemonIdsEquivalent(nodeDaemonId, this.deps.statusInstanceId) && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch;
80533
80901
  if (isRemoteWorktree) {
80534
80902
  const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "remove_mesh_node", {
80535
80903
  ...typeof args === "object" && args !== null ? args : {},
@@ -80611,7 +80979,7 @@ ${hintLines.join("\n")}` : "",
80611
80979
  const sourceNode = mesh.nodes?.find((n) => meshNodeIdMatches(n, sourceNodeId));
80612
80980
  if (!sourceNode) return { success: false, error: `Source node '${sourceNodeId}' not found in mesh` };
80613
80981
  const sourceDaemonId = typeof sourceNode.daemonId === "string" ? sourceNode.daemonId.trim() : void 0;
80614
- if (sourceDaemonId && sourceDaemonId !== this.deps.statusInstanceId && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
80982
+ if (sourceDaemonId && !daemonIdsEquivalent(sourceDaemonId, this.deps.statusInstanceId) && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
80615
80983
  const forwarded = await this.deps.dispatchMeshCommand(sourceDaemonId, "clone_mesh_node", {
80616
80984
  ...typeof args === "object" && args !== null ? args : {},
80617
80985
  _meshDirectDispatch: true
@@ -80853,7 +81221,7 @@ ${hintLines.join("\n")}` : "",
80853
81221
  if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
80854
81222
  if (!node.isLocalWorktree) return { success: false, error: "Node is not a local worktree node" };
80855
81223
  const nodeDaemonId = typeof node.daemonId === "string" ? node.daemonId.trim() : void 0;
80856
- if (nodeDaemonId && nodeDaemonId !== this.deps.statusInstanceId && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
81224
+ if (nodeDaemonId && !daemonIdsEquivalent(nodeDaemonId, this.deps.statusInstanceId) && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
80857
81225
  const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "retry_mesh_node_bootstrap", {
80858
81226
  ...typeof args === "object" && args !== null ? args : {},
80859
81227
  _meshDirectDispatch: true
@@ -82061,16 +82429,16 @@ ${ptyResult.output.slice(-2e3)}`);
82061
82429
  const now = this.lastStatusSentAt;
82062
82430
  const target = opts?.p2pOnly ? "P2P" : serverConnected ? "P2P+Server" : "P2P";
82063
82431
  const allStates = this.deps.instanceManager.collectAllStates();
82064
- const ideStates = allStates.filter((s) => s.category === "ide");
82065
- const cliStates = allStates.filter((s) => s.category === "cli");
82066
- const acpStates = allStates.filter((s) => s.category === "acp");
82067
- const ideSummary = ideStates.map((s) => {
82068
- const msgs = s.activeChat?.messages?.length || 0;
82069
- const exts = s.extensions.length;
82070
- return `${s.type}(${s.status},${msgs}msg,${exts}ext)`;
82432
+ const ideStates = allStates.filter((s2) => s2.category === "ide");
82433
+ const cliStates = allStates.filter((s2) => s2.category === "cli");
82434
+ const acpStates = allStates.filter((s2) => s2.category === "acp");
82435
+ const ideSummary = ideStates.map((s2) => {
82436
+ const msgs = s2.activeChat?.messages?.length || 0;
82437
+ const exts = s2.extensions.length;
82438
+ return `${s2.type}(${s2.status},${msgs}msg,${exts}ext)`;
82071
82439
  }).join(", ");
82072
- const cliSummary = cliStates.map((s) => `${s.type}(${s.status})`).join(", ");
82073
- const acpSummary = acpStates.map((s) => `${s.type}(${s.status})`).join(", ");
82440
+ const cliSummary = cliStates.map((s2) => `${s2.type}(${s2.status})`).join(", ");
82441
+ const acpSummary = acpStates.map((s2) => `${s2.type}(${s2.status})`).join(", ");
82074
82442
  const logLevel = opts?.p2pOnly ? "debug" : "info";
82075
82443
  const baseSummary = `IDE: ${ideStates.length} [${ideSummary}] CLI: ${cliStates.length} [${cliSummary}] ACP: ${acpStates.length} [${acpSummary}]`;
82076
82444
  const summaryChanged = baseSummary !== this.lastStatusSummary;
@@ -82181,10 +82549,10 @@ ${ptyResult.output.slice(-2e3)}`);
82181
82549
  }
82182
82550
  return false;
82183
82551
  }
82184
- simpleHash(s) {
82552
+ simpleHash(s2) {
82185
82553
  let h = 2166136261;
82186
- for (let i = 0; i < s.length; i++) {
82187
- h ^= s.charCodeAt(i);
82554
+ for (let i = 0; i < s2.length; i++) {
82555
+ h ^= s2.charCodeAt(i);
82188
82556
  h = h * 16777619 >>> 0;
82189
82557
  }
82190
82558
  return h.toString(36);
@@ -83392,7 +83760,7 @@ ${ptyResult.output.slice(-2e3)}`);
83392
83760
  * Per-category status collect
83393
83761
  */
83394
83762
  collectStatesByCategory(category) {
83395
- return this.collectAllStates().filter((s) => s.category === category);
83763
+ return this.collectAllStates().filter((s2) => s2.category === category);
83396
83764
  }
83397
83765
  // ─── Tick engine ─────────────────────────────────
83398
83766
  /**
@@ -85278,9 +85646,9 @@ async (params) => {
85278
85646
  function findCliTarget(ctx, type, instanceId) {
85279
85647
  if (!ctx.instanceManager) return null;
85280
85648
  const cliStates = ctx.instanceManager.collectAllStates().filter(isCliTargetState);
85281
- if (instanceId) return cliStates.find((s) => s.instanceId === instanceId) || null;
85649
+ if (instanceId) return cliStates.find((s2) => s2.instanceId === instanceId) || null;
85282
85650
  if (!type) return cliStates[cliStates.length - 1] || null;
85283
- const matches = cliStates.filter((s) => s.type === type);
85651
+ const matches = cliStates.filter((s2) => s2.type === type);
85284
85652
  return matches[matches.length - 1] || null;
85285
85653
  }
85286
85654
  function getCliTargetBundle(ctx, type, instanceId) {
@@ -85643,20 +86011,20 @@ async (params) => {
85643
86011
  return;
85644
86012
  }
85645
86013
  const allStates = ctx.instanceManager.collectAllStates();
85646
- const cliStates = allStates.filter((s) => s.category === "cli" || s.category === "acp");
85647
- const result = cliStates.map((s) => ({
85648
- instanceId: s.instanceId,
85649
- type: s.type,
85650
- name: s.name,
85651
- category: s.category,
85652
- status: s.status,
85653
- mode: s.mode,
85654
- workspace: s.workspace,
85655
- messageCount: s.activeChat?.messages?.length || 0,
85656
- lastMessage: s.activeChat?.messages?.slice(-1)[0] || null,
85657
- activeModal: s.activeChat?.activeModal || null,
85658
- pendingEvents: s.pendingEvents || [],
85659
- settings: s.settings
86014
+ const cliStates = allStates.filter((s2) => s2.category === "cli" || s2.category === "acp");
86015
+ const result = cliStates.map((s2) => ({
86016
+ instanceId: s2.instanceId,
86017
+ type: s2.type,
86018
+ name: s2.name,
86019
+ category: s2.category,
86020
+ status: s2.status,
86021
+ mode: s2.mode,
86022
+ workspace: s2.workspace,
86023
+ messageCount: s2.activeChat?.messages?.length || 0,
86024
+ lastMessage: s2.activeChat?.messages?.slice(-1)[0] || null,
86025
+ activeModal: s2.activeChat?.activeModal || null,
86026
+ pendingEvents: s2.pendingEvents || [],
86027
+ settings: s2.settings
85660
86028
  }));
85661
86029
  ctx.json(res, 200, { instances: result, count: result.length });
85662
86030
  }
@@ -85745,9 +86113,9 @@ async (params) => {
85745
86113
  }
85746
86114
  if (ctx.instanceManager) {
85747
86115
  const allStates = ctx.instanceManager.collectAllStates();
85748
- const cliStates = allStates.filter((s) => s.category === "cli" || s.category === "acp");
85749
- for (const s of cliStates) {
85750
- ctx.sendCliSSE({ event: "snapshot", providerType: s.type, status: s.status, instanceId: s.instanceId });
86116
+ const cliStates = allStates.filter((s2) => s2.category === "cli" || s2.category === "acp");
86117
+ for (const s2 of cliStates) {
86118
+ ctx.sendCliSSE({ event: "snapshot", providerType: s2.type, status: s2.status, instanceId: s2.instanceId });
85751
86119
  }
85752
86120
  }
85753
86121
  _req.on("close", () => {
@@ -85763,7 +86131,7 @@ async (params) => {
85763
86131
  const target = findCliTarget(ctx, type);
85764
86132
  if (!target) {
85765
86133
  const allStates = ctx.instanceManager.collectAllStates();
85766
- ctx.json(res, 404, { error: `No running instance for: ${type}`, available: allStates.filter((s) => s.category === "cli" || s.category === "acp").map((s) => s.type) });
86134
+ ctx.json(res, 404, { error: `No running instance for: ${type}`, available: allStates.filter((s2) => s2.category === "cli" || s2.category === "acp").map((s2) => s2.type) });
85767
86135
  return;
85768
86136
  }
85769
86137
  const instance = ctx.instanceManager.getInstance(target.instanceId);
@@ -85809,7 +86177,7 @@ async (params) => {
85809
86177
  const allStates = ctx.instanceManager.collectAllStates();
85810
86178
  ctx.json(res, 404, {
85811
86179
  error: `No running instance for: ${type}`,
85812
- available: allStates.filter((s) => s.category === "cli" || s.category === "acp").map((s) => s.type)
86180
+ available: allStates.filter((s2) => s2.category === "cli" || s2.category === "acp").map((s2) => s2.type)
85813
86181
  });
85814
86182
  return;
85815
86183
  }
@@ -86612,7 +86980,7 @@ async (params) => {
86612
86980
  child.write("\x1B[12;1R");
86613
86981
  ctx.log("Terminal CPR request (\\x1b[6n) intercepted in PTY, responding with dummy coordinates [12;1R]");
86614
86982
  }
86615
- checkAutoApproval(data, (s) => child.write(s));
86983
+ checkAutoApproval(data, (s2) => child.write(s2));
86616
86984
  sendAutoImplSSE(ctx, { event: "output", data: { chunk: data, stream: "stdout" } });
86617
86985
  scheduleAutoStopForVerification();
86618
86986
  });
@@ -86625,7 +86993,7 @@ async (params) => {
86625
86993
  stdout += chunk;
86626
86994
  clearAutoStopTimer();
86627
86995
  if (chunk.includes("\x1B[6n")) child.stdin?.write("\x1B[1;1R");
86628
- checkAutoApproval(chunk, (s) => child.stdin?.write(s));
86996
+ checkAutoApproval(chunk, (s2) => child.stdin?.write(s2));
86629
86997
  sendAutoImplSSE(ctx, { event: "output", data: { chunk, stream: "stdout" } });
86630
86998
  scheduleAutoStopForVerification();
86631
86999
  });
@@ -86633,7 +87001,7 @@ async (params) => {
86633
87001
  const chunk = d.toString();
86634
87002
  stderr += chunk;
86635
87003
  clearAutoStopTimer();
86636
- checkAutoApproval(chunk, (s) => child.stdin?.write(s));
87004
+ checkAutoApproval(chunk, (s2) => child.stdin?.write(s2));
86637
87005
  sendAutoImplSSE(ctx, { event: "output", data: { chunk, stream: "stderr" } });
86638
87006
  scheduleAutoStopForVerification();
86639
87007
  });
@@ -87446,59 +87814,59 @@ data: ${JSON.stringify(msg.data)}
87446
87814
  // ─── Route Table ─────────────────────────────────────
87447
87815
  routes = [
87448
87816
  // Static routes
87449
- { method: "GET", pattern: "/api/providers", handler: (q, s) => this.handleListProviders(q, s) },
87450
- { method: "GET", pattern: "/api/providers/source-config", handler: (q, s) => this.handleGetProviderSourceConfig(q, s) },
87451
- { method: "POST", pattern: "/api/providers/source-config", handler: (q, s) => this.handleSetProviderSourceConfig(q, s) },
87452
- { method: "GET", pattern: "/api/providers/versions", handler: (q, s) => this.handleDetectVersions(q, s) },
87453
- { method: "POST", pattern: "/api/providers/reload", handler: (q, s) => this.handleReload(q, s) },
87454
- { method: "POST", pattern: "/api/cdp/evaluate", handler: (q, s) => this.handleCdpEvaluate(q, s) },
87455
- { method: "POST", pattern: "/api/cdp/click", handler: (q, s) => this.handleCdpClick(q, s) },
87456
- { method: "POST", pattern: "/api/cdp/dom/query", handler: (q, s) => this.handleCdpDomQuery(q, s) },
87457
- { method: "POST", pattern: "/api/cdp/dom/inspect", handler: (q, s) => this.handleDomInspect(q, s) },
87458
- { method: "POST", pattern: "/api/cdp/dom/children", handler: (q, s) => this.handleDomChildren(q, s) },
87459
- { method: "POST", pattern: "/api/cdp/dom/analyze", handler: (q, s) => this.handleDomAnalyze(q, s) },
87460
- { method: "POST", pattern: "/api/cdp/dom/find-text", handler: (q, s) => this.handleFindByText(q, s) },
87461
- { method: "POST", pattern: "/api/cdp/dom/find-common", handler: (q, s) => this.handleFindCommon(q, s) },
87462
- { method: "GET", pattern: "/api/cdp/screenshot", handler: (q, s) => this.handleScreenshot(q, s) },
87463
- { method: "GET", pattern: "/api/cdp/targets", handler: (q, s) => this.handleCdpTargets(q, s) },
87464
- { method: "POST", pattern: "/api/scripts/run", handler: (q, s) => this.handleScriptsRun(q, s) },
87465
- { method: "GET", pattern: "/api/status", handler: (q, s) => this.handleStatus(q, s) },
87466
- { method: "POST", pattern: "/api/watch/start", handler: (q, s) => this.handleWatchStart(q, s) },
87467
- { method: "POST", pattern: "/api/watch/stop", handler: (q, s) => this.handleWatchStop(q, s) },
87468
- { method: "GET", pattern: "/api/watch/events", handler: (q, s) => this.handleSSE(q, s) },
87469
- { method: "POST", pattern: "/api/scaffold", handler: (q, s) => this.handleScaffold(q, s) },
87817
+ { method: "GET", pattern: "/api/providers", handler: (q, s2) => this.handleListProviders(q, s2) },
87818
+ { method: "GET", pattern: "/api/providers/source-config", handler: (q, s2) => this.handleGetProviderSourceConfig(q, s2) },
87819
+ { method: "POST", pattern: "/api/providers/source-config", handler: (q, s2) => this.handleSetProviderSourceConfig(q, s2) },
87820
+ { method: "GET", pattern: "/api/providers/versions", handler: (q, s2) => this.handleDetectVersions(q, s2) },
87821
+ { method: "POST", pattern: "/api/providers/reload", handler: (q, s2) => this.handleReload(q, s2) },
87822
+ { method: "POST", pattern: "/api/cdp/evaluate", handler: (q, s2) => this.handleCdpEvaluate(q, s2) },
87823
+ { method: "POST", pattern: "/api/cdp/click", handler: (q, s2) => this.handleCdpClick(q, s2) },
87824
+ { method: "POST", pattern: "/api/cdp/dom/query", handler: (q, s2) => this.handleCdpDomQuery(q, s2) },
87825
+ { method: "POST", pattern: "/api/cdp/dom/inspect", handler: (q, s2) => this.handleDomInspect(q, s2) },
87826
+ { method: "POST", pattern: "/api/cdp/dom/children", handler: (q, s2) => this.handleDomChildren(q, s2) },
87827
+ { method: "POST", pattern: "/api/cdp/dom/analyze", handler: (q, s2) => this.handleDomAnalyze(q, s2) },
87828
+ { method: "POST", pattern: "/api/cdp/dom/find-text", handler: (q, s2) => this.handleFindByText(q, s2) },
87829
+ { method: "POST", pattern: "/api/cdp/dom/find-common", handler: (q, s2) => this.handleFindCommon(q, s2) },
87830
+ { method: "GET", pattern: "/api/cdp/screenshot", handler: (q, s2) => this.handleScreenshot(q, s2) },
87831
+ { method: "GET", pattern: "/api/cdp/targets", handler: (q, s2) => this.handleCdpTargets(q, s2) },
87832
+ { method: "POST", pattern: "/api/scripts/run", handler: (q, s2) => this.handleScriptsRun(q, s2) },
87833
+ { method: "GET", pattern: "/api/status", handler: (q, s2) => this.handleStatus(q, s2) },
87834
+ { method: "POST", pattern: "/api/watch/start", handler: (q, s2) => this.handleWatchStart(q, s2) },
87835
+ { method: "POST", pattern: "/api/watch/stop", handler: (q, s2) => this.handleWatchStop(q, s2) },
87836
+ { method: "GET", pattern: "/api/watch/events", handler: (q, s2) => this.handleSSE(q, s2) },
87837
+ { method: "POST", pattern: "/api/scaffold", handler: (q, s2) => this.handleScaffold(q, s2) },
87470
87838
  // CLI Debug routes
87471
- { method: "GET", pattern: "/api/cli/status", handler: (q, s) => this.handleCliStatus(q, s) },
87472
- { method: "POST", pattern: "/api/cli/launch", handler: (q, s) => this.handleCliLaunch(q, s) },
87473
- { method: "POST", pattern: "/api/cli/send", handler: (q, s) => this.handleCliSend(q, s) },
87474
- { method: "POST", pattern: "/api/cli/exercise", handler: (q, s) => this.handleCliExercise(q, s) },
87475
- { method: "POST", pattern: "/api/cli/fixture/capture", handler: (q, s) => this.handleCliFixtureCapture(q, s) },
87476
- { method: "POST", pattern: "/api/cli/fixture/replay", handler: (q, s) => this.handleCliFixtureReplay(q, s) },
87477
- { method: "POST", pattern: "/api/cli/resolve", handler: (q, s) => this.handleCliResolve(q, s) },
87478
- { method: "POST", pattern: "/api/cli/raw", handler: (q, s) => this.handleCliRaw(q, s) },
87479
- { method: "POST", pattern: "/api/cli/stop", handler: (q, s) => this.handleCliStop(q, s) },
87480
- { method: "GET", pattern: "/api/cli/events", handler: (q, s) => this.handleCliSSE(q, s) },
87481
- { method: "GET", pattern: /^\/api\/cli\/debug\/([^/]+)$/, handler: (q, s, p) => this.handleCliDebug(p[0], q, s) },
87482
- { method: "GET", pattern: /^\/api\/cli\/trace\/([^/]+)$/, handler: (q, s, p) => this.handleCliTrace(p[0], q, s) },
87483
- { method: "GET", pattern: /^\/api\/cli\/fixtures\/([^/]+)$/, handler: (q, s, p) => this.handleCliFixtureList(p[0], q, s) },
87839
+ { method: "GET", pattern: "/api/cli/status", handler: (q, s2) => this.handleCliStatus(q, s2) },
87840
+ { method: "POST", pattern: "/api/cli/launch", handler: (q, s2) => this.handleCliLaunch(q, s2) },
87841
+ { method: "POST", pattern: "/api/cli/send", handler: (q, s2) => this.handleCliSend(q, s2) },
87842
+ { method: "POST", pattern: "/api/cli/exercise", handler: (q, s2) => this.handleCliExercise(q, s2) },
87843
+ { method: "POST", pattern: "/api/cli/fixture/capture", handler: (q, s2) => this.handleCliFixtureCapture(q, s2) },
87844
+ { method: "POST", pattern: "/api/cli/fixture/replay", handler: (q, s2) => this.handleCliFixtureReplay(q, s2) },
87845
+ { method: "POST", pattern: "/api/cli/resolve", handler: (q, s2) => this.handleCliResolve(q, s2) },
87846
+ { method: "POST", pattern: "/api/cli/raw", handler: (q, s2) => this.handleCliRaw(q, s2) },
87847
+ { method: "POST", pattern: "/api/cli/stop", handler: (q, s2) => this.handleCliStop(q, s2) },
87848
+ { method: "GET", pattern: "/api/cli/events", handler: (q, s2) => this.handleCliSSE(q, s2) },
87849
+ { method: "GET", pattern: /^\/api\/cli\/debug\/([^/]+)$/, handler: (q, s2, p) => this.handleCliDebug(p[0], q, s2) },
87850
+ { method: "GET", pattern: /^\/api\/cli\/trace\/([^/]+)$/, handler: (q, s2, p) => this.handleCliTrace(p[0], q, s2) },
87851
+ { method: "GET", pattern: /^\/api\/cli\/fixtures\/([^/]+)$/, handler: (q, s2, p) => this.handleCliFixtureList(p[0], q, s2) },
87484
87852
  // Dynamic routes (provider :type param)
87485
- { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/script$/, handler: (q, s, p) => this.handleRunScript(p[0], q, s) },
87486
- { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/files$/, handler: (q, s, p) => this.handleListFiles(p[0], q, s) },
87487
- { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q, s, p) => this.handleReadFile(p[0], q, s) },
87488
- { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q, s, p) => this.handleWriteFile(p[0], q, s) },
87489
- { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/source$/, handler: (q, s, p) => this.handleSource(p[0], q, s) },
87490
- { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/save$/, handler: (q, s, p) => this.handleSave(p[0], q, s) },
87491
- { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/typeAndSend$/, handler: (q, s, p) => this.handleTypeAndSend(p[0], q, s) },
87492
- { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/typeAndSendAt$/, handler: (q, s, p) => this.handleTypeAndSendAt(p[0], q, s) },
87493
- { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/config$/, handler: (q, s, p) => this.handleProviderConfig(p[0], q, s) },
87494
- { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/dom-context$/, handler: (q, s, p) => this.handleDomContext(p[0], q, s) },
87495
- { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement$/, handler: (q, s, p) => this.handleAutoImplement(p[0], q, s) },
87496
- { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/cancel$/, handler: (q, s, p) => this.handleAutoImplCancel(p[0], q, s) },
87497
- { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/status$/, handler: (q, s, p) => this.handleAutoImplSSE(p[0], q, s) },
87498
- { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/spawn-test$/, handler: (q, s, p) => this.handleSpawnTest(p[0], q, s) },
87499
- { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/validate$/, handler: (q, s, p) => this.handleValidate(p[0], q, s) },
87500
- { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/acp-chat$/, handler: (q, s, p) => this.handleAcpChat(p[0], q, s) },
87501
- { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/script-hints$/, handler: (q, s, p) => this.handleScriptHints(p[0], q, s) }
87853
+ { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/script$/, handler: (q, s2, p) => this.handleRunScript(p[0], q, s2) },
87854
+ { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/files$/, handler: (q, s2, p) => this.handleListFiles(p[0], q, s2) },
87855
+ { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q, s2, p) => this.handleReadFile(p[0], q, s2) },
87856
+ { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q, s2, p) => this.handleWriteFile(p[0], q, s2) },
87857
+ { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/source$/, handler: (q, s2, p) => this.handleSource(p[0], q, s2) },
87858
+ { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/save$/, handler: (q, s2, p) => this.handleSave(p[0], q, s2) },
87859
+ { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/typeAndSend$/, handler: (q, s2, p) => this.handleTypeAndSend(p[0], q, s2) },
87860
+ { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/typeAndSendAt$/, handler: (q, s2, p) => this.handleTypeAndSendAt(p[0], q, s2) },
87861
+ { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/config$/, handler: (q, s2, p) => this.handleProviderConfig(p[0], q, s2) },
87862
+ { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/dom-context$/, handler: (q, s2, p) => this.handleDomContext(p[0], q, s2) },
87863
+ { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement$/, handler: (q, s2, p) => this.handleAutoImplement(p[0], q, s2) },
87864
+ { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/cancel$/, handler: (q, s2, p) => this.handleAutoImplCancel(p[0], q, s2) },
87865
+ { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/status$/, handler: (q, s2, p) => this.handleAutoImplSSE(p[0], q, s2) },
87866
+ { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/spawn-test$/, handler: (q, s2, p) => this.handleSpawnTest(p[0], q, s2) },
87867
+ { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/validate$/, handler: (q, s2, p) => this.handleValidate(p[0], q, s2) },
87868
+ { method: "POST", pattern: /^\/api\/providers\/([^/]+)\/acp-chat$/, handler: (q, s2, p) => this.handleAcpChat(p[0], q, s2) },
87869
+ { method: "GET", pattern: /^\/api\/providers\/([^/]+)\/script-hints$/, handler: (q, s2, p) => this.handleScriptHints(p[0], q, s2) }
87502
87870
  ];
87503
87871
  matchRoute(method, pathname) {
87504
87872
  for (const route of this.routes) {
@@ -88093,14 +88461,14 @@ data: ${JSON.stringify(msg.data)}
88093
88461
  warnings.push(...validation.warnings);
88094
88462
  if (config2.settings) {
88095
88463
  for (const [key, val] of Object.entries(config2.settings)) {
88096
- const s = val;
88097
- if (!s.type) errors.push(`settings.${key}: missing type`);
88098
- else if (!["boolean", "number", "string", "select"].includes(s.type))
88099
- errors.push(`settings.${key}: invalid type '${s.type}'`);
88100
- if (s.default === void 0) warnings.push(`settings.${key}: no default value`);
88101
- if (s.type === "number" && s.min !== void 0 && s.max !== void 0 && s.min > s.max)
88102
- errors.push(`settings.${key}: min (${s.min}) > max (${s.max})`);
88103
- if (s.type === "select" && (!s.options || !Array.isArray(s.options) || s.options.length === 0))
88464
+ const s2 = val;
88465
+ if (!s2.type) errors.push(`settings.${key}: missing type`);
88466
+ else if (!["boolean", "number", "string", "select"].includes(s2.type))
88467
+ errors.push(`settings.${key}: invalid type '${s2.type}'`);
88468
+ if (s2.default === void 0) warnings.push(`settings.${key}: no default value`);
88469
+ if (s2.type === "number" && s2.min !== void 0 && s2.max !== void 0 && s2.min > s2.max)
88470
+ errors.push(`settings.${key}: min (${s2.min}) > max (${s2.max})`);
88471
+ if (s2.type === "select" && (!s2.options || !Array.isArray(s2.options) || s2.options.length === 0))
88104
88472
  errors.push(`settings.${key}: select type requires options[]`);
88105
88473
  }
88106
88474
  }