@adhdev/daemon-standalone 0.9.82-rc.310 → 0.9.82-rc.312

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
@@ -29735,6 +29735,18 @@ var require_dist3 = __commonJS({
29735
29735
  mod
29736
29736
  ));
29737
29737
  var __toCommonJS2 = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
29738
+ function normalizeMeshSchedulingStrategy(value) {
29739
+ if (typeof value !== "string") return DEFAULT_MESH_SCHEDULING_STRATEGY;
29740
+ const trimmed = value.trim();
29741
+ return MESH_SCHEDULING_STRATEGIES.includes(trimmed) ? trimmed : DEFAULT_MESH_SCHEDULING_STRATEGY;
29742
+ }
29743
+ function resolveNodeSchedulingPriority(nodePolicy) {
29744
+ const raw = Number(nodePolicy?.schedulingPriority);
29745
+ return Number.isFinite(raw) ? raw : 0;
29746
+ }
29747
+ function resolveAutoConvergeCodeChange(policy) {
29748
+ return policy?.autoConvergeCodeChange === true;
29749
+ }
29738
29750
  function resolveDelegatedWorkerAutoApprove(meshPolicy, nodePolicy) {
29739
29751
  if (typeof nodePolicy?.delegatedWorkerAutoApprove === "boolean") {
29740
29752
  return nodePolicy.delegatedWorkerAutoApprove;
@@ -29762,10 +29774,23 @@ var require_dist3 = __commonJS({
29762
29774
  if (!Number.isFinite(raw) || raw < 0) return void 0;
29763
29775
  return Math.floor(raw);
29764
29776
  }
29777
+ var MESH_SCHEDULING_STRATEGIES;
29778
+ var DEFAULT_MESH_SCHEDULING_STRATEGY;
29779
+ var MESH_CONVERGE_REFINE_TAG;
29780
+ var MESH_CONVERGE_FAST_FORWARD_TAG;
29765
29781
  var DEFAULT_MESH_POLICY;
29766
29782
  var init_repo_mesh_types = __esm2({
29767
29783
  "src/repo-mesh-types.ts"() {
29768
29784
  "use strict";
29785
+ MESH_SCHEDULING_STRATEGIES = [
29786
+ "first_eligible",
29787
+ "least_loaded",
29788
+ "round_robin",
29789
+ "priority_only"
29790
+ ];
29791
+ DEFAULT_MESH_SCHEDULING_STRATEGY = "first_eligible";
29792
+ MESH_CONVERGE_REFINE_TAG = "converge=refine";
29793
+ MESH_CONVERGE_FAST_FORWARD_TAG = "converge=fast_forward";
29769
29794
  DEFAULT_MESH_POLICY = {
29770
29795
  requirePreTaskCheckpoint: false,
29771
29796
  requirePostTaskCheckpoint: true,
@@ -30004,10 +30029,10 @@ var require_dist3 = __commonJS({
30004
30029
  }
30005
30030
  function getDaemonBuildInfo() {
30006
30031
  if (cached2) return cached2;
30007
- const commit = readInjected(true ? "33fe83f72a43bccb1b4bec7744ee5c6d8c11a325" : void 0) ?? "unknown";
30008
- const commitShort = readInjected(true ? "33fe83f7" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
30009
- const version2 = readInjected(true ? "0.9.82-rc.310" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
30010
- const builtAt = readInjected(true ? "2026-06-17T09:35:20.983Z" : void 0);
30032
+ const commit = readInjected(true ? "35facf0367dbbe37f25a3b5589287dc757ee6213" : void 0) ?? "unknown";
30033
+ const commitShort = readInjected(true ? "35facf03" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
30034
+ const version2 = readInjected(true ? "0.9.82-rc.312" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
30035
+ const builtAt = readInjected(true ? "2026-06-17T22:49:21.710Z" : void 0);
30011
30036
  cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
30012
30037
  return cached2;
30013
30038
  }
@@ -31261,6 +31286,17 @@ ${error48.message || ""}`;
31261
31286
  if (!SPAWNED_SESSION_VISIBILITY_MODES.has(String(policy.spawnedSessionVisibility))) {
31262
31287
  policy.spawnedSessionVisibility = "visible";
31263
31288
  }
31289
+ const normalizedStrategy = normalizeMeshSchedulingStrategy(policy.schedulingStrategy);
31290
+ if (normalizedStrategy === "first_eligible") {
31291
+ delete policy.schedulingStrategy;
31292
+ } else {
31293
+ policy.schedulingStrategy = normalizedStrategy;
31294
+ }
31295
+ if (policy.autoConvergeCodeChange === true) {
31296
+ policy.autoConvergeCodeChange = true;
31297
+ } else {
31298
+ delete policy.autoConvergeCodeChange;
31299
+ }
31264
31300
  return policy;
31265
31301
  }
31266
31302
  function normalizeAutoFastForwardPolicy(value) {
@@ -31809,6 +31845,7 @@ ${rules.join("\n")}`;
31809
31845
  | \`mesh_read_debug\` | Collect a daemon-side chat/parser debug bundle for a session |
31810
31846
  | \`mesh_task_history\` | Read the task ledger \u2014 dispatches, completions, failures. Use to understand what has been done before deciding next steps |
31811
31847
  | \`mesh_git_status\` | Check git status on a specific node |
31848
+ | \`mesh_read_node_logs\` | Fetch a remote node's daemon log tail directly over P2P (grep/since/byte-bounded, secrets redacted) \u2014 no session/PowerShell needed to debug a node's daemon |
31812
31849
  | \`mesh_fast_forward_node\` | Safely dry-run or explicitly execute an obvious clean fast-forward without launching an agent session |
31813
31850
  | \`mesh_checkpoint\` | Create a git checkpoint on a node |
31814
31851
  | \`mesh_approve\` | Approve/reject a pending agent action |
@@ -32573,6 +32610,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
32573
32610
  recordMeshToolCall: () => recordMeshToolCall,
32574
32611
  recordTaskAutoLaunch: () => recordTaskAutoLaunch,
32575
32612
  requeueTask: () => requeueTask,
32613
+ resolveConvergeRequiredTags: () => resolveConvergeRequiredTags,
32576
32614
  updateDirectDispatchStatus: () => updateDirectDispatchStatus,
32577
32615
  updateSessionTaskStatus: () => updateSessionTaskStatus,
32578
32616
  updateTaskStatus: () => updateTaskStatus,
@@ -32646,6 +32684,21 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
32646
32684
  if (!Array.isArray(raw)) return void 0;
32647
32685
  return raw.find((type) => typeof type === "string" && type.trim())?.trim();
32648
32686
  }
32687
+ function roleCapabilityTags(policy, providerType) {
32688
+ const roles = policy && typeof policy === "object" && !Array.isArray(policy) ? policy.providerRoles : void 0;
32689
+ if (!Array.isArray(roles)) return [];
32690
+ const wantedProvider = typeof providerType === "string" && providerType.trim() ? providerType.trim().toLowerCase() : "";
32691
+ const out = [];
32692
+ for (const entry of roles) {
32693
+ if (!entry || typeof entry !== "object") continue;
32694
+ const type = typeof entry.providerType === "string" ? entry.providerType.trim().toLowerCase() : "";
32695
+ const role = typeof entry.role === "string" ? entry.role.trim().toLowerCase() : "";
32696
+ if (!role) continue;
32697
+ if (wantedProvider && type && type !== wantedProvider) continue;
32698
+ out.push(`role=${role}`);
32699
+ }
32700
+ return out;
32701
+ }
32649
32702
  function buildMeshNodeCapabilityTags(node, providerType) {
32650
32703
  const provider = typeof providerType === "string" && providerType.trim() ? providerType.trim() : firstProviderPriority(node?.policy);
32651
32704
  const worktreeBranch = typeof node?.worktreeBranch === "string" && node.worktreeBranch.trim() ? node.worktreeBranch.trim() : null;
@@ -32657,7 +32710,25 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
32657
32710
  // Worktree nodes automatically expose a "worktree=<branch>" tag so that
32658
32711
  // mesh_enqueue_task with required_tags: ["worktree=<branch>"] routes
32659
32712
  // only to the matching worktree node.
32660
- ...node?.isLocalWorktree === true && worktreeBranch ? [`worktree=${worktreeBranch}`] : []
32713
+ ...node?.isLocalWorktree === true && worktreeBranch ? [`worktree=${worktreeBranch}`] : [],
32714
+ // Convergence routing: advertise how this node can land its work onto base.
32715
+ // - converge=refine: local worktree nodes (on ANY machine — refine_mesh_node
32716
+ // now forwards to the owning daemon) can run the Refinery merge → push →
32717
+ // cleanup against their own checkout, so they accept code_change tasks.
32718
+ // - converge=fast_forward: non-worktree nodes (the machine itself) can only
32719
+ // ff/push an already-converged branch; they are NOT a destination for
32720
+ // code_change work (a worktree is created first, and that worktree node
32721
+ // receives the task instead). Reuses the ordinary required-tags filter —
32722
+ // the load-balancing scheduler auto-injects converge=refine for code_change
32723
+ // so such work is hard-filtered onto refine-capable nodes.
32724
+ ...node?.isLocalWorktree === true ? ["converge=refine"] : ["converge=fast_forward"],
32725
+ // Role-based routing: advertise role=<x> for each (node, provider) role
32726
+ // declared in policy.providerRoles. Narrowed to the selected provider when
32727
+ // one is given so the chosen provider must match a task's required role;
32728
+ // when no provider is selected, all declared roles are advertised for the
32729
+ // node-level eligibility scan. Reuses the ordinary required-tags filter —
32730
+ // no separate role field/gate.
32731
+ ...roleCapabilityTags(node?.policy, providerType)
32661
32732
  ]);
32662
32733
  }
32663
32734
  function nodeSatisfiesRequiredTags(requiredTags, capabilityTags) {
@@ -32666,6 +32737,18 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
32666
32737
  const available = new Set(normalizeMeshCapabilityTags(capabilityTags));
32667
32738
  return required2.every((tag) => available.has(tag));
32668
32739
  }
32740
+ function resolveConvergeRequiredTags(meshId, taskMode, explicitRequiredTags, opts) {
32741
+ if (taskMode !== "code_change") return explicitRequiredTags;
32742
+ if (typeof opts?.targetNodeId === "string" && opts.targetNodeId.trim()) return explicitRequiredTags;
32743
+ let optedIn = false;
32744
+ try {
32745
+ optedIn = resolveAutoConvergeCodeChange(getMesh(meshId)?.policy);
32746
+ } catch {
32747
+ optedIn = false;
32748
+ }
32749
+ if (!optedIn) return explicitRequiredTags;
32750
+ return normalizeMeshCapabilityTags([...explicitRequiredTags, MESH_CONVERGE_REFINE_TAG]);
32751
+ }
32669
32752
  function withQueueLock(_meshId, fn) {
32670
32753
  return MeshRuntimeStore.getInstance().transaction(fn);
32671
32754
  }
@@ -32724,7 +32807,15 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
32724
32807
  taskMode: modeValidation.taskMode,
32725
32808
  targetNodeId: opts?.targetNodeId,
32726
32809
  targetSessionId: opts?.targetSessionId,
32727
- requiredTags: normalizeMeshCapabilityTags(opts?.requiredTags),
32810
+ // Convergence routing (opt-in): auto-inject converge=refine for code_change
32811
+ // tasks so they hard-filter onto refine-capable worktree nodes. No-op unless
32812
+ // the mesh opts in; explicit target_node_id / required_tags are preserved.
32813
+ requiredTags: resolveConvergeRequiredTags(
32814
+ meshId,
32815
+ modeValidation.taskMode,
32816
+ normalizeMeshCapabilityTags(opts?.requiredTags),
32817
+ { targetNodeId: opts?.targetNodeId }
32818
+ ),
32728
32819
  ...dependsOn.length > 0 ? { dependsOn } : {},
32729
32820
  ...typeof opts?.missionId === "string" && opts.missionId.trim() ? { missionId: opts.missionId.trim() } : {},
32730
32821
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -32992,6 +33083,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
32992
33083
  "use strict";
32993
33084
  import_crypto5 = require("crypto");
32994
33085
  init_mesh_host_ownership();
33086
+ init_repo_mesh_types();
32995
33087
  init_mesh_runtime_store();
32996
33088
  init_mesh_config();
32997
33089
  ACTIVE_MESH_QUEUE_STATUSES = ["pending", "assigned"];
@@ -33289,6 +33381,17 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
33289
33381
 
33290
33382
  CREATE INDEX IF NOT EXISTS idx_mesh_missions_mesh_status
33291
33383
  ON mesh_missions(mesh_id, status, updated_at);
33384
+
33385
+ -- Load-balancing scheduler: per-mesh round-robin rotation cursor. When
33386
+ -- the schedulingStrategy is 'round_robin', several eligible nodes tied at
33387
+ -- the least load are rotated by this cursor so the tie-break winner cycles
33388
+ -- across scheduling passes instead of always favouring the same array-order
33389
+ -- node. Persisted (not a module Map) so rotation survives daemon restarts
33390
+ -- and stays a single source of truth across scheduling entry points.
33391
+ CREATE TABLE IF NOT EXISTS mesh_scheduler_cursor (
33392
+ mesh_id TEXT PRIMARY KEY,
33393
+ cursor INTEGER NOT NULL DEFAULT 0
33394
+ );
33292
33395
  `);
33293
33396
  }
33294
33397
  hasCompletionFingerprint(fingerprint) {
@@ -33466,6 +33569,44 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
33466
33569
  `).get(meshId, nodeId);
33467
33570
  return row !== void 0;
33468
33571
  }
33572
+ /**
33573
+ * Count active (status='assigned') tasks on a node, regardless of provider or
33574
+ * task mode. This is the load metric for least-loaded / round-robin ranking:
33575
+ * the scheduler prefers the node with the fewest active assignments so
33576
+ * untargeted work spreads instead of piling onto whichever node asks first.
33577
+ */
33578
+ nodeActiveAssignmentCount(meshId, nodeId) {
33579
+ const row = this.db.prepare(`
33580
+ SELECT COUNT(*) as count FROM mesh_queue
33581
+ WHERE mesh_id = ? AND status = 'assigned' AND assigned_node_id = ?
33582
+ `).get(meshId, nodeId);
33583
+ return row?.count ?? 0;
33584
+ }
33585
+ /**
33586
+ * Read the current per-mesh round-robin cursor (0 when unset). Used to rotate
33587
+ * the tie-break winner among nodes tied at the least load.
33588
+ */
33589
+ getSchedulerCursor(meshId) {
33590
+ const row = this.db.prepare(
33591
+ "SELECT cursor FROM mesh_scheduler_cursor WHERE mesh_id = ?"
33592
+ ).get(meshId);
33593
+ return row?.cursor ?? 0;
33594
+ }
33595
+ /**
33596
+ * Atomically advance the per-mesh round-robin cursor by one and return the
33597
+ * value that was current BEFORE the bump (the value the caller should rotate
33598
+ * by for this pass). UPSERT keeps it lock-free across concurrent passes.
33599
+ */
33600
+ bumpSchedulerCursor(meshId) {
33601
+ return this.transaction(() => {
33602
+ const current = this.getSchedulerCursor(meshId);
33603
+ this.db.prepare(`
33604
+ INSERT INTO mesh_scheduler_cursor (mesh_id, cursor) VALUES (?, ?)
33605
+ ON CONFLICT(mesh_id) DO UPDATE SET cursor = excluded.cursor
33606
+ `).run(meshId, current + 1);
33607
+ return current;
33608
+ });
33609
+ }
33469
33610
  /**
33470
33611
  * Count active (status='assigned') tasks on a (node, provider) combination,
33471
33612
  * matched by the assignedProviderType stamped on the payload at claim time.
@@ -35445,8 +35586,8 @@ ${rendered}`, "utf-8");
35445
35586
  const remaining = (existing.slice(0, openIdx) + existing.slice(closeIdx + CLOSE.length)).replace(/^\s*\n+/, "").replace(/\n+\s*$/, "");
35446
35587
  if (!remaining.trim()) {
35447
35588
  try {
35448
- const fs30 = require("fs");
35449
- fs30.unlinkSync(filePath);
35589
+ const fs31 = require("fs");
35590
+ fs31.unlinkSync(filePath);
35450
35591
  } catch {
35451
35592
  }
35452
35593
  } else {
@@ -38051,6 +38192,33 @@ Next step: ${nextStep}`;
38051
38192
  function nodeHasActiveAssignment(meshId, nodeId) {
38052
38193
  return getQueue(meshId, { status: ["assigned"] }).some((task) => task.assignedNodeId === nodeId);
38053
38194
  }
38195
+ function nodeActiveLoad(meshId, nodeId) {
38196
+ return MeshRuntimeStore.getInstance().nodeActiveAssignmentCount(meshId, nodeId);
38197
+ }
38198
+ function resolveSchedulingStrategy(mesh) {
38199
+ return normalizeMeshSchedulingStrategy(mesh?.policy?.schedulingStrategy);
38200
+ }
38201
+ function orderEligibleNodes(meshId, strategy, nodes, opts) {
38202
+ if (strategy === "first_eligible" || nodes.length <= 1) {
38203
+ return nodes;
38204
+ }
38205
+ const priorityOf = (n) => resolveNodeSchedulingPriority(n.node?.policy);
38206
+ let rotation = 0;
38207
+ if (strategy === "round_robin") {
38208
+ const cursor = opts?.bumpCursor ? MeshRuntimeStore.getInstance().bumpSchedulerCursor(meshId) : MeshRuntimeStore.getInstance().getSchedulerCursor(meshId);
38209
+ rotation = (cursor % nodes.length + nodes.length) % nodes.length;
38210
+ }
38211
+ const rotationRank = (index) => (index - rotation + nodes.length) % nodes.length;
38212
+ return [...nodes].sort((a, b) => {
38213
+ const prioDelta = priorityOf(b) - priorityOf(a);
38214
+ if (prioDelta !== 0) return prioDelta;
38215
+ if (strategy === "least_loaded" || strategy === "round_robin") {
38216
+ const loadDelta = nodeActiveLoad(meshId, a.nodeId) - nodeActiveLoad(meshId, b.nodeId);
38217
+ if (loadDelta !== 0) return loadDelta;
38218
+ }
38219
+ return rotationRank(a.index) - rotationRank(b.index);
38220
+ });
38221
+ }
38054
38222
  function activeProviderAssignedCount(meshId, nodeId, providerType) {
38055
38223
  return getQueue(meshId, { status: ["assigned"] }).filter((task) => task.assignedNodeId === nodeId && task.assignedProviderType === providerType).length;
38056
38224
  }
@@ -38187,7 +38355,14 @@ Next step: ${nextStep}`;
38187
38355
  markAutoLaunch(meshId, task.id, { status: "skipped", reason: "no_node_satisfies_required_tags", nodeId: task.targetNodeId });
38188
38356
  continue;
38189
38357
  }
38190
- for (const node of candidateNodes) {
38358
+ const strategy = resolveSchedulingStrategy(mesh);
38359
+ const orderedCandidateNodes = strategy === "first_eligible" ? candidateNodes : orderEligibleNodes(
38360
+ meshId,
38361
+ strategy,
38362
+ candidateNodes.map((node, index) => ({ nodeId: readMeshNodeId(node), node, index })).filter((c) => c.nodeId),
38363
+ { bumpCursor: true }
38364
+ ).map((c) => c.node);
38365
+ for (const node of orderedCandidateNodes) {
38191
38366
  const nodeId = readMeshNodeId(node);
38192
38367
  if (!nodeId) continue;
38193
38368
  const launchKey = `${meshId}:${nodeId}`;
@@ -38314,6 +38489,8 @@ Next step: ${nextStep}`;
38314
38489
  noIdleMeshSessionAvailable: true
38315
38490
  };
38316
38491
  }
38492
+ const strategy = resolveSchedulingStrategy(mesh);
38493
+ const localCandidates = [];
38317
38494
  const cliInstances = components.instanceManager.getByCategory("cli");
38318
38495
  for (const inst of cliInstances) {
38319
38496
  const state = inst.getState();
@@ -38336,7 +38513,7 @@ Next step: ${nextStep}`;
38336
38513
  const providerType = state.type || readNonEmptyString2(settings.providerType);
38337
38514
  if (providerType) {
38338
38515
  localIdleSessionsChecked += 1;
38339
- tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType);
38516
+ localCandidates.push({ nodeId, sessionId, providerType, origin: "local", node: mesh.nodes.find((n) => readMeshNodeId(n) === nodeId) });
38340
38517
  } else {
38341
38518
  skippedSessions.push({
38342
38519
  nodeId,
@@ -38350,18 +38527,49 @@ Next step: ${nextStep}`;
38350
38527
  remoteSessions = MeshRuntimeStore.getInstance().getRemoteIdleSessions();
38351
38528
  } catch {
38352
38529
  }
38530
+ const remoteCandidates = [];
38353
38531
  for (const idle of remoteSessions) {
38354
38532
  const node = mesh.nodes.find((n) => n.id === idle.nodeId);
38355
38533
  if (node) {
38356
38534
  remoteIdleSessionsChecked += 1;
38357
- const assigned = tryAssignQueueTask(components, meshId, idle.nodeId, idle.sessionId, idle.providerType);
38358
- if (assigned) {
38359
- try {
38360
- MeshRuntimeStore.getInstance().deleteRemoteIdleSession(idle.nodeId, idle.sessionId);
38361
- } catch {
38362
- }
38535
+ remoteCandidates.push({ nodeId: idle.nodeId, sessionId: idle.sessionId, providerType: idle.providerType, origin: "remote", node });
38536
+ }
38537
+ }
38538
+ const assignIdleCandidate = (candidate) => {
38539
+ const assigned = tryAssignQueueTask(components, meshId, candidate.nodeId, candidate.sessionId, candidate.providerType);
38540
+ if (assigned && candidate.origin === "remote") {
38541
+ try {
38542
+ MeshRuntimeStore.getInstance().deleteRemoteIdleSession(candidate.nodeId, candidate.sessionId);
38543
+ } catch {
38363
38544
  }
38364
38545
  }
38546
+ };
38547
+ if (strategy === "first_eligible") {
38548
+ for (const candidate of localCandidates) assignIdleCandidate(candidate);
38549
+ for (const candidate of remoteCandidates) assignIdleCandidate(candidate);
38550
+ } else {
38551
+ const pool = [...localCandidates, ...remoteCandidates];
38552
+ const baseIndex = /* @__PURE__ */ new Map();
38553
+ pool.forEach((c, i) => {
38554
+ if (!baseIndex.has(c.nodeId)) baseIndex.set(c.nodeId, i);
38555
+ });
38556
+ const uniqueNodes = [...new Set(pool.map((c) => c.nodeId))].map((nodeId, index) => ({ nodeId, node: pool.find((c) => c.nodeId === nodeId)?.node, index }));
38557
+ const ranked = orderEligibleNodes(meshId, strategy, uniqueNodes, { bumpCursor: true });
38558
+ const rankIndex = new Map(ranked.map((r, i) => [r.nodeId, i]));
38559
+ const remaining = [...pool];
38560
+ while (remaining.length > 0) {
38561
+ remaining.sort((a, b) => {
38562
+ const aPrio = resolveNodeSchedulingPriority(a.node?.policy);
38563
+ const bPrio = resolveNodeSchedulingPriority(b.node?.policy);
38564
+ if (aPrio !== bPrio) return bPrio - aPrio;
38565
+ if (strategy === "least_loaded" || strategy === "round_robin") {
38566
+ const loadDelta = nodeActiveLoad(meshId, a.nodeId) - nodeActiveLoad(meshId, b.nodeId);
38567
+ if (loadDelta !== 0) return loadDelta;
38568
+ }
38569
+ return (rankIndex.get(a.nodeId) ?? 0) - (rankIndex.get(b.nodeId) ?? 0);
38570
+ });
38571
+ assignIdleCandidate(remaining.shift());
38572
+ }
38365
38573
  }
38366
38574
  autoLaunchStarted = await maybeAutoLaunchOneQueueSession(components, meshId, mesh);
38367
38575
  const afterQueue = getQueue(meshId);
@@ -40424,8 +40632,8 @@ Next step: ${nextStep}`;
40424
40632
  let cwd = options.cwd;
40425
40633
  if (cwd) {
40426
40634
  try {
40427
- const fs30 = require("fs");
40428
- const stat2 = fs30.statSync(cwd);
40635
+ const fs31 = require("fs");
40636
+ const stat2 = fs31.statSync(cwd);
40429
40637
  if (!stat2.isDirectory()) cwd = os11.homedir();
40430
40638
  } catch {
40431
40639
  cwd = os11.homedir();
@@ -40530,9 +40738,9 @@ Next step: ${nextStep}`;
40530
40738
  for (const ext of exes) {
40531
40739
  const fullPath = path17.join(p, trimmed + ext);
40532
40740
  try {
40533
- const fs30 = require("fs");
40534
- if (fs30.existsSync(fullPath)) {
40535
- const stat2 = fs30.statSync(fullPath);
40741
+ const fs31 = require("fs");
40742
+ if (fs31.existsSync(fullPath)) {
40743
+ const stat2 = fs31.statSync(fullPath);
40536
40744
  if (stat2.isFile() && (isWin || stat2.mode & 73)) {
40537
40745
  return fullPath;
40538
40746
  }
@@ -40546,12 +40754,12 @@ Next step: ${nextStep}`;
40546
40754
  function isScriptBinary(binaryPath) {
40547
40755
  if (!path17.isAbsolute(binaryPath)) return false;
40548
40756
  try {
40549
- const fs30 = require("fs");
40550
- const resolved = fs30.realpathSync(binaryPath);
40757
+ const fs31 = require("fs");
40758
+ const resolved = fs31.realpathSync(binaryPath);
40551
40759
  const head = Buffer.alloc(8);
40552
- const fd = fs30.openSync(resolved, "r");
40553
- fs30.readSync(fd, head, 0, 8, 0);
40554
- fs30.closeSync(fd);
40760
+ const fd = fs31.openSync(resolved, "r");
40761
+ fs31.readSync(fd, head, 0, 8, 0);
40762
+ fs31.closeSync(fd);
40555
40763
  let i = 0;
40556
40764
  if (head[0] === 239 && head[1] === 187 && head[2] === 191) i = 3;
40557
40765
  return head[i] === 35 && head[i + 1] === 33;
@@ -40562,12 +40770,12 @@ Next step: ${nextStep}`;
40562
40770
  function looksLikeMachOOrElf(filePath) {
40563
40771
  if (!path17.isAbsolute(filePath)) return false;
40564
40772
  try {
40565
- const fs30 = require("fs");
40566
- const resolved = fs30.realpathSync(filePath);
40773
+ const fs31 = require("fs");
40774
+ const resolved = fs31.realpathSync(filePath);
40567
40775
  const buf = Buffer.alloc(8);
40568
- const fd = fs30.openSync(resolved, "r");
40569
- fs30.readSync(fd, buf, 0, 8, 0);
40570
- fs30.closeSync(fd);
40776
+ const fd = fs31.openSync(resolved, "r");
40777
+ fs31.readSync(fd, buf, 0, 8, 0);
40778
+ fs31.closeSync(fd);
40571
40779
  let i = 0;
40572
40780
  if (buf[0] === 239 && buf[1] === 187 && buf[2] === 191) i = 3;
40573
40781
  const b = buf.subarray(i);
@@ -41743,7 +41951,7 @@ ${cont}` : cont;
41743
41951
  scheduleSettle() {
41744
41952
  if (this.settleTimer) clearTimeout(this.settleTimer);
41745
41953
  const epoch = this.responseEpoch;
41746
- const delay = Math.max(
41954
+ const delay2 = Math.max(
41747
41955
  this.timeouts.outputSettle,
41748
41956
  this.submitPendingUntil > Date.now() ? this.submitPendingUntil - Date.now() + this.timeouts.outputSettle : 0
41749
41957
  );
@@ -41751,7 +41959,7 @@ ${cont}` : cont;
41751
41959
  this.settleTimer = null;
41752
41960
  if (epoch !== this.responseEpoch) return;
41753
41961
  this.evaluateSettled(this.transport.getSnapshot());
41754
- }, delay);
41962
+ }, delay2);
41755
41963
  }
41756
41964
  /** Called from sendMessage in transport once a turn scope is established. */
41757
41965
  onTurnStarted(turnScope) {
@@ -45262,6 +45470,7 @@ ${lastSnapshot}`;
45262
45470
  DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS: () => DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS,
45263
45471
  DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS: () => DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS2,
45264
45472
  DEFAULT_MESH_POLICY: () => DEFAULT_MESH_POLICY,
45473
+ DEFAULT_MESH_SCHEDULING_STRATEGY: () => DEFAULT_MESH_SCHEDULING_STRATEGY,
45265
45474
  DEFAULT_SESSION_HOST_APP_NAME: () => DEFAULT_SESSION_HOST_APP_NAME,
45266
45475
  DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS: () => DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS2,
45267
45476
  DEFAULT_SESSION_HOST_READY_TIMEOUT_MS: () => DEFAULT_SESSION_HOST_READY_TIMEOUT_MS2,
@@ -45287,9 +45496,12 @@ ${lastSnapshot}`;
45287
45496
  InMemoryGitSnapshotStore: () => InMemoryGitSnapshotStore,
45288
45497
  LOG: () => LOG2,
45289
45498
  MAX_LEDGER_SLICE_LIMIT: () => MAX_LEDGER_SLICE_LIMIT,
45499
+ MESH_CONVERGE_FAST_FORWARD_TAG: () => MESH_CONVERGE_FAST_FORWARD_TAG,
45500
+ MESH_CONVERGE_REFINE_TAG: () => MESH_CONVERGE_REFINE_TAG,
45290
45501
  MESH_MISSION_STATUSES: () => MESH_MISSION_STATUSES,
45291
45502
  MESH_REFINE_CONFIG_LOCATIONS: () => MESH_REFINE_CONFIG_LOCATIONS,
45292
45503
  MESH_REFINE_CONFIG_SCHEMA: () => MESH_REFINE_CONFIG_SCHEMA,
45504
+ MESH_SCHEDULING_STRATEGIES: () => MESH_SCHEDULING_STRATEGIES,
45293
45505
  MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS: () => MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS,
45294
45506
  MESH_WORKTREE_BOOTSTRAP_CONFIG_SCHEMA: () => MESH_WORKTREE_BOOTSTRAP_CONFIG_SCHEMA,
45295
45507
  MIN_GIT_WORKSPACE_POLL_INTERVAL_MS: () => MIN_GIT_WORKSPACE_POLL_INTERVAL_MS,
@@ -45490,6 +45702,7 @@ ${lastSnapshot}`;
45490
45702
  normalizeManagedStatus: () => normalizeManagedStatus,
45491
45703
  normalizeMeshCapabilityTags: () => normalizeMeshCapabilityTags,
45492
45704
  normalizeMeshDaemonRole: () => normalizeMeshDaemonRole,
45705
+ normalizeMeshSchedulingStrategy: () => normalizeMeshSchedulingStrategy,
45493
45706
  normalizeMeshTaskMode: () => normalizeMeshTaskMode,
45494
45707
  normalizeMeshWorkerResult: () => normalizeMeshWorkerResult,
45495
45708
  normalizeMessageParts: () => normalizeMessageParts,
@@ -45527,7 +45740,9 @@ ${lastSnapshot}`;
45527
45740
  resetConfig: () => resetConfig,
45528
45741
  resetDebugRuntimeConfig: () => resetDebugRuntimeConfig,
45529
45742
  resetState: () => resetState,
45743
+ resolveAutoConvergeCodeChange: () => resolveAutoConvergeCodeChange,
45530
45744
  resolveChatMessageKind: () => resolveChatMessageKind,
45745
+ resolveConvergeRequiredTags: () => resolveConvergeRequiredTags,
45531
45746
  resolveCurrentGlobalInstallSurface: () => resolveCurrentGlobalInstallSurface,
45532
45747
  resolveDebugRuntimeConfig: () => resolveDebugRuntimeConfig,
45533
45748
  resolveDelegatedWorkerAutoApprove: () => resolveDelegatedWorkerAutoApprove,
@@ -45535,6 +45750,7 @@ ${lastSnapshot}`;
45535
45750
  resolveGitRepository: () => resolveGitRepository,
45536
45751
  resolveMeshHostStatus: () => resolveMeshHostStatus,
45537
45752
  resolveMeshRefineValidationPlan: () => resolveMeshRefineValidationPlan,
45753
+ resolveNodeSchedulingPriority: () => resolveNodeSchedulingPriority,
45538
45754
  resolveSessionHostAppName: () => resolveSessionHostAppName,
45539
45755
  resolveSessionHostAppNameResolution: () => resolveSessionHostAppNameResolution2,
45540
45756
  resolveWorktreePath: () => resolveWorktreePath,
@@ -47863,9 +48079,9 @@ ${lastSnapshot}`;
47863
48079
  return typeof value === "string" && value.trim() ? value.trim() : void 0;
47864
48080
  }
47865
48081
  function summarizeMessage(message) {
47866
- const oneLine = message.replace(/\s+/g, " ").trim();
47867
- const title = oneLine.length > 96 ? `${oneLine.slice(0, 93)}...` : oneLine;
47868
- return { title: title || "(untitled task)", summary: oneLine };
48082
+ const oneLine2 = message.replace(/\s+/g, " ").trim();
48083
+ const title = oneLine2.length > 96 ? `${oneLine2.slice(0, 93)}...` : oneLine2;
48084
+ return { title: title || "(untitled task)", summary: oneLine2 };
47869
48085
  }
47870
48086
  function elapsedSince(value, now) {
47871
48087
  const started = value ? new Date(value).getTime() : Number.NaN;
@@ -50937,6 +51153,11 @@ ${cleanBody}`;
50937
51153
  continue;
50938
51154
  }
50939
51155
  if (message.role === "assistant") {
51156
+ const isActivity = message.kind === "tool" || message.kind === "terminal" || message.kind === "thought";
51157
+ if (isActivity) {
51158
+ collapsed.push(message);
51159
+ continue;
51160
+ }
50940
51161
  if (sawAssistantSinceLastUser) continue;
50941
51162
  sawAssistantSinceLastUser = true;
50942
51163
  collapsed.push(message);
@@ -56028,7 +56249,8 @@ ${effect.notification.body || ""}`.trim();
56028
56249
  const sessionIdHint = typeof args?.targetSessionId === "string" ? args.targetSessionId : typeof args?.sessionId === "string" ? args.sessionId : "";
56029
56250
  const providerHint = typeof args?.cliType === "string" ? args.cliType : typeof args?.providerType === "string" ? args.providerType : typeof args?.agentType === "string" ? args.agentType : "";
56030
56251
  const filteredMessages = h ? maybeHideCoordinatorPromptMessage(h, providerHint, sessionIdHint, messages) : messages;
56031
- const visibleMessages = filterUserFacingChatMessages(filteredMessages);
56252
+ const includeActivity = args?.includeActivity === true || args?.includeActivity === "true";
56253
+ const visibleMessages = includeActivity ? filteredMessages.filter((m) => isUserFacingChatMessage(m) || isActivityChatMessage(m)) : filterUserFacingChatMessages(filteredMessages);
56032
56254
  const sync = buildFullTail(visibleMessages, normalizeReadChatTailLimit(args));
56033
56255
  const hiddenMsgCount = Math.max(0, messages.length - visibleMessages.length);
56034
56256
  const preservedPayloadFields = Object.fromEntries(Object.entries(payload).filter(([key]) => shouldPreserveReadChatPayloadField(key)));
@@ -58387,6 +58609,9 @@ ${effect.notification.body || ""}`.trim();
58387
58609
  }
58388
58610
  function buildControlScriptResult(scriptName, payload) {
58389
58611
  if (!payload || typeof payload !== "object") return {};
58612
+ if (payload.controlResult && typeof payload.controlResult === "object") {
58613
+ return { controlResult: payload.controlResult };
58614
+ }
58390
58615
  const legacyListPayload = (() => {
58391
58616
  if (Array.isArray(payload.options)) return payload;
58392
58617
  if (/^listmodels$/i.test(scriptName) && Array.isArray(payload.models)) {
@@ -59245,7 +59470,7 @@ ${effect.notification.body || ""}`.trim();
59245
59470
  return { success: false, error: "invalid type" };
59246
59471
  }
59247
59472
  const https = require("https");
59248
- const fs30 = require("fs");
59473
+ const fs31 = require("fs");
59249
59474
  const path41 = require("path");
59250
59475
  const crypto6 = require("crypto");
59251
59476
  const REGISTRY = "https://api.adhf.dev/api/v1/registry";
@@ -59289,7 +59514,7 @@ ${effect.notification.body || ""}`.trim();
59289
59514
  if (!targetDir.startsWith(installRootResolved + path41.sep)) {
59290
59515
  return { success: false, error: "install path escaped upstream root" };
59291
59516
  }
59292
- fs30.mkdirSync(targetDir, { recursive: true });
59517
+ fs31.mkdirSync(targetDir, { recursive: true });
59293
59518
  let manifestProbe = {};
59294
59519
  try {
59295
59520
  manifestProbe = JSON.parse(manifestBody);
@@ -59314,7 +59539,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
59314
59539
  }
59315
59540
  const targetFile = isV1 ? "provider.v1.json" : "provider.json";
59316
59541
  const targetPath = path41.join(targetDir, targetFile);
59317
- fs30.writeFileSync(targetPath, manifestBody, "utf-8");
59542
+ fs31.writeFileSync(targetPath, manifestBody, "utf-8");
59318
59543
  const manifestJson = JSON.parse(manifestBody);
59319
59544
  const scriptFetch = await this.fetchProviderSources(
59320
59545
  manifestJson,
@@ -59384,7 +59609,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
59384
59609
  const repo = source.repo;
59385
59610
  const ref = source.ref;
59386
59611
  const https = require("https");
59387
- const fs30 = require("fs");
59612
+ const fs31 = require("fs");
59388
59613
  const path41 = require("path");
59389
59614
  function fetchJson(url2, timeoutMs) {
59390
59615
  return new Promise((resolve24, reject) => {
@@ -59468,8 +59693,8 @@ ${formatManifestValidationIssues2(validation.issues)}`,
59468
59693
  const relInside = entry.path.startsWith(sharedDirRel + "/") ? entry.path.slice(sharedDirRel.length + 1) : entry.path;
59469
59694
  const outPath = path41.resolve(path41.join(sharedTargetDir, relInside));
59470
59695
  if (!outPath.startsWith(path41.resolve(sharedTargetDir) + path41.sep)) continue;
59471
- fs30.mkdirSync(path41.dirname(outPath), { recursive: true });
59472
- fs30.writeFileSync(outPath, body);
59696
+ fs31.mkdirSync(path41.dirname(outPath), { recursive: true });
59697
+ fs31.writeFileSync(outPath, body);
59473
59698
  fetchedCount++;
59474
59699
  } catch (e) {
59475
59700
  errors.push(`fetch shared ${entry.path}: ${e?.message ?? e}`);
@@ -59507,8 +59732,8 @@ ${formatManifestValidationIssues2(validation.issues)}`,
59507
59732
  errors.push(`refusing to write outside targetDir: ${entry.path}`);
59508
59733
  continue;
59509
59734
  }
59510
- fs30.mkdirSync(path41.dirname(outPath), { recursive: true });
59511
- fs30.writeFileSync(outPath, body);
59735
+ fs31.mkdirSync(path41.dirname(outPath), { recursive: true });
59736
+ fs31.writeFileSync(outPath, body);
59512
59737
  fetchedCount++;
59513
59738
  } catch (e) {
59514
59739
  errors.push(`fetch ${entry.path}: ${e?.message ?? e}`);
@@ -59536,7 +59761,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
59536
59761
  if (!["cli", "ide", "extension", "acp"].includes(category)) {
59537
59762
  return { success: false, error: `unknown category: ${category}` };
59538
59763
  }
59539
- const fs30 = require("fs");
59764
+ const fs31 = require("fs");
59540
59765
  const path41 = require("path");
59541
59766
  try {
59542
59767
  const installRoot = this.getUpstreamInstallRoot();
@@ -59545,10 +59770,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
59545
59770
  if (!targetDir.startsWith(installRootResolved + path41.sep)) {
59546
59771
  return { success: false, error: "refusing to delete outside upstream root" };
59547
59772
  }
59548
- if (!fs30.existsSync(targetDir)) {
59773
+ if (!fs31.existsSync(targetDir)) {
59549
59774
  return { success: false, error: "not installed" };
59550
59775
  }
59551
- fs30.rmSync(targetDir, { recursive: true, force: true });
59776
+ fs31.rmSync(targetDir, { recursive: true, force: true });
59552
59777
  if (this._ctx.providerLoader) {
59553
59778
  this._ctx.providerLoader.reload();
59554
59779
  this._ctx.providerLoader.registerToDetector();
@@ -59564,28 +59789,28 @@ ${formatManifestValidationIssues2(validation.issues)}`,
59564
59789
  * the UI and by the update checker.
59565
59790
  */
59566
59791
  handleListInstalledProviders(_args) {
59567
- const fs30 = require("fs");
59792
+ const fs31 = require("fs");
59568
59793
  const path41 = require("path");
59569
59794
  const installRoot = this.getUpstreamInstallRoot();
59570
- if (!fs30.existsSync(installRoot)) return { success: true, providers: [] };
59795
+ if (!fs31.existsSync(installRoot)) return { success: true, providers: [] };
59571
59796
  const CATEGORIES = ["cli", "ide", "extension", "acp"];
59572
59797
  const items = [];
59573
59798
  for (const category of CATEGORIES) {
59574
59799
  const categoryDir = path41.join(installRoot, category);
59575
- if (!fs30.existsSync(categoryDir)) continue;
59800
+ if (!fs31.existsSync(categoryDir)) continue;
59576
59801
  let entries;
59577
59802
  try {
59578
- entries = fs30.readdirSync(categoryDir);
59803
+ entries = fs31.readdirSync(categoryDir);
59579
59804
  } catch {
59580
59805
  continue;
59581
59806
  }
59582
59807
  for (const type of entries) {
59583
59808
  const v1Path = path41.join(categoryDir, type, "provider.v1.json");
59584
59809
  const v0Path = path41.join(categoryDir, type, "provider.json");
59585
- const manifestPath = fs30.existsSync(v1Path) ? v1Path : fs30.existsSync(v0Path) ? v0Path : null;
59810
+ const manifestPath = fs31.existsSync(v1Path) ? v1Path : fs31.existsSync(v0Path) ? v0Path : null;
59586
59811
  if (!manifestPath) continue;
59587
59812
  try {
59588
- const m = JSON.parse(fs30.readFileSync(manifestPath, "utf-8"));
59813
+ const m = JSON.parse(fs31.readFileSync(manifestPath, "utf-8"));
59589
59814
  items.push({
59590
59815
  type,
59591
59816
  category,
@@ -59696,7 +59921,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
59696
59921
  if (!/^@[a-z0-9_-]+$/i.test(requestedName)) {
59697
59922
  return { success: false, error: "name must match @[a-z0-9_-]+" };
59698
59923
  }
59699
- const fs30 = require("fs");
59924
+ const fs31 = require("fs");
59700
59925
  const path41 = require("path");
59701
59926
  const { spawnSync: spawnSync2 } = require("child_process");
59702
59927
  const file2 = ext.loadExternalSources();
@@ -59707,8 +59932,8 @@ ${formatManifestValidationIssues2(validation.issues)}`,
59707
59932
  return { success: false, error: `source url+ref already registered (use a different name to track another ref)` };
59708
59933
  }
59709
59934
  const sourceDir = path41.join(ext.externalRoot(), requestedName);
59710
- if (!fs30.existsSync(ext.externalRoot())) fs30.mkdirSync(ext.externalRoot(), { recursive: true });
59711
- if (fs30.existsSync(sourceDir)) {
59935
+ if (!fs31.existsSync(ext.externalRoot())) fs31.mkdirSync(ext.externalRoot(), { recursive: true });
59936
+ if (fs31.existsSync(sourceDir)) {
59712
59937
  return { success: false, error: `directory already exists: ${sourceDir} (rename or remove first)` };
59713
59938
  }
59714
59939
  const clone2 = spawnSync2("git", ["clone", "--depth=1", "--branch", ref, "--", url2, sourceDir], {
@@ -59718,7 +59943,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
59718
59943
  });
59719
59944
  if (clone2.status !== 0) {
59720
59945
  try {
59721
- fs30.rmSync(sourceDir, { recursive: true, force: true });
59946
+ fs31.rmSync(sourceDir, { recursive: true, force: true });
59722
59947
  } catch {
59723
59948
  }
59724
59949
  return { success: false, error: `git clone failed: ${(clone2.stderr || clone2.stdout || "").trim() || "unknown error"}` };
@@ -59762,15 +59987,15 @@ ${formatManifestValidationIssues2(validation.issues)}`,
59762
59987
  const name = typeof args?.name === "string" ? args.name.trim() : "";
59763
59988
  if (!name) return { success: false, error: "name is required" };
59764
59989
  const ext = (init_external_sources(), __toCommonJS2(external_sources_exports));
59765
- const fs30 = require("fs");
59990
+ const fs31 = require("fs");
59766
59991
  const path41 = require("path");
59767
59992
  const file2 = ext.loadExternalSources();
59768
59993
  const match = file2.sources.find((s) => s.name === name);
59769
59994
  if (!match) return { success: false, error: `source "${name}" not registered` };
59770
59995
  const sourceDir = path41.join(ext.externalRoot(), name);
59771
- if (fs30.existsSync(sourceDir)) {
59996
+ if (fs31.existsSync(sourceDir)) {
59772
59997
  try {
59773
- fs30.rmSync(sourceDir, { recursive: true, force: true });
59998
+ fs31.rmSync(sourceDir, { recursive: true, force: true });
59774
59999
  } catch (e) {
59775
60000
  return { success: false, error: `failed to delete ${sourceDir}: ${e?.message || e}` };
59776
60001
  }
@@ -60217,12 +60442,12 @@ ${formatManifestValidationIssues2(validation.issues)}`,
60217
60442
  scheduleSpawnPrime() {
60218
60443
  const seqs = this.spec.send_on_spawn;
60219
60444
  if (!Array.isArray(seqs) || seqs.length === 0) return;
60220
- const delay = Math.max(0, this.spec.send_on_spawn_delay_ms ?? 250);
60445
+ const delay2 = Math.max(0, this.spec.send_on_spawn_delay_ms ?? 250);
60221
60446
  setTimeout(() => {
60222
60447
  for (const seq of seqs) {
60223
60448
  if (typeof seq === "string" && seq.length > 0) this.adapter.send_keys(seq);
60224
60449
  }
60225
- }, delay);
60450
+ }, delay2);
60226
60451
  }
60227
60452
  dispatch(cmd) {
60228
60453
  switch (cmd.kind) {
@@ -60588,11 +60813,11 @@ ${formatManifestValidationIssues2(validation.issues)}`,
60588
60813
  const armed = this.delegateTimers.has(d.id);
60589
60814
  const shouldFire = d.when_state === currentStateId;
60590
60815
  if (shouldFire && !armed) {
60591
- const delay = d.after_duration_ms ?? 0;
60816
+ const delay2 = d.after_duration_ms ?? 0;
60592
60817
  const t = setTimeout(() => {
60593
60818
  this.fireDelegate(d);
60594
60819
  this.delegateTimers.delete(d.id);
60595
- }, delay);
60820
+ }, delay2);
60596
60821
  this.delegateTimers.set(d.id, t);
60597
60822
  } else if (!shouldFire && armed) {
60598
60823
  clearTimeout(this.delegateTimers.get(d.id));
@@ -60646,7 +60871,15 @@ ${formatManifestValidationIssues2(validation.issues)}`,
60646
60871
  this.adapter.send_keys(a.keys);
60647
60872
  return;
60648
60873
  case "open_picker":
60649
- this.adapter.send_keys(a.trigger_keys);
60874
+ {
60875
+ const m = /^([\s\S]*?)([\r\n]+)$/.exec(a.trigger_keys);
60876
+ if (m && m[1]) {
60877
+ this.adapter.send_keys(m[1]);
60878
+ setTimeout(() => this.adapter.send_keys(m[2]), 200);
60879
+ } else {
60880
+ this.adapter.send_keys(a.trigger_keys);
60881
+ }
60882
+ }
60650
60883
  this.pickerInProgress = { control_id: ctl.id, spec: ctl };
60651
60884
  return;
60652
60885
  case "attach_image": {
@@ -60829,8 +61062,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
60829
61062
  for (let i = 0; i < lines.length; i += 1) {
60830
61063
  const rec = lines[i];
60831
61064
  if (filter && !filter(rec)) continue;
60832
- const msg = projectMessage(rec, src.message_map, i, lines.length, mtime);
60833
- if (msg) {
61065
+ for (const msg of projectMessages(rec, src.message_map, i, lines.length, mtime)) {
60834
61066
  if (transcriptWorkspace) msg.workspace = transcriptWorkspace;
60835
61067
  messages.push(msg);
60836
61068
  }
@@ -60910,8 +61142,9 @@ ${formatManifestValidationIssues2(validation.issues)}`,
60910
61142
  const mtime = safeMtimeMs(resolved);
60911
61143
  const messages = [];
60912
61144
  for (let i = 0; i < messageRows.length; i += 1) {
60913
- const msg = projectMessage(messageRows[i], src.message_map, i, messageRows.length, mtime);
60914
- if (msg) messages.push(msg);
61145
+ for (const msg of projectMessages(messageRows[i], src.message_map, i, messageRows.length, mtime)) {
61146
+ messages.push(msg);
61147
+ }
60915
61148
  }
60916
61149
  if (messages.length === 0) return null;
60917
61150
  return {
@@ -61309,11 +61542,42 @@ ${formatManifestValidationIssues2(validation.issues)}`,
61309
61542
  }
61310
61543
  return cur;
61311
61544
  }
61312
- function projectMessage(record2, map2, index, total, sourceMtimeMs) {
61545
+ function projectMessages(record2, map2, index, total, sourceMtimeMs) {
61313
61546
  const roleRaw = jsonPathGet(record2, map2.role);
61314
- const contentRaw = jsonPathGet(record2, map2.content);
61315
61547
  const role = normalizeRole(roleRaw);
61316
- let content = stringifyContent(contentRaw);
61548
+ let receivedAt = sourceMtimeMs - (total - 1 - index) * 1e3;
61549
+ if (map2.timestamp_ms) {
61550
+ const tsRaw = jsonPathGet(record2, map2.timestamp_ms);
61551
+ const parsed = parseTimestamp(tsRaw);
61552
+ if (parsed != null) receivedAt = parsed;
61553
+ }
61554
+ const kindRaw = map2.kind ? jsonPathGet(record2, map2.kind) : void 0;
61555
+ const kind = typeof kindRaw === "string" && kindRaw ? kindRaw : "standard";
61556
+ const out = [];
61557
+ if (map2.tools) {
61558
+ const recordTool = projectToolBlock(record2, role, map2.tools);
61559
+ if (recordTool) {
61560
+ out.push({ ...recordTool, receivedAt });
61561
+ return out;
61562
+ }
61563
+ }
61564
+ const contentRaw = jsonPathGet(record2, map2.content);
61565
+ const content = cleanContent(stringifyContent(contentRaw), map2);
61566
+ if (content) out.push({ role, content, receivedAt, kind });
61567
+ if (map2.tools && Array.isArray(contentRaw)) {
61568
+ let nudge = 1;
61569
+ for (const block2 of contentRaw) {
61570
+ const tool = projectToolBlock(block2, role, map2.tools);
61571
+ if (tool) {
61572
+ out.push({ ...tool, receivedAt: receivedAt + nudge });
61573
+ nudge += 1;
61574
+ }
61575
+ }
61576
+ }
61577
+ return out;
61578
+ }
61579
+ function cleanContent(input, map2) {
61580
+ let content = input;
61317
61581
  if (content && map2.content_strip) {
61318
61582
  for (const tag of map2.content_strip) {
61319
61583
  const safeTag = tag.replace(/[.+^${}()|[\]\\]/g, "\\$&");
@@ -61329,17 +61593,33 @@ ${formatManifestValidationIssues2(validation.issues)}`,
61329
61593
  content = content.replace(open, "").replace(close, "");
61330
61594
  }
61331
61595
  }
61332
- if (content) content = content.trim();
61333
- if (!content) return null;
61334
- let receivedAt = sourceMtimeMs - (total - 1 - index) * 1e3;
61335
- if (map2.timestamp_ms) {
61336
- const tsRaw = jsonPathGet(record2, map2.timestamp_ms);
61337
- const parsed = parseTimestamp(tsRaw);
61338
- if (parsed != null) receivedAt = parsed;
61596
+ return content ? content.trim() : "";
61597
+ }
61598
+ var DEFAULT_TOOL_CALL_TYPES = ["tool_use", "function_call", "custom_tool_call"];
61599
+ var DEFAULT_TOOL_RESULT_TYPES = ["tool_result", "function_call_output", "custom_tool_call_output"];
61600
+ function projectToolBlock(block2, role, tmap) {
61601
+ void role;
61602
+ if (block2 == null || typeof block2 !== "object") return null;
61603
+ const typeVal = String(jsonPathGet(block2, tmap.block_type || "$.type") ?? "");
61604
+ if (!typeVal) return null;
61605
+ const callTypes = tmap.call_types ?? DEFAULT_TOOL_CALL_TYPES;
61606
+ const resultTypes = tmap.result_types ?? DEFAULT_TOOL_RESULT_TYPES;
61607
+ if (callTypes.includes(typeVal)) {
61608
+ const name = String(jsonPathGet(block2, tmap.call_name || "$.name") ?? "tool").trim() || "tool";
61609
+ const args = oneLine(stringifyContent(jsonPathGet(block2, tmap.call_args || "$.input")), 240);
61610
+ const content = args ? `\u2197 ${name}: ${args}` : `\u2197 ${name}`;
61611
+ return { role: "assistant", content, receivedAt: 0, kind: "tool" };
61612
+ }
61613
+ if (resultTypes.includes(typeVal)) {
61614
+ const result = oneLine(stringifyContent(jsonPathGet(block2, tmap.result_content || "$.content")), 600);
61615
+ if (!result) return null;
61616
+ return { role: "assistant", content: `\u2198 ${result}`, receivedAt: 0, kind: "tool" };
61339
61617
  }
61340
- const kindRaw = map2.kind ? jsonPathGet(record2, map2.kind) : void 0;
61341
- const kind = typeof kindRaw === "string" && kindRaw ? kindRaw : "standard";
61342
- return { role, content, receivedAt, kind };
61618
+ return null;
61619
+ }
61620
+ function oneLine(s, max) {
61621
+ const flat = s.replace(/\s+/g, " ").trim();
61622
+ return flat.length > max ? flat.slice(0, max - 1) + "\u2026" : flat;
61343
61623
  }
61344
61624
  function parseTimestamp(v) {
61345
61625
  if (v == null) return null;
@@ -61478,6 +61758,9 @@ ${formatManifestValidationIssues2(validation.issues)}`,
61478
61758
  function stripAnsi3(text) {
61479
61759
  return String(text || "").replace(/\x1B\][^\x07]*(?:\x07|\x1B\\)/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "");
61480
61760
  }
61761
+ function delay(ms) {
61762
+ return new Promise((resolve24) => setTimeout(resolve24, ms));
61763
+ }
61481
61764
  var SpecCliAdapter = class _SpecCliAdapter {
61482
61765
  cliType;
61483
61766
  cliName;
@@ -61699,9 +61982,15 @@ ${formatManifestValidationIssues2(validation.issues)}`,
61699
61982
  * drives the dispatch:
61700
61983
  *
61701
61984
  * send_keys → click_control (e.g. stop)
61702
- * open_picker → click_control then resolve when extract_choices
61703
- * surface; choice index comes from args.choiceIndex
61704
- * or args.choice (string label match), defaulting to 0
61985
+ * open_picker → two roles, driven by the screen, not a hardcoded list:
61986
+ * - LIST (no choice arg): open the picker, wait for it
61987
+ * to render, parse the on-screen options via
61988
+ * `extract_choices`, and return them as
61989
+ * `controlResult.options` (+ `currentValue`). This is
61990
+ * how the dashboard's Model/Mode controls learn what is
61991
+ * actually selectable in this CLI right now.
61992
+ * - SELECT (args.choiceIndex / args.choiceLabel): drive
61993
+ * the picker to that option using `submit_key`.
61705
61994
  * attach_image → attach_image dispatch; expects args.blob (data url
61706
61995
  * or base64) and args.mime
61707
61996
  *
@@ -61726,11 +62015,128 @@ ${formatManifestValidationIssues2(validation.issues)}`,
61726
62015
  this.driver.dispatch({ kind: "attach_image", blob, mime });
61727
62016
  return Promise.resolve({ ok: true, effects: [{ type: "attached_image", controlId: ctl.id }] });
61728
62017
  }
62018
+ if (action.type === "open_picker") {
62019
+ const choiceIndex = typeof flat.choiceIndex === "number" ? flat.choiceIndex : typeof flat.choiceIndex === "string" && flat.choiceIndex.trim() ? Number(flat.choiceIndex) : void 0;
62020
+ const choiceLabel = typeof flat.choiceLabel === "string" ? flat.choiceLabel : typeof flat.choice === "string" ? flat.choice : void 0;
62021
+ if (typeof choiceIndex === "number" && Number.isFinite(choiceIndex) || choiceLabel && choiceLabel.trim()) {
62022
+ return this.selectPickerChoice(ctl, action, choiceIndex, choiceLabel);
62023
+ }
62024
+ return this.openPickerAndListChoices(ctl, action);
62025
+ }
61729
62026
  this.driver.dispatch({ kind: "click_control", control_id: ctl.id, payload: flat });
61730
- const effects = [];
61731
- if (action.type === "open_picker") effects.push({ type: "opened_picker", controlId: ctl.id });
61732
- else if (action.type === "send_keys") effects.push({ type: "sent_keys", controlId: ctl.id });
61733
- return Promise.resolve({ ok: true, effects });
62027
+ return Promise.resolve({ ok: true, effects: [{ type: "sent_keys", controlId: ctl.id }] });
62028
+ }
62029
+ /**
62030
+ * Open an `open_picker` control and return the options the CLI is showing,
62031
+ * parsed live from the screen via `extract_choices`. Nothing is selected —
62032
+ * the picker is left open so a follow-up SELECT invoke can commit a choice.
62033
+ */
62034
+ async openPickerAndListChoices(ctl, action) {
62035
+ this.driver.dispatch({ kind: "click_control", control_id: ctl.id });
62036
+ const ready = await this.waitForPickerRendered(action);
62037
+ const options = this.extractPickerChoices(action);
62038
+ const currentValue = options.find((o) => o.current)?.label;
62039
+ return {
62040
+ ok: true,
62041
+ effects: [{ type: "opened_picker", controlId: ctl.id }],
62042
+ controlResult: {
62043
+ options: options.map((o) => ({ value: o.label, label: o.label, current: o.current })),
62044
+ ...currentValue ? { currentValue } : {},
62045
+ source: "screen-parse",
62046
+ ...ready ? {} : { warning: "picker_render_timeout" }
62047
+ }
62048
+ };
62049
+ }
62050
+ /**
62051
+ * Drive an already-listable picker to a specific option. The option can be
62052
+ * named (choiceLabel — matched against the parsed on-screen labels) or
62053
+ * positional (choiceIndex — the on-screen number). The actual keystrokes
62054
+ * come from the spec's `submit_key` with `{index}` substituted, so the spec
62055
+ * — not this code — decides how a selection is keyed for each CLI.
62056
+ */
62057
+ async selectPickerChoice(ctl, action, choiceIndex, choiceLabel) {
62058
+ this.driver.dispatch({ kind: "click_control", control_id: ctl.id });
62059
+ await this.waitForPickerRendered(action);
62060
+ const options = this.extractPickerChoices(action);
62061
+ let index = choiceIndex;
62062
+ if ((index == null || !Number.isFinite(index)) && choiceLabel) {
62063
+ const needle = choiceLabel.trim().toLowerCase();
62064
+ const match = options.find((o) => o.label.toLowerCase().includes(needle));
62065
+ if (!match) {
62066
+ return { ok: false, error: `choice not found on screen: ${choiceLabel}`, controlResult: { options: options.map((o) => ({ value: o.label, label: o.label })) } };
62067
+ }
62068
+ index = match.index;
62069
+ }
62070
+ if (index == null || !Number.isFinite(index)) {
62071
+ return { ok: false, error: "choiceIndex or choiceLabel required to select" };
62072
+ }
62073
+ const keys = (action.submit_key || "{index}\r").replace(/\{index\}/g, String(index));
62074
+ this.driver.dispatch({ kind: "pty_write", data: keys });
62075
+ const selected = options.find((o) => o.index === index);
62076
+ return {
62077
+ ok: true,
62078
+ effects: [{ type: "selected_choice", controlId: ctl.id }],
62079
+ controlResult: {
62080
+ ok: true,
62081
+ ...selected ? { currentValue: selected.label } : {},
62082
+ selectedIndex: index
62083
+ }
62084
+ };
62085
+ }
62086
+ /** Poll the live screen until the picker's `wait_for` condition matches,
62087
+ * up to a short budget. Returns true if it rendered, false on timeout. */
62088
+ async waitForPickerRendered(action) {
62089
+ const wf = action.wait_for;
62090
+ if (!wf?.regex) {
62091
+ await delay(250);
62092
+ return true;
62093
+ }
62094
+ const re = new RegExp(wf.regex, wf.flags ?? "i");
62095
+ const deadline = Date.now() + 2500;
62096
+ while (Date.now() < deadline) {
62097
+ await delay(120);
62098
+ const hay = this.readScreenSectionText(wf.section);
62099
+ if (re.test(hay)) return true;
62100
+ }
62101
+ return false;
62102
+ }
62103
+ /** Parse the picker's `extract_choices` pattern against the live screen.
62104
+ * Each match yields { index, label, current }. `current` is true for the
62105
+ * line the CLI marks with its cursor glyph (❯ ›). Purely screen-driven —
62106
+ * no model/mode names are baked in. */
62107
+ extractPickerChoices(action) {
62108
+ const ec = action.extract_choices;
62109
+ if (!ec?.pattern) return [];
62110
+ const text = this.readScreenSectionText(ec.section);
62111
+ const out = [];
62112
+ const seen = /* @__PURE__ */ new Set();
62113
+ for (const rawLine of text.split("\n")) {
62114
+ const line = rawLine.replace(/\r$/, "");
62115
+ const m = new RegExp(ec.pattern, ec.flags ?? "").exec(line);
62116
+ if (!m) continue;
62117
+ const idx = Number(m[1]);
62118
+ if (!Number.isFinite(idx) || seen.has(idx)) continue;
62119
+ const label = (m[2] ?? "").replace(/\s+/g, " ").trim();
62120
+ if (!label) continue;
62121
+ const current = /^\s*[❯›>]/.test(line) || /[✔✓●]\s*$/.test(label);
62122
+ seen.add(idx);
62123
+ out.push({ index: idx, label, current });
62124
+ }
62125
+ return out;
62126
+ }
62127
+ /** Live text of a named screen section (or the whole screen when no
62128
+ * section is named), resolved from the driver's current sections. */
62129
+ readScreenSectionText(sectionId) {
62130
+ try {
62131
+ const sections = this.driver.getSections();
62132
+ if (sectionId && sections) {
62133
+ const hit = sections.find((s) => s.id === sectionId);
62134
+ if (hit) return hit.text;
62135
+ }
62136
+ return this.driver.getScreen();
62137
+ } catch {
62138
+ return "";
62139
+ }
61734
62140
  }
61735
62141
  getDebugSnapshot() {
61736
62142
  let screen = "";
@@ -68643,7 +69049,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
68643
69049
  }
68644
69050
  if (providerDir) {
68645
69051
  try {
68646
- const fs30 = require("fs");
69052
+ const fs31 = require("fs");
68647
69053
  const path41 = require("path");
68648
69054
  const candidates = [];
68649
69055
  if (Array.isArray(base.compatibility)) {
@@ -68655,13 +69061,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
68655
69061
  }
68656
69062
  candidates.push(path41.join(providerDir, "specs", "default.json"));
68657
69063
  candidates.push(path41.join(providerDir, "spec.json"));
68658
- const specPath = candidates.find((p) => fs30.existsSync(p));
69064
+ const specPath = candidates.find((p) => fs31.existsSync(p));
68659
69065
  if (specPath) {
68660
69066
  resolved._resolvedSpecPath = specPath;
68661
69067
  let specControls;
68662
69068
  let nh;
68663
69069
  try {
68664
- const rawSpec = JSON.parse(fs30.readFileSync(specPath, "utf8"));
69070
+ const rawSpec = JSON.parse(fs31.readFileSync(specPath, "utf8"));
68665
69071
  specControls = rawSpec.control_bar;
68666
69072
  nh = rawSpec.native_history;
68667
69073
  } catch {
@@ -68686,7 +69092,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
68686
69092
  reader = (input) => executeNativeHistory(nh, input);
68687
69093
  } else if (nh.override_path) {
68688
69094
  const overrideFile = path41.resolve(providerDir, nh.override_path);
68689
- if (fs30.existsSync(overrideFile)) {
69095
+ if (fs31.existsSync(overrideFile)) {
68690
69096
  try {
68691
69097
  registerProviderScriptRootSafely(path41.dirname(path41.dirname(providerDir)));
68692
69098
  delete require.cache[require.resolve(overrideFile)];
@@ -69867,7 +70273,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
69867
70273
  }
69868
70274
  } else if (plat === "win32") {
69869
70275
  try {
69870
- const fs30 = require("fs");
70276
+ const fs31 = require("fs");
69871
70277
  const appNameMap = getMacAppIdentifiers();
69872
70278
  const appName = appNameMap[ideId];
69873
70279
  if (appName) {
@@ -69876,8 +70282,8 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
69876
70282
  appName,
69877
70283
  "storage.json"
69878
70284
  );
69879
- if (fs30.existsSync(storagePath)) {
69880
- const data = JSON.parse(fs30.readFileSync(storagePath, "utf-8"));
70285
+ if (fs31.existsSync(storagePath)) {
70286
+ const data = JSON.parse(fs31.readFileSync(storagePath, "utf-8"));
69881
70287
  const workspaces = data?.openedPathsList?.workspaces3 || data?.openedPathsList?.entries || [];
69882
70288
  if (workspaces.length > 0) {
69883
70289
  const recent = workspaces[0];
@@ -70203,6 +70609,204 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
70203
70609
  cleanOldFiles();
70204
70610
  var yaml3 = __toESM2(require_js_yaml());
70205
70611
  init_logger();
70612
+ var fs23 = __toESM2(require("fs"));
70613
+ init_logger();
70614
+ var DEFAULT_TAIL_BYTES = 64 * 1024;
70615
+ var MAX_TAIL_BYTES = 128 * 1024;
70616
+ var READ_CHUNK_BYTES = 64 * 1024;
70617
+ function resolveLogPath(date5) {
70618
+ if (date5 instanceof Date) return getCurrentDaemonLogPath(date5);
70619
+ if (typeof date5 === "string" && date5.trim()) {
70620
+ const parsed = /* @__PURE__ */ new Date(`${date5.trim()}T00:00:00.000Z`);
70621
+ if (!Number.isNaN(parsed.getTime())) return getCurrentDaemonLogPath(parsed);
70622
+ }
70623
+ return getCurrentDaemonLogPath();
70624
+ }
70625
+ function clampTailBytes(tailBytes) {
70626
+ if (!Number.isFinite(tailBytes) || tailBytes <= 0) return DEFAULT_TAIL_BYTES;
70627
+ return Math.min(Math.floor(tailBytes), MAX_TAIL_BYTES);
70628
+ }
70629
+ function readByteBoundedTail(filePath, limitBytes) {
70630
+ const fd = fs23.openSync(filePath, "r");
70631
+ try {
70632
+ const stat2 = fs23.fstatSync(fd);
70633
+ const size = stat2.size;
70634
+ if (size === 0) return { text: "", truncated: false, bytesReturned: 0 };
70635
+ const want = Math.min(limitBytes, size);
70636
+ let start = size - want;
70637
+ const truncated = start > 0;
70638
+ const buffers = [];
70639
+ let position = start;
70640
+ while (position < size) {
70641
+ const chunkSize = Math.min(READ_CHUNK_BYTES, size - position);
70642
+ const chunk = Buffer.alloc(chunkSize);
70643
+ fs23.readSync(fd, chunk, 0, chunkSize, position);
70644
+ buffers.push(chunk);
70645
+ position += chunkSize;
70646
+ }
70647
+ let buf = Buffer.concat(buffers);
70648
+ if (truncated) {
70649
+ const firstNewline = buf.indexOf(10);
70650
+ if (firstNewline >= 0) {
70651
+ buf = buf.subarray(firstNewline + 1);
70652
+ }
70653
+ }
70654
+ return { text: buf.toString("utf-8"), truncated, bytesReturned: buf.length };
70655
+ } finally {
70656
+ fs23.closeSync(fd);
70657
+ }
70658
+ }
70659
+ function parseLineEpochMs(line, fileDate) {
70660
+ const m = line.match(/^\[(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,3}))?\]/);
70661
+ if (!m) {
70662
+ const iso = line.match(/\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:\.\d+)?/);
70663
+ if (iso) {
70664
+ const t = Date.parse(iso[0].replace(" ", "T"));
70665
+ return Number.isNaN(t) ? null : t;
70666
+ }
70667
+ return null;
70668
+ }
70669
+ const d = new Date(fileDate);
70670
+ d.setHours(Number(m[1]), Number(m[2]), Number(m[3]), m[4] ? Number(m[4].padEnd(3, "0")) : 0);
70671
+ return d.getTime();
70672
+ }
70673
+ function readDaemonLogTail(args = {}) {
70674
+ const platform10 = process.platform;
70675
+ const limitBytes = clampTailBytes(args.tailBytes);
70676
+ let logPath = resolveLogPath(args.date);
70677
+ if (!fs23.existsSync(logPath)) {
70678
+ const backup = logPath.replace(/\.log$/, ".1.log");
70679
+ if (fs23.existsSync(backup)) {
70680
+ logPath = backup;
70681
+ } else {
70682
+ return {
70683
+ success: false,
70684
+ error: `No daemon log file at ${logPath} (dir: ${getDaemonLogDir()})`,
70685
+ lines: [],
70686
+ truncated: false,
70687
+ logPath,
70688
+ platform: platform10,
70689
+ bytesReturned: 0,
70690
+ filtered: false
70691
+ };
70692
+ }
70693
+ }
70694
+ let raw;
70695
+ try {
70696
+ raw = readByteBoundedTail(logPath, limitBytes);
70697
+ } catch (e) {
70698
+ return {
70699
+ success: false,
70700
+ error: `Failed to read ${logPath}: ${e?.message ?? String(e)}`,
70701
+ lines: [],
70702
+ truncated: false,
70703
+ logPath,
70704
+ platform: platform10,
70705
+ bytesReturned: 0,
70706
+ filtered: false
70707
+ };
70708
+ }
70709
+ let lines = raw.text.split("\n");
70710
+ if (lines.length && lines[lines.length - 1] === "") lines.pop();
70711
+ const rawCount = lines.length;
70712
+ if (Number.isFinite(args.sinceMs)) {
70713
+ const fileDate = args.date instanceof Date ? args.date : typeof args.date === "string" && args.date.trim() ? /* @__PURE__ */ new Date(`${args.date.trim()}T00:00:00.000Z`) : /* @__PURE__ */ new Date();
70714
+ const floor = args.sinceMs;
70715
+ lines = lines.filter((line) => {
70716
+ const ts2 = parseLineEpochMs(line, fileDate);
70717
+ return ts2 === null || ts2 >= floor;
70718
+ });
70719
+ }
70720
+ let appliedGrep;
70721
+ if (typeof args.grep === "string" && args.grep.trim()) {
70722
+ appliedGrep = args.grep.trim();
70723
+ let re = null;
70724
+ try {
70725
+ re = new RegExp(appliedGrep, "i");
70726
+ } catch {
70727
+ re = null;
70728
+ }
70729
+ if (re) {
70730
+ const compiled = re;
70731
+ lines = lines.filter((line) => compiled.test(line));
70732
+ } else {
70733
+ const needle = appliedGrep.toLowerCase();
70734
+ lines = lines.filter((line) => line.toLowerCase().includes(needle));
70735
+ }
70736
+ }
70737
+ return {
70738
+ success: true,
70739
+ lines,
70740
+ truncated: raw.truncated,
70741
+ logPath,
70742
+ platform: platform10,
70743
+ bytesReturned: raw.bytesReturned,
70744
+ filtered: lines.length !== rawCount,
70745
+ ...appliedGrep ? { grep: appliedGrep } : {}
70746
+ };
70747
+ }
70748
+ var MASK = "\u2022\u2022\u2022\u2022redacted";
70749
+ function maskKeepTail(token) {
70750
+ if (token.length <= 8) return MASK;
70751
+ return `${MASK}${token.slice(-4)}`;
70752
+ }
70753
+ var RULES = [
70754
+ // `JWT_SECRET=...`, `TOKEN=...`, `API_KEY=...`, `password: ...` env/config dumps.
70755
+ // Captures the key + delimiter and masks only the value.
70756
+ {
70757
+ name: "key_value_secret",
70758
+ pattern: /\b([A-Z0-9_]*(?:SECRET|TOKEN|API[_-]?KEY|PASSWORD|PASSWD|PRIVATE[_-]?KEY|CREDENTIAL|CLIENT[_-]?SECRET)[A-Z0-9_]*)(\s*[:=]\s*)(["']?)([^\s"',;]+)\3/gi,
70759
+ replace: (_m, key, delim, quote) => `${key}${delim}${quote}${MASK}${quote}`
70760
+ },
70761
+ // Authorization: Bearer <token>
70762
+ {
70763
+ name: "bearer_token",
70764
+ pattern: /\b(Bearer\s+)([A-Za-z0-9._\-+/=]{8,})/g,
70765
+ replace: (_m, prefix, token) => `${prefix}${maskKeepTail(token)}`
70766
+ },
70767
+ // ADHDev credential prefixes: API key (adk_), machine secret (adm_), provider key (adp_).
70768
+ {
70769
+ name: "adhdev_prefixed_secret",
70770
+ pattern: /\b(ad[kmp]_)([A-Za-z0-9]{6,})/g,
70771
+ replace: (_m, prefix, token) => `${prefix}${maskKeepTail(prefix + token)}`
70772
+ },
70773
+ // JWT: three base64url segments separated by dots, header starts with eyJ.
70774
+ {
70775
+ name: "jwt",
70776
+ pattern: /\beyJ[A-Za-z0-9_-]{4,}\.[A-Za-z0-9_-]{4,}\.[A-Za-z0-9_-]{4,}/g,
70777
+ replace: () => MASK
70778
+ },
70779
+ // TURN credential: a long credential value following a `credential` key in
70780
+ // any common shape — `credential: x`, `credential=x`, or `credential "x"`.
70781
+ // Mask the credential value only, preserving the key + delimiter/quote.
70782
+ {
70783
+ name: "turn_credential",
70784
+ pattern: /\b(credential["']?\s*(?:[:=]\s*)?["']?)([^\s"',;]{6,})/gi,
70785
+ replace: (_m, prefix) => `${prefix}${MASK}`
70786
+ },
70787
+ // TURN REST username:credential of the form `<expiry-ts>:<base64hmac>`,
70788
+ // where the hmac part is long base64. Mask the hmac.
70789
+ {
70790
+ name: "turn_rest_pair",
70791
+ pattern: /\b(\d{10,}:)([A-Za-z0-9+/]{20,}={0,2})\b/g,
70792
+ replace: (_m, prefix) => `${prefix}${MASK}`
70793
+ }
70794
+ ];
70795
+ function redactLogLine(line) {
70796
+ if (!line) return line;
70797
+ let out = line;
70798
+ for (const rule of RULES) {
70799
+ try {
70800
+ out = out.replace(rule.pattern, rule.replace);
70801
+ } catch {
70802
+ }
70803
+ }
70804
+ return out;
70805
+ }
70806
+ function redactLogLines(lines) {
70807
+ return lines.map((line) => redactLogLine(line));
70808
+ }
70809
+ var LOG_REDACTION_RULE_NAMES = RULES.map((r) => r.name);
70206
70810
  init_mesh_coordinator();
70207
70811
  init_mesh_events();
70208
70812
  init_mesh_routing();
@@ -70833,21 +71437,21 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
70833
71437
  init_build_info();
70834
71438
  var import_child_process8 = require("child_process");
70835
71439
  var import_child_process9 = require("child_process");
70836
- var fs23 = __toESM2(require("fs"));
71440
+ var fs24 = __toESM2(require("fs"));
70837
71441
  var os27 = __toESM2(require("os"));
70838
71442
  var path35 = __toESM2(require("path"));
70839
71443
  var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
70840
71444
  function getUpgradeLogPath() {
70841
71445
  const home = os27.homedir();
70842
71446
  const dir = path35.join(home, ".adhdev");
70843
- fs23.mkdirSync(dir, { recursive: true });
71447
+ fs24.mkdirSync(dir, { recursive: true });
70844
71448
  return path35.join(dir, "daemon-upgrade.log");
70845
71449
  }
70846
71450
  function appendUpgradeLog(message) {
70847
71451
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
70848
71452
  `;
70849
71453
  try {
70850
- fs23.appendFileSync(getUpgradeLogPath(), line, "utf8");
71454
+ fs24.appendFileSync(getUpgradeLogPath(), line, "utf8");
70851
71455
  } catch {
70852
71456
  }
70853
71457
  }
@@ -70855,12 +71459,12 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
70855
71459
  const binDir = path35.dirname(nodeExecutable);
70856
71460
  if (platform10 === "win32") {
70857
71461
  const npmCliPath = path35.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
70858
- if (fs23.existsSync(npmCliPath)) {
71462
+ if (fs24.existsSync(npmCliPath)) {
70859
71463
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
70860
71464
  }
70861
71465
  for (const candidate of ["npm.exe", "npm"]) {
70862
71466
  const candidatePath = path35.join(binDir, candidate);
70863
- if (fs23.existsSync(candidatePath)) {
71467
+ if (fs24.existsSync(candidatePath)) {
70864
71468
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
70865
71469
  }
70866
71470
  }
@@ -70868,7 +71472,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
70868
71472
  }
70869
71473
  for (const candidate of ["npm"]) {
70870
71474
  const candidatePath = path35.join(binDir, candidate);
70871
- if (fs23.existsSync(candidatePath)) {
71475
+ if (fs24.existsSync(candidatePath)) {
70872
71476
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
70873
71477
  }
70874
71478
  }
@@ -70878,12 +71482,12 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
70878
71482
  if (!currentCliPath) return null;
70879
71483
  let resolvedPath = currentCliPath;
70880
71484
  try {
70881
- resolvedPath = fs23.realpathSync.native(currentCliPath);
71485
+ resolvedPath = fs24.realpathSync.native(currentCliPath);
70882
71486
  } catch {
70883
71487
  }
70884
71488
  let currentDir = resolvedPath;
70885
71489
  try {
70886
- if (fs23.statSync(resolvedPath).isFile()) {
71490
+ if (fs24.statSync(resolvedPath).isFile()) {
70887
71491
  currentDir = path35.dirname(resolvedPath);
70888
71492
  }
70889
71493
  } catch {
@@ -70892,8 +71496,8 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
70892
71496
  while (true) {
70893
71497
  const packageJsonPath = path35.join(currentDir, "package.json");
70894
71498
  try {
70895
- if (fs23.existsSync(packageJsonPath)) {
70896
- const parsed = JSON.parse(fs23.readFileSync(packageJsonPath, "utf8"));
71499
+ if (fs24.existsSync(packageJsonPath)) {
71500
+ const parsed = JSON.parse(fs24.readFileSync(packageJsonPath, "utf8"));
70897
71501
  if (parsed?.name === packageName) {
70898
71502
  const normalized = currentDir.replace(/\\/g, "/");
70899
71503
  return normalized.includes("/node_modules/") ? currentDir : null;
@@ -71042,8 +71646,8 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
71042
71646
  function stopSessionHostProcesses(appName) {
71043
71647
  const pidFile = path35.join(os27.homedir(), ".adhdev", `${appName}-session-host.pid`);
71044
71648
  try {
71045
- if (fs23.existsSync(pidFile)) {
71046
- const pid = Number.parseInt(fs23.readFileSync(pidFile, "utf8").trim(), 10);
71649
+ if (fs24.existsSync(pidFile)) {
71650
+ const pid = Number.parseInt(fs24.readFileSync(pidFile, "utf8").trim(), 10);
71047
71651
  if (Number.isFinite(pid) && pid !== process.pid && isManagedSessionHostPid(pid)) {
71048
71652
  killPid2(pid);
71049
71653
  }
@@ -71051,7 +71655,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
71051
71655
  } catch {
71052
71656
  } finally {
71053
71657
  try {
71054
- fs23.unlinkSync(pidFile);
71658
+ fs24.unlinkSync(pidFile);
71055
71659
  } catch {
71056
71660
  }
71057
71661
  }
@@ -71059,7 +71663,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
71059
71663
  function removeDaemonPidFile() {
71060
71664
  const pidFile = path35.join(os27.homedir(), ".adhdev", "daemon.pid");
71061
71665
  try {
71062
- fs23.unlinkSync(pidFile);
71666
+ fs24.unlinkSync(pidFile);
71063
71667
  } catch {
71064
71668
  }
71065
71669
  }
@@ -71077,23 +71681,23 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
71077
71681
  if (pkgName.startsWith("@")) {
71078
71682
  const [scope, name] = pkgName.split("/");
71079
71683
  const scopeDir = path35.join(npmRoot, scope);
71080
- if (!fs23.existsSync(scopeDir)) return;
71081
- for (const entry of fs23.readdirSync(scopeDir)) {
71684
+ if (!fs24.existsSync(scopeDir)) return;
71685
+ for (const entry of fs24.readdirSync(scopeDir)) {
71082
71686
  if (!entry.startsWith(`.${name}-`)) continue;
71083
- fs23.rmSync(path35.join(scopeDir, entry), { recursive: true, force: true });
71687
+ fs24.rmSync(path35.join(scopeDir, entry), { recursive: true, force: true });
71084
71688
  appendUpgradeLog(`Removed stale scoped staging dir: ${path35.join(scopeDir, entry)}`);
71085
71689
  }
71086
71690
  } else {
71087
- for (const entry of fs23.readdirSync(npmRoot)) {
71691
+ for (const entry of fs24.readdirSync(npmRoot)) {
71088
71692
  if (!entry.startsWith(`.${pkgName}-`)) continue;
71089
- fs23.rmSync(path35.join(npmRoot, entry), { recursive: true, force: true });
71693
+ fs24.rmSync(path35.join(npmRoot, entry), { recursive: true, force: true });
71090
71694
  appendUpgradeLog(`Removed stale staging dir: ${path35.join(npmRoot, entry)}`);
71091
71695
  }
71092
71696
  }
71093
- if (fs23.existsSync(binDir)) {
71094
- for (const entry of fs23.readdirSync(binDir)) {
71697
+ if (fs24.existsSync(binDir)) {
71698
+ for (const entry of fs24.readdirSync(binDir)) {
71095
71699
  if (!Array.from(binNames).some((name) => entry.startsWith(`.${name}-`))) continue;
71096
- fs23.rmSync(path35.join(binDir, entry), { recursive: true, force: true });
71700
+ fs24.rmSync(path35.join(binDir, entry), { recursive: true, force: true });
71097
71701
  appendUpgradeLog(`Removed stale bin staging entry: ${path35.join(binDir, entry)}`);
71098
71702
  }
71099
71703
  }
@@ -71182,7 +71786,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
71182
71786
  init_repo_mesh_types();
71183
71787
  var import_os3 = require("os");
71184
71788
  var import_path11 = require("path");
71185
- var fs24 = __toESM2(require("fs"));
71789
+ var fs25 = __toESM2(require("fs"));
71186
71790
  var import_node_child_process6 = require("child_process");
71187
71791
  var CHANNEL_NPM_TAG = { stable: "latest", preview: "next" };
71188
71792
  var CHANNEL_SERVER_URL = {
@@ -71508,6 +72112,12 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
71508
72112
  function readInlineMeshNodeId(node) {
71509
72113
  return normalizeMeshNodeId(node) ?? "";
71510
72114
  }
72115
+ function isDeadLocalWorktreeNode(node) {
72116
+ if (node?.isLocalWorktree !== true) return false;
72117
+ const workspace = readStringValue(node?.workspace);
72118
+ if (!workspace) return false;
72119
+ return !fs25.existsSync(workspace);
72120
+ }
71511
72121
  function foldMeshNodeIdentityToCanonical(node) {
71512
72122
  if (!node || typeof node !== "object" || Array.isArray(node)) return node;
71513
72123
  const canonical = normalizeMeshNodeId(node);
@@ -71754,7 +72364,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
71754
72364
  const followUps = nodes.filter((node) => {
71755
72365
  if (readObjectRecord(node.branchConvergence).needsConvergence !== true) return false;
71756
72366
  const workspace = typeof node.workspace === "string" ? node.workspace : "";
71757
- if (workspace && !fs24.existsSync(workspace)) return false;
72367
+ if (workspace && !fs25.existsSync(workspace)) return false;
71758
72368
  return true;
71759
72369
  }).map((node) => {
71760
72370
  const convergence = readObjectRecord(node.branchConvergence);
@@ -71882,6 +72492,43 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
71882
72492
  }
71883
72493
  var MESH_DIRECT_PROBE_TIMEOUT_MS = readMeshTimeoutEnvMs("MESH_DIRECT_PROBE_TIMEOUT_MS", 25e3);
71884
72494
  var MESH_DIRECT_PROBE_RETRY_TIMEOUT_MS = readMeshTimeoutEnvMs("MESH_DIRECT_PROBE_RETRY_TIMEOUT_MS", 25e3);
72495
+ var MESH_DIRECT_PROBE_REUSE_MS = readMeshTimeoutEnvMs("MESH_DIRECT_PROBE_REUSE_MS", 12e3);
72496
+ var MeshGitProbeCache = class {
72497
+ constructor(reuseMs, now = Date.now) {
72498
+ this.reuseMs = reuseMs;
72499
+ this.now = now;
72500
+ }
72501
+ inflight = /* @__PURE__ */ new Map();
72502
+ recent = /* @__PURE__ */ new Map();
72503
+ key(daemonId, workspace) {
72504
+ return `${daemonId}::${workspace}`;
72505
+ }
72506
+ /**
72507
+ * Run `probe` for this peer, but reuse a fresh recent result or an in-flight
72508
+ * probe for the same key when one is available. `probe` is only invoked when
72509
+ * neither gate is satisfied.
72510
+ */
72511
+ async probe(daemonId, workspace, probe) {
72512
+ const key = this.key(daemonId, workspace);
72513
+ const cached22 = this.recent.get(key);
72514
+ if (cached22 && this.now() - cached22.at < this.reuseMs) {
72515
+ return cached22.value;
72516
+ }
72517
+ const existing = this.inflight.get(key);
72518
+ if (existing) return existing;
72519
+ const pending = (async () => {
72520
+ const result = await probe();
72521
+ if (result) this.recent.set(key, { at: this.now(), value: result });
72522
+ return result;
72523
+ })();
72524
+ this.inflight.set(key, pending);
72525
+ try {
72526
+ return await pending;
72527
+ } finally {
72528
+ if (this.inflight.get(key) === pending) this.inflight.delete(key);
72529
+ }
72530
+ }
72531
+ };
71885
72532
  async function probeRemoteMeshGitStatus(args) {
71886
72533
  if (!args.dispatchMeshCommand) return null;
71887
72534
  const remoteResult = await Promise.race([
@@ -71925,7 +72572,8 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
71925
72572
  peerAttemptedCount: 0,
71926
72573
  peerConfirmedCount: 0,
71927
72574
  standingEvidenceCount: 0,
71928
- unavailableNodeIds: []
72575
+ unavailableNodeIds: [],
72576
+ deadNodeIds: []
71929
72577
  };
71930
72578
  }
71931
72579
  const selectedCoordinatorNodeId = readStringValue(
@@ -71938,6 +72586,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
71938
72586
  let peerConfirmedCount = 0;
71939
72587
  let standingEvidenceCount = 0;
71940
72588
  const unavailableNodeIds = [];
72589
+ const deadNodeIds = [];
71941
72590
  for (const [nodeIndex, node] of nodes.entries()) {
71942
72591
  const nodeId = normalizeMeshNodeId(node) || `node_${nodeIndex}`;
71943
72592
  const workspace = readStringValue(node?.workspace);
@@ -71947,11 +72596,18 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
71947
72596
  ) || Boolean(
71948
72597
  daemonId && (daemonId === args.localMachineId || daemonId === args.statusInstanceId)
71949
72598
  ) || Boolean(args.meshSource !== "local_config" && nodeIndex === 0);
72599
+ const isSelfDaemonNode = Boolean(
72600
+ daemonId && (daemonId === args.localMachineId || daemonId === args.statusInstanceId)
72601
+ );
72602
+ if ((isSelfNode || isSelfDaemonNode) && isDeadLocalWorktreeNode(node)) {
72603
+ deadNodeIds.push(nodeId);
72604
+ continue;
72605
+ }
71950
72606
  if (!workspace) {
71951
72607
  if (!isSelfNode && daemonId) unavailableNodeIds.push(nodeId);
71952
72608
  continue;
71953
72609
  }
71954
- if (fs24.existsSync(workspace)) {
72610
+ if (fs25.existsSync(workspace)) {
71955
72611
  try {
71956
72612
  const localGit = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
71957
72613
  if (localGit?.isGitRepo) {
@@ -71975,7 +72631,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
71975
72631
  continue;
71976
72632
  }
71977
72633
  peerAttemptedCount += 1;
71978
- const remoteGit = await probeRemoteMeshGitStatusWithRetry({
72634
+ const runProbe = () => probeRemoteMeshGitStatusWithRetry({
71979
72635
  dispatchMeshCommand: args.dispatchMeshCommand,
71980
72636
  daemonId,
71981
72637
  workspace,
@@ -71983,6 +72639,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
71983
72639
  retryTimeoutMs: MESH_DIRECT_PROBE_RETRY_TIMEOUT_MS,
71984
72640
  getConnection: args.getMeshPeerConnectionStatus
71985
72641
  });
72642
+ const remoteGit = args.probeCache ? await args.probeCache.probe(daemonId, workspace, runProbe) : await runProbe();
71986
72643
  if (remoteGit) {
71987
72644
  recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
71988
72645
  peerConfirmedCount += 1;
@@ -71996,7 +72653,8 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
71996
72653
  peerAttemptedCount,
71997
72654
  peerConfirmedCount,
71998
72655
  standingEvidenceCount,
71999
- unavailableNodeIds
72656
+ unavailableNodeIds,
72657
+ deadNodeIds
72000
72658
  };
72001
72659
  }
72002
72660
  function summarizeMeshSessionRecord(record2) {
@@ -72055,7 +72713,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
72055
72713
  }
72056
72714
  function collectLiveMeshSessionRecords(args) {
72057
72715
  const nodeWorkspace = readStringValue(args.node?.workspace);
72058
- const nodeIsMissingLocalWorktree = args.node?.isLocalWorktree === true && !!nodeWorkspace && !fs24.existsSync(nodeWorkspace);
72716
+ const nodeIsMissingLocalWorktree = args.node?.isLocalWorktree === true && !!nodeWorkspace && !fs25.existsSync(nodeWorkspace);
72059
72717
  const matches = args.liveSessionRecords.filter((record2) => {
72060
72718
  const recordNodeId = readStringValue(record2?.meta?.meshNodeId);
72061
72719
  if (recordNodeId && recordNodeId !== args.nodeId) return false;
@@ -72082,7 +72740,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
72082
72740
  const workspace = readStringValue(node?.workspace);
72083
72741
  if (nodeId) liveNodeIds.add(nodeId);
72084
72742
  if (workspace) liveWorkspaces.add(workspace);
72085
- if (nodeId && node?.isLocalWorktree === true && workspace && !fs24.existsSync(workspace)) {
72743
+ if (nodeId && node?.isLocalWorktree === true && workspace && !fs25.existsSync(workspace)) {
72086
72744
  missingLocalWorktreeNodeIds.add(nodeId);
72087
72745
  }
72088
72746
  }
@@ -72442,7 +73100,7 @@ ${e?.stderr || ""}`
72442
73100
  if (!baseCommit || !branchCommit) return false;
72443
73101
  if (baseCommit === branchCommit) return true;
72444
73102
  try {
72445
- if (!fs24.existsSync(submoduleRepoPath)) return false;
73103
+ if (!fs25.existsSync(submoduleRepoPath)) return false;
72446
73104
  (0, import_node_child_process6.execFileSync)("git", ["cat-file", "-e", `${baseCommit}^{commit}`], { cwd: submoduleRepoPath, stdio: "ignore" });
72447
73105
  (0, import_node_child_process6.execFileSync)("git", ["cat-file", "-e", `${branchCommit}^{commit}`], { cwd: submoduleRepoPath, stdio: "ignore" });
72448
73106
  (0, import_node_child_process6.execFileSync)("git", ["merge-base", "--is-ancestor", baseCommit, branchCommit], { cwd: submoduleRepoPath, stdio: "ignore" });
@@ -72559,7 +73217,7 @@ ${e?.stderr || ""}`
72559
73217
  return newTree || void 0;
72560
73218
  } finally {
72561
73219
  try {
72562
- fs24.rmSync(tmpIndex, { force: true });
73220
+ fs25.rmSync(tmpIndex, { force: true });
72563
73221
  } catch {
72564
73222
  }
72565
73223
  }
@@ -72634,7 +73292,7 @@ ${e?.stderr || ""}`
72634
73292
  return newTree || void 0;
72635
73293
  } finally {
72636
73294
  try {
72637
- fs24.rmSync(tmpIndex, { force: true });
73295
+ fs25.rmSync(tmpIndex, { force: true });
72638
73296
  } catch {
72639
73297
  }
72640
73298
  }
@@ -72740,7 +73398,7 @@ ${e?.stderr || ""}`
72740
73398
  return { stdout: String(stdout || ""), stderr: String(stderr || ""), refspec };
72741
73399
  };
72742
73400
  const importCommitFromWorktreeSubmodule = async (submodulePath, worktreeSubmodulePath, commit) => {
72743
- if (!fs24.existsSync(worktreeSubmodulePath)) return false;
73401
+ if (!fs25.existsSync(worktreeSubmodulePath)) return false;
72744
73402
  try {
72745
73403
  await runGit3(worktreeSubmodulePath, ["cat-file", "-e", `${commit}^{commit}`]);
72746
73404
  } catch {
@@ -72763,7 +73421,7 @@ ${e?.stderr || ""}`
72763
73421
  reachable: false
72764
73422
  };
72765
73423
  try {
72766
- if (!fs24.existsSync(submodulePath)) {
73424
+ if (!fs25.existsSync(submodulePath)) {
72767
73425
  entry.error = `Submodule checkout missing at ${gitlink.path}`;
72768
73426
  entry.publishRequired = true;
72769
73427
  if (options.allowAutoPublishSubmoduleMainCommits === true) {
@@ -73000,9 +73658,9 @@ ${e?.stderr || ""}`
73000
73658
  return ["npm", "pnpm", "yarn", "bun"].includes(command) && candidate.args.some((arg) => arg === "run" || arg === "test" || arg === "exec");
73001
73659
  };
73002
73660
  const dependenciesLikelyMissing = (cwd) => {
73003
- if (!fs24.existsSync((0, import_path11.join)(cwd, "package.json"))) return false;
73004
- if (fs24.existsSync((0, import_path11.join)(cwd, "node_modules"))) return false;
73005
- return ["package-lock.json", "npm-shrinkwrap.json", "pnpm-lock.yaml", "yarn.lock", "bun.lockb", "bun.lock"].some((lock) => fs24.existsSync((0, import_path11.join)(cwd, lock)));
73661
+ if (!fs25.existsSync((0, import_path11.join)(cwd, "package.json"))) return false;
73662
+ if (fs25.existsSync((0, import_path11.join)(cwd, "node_modules"))) return false;
73663
+ return ["package-lock.json", "npm-shrinkwrap.json", "pnpm-lock.yaml", "yarn.lock", "bun.lockb", "bun.lock"].some((lock) => fs25.existsSync((0, import_path11.join)(cwd, lock)));
73006
73664
  };
73007
73665
  if (runLegacyBootstrapCommands) {
73008
73666
  summary.bootstrap = { stage: "legacy" };
@@ -73104,9 +73762,9 @@ ${e?.stderr || ""}`
73104
73762
  function loadHermesCoordinatorBaseConfig(targetConfigPath) {
73105
73763
  const sourceHome = resolveHermesUserHome();
73106
73764
  const sourceConfigPath = (0, import_path11.join)(sourceHome, "config.yaml");
73107
- if (!fs24.existsSync(sourceConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
73765
+ if (!fs25.existsSync(sourceConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
73108
73766
  if ((0, import_path11.resolve)(sourceConfigPath) === (0, import_path11.resolve)(targetConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
73109
- const parsed = parseMeshCoordinatorMcpConfig(fs24.readFileSync(sourceConfigPath, "utf-8"), "hermes_config_yaml");
73767
+ const parsed = parseMeshCoordinatorMcpConfig(fs25.readFileSync(sourceConfigPath, "utf-8"), "hermes_config_yaml");
73110
73768
  const { mcp_servers: _mcpServers, ...baseConfig } = parsed;
73111
73769
  return { config: baseConfig, sourceHome, sourceConfigPath };
73112
73770
  }
@@ -73143,9 +73801,9 @@ ${e?.stderr || ""}`
73143
73801
  for (const fileName of [".env", "auth.json"]) {
73144
73802
  const sourcePath = (0, import_path11.join)(sourceHome, fileName);
73145
73803
  const targetPath = (0, import_path11.join)(targetHome, fileName);
73146
- if (!fs24.existsSync(sourcePath)) continue;
73804
+ if (!fs25.existsSync(sourcePath)) continue;
73147
73805
  try {
73148
- fs24.copyFileSync(sourcePath, targetPath);
73806
+ fs25.copyFileSync(sourcePath, targetPath);
73149
73807
  } catch (error48) {
73150
73808
  LOG2.warn("MeshCoordinator", `Could not copy Hermes ${fileName} into isolated coordinator home: ${error48?.message || error48}`);
73151
73809
  }
@@ -73303,8 +73961,21 @@ ${e?.stderr || ""}`
73303
73961
  * Allows the MCP server to query mesh data via get_mesh even when
73304
73962
  * the mesh doesn't exist in the local meshes.json file. */
73305
73963
  inlineMeshCache = /* @__PURE__ */ new Map();
73964
+ /** Tombstones for inline mesh nodes removed via remove_mesh_node, keyed by
73965
+ * meshId → set of removed nodeIds. The dashboard keeps echoing the removed
73966
+ * node in the inlineMesh it attaches to every command; without a tombstone,
73967
+ * reconcileInlineMeshCache MERGEs it straight back (resurrection). A
73968
+ * tombstoned node is skipped during reconcile only while its workspace is
73969
+ * absent from disk — a genuine re-registration (same nodeId, workspace back
73970
+ * on disk) clears the tombstone and merges normally, preserving clone
73971
+ * worktree visibility and legitimate node re-creation. */
73972
+ removedInlineMeshNodeIds = /* @__PURE__ */ new Map();
73306
73973
  /** Coordinator-owned whole-mesh aggregate status snapshots. Browser callers read this by default. */
73307
73974
  aggregateMeshStatusCache = /* @__PURE__ */ new Map();
73975
+ /** Shared per-peer git_status probe dedup + recently-probed reuse gate.
73976
+ * Spans separate mesh_status/get_mesh calls so the dashboard auto-retry
73977
+ * loop cannot storm a slow peer with back-to-back refreshUpstream probes. */
73978
+ meshGitProbeCache = new MeshGitProbeCache(MESH_DIRECT_PROBE_REUSE_MS);
73308
73979
  /** In-memory async Refinery jobs keyed by meshId:nodeId to reject/return duplicate in-flight requests. */
73309
73980
  runningRefineJobs = /* @__PURE__ */ new Map();
73310
73981
  /** Terminal async Refinery jobs preserve a clear answer after the worktree node has been removed. */
@@ -73332,10 +74003,23 @@ ${e?.stderr || ""}`
73332
74003
  const unavailableNodeIds = /* @__PURE__ */ new Set();
73333
74004
  const sourceOfTruth = readObjectRecord(snapshot.sourceOfTruth);
73334
74005
  const directPeerTruth = readObjectRecord(sourceOfTruth.directPeerTruth);
74006
+ const deadNodeIds = /* @__PURE__ */ new Set();
74007
+ for (const node of mesh.nodes) {
74008
+ if (!isDeadLocalWorktreeNode(node)) continue;
74009
+ const deadId = readInlineMeshNodeId(node);
74010
+ if (deadId) deadNodeIds.add(deadId);
74011
+ }
74012
+ let droppedDeadUnavailable = false;
73335
74013
  for (const entry of Array.isArray(directPeerTruth.unavailableNodeIds) ? directPeerTruth.unavailableNodeIds : []) {
73336
74014
  const nodeId = readStringValue(entry);
73337
- if (nodeId) unavailableNodeIds.add(nodeId);
74015
+ if (!nodeId) continue;
74016
+ if (deadNodeIds.has(nodeId)) {
74017
+ droppedDeadUnavailable = true;
74018
+ continue;
74019
+ }
74020
+ unavailableNodeIds.add(nodeId);
73338
74021
  }
74022
+ if (droppedDeadUnavailable) changed = true;
73339
74023
  const nodes = snapshot.nodes.map((statusNode) => {
73340
74024
  const nodeId = normalizeMeshNodeId(statusNode);
73341
74025
  const inlineNode = nodeId ? inlineNodesById.get(nodeId) : void 0;
@@ -73450,7 +74134,10 @@ ${e?.stderr || ""}`
73450
74134
  }
73451
74135
  warmInlineMeshCache(meshId, inlineMesh) {
73452
74136
  if (!inlineMesh || typeof inlineMesh !== "object") return void 0;
73453
- const sanitizedInlineMesh = sanitizeInlineMesh(normalizeInlineMeshNodeIdentity(inlineMesh));
74137
+ const sanitizedInlineMesh = this.applyInlineMeshNodeTombstones(
74138
+ meshId,
74139
+ sanitizeInlineMesh(normalizeInlineMeshNodeIdentity(inlineMesh))
74140
+ );
73454
74141
  const cached22 = this.inlineMeshCache.get(meshId);
73455
74142
  if (cached22) {
73456
74143
  const merged = reconcileInlineMeshCache(cached22, sanitizedInlineMesh);
@@ -73466,7 +74153,10 @@ ${e?.stderr || ""}`
73466
74153
  const cached3 = this.getCachedInlineMesh(meshId);
73467
74154
  if (cached3) {
73468
74155
  if (inlineMeshCarriesTransientNodeTruth(inlineMesh)) {
73469
- const merged = reconcileInlineMeshCache(cached3, inlineMesh);
74156
+ const merged = reconcileInlineMeshCache(
74157
+ cached3,
74158
+ this.applyInlineMeshNodeTombstones(meshId, inlineMesh)
74159
+ );
73470
74160
  this.inlineMeshCache.set(meshId, sanitizeInlineMesh(normalizeInlineMeshNodeIdentity(merged)));
73471
74161
  return { mesh: merged, inline: true, source: "inline_cache" };
73472
74162
  }
@@ -73517,12 +74207,49 @@ ${e?.stderr || ""}`
73517
74207
  if (!mesh || !Array.isArray(mesh.nodes)) return false;
73518
74208
  const idx = mesh.nodes.findIndex((entry) => meshNodeIdMatches(entry, nodeId));
73519
74209
  if (idx === -1) return false;
74210
+ const canonicalNodeId = readInlineMeshNodeId(mesh.nodes[idx]) || nodeId;
73520
74211
  mesh.nodes.splice(idx, 1);
73521
74212
  mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
73522
74213
  this.inlineMeshCache.set(meshId, mesh);
74214
+ this.tombstoneRemovedInlineMeshNode(meshId, canonicalNodeId);
74215
+ if (canonicalNodeId !== nodeId) this.tombstoneRemovedInlineMeshNode(meshId, nodeId);
73523
74216
  this.invalidateAggregateMeshStatus(meshId);
73524
74217
  return true;
73525
74218
  }
74219
+ tombstoneRemovedInlineMeshNode(meshId, nodeId) {
74220
+ if (!nodeId) return;
74221
+ let set2 = this.removedInlineMeshNodeIds.get(meshId);
74222
+ if (!set2) {
74223
+ set2 = /* @__PURE__ */ new Set();
74224
+ this.removedInlineMeshNodeIds.set(meshId, set2);
74225
+ }
74226
+ set2.add(nodeId);
74227
+ }
74228
+ /** Filter an incoming inline mesh against this mesh's tombstones before it is
74229
+ * reconciled into the cache. A tombstoned node is dropped only while its
74230
+ * workspace is still absent from disk; if the workspace is back (genuine
74231
+ * re-registration), the tombstone is cleared and the node merges normally. */
74232
+ applyInlineMeshNodeTombstones(meshId, incoming) {
74233
+ const tombstones = this.removedInlineMeshNodeIds.get(meshId);
74234
+ if (!tombstones?.size || !incoming || typeof incoming !== "object" || !Array.isArray(incoming.nodes)) {
74235
+ return incoming;
74236
+ }
74237
+ let dropped = false;
74238
+ const nodes = incoming.nodes.filter((node) => {
74239
+ const nodeId = readInlineMeshNodeId(node);
74240
+ if (!nodeId || !tombstones.has(nodeId)) return true;
74241
+ const workspace = readStringValue(node?.workspace);
74242
+ if (workspace && fs25.existsSync(workspace)) {
74243
+ tombstones.delete(nodeId);
74244
+ return true;
74245
+ }
74246
+ dropped = true;
74247
+ return false;
74248
+ });
74249
+ if (tombstones.size === 0) this.removedInlineMeshNodeIds.delete(meshId);
74250
+ if (!dropped) return incoming;
74251
+ return { ...incoming, nodes };
74252
+ }
73526
74253
  normalizeMeshSessionCleanupMode(value) {
73527
74254
  return value === "stop" || value === "delete_stopped" || value === "stop_and_delete" || value === "preserve" ? value : "preserve";
73528
74255
  }
@@ -73545,13 +74272,13 @@ ${e?.stderr || ""}`
73545
74272
  recoveryHint: "Inspect the mesh node record before removing it, or remove stale metadata manually only after confirming no managed worktree remains."
73546
74273
  };
73547
74274
  }
73548
- const worktreeExists = fs24.existsSync(workspace);
74275
+ const worktreeExists = fs25.existsSync(workspace);
73549
74276
  const sourceNode = args.node?.clonedFromNodeId ? args.mesh?.nodes?.find((n) => meshNodeIdMatches(n, args.node.clonedFromNodeId)) : args.mesh?.nodes?.find((n) => !n.isLocalWorktree);
73550
74277
  const repoRoot = typeof sourceNode?.repoRoot === "string" && sourceNode.repoRoot.trim() ? sourceNode.repoRoot.trim() : typeof sourceNode?.workspace === "string" && sourceNode.workspace.trim() ? sourceNode.workspace.trim() : "";
73551
74278
  if (!worktreeExists) {
73552
74279
  return { success: true, skipped: true, removedPath: workspace, repoRoot: repoRoot || void 0, reason: "worktree_path_missing" };
73553
74280
  }
73554
- if (!repoRoot || !fs24.existsSync(repoRoot)) {
74281
+ if (!repoRoot || !fs25.existsSync(repoRoot)) {
73555
74282
  return {
73556
74283
  success: false,
73557
74284
  code: "mesh_worktree_cleanup_missing_source_repo",
@@ -73571,7 +74298,7 @@ ${e?.stderr || ""}`
73571
74298
  const normalizePath = (value) => {
73572
74299
  const resolved = (0, import_path11.resolve)(value);
73573
74300
  try {
73574
- return fs24.realpathSync(resolved);
74301
+ return fs25.realpathSync(resolved);
73575
74302
  } catch {
73576
74303
  return resolved;
73577
74304
  }
@@ -73657,7 +74384,7 @@ ${e?.stderr || ""}`
73657
74384
  };
73658
74385
  } catch (deinitError) {
73659
74386
  try {
73660
- fs24.rmSync(workspace, { recursive: true, force: true });
74387
+ fs25.rmSync(workspace, { recursive: true, force: true });
73661
74388
  await execFileAsync4("git", ["worktree", "prune"], {
73662
74389
  cwd: repoRoot,
73663
74390
  encoding: "utf8",
@@ -75436,8 +76163,8 @@ ${hintLines.join("\n")}` : "",
75436
76163
  if (sinceTs > 0) {
75437
76164
  return { success: true, logs: [], totalBuffered: 0 };
75438
76165
  }
75439
- if (fs24.existsSync(LOG_PATH)) {
75440
- const content = fs24.readFileSync(LOG_PATH, "utf-8");
76166
+ if (fs25.existsSync(LOG_PATH)) {
76167
+ const content = fs25.readFileSync(LOG_PATH, "utf-8");
75441
76168
  const allLines = content.split("\n");
75442
76169
  const recent = allLines.slice(-count).join("\n");
75443
76170
  return { success: true, logs: recent, totalLines: allLines.length };
@@ -75982,14 +76709,14 @@ ${hintLines.join("\n")}` : "",
75982
76709
  // Settings page in the dashboard reads/writes via these two
75983
76710
  // commands instead of going through fs from the browser.
75984
76711
  case "list_coordinator_prompts": {
75985
- const fs30 = await import("fs");
76712
+ const fs31 = await import("fs");
75986
76713
  const path41 = await import("path");
75987
76714
  const os30 = await import("os");
75988
76715
  const dir = path41.join(os30.homedir(), ".adhdev", "coordinator-prompts");
75989
76716
  const entries = {};
75990
76717
  try {
75991
- if (fs30.existsSync(dir)) {
75992
- for (const name of fs30.readdirSync(dir)) {
76718
+ if (fs31.existsSync(dir)) {
76719
+ for (const name of fs31.readdirSync(dir)) {
75993
76720
  const matchOverride = name.match(/^([a-zA-Z0-9_.-]+)\.md$/);
75994
76721
  const matchAppend = name.match(/^([a-zA-Z0-9_.-]+)\.append\.md$/);
75995
76722
  const m = matchAppend || matchOverride;
@@ -75999,7 +76726,7 @@ ${hintLines.join("\n")}` : "",
75999
76726
  const full = path41.join(dir, name);
76000
76727
  let content = "";
76001
76728
  try {
76002
- content = fs30.readFileSync(full, "utf8");
76729
+ content = fs31.readFileSync(full, "utf8");
76003
76730
  } catch {
76004
76731
  }
76005
76732
  if (!entries[key]) entries[key] = { override: "", append: "" };
@@ -76013,7 +76740,7 @@ ${hintLines.join("\n")}` : "",
76013
76740
  return { success: true, dir, entries };
76014
76741
  }
76015
76742
  case "write_coordinator_prompt": {
76016
- const fs30 = await import("fs");
76743
+ const fs31 = await import("fs");
76017
76744
  const path41 = await import("path");
76018
76745
  const os30 = await import("os");
76019
76746
  const key = typeof args?.key === "string" ? args.key.trim() : "";
@@ -76026,11 +76753,11 @@ ${hintLines.join("\n")}` : "",
76026
76753
  const filename = kind === "append" ? `${key}.append.md` : `${key}.md`;
76027
76754
  const full = path41.join(dir, filename);
76028
76755
  try {
76029
- fs30.mkdirSync(dir, { recursive: true });
76756
+ fs31.mkdirSync(dir, { recursive: true });
76030
76757
  if (content.trim()) {
76031
- fs30.writeFileSync(full, content, { encoding: "utf8", mode: 384 });
76032
- } else if (fs30.existsSync(full)) {
76033
- fs30.unlinkSync(full);
76758
+ fs31.writeFileSync(full, content, { encoding: "utf8", mode: 384 });
76759
+ } else if (fs31.existsSync(full)) {
76760
+ fs31.unlinkSync(full);
76034
76761
  }
76035
76762
  return { success: true, path: full, kind, key };
76036
76763
  } catch (error48) {
@@ -76207,7 +76934,8 @@ ${hintLines.join("\n")}` : "",
76207
76934
  getMeshPeerConnectionStatus: this.deps.getMeshPeerConnectionStatus,
76208
76935
  statusInstanceId: this.deps.statusInstanceId,
76209
76936
  localMachineId: loadConfig2().machineId || "",
76210
- probeRemotePeers
76937
+ probeRemotePeers,
76938
+ probeCache: this.meshGitProbeCache
76211
76939
  });
76212
76940
  const directTruthSatisfied = meshRecord.source !== "inline_bootstrap" || directTruth.directEvidenceCount > 0;
76213
76941
  const sourceOfTruth = {
@@ -76807,10 +77535,75 @@ ${hintLines.join("\n")}` : "",
76807
77535
  });
76808
77536
  return result;
76809
77537
  }
77538
+ case "get_mesh_node_logs": {
77539
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
77540
+ const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
77541
+ let nodeDaemonId;
77542
+ if (meshId && nodeId) {
77543
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
77544
+ const node = meshRecord?.mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
77545
+ nodeDaemonId = typeof node?.daemonId === "string" ? node.daemonId.trim() : void 0;
77546
+ }
77547
+ const selfDaemonId = this.deps.statusInstanceId;
77548
+ const isRemote = nodeDaemonId && selfDaemonId && nodeDaemonId !== selfDaemonId;
77549
+ if (isRemote && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
77550
+ const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "get_mesh_node_logs", {
77551
+ ...typeof args === "object" && args !== null ? args : {},
77552
+ _meshDirectDispatch: true
77553
+ });
77554
+ return forwarded ?? { success: false, error: "no response from remote node" };
77555
+ }
77556
+ const rawTailBytes = Number(args?.tailBytes);
77557
+ const tail = readDaemonLogTail({
77558
+ date: typeof args?.date === "string" ? args.date : void 0,
77559
+ tailBytes: Number.isFinite(rawTailBytes) ? Math.min(rawTailBytes, MAX_TAIL_BYTES) : void 0,
77560
+ grep: typeof args?.grep === "string" ? args.grep : void 0,
77561
+ sinceMs: Number.isFinite(Number(args?.sinceMs)) ? Number(args?.sinceMs) : void 0
77562
+ });
77563
+ if (!tail.success) {
77564
+ return {
77565
+ success: false,
77566
+ error: tail.error || "failed to read daemon log tail",
77567
+ nodeId,
77568
+ logPath: tail.logPath,
77569
+ platform: tail.platform
77570
+ };
77571
+ }
77572
+ const redactedLines = redactLogLines(tail.lines);
77573
+ return {
77574
+ success: true,
77575
+ nodeId,
77576
+ daemonId: selfDaemonId,
77577
+ logPath: tail.logPath,
77578
+ platform: tail.platform,
77579
+ lines: redactedLines,
77580
+ lineCount: redactedLines.length,
77581
+ truncated: tail.truncated,
77582
+ filtered: tail.filtered,
77583
+ bytesReturned: tail.bytesReturned,
77584
+ ...tail.grep ? { grep: tail.grep } : {}
77585
+ };
77586
+ }
76810
77587
  case "refine_mesh_node": {
76811
77588
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
76812
77589
  const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
76813
77590
  if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
77591
+ {
77592
+ const meshRecordForForward = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
77593
+ const forwardNode = meshRecordForForward?.mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
77594
+ const nodeDaemonId = typeof forwardNode?.daemonId === "string" ? forwardNode.daemonId.trim() : void 0;
77595
+ const selfDaemonId = this.deps.statusInstanceId;
77596
+ const isRemote = nodeDaemonId && selfDaemonId && nodeDaemonId !== selfDaemonId;
77597
+ if (isRemote && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
77598
+ const callerCoordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : void 0;
77599
+ const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "refine_mesh_node", {
77600
+ ...typeof args === "object" && args !== null ? args : {},
77601
+ coordinatorDaemonId: callerCoordinatorDaemonId || selfDaemonId,
77602
+ _meshDirectDispatch: true
77603
+ });
77604
+ return forwarded ?? { success: false, error: "no response from remote node" };
77605
+ }
77606
+ }
76814
77607
  const isDryRun = args?.dryRun !== false && args?.execute !== true;
76815
77608
  if (isDryRun) {
76816
77609
  const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
@@ -77458,15 +78251,15 @@ ${ptyResult.output.slice(-2e3)}`);
77458
78251
  }
77459
78252
  if (cliType === "codex-cli") {
77460
78253
  const repoMcpConfigPath = (0, import_path11.join)(workspace, ".mcp.json");
77461
- if (fs24.existsSync(repoMcpConfigPath)) {
78254
+ if (fs25.existsSync(repoMcpConfigPath)) {
77462
78255
  try {
77463
78256
  const repoMcpConfig = parseMeshCoordinatorMcpConfig(
77464
- fs24.readFileSync(repoMcpConfigPath, "utf-8"),
78257
+ fs25.readFileSync(repoMcpConfigPath, "utf-8"),
77465
78258
  "claude_mcp_json"
77466
78259
  );
77467
78260
  const existingServers2 = repoMcpConfig.mcpServers;
77468
78261
  if (existingServers2 && typeof existingServers2 === "object" && !Array.isArray(existingServers2) && existingServers2[coordinatorSetup.serverName]) {
77469
- fs24.writeFileSync(repoMcpConfigPath, serializeMeshCoordinatorMcpConfig({
78262
+ fs25.writeFileSync(repoMcpConfigPath, serializeMeshCoordinatorMcpConfig({
77470
78263
  ...repoMcpConfig,
77471
78264
  mcpServers: {
77472
78265
  ...existingServers2,
@@ -77582,7 +78375,7 @@ ${ptyResult.output.slice(-2e3)}`);
77582
78375
  workspace
77583
78376
  };
77584
78377
  }
77585
- const { existsSync: existsSync43, readFileSync: readFileSync35, writeFileSync: writeFileSync23, copyFileSync: copyFileSync4, mkdirSync: mkdirSync21 } = await import("fs");
78378
+ const { existsSync: existsSync44, readFileSync: readFileSync35, writeFileSync: writeFileSync23, copyFileSync: copyFileSync4, mkdirSync: mkdirSync21 } = await import("fs");
77586
78379
  const { dirname: dirname14 } = await import("path");
77587
78380
  const mcpConfigPath = coordinatorSetup.configPath;
77588
78381
  const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
@@ -77625,7 +78418,7 @@ ${ptyResult.output.slice(-2e3)}`);
77625
78418
  if (hermesManualFallback) return returnManualFallback(message);
77626
78419
  return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
77627
78420
  }
77628
- const hadExistingMcpConfig = existsSync43(mcpConfigPath);
78421
+ const hadExistingMcpConfig = existsSync44(mcpConfigPath);
77629
78422
  let existingMcpConfig = hermesBaseConfig?.config || {};
77630
78423
  if (hermesBaseConfig) {
77631
78424
  copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname14(mcpConfigPath));
@@ -77783,6 +78576,7 @@ ${ptyResult.output.slice(-2e3)}`);
77783
78576
  const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
77784
78577
  const localMachineId = loadConfig2().machineId || "";
77785
78578
  const requireDirectPeerTruth = args?.requireDirectPeerTruth === true;
78579
+ const meshGitProbeCache = this.meshGitProbeCache;
77786
78580
  const directTruth = requireDirectPeerTruth ? await hydrateInlineMeshDirectTruth({
77787
78581
  mesh,
77788
78582
  meshSource: meshRecord.source,
@@ -77793,14 +78587,16 @@ ${ptyResult.output.slice(-2e3)}`);
77793
78587
  // Standing-state model: only an explicit refresh fans
77794
78588
  // out a blocking peer git probe. Default loads return
77795
78589
  // held truth so one slow peer can't block the graph.
77796
- probeRemotePeers: refreshRequested
78590
+ probeRemotePeers: refreshRequested,
78591
+ probeCache: meshGitProbeCache
77797
78592
  }) : {
77798
78593
  directEvidenceCount: 0,
77799
78594
  localConfirmedCount: 0,
77800
78595
  peerAttemptedCount: 0,
77801
78596
  peerConfirmedCount: 0,
77802
78597
  standingEvidenceCount: 0,
77803
- unavailableNodeIds: []
78598
+ unavailableNodeIds: [],
78599
+ deadNodeIds: []
77804
78600
  };
77805
78601
  const passivePeerTruthNotAttempted = requireDirectPeerTruth && !refreshRequested && directTruth.directEvidenceCount > 0 && directTruth.peerAttemptedCount === 0;
77806
78602
  const effectiveDirectTruth = passivePeerTruthNotAttempted ? { ...directTruth, unavailableNodeIds: [] } : directTruth;
@@ -77940,7 +78736,7 @@ ${ptyResult.output.slice(-2e3)}`);
77940
78736
  }
77941
78737
  }
77942
78738
  if (workspace) {
77943
- if (!fs24.existsSync(workspace)) {
78739
+ if (!fs25.existsSync(workspace)) {
77944
78740
  const inlineTransitGit = buildInlineMeshTransitGitStatus(node);
77945
78741
  let remoteProbeApplied = false;
77946
78742
  if (inlineTransitGit) {
@@ -77954,7 +78750,7 @@ ${ptyResult.output.slice(-2e3)}`);
77954
78750
  }
77955
78751
  remoteProbeApplied = true;
77956
78752
  } else if (refreshRequested && !isSelfNode && daemonId && this.deps.dispatchMeshCommand && !directTruthUnavailableNodeIds.has(nodeId)) {
77957
- const remoteGit = await probeRemoteMeshGitStatusWithRetry({
78753
+ const runNodeProbe = () => probeRemoteMeshGitStatusWithRetry({
77958
78754
  dispatchMeshCommand: this.deps.dispatchMeshCommand,
77959
78755
  daemonId,
77960
78756
  workspace,
@@ -77965,6 +78761,7 @@ ${ptyResult.output.slice(-2e3)}`);
77965
78761
  status.connection = connection;
77966
78762
  }
77967
78763
  });
78764
+ const remoteGit = await meshGitProbeCache.probe(daemonId, workspace, runNodeProbe);
77968
78765
  if (remoteGit) {
77969
78766
  status.git = remoteGit;
77970
78767
  status.health = remoteGit.isGitRepo ? deriveMeshNodeHealthFromGit(remoteGit) : "degraded";
@@ -78030,7 +78827,7 @@ ${ptyResult.output.slice(-2e3)}`);
78030
78827
  const pendingCoordinatorEvents = getPendingMeshCoordinatorEvents(meshId, callerCoordinatorDaemonId);
78031
78828
  const unroutableDeliveries = getRecentUnroutableDeliveries();
78032
78829
  const previewFreshness = (() => {
78033
- const localRepoRoot = nodeStatuses.map((node) => readStringValue(node?.git?.repoRoot, node?.repoRoot, node?.workspace)).find((candidate) => !!candidate && fs24.existsSync(candidate));
78830
+ const localRepoRoot = nodeStatuses.map((node) => readStringValue(node?.git?.repoRoot, node?.repoRoot, node?.workspace)).find((candidate) => !!candidate && fs25.existsSync(candidate));
78034
78831
  return localRepoRoot ? buildPreviewFreshness(localRepoRoot) : void 0;
78035
78832
  })();
78036
78833
  const asyncRefineJobs = buildMeshAsyncRefineJobs({
@@ -78125,7 +78922,7 @@ ${ptyResult.output.slice(-2e3)}`);
78125
78922
  const { deriveMeshReviewInboxItems: deriveMeshReviewInboxItems2 } = await Promise.resolve().then(() => (init_mesh_review_inbox(), mesh_review_inbox_exports));
78126
78923
  const { readLedgerEntries: readLedgerEntries2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
78127
78924
  const { getGitDiffSummary: getGitDiffSummary2 } = await Promise.resolve().then(() => (init_git_diff(), git_diff_exports));
78128
- const { existsSync: existsSync43 } = await import("fs");
78925
+ const { existsSync: existsSync44 } = await import("fs");
78129
78926
  const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
78130
78927
  const mesh = meshRecord?.mesh;
78131
78928
  if (!mesh) return { success: false, error: "Mesh not found" };
@@ -78144,7 +78941,7 @@ ${ptyResult.output.slice(-2e3)}`);
78144
78941
  const derivation = deriveMeshReviewInboxItems2({ nodes: nodeStatuses, ledgerEntries });
78145
78942
  for (const item of derivation.items) {
78146
78943
  const workspace = item.workspace;
78147
- if (!workspace || !existsSync43(workspace)) continue;
78944
+ if (!workspace || !existsSync44(workspace)) continue;
78148
78945
  const baseRef = item.defaultBranch ? `origin/${item.defaultBranch}` : "origin/main";
78149
78946
  try {
78150
78947
  const diffResult = await getGitDiffSummary2(workspace, { baseRef, maxFiles: 100 });
@@ -79868,7 +80665,7 @@ ${ptyResult.output.slice(-2e3)}`);
79868
80665
  this.eventListeners = [];
79869
80666
  }
79870
80667
  };
79871
- var fs25 = __toESM2(require("fs"));
80668
+ var fs26 = __toESM2(require("fs"));
79872
80669
  var path36 = __toESM2(require("path"));
79873
80670
  var os28 = __toESM2(require("os"));
79874
80671
  var import_os4 = require("os");
@@ -79882,8 +80679,8 @@ ${ptyResult.output.slice(-2e3)}`);
79882
80679
  }
79883
80680
  load() {
79884
80681
  try {
79885
- if (fs25.existsSync(ARCHIVE_PATH)) {
79886
- this.history = JSON.parse(fs25.readFileSync(ARCHIVE_PATH, "utf-8"));
80682
+ if (fs26.existsSync(ARCHIVE_PATH)) {
80683
+ this.history = JSON.parse(fs26.readFileSync(ARCHIVE_PATH, "utf-8"));
79887
80684
  }
79888
80685
  } catch {
79889
80686
  this.history = {};
@@ -79920,8 +80717,8 @@ ${ptyResult.output.slice(-2e3)}`);
79920
80717
  }
79921
80718
  save() {
79922
80719
  try {
79923
- fs25.mkdirSync(path36.dirname(ARCHIVE_PATH), { recursive: true });
79924
- fs25.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
80720
+ fs26.mkdirSync(path36.dirname(ARCHIVE_PATH), { recursive: true });
80721
+ fs26.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
79925
80722
  } catch {
79926
80723
  }
79927
80724
  }
@@ -79946,8 +80743,8 @@ ${ptyResult.output.slice(-2e3)}`);
79946
80743
  for (const ext of exes) {
79947
80744
  const fullPath = path36.join(p, name + ext);
79948
80745
  try {
79949
- if (fs25.existsSync(fullPath)) {
79950
- const stat2 = fs25.statSync(fullPath);
80746
+ if (fs26.existsSync(fullPath)) {
80747
+ const stat2 = fs26.statSync(fullPath);
79951
80748
  if (stat2.isFile() && (isWin || stat2.mode & 73)) {
79952
80749
  return fullPath;
79953
80750
  }
@@ -79994,9 +80791,9 @@ ${ptyResult.output.slice(-2e3)}`);
79994
80791
  if (p.includes("*")) {
79995
80792
  const home = os28.homedir();
79996
80793
  const resolved = p.replace(/\*/g, home.split(path36.sep).pop() || "");
79997
- if (fs25.existsSync(resolved)) return resolved;
80794
+ if (fs26.existsSync(resolved)) return resolved;
79998
80795
  } else {
79999
- if (fs25.existsSync(p)) return p;
80796
+ if (fs26.existsSync(p)) return p;
80000
80797
  }
80001
80798
  }
80002
80799
  return null;
@@ -80004,7 +80801,7 @@ ${ptyResult.output.slice(-2e3)}`);
80004
80801
  async function getMacAppVersion(appPath) {
80005
80802
  if ((0, import_os4.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
80006
80803
  const plistPath = path36.join(appPath, "Contents", "Info.plist");
80007
- if (!fs25.existsSync(plistPath)) return null;
80804
+ if (!fs26.existsSync(plistPath)) return null;
80008
80805
  const raw = await runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
80009
80806
  return raw || null;
80010
80807
  }
@@ -80030,7 +80827,7 @@ ${ptyResult.output.slice(-2e3)}`);
80030
80827
  let resolvedBin = cliBin;
80031
80828
  if (!resolvedBin && appPath && currentOs === "darwin") {
80032
80829
  const bundled = path36.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
80033
- if (provider.cli && fs25.existsSync(bundled)) resolvedBin = bundled;
80830
+ if (provider.cli && fs26.existsSync(bundled)) resolvedBin = bundled;
80034
80831
  }
80035
80832
  info.installed = !!(appPath || resolvedBin);
80036
80833
  info.path = appPath || null;
@@ -80067,7 +80864,7 @@ ${ptyResult.output.slice(-2e3)}`);
80067
80864
  return results;
80068
80865
  }
80069
80866
  var http2 = __toESM2(require("http"));
80070
- var fs29 = __toESM2(require("fs"));
80867
+ var fs30 = __toESM2(require("fs"));
80071
80868
  var path40 = __toESM2(require("path"));
80072
80869
  init_config();
80073
80870
  function generateFiles(type, name, category, opts = {}) {
@@ -80412,7 +81209,7 @@ async (params) => {
80412
81209
  };
80413
81210
  }
80414
81211
  init_logger();
80415
- var fs26 = __toESM2(require("fs"));
81212
+ var fs27 = __toESM2(require("fs"));
80416
81213
  var path37 = __toESM2(require("path"));
80417
81214
  init_logger();
80418
81215
  async function handleCdpEvaluate(ctx, req, res) {
@@ -80593,17 +81390,17 @@ async (params) => {
80593
81390
  }
80594
81391
  let scriptsPath = "";
80595
81392
  const directScripts = path37.join(dir, "scripts.js");
80596
- if (fs26.existsSync(directScripts)) {
81393
+ if (fs27.existsSync(directScripts)) {
80597
81394
  scriptsPath = directScripts;
80598
81395
  } else {
80599
81396
  const scriptsDir = path37.join(dir, "scripts");
80600
- if (fs26.existsSync(scriptsDir)) {
80601
- const versions = fs26.readdirSync(scriptsDir).filter((d) => {
80602
- return fs26.statSync(path37.join(scriptsDir, d)).isDirectory();
81397
+ if (fs27.existsSync(scriptsDir)) {
81398
+ const versions = fs27.readdirSync(scriptsDir).filter((d) => {
81399
+ return fs27.statSync(path37.join(scriptsDir, d)).isDirectory();
80603
81400
  }).sort().reverse();
80604
81401
  for (const ver of versions) {
80605
81402
  const p = path37.join(scriptsDir, ver, "scripts.js");
80606
- if (fs26.existsSync(p)) {
81403
+ if (fs27.existsSync(p)) {
80607
81404
  scriptsPath = p;
80608
81405
  break;
80609
81406
  }
@@ -80615,7 +81412,7 @@ async (params) => {
80615
81412
  return;
80616
81413
  }
80617
81414
  try {
80618
- const source = fs26.readFileSync(scriptsPath, "utf-8");
81415
+ const source = fs27.readFileSync(scriptsPath, "utf-8");
80619
81416
  const hints = {};
80620
81417
  const funcRegex = /module\.exports\.(\w+)\s*=\s*function\s+\w+\s*\(params\)/g;
80621
81418
  let match;
@@ -81428,7 +82225,7 @@ async (params) => {
81428
82225
  ctx.json(res, 500, { error: `DOM context collection failed: ${e.message}` });
81429
82226
  }
81430
82227
  }
81431
- var fs27 = __toESM2(require("fs"));
82228
+ var fs28 = __toESM2(require("fs"));
81432
82229
  var path38 = __toESM2(require("path"));
81433
82230
  function slugifyFixtureName(value) {
81434
82231
  const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
@@ -81444,10 +82241,10 @@ async (params) => {
81444
82241
  function readCliFixture(ctx, type, name) {
81445
82242
  const fixtureDir = getCliFixtureDir(ctx, type);
81446
82243
  const filePath = path38.join(fixtureDir, `${name}.json`);
81447
- if (!fs27.existsSync(filePath)) {
82244
+ if (!fs28.existsSync(filePath)) {
81448
82245
  throw new Error(`Fixture not found: ${filePath}`);
81449
82246
  }
81450
- return JSON.parse(fs27.readFileSync(filePath, "utf-8"));
82247
+ return JSON.parse(fs28.readFileSync(filePath, "utf-8"));
81451
82248
  }
81452
82249
  function getExerciseTranscriptText(result) {
81453
82250
  const parts = [];
@@ -82192,7 +82989,7 @@ async (params) => {
82192
82989
  return;
82193
82990
  }
82194
82991
  const fixtureDir = getCliFixtureDir(ctx, type);
82195
- fs27.mkdirSync(fixtureDir, { recursive: true });
82992
+ fs28.mkdirSync(fixtureDir, { recursive: true });
82196
82993
  const name = slugifyFixtureName(String(body?.name || `${type}-${Date.now()}`));
82197
82994
  const result = await runCliExerciseInternal(ctx, { ...request, type });
82198
82995
  const fixture = {
@@ -82220,7 +83017,7 @@ async (params) => {
82220
83017
  notes: typeof body?.notes === "string" ? body.notes : void 0
82221
83018
  };
82222
83019
  const filePath = path38.join(fixtureDir, `${name}.json`);
82223
- fs27.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
83020
+ fs28.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
82224
83021
  ctx.json(res, 200, {
82225
83022
  saved: true,
82226
83023
  name,
@@ -82238,14 +83035,14 @@ async (params) => {
82238
83035
  async function handleCliFixtureList(ctx, type, _req, res) {
82239
83036
  try {
82240
83037
  const fixtureDir = getCliFixtureDir(ctx, type);
82241
- if (!fs27.existsSync(fixtureDir)) {
83038
+ if (!fs28.existsSync(fixtureDir)) {
82242
83039
  ctx.json(res, 200, { fixtures: [], count: 0 });
82243
83040
  return;
82244
83041
  }
82245
- const fixtures = fs27.readdirSync(fixtureDir).filter((file2) => file2.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file2) => {
83042
+ const fixtures = fs28.readdirSync(fixtureDir).filter((file2) => file2.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file2) => {
82246
83043
  const fullPath = path38.join(fixtureDir, file2);
82247
83044
  try {
82248
- const raw = JSON.parse(fs27.readFileSync(fullPath, "utf-8"));
83045
+ const raw = JSON.parse(fs28.readFileSync(fullPath, "utf-8"));
82249
83046
  return {
82250
83047
  name: raw.name || file2.replace(/\.json$/i, ""),
82251
83048
  path: fullPath,
@@ -82376,7 +83173,7 @@ async (params) => {
82376
83173
  ctx.json(res, 500, { error: `Raw send failed: ${e.message}` });
82377
83174
  }
82378
83175
  }
82379
- var fs28 = __toESM2(require("fs"));
83176
+ var fs29 = __toESM2(require("fs"));
82380
83177
  var path39 = __toESM2(require("path"));
82381
83178
  var os29 = __toESM2(require("os"));
82382
83179
  var import_session_host_core8 = require_dist();
@@ -82425,10 +83222,10 @@ async (params) => {
82425
83222
  return fallback?.type || null;
82426
83223
  }
82427
83224
  function getLatestScriptVersionDir(scriptsDir) {
82428
- if (!fs28.existsSync(scriptsDir)) return null;
82429
- const versions = fs28.readdirSync(scriptsDir).filter((d) => {
83225
+ if (!fs29.existsSync(scriptsDir)) return null;
83226
+ const versions = fs29.readdirSync(scriptsDir).filter((d) => {
82430
83227
  try {
82431
- return fs28.statSync(path39.join(scriptsDir, d)).isDirectory();
83228
+ return fs29.statSync(path39.join(scriptsDir, d)).isDirectory();
82432
83229
  } catch {
82433
83230
  return false;
82434
83231
  }
@@ -82450,13 +83247,13 @@ async (params) => {
82450
83247
  if (!sourceDir) {
82451
83248
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
82452
83249
  }
82453
- if (!fs28.existsSync(desiredDir)) {
82454
- fs28.mkdirSync(path39.dirname(desiredDir), { recursive: true });
82455
- fs28.cpSync(sourceDir, desiredDir, { recursive: true });
83250
+ if (!fs29.existsSync(desiredDir)) {
83251
+ fs29.mkdirSync(path39.dirname(desiredDir), { recursive: true });
83252
+ fs29.cpSync(sourceDir, desiredDir, { recursive: true });
82456
83253
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
82457
83254
  }
82458
83255
  const providerJson = path39.join(desiredDir, "provider.json");
82459
- if (!fs28.existsSync(providerJson)) {
83256
+ if (!fs29.existsSync(providerJson)) {
82460
83257
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
82461
83258
  }
82462
83259
  return { dir: desiredDir };
@@ -82464,15 +83261,15 @@ async (params) => {
82464
83261
  function loadAutoImplReferenceScripts(ctx, referenceType) {
82465
83262
  if (!referenceType) return {};
82466
83263
  const refDir = ctx.findProviderDir(referenceType);
82467
- if (!refDir || !fs28.existsSync(refDir)) return {};
83264
+ if (!refDir || !fs29.existsSync(refDir)) return {};
82468
83265
  const referenceScripts = {};
82469
83266
  const scriptsDir = path39.join(refDir, "scripts");
82470
83267
  const latestDir = getLatestScriptVersionDir(scriptsDir);
82471
83268
  if (!latestDir) return referenceScripts;
82472
- for (const file2 of fs28.readdirSync(latestDir)) {
83269
+ for (const file2 of fs29.readdirSync(latestDir)) {
82473
83270
  if (!file2.endsWith(".js")) continue;
82474
83271
  try {
82475
- referenceScripts[file2] = fs28.readFileSync(path39.join(latestDir, file2), "utf-8");
83272
+ referenceScripts[file2] = fs29.readFileSync(path39.join(latestDir, file2), "utf-8");
82476
83273
  } catch {
82477
83274
  }
82478
83275
  }
@@ -82581,15 +83378,15 @@ async (params) => {
82581
83378
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
82582
83379
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
82583
83380
  const tmpDir = path39.join(os29.tmpdir(), "adhdev-autoimpl");
82584
- if (!fs28.existsSync(tmpDir)) fs28.mkdirSync(tmpDir, { recursive: true });
83381
+ if (!fs29.existsSync(tmpDir)) fs29.mkdirSync(tmpDir, { recursive: true });
82585
83382
  const promptFile = path39.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
82586
- fs28.writeFileSync(promptFile, prompt, "utf-8");
83383
+ fs29.writeFileSync(promptFile, prompt, "utf-8");
82587
83384
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
82588
83385
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
82589
83386
  const spawn4 = agentProvider?.spawn;
82590
83387
  if (!spawn4?.command) {
82591
83388
  try {
82592
- fs28.unlinkSync(promptFile);
83389
+ fs29.unlinkSync(promptFile);
82593
83390
  } catch {
82594
83391
  }
82595
83392
  ctx.json(res, 400, { error: `Agent '${agent}' has no spawn config. Select a CLI provider with a spawn configuration.` });
@@ -82691,7 +83488,7 @@ async (params) => {
82691
83488
  } catch {
82692
83489
  }
82693
83490
  try {
82694
- fs28.unlinkSync(promptFile);
83491
+ fs29.unlinkSync(promptFile);
82695
83492
  } catch {
82696
83493
  }
82697
83494
  ctx.log(`Auto-implement (ACP) ${success2 ? "completed" : "failed"}: ${type} (exit: ${code})`);
@@ -82917,7 +83714,7 @@ async (params) => {
82917
83714
  }
82918
83715
  });
82919
83716
  try {
82920
- fs28.unlinkSync(promptFile);
83717
+ fs29.unlinkSync(promptFile);
82921
83718
  } catch {
82922
83719
  }
82923
83720
  ctx.log(`Auto-implement ${success2 ? "completed" : "failed"}: ${type} (exit: ${code})${verificationSummary ? ` verify=${verificationSummary.pass ? "pass" : "fail"}` : ""}`);
@@ -83022,10 +83819,10 @@ async (params) => {
83022
83819
  lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
83023
83820
  lines.push("These are the ONLY files you are allowed to modify. Replace the TODO stubs with working implementations.");
83024
83821
  lines.push("");
83025
- for (const file2 of fs28.readdirSync(latestScriptsDir)) {
83822
+ for (const file2 of fs29.readdirSync(latestScriptsDir)) {
83026
83823
  if (file2.endsWith(".js") && targetFileNames.has(file2)) {
83027
83824
  try {
83028
- const content = fs28.readFileSync(path39.join(latestScriptsDir, file2), "utf-8");
83825
+ const content = fs29.readFileSync(path39.join(latestScriptsDir, file2), "utf-8");
83029
83826
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
83030
83827
  lines.push("```javascript");
83031
83828
  lines.push(content);
@@ -83035,14 +83832,14 @@ async (params) => {
83035
83832
  }
83036
83833
  }
83037
83834
  }
83038
- const refFiles = fs28.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
83835
+ const refFiles = fs29.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
83039
83836
  if (refFiles.length > 0) {
83040
83837
  lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
83041
83838
  lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
83042
83839
  lines.push("");
83043
83840
  for (const file2 of refFiles) {
83044
83841
  try {
83045
- const content = fs28.readFileSync(path39.join(latestScriptsDir, file2), "utf-8");
83842
+ const content = fs29.readFileSync(path39.join(latestScriptsDir, file2), "utf-8");
83046
83843
  lines.push(`### \`${file2}\` \u{1F512}`);
83047
83844
  lines.push("```javascript");
83048
83845
  lines.push(content);
@@ -83087,7 +83884,7 @@ async (params) => {
83087
83884
  const loadGuide = (name) => {
83088
83885
  try {
83089
83886
  const p = path39.join(docsDir, name);
83090
- if (fs28.existsSync(p)) return fs28.readFileSync(p, "utf-8");
83887
+ if (fs29.existsSync(p)) return fs29.readFileSync(p, "utf-8");
83091
83888
  } catch {
83092
83889
  }
83093
83890
  return null;
@@ -83331,11 +84128,11 @@ async (params) => {
83331
84128
  lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
83332
84129
  lines.push("These are the ONLY files you are allowed to modify. Replace TODO or heuristic-only logic with working PTY-aware implementations.");
83333
84130
  lines.push("");
83334
- for (const file2 of fs28.readdirSync(latestScriptsDir)) {
84131
+ for (const file2 of fs29.readdirSync(latestScriptsDir)) {
83335
84132
  if (!file2.endsWith(".js")) continue;
83336
84133
  if (!targetFileNames.has(file2)) continue;
83337
84134
  try {
83338
- const content = fs28.readFileSync(path39.join(latestScriptsDir, file2), "utf-8");
84135
+ const content = fs29.readFileSync(path39.join(latestScriptsDir, file2), "utf-8");
83339
84136
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
83340
84137
  lines.push("```javascript");
83341
84138
  lines.push(content);
@@ -83344,14 +84141,14 @@ async (params) => {
83344
84141
  } catch {
83345
84142
  }
83346
84143
  }
83347
- const refFiles = fs28.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
84144
+ const refFiles = fs29.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
83348
84145
  if (refFiles.length > 0) {
83349
84146
  lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
83350
84147
  lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
83351
84148
  lines.push("");
83352
84149
  for (const file2 of refFiles) {
83353
84150
  try {
83354
- const content = fs28.readFileSync(path39.join(latestScriptsDir, file2), "utf-8");
84151
+ const content = fs29.readFileSync(path39.join(latestScriptsDir, file2), "utf-8");
83355
84152
  lines.push(`### \`${file2}\` \u{1F512}`);
83356
84153
  lines.push("```javascript");
83357
84154
  lines.push(content);
@@ -83388,7 +84185,7 @@ async (params) => {
83388
84185
  const loadGuide = (name) => {
83389
84186
  try {
83390
84187
  const p = path39.join(docsDir, name);
83391
- if (fs28.existsSync(p)) return fs28.readFileSync(p, "utf-8");
84188
+ if (fs29.existsSync(p)) return fs29.readFileSync(p, "utf-8");
83392
84189
  } catch {
83393
84190
  }
83394
84191
  return null;
@@ -84126,7 +84923,7 @@ data: ${JSON.stringify(msg.data)}
84126
84923
  path40.join(process.cwd(), "packages/web-devconsole/dist")
84127
84924
  ];
84128
84925
  for (const dir of candidates) {
84129
- if (fs29.existsSync(path40.join(dir, "index.html"))) return dir;
84926
+ if (fs30.existsSync(path40.join(dir, "index.html"))) return dir;
84130
84927
  }
84131
84928
  return null;
84132
84929
  }
@@ -84138,7 +84935,7 @@ data: ${JSON.stringify(msg.data)}
84138
84935
  }
84139
84936
  const htmlPath = path40.join(distDir, "index.html");
84140
84937
  try {
84141
- const html = fs29.readFileSync(htmlPath, "utf-8");
84938
+ const html = fs30.readFileSync(htmlPath, "utf-8");
84142
84939
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
84143
84940
  res.end(html);
84144
84941
  } catch (e) {
@@ -84168,7 +84965,7 @@ data: ${JSON.stringify(msg.data)}
84168
84965
  return;
84169
84966
  }
84170
84967
  try {
84171
- const content = fs29.readFileSync(filePath);
84968
+ const content = fs30.readFileSync(filePath);
84172
84969
  const ext = path40.extname(filePath);
84173
84970
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
84174
84971
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
@@ -84277,14 +85074,14 @@ data: ${JSON.stringify(msg.data)}
84277
85074
  const files = [];
84278
85075
  const scan = (d, prefix) => {
84279
85076
  try {
84280
- for (const entry of fs29.readdirSync(d, { withFileTypes: true })) {
85077
+ for (const entry of fs30.readdirSync(d, { withFileTypes: true })) {
84281
85078
  if (entry.name.startsWith(".") || entry.name.endsWith(".bak")) continue;
84282
85079
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
84283
85080
  if (entry.isDirectory()) {
84284
85081
  files.push({ path: rel, size: 0, type: "dir" });
84285
85082
  scan(path40.join(d, entry.name), rel);
84286
85083
  } else {
84287
- const stat2 = fs29.statSync(path40.join(d, entry.name));
85084
+ const stat2 = fs30.statSync(path40.join(d, entry.name));
84288
85085
  files.push({ path: rel, size: stat2.size, type: "file" });
84289
85086
  }
84290
85087
  }
@@ -84312,11 +85109,11 @@ data: ${JSON.stringify(msg.data)}
84312
85109
  this.json(res, 403, { error: "Forbidden" });
84313
85110
  return;
84314
85111
  }
84315
- if (!fs29.existsSync(fullPath) || fs29.statSync(fullPath).isDirectory()) {
85112
+ if (!fs30.existsSync(fullPath) || fs30.statSync(fullPath).isDirectory()) {
84316
85113
  this.json(res, 404, { error: `File not found: ${filePath}` });
84317
85114
  return;
84318
85115
  }
84319
- const content = fs29.readFileSync(fullPath, "utf-8");
85116
+ const content = fs30.readFileSync(fullPath, "utf-8");
84320
85117
  this.json(res, 200, { type, path: filePath, content, lines: content.split("\n").length });
84321
85118
  }
84322
85119
  /** POST /api/providers/:type/file — write a file { path, content } */
@@ -84338,9 +85135,9 @@ data: ${JSON.stringify(msg.data)}
84338
85135
  return;
84339
85136
  }
84340
85137
  try {
84341
- if (fs29.existsSync(fullPath)) fs29.copyFileSync(fullPath, fullPath + ".bak");
84342
- fs29.mkdirSync(path40.dirname(fullPath), { recursive: true });
84343
- fs29.writeFileSync(fullPath, content, "utf-8");
85138
+ if (fs30.existsSync(fullPath)) fs30.copyFileSync(fullPath, fullPath + ".bak");
85139
+ fs30.mkdirSync(path40.dirname(fullPath), { recursive: true });
85140
+ fs30.writeFileSync(fullPath, content, "utf-8");
84344
85141
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
84345
85142
  this.providerLoader.reload();
84346
85143
  this.json(res, 200, { saved: true, path: filePath, chars: content.length });
@@ -84357,8 +85154,8 @@ data: ${JSON.stringify(msg.data)}
84357
85154
  }
84358
85155
  for (const name of ["scripts.js", "provider.json"]) {
84359
85156
  const p = path40.join(dir, name);
84360
- if (fs29.existsSync(p)) {
84361
- const source = fs29.readFileSync(p, "utf-8");
85157
+ if (fs30.existsSync(p)) {
85158
+ const source = fs30.readFileSync(p, "utf-8");
84362
85159
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
84363
85160
  return;
84364
85161
  }
@@ -84377,11 +85174,11 @@ data: ${JSON.stringify(msg.data)}
84377
85174
  this.json(res, 404, { error: `Provider not found: ${type}` });
84378
85175
  return;
84379
85176
  }
84380
- const target = fs29.existsSync(path40.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
85177
+ const target = fs30.existsSync(path40.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
84381
85178
  const targetPath = path40.join(dir, target);
84382
85179
  try {
84383
- if (fs29.existsSync(targetPath)) fs29.copyFileSync(targetPath, targetPath + ".bak");
84384
- fs29.writeFileSync(targetPath, source, "utf-8");
85180
+ if (fs30.existsSync(targetPath)) fs30.copyFileSync(targetPath, targetPath + ".bak");
85181
+ fs30.writeFileSync(targetPath, source, "utf-8");
84385
85182
  this.log(`Saved provider: ${targetPath} (${source.length} chars)`);
84386
85183
  this.providerLoader.reload();
84387
85184
  this.json(res, 200, { saved: true, path: targetPath, chars: source.length });
@@ -84526,20 +85323,20 @@ data: ${JSON.stringify(msg.data)}
84526
85323
  let targetDir;
84527
85324
  targetDir = this.providerLoader.getUserProviderDir(category, type);
84528
85325
  const jsonPath = path40.join(targetDir, "provider.json");
84529
- if (fs29.existsSync(jsonPath)) {
85326
+ if (fs30.existsSync(jsonPath)) {
84530
85327
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
84531
85328
  return;
84532
85329
  }
84533
85330
  try {
84534
85331
  const result = generateFiles(type, name, category, { cdpPorts, cli, processName, installPath, binary, extensionId, version: version2, osPaths, processNames });
84535
- fs29.mkdirSync(targetDir, { recursive: true });
84536
- fs29.writeFileSync(jsonPath, result["provider.json"], "utf-8");
85332
+ fs30.mkdirSync(targetDir, { recursive: true });
85333
+ fs30.writeFileSync(jsonPath, result["provider.json"], "utf-8");
84537
85334
  const createdFiles = ["provider.json"];
84538
85335
  if (result.files) {
84539
85336
  for (const [relPath, content] of Object.entries(result.files)) {
84540
85337
  const fullPath = path40.join(targetDir, relPath);
84541
- fs29.mkdirSync(path40.dirname(fullPath), { recursive: true });
84542
- fs29.writeFileSync(fullPath, content, "utf-8");
85338
+ fs30.mkdirSync(path40.dirname(fullPath), { recursive: true });
85339
+ fs30.writeFileSync(fullPath, content, "utf-8");
84543
85340
  createdFiles.push(relPath);
84544
85341
  }
84545
85342
  }
@@ -84588,10 +85385,10 @@ data: ${JSON.stringify(msg.data)}
84588
85385
  }
84589
85386
  // ─── Phase 2: Auto-Implement Backend ───
84590
85387
  getLatestScriptVersionDir(scriptsDir) {
84591
- if (!fs29.existsSync(scriptsDir)) return null;
84592
- const versions = fs29.readdirSync(scriptsDir).filter((d) => {
85388
+ if (!fs30.existsSync(scriptsDir)) return null;
85389
+ const versions = fs30.readdirSync(scriptsDir).filter((d) => {
84593
85390
  try {
84594
- return fs29.statSync(path40.join(scriptsDir, d)).isDirectory();
85391
+ return fs30.statSync(path40.join(scriptsDir, d)).isDirectory();
84595
85392
  } catch {
84596
85393
  return false;
84597
85394
  }
@@ -84613,13 +85410,13 @@ data: ${JSON.stringify(msg.data)}
84613
85410
  if (!sourceDir) {
84614
85411
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
84615
85412
  }
84616
- if (!fs29.existsSync(desiredDir)) {
84617
- fs29.mkdirSync(path40.dirname(desiredDir), { recursive: true });
84618
- fs29.cpSync(sourceDir, desiredDir, { recursive: true });
85413
+ if (!fs30.existsSync(desiredDir)) {
85414
+ fs30.mkdirSync(path40.dirname(desiredDir), { recursive: true });
85415
+ fs30.cpSync(sourceDir, desiredDir, { recursive: true });
84619
85416
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
84620
85417
  }
84621
85418
  const providerJson = path40.join(desiredDir, "provider.json");
84622
- if (!fs29.existsSync(providerJson)) {
85419
+ if (!fs30.existsSync(providerJson)) {
84623
85420
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
84624
85421
  }
84625
85422
  return { dir: desiredDir };
@@ -84662,10 +85459,10 @@ data: ${JSON.stringify(msg.data)}
84662
85459
  lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
84663
85460
  lines.push("These are the ONLY files you are allowed to modify. Replace the TODO stubs with working implementations.");
84664
85461
  lines.push("");
84665
- for (const file2 of fs29.readdirSync(latestScriptsDir)) {
85462
+ for (const file2 of fs30.readdirSync(latestScriptsDir)) {
84666
85463
  if (file2.endsWith(".js") && targetFileNames.has(file2)) {
84667
85464
  try {
84668
- const content = fs29.readFileSync(path40.join(latestScriptsDir, file2), "utf-8");
85465
+ const content = fs30.readFileSync(path40.join(latestScriptsDir, file2), "utf-8");
84669
85466
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
84670
85467
  lines.push("```javascript");
84671
85468
  lines.push(content);
@@ -84675,14 +85472,14 @@ data: ${JSON.stringify(msg.data)}
84675
85472
  }
84676
85473
  }
84677
85474
  }
84678
- const refFiles = fs29.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
85475
+ const refFiles = fs30.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
84679
85476
  if (refFiles.length > 0) {
84680
85477
  lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
84681
85478
  lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
84682
85479
  lines.push("");
84683
85480
  for (const file2 of refFiles) {
84684
85481
  try {
84685
- const content = fs29.readFileSync(path40.join(latestScriptsDir, file2), "utf-8");
85482
+ const content = fs30.readFileSync(path40.join(latestScriptsDir, file2), "utf-8");
84686
85483
  lines.push(`### \`${file2}\` \u{1F512}`);
84687
85484
  lines.push("```javascript");
84688
85485
  lines.push(content);
@@ -84727,7 +85524,7 @@ data: ${JSON.stringify(msg.data)}
84727
85524
  const loadGuide = (name) => {
84728
85525
  try {
84729
85526
  const p = path40.join(docsDir, name);
84730
- if (fs29.existsSync(p)) return fs29.readFileSync(p, "utf-8");
85527
+ if (fs30.existsSync(p)) return fs30.readFileSync(p, "utf-8");
84731
85528
  } catch {
84732
85529
  }
84733
85530
  return null;
@@ -84908,11 +85705,11 @@ data: ${JSON.stringify(msg.data)}
84908
85705
  lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
84909
85706
  lines.push("These are the ONLY files you are allowed to modify. Replace TODO or heuristic-only logic with working PTY-aware implementations.");
84910
85707
  lines.push("");
84911
- for (const file2 of fs29.readdirSync(latestScriptsDir)) {
85708
+ for (const file2 of fs30.readdirSync(latestScriptsDir)) {
84912
85709
  if (!file2.endsWith(".js")) continue;
84913
85710
  if (!targetFileNames.has(file2)) continue;
84914
85711
  try {
84915
- const content = fs29.readFileSync(path40.join(latestScriptsDir, file2), "utf-8");
85712
+ const content = fs30.readFileSync(path40.join(latestScriptsDir, file2), "utf-8");
84916
85713
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
84917
85714
  lines.push("```javascript");
84918
85715
  lines.push(content);
@@ -84921,14 +85718,14 @@ data: ${JSON.stringify(msg.data)}
84921
85718
  } catch {
84922
85719
  }
84923
85720
  }
84924
- const refFiles = fs29.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
85721
+ const refFiles = fs30.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
84925
85722
  if (refFiles.length > 0) {
84926
85723
  lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
84927
85724
  lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
84928
85725
  lines.push("");
84929
85726
  for (const file2 of refFiles) {
84930
85727
  try {
84931
- const content = fs29.readFileSync(path40.join(latestScriptsDir, file2), "utf-8");
85728
+ const content = fs30.readFileSync(path40.join(latestScriptsDir, file2), "utf-8");
84932
85729
  lines.push(`### \`${file2}\` \u{1F512}`);
84933
85730
  lines.push("```javascript");
84934
85731
  lines.push(content);
@@ -84965,7 +85762,7 @@ data: ${JSON.stringify(msg.data)}
84965
85762
  const loadGuide = (name) => {
84966
85763
  try {
84967
85764
  const p = path40.join(docsDir, name);
84968
- if (fs29.existsSync(p)) return fs29.readFileSync(p, "utf-8");
85765
+ if (fs30.existsSync(p)) return fs30.readFileSync(p, "utf-8");
84969
85766
  } catch {
84970
85767
  }
84971
85768
  return null;
@@ -86052,8 +86849,8 @@ data: ${JSON.stringify(msg.data)}
86052
86849
  const res = await fetch(extension.vsixUrl);
86053
86850
  if (res.ok) {
86054
86851
  const buffer = Buffer.from(await res.arrayBuffer());
86055
- const fs30 = await import("fs");
86056
- fs30.writeFileSync(vsixPath, buffer);
86852
+ const fs31 = await import("fs");
86853
+ fs31.writeFileSync(vsixPath, buffer);
86057
86854
  return new Promise((resolve24) => {
86058
86855
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
86059
86856
  (0, import_child_process11.exec)(cmd, { timeout: 6e4 }, (error48, _stdout, stderr) => {