@adhdev/daemon-standalone 0.9.82-rc.407 → 0.9.82-rc.409

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.
@@ -339,7 +339,7 @@ function compactChatPayload(payload, opts = {}) {
339
339
  }
340
340
 
341
341
  // src/tools/mesh-tools-internal.ts
342
- var import_daemon_core2 = require("@adhdev/daemon-core");
342
+ var import_daemon_core3 = require("@adhdev/daemon-core");
343
343
 
344
344
  // src/tools/mesh-tool-shared.ts
345
345
  function readString(value) {
@@ -390,6 +390,7 @@ function elideLargeNestedValue(key, value) {
390
390
  }
391
391
 
392
392
  // src/tools/mesh-session-helpers.ts
393
+ var import_daemon_core = require("@adhdev/daemon-core");
393
394
  function readSessionRecordId(session) {
394
395
  return readString(session?.id) || readString(session?.sessionId) || readString(session?.session_id) || readString(session?.runtimeSessionId) || readString(session?.runtime_session_id) || readString(session?.instanceId) || readString(session?.instance_id);
395
396
  }
@@ -417,8 +418,8 @@ function isUnmanagedSessionRecord(session) {
417
418
  );
418
419
  return !launchedByCoordinator;
419
420
  }
420
- function isWorkerTaskMode(taskMode) {
421
- return taskMode !== "live_debug_readonly";
421
+ function isWorkerTaskMode(taskMode, readonly) {
422
+ return !(0, import_daemon_core.isTaskReadonly)({ readonly, taskMode });
422
423
  }
423
424
  function addSessionRecord(target, session) {
424
425
  if (!session || typeof session !== "object" || isTerminalSessionRecord(session)) return;
@@ -483,7 +484,7 @@ function isIdleSessionRecord(session) {
483
484
  }
484
485
 
485
486
  // src/tools/mesh-node-identity.ts
486
- var import_daemon_core = require("@adhdev/daemon-core");
487
+ var import_daemon_core2 = require("@adhdev/daemon-core");
487
488
  function resolveCoordinatorNode(ctx) {
488
489
  const preferredNodeId = typeof ctx.mesh.coordinator?.preferredNodeId === "string" ? ctx.mesh.coordinator.preferredNodeId.trim() : "";
489
490
  if (preferredNodeId) {
@@ -567,8 +568,8 @@ function buildNodeMachineIdentity(ctx, node) {
567
568
  function nodeHasLocalDaemonEvidence(ctx, node) {
568
569
  const isLocal = (session) => {
569
570
  if (!session || typeof session !== "object") return false;
570
- if (ctx.localDaemonId && (0, import_daemon_core.daemonIdsEquivalent)(session.runtime?.owner, ctx.localDaemonId)) return true;
571
- if (ctx.localDaemonId && (0, import_daemon_core.daemonIdsEquivalent)(session.daemonClient?.daemonId, ctx.localDaemonId)) return true;
571
+ if (ctx.localDaemonId && (0, import_daemon_core2.daemonIdsEquivalent)(session.runtime?.owner, ctx.localDaemonId)) return true;
572
+ if (ctx.localDaemonId && (0, import_daemon_core2.daemonIdsEquivalent)(session.daemonClient?.daemonId, ctx.localDaemonId)) return true;
572
573
  return false;
573
574
  };
574
575
  const sessionArrays = [
@@ -607,7 +608,7 @@ function isDirectLocalNode(ctx, node) {
607
608
  const machineId = readNodeMachineId(node);
608
609
  const daemonId = readNodeDaemonId(node);
609
610
  return Boolean(
610
- ctx.localMachineId && (0, import_daemon_core.daemonIdsEquivalent)(machineId, ctx.localMachineId) || ctx.localDaemonId && (0, import_daemon_core.daemonIdsEquivalent)(daemonId, ctx.localDaemonId) || nodeHasLocalDaemonEvidence(ctx, node)
611
+ ctx.localMachineId && (0, import_daemon_core2.daemonIdsEquivalent)(machineId, ctx.localMachineId) || ctx.localDaemonId && (0, import_daemon_core2.daemonIdsEquivalent)(daemonId, ctx.localDaemonId) || nodeHasLocalDaemonEvidence(ctx, node)
611
612
  );
612
613
  }
613
614
  function isConfiguredCoordinatorNode(ctx, node) {
@@ -616,8 +617,8 @@ function isConfiguredCoordinatorNode(ctx, node) {
616
617
  if (!nodeId) return false;
617
618
  const nodeDaemonId = readNodeDaemonId(node);
618
619
  const nodeMachineId = readNodeMachineId(node);
619
- if (nodeDaemonId && ctx.localDaemonId && !(0, import_daemon_core.daemonIdsEquivalent)(nodeDaemonId, ctx.localDaemonId)) return false;
620
- if (nodeMachineId && ctx.localMachineId && !(0, import_daemon_core.daemonIdsEquivalent)(nodeMachineId, ctx.localMachineId)) return false;
620
+ if (nodeDaemonId && ctx.localDaemonId && !(0, import_daemon_core2.daemonIdsEquivalent)(nodeDaemonId, ctx.localDaemonId)) return false;
621
+ if (nodeMachineId && ctx.localMachineId && !(0, import_daemon_core2.daemonIdsEquivalent)(nodeMachineId, ctx.localMachineId)) return false;
621
622
  const preferredNodeId = readString(ctx.mesh.coordinator?.preferredNodeId) || readString(ctx.mesh.coordinator?.preferred_node_id);
622
623
  if (preferredNodeId) return nodeId === preferredNodeId;
623
624
  const first = ctx.mesh.nodes?.[0];
@@ -637,7 +638,7 @@ function getLocalControlPlaneMatchReason(ctx, node) {
637
638
  function findClonedFromNode(ctx, node) {
638
639
  const clonedFromNodeId = readString(node.clonedFromNodeId) || readString(node.cloned_from_node_id);
639
640
  if (!clonedFromNodeId) return void 0;
640
- return ctx.mesh.nodes.find((n) => (0, import_daemon_core.meshNodeIdMatches)(n, clonedFromNodeId));
641
+ return ctx.mesh.nodes.find((n) => (0, import_daemon_core2.meshNodeIdMatches)(n, clonedFromNodeId));
641
642
  }
642
643
  function resolvePreferredWorktreeNodeId(ctx) {
643
644
  const worktreeNodes = (ctx.mesh.nodes || []).filter((n) => n.isLocalWorktree === true);
@@ -683,6 +684,8 @@ var MESH_ENQUEUE_TASK_TOOL = {
683
684
  message: { type: "string", description: "The task instruction for the agent." },
684
685
  task_mode: { type: "string", enum: ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"], description: "Optional task-mode contract. live_debug_readonly rejects obvious write/commit/push/deploy/destructive instructions before dispatch." },
685
686
  taskMode: { type: "string", enum: ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"], description: "CamelCase alias for task_mode." },
687
+ readonly: { type: "boolean", description: "Optional read-only axis (orthogonal to task_mode). When true the task runs without the one-active-per-node write isolation (N read-only tasks may run in parallel on one node), is counted under the read-only safety cap, and rejects write/commit/push/deploy/destructive instructions like live_debug_readonly. Equivalent to task_mode=live_debug_readonly but composable with any task_mode." },
688
+ read_only: { type: "boolean", description: "Snake-case alias for readonly." },
686
689
  requiredTags: { type: "array", items: { type: "string" }, description: "Optional capability tags that every eligible node must have, e.g. os=darwin, provider=codex-cli, gpu." },
687
690
  required_tags: { type: "array", items: { type: "string" }, description: "Snake_case alias for requiredTags." },
688
691
  target_node_id: { type: "string", description: "Optional HARD constraint: ONLY this node may claim the task. No other node (especially a different machine) will ever claim it \u2014 if the target node has no idle session the task stays pending until it does. Use to route a queued task to a specific (e.g. freshly cloned) worktree node instead of letting the first idle base node claim it. Takes priority over prefer_worktree. An unresolvable target id is rejected at enqueue (no silent unpin)." },
@@ -760,6 +763,8 @@ var MESH_SEND_TASK_TOOL = {
760
763
  message: { type: "string", description: "Natural-language task to send to the agent." },
761
764
  task_mode: { type: "string", enum: ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"], description: "Optional task-mode contract. live_debug_readonly rejects obvious write/commit/push/deploy/destructive instructions before local or remote direct dispatch." },
762
765
  taskMode: { type: "string", enum: ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"], description: "CamelCase alias for task_mode." },
766
+ readonly: { type: "boolean", description: "Optional read-only axis (orthogonal to task_mode). When true the task runs without write isolation, is counted under the read-only cap, and rejects write/commit/push/deploy/destructive instructions like live_debug_readonly. Composable with any task_mode." },
767
+ read_only: { type: "boolean", description: "Snake-case alias for readonly." },
763
768
  mission_id: { type: "string", description: "Mission this task belongs to (mesh_mission record id). When set, the directly dispatched task is attributed to the mission task aggregates exactly like mesh_enqueue_task, including terminal completion. Omit for an unattributed direct dispatch." },
764
769
  missionId: { type: "string", description: "CamelCase alias for mission_id." }
765
770
  },
@@ -1608,7 +1613,7 @@ function annotateRapidReadChatAdvisory(payload, options) {
1608
1613
  }
1609
1614
 
1610
1615
  // src/tools/mesh-tools-internal.ts
1611
- var import_daemon_core3 = require("@adhdev/daemon-core");
1616
+ var import_daemon_core4 = require("@adhdev/daemon-core");
1612
1617
  var import_node_crypto = require("crypto");
1613
1618
  var SESSION_PROVIDER_METADATA_TTL_MS = 30 * 6e4;
1614
1619
  var meshSessionProviderMetadata = /* @__PURE__ */ new Map();
@@ -1655,7 +1660,7 @@ function buildDirectTaskPayload(message, via, opts) {
1655
1660
  };
1656
1661
  }
1657
1662
  function findNode(mesh, nodeId) {
1658
- const node = mesh.nodes.find((n) => (0, import_daemon_core2.meshNodeIdMatches)(n, nodeId));
1663
+ const node = mesh.nodes.find((n) => (0, import_daemon_core3.meshNodeIdMatches)(n, nodeId));
1659
1664
  if (!node) throw new Error(`Node '${nodeId}' is not a member of mesh '${mesh.name}'`);
1660
1665
  return node;
1661
1666
  }
@@ -1681,23 +1686,23 @@ async function syncCoordinatorDaemonMeshCache(ctx) {
1681
1686
  }
1682
1687
  }
1683
1688
  async function findNodeWithRefresh(ctx, nodeId) {
1684
- const hit = ctx.mesh.nodes.find((n) => (0, import_daemon_core2.meshNodeIdMatches)(n, nodeId));
1689
+ const hit = ctx.mesh.nodes.find((n) => (0, import_daemon_core3.meshNodeIdMatches)(n, nodeId));
1685
1690
  if (hit && !hit.isLocalWorktree) return hit;
1686
1691
  await refreshMeshFromDaemon(ctx);
1687
- const refreshed = ctx.mesh.nodes.find((n) => (0, import_daemon_core2.meshNodeIdMatches)(n, nodeId));
1692
+ const refreshed = ctx.mesh.nodes.find((n) => (0, import_daemon_core3.meshNodeIdMatches)(n, nodeId));
1688
1693
  if (!refreshed) throw new Error(`Node '${nodeId}' is not a member of mesh '${ctx.mesh.name}'`);
1689
1694
  return refreshed;
1690
1695
  }
1691
1696
  async function findOptionalNodeWithRefresh(ctx, nodeId) {
1692
- const hit = ctx.mesh.nodes.find((n) => (0, import_daemon_core2.meshNodeIdMatches)(n, nodeId));
1697
+ const hit = ctx.mesh.nodes.find((n) => (0, import_daemon_core3.meshNodeIdMatches)(n, nodeId));
1693
1698
  if (hit && !hit.isLocalWorktree) return hit;
1694
1699
  await refreshMeshFromDaemon(ctx);
1695
- return ctx.mesh.nodes.find((n) => (0, import_daemon_core2.meshNodeIdMatches)(n, nodeId)) ?? null;
1700
+ return ctx.mesh.nodes.find((n) => (0, import_daemon_core3.meshNodeIdMatches)(n, nodeId)) ?? null;
1696
1701
  }
1697
1702
  function hasRecentDuplicateDispatch(ctx, args) {
1698
1703
  const now = Date.now();
1699
1704
  const normalizedMessage = args.message.trim();
1700
- for (const task of (0, import_daemon_core2.getQueue)(ctx.mesh.id)) {
1705
+ for (const task of (0, import_daemon_core3.getQueue)(ctx.mesh.id)) {
1701
1706
  const timestamp = new Date(task.updatedAt || task.createdAt).getTime();
1702
1707
  if (!Number.isFinite(timestamp) || now - timestamp > DUPLICATE_DISPATCH_WINDOW_MS) continue;
1703
1708
  if (task.targetNodeId && task.targetNodeId !== args.node_id) continue;
@@ -1707,7 +1712,7 @@ function hasRecentDuplicateDispatch(ctx, args) {
1707
1712
  return { duplicate: true, entry: task, source: "queue" };
1708
1713
  }
1709
1714
  }
1710
- const entries = (0, import_daemon_core2.readLedgerEntries)(ctx.mesh.id, { tail: 200 });
1715
+ const entries = (0, import_daemon_core3.readLedgerEntries)(ctx.mesh.id, { tail: 200 });
1711
1716
  for (let i = entries.length - 1; i >= 0; i -= 1) {
1712
1717
  const entry = entries[i];
1713
1718
  const timestamp = new Date(entry.timestamp).getTime();
@@ -1723,7 +1728,7 @@ function hasRecentDuplicateDispatch(ctx, args) {
1723
1728
  return { duplicate: false };
1724
1729
  }
1725
1730
  function buildMissingNodeReadChatRecovery(ctx, args) {
1726
- const entries = (0, import_daemon_core2.readLedgerEntries)(ctx.mesh.id, { tail: 300 });
1731
+ const entries = (0, import_daemon_core3.readLedgerEntries)(ctx.mesh.id, { tail: 300 });
1727
1732
  const relatedEntries = entries.filter((entry) => entry.nodeId === args.node_id || entry.sessionId === args.session_id);
1728
1733
  const completedEntries = relatedEntries.filter((entry) => entry.kind === "task_completed");
1729
1734
  const lastDispatch = [...relatedEntries].reverse().find((entry) => entry.kind === "task_dispatched");
@@ -1843,7 +1848,7 @@ function readFinalAssistantTranscriptEvidence(payload) {
1843
1848
  }
1844
1849
  function findNodeSession(nodes, nodeId, sessionId) {
1845
1850
  if (!nodeId || !sessionId) return {};
1846
- const node = nodes.find((candidate) => (0, import_daemon_core2.meshNodeIdMatches)(candidate, nodeId));
1851
+ const node = nodes.find((candidate) => (0, import_daemon_core3.meshNodeIdMatches)(candidate, nodeId));
1847
1852
  if (!node) return {};
1848
1853
  const sessions = Array.isArray(node.sessions) ? node.sessions : [];
1849
1854
  const session = sessions.find((candidate) => readSessionRecordId(candidate) === sessionId);
@@ -1914,7 +1919,7 @@ async function reconcileDirectDispatchesFromTranscriptEvidence(ctx, liveNodes, d
1914
1919
  if (payload?.success === false) continue;
1915
1920
  const evidence = readFinalAssistantTranscriptEvidence(payload);
1916
1921
  if (!evidence.finalSummary) continue;
1917
- const result = (0, import_daemon_core2.reconcileDirectDispatchCompletionFromTranscript)({
1922
+ const result = (0, import_daemon_core3.reconcileDirectDispatchCompletionFromTranscript)({
1918
1923
  meshId: ctx.mesh.id,
1919
1924
  nodeId,
1920
1925
  sessionId,
@@ -2092,7 +2097,7 @@ function extractLaunchPayload(value) {
2092
2097
  function classifyMeshLaunchFailure(error) {
2093
2098
  const message = error instanceof Error ? error.message : String(error || "launch failed");
2094
2099
  const lower = message.toLowerCase();
2095
- const p2pClassification = (0, import_daemon_core2.classifyP2pRelayFailure)(error, { command: "launch_cli" });
2100
+ const p2pClassification = (0, import_daemon_core3.classifyP2pRelayFailure)(error, { command: "launch_cli" });
2096
2101
  if (p2pClassification.recoverable) {
2097
2102
  return p2pClassification;
2098
2103
  }
@@ -2167,7 +2172,7 @@ function buildRecoverableLaunchFailure(ctx, node, providerType, error) {
2167
2172
  function recordRecoverableLaunchFailure(ctx, node, providerType, error) {
2168
2173
  const failure = buildRecoverableLaunchFailure(ctx, node, providerType, error);
2169
2174
  try {
2170
- (0, import_daemon_core2.appendLedgerEntry)(ctx.mesh.id, {
2175
+ (0, import_daemon_core3.appendLedgerEntry)(ctx.mesh.id, {
2171
2176
  kind: "recovery_attempted",
2172
2177
  nodeId: node.id,
2173
2178
  providerType,
@@ -2181,7 +2186,7 @@ function recordRecoverableLaunchFailure(ctx, node, providerType, error) {
2181
2186
  return failure;
2182
2187
  }
2183
2188
  function getLatestActiveLaunchFailure(meshId, nodeId) {
2184
- const entries = (0, import_daemon_core2.readLedgerEntries)(meshId, { tail: 200 });
2189
+ const entries = (0, import_daemon_core3.readLedgerEntries)(meshId, { tail: 200 });
2185
2190
  for (let i = entries.length - 1; i >= 0; i -= 1) {
2186
2191
  const entry = entries[i];
2187
2192
  if (entry.nodeId !== nodeId) continue;
@@ -2193,7 +2198,7 @@ function getLatestActiveLaunchFailure(meshId, nodeId) {
2193
2198
  return null;
2194
2199
  }
2195
2200
  function buildCoordinatorP2pRelayFailure(error, context) {
2196
- const payload = (0, import_daemon_core2.buildP2pRelayFailurePayload)(error, {
2201
+ const payload = (0, import_daemon_core3.buildP2pRelayFailurePayload)(error, {
2197
2202
  command: context.command,
2198
2203
  targetDaemonId: context.targetDaemonId
2199
2204
  });
@@ -2374,7 +2379,7 @@ function rememberMeshSessionProviderMetadataFromEvent(event) {
2374
2379
  });
2375
2380
  }
2376
2381
  function resolveMeshSessionProviderMetadataFromLedger(ctx, nodeId, runtimeSessionId) {
2377
- const entries = (0, import_daemon_core2.readLedgerEntries)(ctx.mesh.id, { tail: 50 });
2382
+ const entries = (0, import_daemon_core3.readLedgerEntries)(ctx.mesh.id, { tail: 50 });
2378
2383
  for (let i = entries.length - 1; i >= 0; i -= 1) {
2379
2384
  const entry = entries[i];
2380
2385
  const payload = entry.payload && typeof entry.payload === "object" && !Array.isArray(entry.payload) ? entry.payload : {};
@@ -2481,12 +2486,12 @@ function readProviderPriority(policy) {
2481
2486
  }
2482
2487
  function buildNodeCapabilityExposure(node) {
2483
2488
  const providers = readProviderPriority(node.policy);
2484
- const capabilityTags = (0, import_daemon_core2.buildMeshNodeCapabilityTags)(node);
2489
+ const capabilityTags = (0, import_daemon_core3.buildMeshNodeCapabilityTags)(node);
2485
2490
  const exposure = { capabilityTags };
2486
2491
  if (providers.length) {
2487
2492
  const byProvider = {};
2488
2493
  for (const provider of providers) {
2489
- byProvider[provider] = (0, import_daemon_core2.buildMeshNodeCapabilityTags)(node, provider);
2494
+ byProvider[provider] = (0, import_daemon_core3.buildMeshNodeCapabilityTags)(node, provider);
2490
2495
  }
2491
2496
  exposure.capabilityTagsByProvider = byProvider;
2492
2497
  }
@@ -2827,12 +2832,12 @@ async function drainCoordinatorPendingEvents(ctx, opts) {
2827
2832
  }
2828
2833
  return surfacedEvents;
2829
2834
  }
2830
- const events = (0, import_daemon_core2.drainPendingMeshCoordinatorEvents)(ctx.mesh.id, ctx.localDaemonId).filter(matchesCurrentMesh);
2835
+ const events = (0, import_daemon_core3.drainPendingMeshCoordinatorEvents)(ctx.mesh.id, ctx.localDaemonId).filter(matchesCurrentMesh);
2831
2836
  events.forEach(rememberMeshSessionProviderMetadataFromEvent);
2832
2837
  return events;
2833
2838
  }
2834
2839
  function isP2pTransportUnavailableError(error) {
2835
- return (0, import_daemon_core2.isP2pRelayTransportFailure)(error);
2840
+ return (0, import_daemon_core3.isP2pRelayTransportFailure)(error);
2836
2841
  }
2837
2842
  function buildRemoveNodeArgs(ctx, nodeId, sessionCleanupMode, force) {
2838
2843
  return {
@@ -2851,7 +2856,7 @@ function classifyReadChatTransportCause(error) {
2851
2856
  return "saturated";
2852
2857
  }
2853
2858
  function resolveCachedMeshSessionPreviewFromLedger(ctx, nodeId, sessionId) {
2854
- const entries = (0, import_daemon_core2.readLedgerEntries)(ctx.mesh.id, { tail: 200 });
2859
+ const entries = (0, import_daemon_core3.readLedgerEntries)(ctx.mesh.id, { tail: 200 });
2855
2860
  for (let i = entries.length - 1; i >= 0; i -= 1) {
2856
2861
  const entry = entries[i];
2857
2862
  const payload = entry.payload && typeof entry.payload === "object" && !Array.isArray(entry.payload) ? entry.payload : {};
@@ -2860,7 +2865,7 @@ function resolveCachedMeshSessionPreviewFromLedger(ctx, nodeId, sessionId) {
2860
2865
  const entrySessionId = readString(entry.sessionId) || readString(payload.targetSessionId) || readString(payload.sessionId) || readString(payload.instanceId);
2861
2866
  if (entrySessionId !== sessionId) continue;
2862
2867
  const metadataEvent = payload.metadataEvent && typeof payload.metadataEvent === "object" && !Array.isArray(payload.metadataEvent) ? payload.metadataEvent : payload;
2863
- const preview = (0, import_daemon_core2.resolveMeshSurfacedSessionPreview)(metadataEvent);
2868
+ const preview = (0, import_daemon_core3.resolveMeshSurfacedSessionPreview)(metadataEvent);
2864
2869
  if (preview) {
2865
2870
  return { ...preview, ledgerKind: entry.kind, timestamp: entry.timestamp };
2866
2871
  }
@@ -2868,7 +2873,7 @@ function resolveCachedMeshSessionPreviewFromLedger(ctx, nodeId, sessionId) {
2868
2873
  return void 0;
2869
2874
  }
2870
2875
  function buildMeshReadChatCacheFallback(ctx, args, node, error) {
2871
- const classification = (0, import_daemon_core2.classifyP2pRelayFailure)(error, { command: "read_chat", targetDaemonId: node.daemonId });
2876
+ const classification = (0, import_daemon_core3.classifyP2pRelayFailure)(error, { command: "read_chat", targetDaemonId: node.daemonId });
2872
2877
  const cause = classifyReadChatTransportCause(error);
2873
2878
  const errorMessage = error instanceof Error ? error.message : String(error ?? "");
2874
2879
  const causeNote = cause === "not_connected" ? "the worker daemon is not currently connected over P2P (no live channel)" : "the worker daemon is connected but saturated \u2014 it acknowledged the request but did not return the transcript within the deadline";
@@ -2927,12 +2932,12 @@ function resolveRefineConfigNode(ctx, nodeId) {
2927
2932
 
2928
2933
  // src/tools/mesh-tools-status.ts
2929
2934
  async function meshStatus(ctx, args = {}) {
2930
- const rateResult = (0, import_daemon_core3.recordMeshToolCall)({ meshId: ctx.mesh.id, tool: "mesh_status" });
2935
+ const rateResult = (0, import_daemon_core4.recordMeshToolCall)({ meshId: ctx.mesh.id, tool: "mesh_status" });
2931
2936
  const compact = args.verbose === true ? false : args.compact ?? true;
2932
2937
  await refreshMeshFromDaemon(ctx);
2933
2938
  const { mesh, transport } = ctx;
2934
- let ledgerSummary = (0, import_daemon_core3.getLedgerSummary)(mesh.id);
2935
- const schedulingRuntime = (0, import_daemon_core3.buildMeshSchedulingRuntime)(mesh, (0, import_daemon_core3.getQueue)(mesh.id));
2939
+ let ledgerSummary = (0, import_daemon_core4.getLedgerSummary)(mesh.id);
2940
+ const schedulingRuntime = (0, import_daemon_core4.buildMeshSchedulingRuntime)(mesh, (0, import_daemon_core4.getQueue)(mesh.id));
2936
2941
  const schedulingByNode = new Map(schedulingRuntime.nodes.map((n) => [n.nodeId, n]));
2937
2942
  const results = await Promise.all(mesh.nodes.map(async (node) => {
2938
2943
  const entry = {
@@ -2994,14 +2999,14 @@ async function meshStatus(ctx, args = {}) {
2994
2999
  noFallbackReason: failure.noFallbackReason
2995
3000
  });
2996
3001
  }
2997
- entry.dataFreshness = (0, import_daemon_core3.buildMeshNodeProbeFreshness)({
3002
+ entry.dataFreshness = (0, import_daemon_core4.buildMeshNodeProbeFreshness)({
2998
3003
  git: entry.git,
2999
3004
  liveTruthProbed,
3000
3005
  isSelfNode: entry.machine?.sameMachine === true,
3001
3006
  daemonId: readNodeDaemonId(node),
3002
3007
  node
3003
3008
  });
3004
- const recoveryContext = (0, import_daemon_core3.getSessionRecoveryContext)(mesh.id, { nodeId: node.id });
3009
+ const recoveryContext = (0, import_daemon_core4.getSessionRecoveryContext)(mesh.id, { nodeId: node.id });
3005
3010
  if (recoveryContext.consecutiveNodeFailures > 0) {
3006
3011
  entry.recoveryHints = {
3007
3012
  consecutiveFailures: recoveryContext.consecutiveNodeFailures,
@@ -3073,23 +3078,23 @@ async function meshStatus(ctx, args = {}) {
3073
3078
  }
3074
3079
  return entry;
3075
3080
  }));
3076
- let ledgerEntries = (0, import_daemon_core3.readLedgerEntries)(mesh.id, { tail: 200 });
3077
- let directDispatches = (0, import_daemon_core3.getActiveDirectDispatches)(mesh.id);
3081
+ let ledgerEntries = (0, import_daemon_core4.readLedgerEntries)(mesh.id, { tail: 200 });
3082
+ let directDispatches = (0, import_daemon_core4.getActiveDirectDispatches)(mesh.id);
3078
3083
  const directReconciliation = await reconcileDirectDispatchesFromTranscriptEvidence(ctx, results, directDispatches, ledgerEntries);
3079
3084
  if (directReconciliation.reconciled > 0) {
3080
- ledgerEntries = (0, import_daemon_core3.readLedgerEntries)(mesh.id, { tail: 200 });
3081
- directDispatches = (0, import_daemon_core3.getActiveDirectDispatches)(mesh.id);
3082
- ledgerSummary = (0, import_daemon_core3.getLedgerSummary)(mesh.id);
3085
+ ledgerEntries = (0, import_daemon_core4.readLedgerEntries)(mesh.id, { tail: 200 });
3086
+ directDispatches = (0, import_daemon_core4.getActiveDirectDispatches)(mesh.id);
3087
+ ledgerSummary = (0, import_daemon_core4.getLedgerSummary)(mesh.id);
3083
3088
  }
3084
- const activeWorkEvidence = (0, import_daemon_core3.buildMeshActiveWork)({
3089
+ const activeWorkEvidence = (0, import_daemon_core4.buildMeshActiveWork)({
3085
3090
  meshId: mesh.id,
3086
- queue: (0, import_daemon_core3.getQueue)(mesh.id),
3091
+ queue: (0, import_daemon_core4.getQueue)(mesh.id),
3087
3092
  ledgerEntries,
3088
3093
  directDispatches,
3089
3094
  nodes: results
3090
3095
  });
3091
3096
  const pollingGuidance = buildActiveWorkPollingGuidance(activeWorkEvidence.summary);
3092
- const staleDirectWorkSummary = (0, import_daemon_core3.buildCompactStaleDirectWorkSummary)(activeWorkEvidence.staleDirectWork, {
3097
+ const staleDirectWorkSummary = (0, import_daemon_core4.buildCompactStaleDirectWorkSummary)(activeWorkEvidence.staleDirectWork, {
3093
3098
  note: activeWorkEvidence.staleDirectWorkNote,
3094
3099
  detailHint: "Full stale direct entries are omitted from mesh_status by default. Call mesh_status with includeStaleDirectWorkDetails=true or inspect mesh_task_history for ledger detail."
3095
3100
  });
@@ -3289,7 +3294,7 @@ async function meshStatus(ctx, args = {}) {
3289
3294
  }
3290
3295
  try {
3291
3296
  if (compact) {
3292
- const { live, historyFold } = (0, import_daemon_core3.getMeshStatusMissionsCompact)(mesh.id);
3297
+ const { live, historyFold } = (0, import_daemon_core4.getMeshStatusMissionsCompact)(mesh.id);
3293
3298
  const ranked = [...live].sort((a, b) => String(b.tasks?.lastActivityAt ?? "").localeCompare(String(a.tasks?.lastActivityAt ?? "")));
3294
3299
  const kept = [];
3295
3300
  const overflow = [];
@@ -3316,11 +3321,11 @@ async function meshStatus(ctx, args = {}) {
3316
3321
  }
3317
3322
  if (historyFold) response.missionsHistory = historyFold;
3318
3323
  } else {
3319
- const missions = (0, import_daemon_core3.getMeshStatusMissionSummaries)(mesh.id, { verbose: true });
3324
+ const missions = (0, import_daemon_core4.getMeshStatusMissionSummaries)(mesh.id, { verbose: true });
3320
3325
  if (missions.length > 0) {
3321
3326
  response.missions = missions.map((mission) => {
3322
3327
  try {
3323
- return { ...mission, stats: (0, import_daemon_core3.computeMeshMissionStats)(mesh.id, mission.id) };
3328
+ return { ...mission, stats: (0, import_daemon_core4.computeMeshMissionStats)(mesh.id, mission.id) };
3324
3329
  } catch {
3325
3330
  return mission;
3326
3331
  }
@@ -3331,14 +3336,14 @@ async function meshStatus(ctx, args = {}) {
3331
3336
  }
3332
3337
  try {
3333
3338
  const pendingEvents = await drainCoordinatorPendingEvents(ctx);
3334
- const asyncRefineJobs = (0, import_daemon_core3.buildMeshAsyncRefineJobs)({
3339
+ const asyncRefineJobs = (0, import_daemon_core4.buildMeshAsyncRefineJobs)({
3335
3340
  meshId: mesh.id,
3336
3341
  ledgerEntries,
3337
3342
  pendingEvents
3338
3343
  });
3339
3344
  if (asyncRefineJobs.length > 0) {
3340
3345
  if (compact) {
3341
- const summary = (0, import_daemon_core3.summarizeMeshAsyncRefineJobs)(asyncRefineJobs);
3346
+ const summary = (0, import_daemon_core4.summarizeMeshAsyncRefineJobs)(asyncRefineJobs);
3342
3347
  if (summary.activeJobs.length > 0) response.asyncRefineJobs = summary.activeJobs;
3343
3348
  response.asyncRefineJobsSummary = {
3344
3349
  total: summary.total,
@@ -3382,14 +3387,15 @@ async function meshListNodes(ctx) {
3382
3387
  // src/tools/mesh-tools-queue.ts
3383
3388
  async function meshEnqueueTask(ctx, args) {
3384
3389
  const taskMode = readString(args.task_mode) || readString(args.taskMode);
3385
- const requiredTags = (0, import_daemon_core3.normalizeMeshCapabilityTags)(Array.isArray(args.requiredTags) ? args.requiredTags : args.required_tags);
3390
+ const readonly = args.readonly === true || args.read_only === true;
3391
+ const requiredTags = (0, import_daemon_core4.normalizeMeshCapabilityTags)(Array.isArray(args.requiredTags) ? args.requiredTags : args.required_tags);
3386
3392
  const dependsOn = Array.isArray(args.dependsOn) ? args.dependsOn : Array.isArray(args.depends_on) ? args.depends_on : void 0;
3387
3393
  const missionId = readString(args.missionId) || readString(args.mission_id) || void 0;
3388
3394
  const explicitTargetRaw = readString(args.targetNodeId) || readString(args.target_node_id) || readString(args.targetNode) || readString(args.target_node) || void 0;
3389
3395
  const preferWorktree = args.preferWorktree === true || args.prefer_worktree === true;
3390
3396
  let targetNodeId;
3391
3397
  if (explicitTargetRaw) {
3392
- const matched = ctx.mesh.nodes.find((n) => (0, import_daemon_core3.meshNodeIdMatches)(n, explicitTargetRaw));
3398
+ const matched = ctx.mesh.nodes.find((n) => (0, import_daemon_core4.meshNodeIdMatches)(n, explicitTargetRaw));
3393
3399
  if (!matched) {
3394
3400
  return JSON.stringify({
3395
3401
  success: false,
@@ -3404,7 +3410,7 @@ async function meshEnqueueTask(ctx, args) {
3404
3410
  targetNodeId = resolvePreferredWorktreeNodeId(ctx) || void 0;
3405
3411
  }
3406
3412
  try {
3407
- const task = (0, import_daemon_core3.enqueueTask)(ctx.mesh.id, args.message, { taskMode, requiredTags, dependsOn, missionId, targetNodeId, ...ctx.coordinatorSessionId ? { sourceCoordinatorSessionId: ctx.coordinatorSessionId } : {} });
3413
+ const task = (0, import_daemon_core4.enqueueTask)(ctx.mesh.id, args.message, { taskMode, ...readonly ? { readonly: true } : {}, requiredTags, dependsOn, missionId, targetNodeId, ...ctx.coordinatorSessionId ? { sourceCoordinatorSessionId: ctx.coordinatorSessionId } : {} });
3408
3414
  if (!(ctx.transport instanceof IpcTransport)) {
3409
3415
  const queueTrigger = await triggerMeshQueueAndReport(ctx);
3410
3416
  return JSON.stringify({
@@ -3428,7 +3434,7 @@ async function meshEnqueueTask(ctx, args) {
3428
3434
  const isLocalNode = isLocalControlPlaneNode(ctx, node);
3429
3435
  if (isLocalNode || !node.daemonId) continue;
3430
3436
  if (targetNodeId && node.id !== targetNodeId) continue;
3431
- if (!(0, import_daemon_core3.nodeSatisfiesRequiredTags)(requiredTags, (0, import_daemon_core3.buildMeshNodeCapabilityTags)(node))) continue;
3437
+ if (!(0, import_daemon_core4.nodeSatisfiesRequiredTags)(requiredTags, (0, import_daemon_core4.buildMeshNodeCapabilityTags)(node))) continue;
3432
3438
  dispatchPromises.push(
3433
3439
  ipcDispatchToRemoteAgent(ctx, node, {
3434
3440
  message: args.message,
@@ -3443,7 +3449,7 @@ async function meshEnqueueTask(ctx, args) {
3443
3449
  try {
3444
3450
  const providerType = result.providerType;
3445
3451
  const descriptor = summarizeTaskMessage(args.message);
3446
- (0, import_daemon_core3.appendLedgerEntry)(ctx.mesh.id, {
3452
+ (0, import_daemon_core4.appendLedgerEntry)(ctx.mesh.id, {
3447
3453
  kind: "task_dispatched",
3448
3454
  nodeId: node.id,
3449
3455
  sessionId: result.sessionId,
@@ -3465,7 +3471,7 @@ async function meshEnqueueTask(ctx, args) {
3465
3471
  }
3466
3472
  }).catch((err) => {
3467
3473
  try {
3468
- (0, import_daemon_core3.appendLedgerEntry)(ctx.mesh.id, {
3474
+ (0, import_daemon_core4.appendLedgerEntry)(ctx.mesh.id, {
3469
3475
  kind: "p2p_dispatch_failed",
3470
3476
  nodeId: node.id,
3471
3477
  payload: {
@@ -3508,17 +3514,17 @@ async function meshEnqueueTask(ctx, args) {
3508
3514
  }
3509
3515
  }
3510
3516
  async function meshViewQueue(ctx, args) {
3511
- const rateResult = (0, import_daemon_core3.recordMeshToolCall)({ meshId: ctx.mesh.id, tool: "mesh_view_queue" });
3517
+ const rateResult = (0, import_daemon_core4.recordMeshToolCall)({ meshId: ctx.mesh.id, tool: "mesh_view_queue" });
3512
3518
  const compact = args.verbose === true ? false : args.compact ?? true;
3513
3519
  try {
3514
3520
  await refreshMeshFromDaemon(ctx);
3515
3521
  const statusFilter = sanitizeQueueStatusFilter(args.status);
3516
3522
  const view = normalizeQueueViewMode(args.view);
3517
- const rawQueue = (0, import_daemon_core3.getQueue)(ctx.mesh.id);
3523
+ const rawQueue = (0, import_daemon_core4.getQueue)(ctx.mesh.id);
3518
3524
  const statusById = new Map(rawQueue.map((task) => [task.id, task.status]));
3519
3525
  const withDependencies = rawQueue.map((task) => {
3520
3526
  if (!Array.isArray(task.dependsOn) || task.dependsOn.length === 0) return task;
3521
- const depState = (0, import_daemon_core3.describeTaskDependencyState)(task, statusById);
3527
+ const depState = (0, import_daemon_core4.describeTaskDependencyState)(task, statusById);
3522
3528
  return { ...task, ...depState };
3523
3529
  });
3524
3530
  const fullQueue = prioritizeActiveQueueRows(annotateQueueStaleness(withDependencies, ctx.mesh));
@@ -3527,16 +3533,16 @@ async function meshViewQueue(ctx, args) {
3527
3533
  const visibleSummary = buildQueueStatusSummary(queue);
3528
3534
  const maintenance = buildQueueMaintenanceReport(fullQueue);
3529
3535
  const liveNodes = await collectMeshViewQueueNodesWithLiveSessions(ctx);
3530
- let ledgerEntries = (0, import_daemon_core3.readLedgerEntries)(ctx.mesh.id, { tail: 200 });
3531
- let directDispatches = (0, import_daemon_core3.getActiveDirectDispatches)(ctx.mesh.id);
3536
+ let ledgerEntries = (0, import_daemon_core4.readLedgerEntries)(ctx.mesh.id, { tail: 200 });
3537
+ let directDispatches = (0, import_daemon_core4.getActiveDirectDispatches)(ctx.mesh.id);
3532
3538
  const directReconciliation = await reconcileDirectDispatchesFromTranscriptEvidence(ctx, liveNodes, directDispatches, ledgerEntries);
3533
3539
  if (directReconciliation.reconciled > 0) {
3534
- ledgerEntries = (0, import_daemon_core3.readLedgerEntries)(ctx.mesh.id, { tail: 200 });
3535
- directDispatches = (0, import_daemon_core3.getActiveDirectDispatches)(ctx.mesh.id);
3540
+ ledgerEntries = (0, import_daemon_core4.readLedgerEntries)(ctx.mesh.id, { tail: 200 });
3541
+ directDispatches = (0, import_daemon_core4.getActiveDirectDispatches)(ctx.mesh.id);
3536
3542
  }
3537
- (0, import_daemon_core3.markStaleDirectDispatches)(ctx.mesh.id);
3538
- directDispatches = (0, import_daemon_core3.getActiveDirectDispatches)(ctx.mesh.id);
3539
- const activeWorkEvidence = (0, import_daemon_core3.buildMeshActiveWork)({
3543
+ (0, import_daemon_core4.markStaleDirectDispatches)(ctx.mesh.id);
3544
+ directDispatches = (0, import_daemon_core4.getActiveDirectDispatches)(ctx.mesh.id);
3545
+ const activeWorkEvidence = (0, import_daemon_core4.buildMeshActiveWork)({
3540
3546
  meshId: ctx.mesh.id,
3541
3547
  queue: fullQueue,
3542
3548
  ledgerEntries,
@@ -3561,7 +3567,7 @@ async function meshViewQueue(ctx, args) {
3561
3567
  const wantActiveQueueArray = view === "active" || statusFilter?.some((status) => ACTIVE_QUEUE_STATUSES.has(status));
3562
3568
  const wantHistoricalQueueArray = !compact && (view === "historical" || requestedHistoricalRows);
3563
3569
  const activeWorkResult = compact ? compactActiveWorkRecords(activeWorkEvidence.activeWork) : { records: activeWorkEvidence.activeWork, omitted: 0 };
3564
- const staleDirectWorkSummary = (0, import_daemon_core3.buildCompactStaleDirectWorkSummary)(activeWorkEvidence.staleDirectWork, {
3570
+ const staleDirectWorkSummary = (0, import_daemon_core4.buildCompactStaleDirectWorkSummary)(activeWorkEvidence.staleDirectWork, {
3565
3571
  note: activeWorkEvidence.staleDirectWorkNote,
3566
3572
  detailHint: "Full stale direct entries are omitted from mesh_view_queue in compact mode. Call mesh_view_queue with verbose=true, or inspect mesh_task_history for ledger detail."
3567
3573
  });
@@ -3636,12 +3642,12 @@ async function meshQueueCancel(ctx, args) {
3636
3642
  try {
3637
3643
  const taskId = (args.task_id || args.taskId || "").trim();
3638
3644
  if (!taskId) return JSON.stringify({ success: false, error: "task_id required" });
3639
- const preCancel = (0, import_daemon_core3.getQueue)(ctx.mesh.id).find((t) => t?.id === taskId);
3645
+ const preCancel = (0, import_daemon_core4.getQueue)(ctx.mesh.id).find((t) => t?.id === taskId);
3640
3646
  const wasAssigned = preCancel?.status === "assigned";
3641
3647
  const assignedSessionId = readString(preCancel?.assignedSessionId) || void 0;
3642
3648
  const assignedNodeId = readString(preCancel?.assignedNodeId) || void 0;
3643
3649
  const assignedProviderType = readString(preCancel?.assignedProviderType) || void 0;
3644
- const task = (0, import_daemon_core3.cancelTask)(ctx.mesh.id, taskId, { reason: args.reason });
3650
+ const task = (0, import_daemon_core4.cancelTask)(ctx.mesh.id, taskId, { reason: args.reason });
3645
3651
  if (!task) return JSON.stringify({ success: false, error: `Queue task '${taskId}' not found` });
3646
3652
  ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
3647
3653
  });
@@ -3680,7 +3686,7 @@ async function meshQueueRequeue(ctx, args) {
3680
3686
  const targetNodeId = (args.target_node_id || args.targetNodeId || "").trim() || void 0;
3681
3687
  const targetSessionId = (args.target_session_id || args.targetSessionId || "").trim() || void 0;
3682
3688
  const keepTargetSession = args.keep_target_session === true || args.keepTargetSession === true;
3683
- const task = (0, import_daemon_core3.requeueTask)(ctx.mesh.id, taskId, {
3689
+ const task = (0, import_daemon_core4.requeueTask)(ctx.mesh.id, taskId, {
3684
3690
  reason: args.reason,
3685
3691
  targetNodeId,
3686
3692
  targetSessionId,
@@ -3719,17 +3725,17 @@ async function meshTaskHistory(ctx, args) {
3719
3725
  const compactCap = requestedTail > 50 ? 20 : 30;
3720
3726
  const tail = compact ? Math.min(requestedTail, compactCap) : Math.min(requestedTail, 200);
3721
3727
  const kind = typeof args.kind === "string" && args.kind.trim() ? [args.kind.trim()] : void 0;
3722
- const rawEntries = (0, import_daemon_core3.readLedgerEntries)(mesh.id, { tail, kind });
3728
+ const rawEntries = (0, import_daemon_core4.readLedgerEntries)(mesh.id, { tail, kind });
3723
3729
  const entries = compact ? rawEntries.map((e) => ({
3724
3730
  ...e,
3725
3731
  payload: e.payload ? slimLedgerPayload(e.payload) : e.payload
3726
3732
  })) : rawEntries;
3727
- const summary = (0, import_daemon_core3.getLedgerSummary)(mesh.id);
3733
+ const summary = (0, import_daemon_core4.getLedgerSummary)(mesh.id);
3728
3734
  let taskStats;
3729
3735
  try {
3730
3736
  const taskIds = [...new Set(rawEntries.map((e) => typeof e.payload?.taskId === "string" ? e.payload.taskId : "").filter(Boolean))];
3731
3737
  if (taskIds.length > 0) {
3732
- const stats = (0, import_daemon_core3.computeMeshTaskStats)(mesh.id, { taskIds });
3738
+ const stats = (0, import_daemon_core4.computeMeshTaskStats)(mesh.id, { taskIds });
3733
3739
  if (stats.length > 0) taskStats = stats;
3734
3740
  }
3735
3741
  } catch {
@@ -3752,7 +3758,7 @@ async function meshRecordNote(ctx, args) {
3752
3758
  const category = args.category === "provider_quirk" || args.category === "pattern_to_avoid" || args.category === "recovery_lesson" ? args.category : void 0;
3753
3759
  const createdAt = (/* @__PURE__ */ new Date()).toISOString();
3754
3760
  const sourceCoordinator = ctx.coordinatorSessionId || ctx.localDaemonId || ctx.coordinatorHostname || void 0;
3755
- const entry = (0, import_daemon_core3.appendLedgerEntry)(mesh.id, {
3761
+ const entry = (0, import_daemon_core4.appendLedgerEntry)(mesh.id, {
3756
3762
  kind: "coordinator_operating_note",
3757
3763
  ...sourceCoordinator ? { sessionId: sourceCoordinator } : {},
3758
3764
  payload: {
@@ -3785,8 +3791,8 @@ async function meshReconcileLedger(ctx, args) {
3785
3791
  for (const node of nodes) {
3786
3792
  try {
3787
3793
  if (isLocalControlPlaneNode(ctx, node) || !node.daemonId) {
3788
- const slice2 = (0, import_daemon_core3.readLedgerSliceFromStore)(ctx.mesh.id, queryArgs);
3789
- replicas.push((0, import_daemon_core3.buildMeshLedgerReplicaEvidence)({
3794
+ const slice2 = (0, import_daemon_core4.readLedgerSliceFromStore)(ctx.mesh.id, queryArgs);
3795
+ replicas.push((0, import_daemon_core4.buildMeshLedgerReplicaEvidence)({
3790
3796
  nodeId: node.id,
3791
3797
  daemonId: node.daemonId,
3792
3798
  transport: "local",
@@ -3804,8 +3810,8 @@ async function meshReconcileLedger(ctx, args) {
3804
3810
  if (slice?.protocol !== "adhdev.mesh.ledger.slice.v1" || !Array.isArray(slice.entries)) {
3805
3811
  throw new Error("remote daemon returned an invalid ledger slice payload");
3806
3812
  }
3807
- const importResult = shouldImport ? (0, import_daemon_core3.appendRemoteLedgerEntries)(ctx.mesh.id, slice.entries) : { accepted: 0, skippedDuplicate: 0, rejectedInvalid: 0, entries: [] };
3808
- replicas.push((0, import_daemon_core3.buildMeshLedgerReplicaEvidence)({
3813
+ const importResult = shouldImport ? (0, import_daemon_core4.appendRemoteLedgerEntries)(ctx.mesh.id, slice.entries) : { accepted: 0, skippedDuplicate: 0, rejectedInvalid: 0, entries: [] };
3814
+ replicas.push((0, import_daemon_core4.buildMeshLedgerReplicaEvidence)({
3809
3815
  nodeId: node.id,
3810
3816
  daemonId: node.daemonId,
3811
3817
  transport: "p2p_datachannel",
@@ -3813,7 +3819,7 @@ async function meshReconcileLedger(ctx, args) {
3813
3819
  importResult
3814
3820
  }));
3815
3821
  if (shouldImport && importResult.accepted > 0) {
3816
- (0, import_daemon_core3.appendLedgerEntry)(ctx.mesh.id, {
3822
+ (0, import_daemon_core4.appendLedgerEntry)(ctx.mesh.id, {
3817
3823
  kind: "ledger_replicated",
3818
3824
  nodeId: node.id,
3819
3825
  payload: {
@@ -3827,7 +3833,7 @@ async function meshReconcileLedger(ctx, args) {
3827
3833
  });
3828
3834
  }
3829
3835
  } catch (e) {
3830
- replicas.push((0, import_daemon_core3.buildMeshLedgerReplicaEvidence)({
3836
+ replicas.push((0, import_daemon_core4.buildMeshLedgerReplicaEvidence)({
3831
3837
  nodeId: node.id,
3832
3838
  daemonId: node.daemonId,
3833
3839
  transport: node.daemonId ? "p2p_datachannel" : "local",
@@ -3836,8 +3842,8 @@ async function meshReconcileLedger(ctx, args) {
3836
3842
  }));
3837
3843
  }
3838
3844
  }
3839
- const evidence = (0, import_daemon_core3.buildMeshLedgerReconciliationEvidence)(ctx.mesh.id, replicas);
3840
- (0, import_daemon_core3.appendLedgerEntry)(ctx.mesh.id, {
3845
+ const evidence = (0, import_daemon_core4.buildMeshLedgerReconciliationEvidence)(ctx.mesh.id, replicas);
3846
+ (0, import_daemon_core4.appendLedgerEntry)(ctx.mesh.id, {
3841
3847
  kind: "ledger_reconciled",
3842
3848
  payload: {
3843
3849
  protocol: evidence.protocol,
@@ -3850,7 +3856,7 @@ async function meshReconcileLedger(ctx, args) {
3850
3856
  }
3851
3857
  async function meshMissionUpsert(ctx, args) {
3852
3858
  try {
3853
- const mission = (0, import_daemon_core3.upsertMeshMission)(ctx.mesh.id, {
3859
+ const mission = (0, import_daemon_core4.upsertMeshMission)(ctx.mesh.id, {
3854
3860
  id: readString(args.mission_id) || readString(args.missionId) || void 0,
3855
3861
  title: args.title,
3856
3862
  goal: typeof args.goal === "string" ? args.goal : void 0,
@@ -3870,21 +3876,21 @@ async function meshMissionUpsert(ctx, args) {
3870
3876
  async function meshMissionList(ctx, args = {}) {
3871
3877
  try {
3872
3878
  const rawStatuses = Array.isArray(args.status) ? args.status : typeof args.status === "string" && args.status.trim() ? [args.status] : [];
3873
- const invalid = rawStatuses.filter((s) => !import_daemon_core3.MESH_MISSION_STATUSES.includes(s));
3879
+ const invalid = rawStatuses.filter((s) => !import_daemon_core4.MESH_MISSION_STATUSES.includes(s));
3874
3880
  if (invalid.length > 0) {
3875
3881
  return JSON.stringify({
3876
3882
  success: false,
3877
3883
  code: "invalid_mission_status",
3878
- error: `invalid status filter: ${invalid.join(", ")} (valid: ${import_daemon_core3.MESH_MISSION_STATUSES.join(", ")})`
3884
+ error: `invalid status filter: ${invalid.join(", ")} (valid: ${import_daemon_core4.MESH_MISSION_STATUSES.join(", ")})`
3879
3885
  });
3880
3886
  }
3881
3887
  const statuses = rawStatuses.length > 0 ? rawStatuses : void 0;
3882
- const missions = (0, import_daemon_core3.listMeshMissionSummaries)(ctx.mesh.id, {
3888
+ const missions = (0, import_daemon_core4.listMeshMissionSummaries)(ctx.mesh.id, {
3883
3889
  statuses,
3884
3890
  verbose: args.verbose === true
3885
3891
  }).map((mission) => {
3886
3892
  try {
3887
- return { ...mission, stats: (0, import_daemon_core3.computeMeshMissionStats)(ctx.mesh.id, mission.id) };
3893
+ return { ...mission, stats: (0, import_daemon_core4.computeMeshMissionStats)(ctx.mesh.id, mission.id) };
3888
3894
  } catch {
3889
3895
  return mission;
3890
3896
  }
@@ -3923,11 +3929,11 @@ async function meshPruneStaleDirect(ctx, args = {}) {
3923
3929
  const execute = args.execute === true && args.dry_run !== true;
3924
3930
  const includeTerminal = args.include_terminal === true;
3925
3931
  const liveNodes = await collectMeshViewQueueNodesWithLiveSessions(ctx);
3926
- const ledgerEntries = (0, import_daemon_core3.readLedgerEntries)(ctx.mesh.id, { tail: 500 });
3927
- const directDispatches = (0, import_daemon_core3.getActiveDirectDispatches)(ctx.mesh.id);
3928
- const result = (0, import_daemon_core3.pruneStaleDirectDispatches)({
3932
+ const ledgerEntries = (0, import_daemon_core4.readLedgerEntries)(ctx.mesh.id, { tail: 500 });
3933
+ const directDispatches = (0, import_daemon_core4.getActiveDirectDispatches)(ctx.mesh.id);
3934
+ const result = (0, import_daemon_core4.pruneStaleDirectDispatches)({
3929
3935
  meshId: ctx.mesh.id,
3930
- queue: (0, import_daemon_core3.getQueue)(ctx.mesh.id),
3936
+ queue: (0, import_daemon_core4.getQueue)(ctx.mesh.id),
3931
3937
  ledgerEntries,
3932
3938
  directDispatches,
3933
3939
  nodes: liveNodes,
@@ -3968,8 +3974,9 @@ async function meshPruneStaleDirect(ctx, args = {}) {
3968
3974
  }
3969
3975
  async function meshSendTask(ctx, args) {
3970
3976
  const requestedTaskMode = readString(args.task_mode) || readString(args.taskMode);
3977
+ const readonly = args.readonly === true || args.read_only === true;
3971
3978
  const missionId = readString(args.missionId) || readString(args.mission_id) || void 0;
3972
- const modeValidation = (0, import_daemon_core3.validateMeshTaskModeRequest)(requestedTaskMode, args.message);
3979
+ const modeValidation = (0, import_daemon_core4.validateMeshTaskModeRequest)(requestedTaskMode, args.message, readonly);
3973
3980
  if (!modeValidation.valid) {
3974
3981
  return JSON.stringify({
3975
3982
  success: false,
@@ -3999,7 +4006,7 @@ async function meshSendTask(ctx, args) {
3999
4006
  });
4000
4007
  }
4001
4008
  let explicitTargetSession;
4002
- if (args.session_id && isWorkerTaskMode(taskMode)) {
4009
+ if (args.session_id && isWorkerTaskMode(taskMode, readonly)) {
4003
4010
  try {
4004
4011
  const statusResult = await commandForNode(ctx, node, "get_status_metadata", {});
4005
4012
  const sessions = extractStatusMetadataSessions(statusResult);
@@ -4081,7 +4088,7 @@ async function meshSendTask(ctx, args) {
4081
4088
  const dispatchedAt = (/* @__PURE__ */ new Date()).toISOString();
4082
4089
  try {
4083
4090
  const providerType = result2.providerType || cached?.providerType;
4084
- (0, import_daemon_core3.appendLedgerEntry)(ctx.mesh.id, {
4091
+ (0, import_daemon_core4.appendLedgerEntry)(ctx.mesh.id, {
4085
4092
  kind: "task_dispatched",
4086
4093
  nodeId: args.node_id,
4087
4094
  sessionId: dispatchedSessionId,
@@ -4094,7 +4101,7 @@ async function meshSendTask(ctx, args) {
4094
4101
  ...ctx.coordinatorSessionId ? { coordinatorSessionId: ctx.coordinatorSessionId } : {}
4095
4102
  })
4096
4103
  });
4097
- (0, import_daemon_core3.insertDirectDispatch)(ctx.mesh.id, {
4104
+ (0, import_daemon_core4.insertDirectDispatch)(ctx.mesh.id, {
4098
4105
  taskId,
4099
4106
  nodeId: args.node_id,
4100
4107
  sessionId: dispatchedSessionId,
@@ -4105,12 +4112,13 @@ async function meshSendTask(ctx, args) {
4105
4112
  dispatchedAt
4106
4113
  });
4107
4114
  if (missionId) {
4108
- (0, import_daemon_core3.recordDirectDispatchTask)(ctx.mesh.id, args.message, {
4115
+ (0, import_daemon_core4.recordDirectDispatchTask)(ctx.mesh.id, args.message, {
4109
4116
  id: taskId,
4110
4117
  missionId,
4111
4118
  assignedNodeId: args.node_id,
4112
4119
  assignedSessionId: dispatchedSessionId,
4113
4120
  taskMode,
4121
+ ...readonly ? { readonly: true } : {},
4114
4122
  dispatchedAt
4115
4123
  });
4116
4124
  }
@@ -4237,7 +4245,7 @@ async function meshSendTask(ctx, args) {
4237
4245
  const dispatchedAt = (/* @__PURE__ */ new Date()).toISOString();
4238
4246
  const coordinatorDaemonId = resolveCoordinatorDaemonId(ctx);
4239
4247
  try {
4240
- (0, import_daemon_core3.appendLedgerEntry)(ctx.mesh.id, {
4248
+ (0, import_daemon_core4.appendLedgerEntry)(ctx.mesh.id, {
4241
4249
  kind: "task_dispatched",
4242
4250
  nodeId: args.node_id,
4243
4251
  sessionId: args.session_id,
@@ -4253,7 +4261,7 @@ async function meshSendTask(ctx, args) {
4253
4261
  });
4254
4262
  } catch {
4255
4263
  }
4256
- (0, import_daemon_core3.insertDirectDispatch)(ctx.mesh.id, {
4264
+ (0, import_daemon_core4.insertDirectDispatch)(ctx.mesh.id, {
4257
4265
  taskId,
4258
4266
  nodeId: args.node_id,
4259
4267
  sessionId: args.session_id,
@@ -4266,7 +4274,7 @@ async function meshSendTask(ctx, args) {
4266
4274
  });
4267
4275
  let dispatchPreRecorded = false;
4268
4276
  try {
4269
- dispatchPreRecorded = (0, import_daemon_core3.getActiveDirectDispatches)(ctx.mesh.id).some((d) => d.taskId === taskId);
4277
+ dispatchPreRecorded = (0, import_daemon_core4.getActiveDirectDispatches)(ctx.mesh.id).some((d) => d.taskId === taskId);
4270
4278
  } catch {
4271
4279
  }
4272
4280
  const dispatchResult = await commandForNode(ctx, node, "agent_command", {
@@ -4288,7 +4296,7 @@ async function meshSendTask(ctx, args) {
4288
4296
  const dispatchPayload = unwrapCommandPayload(dispatchResult);
4289
4297
  if (dispatchPayload?.success === false || dispatchResult?.success === false) {
4290
4298
  try {
4291
- (0, import_daemon_core3.deleteDirectDispatchesByTaskId)(ctx.mesh.id, [taskId]);
4299
+ (0, import_daemon_core4.deleteDirectDispatchesByTaskId)(ctx.mesh.id, [taskId]);
4292
4300
  } catch {
4293
4301
  }
4294
4302
  dispatchPreRecorded = false;
@@ -4303,12 +4311,13 @@ async function meshSendTask(ctx, args) {
4303
4311
  }
4304
4312
  if (missionId) {
4305
4313
  try {
4306
- (0, import_daemon_core3.recordDirectDispatchTask)(ctx.mesh.id, args.message, {
4314
+ (0, import_daemon_core4.recordDirectDispatchTask)(ctx.mesh.id, args.message, {
4307
4315
  id: taskId,
4308
4316
  missionId,
4309
4317
  assignedNodeId: args.node_id,
4310
4318
  assignedSessionId: args.session_id,
4311
4319
  taskMode,
4320
+ ...readonly ? { readonly: true } : {},
4312
4321
  dispatchedAt
4313
4322
  });
4314
4323
  } catch {
@@ -4347,14 +4356,15 @@ async function meshSendTask(ctx, args) {
4347
4356
  ...computeIdleDispatchAckRisk(sessionWasIdle, dispatchPreRecorded, args.session_id)
4348
4357
  });
4349
4358
  }
4350
- const task = (0, import_daemon_core3.enqueueTask)(ctx.mesh.id, args.message, {
4359
+ const task = (0, import_daemon_core4.enqueueTask)(ctx.mesh.id, args.message, {
4351
4360
  targetNodeId: args.node_id,
4352
4361
  targetSessionId: args.session_id,
4353
4362
  taskMode,
4363
+ ...readonly ? { readonly: true } : {},
4354
4364
  ...missionId ? { missionId } : {}
4355
4365
  });
4356
4366
  const queueTrigger = await triggerMeshQueueAndReport(ctx);
4357
- const pendingEvents = (0, import_daemon_core3.drainPendingMeshCoordinatorEvents)(ctx.mesh.id, ctx.localDaemonId);
4367
+ const pendingEvents = (0, import_daemon_core4.drainPendingMeshCoordinatorEvents)(ctx.mesh.id, ctx.localDaemonId);
4358
4368
  const result = {
4359
4369
  success: true,
4360
4370
  source: "queue",
@@ -4399,7 +4409,7 @@ async function meshReadChat(ctx, args) {
4399
4409
  tailLimit: args.tail ?? 10
4400
4410
  });
4401
4411
  } catch (e) {
4402
- if (isLocalNode || !(0, import_daemon_core3.isP2pRelayTransportFailure)(e)) throw e;
4412
+ if (isLocalNode || !(0, import_daemon_core4.isP2pRelayTransportFailure)(e)) throw e;
4403
4413
  return buildMeshReadChatCacheFallback(ctx, args, node, e);
4404
4414
  }
4405
4415
  const payload = annotateRapidReadChatAdvisory(unwrapCommandPayload(result), {
@@ -4467,7 +4477,7 @@ async function meshLaunchSession(ctx, args) {
4467
4477
  const coordinatorNode = resolveCoordinatorNode(ctx);
4468
4478
  const coordinatorDaemonId = resolveCoordinatorDaemonId(ctx);
4469
4479
  const spawnedSessionVisibility = readSpawnedSessionVisibility(ctx.mesh.policy);
4470
- const delegatedWorkerAutoApprove = (0, import_daemon_core3.resolveDelegatedWorkerAutoApprove)(ctx.mesh.policy, node.policy);
4480
+ const delegatedWorkerAutoApprove = (0, import_daemon_core4.resolveDelegatedWorkerAutoApprove)(ctx.mesh.policy, node.policy);
4471
4481
  const isLocalNode = isLocalControlPlaneNode(ctx, node);
4472
4482
  if (node.daemonId && !isLocalNode && !coordinatorDaemonId) {
4473
4483
  return JSON.stringify(buildMissingCoordinatorDaemonIdFailure(ctx, node, resolvedProviderType), null, 2);
@@ -4543,7 +4553,7 @@ async function meshLaunchSession(ctx, args) {
4543
4553
  });
4544
4554
  }
4545
4555
  try {
4546
- (0, import_daemon_core3.appendLedgerEntry)(ctx.mesh.id, {
4556
+ (0, import_daemon_core4.appendLedgerEntry)(ctx.mesh.id, {
4547
4557
  kind: "session_launched",
4548
4558
  nodeId: args.node_id,
4549
4559
  sessionId: runtimeSessionId || void 0,
@@ -4724,7 +4734,7 @@ async function meshCheckpoint(ctx, args) {
4724
4734
  includeUntracked: true
4725
4735
  });
4726
4736
  try {
4727
- (0, import_daemon_core3.appendLedgerEntry)(ctx.mesh.id, {
4737
+ (0, import_daemon_core4.appendLedgerEntry)(ctx.mesh.id, {
4728
4738
  kind: "checkpoint_created",
4729
4739
  nodeId: args.node_id,
4730
4740
  payload: {