@adhdev/daemon-standalone 1.0.56-rc.4 → 1.0.56-rc.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/daemon-standalone",
3
- "version": "1.0.56-rc.4",
3
+ "version": "1.0.56-rc.6",
4
4
  "description": "ADHDev standalone daemon — embedded HTTP/WS server for local dashboard",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -37,7 +37,7 @@
37
37
  "license": "AGPL-3.0-or-later",
38
38
  "dependencies": {
39
39
  "@adhdev/ghostty-vt-node": "*",
40
- "@adhdev/session-host-core": "1.0.56-rc.4",
40
+ "@adhdev/session-host-core": "1.0.56-rc.6",
41
41
  "@xterm/addon-serialize": "^0.14.0",
42
42
  "@xterm/xterm": "^6.0.0",
43
43
  "chalk": "^5.3.0",
@@ -627,8 +627,9 @@ function buildMagiPanelProposal(detected, opts = {}) {
627
627
  var CANONICAL_MESH_TOOL_NAMES = [
628
628
  "mesh_status",
629
629
  "mesh_list_nodes",
630
- "mesh_enqueue_task",
630
+ // GRAPH-ORCHESTRATION Phase F — batch before task, mirroring ALL_MESH_TOOLS.
631
631
  "mesh_enqueue_batch",
632
+ "mesh_enqueue_task",
632
633
  "mesh_view_queue",
633
634
  // GRAPH-ORCHESTRATION Phase E — the coordinator gate + graph view surface.
634
635
  "mesh_graph_view",
@@ -1030,9 +1031,30 @@ var MESH_LIST_NODES_TOOL = {
1030
1031
  }
1031
1032
  }
1032
1033
  };
1034
+ var ENQUEUE_TOOL_GROUP = "mesh.enqueue";
1035
+ var ENQUEUE_TOOL_GROUP_MEMBERS = ["mesh_enqueue_batch", "mesh_enqueue_task"];
1036
+ var ENQUEUE_DISCOVERY_KEYWORDS = ["enqueue", "delegate", "task", "graph", "dependency"];
1037
+ var ENQUEUE_RANK_QUERIES = ["enqueue", "delegate"];
1038
+ var ENQUEUE_BATCH_DISCOVERY_META = {
1039
+ toolGroup: ENQUEUE_TOOL_GROUP,
1040
+ toolGroupMembers: ENQUEUE_TOOL_GROUP_MEMBERS,
1041
+ discoveryKeywords: ENQUEUE_DISCOVERY_KEYWORDS,
1042
+ discoveryRankQueries: ENQUEUE_RANK_QUERIES,
1043
+ discoveryRank: 0,
1044
+ enqueueRole: "default"
1045
+ };
1046
+ var ENQUEUE_TASK_DISCOVERY_META = {
1047
+ toolGroup: ENQUEUE_TOOL_GROUP,
1048
+ toolGroupMembers: ENQUEUE_TOOL_GROUP_MEMBERS,
1049
+ discoveryKeywords: ENQUEUE_DISCOVERY_KEYWORDS,
1050
+ discoveryRankQueries: ENQUEUE_RANK_QUERIES,
1051
+ discoveryRank: 10,
1052
+ enqueueRole: "single_task_fallback"
1053
+ };
1033
1054
  var MESH_ENQUEUE_TASK_TOOL = {
1034
1055
  name: "mesh_enqueue_task",
1035
- description: "Add a new task to the mesh work queue. Idle nodes will automatically pull and execute tasks from this queue. Use this instead of mesh_send_task when you do not need to target a specific node. For a dependency-wired MULTI-task graph prefer mesh_enqueue_batch: it inserts the whole set atomically and lets depends_on reference batch-local refs, so no half-registered chain can be left behind. Supports task-level priority (high tasks are pulled ahead of older normal/low tasks), not_before delayed execution (hold a task pending until a time), maxRetries (auto-fail after N requeues), and duplicate detection (by default warns in the response when an in-flight task with the same message+target already exists; pass block_duplicate=true to refuse instead, or allow_duplicate=true to silence the warning).",
1056
+ description: "SINGLE-TASK FALLBACK. Use only when exactly one new worker task is currently known and no downstream graph step can yet be declared. If two or more steps are known\u2014including steps that need outputs, worktree preparation, a condition, or a coordinator action\u2014load and use mesh_enqueue_batch instead. Same-session continuation belongs in mesh_send_task. Adds the task to the mesh work queue; idle nodes automatically pull and execute from it. Use this instead of mesh_send_task when you do not need to target a specific node. Supports task-level priority (high tasks are pulled ahead of older normal/low tasks), not_before delayed execution (hold a task pending until a time), maxRetries (auto-fail after N requeues), and duplicate detection (by default warns in the response when an in-flight task with the same message+target already exists; pass block_duplicate=true to refuse instead, or allow_duplicate=true to silence the warning).",
1057
+ _meta: ENQUEUE_TASK_DISCOVERY_META,
1036
1058
  inputSchema: {
1037
1059
  type: "object",
1038
1060
  properties: {
@@ -1063,14 +1085,25 @@ var MESH_ENQUEUE_TASK_TOOL = {
1063
1085
  block_duplicate: { type: "boolean", description: "G4 (duplicate detection, block mode). Default false = warn-only: if an in-flight (pending/assigned) task with the same message (+ target node when pinned) already exists, the task is still enqueued but the response carries duplicateSuspect. Set true to REFUSE the enqueue with code duplicate_suspect instead (structural TASKBUBBLE-DUP defense \u2014 use when re-sending a task that a slow prior turn may have already enqueued)." },
1064
1086
  blockDuplicate: { type: "boolean", description: "CamelCase alias for block_duplicate." },
1065
1087
  allow_duplicate: { type: "boolean", description: "G4. Set true to skip duplicate detection entirely (no warning, no block) for an intentional re-enqueue of the same instruction." },
1066
- allowDuplicate: { type: "boolean", description: "CamelCase alias for allow_duplicate." }
1088
+ allowDuplicate: { type: "boolean", description: "CamelCase alias for allow_duplicate." },
1089
+ // design :692 — "The single tool should require an orchestration_decision".
1090
+ // OPTIONAL here on purpose: Phase F is warn-only (see the discovery-meta note
1091
+ // above), and a required field would break legacy/external clients that
1092
+ // predate it. An omitted record degrades to decision_missing, which is itself
1093
+ // the signal — never an enqueue failure.
1094
+ orchestration_decision: {
1095
+ type: "object",
1096
+ description: "Record of your planning decision, for adoption measurement: {decision, ready_worker_tasks, known_graph_steps, single_reason, capability_blockers}. On this single-task surface, single_reason says why one task was right \u2014 one of only_one_step_known, future_step_not_specifiable, same_session_continuation, legacy_client, operator_override. output_needed / workspace_unresolved / coordinator_action_between are NOT blockers any more (mesh_enqueue_batch covers them via inputs_from, workspace_ref and coordinator gates); reporting one returns a batch_capability_available warning. Optional and never rejected: omitting it is recorded as decision_missing, and declaring known_graph_steps >= 2 here is recorded as a declared eligible single. Provenance only \u2014 it never changes execution."
1097
+ },
1098
+ orchestrationDecision: { type: "object", description: "CamelCase alias for orchestration_decision." }
1067
1099
  },
1068
1100
  required: ["message", "difficulty"]
1069
1101
  }
1070
1102
  };
1071
1103
  var MESH_ENQUEUE_BATCH_TOOL = {
1072
1104
  name: "mesh_enqueue_batch",
1073
- description: "G5: atomically enqueue a dependency-wired set of tasks \u2014 either EVERY task in the batch is inserted or NONE is (a mid-batch error such as a dependency cycle, invalid difficulty, or guardrail violation rolls the whole batch back). Use this instead of N sequential mesh_enqueue_task calls whenever you are wiring a multi-task graph: give each task a batch-local `ref` label and name sibling refs in `depends_on` (forward references allowed \u2014 array order does not matter). A depends_on value that is not a ref in this batch must be an EXISTING queue task id; anything else is rejected. Per-task fields are the same as mesh_enqueue_task. Top-level mission_id applies to every task that lacks its own. Beyond plain ordering it also accepts a full orchestration graph, so you can submit the WHOLE known plan once instead of enqueueing each step as the previous one finishes: `inputs_from` binds selected predecessor outputs into a later task (no hand-copying worker text), `run_if` branches on those outputs, `gates` declare steps that stop for a coordinator action (Refinery landing, approval, CI wait, publish, deploy) with downstream tasks pointing at them via `gated_by`, and `workspaces` + `workspace_ref` prepare a worktree later for a task that needs one. These are strictly additive: a batch using only message/depends_on behaves exactly as before. Only graph-using batches create a graph, inspectable with mesh_graph_view.",
1105
+ description: "DEFAULT enqueue surface for a plan with two or more known graph steps. Atomically persists the graph plan and worker queue entries. Supports batch-local refs, completion dependencies, selected predecessor outputs through `inputs_from`, declarative `run_if`, delayed `workspace_ref` preparation, and coordinator gates. Worker dispatch still requires the shared dependency predicate: all active worker dependencies completed and no system block. Git workspace preparation is a compensated saga and is reported separately from DB atomicity. Atomicity in detail: either EVERY task in the batch is inserted or NONE is (a mid-batch error such as a dependency cycle, invalid difficulty, or guardrail violation rolls the whole batch back). Give each task a batch-local `ref` label and name sibling refs in `depends_on` (forward references allowed \u2014 array order does not matter). A depends_on value that is not a ref in this batch must be an EXISTING queue task id; anything else is rejected. Per-task fields are the same as mesh_enqueue_task. Top-level mission_id applies to every task that lacks its own. `inputs_from` binds selected predecessor outputs into a later task (no hand-copying worker text), `run_if` branches on those outputs, `gates` declare steps that stop for a coordinator action (Refinery landing, approval, CI wait, publish, deploy) with downstream tasks pointing at them via `gated_by`, and `workspaces` + `workspace_ref` prepare a worktree later for a task that needs one. These are strictly additive: a batch using only message/depends_on behaves exactly as before. Only graph-using batches create a graph, inspectable with mesh_graph_view.",
1106
+ _meta: ENQUEUE_BATCH_DISCOVERY_META,
1074
1107
  inputSchema: {
1075
1108
  type: "object",
1076
1109
  properties: {
@@ -1483,7 +1516,7 @@ var MESH_CHECKPOINT_TOOL = {
1483
1516
  };
1484
1517
  var MESH_MISSION_UPSERT_TOOL = {
1485
1518
  name: "mesh_mission_upsert",
1486
- description: "Create or update a persistent mission record so the plan survives coordinator restarts. Create a mission before enqueueing a multi-task batch, attach tasks via mesh_enqueue_task mission_id, and update status to completed/abandoned when the outcome is decided. Progress is derived from task statuses \u2014 there is no separate progress field. Single mission: pass title (and optionally mission_id to update an existing one). Bulk status transition (e.g. one-time stale cleanup): pass mission_ids (array) + status to apply that status to many missions at once; title/goal are ignored and a per-mission result array is returned. mission_ids takes precedence over mission_id when both are given.",
1519
+ description: "Create or update a persistent mission record so the plan survives coordinator restarts. Create a mission before enqueueing a multi-task batch, then submit that plan as ONE mesh_enqueue_batch carrying the mission_id (a top-level mission_id applies to every entry; mesh_enqueue_task is the single-step fallback). Update status to completed/abandoned when the outcome is decided. Progress is derived from task statuses \u2014 there is no separate progress field. Single mission: pass title (and optionally mission_id to update an existing one). Bulk status transition (e.g. one-time stale cleanup): pass mission_ids (array) + status to apply that status to many missions at once; title/goal are ignored and a per-mission result array is returned. mission_ids takes precedence over mission_id when both are given.",
1487
1520
  inputSchema: {
1488
1521
  type: "object",
1489
1522
  properties: {
@@ -1613,7 +1646,7 @@ var MESH_PLAN_ONBOARDING_TOOL = {
1613
1646
  };
1614
1647
  var MESH_ADD_NODE_TOOL = {
1615
1648
  name: "mesh_add_node",
1616
- description: "Register a workspace as a node in an EXISTING mesh \u2014 the second bootstrap step after mesh_create (or to add more nodes later). Mirrors `adhdev mesh add-node <mesh_id>` with --workspace / --read-only / --provider-priority. A node is a repo checkout on a daemon that the coordinator can launch agents on and delegate tasks to. mesh_id is REQUIRED in standard mode (pass the id returned by mesh_create); in mesh mode it defaults to the active mesh. workspace is the absolute path to the repo checkout ON THE DAEMON that owns it \u2014 the local base node is added by the daemon that created the mesh. This is a persistent mesh write: call mesh_plan_onboarding first and obtain explicit user approval. The implementation re-runs that preflight before writing. NOTE: this registers an EXISTING directory as a node (including auto-detected linked worktrees). To CREATE a fresh git worktree + branch for isolated parallel work, use mesh_clone_node instead \u2014 that runs the actual `git worktree add`. Returns node_id + workspace so you can immediately target the node with mesh_launch_session / mesh_send_task / mesh_enqueue_task.",
1649
+ description: "Register a workspace as a node in an EXISTING mesh \u2014 the second bootstrap step after mesh_create (or to add more nodes later). Mirrors `adhdev mesh add-node <mesh_id>` with --workspace / --read-only / --provider-priority. A node is a repo checkout on a daemon that the coordinator can launch agents on and delegate tasks to. mesh_id is REQUIRED in standard mode (pass the id returned by mesh_create); in mesh mode it defaults to the active mesh. workspace is the absolute path to the repo checkout ON THE DAEMON that owns it \u2014 the local base node is added by the daemon that created the mesh. This is a persistent mesh write: call mesh_plan_onboarding first and obtain explicit user approval. The implementation re-runs that preflight before writing. NOTE: this registers an EXISTING directory as a node (including auto-detected linked worktrees). To CREATE a fresh git worktree + branch for isolated parallel work, use mesh_clone_node instead \u2014 that runs the actual `git worktree add`. Returns node_id + workspace so you can immediately target the node with mesh_launch_session / mesh_send_task / mesh_enqueue_task. That immediate-targeting path is right when the node is the only thing you were waiting on; when the work behind it is a multi-step plan, prefer declaring the whole plan in one mesh_enqueue_batch instead of registering, then enqueueing step by step.",
1617
1650
  inputSchema: {
1618
1651
  type: "object",
1619
1652
  properties: {
@@ -1632,7 +1665,7 @@ var MESH_ADD_NODE_TOOL = {
1632
1665
  };
1633
1666
  var MESH_CLONE_NODE_TOOL = {
1634
1667
  name: "mesh_clone_node",
1635
- description: "Create a new worktree-based node from an existing node for isolated parallel work. Creates a git worktree on a new branch so multiple tasks can run on separate branches simultaneously. This writes a branch, worktree and mesh node: call mesh_plan_onboarding with operation=clone_worktree and obtain explicit user approval first; the implementation re-runs the clean/source preflight.",
1668
+ description: "Create a new worktree-based node from an existing node for isolated parallel work. Creates a git worktree on a new branch so multiple tasks can run on separate branches simultaneously. This writes a branch, worktree and mesh node: call mesh_plan_onboarding with operation=clone_worktree and obtain explicit user approval first; the implementation re-runs the clean/source preflight. Call this directly when you need the worktree NOW and will target it right away. When the worktree only exists to host a plan you already know, that plan can be submitted as one mesh_enqueue_batch: declare the worktree in the top-level `workspaces` array and point its tasks at it with `workspace_ref`, so preparation happens as part of the graph instead of a manual clone followed by step-by-step enqueues.",
1636
1669
  inputSchema: {
1637
1670
  type: "object",
1638
1671
  properties: {
@@ -2083,8 +2116,11 @@ var MESH_COORDINATOR_PROMPT_APPEND_SET_TOOL = {
2083
2116
  var ALL_MESH_TOOLS = [
2084
2117
  MESH_STATUS_TOOL,
2085
2118
  MESH_LIST_NODES_TOOL,
2086
- MESH_ENQUEUE_TASK_TOOL,
2119
+ // GRAPH-ORCHESTRATION Phase F — batch BEFORE task. Registry order is what a
2120
+ // client that lists tools without ranking sees first, so the default enqueue
2121
+ // surface leads and the single-task fallback follows it.
2087
2122
  MESH_ENQUEUE_BATCH_TOOL,
2123
+ MESH_ENQUEUE_TASK_TOOL,
2088
2124
  MESH_VIEW_QUEUE_TOOL,
2089
2125
  // GRAPH-ORCHESTRATION Phase E — placed next to the queue/enqueue tools so a
2090
2126
  // coordinator that loaded the batch schema also discovers how to pass a gate.
@@ -2669,6 +2705,15 @@ function annotateRapidReadChatAdvisory(payload, options) {
2669
2705
  // src/tools/mesh-tools-internal.ts
2670
2706
  var import_daemon_core6 = require("@adhdev/daemon-core");
2671
2707
  var import_node_crypto = require("crypto");
2708
+ function recordMeshCoordinatorToolCall(ctx, tool) {
2709
+ const sessionId = ctx.coordinatorSessionId ?? null;
2710
+ return (0, import_daemon_core5.recordMeshToolCall)({
2711
+ meshId: ctx.mesh.id,
2712
+ tool,
2713
+ sessionId,
2714
+ callerRole: sessionId ? "coordinator" : "unknown"
2715
+ });
2716
+ }
2672
2717
  var SESSION_PROVIDER_METADATA_TTL_MS = 30 * 6e4;
2673
2718
  var meshSessionProviderMetadata = /* @__PURE__ */ new Map();
2674
2719
  function getSessionMetadata(key) {
@@ -4229,7 +4274,7 @@ function summarizePendingEventProtocolMetrics(pendingEvents) {
4229
4274
  };
4230
4275
  }
4231
4276
  async function meshStatus(ctx, args = {}) {
4232
- const rateResult = (0, import_daemon_core6.recordMeshToolCall)({ meshId: ctx.mesh.id, tool: "mesh_status" });
4277
+ const rateResult = recordMeshCoordinatorToolCall(ctx, "mesh_status");
4233
4278
  const compact = args.verbose === true ? false : args.compact ?? true;
4234
4279
  await refreshMeshFromDaemon(ctx);
4235
4280
  const { mesh, transport } = ctx;
@@ -4863,7 +4908,7 @@ function resolveGateSession(ctx, explicit) {
4863
4908
  return readString(explicit) || ctx.coordinatorSessionId || void 0;
4864
4909
  }
4865
4910
  async function meshGraphGateClaim(ctx, args) {
4866
- (0, import_daemon_core6.recordMeshToolCall)({ meshId: ctx.mesh.id, tool: "mesh_graph_gate_claim" });
4911
+ recordMeshCoordinatorToolCall(ctx, "mesh_graph_gate_claim");
4867
4912
  const gateId = readString(args.gate_id) || readString(args.gateId);
4868
4913
  if (!gateId) {
4869
4914
  return JSON.stringify({
@@ -4958,7 +5003,7 @@ function describeClaimRefusal(reason, state) {
4958
5003
  }
4959
5004
  }
4960
5005
  async function meshGraphGateRelease(ctx, args) {
4961
- (0, import_daemon_core6.recordMeshToolCall)({ meshId: ctx.mesh.id, tool: "mesh_graph_gate_release" });
5006
+ recordMeshCoordinatorToolCall(ctx, "mesh_graph_gate_release");
4962
5007
  const gateId = readString(args.gate_id) || readString(args.gateId);
4963
5008
  const fencingToken = readString(args.fencing_token) || readString(args.fencingToken);
4964
5009
  const leaseGeneration = readNumber(args.lease_generation ?? args.leaseGeneration);
@@ -5007,6 +5052,7 @@ async function meshGraphGateRelease(ctx, args) {
5007
5052
  duplicate: result.duplicate
5008
5053
  });
5009
5054
  const queueTrigger = result.materializedNodeIds.length > 0 ? await triggerMeshQueueAndReport(ctx) : void 0;
5055
+ const releasedNothingDownstream = !result.duplicate && result.materializedNodeIds.length === 0 && result.downstreamNodeCount === 0 && result.graphCompleted !== true;
5010
5056
  return JSON.stringify({
5011
5057
  success: true,
5012
5058
  released: true,
@@ -5019,6 +5065,10 @@ async function meshGraphGateRelease(ctx, args) {
5019
5065
  outcome,
5020
5066
  materializedNodeIds: result.materializedNodeIds,
5021
5067
  materializedCount: result.materializedNodeIds.length,
5068
+ ...result.downstreamNodeCount !== void 0 ? { downstreamNodeCount: result.downstreamNodeCount } : {},
5069
+ ...releasedNothingDownstream ? {
5070
+ noDownstreamAdvisory: "This gate opened nothing downstream: no task declared it in gated_by, so claiming and releasing it bought no scheduling while the rest of the graph is still outstanding. Declare the next step in the same batch and point it at this gate with gated_by, so releasing the gate dispatches it \u2014 or drop the gate and enqueue that step directly."
5071
+ } : {},
5022
5072
  ...queueTrigger ? { queueTrigger } : {},
5023
5073
  ...result.duplicate ? { duplicateHint: "This idempotency_key + payload was already committed; nothing changed. Re-sending an identical release is safe." } : {}
5024
5074
  });
@@ -5040,7 +5090,7 @@ async function meshGraphGateRelease(ctx, args) {
5040
5090
  }
5041
5091
  }
5042
5092
  async function meshGraphView(ctx, args) {
5043
- (0, import_daemon_core6.recordMeshToolCall)({ meshId: ctx.mesh.id, tool: "mesh_graph_view" });
5093
+ recordMeshCoordinatorToolCall(ctx, "mesh_graph_view");
5044
5094
  try {
5045
5095
  await refreshMeshFromDaemon(ctx);
5046
5096
  const graphId = readString(args.graph_id) || readString(args.graphId);
@@ -5258,6 +5308,17 @@ async function meshEnqueueTask(ctx, args) {
5258
5308
  } = normalized.value;
5259
5309
  const allowDuplicate = args.allowDuplicate === true || args.allow_duplicate === true;
5260
5310
  const blockDuplicate = args.blockDuplicate === true || args.block_duplicate === true;
5311
+ const rawDecision = args.orchestration_decision ?? args.orchestrationDecision;
5312
+ const decisionMissing = rawDecision === void 0 || rawDecision === null;
5313
+ const orchestration = (0, import_daemon_core6.normalizeOrchestrationDecision)(rawDecision, "single");
5314
+ const orchestrationWarning = {
5315
+ ...orchestration.batchCapabilityAvailable ? { batchCapabilityAvailable: orchestration.batchCapabilityAvailable } : {},
5316
+ ...orchestration.declaredEligibleSingle ? {
5317
+ declaredEligibleSingle: true,
5318
+ declaredEligibleSingleHint: import_daemon_core6.MESH_DECLARED_ELIGIBLE_SINGLE_HINT
5319
+ } : {},
5320
+ ...decisionMissing ? { orchestrationDecisionMissing: true } : {}
5321
+ };
5261
5322
  const duplicateSuspect = allowDuplicate ? null : findInFlightDuplicate(ctx, message, targetNodeId);
5262
5323
  if (duplicateSuspect && blockDuplicate) {
5263
5324
  return JSON.stringify({
@@ -5283,6 +5344,15 @@ async function meshEnqueueTask(ctx, args) {
5283
5344
  ...maxRetries !== void 0 ? { maxRetries } : {},
5284
5345
  ...ctx.coordinatorSessionId ? { sourceCoordinatorSessionId: ctx.coordinatorSessionId } : {}
5285
5346
  });
5347
+ (0, import_daemon_core6.recordSingleEnqueueDecision)(ctx.mesh.id, {
5348
+ taskId: task.id,
5349
+ ...missionId ? { missionId } : {},
5350
+ ...ctx.coordinatorSessionId ? { coordinatorSessionId: ctx.coordinatorSessionId } : {},
5351
+ decision: orchestration.decision,
5352
+ ...decisionMissing ? { decisionMissing: true } : {},
5353
+ ...orchestration.declaredEligibleSingle ? { declaredEligibleSingle: true } : {},
5354
+ ...orchestration.batchCapabilityAvailable ? { batchCapabilityAvailable: orchestration.batchCapabilityAvailable.reportedReason } : {}
5355
+ });
5286
5356
  const duplicateWarning = duplicateSuspect ? { duplicateSuspect: { taskId: duplicateSuspect.id, status: duplicateSuspect.status, assignedNodeId: duplicateSuspect.assignedNodeId, targetNodeId: duplicateSuspect.targetNodeId }, duplicateSuspectHint: "An in-flight task with the same message+target already exists. This new task was enqueued anyway (warn-only). Cancel one via mesh_queue_cancel if it is an accidental re-enqueue, or pass allow_duplicate=true to silence this, or block_duplicate=true to refuse next time." } : {};
5287
5357
  const missionWarning = buildMissionInactiveWarning(ctx, missionId) ?? {};
5288
5358
  const worktreeAdvisory = buildUntargetedCodeChangeWorktreeAdvisory({
@@ -5312,6 +5382,7 @@ async function meshEnqueueTask(ctx, args) {
5312
5382
  ...duplicateWarning,
5313
5383
  ...missionWarning,
5314
5384
  ...worktreeAdvisory,
5385
+ ...orchestrationWarning,
5315
5386
  queueTrigger,
5316
5387
  ...buildQueueTriggerGuidance(queueTrigger)
5317
5388
  });
@@ -5340,6 +5411,7 @@ async function meshEnqueueTask(ctx, args) {
5340
5411
  ...duplicateWarning,
5341
5412
  ...missionWarning,
5342
5413
  ...worktreeAdvisory,
5414
+ ...orchestrationWarning,
5343
5415
  queueTrigger,
5344
5416
  ...buildQueueTriggerGuidance(queueTrigger)
5345
5417
  });
@@ -5637,7 +5709,7 @@ async function meshEnqueueBatch(ctx, args) {
5637
5709
  });
5638
5710
  }
5639
5711
  async function meshViewQueue(ctx, args) {
5640
- const rateResult = (0, import_daemon_core6.recordMeshToolCall)({ meshId: ctx.mesh.id, tool: "mesh_view_queue" });
5712
+ const rateResult = recordMeshCoordinatorToolCall(ctx, "mesh_view_queue");
5641
5713
  const compact = args.verbose === true ? false : args.compact ?? true;
5642
5714
  try {
5643
5715
  await refreshMeshFromDaemon(ctx);
@@ -8944,7 +9016,7 @@ async function meshAnswerQuestion(ctx, args) {
8944
9016
  return JSON.stringify(result, null, 2);
8945
9017
  }
8946
9018
  async function meshListPendingApprovals(ctx, _args = {}) {
8947
- (0, import_daemon_core6.recordMeshToolCall)({ meshId: ctx.mesh.id, tool: "mesh_list_pending_approvals" });
9019
+ recordMeshCoordinatorToolCall(ctx, "mesh_list_pending_approvals");
8948
9020
  await refreshMeshFromDaemon(ctx);
8949
9021
  const liveNodes = await collectMeshViewQueueNodesWithLiveSessions(ctx);
8950
9022
  let ledgerEntries = (0, import_daemon_core6.readLedgerEntries)(ctx.mesh.id, { tail: 200 });