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

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
@@ -35904,6 +35904,15 @@ var require_dist3 = __commonJS({
35904
35904
  } else {
35905
35905
  delete policy.quotaRouting;
35906
35906
  }
35907
+ if (policy.onDependencyFailure === void 0 || policy.onDependencyFailure === "block") {
35908
+ delete policy.onDependencyFailure;
35909
+ } else if (policy.onDependencyFailure === "cancel") {
35910
+ policy.onDependencyFailure = "cancel";
35911
+ } else {
35912
+ throw new Error(
35913
+ `invalid_on_dependency_failure: must be 'block' or 'cancel' (got ${JSON.stringify(policy.onDependencyFailure)}). Invalid values are rejected; they do not silently become 'block'.`
35914
+ );
35915
+ }
35907
35916
  return policy;
35908
35917
  }
35909
35918
  function resolveDelegatedWorkerAutoApprove(meshPolicy, nodePolicy, provider, repoConfig, providerType, overrideModeId, overrideLegacyAutoApprove) {
@@ -36040,7 +36049,8 @@ var require_dist3 = __commonJS({
36040
36049
  // notifies the owner. Opt into 'auto_silent_on_dispatch' to one-shot-silence the
36041
36050
  // routine idle push for a coordinator-driven task (approval/failure notifications
36042
36051
  // are never affected — see coordinatorIdlePushPolicy).
36043
- coordinatorIdlePushPolicy: "always"
36052
+ coordinatorIdlePushPolicy: "always",
36053
+ onDependencyFailure: "block"
36044
36054
  };
36045
36055
  DEFAULT_QUOTA_ROUTING_POLICY = {
36046
36056
  staleAfterMs: 30 * 60 * 1e3,
@@ -36610,10 +36620,10 @@ var require_dist3 = __commonJS({
36610
36620
  }
36611
36621
  function getDaemonBuildInfo() {
36612
36622
  if (cached2) return cached2;
36613
- const commit = readInjected(true ? "043f842c15bd9babf19ea49b2392bf827f8cc97a" : void 0) ?? "unknown";
36614
- const commitShort = readInjected(true ? "043f842c" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
36615
- const version2 = readInjected(true ? "1.0.56-rc.3" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
36616
- const builtAt = readInjected(true ? "2026-08-18T13:29:56.354Z" : void 0);
36623
+ const commit = readInjected(true ? "0ac5de5a5c119ce79644b72b5cf2e44ae1afc677" : void 0) ?? "unknown";
36624
+ const commitShort = readInjected(true ? "0ac5de5a" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
36625
+ const version2 = readInjected(true ? "1.0.56-rc.4" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
36626
+ const builtAt = readInjected(true ? "2026-08-19T02:15:04.773Z" : void 0);
36617
36627
  cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
36618
36628
  return cached2;
36619
36629
  }
@@ -42845,6 +42855,10 @@ ${error48.message || ""}`;
42845
42855
  "mesh_enqueue_task",
42846
42856
  "mesh_enqueue_batch",
42847
42857
  "mesh_view_queue",
42858
+ // GRAPH-ORCHESTRATION Phase E — the coordinator gate + graph view surface.
42859
+ "mesh_graph_view",
42860
+ "mesh_graph_gate_claim",
42861
+ "mesh_graph_gate_release",
42848
42862
  "mesh_queue_cancel",
42849
42863
  "mesh_queue_requeue",
42850
42864
  "mesh_send_task",
@@ -43952,6 +43966,10 @@ ${error48.message || ""}`;
43952
43966
  return `[System] ${args.nodeLabel} already has completion evidence${metadata}. The no-progress monitor reconciled the terminal handoff and marked the session complete; wait for the queued completion event/status refresh before doing any manual transcript check.`;
43953
43967
  }
43954
43968
  const reviewRecommended = args.metadataEvent.reviewRecommended === true;
43969
+ const timedOutNoResponse = args.metadataEvent.completionDiagnostic && typeof args.metadataEvent.completionDiagnostic === "object" && args.metadataEvent.completionDiagnostic.timedOutWithoutFinalAssistant === true;
43970
+ if (timedOutNoResponse) {
43971
+ return `[System] ${args.nodeLabel} was forcibly terminated WITHOUT a response${metadata}: the finalization wait expired with no final assistant answer, so the task was recorded as a forced termination (failed), NOT as a completion. Verify the actual state with mesh_read_chat / git status and re-dispatch the task if the work is still needed.`;
43972
+ }
43955
43973
  const weakCompletion = isWeakCompletionMetadata(args.metadataEvent);
43956
43974
  const completionLead = weakCompletion ? `[System] ${args.nodeLabel} reported a possible completion (weak evidence) \u2014 awaiting confirmation${metadata}.` : `[System] ${args.nodeLabel} has completed its task and is now idle${metadata}.`;
43957
43975
  const verifyTextNote = " Completion evidence is weak \u2014 verify via mesh_read_chat or git status before declaring the task done; the worker may still be mid-turn or parked on an approval/modal.";
@@ -45352,14 +45370,40 @@ Next step: ${nextStep}`;
45352
45370
  sessionOrderChains = /* @__PURE__ */ new Map();
45353
45371
  }
45354
45372
  });
45373
+ function newMeshGraphId() {
45374
+ return (0, import_crypto6.randomUUID)();
45375
+ }
45376
+ function newMeshGraphNodeId() {
45377
+ return (0, import_crypto6.randomUUID)();
45378
+ }
45379
+ function newMeshGraphGateId() {
45380
+ return (0, import_crypto6.randomUUID)();
45381
+ }
45355
45382
  function newMeshGraphOutboxId() {
45356
45383
  return (0, import_crypto6.randomUUID)();
45357
45384
  }
45358
45385
  var import_crypto6;
45386
+ var MESH_GRAPH_SCHEMA_VERSION;
45387
+ var MESH_GRAPH_ON_UPSTREAM_SKIP_POLICIES;
45388
+ var MESH_GRAPH_GATE_ACTIONS;
45389
+ var MESH_GRAPH_GATE_TIMEOUT_POLICIES;
45390
+ var MESH_GRAPH_ON_DEPENDENCY_FAILURE_POLICIES;
45359
45391
  var init_mesh_graph_types = __esm2({
45360
45392
  "src/mesh/mesh-graph-types.ts"() {
45361
45393
  "use strict";
45362
45394
  import_crypto6 = require("crypto");
45395
+ MESH_GRAPH_SCHEMA_VERSION = 2;
45396
+ MESH_GRAPH_ON_UPSTREAM_SKIP_POLICIES = ["skip", "omit_dependency"];
45397
+ MESH_GRAPH_GATE_ACTIONS = [
45398
+ "refinery",
45399
+ "approval",
45400
+ "ci_wait",
45401
+ "publish",
45402
+ "deploy",
45403
+ "custom"
45404
+ ];
45405
+ MESH_GRAPH_GATE_TIMEOUT_POLICIES = ["hold", "cancel_downstream", "fail_graph"];
45406
+ MESH_GRAPH_ON_DEPENDENCY_FAILURE_POLICIES = ["block", "cancel"];
45363
45407
  }
45364
45408
  });
45365
45409
  function maskKeepTail(token) {
@@ -45895,6 +45939,188 @@ ${blocks.join("\n\n")}`;
45895
45939
  init_mesh_graph_workspace_identity();
45896
45940
  }
45897
45941
  });
45942
+ function parseOnDependencyFailurePolicy(value) {
45943
+ if (value === void 0 || value === null || value === "") return "block";
45944
+ if (typeof value === "string" && MESH_GRAPH_ON_DEPENDENCY_FAILURE_POLICIES.includes(value)) {
45945
+ return value;
45946
+ }
45947
+ throw new MeshGraphPolicyError(
45948
+ `invalid_on_dependency_failure: must be 'block' or 'cancel' (got ${JSON.stringify(value)}). Invalid values are rejected; they do not silently become 'block'.`
45949
+ );
45950
+ }
45951
+ function resolveOnDependencyFailurePolicy(value) {
45952
+ return value === "cancel" ? "cancel" : "block";
45953
+ }
45954
+ function parseGraphPolicy(policyJson) {
45955
+ const parsed = safeParseObject(policyJson);
45956
+ const raw = parsed?.on_dependency_failure ?? parsed?.onDependencyFailure;
45957
+ return { on_dependency_failure: parseOnDependencyFailurePolicy(raw) };
45958
+ }
45959
+ function projectGraphPublicPolicy(policyJson) {
45960
+ try {
45961
+ return parseGraphPolicy(policyJson);
45962
+ } catch (e) {
45963
+ return {
45964
+ on_dependency_failure: "block",
45965
+ policyInvalid: e instanceof Error ? e.message : String(e)
45966
+ };
45967
+ }
45968
+ }
45969
+ function serializeGraphPolicy(policy) {
45970
+ return JSON.stringify({ on_dependency_failure: policy.on_dependency_failure });
45971
+ }
45972
+ function isGraphSkipPlaceholder(entry) {
45973
+ if (!entry) return false;
45974
+ const reason = entry.blockedReason ?? entry.cancelReason ?? "";
45975
+ return entry.status === "cancelled" && reason.startsWith(MESH_GRAPH_SKIP_BLOCK_PREFIX);
45976
+ }
45977
+ function parseLegacyDependencyFailedPredecessor(reason) {
45978
+ if (typeof reason !== "string") return null;
45979
+ if (!reason.startsWith(LEGACY_DEPENDENCY_FAILED_PREFIX)) return null;
45980
+ const rest = reason.slice(LEGACY_DEPENDENCY_FAILED_PREFIX.length);
45981
+ if (!rest || rest.startsWith(":")) return null;
45982
+ return rest;
45983
+ }
45984
+ function deriveDependencyFailures(dependsOn, statusById, depMetaById) {
45985
+ const deps = Array.isArray(dependsOn) ? dependsOn : [];
45986
+ const failures = [];
45987
+ for (const taskId of deps) {
45988
+ const meta3 = depMetaById?.get(taskId);
45989
+ const status = statusById.get(taskId) ?? meta3?.status;
45990
+ if (isGraphSkipPlaceholder({ status, blockedReason: meta3?.blockedReason, cancelReason: meta3?.cancelReason })) {
45991
+ continue;
45992
+ }
45993
+ if (status !== "failed" && status !== "cancelled") continue;
45994
+ const reason = meta3?.cancelReason ?? meta3?.blockedReason;
45995
+ failures.push({
45996
+ taskId,
45997
+ status,
45998
+ ...reason ? { reason } : {}
45999
+ });
46000
+ }
46001
+ return failures;
46002
+ }
46003
+ function classifyGraphRollup(nodes) {
46004
+ const gates = nodes.filter((n) => n.kind === "coordinator_gate");
46005
+ const workers = nodes.filter((n) => n.kind !== "coordinator_gate");
46006
+ if (gates.some((g) => !GATE_SETTLED.has(g.state))) return null;
46007
+ if (workers.some((w) => !WORKER_SETTLED.has(w.state))) return null;
46008
+ if (workers.some((w) => w.state === "failed")) return "failed";
46009
+ if (workers.some((w) => w.state === "cancelled") || gates.some((g) => g.state === "cancelled" || g.state === "expired")) {
46010
+ return "cancelled";
46011
+ }
46012
+ if (workers.length === 0 && gates.length === 0) return "completed";
46013
+ if (workers.every((w) => SUCCESS_TERMINAL.has(w.state)) && gates.every((g) => g.state === "released" || SUCCESS_TERMINAL.has(g.state))) {
46014
+ return "completed";
46015
+ }
46016
+ return "completed";
46017
+ }
46018
+ function applyGraphCancelCascade(store, nodes, edges, origin, nowIso, updateNodeState) {
46019
+ const byId = new Map(nodes.map((n) => [n.nodeId, n]));
46020
+ const frontier = [origin.nodeId];
46021
+ const seen = new Set(frontier);
46022
+ const cancelledNodeIds = [];
46023
+ const cancelledTaskIds = [];
46024
+ const sourceTaskId = origin.queueTaskId ?? origin.nodeId;
46025
+ const sourceRef = origin.ref ?? origin.nodeId;
46026
+ while (frontier.length > 0) {
46027
+ const currentId = frontier.pop();
46028
+ const outgoing = edges.filter((e) => e.fromNodeId === currentId && e.kind !== "gate");
46029
+ for (const edge of outgoing) {
46030
+ const target = byId.get(edge.toNodeId);
46031
+ if (!target || seen.has(target.nodeId)) continue;
46032
+ seen.add(target.nodeId);
46033
+ if (target.kind !== "worker_task") continue;
46034
+ if (target.state === "skipped") continue;
46035
+ if (!CANCELABLE_NODE_STATES.has(target.state)) continue;
46036
+ const reason = `${LEGACY_DEPENDENCY_FAILED_PREFIX}${sourceRef}`;
46037
+ updateNodeState(target, reason);
46038
+ target.state = "cancelled";
46039
+ target.failureReason = reason;
46040
+ cancelledNodeIds.push(target.nodeId);
46041
+ if (target.queueTaskId) {
46042
+ const entry = store.findQueueEntryById(target.meshId, target.queueTaskId);
46043
+ if (entry && entry.status === "pending") {
46044
+ cancelledTaskIds.push(entry.id);
46045
+ }
46046
+ }
46047
+ frontier.push(target.nodeId);
46048
+ }
46049
+ }
46050
+ return { cancelledNodeIds, cancelledTaskIds };
46051
+ }
46052
+ function migrateLegacyDependencyFailedQueueBlocks(db) {
46053
+ let rows;
46054
+ try {
46055
+ rows = db.prepare(`SELECT id, mesh_id, payload FROM mesh_queue`).all();
46056
+ } catch {
46057
+ return [];
46058
+ }
46059
+ const cleared = [];
46060
+ const update = db.prepare(`UPDATE mesh_queue SET payload = ?, updated_at = ? WHERE id = ? AND mesh_id = ?`);
46061
+ const nowIso = (/* @__PURE__ */ new Date()).toISOString();
46062
+ for (const row of rows) {
46063
+ let entry;
46064
+ try {
46065
+ entry = JSON.parse(row.payload);
46066
+ } catch {
46067
+ continue;
46068
+ }
46069
+ const predecessorId = parseLegacyDependencyFailedPredecessor(entry.blockedReason);
46070
+ if (!predecessorId) continue;
46071
+ delete entry.blockedReason;
46072
+ update.run(JSON.stringify(entry), nowIso, row.id, row.mesh_id);
46073
+ cleared.push({ taskId: row.id, meshId: row.mesh_id, predecessorId });
46074
+ }
46075
+ return cleared;
46076
+ }
46077
+ function safeParseObject(text) {
46078
+ if (!text) return null;
46079
+ try {
46080
+ const value = JSON.parse(text);
46081
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
46082
+ return value;
46083
+ } catch {
46084
+ return null;
46085
+ }
46086
+ }
46087
+ var MESH_ON_DEPENDENCY_FAILURE_PUBLIC_TEXT;
46088
+ var MESH_GRAPH_SKIP_BLOCK_PREFIX;
46089
+ var LEGACY_DEPENDENCY_FAILED_PREFIX;
46090
+ var MeshGraphPolicyError;
46091
+ var SUCCESS_TERMINAL;
46092
+ var WORKER_SETTLED;
46093
+ var GATE_SETTLED;
46094
+ var CANCELABLE_NODE_STATES;
46095
+ var init_mesh_graph_derived_failure = __esm2({
46096
+ "src/mesh/mesh-graph-derived-failure.ts"() {
46097
+ "use strict";
46098
+ init_mesh_graph_types();
46099
+ MESH_ON_DEPENDENCY_FAILURE_PUBLIC_TEXT = "on_dependency_failure controls downstream tasks when a required worker task fails or is cancelled. `block` (default) keeps downstream pending and automatically recovers if the predecessor is retried and later completes. `cancel` terminally cancels the dependent branch; it is not revived by predecessor retry.";
46100
+ MESH_GRAPH_SKIP_BLOCK_PREFIX = "graph_skipped:";
46101
+ LEGACY_DEPENDENCY_FAILED_PREFIX = "dependency_failed:";
46102
+ MeshGraphPolicyError = class extends Error {
46103
+ constructor(message, code = "invalid_on_dependency_failure") {
46104
+ super(message);
46105
+ this.code = code;
46106
+ this.name = "MeshGraphPolicyError";
46107
+ }
46108
+ };
46109
+ SUCCESS_TERMINAL = /* @__PURE__ */ new Set(["completed", "released", "skipped"]);
46110
+ WORKER_SETTLED = /* @__PURE__ */ new Set([
46111
+ "completed",
46112
+ "skipped",
46113
+ "failed",
46114
+ "cancelled"
46115
+ ]);
46116
+ GATE_SETTLED = /* @__PURE__ */ new Set(["released", "cancelled", "expired"]);
46117
+ CANCELABLE_NODE_STATES = /* @__PURE__ */ new Set([
46118
+ "declared",
46119
+ "blocked",
46120
+ "materialized"
46121
+ ]);
46122
+ }
46123
+ });
45898
46124
  function graphMaterializationBlockReason(nodeId, materializationVersion) {
45899
46125
  return `${GRAPH_BLOCK_PREFIX}${nodeId}:${materializationVersion}`;
45900
46126
  }
@@ -45907,6 +46133,14 @@ ${blocks.join("\n\n")}`;
45907
46133
  if (!Number.isInteger(version2) || version2 < 0) return null;
45908
46134
  return { nodeId: rest.slice(0, sep15), version: version2 };
45909
46135
  }
46136
+ function coordinatorGateBlockReason(gateId) {
46137
+ return `${GATE_BLOCK_PREFIX}${gateId}`;
46138
+ }
46139
+ function parseCoordinatorGateBlock(reason) {
46140
+ if (!reason || !reason.startsWith(GATE_BLOCK_PREFIX)) return null;
46141
+ const gateId = reason.slice(GATE_BLOCK_PREFIX.length);
46142
+ return gateId.length > 0 ? { gateId } : null;
46143
+ }
45910
46144
  function registerMeshGraphQueueWakeHandler(handler) {
45911
46145
  queueWakeHandler = handler;
45912
46146
  }
@@ -46030,11 +46264,59 @@ ${blocks.join("\n\n")}`;
46030
46264
  });
46031
46265
  const nodes = graphStore.listNodes(node.graphId);
46032
46266
  const byId = new Map(nodes.map((n) => [n.nodeId, n]));
46033
- let graphRolledUp = false;
46034
- if (nodes.every(isTerminalEquivalent)) {
46035
- graphStore.updateGraphStatus(node.graphId, "completed", nowIso, true);
46036
- outbox.push({ kind: "graph_completed", payload: { graphId: node.graphId } });
46037
- graphRolledUp = true;
46267
+ const graph = graphStore.getGraph(node.graphId);
46268
+ const failurePolicy = projectGraphPublicPolicy(graph?.policyJson).on_dependency_failure;
46269
+ if ((terminal.status === "failed" || terminal.status === "cancelled") && failurePolicy === "cancel") {
46270
+ const edges = graphStore.listEdges(node.graphId);
46271
+ const cascade = applyGraphCancelCascade(
46272
+ store,
46273
+ nodes,
46274
+ edges,
46275
+ node,
46276
+ nowIso,
46277
+ (target, reason) => {
46278
+ graphStore.updateNodeState(target.graphId, target.nodeId, "cancelled", nowIso, {
46279
+ failureReason: reason
46280
+ });
46281
+ }
46282
+ );
46283
+ for (const taskId of cascade.cancelledTaskIds) {
46284
+ const entry = store.findQueueEntryById(node.meshId, taskId);
46285
+ if (entry && entry.status === "pending") {
46286
+ entry.status = "cancelled";
46287
+ entry.cancelledAt = nowIso;
46288
+ entry.cancelReason = `dependency_failed:${terminal.taskId}`;
46289
+ store.updateQueueEntry(entry);
46290
+ }
46291
+ }
46292
+ for (const nodeId of cascade.cancelledNodeIds) {
46293
+ const target = byId.get(nodeId);
46294
+ outbox.push({
46295
+ kind: "graph_node_cancelled",
46296
+ payload: {
46297
+ graphId: node.graphId,
46298
+ nodeId,
46299
+ ref: target?.ref,
46300
+ taskId: target?.queueTaskId,
46301
+ reason: `dependency_failed:${node.ref ?? node.nodeId}`
46302
+ }
46303
+ });
46304
+ }
46305
+ } else if (terminal.status === "failed" || terminal.status === "cancelled") {
46306
+ const dependents = graphStore.listEdges(node.graphId).filter((e) => e.fromNodeId === node.nodeId && e.kind !== "gate").map((e) => byId.get(e.toNodeId)).filter((n) => !!n && n.kind === "worker_task");
46307
+ outbox.push({
46308
+ kind: "graph_derived_failure",
46309
+ payload: {
46310
+ graphId: node.graphId,
46311
+ nodeId: node.nodeId,
46312
+ ref: node.ref,
46313
+ taskId: terminal.taskId,
46314
+ outcome: terminal.status,
46315
+ policy: "block",
46316
+ dependentNodeIds: dependents.map((d) => d.nodeId),
46317
+ dependentTaskIds: dependents.map((d) => d.queueTaskId).filter(Boolean)
46318
+ }
46319
+ });
46038
46320
  }
46039
46321
  const materialized = [];
46040
46322
  if (terminal.status === "completed") {
@@ -46047,7 +46329,12 @@ ${blocks.join("\n\n")}`;
46047
46329
  );
46048
46330
  for (const targetId of downstreamIds) {
46049
46331
  const target = byId.get(targetId);
46050
- if (!target || target.kind !== "worker_task" || !target.queueTaskId) continue;
46332
+ if (!target) continue;
46333
+ if (target.kind === "coordinator_gate") {
46334
+ maybeOpenCoordinatorGate(store, target, edges, byId, nowIso);
46335
+ continue;
46336
+ }
46337
+ if (target.kind !== "worker_task" || !target.queueTaskId) continue;
46051
46338
  if (target.state !== "declared" && target.state !== "blocked") continue;
46052
46339
  const outcome = settleDownstreamNode(store, target, edges, byId, nowIso);
46053
46340
  if (outcome.kind === "materialized") {
@@ -46091,10 +46378,12 @@ ${blocks.join("\n\n")}`;
46091
46378
  }
46092
46379
  frontier = nextFrontier;
46093
46380
  }
46094
- if (!graphRolledUp && graphStore.listNodes(node.graphId).every(isTerminalEquivalent)) {
46095
- graphStore.updateGraphStatus(node.graphId, "completed", nowIso, true);
46096
- outbox.push({ kind: "graph_completed", payload: { graphId: node.graphId } });
46097
- }
46381
+ }
46382
+ const rolled = classifyGraphRollup(graphStore.listNodes(node.graphId));
46383
+ if (rolled && graph?.status !== rolled) {
46384
+ graphStore.updateGraphStatus(node.graphId, rolled, nowIso, true);
46385
+ const kind = rolled === "completed" ? "graph_completed" : rolled === "failed" ? "graph_failed" : "graph_cancelled";
46386
+ outbox.push({ kind, payload: { graphId: node.graphId, status: rolled } });
46098
46387
  }
46099
46388
  if (materialized.length > 0) {
46100
46389
  outbox.push({ kind: "queue_wake", payload: { meshId: node.meshId, reason: "graph_materialization", graphId: node.graphId } });
@@ -46117,9 +46406,95 @@ ${blocks.join("\n\n")}`;
46117
46406
  function isTerminalEquivalent(n) {
46118
46407
  return n.state === "completed" || n.state === "released" || n.state === "skipped";
46119
46408
  }
46409
+ function maybeOpenCoordinatorGate(store, gateNode, edges, byId, nowIso) {
46410
+ const graphStore = store.graphStore();
46411
+ if (gateNode.state !== "declared" && gateNode.state !== "blocked") return false;
46412
+ const gate = graphStore.findGateByNodeId(gateNode.graphId, gateNode.nodeId);
46413
+ if (!gate || gate.state !== "declared") return false;
46414
+ const incoming = edges.filter((e) => e.toNodeId === gateNode.nodeId);
46415
+ const satisfied = incoming.every((e) => {
46416
+ const sourceState = byId.get(e.fromNodeId)?.state;
46417
+ return sourceState === "completed" || sourceState === "released" || sourceState === "skipped" && e.omitOnSkip;
46418
+ });
46419
+ if (!satisfied) return false;
46420
+ const spec = safeParseJson(gateNode.baseSpecJson);
46421
+ const deadlineSeconds = typeof spec?.deadline_seconds === "number" ? spec.deadline_seconds : void 0;
46422
+ const deadlineAt = deadlineSeconds && deadlineSeconds > 0 ? new Date(Date.parse(nowIso) + deadlineSeconds * 1e3).toISOString() : void 0;
46423
+ graphStore.patchGate(gate.gateId, {
46424
+ state: "awaiting_coordinator",
46425
+ ...deadlineAt ? { deadlineAt } : {}
46426
+ }, nowIso);
46427
+ graphStore.updateNodeState(gateNode.graphId, gateNode.nodeId, "awaiting_coordinator", nowIso);
46428
+ gateNode.state = "awaiting_coordinator";
46429
+ byId.set(gateNode.nodeId, gateNode);
46430
+ const block2 = coordinatorGateBlockReason(gate.gateId);
46431
+ for (const edge of edges.filter((e) => e.fromNodeId === gateNode.nodeId)) {
46432
+ const target = byId.get(edge.toNodeId);
46433
+ if (!target || target.kind !== "worker_task" || !target.queueTaskId) continue;
46434
+ if (target.state !== "declared" && target.state !== "blocked") continue;
46435
+ if (target.state !== "blocked") {
46436
+ graphStore.updateNodeState(target.graphId, target.nodeId, "blocked", nowIso);
46437
+ target.state = "blocked";
46438
+ byId.set(target.nodeId, target);
46439
+ }
46440
+ const entry = store.findQueueEntryById(target.meshId, target.queueTaskId);
46441
+ if (!entry || entry.status !== "pending") continue;
46442
+ const owned = !entry.blockedReason || parseGraphMaterializationBlock(entry.blockedReason) !== null || parseCoordinatorGateBlock(entry.blockedReason) !== null || entry.blockedReason.startsWith("materialization_error:");
46443
+ if (owned && entry.blockedReason !== block2) {
46444
+ entry.blockedReason = block2;
46445
+ store.updateQueueEntry(entry);
46446
+ }
46447
+ }
46448
+ graphStore.insertOutboxEvent({
46449
+ id: newMeshGraphOutboxId(),
46450
+ meshId: gateNode.meshId,
46451
+ graphId: gateNode.graphId,
46452
+ kind: "graph_gate_awaiting",
46453
+ payload: JSON.stringify({
46454
+ graphId: gateNode.graphId,
46455
+ gateId: gate.gateId,
46456
+ nodeId: gateNode.nodeId,
46457
+ ref: gate.ref ?? gateNode.ref,
46458
+ action: gate.action,
46459
+ instructions: gate.instructions,
46460
+ deadlineAt
46461
+ }),
46462
+ status: "pending",
46463
+ attemptCount: 0,
46464
+ createdAt: nowIso,
46465
+ updatedAt: nowIso
46466
+ });
46467
+ const graph = graphStore.getGraph(gateNode.graphId);
46468
+ if (graph?.status === "active") {
46469
+ graphStore.updateGraphStatus(gateNode.graphId, "waiting_gate", nowIso);
46470
+ }
46471
+ return true;
46472
+ }
46473
+ function gateOutcomeOutputForNode(graphStore, gateNode) {
46474
+ const gate = graphStore.findGateByNodeId(gateNode.graphId, gateNode.nodeId);
46475
+ if (!gate || gate.state !== "released") return null;
46476
+ const stored = typeof gate.releaseEvidenceJson === "string" ? safeParseJson(gate.releaseEvidenceJson) : void 0;
46477
+ return {
46478
+ ref: gateNode.ref ?? gate.ref ?? gateNode.nodeId,
46479
+ envelope: {
46480
+ gate_outcome: gate.releaseOutcome,
46481
+ action: gate.action,
46482
+ gate_id: gate.gateId,
46483
+ ref: gate.ref ?? gateNode.ref,
46484
+ result: stored?.result,
46485
+ evidence: stored?.evidence,
46486
+ evidence_digest: gate.releaseEvidenceDigest,
46487
+ released_at: gate.updatedAt
46488
+ }
46489
+ };
46490
+ }
46120
46491
  function settleDownstreamNode(store, target, edges, byId, nowIso) {
46121
46492
  const graphStore = store.graphStore();
46122
46493
  const incoming = edges.filter((e) => e.toNodeId === target.nodeId && e.kind !== "gate");
46494
+ const gateIncoming = edges.filter((e) => e.toNodeId === target.nodeId && e.kind === "gate");
46495
+ for (const edge of gateIncoming) {
46496
+ if (byId.get(edge.fromNodeId)?.state !== "released") return { kind: "deferred" };
46497
+ }
46123
46498
  const skippedSources = incoming.filter((e) => byId.get(e.fromNodeId)?.state === "skipped");
46124
46499
  const propagatingSkip = skippedSources.find((e) => !e.omitOnSkip);
46125
46500
  if (propagatingSkip) {
@@ -46132,6 +46507,12 @@ ${blocks.join("\n\n")}`;
46132
46507
  const queueEntry = store.findQueueEntryById(target.meshId, target.queueTaskId);
46133
46508
  if (!queueEntry) return { kind: "deferred" };
46134
46509
  const outputsByRef = collectUpstreamOutputs(store, activeIncoming, byId);
46510
+ for (const edge of gateIncoming) {
46511
+ const gateNode = byId.get(edge.fromNodeId);
46512
+ if (!gateNode) continue;
46513
+ const output = gateOutcomeOutputForNode(graphStore, gateNode);
46514
+ if (output && !outputsByRef.has(output.ref)) outputsByRef.set(output.ref, output);
46515
+ }
46135
46516
  const baseSpec = safeParseJson(target.baseSpecJson);
46136
46517
  let conditionsHold = true;
46137
46518
  let falseCondition;
@@ -46287,6 +46668,10 @@ ${blocks.join("\n\n")}`;
46287
46668
  }
46288
46669
  if (queueEntry.blockedReason?.startsWith("materialization_error:")) {
46289
46670
  delete queueEntry.blockedReason;
46671
+ return;
46672
+ }
46673
+ if (parseCoordinatorGateBlock(queueEntry.blockedReason)) {
46674
+ delete queueEntry.blockedReason;
46290
46675
  }
46291
46676
  }
46292
46677
  function syncNodeRowState(byId, target, state, patch) {
@@ -46375,6 +46760,7 @@ ${blocks.join("\n\n")}`;
46375
46760
  return result.materialized;
46376
46761
  }
46377
46762
  var GRAPH_BLOCK_PREFIX;
46763
+ var GATE_BLOCK_PREFIX;
46378
46764
  var queueWakeHandler;
46379
46765
  var init_mesh_graph_transition_runner = __esm2({
46380
46766
  "src/mesh/mesh-graph-transition-runner.ts"() {
@@ -46386,7 +46772,9 @@ ${blocks.join("\n\n")}`;
46386
46772
  init_mesh_graph_types();
46387
46773
  init_mesh_graph_input_binding();
46388
46774
  init_mesh_graph_workspace_bind();
46775
+ init_mesh_graph_derived_failure();
46389
46776
  GRAPH_BLOCK_PREFIX = "graph_materialization_pending:";
46777
+ GATE_BLOCK_PREFIX = "coordinator_gate:";
46390
46778
  }
46391
46779
  });
46392
46780
  function formatMeshTaskModeViolations(result) {
@@ -48212,7 +48600,10 @@ ${blocks.join("\n\n")}`;
48212
48600
  return record2 ? { ...record2, status: normalizeMissionStatus(record2.status), source: normalizeMissionSource(record2.source) } : null;
48213
48601
  }
48214
48602
  function summarizeMissionTasks(meshId, missionId) {
48215
- const tasks = getQueue(meshId).filter((task) => task.missionId === missionId);
48603
+ const queue = getQueue(meshId);
48604
+ const tasks = queue.filter((task) => task.missionId === missionId);
48605
+ const statusById = new Map(queue.map((task) => [task.id, task.status]));
48606
+ const depMetaById = new Map(queue.map((task) => [task.id, { blockedReason: task.blockedReason, cancelReason: task.cancelReason, status: task.status }]));
48216
48607
  const aggregate = {
48217
48608
  total: tasks.length,
48218
48609
  pending: 0,
@@ -48229,7 +48620,9 @@ ${blocks.join("\n\n")}`;
48229
48620
  else if (task.status === "completed") aggregate.completed += 1;
48230
48621
  else if (task.status === "failed") aggregate.failed += 1;
48231
48622
  else if (task.status === "cancelled") aggregate.cancelled += 1;
48232
- if (task.status === "pending" && task.blockedReason) aggregate.blocked += 1;
48623
+ if (task.status === "pending" && (task.blockedReason || deriveDependencyFailures(task.dependsOn, statusById, depMetaById).length > 0)) {
48624
+ aggregate.blocked += 1;
48625
+ }
48233
48626
  if (task.updatedAt && (!aggregate.lastActivityAt || task.updatedAt > aggregate.lastActivityAt)) {
48234
48627
  aggregate.lastActivityAt = task.updatedAt;
48235
48628
  }
@@ -48425,6 +48818,7 @@ ${blocks.join("\n\n")}`;
48425
48818
  init_logger();
48426
48819
  init_mesh_runtime_store();
48427
48820
  init_mesh_work_queue();
48821
+ init_mesh_graph_derived_failure();
48428
48822
  init_mesh_task_stats();
48429
48823
  init_mesh_ledger();
48430
48824
  init_mesh_events_pending();
@@ -48857,13 +49251,14 @@ ${blocks.join("\n\n")}`;
48857
49251
  function resolveDependencyFailurePolicy(meshId) {
48858
49252
  try {
48859
49253
  const policy = getMesh(meshId)?.policy ?? {};
48860
- return policy.onDependencyFailure === "cancel" ? "cancel" : "block";
49254
+ return resolveOnDependencyFailurePolicy(policy.onDependencyFailure ?? policy.on_dependency_failure);
48861
49255
  } catch {
48862
49256
  return "block";
48863
49257
  }
48864
49258
  }
48865
49259
  function propagateDependencyFailure(meshId, failedTaskId) {
48866
49260
  const policy = resolveDependencyFailurePolicy(meshId);
49261
+ if (policy !== "cancel") return [];
48867
49262
  const store = MeshRuntimeStore.getInstance();
48868
49263
  const cancelled = [];
48869
49264
  const frontier = [failedTaskId];
@@ -48874,17 +49269,12 @@ ${blocks.join("\n\n")}`;
48874
49269
  for (const dependent of dependents) {
48875
49270
  if (seen.has(dependent.id)) continue;
48876
49271
  seen.add(dependent.id);
48877
- if (policy === "cancel") {
48878
- dependent.status = "cancelled";
48879
- dependent.cancelledAt = (/* @__PURE__ */ new Date()).toISOString();
48880
- dependent.cancelReason = `dependency_failed:${currentId}`;
48881
- store.updateQueueEntry(dependent);
48882
- cancelled.push(dependent);
48883
- frontier.push(dependent.id);
48884
- } else {
48885
- dependent.blockedReason = `dependency_failed:${currentId}`;
48886
- store.updateQueueEntry(dependent);
48887
- }
49272
+ dependent.status = "cancelled";
49273
+ dependent.cancelledAt = (/* @__PURE__ */ new Date()).toISOString();
49274
+ dependent.cancelReason = `dependency_failed:${currentId}`;
49275
+ store.updateQueueEntry(dependent);
49276
+ cancelled.push(dependent);
49277
+ frontier.push(dependent.id);
48888
49278
  }
48889
49279
  }
48890
49280
  return cancelled;
@@ -49180,12 +49570,13 @@ ${blocks.join("\n\n")}`;
49180
49570
  const deps = Array.isArray(entry.dependsOn) ? entry.dependsOn : [];
49181
49571
  return deps.every((depId) => statusById.get(depId) === "completed");
49182
49572
  }
49183
- function describeTaskDependencyState(entry, statusById) {
49573
+ function describeTaskDependencyState(entry, statusById, depMetaById) {
49184
49574
  const deps = Array.isArray(entry.dependsOn) ? entry.dependsOn : [];
49185
49575
  const waitingOn = deps.filter((depId) => statusById.get(depId) !== "completed");
49186
49576
  return {
49187
49577
  waitingOn,
49188
- dependenciesSatisfied: taskDependenciesSatisfied(entry, statusById)
49578
+ dependenciesSatisfied: taskDependenciesSatisfied(entry, statusById),
49579
+ dependencyFailures: deriveDependencyFailures(entry.dependsOn, statusById, depMetaById)
49189
49580
  };
49190
49581
  }
49191
49582
  function getMeshQueueStats(meshId) {
@@ -49305,6 +49696,7 @@ ${blocks.join("\n\n")}`;
49305
49696
  init_mesh_task_inflight();
49306
49697
  init_mesh_turn_ledger();
49307
49698
  init_mesh_graph_transition_runner();
49699
+ init_mesh_graph_derived_failure();
49308
49700
  init_dist();
49309
49701
  init_mesh_task_mode_guardrail();
49310
49702
  init_mesh_task_mode_guardrail();
@@ -49520,10 +49912,12 @@ ${blocks.join("\n\n")}`;
49520
49912
  CREATE INDEX IF NOT EXISTS idx_mesh_graph_outbox_graph
49521
49913
  ON mesh_graph_outbox(graph_id, status);
49522
49914
  `);
49915
+ migrateLegacyDependencyFailedQueueBlocks(db);
49523
49916
  }
49524
49917
  var init_mesh_graph_schema = __esm2({
49525
49918
  "src/mesh/mesh-graph-schema.ts"() {
49526
49919
  "use strict";
49920
+ init_mesh_graph_derived_failure();
49527
49921
  }
49528
49922
  });
49529
49923
  function mapGraphRow(r) {
@@ -49704,6 +50098,39 @@ ${blocks.join("\n\n")}`;
49704
50098
  ).get(meshId, batchId);
49705
50099
  return r ? mapGraphRow(r) : null;
49706
50100
  }
50101
+ /**
50102
+ * Phase-E graph listing for the graph view / metrics (design :759-775). Newest
50103
+ * first so a view without an explicit graph id shows current work. `statuses`
50104
+ * narrows to e.g. the in-flight set.
50105
+ */
50106
+ listGraphsByMesh(meshId, opts) {
50107
+ const limit = Math.max(1, Math.min(opts?.limit ?? 50, 500));
50108
+ const statuses = opts?.statuses;
50109
+ if (statuses && statuses.length > 0) {
50110
+ const placeholders = statuses.map(() => "?").join(",");
50111
+ const rows2 = this.db.prepare(
50112
+ `SELECT * FROM mesh_task_graphs WHERE mesh_id = ? AND status IN (${placeholders})
50113
+ ORDER BY created_at DESC LIMIT ?`
50114
+ ).all(meshId, ...statuses, limit);
50115
+ return rows2.map(mapGraphRow);
50116
+ }
50117
+ const rows = this.db.prepare(
50118
+ `SELECT * FROM mesh_task_graphs WHERE mesh_id = ? ORDER BY created_at DESC LIMIT ?`
50119
+ ).all(meshId, limit);
50120
+ return rows.map(mapGraphRow);
50121
+ }
50122
+ /**
50123
+ * Phase-E: replace the graph's normalized policy document. Used at plan-commit
50124
+ * time to attach the enqueue-decision provenance record next to the persisted
50125
+ * `on_dependency_failure` (design :697-710, :733-738). Deliberately a whole-
50126
+ * document write — the policy is normalized once at commit and never patched
50127
+ * field-by-field afterwards.
50128
+ */
50129
+ updateGraphPolicyJson(graphId, policyJson, nowIso) {
50130
+ this.db.prepare(
50131
+ `UPDATE mesh_task_graphs SET policy_json = ?, updated_at = ? WHERE graph_id = ?`
50132
+ ).run(policyJson, nowIso, graphId);
50133
+ }
49707
50134
  /** Phase-B rollup: graph status transition once every node reached a terminal-equivalent state. */
49708
50135
  updateGraphStatus(graphId, status, nowIso, terminal = false) {
49709
50136
  this.db.prepare(`
@@ -49893,6 +50320,79 @@ ${blocks.join("\n\n")}`;
49893
50320
  const r = this.db.prepare(`SELECT * FROM mesh_graph_gates WHERE gate_id = ?`).get(gateId);
49894
50321
  return r ? mapGateRow(r) : null;
49895
50322
  }
50323
+ /** Reverse lookup from a graph node (kind `coordinator_gate`) to its gate row (phase C2). */
50324
+ findGateByNodeId(graphId, nodeId) {
50325
+ const r = this.db.prepare(
50326
+ `SELECT * FROM mesh_graph_gates WHERE graph_id = ? AND node_id = ?`
50327
+ ).get(graphId, nodeId);
50328
+ return r ? mapGateRow(r) : null;
50329
+ }
50330
+ listGatesByGraph(graphId) {
50331
+ const rows = this.db.prepare(
50332
+ `SELECT * FROM mesh_graph_gates WHERE graph_id = ? ORDER BY created_at ASC`
50333
+ ).all(graphId);
50334
+ return rows.map(mapGateRow);
50335
+ }
50336
+ /** Phase-C2 timeout sweep: gates of one mesh, optionally narrowed to states (e.g. awaiting/claimed). */
50337
+ listGatesByMesh(meshId, states) {
50338
+ if (states && states.length > 0) {
50339
+ const placeholders = states.map(() => "?").join(",");
50340
+ const rows2 = this.db.prepare(
50341
+ `SELECT * FROM mesh_graph_gates WHERE mesh_id = ? AND state IN (${placeholders}) ORDER BY created_at ASC`
50342
+ ).all(meshId, ...states);
50343
+ return rows2.map(mapGateRow);
50344
+ }
50345
+ const rows = this.db.prepare(
50346
+ `SELECT * FROM mesh_graph_gates WHERE mesh_id = ? ORDER BY created_at ASC`
50347
+ ).all(meshId);
50348
+ return rows.map(mapGateRow);
50349
+ }
50350
+ /**
50351
+ * Row write for phase C2 (claim / release / deadline sweep). `undefined`
50352
+ * fields are left unchanged; explicit `null` clears a nullable field. The
50353
+ * optional generation CAS rejects a stale fenced writer: the update lands
50354
+ * only while the row still carries `cas.leaseGeneration`.
50355
+ */
50356
+ patchGate(gateId, patch, nowIso, cas) {
50357
+ const current = this.getGate(gateId);
50358
+ if (!current) return false;
50359
+ if (cas && current.leaseGeneration !== cas.leaseGeneration) return false;
50360
+ const next = {
50361
+ state: patch.state ?? current.state,
50362
+ leaseOwnerSessionId: patch.leaseOwnerSessionId === void 0 ? current.leaseOwnerSessionId ?? null : patch.leaseOwnerSessionId,
50363
+ leaseGeneration: patch.leaseGeneration ?? current.leaseGeneration,
50364
+ fencingToken: patch.fencingToken === void 0 ? current.fencingToken ?? null : patch.fencingToken,
50365
+ leaseExpiresAt: patch.leaseExpiresAt === void 0 ? current.leaseExpiresAt ?? null : patch.leaseExpiresAt,
50366
+ deadlineAt: patch.deadlineAt === void 0 ? current.deadlineAt ?? null : patch.deadlineAt,
50367
+ releaseOutcome: patch.releaseOutcome === void 0 ? current.releaseOutcome ?? null : patch.releaseOutcome,
50368
+ releaseEvidenceJson: patch.releaseEvidenceJson === void 0 ? current.releaseEvidenceJson ?? null : patch.releaseEvidenceJson,
50369
+ releaseEvidenceDigest: patch.releaseEvidenceDigest === void 0 ? current.releaseEvidenceDigest ?? null : patch.releaseEvidenceDigest,
50370
+ releaseIdempotencyKey: patch.releaseIdempotencyKey === void 0 ? current.releaseIdempotencyKey ?? null : patch.releaseIdempotencyKey
50371
+ };
50372
+ const r = this.db.prepare(`
50373
+ UPDATE mesh_graph_gates
50374
+ SET state = ?, lease_owner_session_id = ?, lease_generation = ?, fencing_token = ?,
50375
+ lease_expires_at = ?, deadline_at = ?, release_outcome = ?,
50376
+ release_evidence_json = ?, release_evidence_digest = ?,
50377
+ release_idempotency_key = ?, updated_at = ?
50378
+ WHERE gate_id = ? AND lease_generation = ?
50379
+ `).run(
50380
+ next.state,
50381
+ next.leaseOwnerSessionId,
50382
+ next.leaseGeneration,
50383
+ next.fencingToken,
50384
+ next.leaseExpiresAt,
50385
+ next.deadlineAt,
50386
+ next.releaseOutcome,
50387
+ next.releaseEvidenceJson,
50388
+ next.releaseEvidenceDigest,
50389
+ next.releaseIdempotencyKey,
50390
+ nowIso,
50391
+ gateId,
50392
+ current.leaseGeneration
50393
+ );
50394
+ return r.changes > 0;
50395
+ }
49896
50396
  // ── mesh_graph_workspace_intents ─────────────────────────────────────────
49897
50397
  insertWorkspaceIntent(row) {
49898
50398
  this.db.prepare(`
@@ -56325,6 +56825,10 @@ Default branch: \`${mesh.defaultBranch}\`` : ""}`);
56325
56825
  if (policy.coordinatorIdlePushPolicy === "auto_silent_on_dispatch") {
56326
56826
  rules.push("- Delegated-worker completions are **auto-silenced**: the routine idle/completion push for a task you dispatch is suppressed once (approval-needed, failure, and long-running alerts still notify the owner normally)");
56327
56827
  }
56828
+ const failurePolicy = policy.onDependencyFailure === "cancel" ? "cancel" : "block";
56829
+ rules.push(
56830
+ `- on_dependency_failure: **${failurePolicy}** \u2014 controls downstream tasks when a required worker task fails or is cancelled. \`block\` (default) keeps downstream pending and automatically recovers if the predecessor is retried and later completes. \`cancel\` terminally cancels the dependent branch; it is not revived by predecessor retry.`
56831
+ );
56328
56832
  return `## Policy
56329
56833
  ${rules.join("\n")}`;
56330
56834
  }
@@ -56401,8 +56905,11 @@ When you compose the task message you dispatch to a node, include this requireme
56401
56905
  | \`mesh_status\` | Nodes' health, git state, sessions, branch convergence |
56402
56906
  | \`mesh_list_nodes\` | List nodes with workspace paths |
56403
56907
  | \`mesh_enqueue_task\` | Add a task to the pull-based queue; idle nodes auto-claim |
56404
- | \`mesh_enqueue_batch\` | Atomically enqueue a dependency-wired task set; \`depends_on\` may name batch-local \`ref\`s (forward refs OK) |
56908
+ | \`mesh_enqueue_batch\` | Atomically enqueue a dependency-wired task set; \`depends_on\` may name batch-local \`ref\`s (forward refs OK). Also carries the full graph surface: \`inputs_from\`, \`run_if\`, \`gates\` + \`gated_by\`, \`workspaces\` + \`workspace_ref\` |
56405
56909
  | \`mesh_view_queue\` | Queue status \u2014 pending/assigned/completed/failed/cancelled |
56910
+ | \`mesh_graph_view\` | Inspect orchestration graphs \u2014 node states, gates awaiting you, workspace sagas, why something is blocked |
56911
+ | \`mesh_graph_gate_claim\` | Take the lease on a gate awaiting a coordinator; returns the fencing token + generation a release needs |
56912
+ | \`mesh_graph_gate_release\` | Pass a gate you hold \u2014 the ONLY way through one (no timeout ever passes a gate) |
56406
56913
  | \`mesh_queue_cancel\` | Cancel a queue task (audit history kept) |
56407
56914
  | \`mesh_queue_requeue\` | Return a task to pending for retry |
56408
56915
  | \`mesh_send_task\` | Push a task straight to a specific node/session |
@@ -59764,6 +60271,593 @@ ${rendered}`, "utf-8");
59764
60271
  ACTIVE_SAGA_STATES = ["declared", "preparing", "compensating"];
59765
60272
  }
59766
60273
  });
60274
+ function readGateSpec(node) {
60275
+ if (!node) return {};
60276
+ try {
60277
+ const parsed = JSON.parse(node.baseSpecJson);
60278
+ return parsed && typeof parsed === "object" ? parsed : {};
60279
+ } catch {
60280
+ return {};
60281
+ }
60282
+ }
60283
+ function isoAfter(nowMs, seconds) {
60284
+ return new Date(nowMs + seconds * 1e3).toISOString();
60285
+ }
60286
+ function claimMeshGraphGate(input) {
60287
+ const store = MeshRuntimeStore.getInstance();
60288
+ const nowMs = input.nowMs ?? Date.now();
60289
+ const nowIso = new Date(nowMs).toISOString();
60290
+ const outboxEvents = [];
60291
+ const result = store.transaction(() => {
60292
+ const graphStore = store.graphStore();
60293
+ const gate = graphStore.getGate(input.gateId);
60294
+ if (!gate || gate.meshId !== input.meshId) return { claimed: false, reason: "gate_not_found" };
60295
+ if (gate.eligibleCoordinatorSessionId && gate.eligibleCoordinatorSessionId !== input.coordinatorSessionId) {
60296
+ return { claimed: false, reason: "gate_not_eligible" };
60297
+ }
60298
+ if (gate.state === "released" || gate.state === "cancelled") {
60299
+ return { claimed: false, reason: `gate_terminal:${gate.state}` };
60300
+ }
60301
+ if (gate.state === "declared") {
60302
+ return { claimed: false, reason: "gate_not_awaiting" };
60303
+ }
60304
+ const leaseLive = !!gate.leaseExpiresAt && gate.leaseExpiresAt > nowIso;
60305
+ const sameOwner = gate.leaseOwnerSessionId === input.coordinatorSessionId;
60306
+ const priorState = gate.state;
60307
+ let takeoverFromClaimed = false;
60308
+ if (priorState === "claimed" && leaseLive && !sameOwner) {
60309
+ return { claimed: false, reason: "gate_lease_held", gate };
60310
+ }
60311
+ if (priorState === "expired" && gate.onTimeout !== "hold") {
60312
+ return { claimed: false, reason: "gate_terminal:expired", gate };
60313
+ }
60314
+ const node = graphStore.getNode(gate.graphId, gate.nodeId);
60315
+ const spec = readGateSpec(node);
60316
+ const leaseSeconds = input.leaseSeconds ?? spec.lease_seconds ?? MESH_GATE_DEFAULT_LEASE_SECONDS;
60317
+ const leaseExpiresAt = isoAfter(nowMs, leaseSeconds);
60318
+ let generation;
60319
+ let fencingToken;
60320
+ if (priorState === "claimed" && sameOwner && leaseLive) {
60321
+ generation = gate.leaseGeneration;
60322
+ fencingToken = gate.fencingToken;
60323
+ } else {
60324
+ takeoverFromClaimed = priorState === "claimed";
60325
+ generation = gate.leaseGeneration + 1;
60326
+ fencingToken = (0, import_crypto13.randomUUID)();
60327
+ }
60328
+ const deadlineAt = input.extendDeadlineSeconds && input.extendDeadlineSeconds > 0 ? isoAfter(nowMs, input.extendDeadlineSeconds) : gate.deadlineAt;
60329
+ const won = graphStore.patchGate(gate.gateId, {
60330
+ state: "claimed",
60331
+ leaseOwnerSessionId: input.coordinatorSessionId,
60332
+ leaseGeneration: generation,
60333
+ fencingToken,
60334
+ leaseExpiresAt,
60335
+ ...deadlineAt !== void 0 ? { deadlineAt } : {}
60336
+ }, nowIso, { leaseGeneration: gate.leaseGeneration });
60337
+ if (!won) return { claimed: false, reason: "gate_claim_race" };
60338
+ if (node && node.state === "expired") {
60339
+ graphStore.updateNodeState(gate.graphId, gate.nodeId, "awaiting_coordinator", nowIso);
60340
+ }
60341
+ if (takeoverFromClaimed) {
60342
+ outboxEvents.push({
60343
+ kind: "graph_gate_lease_expired",
60344
+ payload: {
60345
+ graphId: gate.graphId,
60346
+ gateId: gate.gateId,
60347
+ ref: gate.ref,
60348
+ previousOwnerSessionId: gate.leaseOwnerSessionId,
60349
+ previousGeneration: gate.leaseGeneration,
60350
+ newGeneration: generation
60351
+ }
60352
+ });
60353
+ }
60354
+ outboxEvents.push({
60355
+ kind: "graph_gate_claimed",
60356
+ payload: {
60357
+ graphId: gate.graphId,
60358
+ gateId: gate.gateId,
60359
+ ref: gate.ref,
60360
+ action: gate.action,
60361
+ ownerSessionId: input.coordinatorSessionId,
60362
+ generation,
60363
+ leaseExpiresAt
60364
+ }
60365
+ });
60366
+ for (const event of outboxEvents) {
60367
+ graphStore.insertOutboxEvent({
60368
+ id: newMeshGraphOutboxId(),
60369
+ meshId: gate.meshId,
60370
+ graphId: gate.graphId,
60371
+ kind: event.kind,
60372
+ payload: JSON.stringify(event.payload),
60373
+ status: "pending",
60374
+ attemptCount: 0,
60375
+ createdAt: nowIso,
60376
+ updatedAt: nowIso
60377
+ });
60378
+ }
60379
+ return {
60380
+ claimed: true,
60381
+ gate: graphStore.getGate(gate.gateId),
60382
+ leaseGeneration: generation,
60383
+ fencingToken,
60384
+ leaseExpiresAt,
60385
+ deadlineAt,
60386
+ ambiguousExternalOutcome: takeoverFromClaimed || priorState === "expired" && gate.leaseGeneration > 0,
60387
+ previousLeaseOwnerSessionId: gate.leaseOwnerSessionId
60388
+ };
60389
+ });
60390
+ if (result.claimed) {
60391
+ try {
60392
+ drainMeshGraphOutbox(input.meshId);
60393
+ } catch {
60394
+ }
60395
+ }
60396
+ return result;
60397
+ }
60398
+ function releaseMeshGraphGate(input) {
60399
+ const store = MeshRuntimeStore.getInstance();
60400
+ const nowMs = input.nowMs ?? Date.now();
60401
+ const nowIso = new Date(nowMs).toISOString();
60402
+ const result = store.transaction(() => {
60403
+ const graphStore = store.graphStore();
60404
+ const gate = graphStore.getGate(input.gateId);
60405
+ if (!gate || gate.meshId !== input.meshId) throw new Error(`gate_not_found: no gate '${input.gateId}'`);
60406
+ const releaseDigest = sha256Hex2(canonicalJson({
60407
+ outcome: input.outcome,
60408
+ result: input.result ?? null,
60409
+ evidence: input.evidence ?? null,
60410
+ patches: input.patches ?? []
60411
+ }));
60412
+ if (gate.releaseIdempotencyKey === input.idempotencyKey) {
60413
+ if (gate.releaseEvidenceDigest === releaseDigest) {
60414
+ return { released: true, duplicate: true, gate, materializedNodeIds: [] };
60415
+ }
60416
+ throw new Error(
60417
+ `gate_release_conflict: idempotency key '${input.idempotencyKey}' already committed with a different release digest (gate '${input.gateId}')`
60418
+ );
60419
+ }
60420
+ if (gate.state === "released") {
60421
+ throw new Error(`gate_already_released: gate '${input.gateId}' was released under a different idempotency key`);
60422
+ }
60423
+ if (gate.state !== "claimed") {
60424
+ throw new Error(`gate_not_claimed: gate '${input.gateId}' is '${gate.state}' \u2014 only a claimed gate can be released`);
60425
+ }
60426
+ if (input.fencingToken !== gate.fencingToken || input.leaseGeneration !== gate.leaseGeneration) {
60427
+ throw new Error(
60428
+ `stale_fence: gate '${input.gateId}' is at lease generation ${gate.leaseGeneration}; the presented token/generation (${input.leaseGeneration}) is stale`
60429
+ );
60430
+ }
60431
+ if (gate.leaseExpiresAt && gate.leaseExpiresAt <= nowIso) {
60432
+ throw new Error(
60433
+ `gate_lease_expired: gate '${input.gateId}' lease expired at ${gate.leaseExpiresAt} \u2014 reclaim the gate (higher generation) and reconcile external evidence before releasing`
60434
+ );
60435
+ }
60436
+ const node = graphStore.getNode(gate.graphId, gate.nodeId);
60437
+ if (!node) throw new Error(`graph_node_not_found: gate '${input.gateId}' backs a missing node '${gate.nodeId}'`);
60438
+ const nodes = graphStore.listNodes(gate.graphId);
60439
+ const edges = graphStore.listEdges(gate.graphId);
60440
+ const byId = new Map(nodes.map((n) => [n.nodeId, n]));
60441
+ const incoming = edges.filter((e) => e.toNodeId === node.nodeId);
60442
+ const upstreamSettled = incoming.every((e) => {
60443
+ const sourceState = byId.get(e.fromNodeId)?.state;
60444
+ return sourceState === "completed" || sourceState === "released" || sourceState === "skipped" && e.omitOnSkip;
60445
+ });
60446
+ if (!upstreamSettled) {
60447
+ throw new Error(`gate_upstream_unsettled: gate '${input.gateId}' has unsatisfied predecessors`);
60448
+ }
60449
+ const directDownstream = new Set(edges.filter((e) => e.fromNodeId === node.nodeId).map((e) => e.toNodeId));
60450
+ for (const patch of input.patches ?? []) {
60451
+ const target = nodes.find((n) => n.nodeId === patch.node || n.ref === patch.node);
60452
+ if (!target || !directDownstream.has(target.nodeId)) {
60453
+ throw new Error(`gate_patch_not_downstream: '${patch.node}' is not a direct downstream node of gate '${input.gateId}'`);
60454
+ }
60455
+ for (const key2 of Object.keys(patch.baseSpecPatch)) {
60456
+ if (!MESH_GATE_RELEASE_PATCH_KEYS.includes(key2)) {
60457
+ throw new Error(`gate_patch_forbidden: key '${key2}' is outside the permitted release patch surface (design :294-299)`);
60458
+ }
60459
+ }
60460
+ if (target.queueTaskId) {
60461
+ const entry = store.findQueueEntryById(target.meshId, target.queueTaskId);
60462
+ if (entry && entry.status !== "pending") {
60463
+ throw new Error(
60464
+ `task_already_claimed: gate release cannot patch node '${target.nodeId}' \u2014 queue task '${target.queueTaskId}' is '${entry.status}' and immutable (design :334)`
60465
+ );
60466
+ }
60467
+ }
60468
+ const rawSpec = (() => {
60469
+ try {
60470
+ return JSON.parse(target.baseSpecJson);
60471
+ } catch {
60472
+ return {};
60473
+ }
60474
+ })();
60475
+ graphStore.updateNodeBaseSpec(
60476
+ target.graphId,
60477
+ target.nodeId,
60478
+ JSON.stringify({ ...rawSpec && typeof rawSpec === "object" ? rawSpec : {}, ...patch.baseSpecPatch }),
60479
+ nowIso
60480
+ );
60481
+ const inMap = byId.get(target.nodeId);
60482
+ if (inMap) inMap.materializationVersion += 1;
60483
+ }
60484
+ const won = graphStore.patchGate(gate.gateId, {
60485
+ state: "released",
60486
+ releaseOutcome: input.outcome,
60487
+ releaseEvidenceJson: canonicalJson({ result: input.result ?? null, evidence: input.evidence ?? null }),
60488
+ releaseEvidenceDigest: releaseDigest,
60489
+ releaseIdempotencyKey: input.idempotencyKey
60490
+ }, nowIso, { leaseGeneration: gate.leaseGeneration });
60491
+ if (!won) throw new Error(`stale_fence: gate '${input.gateId}' moved under the release (generation race)`);
60492
+ graphStore.updateNodeState(gate.graphId, node.nodeId, "released", nowIso);
60493
+ const mapped = byId.get(node.nodeId);
60494
+ if (mapped) mapped.state = "released";
60495
+ const materializedNodeIds = advanceReleasedGateDownstream(store, gate, node, nowIso);
60496
+ const freshNodes = graphStore.listNodes(gate.graphId);
60497
+ const graph = graphStore.getGraph(gate.graphId);
60498
+ if (graph && freshNodes.every(isTerminalEquivalent)) {
60499
+ graphStore.updateGraphStatus(gate.graphId, "completed", nowIso, true);
60500
+ insertGateOutbox(graphStore, gate.meshId, gate.graphId, "graph_completed", { graphId: gate.graphId }, nowIso);
60501
+ } else if (graph?.status === "waiting_gate") {
60502
+ const stillWaiting = graphStore.listGatesByGraph(gate.graphId).some((g) => g.gateId !== gate.gateId && (g.state === "awaiting_coordinator" || g.state === "claimed"));
60503
+ if (!stillWaiting) graphStore.updateGraphStatus(gate.graphId, "active", nowIso);
60504
+ }
60505
+ insertGateOutbox(graphStore, gate.meshId, gate.graphId, "graph_gate_released", {
60506
+ graphId: gate.graphId,
60507
+ gateId: gate.gateId,
60508
+ nodeId: node.nodeId,
60509
+ ref: gate.ref,
60510
+ action: gate.action,
60511
+ outcome: input.outcome,
60512
+ releaseDigest,
60513
+ generation: gate.leaseGeneration,
60514
+ materializedNodeIds
60515
+ }, nowIso);
60516
+ if (materializedNodeIds.length > 0) {
60517
+ insertGateOutbox(graphStore, gate.meshId, gate.graphId, "queue_wake", {
60518
+ meshId: gate.meshId,
60519
+ reason: "graph_gate_released",
60520
+ graphId: gate.graphId,
60521
+ gateId: gate.gateId
60522
+ }, nowIso);
60523
+ }
60524
+ return { released: true, duplicate: false, gate: graphStore.getGate(gate.gateId), materializedNodeIds };
60525
+ });
60526
+ try {
60527
+ drainMeshGraphOutbox(input.meshId);
60528
+ } catch {
60529
+ }
60530
+ return result;
60531
+ }
60532
+ function advanceReleasedGateDownstream(store, gate, gateNode, nowIso) {
60533
+ const graphStore = store.graphStore();
60534
+ const nodes = graphStore.listNodes(gate.graphId);
60535
+ const edges = graphStore.listEdges(gate.graphId);
60536
+ const byId = new Map(nodes.map((n) => [n.nodeId, n]));
60537
+ const mappedGate = byId.get(gateNode.nodeId);
60538
+ if (mappedGate) mappedGate.state = "released";
60539
+ const materialized = [];
60540
+ let frontier = /* @__PURE__ */ new Set([gateNode.nodeId]);
60541
+ for (let pass = 0; pass < nodes.length + 1 && frontier.size > 0; pass += 1) {
60542
+ const nextFrontier = /* @__PURE__ */ new Set();
60543
+ const downstreamIds = new Set(edges.filter((e) => frontier.has(e.fromNodeId)).map((e) => e.toNodeId));
60544
+ for (const targetId of downstreamIds) {
60545
+ const target = byId.get(targetId);
60546
+ if (!target) continue;
60547
+ if (target.kind === "coordinator_gate") {
60548
+ maybeOpenCoordinatorGate(store, target, edges, byId, nowIso);
60549
+ continue;
60550
+ }
60551
+ if (target.kind !== "worker_task" || !target.queueTaskId) continue;
60552
+ if (target.state !== "declared" && target.state !== "blocked") continue;
60553
+ clearReleasedGateHold(store, target, gate.gateId);
60554
+ const outcome = settleDownstreamNode(store, target, edges, byId, nowIso);
60555
+ if (outcome.kind === "materialized") {
60556
+ materialized.push(target.nodeId);
60557
+ insertGateOutbox(graphStore, target.meshId, target.graphId, "graph_node_materialized", {
60558
+ graphId: target.graphId,
60559
+ nodeId: target.nodeId,
60560
+ ref: target.ref,
60561
+ taskId: target.queueTaskId,
60562
+ gateId: gate.gateId,
60563
+ materializationVersion: target.materializationVersion,
60564
+ digest: outcome.digest,
60565
+ receipts: outcome.receipts
60566
+ }, nowIso);
60567
+ } else if (outcome.kind === "skipped") {
60568
+ nextFrontier.add(target.nodeId);
60569
+ insertGateOutbox(graphStore, target.meshId, target.graphId, "graph_node_skipped", {
60570
+ graphId: target.graphId,
60571
+ nodeId: target.nodeId,
60572
+ ref: target.ref,
60573
+ taskId: target.queueTaskId,
60574
+ gateId: gate.gateId,
60575
+ reason: outcome.reason
60576
+ }, nowIso);
60577
+ } else if (outcome.kind === "error") {
60578
+ insertGateOutbox(graphStore, target.meshId, target.graphId, "graph_node_materialization_failed", {
60579
+ graphId: target.graphId,
60580
+ nodeId: target.nodeId,
60581
+ ref: target.ref,
60582
+ taskId: target.queueTaskId,
60583
+ gateId: gate.gateId,
60584
+ blockedReason: outcome.blockedReason
60585
+ }, nowIso);
60586
+ } else {
60587
+ const entry = store.findQueueEntryById(target.meshId, target.queueTaskId);
60588
+ if (entry && entry.status === "pending" && !entry.blockedReason) {
60589
+ entry.blockedReason = graphMaterializationBlockReason(target.nodeId, target.materializationVersion);
60590
+ store.updateQueueEntry(entry);
60591
+ }
60592
+ }
60593
+ }
60594
+ frontier = nextFrontier;
60595
+ }
60596
+ return materialized;
60597
+ }
60598
+ function clearReleasedGateHold(store, target, gateId) {
60599
+ if (!target.queueTaskId) return;
60600
+ const entry = store.findQueueEntryById(target.meshId, target.queueTaskId);
60601
+ if (!entry || entry.status !== "pending") return;
60602
+ const hold = parseCoordinatorGateBlock(entry.blockedReason);
60603
+ if (hold && hold.gateId === gateId) {
60604
+ delete entry.blockedReason;
60605
+ store.updateQueueEntry(entry);
60606
+ }
60607
+ }
60608
+ function sweepMeshGraphGateTimeouts(meshId, nowMs) {
60609
+ const store = MeshRuntimeStore.getInstance();
60610
+ const now = nowMs ?? Date.now();
60611
+ const nowIso = new Date(now).toISOString();
60612
+ const result = store.transaction(() => {
60613
+ const graphStore = store.graphStore();
60614
+ const candidates = graphStore.listGatesByMesh(meshId, ["awaiting_coordinator", "claimed"]);
60615
+ const expiredLeaseGateIds = candidates.filter((g) => g.state === "claimed" && g.leaseExpiresAt && g.leaseExpiresAt <= nowIso).map((g) => g.gateId);
60616
+ const expiredGateIds = [];
60617
+ for (const gate of candidates) {
60618
+ if (!gate.deadlineAt || gate.deadlineAt > nowIso) continue;
60619
+ const node = graphStore.getNode(gate.graphId, gate.nodeId);
60620
+ const won = graphStore.patchGate(gate.gateId, { state: "expired" }, nowIso, { leaseGeneration: gate.leaseGeneration });
60621
+ if (!won) continue;
60622
+ if (node && node.state !== "expired") {
60623
+ graphStore.updateNodeState(gate.graphId, gate.nodeId, "expired", nowIso);
60624
+ }
60625
+ let cancelledNodeIds = [];
60626
+ if (gate.onTimeout === "cancel_downstream" && node) {
60627
+ cancelledNodeIds = cancelGateDownstreamSubtree(store, node, nowIso);
60628
+ } else if (gate.onTimeout === "fail_graph") {
60629
+ graphStore.updateGraphStatus(gate.graphId, "failed", nowIso, true);
60630
+ }
60631
+ insertGateOutbox(graphStore, gate.meshId, gate.graphId, "graph_gate_expired", {
60632
+ graphId: gate.graphId,
60633
+ gateId: gate.gateId,
60634
+ nodeId: gate.nodeId,
60635
+ ref: gate.ref,
60636
+ action: gate.action,
60637
+ policy: gate.onTimeout,
60638
+ deadlineAt: gate.deadlineAt,
60639
+ urgent: true,
60640
+ ...cancelledNodeIds.length > 0 ? { cancelledNodeIds } : {}
60641
+ }, nowIso);
60642
+ expiredGateIds.push(gate.gateId);
60643
+ }
60644
+ return { expiredGateIds, expiredLeaseGateIds };
60645
+ });
60646
+ if (result.expiredGateIds.length > 0) {
60647
+ try {
60648
+ drainMeshGraphOutbox(meshId);
60649
+ } catch {
60650
+ }
60651
+ }
60652
+ if (result.expiredGateIds.length > 0 || result.expiredLeaseGateIds.length > 0) {
60653
+ LOG2.info("MeshGraph", `Gate sweep for mesh ${meshId}: expired=[${result.expiredGateIds.join(",")}] lease-lapsed=[${result.expiredLeaseGateIds.join(",")}]`);
60654
+ }
60655
+ return result;
60656
+ }
60657
+ function isCancelExempt(state) {
60658
+ return state === "completed" || state === "released" || state === "skipped" || state === "cancelled" || state === "failed" || state === "expired";
60659
+ }
60660
+ function cancelGateDownstreamSubtree(store, gateNode, nowIso) {
60661
+ const graphStore = store.graphStore();
60662
+ const nodes = graphStore.listNodes(gateNode.graphId);
60663
+ const edges = graphStore.listEdges(gateNode.graphId);
60664
+ const byId = new Map(nodes.map((n) => [n.nodeId, n]));
60665
+ const cancelled = [];
60666
+ const visited = /* @__PURE__ */ new Set([gateNode.nodeId]);
60667
+ let frontier = [gateNode.nodeId];
60668
+ while (frontier.length > 0) {
60669
+ const next = [];
60670
+ for (const id of frontier) {
60671
+ for (const edge of edges.filter((e) => e.fromNodeId === id)) {
60672
+ if (visited.has(edge.toNodeId)) continue;
60673
+ visited.add(edge.toNodeId);
60674
+ const target = byId.get(edge.toNodeId);
60675
+ if (!target || isCancelExempt(target.state)) continue;
60676
+ graphStore.updateNodeState(target.graphId, target.nodeId, "cancelled", nowIso, {
60677
+ failureReason: `coordinator_gate_timeout:${gateNode.nodeId}`
60678
+ });
60679
+ if (target.queueTaskId) {
60680
+ const entry = store.findQueueEntryById(target.meshId, target.queueTaskId);
60681
+ if (entry && entry.status === "pending") {
60682
+ entry.status = "cancelled";
60683
+ entry.blockedReason = `coordinator_gate_timeout:${gateNode.nodeId}`;
60684
+ store.updateQueueEntry(entry);
60685
+ }
60686
+ }
60687
+ cancelled.push(target.nodeId);
60688
+ next.push(target.nodeId);
60689
+ }
60690
+ }
60691
+ frontier = next;
60692
+ }
60693
+ return cancelled;
60694
+ }
60695
+ function insertGateOutbox(graphStore, meshId, graphId, kind, payload, nowIso) {
60696
+ graphStore.insertOutboxEvent({
60697
+ id: newMeshGraphOutboxId(),
60698
+ meshId,
60699
+ graphId,
60700
+ kind,
60701
+ payload: JSON.stringify(payload),
60702
+ status: "pending",
60703
+ attemptCount: 0,
60704
+ createdAt: nowIso,
60705
+ updatedAt: nowIso
60706
+ });
60707
+ }
60708
+ var import_crypto13;
60709
+ var MESH_GATE_DEFAULT_LEASE_SECONDS;
60710
+ var MESH_GATE_NAMED_OUTCOMES;
60711
+ var MESH_GATE_RELEASE_PATCH_KEYS;
60712
+ var init_mesh_graph_gates = __esm2({
60713
+ "src/mesh/mesh-graph-gates.ts"() {
60714
+ "use strict";
60715
+ import_crypto13 = require("crypto");
60716
+ init_mesh_runtime_store();
60717
+ init_logger();
60718
+ init_mesh_graph_input_binding();
60719
+ init_mesh_graph_types();
60720
+ init_mesh_graph_transition_runner();
60721
+ init_mesh_graph_transition_runner();
60722
+ MESH_GATE_DEFAULT_LEASE_SECONDS = 900;
60723
+ MESH_GATE_NAMED_OUTCOMES = ["passed", "failed", "rejected"];
60724
+ MESH_GATE_RELEASE_PATCH_KEYS = ["run_if", "on_false", "inputs_from", "workspace_ref"];
60725
+ }
60726
+ });
60727
+ function normalizeOrchestrationDecision(raw, surface) {
60728
+ const source = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
60729
+ const readCount = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.floor(value) : void 0;
60730
+ const readyWorkerTasks = readCount(source.ready_worker_tasks ?? source.readyWorkerTasks);
60731
+ const knownGraphSteps = readCount(source.known_graph_steps ?? source.knownGraphSteps);
60732
+ const rawReason = source.single_reason ?? source.singleReason;
60733
+ const singleReason = typeof rawReason === "string" && rawReason.trim() ? rawReason.trim() : null;
60734
+ const rawBlockers = source.capability_blockers ?? source.capabilityBlockers;
60735
+ const blockers = Array.isArray(rawBlockers) ? rawBlockers.filter((b) => typeof b === "string" && b.trim().length > 0).map((b) => b.trim()) : [];
60736
+ const decision = {
60737
+ decision: surface,
60738
+ ...readyWorkerTasks !== void 0 ? { ready_worker_tasks: readyWorkerTasks } : {},
60739
+ ...knownGraphSteps !== void 0 ? { known_graph_steps: knownGraphSteps } : {},
60740
+ single_reason: surface === "single" ? singleReason : null,
60741
+ ...blockers.length > 0 ? { capability_blockers: blockers } : {}
60742
+ };
60743
+ const result = { decision };
60744
+ if (surface !== "single") return result;
60745
+ const superseded = [singleReason, ...blockers].find(
60746
+ (value) => !!value && MESH_SUPERSEDED_SINGLE_REASONS.includes(value)
60747
+ );
60748
+ if (superseded) {
60749
+ result.batchCapabilityAvailable = {
60750
+ code: "batch_capability_available",
60751
+ reportedReason: superseded,
60752
+ message: `'${superseded}' is no longer a blocker: mesh_enqueue_batch supports selected predecessor outputs (inputs_from), delayed worktree preparation (workspace_ref) and coordinator gates. Declare the whole known plan in one batch instead of enqueueing the steps separately.`
60753
+ };
60754
+ }
60755
+ if (knownGraphSteps !== void 0 && knownGraphSteps >= 2) {
60756
+ result.declaredEligibleSingle = true;
60757
+ }
60758
+ return result;
60759
+ }
60760
+ function safeAppend(meshId, kind, payload, taskId) {
60761
+ try {
60762
+ appendLedgerEntry(meshId, { kind, ...taskId ? { taskId } : {}, payload });
60763
+ } catch (e) {
60764
+ LOG2.warn("MeshGraph", `Ledger provenance append (${kind}) failed: ${e?.message || e}`);
60765
+ }
60766
+ }
60767
+ function recordGraphEnqueueCommitted(meshId, p) {
60768
+ safeAppend(meshId, "graph_enqueue_committed", {
60769
+ graphId: p.graphId,
60770
+ batchId: p.batchId,
60771
+ enqueueSurface: p.enqueueSurface,
60772
+ schemaVersion: p.schemaVersion,
60773
+ planDigest: p.planDigest,
60774
+ ...p.missionId ? { missionId: p.missionId } : {},
60775
+ ...p.coordinatorSessionId ? { coordinatorSessionId: p.coordinatorSessionId } : {},
60776
+ taskCount: p.taskCount,
60777
+ gateCount: p.gateCount,
60778
+ workspaceCount: p.workspaceCount,
60779
+ dependencyEdgeCount: p.dependencyEdgeCount,
60780
+ onDependencyFailure: p.onDependencyFailure,
60781
+ ...p.orchestrationDecision ? { orchestrationDecision: p.orchestrationDecision } : {},
60782
+ ...p.replayed ? { replayed: true } : {}
60783
+ });
60784
+ }
60785
+ function recordGraphEnqueueValidationFailed(meshId, p) {
60786
+ safeAppend(meshId, "graph_enqueue_validation_failed", {
60787
+ code: p.code,
60788
+ ...p.batchId ? { batchId: p.batchId } : {},
60789
+ ...p.taskCount !== void 0 ? { taskCount: p.taskCount } : {},
60790
+ ...p.gateCount !== void 0 ? { gateCount: p.gateCount } : {},
60791
+ ...p.workspaceCount !== void 0 ? { workspaceCount: p.workspaceCount } : {},
60792
+ ...p.orchestrationDecision ? { orchestrationDecision: p.orchestrationDecision } : {}
60793
+ });
60794
+ }
60795
+ function recordGraphEnqueueRolledBack(meshId, p) {
60796
+ safeAppend(meshId, "graph_enqueue_rolled_back", {
60797
+ code: p.code,
60798
+ ...p.batchId ? { batchId: p.batchId } : {},
60799
+ ...p.taskCount !== void 0 ? { taskCount: p.taskCount } : {},
60800
+ // The error STRING is a validation message authored by this codebase
60801
+ // (never worker output or a task message), so it is safe provenance.
60802
+ ...p.error ? { error: p.error.slice(0, 500) } : {}
60803
+ });
60804
+ }
60805
+ function recordGraphGateClaimed(meshId, p) {
60806
+ safeAppend(meshId, "graph_gate_claimed", {
60807
+ graphId: p.graphId,
60808
+ gateId: p.gateId,
60809
+ ...p.ref ? { ref: p.ref } : {},
60810
+ action: p.action,
60811
+ generation: p.generation,
60812
+ ownerSessionId: p.ownerSessionId,
60813
+ ...p.leaseExpiresAt ? { leaseExpiresAt: p.leaseExpiresAt } : {},
60814
+ ...p.ambiguousExternalOutcome ? { ambiguousExternalOutcome: true } : {},
60815
+ ...p.previousLeaseOwnerSessionId ? { previousLeaseOwnerSessionId: p.previousLeaseOwnerSessionId } : {}
60816
+ });
60817
+ }
60818
+ function recordGraphGateReleased(meshId, p) {
60819
+ safeAppend(meshId, "graph_gate_released", {
60820
+ graphId: p.graphId,
60821
+ gateId: p.gateId,
60822
+ ...p.ref ? { ref: p.ref } : {},
60823
+ action: p.action,
60824
+ outcome: p.outcome,
60825
+ generation: p.generation,
60826
+ ...p.releaseDigest ? { releaseDigest: p.releaseDigest } : {},
60827
+ ...p.materializedNodeIds?.length ? { materializedNodeIds: p.materializedNodeIds } : {},
60828
+ ...p.duplicate ? { duplicate: true } : {}
60829
+ });
60830
+ }
60831
+ function recordGraphGateExpired(meshId, p) {
60832
+ safeAppend(meshId, "graph_gate_expired", {
60833
+ gateId: p.gateId,
60834
+ ...p.graphId ? { graphId: p.graphId } : {},
60835
+ policy: p.policy,
60836
+ ...p.deadlineAt ? { deadlineAt: p.deadlineAt } : {},
60837
+ ...p.cancelledNodeIds?.length ? { cancelledNodeIds: p.cancelledNodeIds } : {}
60838
+ });
60839
+ }
60840
+ var MESH_VALID_SINGLE_REASONS;
60841
+ var MESH_SUPERSEDED_SINGLE_REASONS;
60842
+ var init_mesh_graph_provenance = __esm2({
60843
+ "src/mesh/mesh-graph-provenance.ts"() {
60844
+ "use strict";
60845
+ init_mesh_ledger();
60846
+ init_logger();
60847
+ MESH_VALID_SINGLE_REASONS = [
60848
+ "only_one_step_known",
60849
+ "future_step_not_specifiable",
60850
+ "same_session_continuation",
60851
+ "legacy_client",
60852
+ "operator_override"
60853
+ ];
60854
+ MESH_SUPERSEDED_SINGLE_REASONS = [
60855
+ "output_needed",
60856
+ "workspace_unresolved",
60857
+ "coordinator_action_between"
60858
+ ];
60859
+ }
60860
+ });
59767
60861
  function turnProjectionActiveWorkStatus(meshId, taskId) {
59768
60862
  const row = resolveTurnAttemptRow({ meshId, taskId });
59769
60863
  if (!row) return null;
@@ -61805,15 +62899,15 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
61805
62899
  }
61806
62900
  return "";
61807
62901
  }
61808
- function extractFinalAssistantSummaryEvidence(messages, maxChars = DEFAULT_FINAL_SUMMARY_MAX_CHARS) {
61809
- const turnEnd = selectFinalAssistantTurnEndMessage(messages);
62902
+ function extractFinalAssistantSummaryEvidence(messages, maxChars = DEFAULT_FINAL_SUMMARY_MAX_CHARS, opts) {
62903
+ const turnEnd = selectFinalAssistantTurnEndMessage(messages, opts);
61810
62904
  if (!turnEnd) return { finalSummary: "" };
61811
62905
  return {
61812
62906
  finalSummary: flattenContent(turnEnd.content).trim().slice(0, maxChars),
61813
62907
  transcriptMessageAt: readChatMessageTimestampIso(turnEnd)
61814
62908
  };
61815
62909
  }
61816
- function selectFinalAssistantTurnEndMessage(messages) {
62910
+ function selectFinalAssistantTurnEndMessage(messages, opts) {
61817
62911
  if (!Array.isArray(messages) || messages.length === 0) return null;
61818
62912
  let chromeFallbacks = 0;
61819
62913
  for (let i = messages.length - 1; i >= 0; i--) {
@@ -61828,6 +62922,13 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
61828
62922
  chromeFallbacks++;
61829
62923
  continue;
61830
62924
  }
62925
+ const boundaryMs = opts?.turnStartedAtMs;
62926
+ if (typeof boundaryMs === "number" && Number.isFinite(boundaryMs)) {
62927
+ const msgAt = readChatMessageTimestampMs(msg);
62928
+ if (typeof msgAt === "number" && Number.isFinite(msgAt) && msgAt >= boundaryMs && msgAt - boundaryMs < FINAL_ANSWER_MIN_TURN_AGE_MS && Date.now() - msgAt < FINAL_ANSWER_MIN_TURN_AGE_MS) {
62929
+ return null;
62930
+ }
62931
+ }
61831
62932
  return msg;
61832
62933
  }
61833
62934
  return null;
@@ -62164,6 +63265,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
62164
63265
  return (Array.isArray(messages) ? messages : []).filter((message) => classifyChatMessageVisibility(message).surface === surface);
62165
63266
  }
62166
63267
  var DEFAULT_FINAL_SUMMARY_MAX_CHARS;
63268
+ var FINAL_ANSWER_MIN_TURN_AGE_MS;
62167
63269
  var FINAL_SUMMARY_CHROME_FALLBACK_MAX_DEPTH;
62168
63270
  var TRANSCRIPT_CHROME_HARD_LINE_PATTERNS;
62169
63271
  var TRANSCRIPT_CHROME_PANEL_LINE_PATTERNS;
@@ -62187,6 +63289,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
62187
63289
  "use strict";
62188
63290
  init_contracts2();
62189
63291
  DEFAULT_FINAL_SUMMARY_MAX_CHARS = 16e3;
63292
+ FINAL_ANSWER_MIN_TURN_AGE_MS = 3e4;
62190
63293
  FINAL_SUMMARY_CHROME_FALLBACK_MAX_DEPTH = 2;
62191
63294
  TRANSCRIPT_CHROME_HARD_LINE_PATTERNS = [
62192
63295
  // Bottom status bar: "auto K3 thinking: high ~/Work/adhdev main [±]"
@@ -66765,7 +67868,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
66765
67868
  const fingerprint = `${target}::${buildPendingEventFingerprint(fingerprintSource)}`;
66766
67869
  try {
66767
67870
  const inserted = store.insertPendingEvent({
66768
- id: (0, import_crypto13.randomUUID)(),
67871
+ id: (0, import_crypto15.randomUUID)(),
66769
67872
  meshId: UNRESOLVED_FORWARD_OUTBOX_MESH_ID,
66770
67873
  coordinatorDaemonId: target,
66771
67874
  event,
@@ -66828,14 +67931,14 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
66828
67931
  return 0;
66829
67932
  }
66830
67933
  }
66831
- var import_crypto13;
67934
+ var import_crypto15;
66832
67935
  var UNRESOLVED_FORWARD_OUTBOX_MESH_ID;
66833
67936
  var UNRESOLVED_FORWARD_MAX_AGE_MS;
66834
67937
  var retryNudgeHandler;
66835
67938
  var init_mesh_unresolved_forward_outbox = __esm2({
66836
67939
  "src/mesh/mesh-unresolved-forward-outbox.ts"() {
66837
67940
  "use strict";
66838
- import_crypto13 = require("crypto");
67941
+ import_crypto15 = require("crypto");
66839
67942
  init_logger();
66840
67943
  init_mesh_runtime_store();
66841
67944
  init_mesh_events_pending();
@@ -69514,6 +70617,15 @@ ${cleanBody}`;
69514
70617
  }
69515
70618
  };
69516
70619
  }
70620
+ if (admission.kind === "admit") {
70621
+ traceMeshEventStage(
70622
+ "terminal_admission_admitted",
70623
+ traceCtx,
70624
+ `${admission.evidenceLevel}:${admission.reason}`
70625
+ );
70626
+ } else {
70627
+ traceMeshEventStage("terminal_admission_not_enforced", traceCtx, admission.reason);
70628
+ }
69517
70629
  }
69518
70630
  if (!readNonEmptyString(args.metadataEvent.taskId) && !sessionHasActiveAssignment(args.meshId, eventSessionId) && !findRecentTerminalLedgerEvidence({ meshId: args.meshId, sessionId: eventSessionId, nodeId: eventNodeId || void 0 }) && isWeakCompletionEvidence(args.metadataEvent)) {
69519
70631
  LOG2.info("MeshEvents", `Suppressed agent:generating_completed for session ${eventSessionId} (mesh ${args.meshId}): no taskId, no active assignment, and no prior terminal ledger evidence \u2014 a pre-dispatch startup/greeting artifact, not a real task completion`);
@@ -69876,13 +70988,13 @@ ${cleanBody}`;
69876
70988
  const emittedAfterFinalizationTimeout = completionDiagnostic?.emittedAfterFinalizationTimeout === true;
69877
70989
  const weakEvidenceAtEntry = isWeakCompletionEvidence(args.metadataEvent);
69878
70990
  const weakCompleted = outcome === "completed" && weakEvidenceAtEntry && !emittedAfterFinalizationTimeout;
69879
- if (outcome === "completed" && emittedAfterFinalizationTimeout && weakEvidenceAtEntry) {
70991
+ if (emittedAfterFinalizationTimeout && weakEvidenceAtEntry) {
69880
70992
  args.metadataEvent.reviewRecommended = true;
69881
70993
  args.metadataEvent.completionDiagnostic = {
69882
70994
  ...completionDiagnostic || {},
69883
70995
  timedOutWithoutFinalAssistant: true
69884
70996
  };
69885
- LOG2.info("MeshQueue", `Completion for session ${sessionId} exhausted the finalization wait with no confirmed final assistant \u2014 flipping terminal (never wedge) but flagged reviewRecommended`);
70997
+ LOG2.info("MeshQueue", `Completion for session ${sessionId} exhausted the finalization wait with no confirmed final assistant \u2014 recording FORCED TERMINATION (outcome=${outcome}; terminal, never wedge) flagged reviewRecommended; NOT a completion`);
69886
70998
  }
69887
70999
  let reducerAllowsFlip = true;
69888
71000
  if (eventTaskId && !weakCompleted) {
@@ -70006,6 +71118,7 @@ ${cleanBody}`;
70006
71118
  return task ? { id: task.id, taskMode: task.taskMode } : null;
70007
71119
  }
70008
71120
  let completedTaskForLedger = null;
71121
+ let forcedTimeoutNoResponse = false;
70009
71122
  let directDispatchTaskIdForLedger;
70010
71123
  let worktreeHasQueuedTask = false;
70011
71124
  if (args.event === "agent:generating_completed") {
@@ -70015,7 +71128,8 @@ ${cleanBody}`;
70015
71128
  if (sessionId) {
70016
71129
  directDispatchTaskIdForLedger = readNonEmptyString(args.metadataEvent.taskId) || resolveActiveDirectDispatchTaskId(args.meshId, sessionId);
70017
71130
  const isFalseIdle = isFalseIdleCompletion(args.metadataEvent);
70018
- completedTaskForLedger = markSessionTerminal(sessionId, "completed", eventTimestamp, { tentativeIfDirect: isFalseIdle });
71131
+ forcedTimeoutNoResponse = isWeakCompletionEvidence(args.metadataEvent) && (args.metadataEvent.completionDiagnostic && typeof args.metadataEvent.completionDiagnostic === "object" && args.metadataEvent.completionDiagnostic.emittedAfterFinalizationTimeout === true) === true;
71132
+ completedTaskForLedger = markSessionTerminal(sessionId, forcedTimeoutNoResponse ? "failed" : "completed", eventTimestamp, { tentativeIfDirect: isFalseIdle });
70019
71133
  if (nodeId && providerType) {
70020
71134
  if (!isFalseIdle) {
70021
71135
  sweepExpiredRemoteIdleSessions();
@@ -70038,7 +71152,7 @@ ${cleanBody}`;
70038
71152
  }
70039
71153
  }
70040
71154
  const completedTaskId = completedTaskForLedger?.id;
70041
- if (completedTaskId && hasPendingDependents(args.meshId, completedTaskId)) {
71155
+ if (completedTaskId && !forcedTimeoutNoResponse && hasPendingDependents(args.meshId, completedTaskId)) {
70042
71156
  setImmediate(() => {
70043
71157
  triggerMeshQueue(components, args.meshId).catch((e) => {
70044
71158
  LOG2.warn("MeshQueue", `Dependent wake after task ${completedTaskId} failed: ${e?.message || e}`);
@@ -70264,7 +71378,7 @@ ${cleanBody}`;
70264
71378
  });
70265
71379
  });
70266
71380
  }
70267
- const ledgerKind = EVENT_TO_LEDGER_KIND[args.event];
71381
+ const ledgerKind = forcedTimeoutNoResponse ? "task_failed" : EVENT_TO_LEDGER_KIND[args.event];
70268
71382
  if (ledgerKind) {
70269
71383
  try {
70270
71384
  const ledgerNodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId) || void 0;
@@ -72466,6 +73580,20 @@ ${cleanBody}`;
72466
73580
  }
72467
73581
  return newest;
72468
73582
  }
73583
+ function escapeTailFingerprint(messages) {
73584
+ let fp = "";
73585
+ for (const msg of messages) {
73586
+ if (!msg) continue;
73587
+ const ts2 = readChatMessageTimestampMs(msg) ?? 0;
73588
+ let len = -1;
73589
+ try {
73590
+ len = JSON.stringify(msg.content)?.length ?? -1;
73591
+ } catch {
73592
+ }
73593
+ fp += `${msg.role}:${ts2}:${len};`;
73594
+ }
73595
+ return fp;
73596
+ }
72469
73597
  async function reconcileUnterminatedDirectDispatches(components, mesh, selfIds, localDaemonId) {
72470
73598
  const dispatches = getActiveDirectDispatches(mesh.id);
72471
73599
  rehydrateAckedHoldsForMesh(mesh.id);
@@ -72476,6 +73604,9 @@ ${cleanBody}`;
72476
73604
  for (const key2 of heldKeys) {
72477
73605
  if (!activeTaskKeys.has(key2)) deleteHoldState(key2, mesh.id);
72478
73606
  }
73607
+ for (const key2 of [...nonIdleEscapeTracks.keys()]) {
73608
+ if (key2.startsWith(`${mesh.id}::`) && !activeTaskKeys.has(key2)) nonIdleEscapeTracks.delete(key2);
73609
+ }
72479
73610
  if (dispatches.length === 0) return;
72480
73611
  const dispatchMeshCommand = components.dispatchMeshCommand;
72481
73612
  const nodeById = new Map(mesh.nodes.map((n) => [n.id, n]));
@@ -72540,23 +73671,43 @@ ${cleanBody}`;
72540
73671
  consecutiveReadFailures: 0,
72541
73672
  ...priorHoldState?.transcriptIdleSinceMs !== void 0 ? { transcriptIdleSinceMs: priorHoldState.transcriptIdleSinceMs } : {}
72542
73673
  });
72543
- let nonIdleEscapeSinceAckMs = null;
72544
73674
  const nowMs = Date.now();
72545
73675
  if (readChatPayloadStatus(payload) !== "idle") {
72546
73676
  if (isAcked && readChatPayloadStatus(payload) === "generating") {
72547
- const escapeAckedAtMs = Date.parse(readNonEmptyString(dispatch.updatedAt));
72548
- const escapeSinceAckMs = Number.isFinite(escapeAckedAtMs) ? nowMs - escapeAckedAtMs : Number.POSITIVE_INFINITY;
72549
- if (escapeSinceAckMs >= resolveAckedDeathDeadlineMs()) {
72550
- nonIdleEscapeSinceAckMs = escapeSinceAckMs;
73677
+ const escapeMessages = Array.isArray(payload.messages) ? payload.messages : [];
73678
+ const fingerprint = escapeTailFingerprint(escapeMessages);
73679
+ const prior = nonIdleEscapeTracks.get(synthKey);
73680
+ if (!prior || prior.tailFingerprint !== fingerprint) {
73681
+ nonIdleEscapeTracks.set(synthKey, { anchorMs: nowMs, tailFingerprint: fingerprint, candidateRecorded: false });
73682
+ if (prior) {
73683
+ LOG2.info("MeshReconcile", `Non-idle escape re-armed: task ${taskId} on node ${nodeId} (mesh ${mesh.id}) reads 'generating' and its transcript tail moved \u2014 worker is alive mid-turn; the escape deadline restarts from now`);
73684
+ }
73685
+ } else {
73686
+ const staticMs = nowMs - prior.anchorMs;
73687
+ if (staticMs >= resolveAckedDeathDeadlineMs() && !prior.candidateRecorded) {
73688
+ prior.candidateRecorded = true;
73689
+ const candidateEvidence = extractFinalAssistantSummaryEvidence(escapeMessages);
73690
+ LOG2.warn("MeshReconcile", `Non-idle escape WEAK CANDIDATE (no completion): task ${taskId} on node ${nodeId} (mesh ${mesh.id}) has read 'generating' with a static transcript tail for ${Math.round(staticMs / 1e3)}s (deadline ${Math.round(resolveAckedDeathDeadlineMs() / 1e3)}s)${candidateEvidence.finalSummary ? " and a final-looking assistant bubble" : ""} \u2014 recorded as a weak candidate only; NOT completed (a timeout is never completion evidence); the hold/reclaim nets own the terminal`);
73691
+ traceMeshEventDrop("non_idle_escape_weak_candidate_held", {
73692
+ taskId,
73693
+ sessionId,
73694
+ nodeId,
73695
+ meshId: mesh.id,
73696
+ event: "agent:generating_completed"
73697
+ }, `staticTailMs=${staticMs} finalAssistant=${candidateEvidence.finalSummary ? "present" : "absent"} transcriptAt=${candidateEvidence.transcriptMessageAt ?? "n/a"}`);
73698
+ }
72551
73699
  }
72552
73700
  }
72553
- if (nonIdleEscapeSinceAckMs === null) {
72554
- setHoldState(synthKey, mesh.id, { liveConfirmedSinceAck: true, consecutiveReadFailures: 0 });
72555
- continue;
72556
- }
73701
+ setHoldState(synthKey, mesh.id, { liveConfirmedSinceAck: true, consecutiveReadFailures: 0 });
73702
+ continue;
72557
73703
  }
72558
73704
  const messages = Array.isArray(payload.messages) ? payload.messages : [];
72559
- const evidence = extractFinalAssistantSummaryEvidence(messages);
73705
+ const dispatchedAtMs = Date.parse(readNonEmptyString(dispatch.dispatchedAt));
73706
+ const evidence = extractFinalAssistantSummaryEvidence(
73707
+ messages,
73708
+ void 0,
73709
+ Number.isFinite(dispatchedAtMs) ? { turnStartedAtMs: dispatchedAtMs } : void 0
73710
+ );
72560
73711
  if (hasTrailingToolActivityAfterFinalAssistant(messages)) {
72561
73712
  setHoldState(synthKey, mesh.id, { liveConfirmedSinceAck: true, consecutiveReadFailures: 0 });
72562
73713
  LOG2.info("MeshReconcile", `Mid-turn causal admission: task ${taskId} on node ${nodeId} (mesh ${mesh.id}) \u2014 the latest final-looking assistant bubble is followed by trailing tool/terminal activity (interim narration; the turn is still executing); holding the transcript synth`);
@@ -72588,7 +73739,7 @@ ${cleanBody}`;
72588
73739
  const deathDeadlineMs = resolveAckedDeathDeadlineMs();
72589
73740
  const holdState = getHoldState(synthKey, mesh.id);
72590
73741
  let fastTrackReady = false;
72591
- if (nonIdleEscapeSinceAckMs === null && evidence.finalSummary) {
73742
+ if (evidence.finalSummary) {
72592
73743
  const idleSinceMs = holdState?.transcriptIdleSinceMs ?? nowMs;
72593
73744
  if (holdState && holdState.transcriptIdleSinceMs === void 0) {
72594
73745
  setHoldState(synthKey, mesh.id, { ...holdState, transcriptIdleSinceMs: idleSinceMs });
@@ -72609,9 +73760,7 @@ ${cleanBody}`;
72609
73760
  }
72610
73761
  if (!fastTrackReady) {
72611
73762
  backstopKind = "ackedHoldDeathDeadlineFired";
72612
- if (nonIdleEscapeSinceAckMs === null) {
72613
- LOG2.warn("MeshReconcile", `Acked-hold death deadline reached: task ${taskId} on node ${nodeId} (mesh ${mesh.id}) still idle ${Math.round(sinceAckMs / 1e3)}s after the ack (deadline ${Math.round(deathDeadlineMs / 1e3)}s) \u2014 synthesizing the missing completion as a notification-loss net (a real emit, if it ever lands, no-ops idempotently).`);
72614
- }
73763
+ LOG2.warn("MeshReconcile", `Acked-hold death deadline reached: task ${taskId} on node ${nodeId} (mesh ${mesh.id}) still idle ${Math.round(sinceAckMs / 1e3)}s after the ack (deadline ${Math.round(deathDeadlineMs / 1e3)}s) \u2014 synthesizing the missing completion as a notification-loss net (a real emit, if it ever lands, no-ops idempotently).`);
72615
73764
  }
72616
73765
  }
72617
73766
  if (realTerminalEmitPendingForTask(mesh.id, taskId)) {
@@ -72620,21 +73769,8 @@ ${cleanBody}`;
72620
73769
  continue;
72621
73770
  }
72622
73771
  if (!evidence.finalSummary) continue;
72623
- const dispatchedAtMs = Date.parse(readNonEmptyString(dispatch.dispatchedAt));
72624
73772
  const transcriptAtMs = Date.parse(evidence.transcriptMessageAt ?? "");
72625
- if (nonIdleEscapeSinceAckMs !== null) {
72626
- if (!Number.isFinite(dispatchedAtMs) || !Number.isFinite(transcriptAtMs) || transcriptAtMs < dispatchedAtMs) {
72627
- LOG2.info("MeshReconcile", `Non-idle-escape stale-summary guard: refusing transcript synth for task ${taskId} on node ${nodeId} (mesh ${mesh.id}) \u2014 final assistant message (${evidence.transcriptMessageAt ?? "unparseable"}) is not provably at/after this task's dispatch (${dispatch.dispatchedAt})`);
72628
- traceMeshEventDrop("reconcile_non_idle_escape_stale_summary", {
72629
- taskId,
72630
- sessionId,
72631
- nodeId,
72632
- meshId: mesh.id,
72633
- event: "agent:generating_completed"
72634
- }, `transcriptAt=${evidence.transcriptMessageAt} dispatchedAt=${dispatch.dispatchedAt}`);
72635
- continue;
72636
- }
72637
- } else if (Number.isFinite(dispatchedAtMs) && Number.isFinite(transcriptAtMs) && transcriptAtMs < dispatchedAtMs) {
73773
+ if (Number.isFinite(dispatchedAtMs) && Number.isFinite(transcriptAtMs) && transcriptAtMs < dispatchedAtMs) {
72638
73774
  LOG2.info("MeshReconcile", `Stale-summary guard: skipping transcript reconcile for task ${taskId} on node ${nodeId} (mesh ${mesh.id}) \u2014 final assistant message (${evidence.transcriptMessageAt}) predates this task's dispatch (${dispatch.dispatchedAt}); it is a prior task's summary`);
72639
73775
  traceMeshEventDrop("reconcile_stale_summary_before_dispatch", {
72640
73776
  taskId,
@@ -72645,15 +73781,12 @@ ${cleanBody}`;
72645
73781
  }, `transcriptAt=${evidence.transcriptMessageAt} < dispatchedAt=${dispatch.dispatchedAt}`);
72646
73782
  continue;
72647
73783
  }
72648
- const reprobeStatus = nonIdleEscapeSinceAckMs !== null ? null : await reprobeWorkerStatus(components, { isLocalNode, nodeDaemonId, readArgs });
73784
+ const reprobeStatus = await reprobeWorkerStatus(components, { isLocalNode, nodeDaemonId, readArgs });
72649
73785
  if (reprobeStatus && reprobeStatus !== "idle") {
72650
73786
  deleteHoldState(synthKey, mesh.id);
72651
73787
  LOG2.info("MeshReconcile", `Live re-probe defer: task ${taskId} on node ${nodeId} (mesh ${mesh.id}) read '${reprobeStatus}' at synth-commit time \u2014 worker resumed generating; deferring synth to a later tick`);
72652
73788
  continue;
72653
73789
  }
72654
- if (nonIdleEscapeSinceAckMs !== null) {
72655
- LOG2.warn("MeshReconcile", `Acked-hold death deadline NON-IDLE escape: task ${taskId} on node ${nodeId} (mesh ${mesh.id}) still reads 'generating' ${Math.round(nonIdleEscapeSinceAckMs / 1e3)}s after the ack with a causally-proven final assistant (transcriptAt=${evidence.transcriptMessageAt ?? "n/a"}) \u2014 the floor-class PTY wedge rescue net; synthesizing the missing completion (a real emit, if it ever lands, no-ops idempotently).`);
72656
- }
72657
73790
  const providerSessionId = readNonEmptyString(payload.providerSessionId);
72658
73791
  const workerSession = components.instanceManager.getInstance(sessionId);
72659
73792
  const workerCoordinatorDaemonId = readNonEmptyString(
@@ -72814,8 +73947,12 @@ ${cleanBody}`;
72814
73947
  if (!payload) return declined("chat_tail_unreadable", "worker transcript read returned no payload (offline/unreachable?)");
72815
73948
  const payloadStatus = readChatPayloadProviderObservedStatus(payload);
72816
73949
  const messages = Array.isArray(payload.messages) ? payload.messages : [];
72817
- const evidence = extractFinalAssistantSummaryEvidence(messages);
72818
73950
  const dispatchedAtMs = Date.parse(readNonEmptyString(row.dispatchTimestamp));
73951
+ const evidence = extractFinalAssistantSummaryEvidence(
73952
+ messages,
73953
+ void 0,
73954
+ Number.isFinite(dispatchedAtMs) ? { turnStartedAtMs: dispatchedAtMs } : void 0
73955
+ );
72819
73956
  const transcriptAtMs = Date.parse(evidence.transcriptMessageAt ?? "");
72820
73957
  if (Number.isFinite(dispatchedAtMs) && Number.isFinite(transcriptAtMs) && transcriptAtMs < dispatchedAtMs) {
72821
73958
  return declined(
@@ -72861,7 +73998,10 @@ ${cleanBody}`;
72861
73998
  `dispatchTimestamp=${row.dispatchTimestamp ?? "none"} transcriptMessageAt=${evidence.transcriptMessageAt ?? "none"} \u2014 shape-only evidence (${verdict.reason}) cannot complete an undated tail; reclaim owns it`
72862
73999
  );
72863
74000
  }
72864
- const selectedFinalAssistant = finalAssistantPresent ? selectFinalAssistantTurnEndMessage(messages) : null;
74001
+ const selectedFinalAssistant = finalAssistantPresent ? selectFinalAssistantTurnEndMessage(
74002
+ messages,
74003
+ Number.isFinite(dispatchedAtMs) ? { turnStartedAtMs: dispatchedAtMs } : void 0
74004
+ ) : null;
72865
74005
  const selectedFinalAssistantIndex = selectedFinalAssistant ? messages.lastIndexOf(selectedFinalAssistant) : -1;
72866
74006
  const admissionSnapshot = {
72867
74007
  producer,
@@ -72897,6 +74037,7 @@ ${cleanBody}`;
72897
74037
  admissionSnapshot
72898
74038
  };
72899
74039
  }
74040
+ var nonIdleEscapeTracks;
72900
74041
  var init_mesh_completion_synthesis = __esm2({
72901
74042
  "src/mesh/mesh-completion-synthesis.ts"() {
72902
74043
  "use strict";
@@ -72917,6 +74058,7 @@ ${cleanBody}`;
72917
74058
  init_mesh_reconcile_v2_backstop();
72918
74059
  init_mesh_reconcile_acked_hold();
72919
74060
  init_mesh_remote_event_pull();
74061
+ nonIdleEscapeTracks = /* @__PURE__ */ new Map();
72920
74062
  }
72921
74063
  });
72922
74064
  function findLiveCoordinators(components) {
@@ -73527,6 +74669,53 @@ ${cleanBody}`;
73527
74669
  producer: "early_idle_transcript_evidence"
73528
74670
  });
73529
74671
  if (terminalEvidence) {
74672
+ const weakCandidateKey = `${meshId}::${row.id}`;
74673
+ if (terminalEvidence.evidenceLevel === "weak") {
74674
+ const candidate = weakCompletionCandidateStreak.get(weakCandidateKey) ?? { count: 0 };
74675
+ if (candidate.finalAssistantAt !== void 0 && candidate.finalAssistantAt !== terminalEvidence.transcriptMessageAt) {
74676
+ candidate.count = 0;
74677
+ }
74678
+ candidate.finalAssistantAt = terminalEvidence.transcriptMessageAt;
74679
+ candidate.count += 1;
74680
+ weakCompletionCandidateStreak.set(weakCandidateKey, candidate);
74681
+ if (candidate.count === 1) {
74682
+ const nodeLabel = row.assignedNodeId ? `Node '${row.assignedNodeId}'` : "Remote agent";
74683
+ const metadataEvent = {
74684
+ evidenceLevel: "weak",
74685
+ finalSummary: terminalEvidence.finalSummary,
74686
+ taskId: row.id,
74687
+ providerType: readNonEmptyString(row.assignedProviderType) || terminalEvidence.providerType,
74688
+ providerSessionId: terminalEvidence.providerSessionId,
74689
+ source: "early_idle_transcript_evidence",
74690
+ targetSessionId: terminalEvidence.sessionId
74691
+ };
74692
+ try {
74693
+ queuePendingMeshCoordinatorEvent({
74694
+ event: "agent:generating_completed",
74695
+ meshId,
74696
+ nodeLabel,
74697
+ nodeId: row.assignedNodeId,
74698
+ metadataEvent,
74699
+ coordinatorMessage: buildMeshSystemMessage({ event: "agent:generating_completed", nodeLabel, metadataEvent }),
74700
+ queuedAt: nowMs
74701
+ });
74702
+ } catch {
74703
+ }
74704
+ }
74705
+ if (candidate.count < WEAK_COMPLETION_CANDIDATE_CONFIRM_TICKS) {
74706
+ traceMeshEventDrop("weak_completion_candidate_held", {
74707
+ taskId: row.id,
74708
+ sessionId: row.assignedSessionId,
74709
+ nodeId: row.assignedNodeId,
74710
+ meshId,
74711
+ event: "agent:generating_completed"
74712
+ }, `weak message-shape completion candidate ${candidate.count}/${WEAK_COMPLETION_CANDIDATE_CONFIRM_TICKS} (early-idle) \u2014 awaiting re-confirmation`);
74713
+ continue;
74714
+ }
74715
+ weakCompletionCandidateStreak.delete(weakCandidateKey);
74716
+ } else {
74717
+ weakCompletionCandidateStreak.delete(weakCandidateKey);
74718
+ }
73530
74719
  const propagation = propagateWatchdogTranscriptCompletion(
73531
74720
  components,
73532
74721
  meshId,
@@ -74466,6 +75655,30 @@ ${cleanBody}`;
74466
75655
  LOG2.warn("MeshReconcile", `Completion reconcile failed for mesh ${mesh.id}: ${e?.message || e}`);
74467
75656
  }
74468
75657
  }
75658
+ if (store) {
75659
+ for (const mesh of listMeshes()) {
75660
+ const selfIds = resolveCoordinatorSelfIds(mesh, drainDaemonIds);
75661
+ if (!daemonHostsMesh(mesh, selfIds)) continue;
75662
+ try {
75663
+ const gateStore = store.graphStore();
75664
+ const preSweep = new Map(
75665
+ gateStore.listGatesByMesh(mesh.id, ["awaiting_coordinator", "claimed"]).map((g) => [g.gateId, { graphId: g.graphId, onTimeout: g.onTimeout, deadlineAt: g.deadlineAt }])
75666
+ );
75667
+ const swept = sweepMeshGraphGateTimeouts(mesh.id);
75668
+ for (const gateId of swept.expiredGateIds) {
75669
+ const meta3 = preSweep.get(gateId);
75670
+ recordGraphGateExpired(mesh.id, {
75671
+ gateId,
75672
+ graphId: meta3?.graphId,
75673
+ policy: meta3?.onTimeout ?? "hold",
75674
+ deadlineAt: meta3?.deadlineAt
75675
+ });
75676
+ }
75677
+ } catch (e) {
75678
+ LOG2.warn("MeshReconcile", `Graph gate sweep failed for mesh ${mesh.id}: ${e?.message || e}`);
75679
+ }
75680
+ }
75681
+ }
74469
75682
  if (store) {
74470
75683
  for (const mesh of listMeshes()) {
74471
75684
  const selfIds = resolveCoordinatorSelfIds(mesh, drainDaemonIds);
@@ -74768,6 +75981,8 @@ ${cleanBody}`;
74768
75981
  init_mesh_reconcile_stranded_dispatch();
74769
75982
  init_mesh_reconcile_unresolved_forward();
74770
75983
  init_mesh_graph_workspace_saga();
75984
+ init_mesh_graph_gates();
75985
+ init_mesh_graph_provenance();
74771
75986
  init_mesh_reconcile_v2_backstop();
74772
75987
  init_mesh_reconcile_acked_hold();
74773
75988
  init_mesh_reconcile_coordinator_drain();
@@ -77195,6 +78410,29 @@ ${cleanBody}`;
77195
78410
  "use strict";
77196
78411
  }
77197
78412
  });
78413
+ function resolveRefineVitestMaxWorkers(env2 = process.env) {
78414
+ const raw = env2[REFINE_VITEST_MAX_WORKERS_ENV];
78415
+ if (raw === void 0 || raw.trim() === "") return DEFAULT_REFINE_VITEST_MAX_WORKERS;
78416
+ const parsed = Number.parseInt(raw, 10);
78417
+ if (!Number.isFinite(parsed)) return DEFAULT_REFINE_VITEST_MAX_WORKERS;
78418
+ if (parsed === 0) return null;
78419
+ return Math.max(1, parsed);
78420
+ }
78421
+ function refineGateChildEnv(env2 = process.env) {
78422
+ if (env2.VITEST_MAX_WORKERS) return {};
78423
+ const cap = resolveRefineVitestMaxWorkers(env2);
78424
+ if (cap === null) return {};
78425
+ return { VITEST_MAX_WORKERS: String(cap) };
78426
+ }
78427
+ var REFINE_VITEST_MAX_WORKERS_ENV;
78428
+ var DEFAULT_REFINE_VITEST_MAX_WORKERS;
78429
+ var init_mesh_refine_worker_cap = __esm2({
78430
+ "src/mesh/mesh-refine-worker-cap.ts"() {
78431
+ "use strict";
78432
+ REFINE_VITEST_MAX_WORKERS_ENV = "ADHDEV_REFINE_VITEST_MAX_WORKERS";
78433
+ DEFAULT_REFINE_VITEST_MAX_WORKERS = 2;
78434
+ }
78435
+ });
77198
78436
  function truncateValidationOutput(value) {
77199
78437
  const text = typeof value === "string" ? value : value == null ? "" : String(value);
77200
78438
  if (text.length <= REFINE_VALIDATION_SUMMARY_CHARS) return text;
@@ -78673,7 +79911,7 @@ ${mergeTreeErr?.stderr || ""}`;
78673
79911
  encoding: "utf8",
78674
79912
  timeout,
78675
79913
  maxBuffer: candidate.outputLimitBytes || REFINE_VALIDATION_OUTPUT_LIMIT_BYTES,
78676
- env: { ...process.env, CI: process.env.CI || "1", ...candidate.env || {} },
79914
+ env: { ...process.env, CI: process.env.CI || "1", ...refineGateChildEnv(), ...candidate.env || {} },
78677
79915
  ...spawn7.windowsVerbatimArguments ? { windowsVerbatimArguments: true } : {}
78678
79916
  });
78679
79917
  summary.bootstrapCommandsRun.push(commandRecord(candidate, cwd, startedAt, result, true, { exitCode: 0 }));
@@ -78718,7 +79956,7 @@ ${mergeTreeErr?.stderr || ""}`;
78718
79956
  encoding: "utf8",
78719
79957
  timeout,
78720
79958
  maxBuffer: candidate.outputLimitBytes || REFINE_VALIDATION_OUTPUT_LIMIT_BYTES,
78721
- env: { ...process.env, CI: process.env.CI || "1", ...candidate.env || {} },
79959
+ env: { ...process.env, CI: process.env.CI || "1", ...refineGateChildEnv(), ...candidate.env || {} },
78722
79960
  ...spawn7.windowsVerbatimArguments ? { windowsVerbatimArguments: true } : {}
78723
79961
  });
78724
79962
  summary.commandsRun.push(commandRecord(candidate, cwd, startedAt, result, true, { exitCode: 0 }));
@@ -78784,6 +80022,7 @@ ${mergeTreeErr?.stderr || ""}`;
78784
80022
  fs48 = __toESM2(require("fs"));
78785
80023
  import_node_child_process11 = require("child_process");
78786
80024
  init_resolve_executable();
80025
+ init_mesh_refine_worker_cap();
78787
80026
  GIT4 = process.platform === "win32" ? resolveWin32Executable("git") : "git";
78788
80027
  REFINE_VALIDATION_TIMEOUT_MS = 12e4;
78789
80028
  REFINE_VALIDATION_OUTPUT_LIMIT_BYTES = 128 * 1024;
@@ -78869,6 +80108,45 @@ ${mergeTreeErr?.stderr || ""}`;
78869
80108
  REFINE_INFLIGHT_FRESHNESS_MS = 30 * 6e4;
78870
80109
  }
78871
80110
  });
80111
+ function resolveRefineMaxConcurrentJobs(env2 = process.env) {
80112
+ const raw = env2[REFINE_MAX_CONCURRENT_JOBS_ENV];
80113
+ if (raw === void 0 || raw.trim() === "") return DEFAULT_REFINE_MAX_CONCURRENT_JOBS;
80114
+ const parsed = Number.parseInt(raw, 10);
80115
+ if (!Number.isFinite(parsed) || parsed < 1) return DEFAULT_REFINE_MAX_CONCURRENT_JOBS;
80116
+ return parsed;
80117
+ }
80118
+ async function runWithRefineExecutionSlot(label, task) {
80119
+ const limit = resolveRefineMaxConcurrentJobs();
80120
+ if (activeExecutions >= limit) {
80121
+ LOG2.info("Mesh", `[Refinery] ${label} QUEUED \u2014 ${activeExecutions} refine job(s) already executing (limit ${limit}), ${waitQueue.length + 1} waiting. It starts automatically; do not re-invoke.`);
80122
+ await new Promise((resolve30) => {
80123
+ waitQueue.push(resolve30);
80124
+ });
80125
+ LOG2.info("Mesh", `[Refinery] ${label} dequeued \u2014 starting now (${activeExecutions} other job(s) still executing).`);
80126
+ }
80127
+ activeExecutions += 1;
80128
+ try {
80129
+ return await task();
80130
+ } finally {
80131
+ activeExecutions -= 1;
80132
+ const next = waitQueue.shift();
80133
+ if (next) next();
80134
+ }
80135
+ }
80136
+ var REFINE_MAX_CONCURRENT_JOBS_ENV;
80137
+ var DEFAULT_REFINE_MAX_CONCURRENT_JOBS;
80138
+ var activeExecutions;
80139
+ var waitQueue;
80140
+ var init_mesh_refine_concurrency = __esm2({
80141
+ "src/mesh/mesh-refine-concurrency.ts"() {
80142
+ "use strict";
80143
+ init_logger();
80144
+ REFINE_MAX_CONCURRENT_JOBS_ENV = "ADHDEV_REFINE_MAX_CONCURRENT_JOBS";
80145
+ DEFAULT_REFINE_MAX_CONCURRENT_JOBS = 1;
80146
+ activeExecutions = 0;
80147
+ waitQueue = [];
80148
+ }
80149
+ });
78872
80150
  function resolveRefineResumeDispatchGraceMs() {
78873
80151
  return resolveTunedReconcileMs("MESH_REFINE_RESUME_DISPATCH_GRACE_MS", 6e4, 0, 10 * 6e4);
78874
80152
  }
@@ -80807,7 +82085,10 @@ ${e?.stderr || ""}`;
80807
82085
  await appendRefineBatchJobLedger(self, "task_dispatched", handle);
80808
82086
  queueRefineBatchJobEvent(self, "refine:accepted", handle);
80809
82087
  setImmediate(() => {
80810
- void finishMeshRefineBatchJob(self, handle, orderedNodes, ordering, args);
82088
+ void runWithRefineExecutionSlot(
82089
+ `batch ${handle.jobId} (mesh ${meshId})`,
82090
+ () => finishMeshRefineBatchJob(self, handle, orderedNodes, ordering, args)
82091
+ );
80811
82092
  });
80812
82093
  return {
80813
82094
  ...handle,
@@ -81006,7 +82287,10 @@ ${e?.stderr || ""}`;
81006
82287
  queueRefineJobEvent(self, "refine:accepted", handle);
81007
82288
  setImmediate(() => {
81008
82289
  void recordRefineAcceptBaseDivergence(self, handle, node);
81009
- void finishMeshRefineJob(self, handle, args);
82290
+ void runWithRefineExecutionSlot(
82291
+ `job ${handle.jobId} (node ${handle.targetNodeId})`,
82292
+ () => finishMeshRefineJob(self, handle, args)
82293
+ );
81010
82294
  });
81011
82295
  return handle;
81012
82296
  }
@@ -81035,6 +82319,7 @@ ${e?.stderr || ""}`;
81035
82319
  init_git_locale();
81036
82320
  init_mesh_node_identity();
81037
82321
  init_mesh_refine_gates();
82322
+ init_mesh_refine_concurrency();
81038
82323
  init_router_refine_resume();
81039
82324
  RETRYABLE_BASE_MOVEMENT_CODES = /* @__PURE__ */ new Set(["base_moved", "base_locked"]);
81040
82325
  }
@@ -81110,6 +82395,9 @@ ${e?.stderr || ""}`;
81110
82395
  MAX_SIZE_ROTATION_GENERATIONS: () => MAX_SIZE_ROTATION_GENERATIONS,
81111
82396
  MESH_CONVERGE_FAST_FORWARD_TAG: () => MESH_CONVERGE_FAST_FORWARD_TAG,
81112
82397
  MESH_CONVERGE_REFINE_TAG: () => MESH_CONVERGE_REFINE_TAG,
82398
+ MESH_GATE_DEFAULT_LEASE_SECONDS: () => MESH_GATE_DEFAULT_LEASE_SECONDS,
82399
+ MESH_GATE_NAMED_OUTCOMES: () => MESH_GATE_NAMED_OUTCOMES,
82400
+ MESH_GATE_RELEASE_PATCH_KEYS: () => MESH_GATE_RELEASE_PATCH_KEYS,
81113
82401
  MESH_JSON_CONFIG_LOCATIONS: () => MESH_JSON_CONFIG_LOCATIONS,
81114
82402
  MESH_JSON_CONFIG_SCHEMA: () => MESH_JSON_CONFIG_SCHEMA,
81115
82403
  MESH_JSON_PROVIDER_DEFAULTS_EXAMPLE: () => MESH_JSON_PROVIDER_DEFAULTS_EXAMPLE,
@@ -81119,16 +82407,21 @@ ${e?.stderr || ""}`;
81119
82407
  MESH_MISSION_LIST_STATUS_LIMIT: () => MESH_MISSION_LIST_STATUS_LIMIT,
81120
82408
  MESH_MISSION_STATUSES: () => MESH_MISSION_STATUSES,
81121
82409
  MESH_NODE_LIVE_TRUTH_MARKER: () => MESH_NODE_LIVE_TRUTH_MARKER,
82410
+ MESH_ON_DEPENDENCY_FAILURE_PUBLIC_TEXT: () => MESH_ON_DEPENDENCY_FAILURE_PUBLIC_TEXT,
81122
82411
  MESH_REFINE_CONFIG_LOCATIONS: () => MESH_REFINE_CONFIG_LOCATIONS,
81123
82412
  MESH_REFINE_CONFIG_SCHEMA: () => MESH_REFINE_CONFIG_SCHEMA,
81124
82413
  MESH_SCHEDULING_STRATEGIES: () => MESH_SCHEDULING_STRATEGIES,
82414
+ MESH_SUPERSEDED_SINGLE_REASONS: () => MESH_SUPERSEDED_SINGLE_REASONS,
81125
82415
  MESH_TASK_GRAPH_MAX_TASKS: () => MESH_TASK_GRAPH_MAX_TASKS,
81126
82416
  MESH_TASK_PRIORITIES: () => MESH_TASK_PRIORITIES,
82417
+ MESH_VALID_SINGLE_REASONS: () => MESH_VALID_SINGLE_REASONS,
81127
82418
  MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS: () => MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS,
81128
82419
  MESH_WORKTREE_BOOTSTRAP_CONFIG_SCHEMA: () => MESH_WORKTREE_BOOTSTRAP_CONFIG_SCHEMA,
81129
82420
  MIN_GIT_WORKSPACE_POLL_INTERVAL_MS: () => MIN_GIT_WORKSPACE_POLL_INTERVAL_MS,
81130
82421
  MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS: () => MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS2,
81131
82422
  MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS: () => MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS2,
82423
+ MeshGraphPlanError: () => MeshGraphPlanError,
82424
+ MeshGraphPolicyError: () => MeshGraphPolicyError,
81132
82425
  NOT_BEFORE_RELATIVE_THRESHOLD_MS: () => NOT_BEFORE_RELATIVE_THRESHOLD_MS,
81133
82426
  NodePtyTransportFactory: () => NodePtyTransportFactory,
81134
82427
  OPERATING_NOTE_DEDUPE_WINDOW: () => OPERATING_NOTE_DEDUPE_WINDOW,
@@ -81185,6 +82478,7 @@ ${e?.stderr || ""}`;
81185
82478
  buildMeshActiveWork: () => buildMeshActiveWork,
81186
82479
  buildMeshActiveWorkSummary: () => buildMeshActiveWorkSummary,
81187
82480
  buildMeshAsyncRefineJobs: () => buildMeshAsyncRefineJobs,
82481
+ buildMeshGraphViews: () => buildMeshGraphViews,
81188
82482
  buildMeshHostRequiredFailure: () => buildMeshHostRequiredFailure,
81189
82483
  buildMeshJsonConfigScaffold: () => buildMeshJsonConfigScaffold,
81190
82484
  buildMeshLedgerReconciliationEvidence: () => buildMeshLedgerReconciliationEvidence,
@@ -81211,6 +82505,7 @@ ${e?.stderr || ""}`;
81211
82505
  buildUserChatMessage: () => buildUserChatMessage,
81212
82506
  cancelTask: () => cancelTask,
81213
82507
  canonicalDaemonId: () => canonicalDaemonId,
82508
+ claimMeshGraphGate: () => claimMeshGraphGate,
81214
82509
  claimNextTask: () => claimNextTask,
81215
82510
  classifyChatMessageVisibility: () => classifyChatMessageVisibility,
81216
82511
  classifyDuplicateMeshDispatch: () => classifyDuplicateMeshDispatch,
@@ -81225,14 +82520,17 @@ ${e?.stderr || ""}`;
81225
82520
  clearPendingMeshCoordinatorEvents: () => clearPendingMeshCoordinatorEvents,
81226
82521
  collectPendingApprovals: () => collectPendingApprovals,
81227
82522
  collectSyncTargetTypes: () => collectSyncTargetTypes,
82523
+ commitMeshGraphPlan: () => commitMeshGraphPlan,
81228
82524
  compareGitSnapshots: () => compareGitSnapshots,
81229
82525
  compensateWorkspaceIntent: () => compensateWorkspaceIntent,
82526
+ computeMeshGraphPlanDigest: () => computeMeshGraphPlanDigest,
81230
82527
  computeMeshMissionStats: () => computeMeshMissionStats,
81231
82528
  computeMeshTaskStats: () => computeMeshTaskStats,
81232
82529
  computeProviderTreeDigest: () => computeProviderTreeDigest,
81233
82530
  configureDebugTraceStore: () => configureDebugTraceStore,
81234
82531
  connectCdpManager: () => connectCdpManager,
81235
82532
  consoleSymbols: () => consoleSymbols,
82533
+ coordinatorGateBlockReason: () => coordinatorGateBlockReason,
81236
82534
  coordinatorIdentityFromEmitFields: () => coordinatorIdentityFromEmitFields,
81237
82535
  createDebugTraceStore: () => createDebugTraceStore,
81238
82536
  createDefaultGitCommandServices: () => createDefaultGitCommandServices,
@@ -81252,6 +82550,7 @@ ${e?.stderr || ""}`;
81252
82550
  delegatedWorkerAutoApproveSettings: () => delegatedWorkerAutoApproveSettings,
81253
82551
  deleteDirectDispatchesByTaskId: () => deleteDirectDispatchesByTaskId,
81254
82552
  deleteMesh: () => deleteMesh,
82553
+ deriveDependencyFailures: () => deriveDependencyFailures,
81255
82554
  deriveMeshNodeHealthFromGit: () => deriveMeshNodeHealthFromGit,
81256
82555
  deriveMeshReviewInboxItems: () => deriveMeshReviewInboxItems,
81257
82556
  deriveWorkspaceBranchIdentity: () => deriveWorkspaceBranchIdentity,
@@ -81352,6 +82651,7 @@ ${e?.stderr || ""}`;
81352
82651
  installGlobalInterceptor: () => installGlobalInterceptor,
81353
82652
  interactivePromptFromClaudeAskUserQuestion: () => interactivePromptFromClaudeAskUserQuestion,
81354
82653
  isActivityChatMessage: () => isActivityChatMessage,
82654
+ isAdvancedGraphTask: () => isAdvancedGraphTask,
81355
82655
  isAlwaysOnTraceCategory: () => isAlwaysOnTraceCategory,
81356
82656
  isBuiltinChatMessageKind: () => isBuiltinChatMessageKind,
81357
82657
  isCdpConnected: () => isCdpConnected,
@@ -81437,11 +82737,13 @@ ${e?.stderr || ""}`;
81437
82737
  normalizeMeshTaskPriority: () => normalizeMeshTaskPriority,
81438
82738
  normalizeMeshWorkerResult: () => normalizeMeshWorkerResult,
81439
82739
  normalizeMessageParts: () => normalizeMessageParts,
82740
+ normalizeOrchestrationDecision: () => normalizeOrchestrationDecision,
81440
82741
  normalizeRepoIdentity: () => normalizeRepoIdentity,
81441
82742
  normalizeRepoMeshDeclarativeConfig: () => normalizeRepoMeshDeclarativeConfig,
81442
82743
  normalizeSessionModalFields: () => normalizeSessionModalFields,
81443
82744
  notifyCoordinatorOfOrphanedPins: () => notifyCoordinatorOfOrphanedPins,
81444
82745
  otherTrackConfigDir: () => otherTrackConfigDir,
82746
+ parseOnDependencyFailurePolicy: () => parseOnDependencyFailurePolicy,
81445
82747
  parsePorcelainV2Status: () => parsePorcelainV2Status,
81446
82748
  parseProviderSourceConfigUpdate: () => parseProviderSourceConfigUpdate,
81447
82749
  parseWorktreeListOutput: () => parseWorktreeListOutput,
@@ -81458,6 +82760,7 @@ ${e?.stderr || ""}`;
81458
82760
  printQuota: () => printQuota2,
81459
82761
  printQuotaInstallError: () => printQuotaInstallError2,
81460
82762
  probeCdpPort: () => probeCdpPort,
82763
+ projectGraphPublicPolicy: () => projectGraphPublicPolicy,
81461
82764
  pruneOperatingNotes: () => pruneOperatingNotes,
81462
82765
  pruneStaleDirectDispatches: () => pruneStaleDirectDispatches,
81463
82766
  queuePendingMeshCoordinatorEvent: () => queuePendingMeshCoordinatorEvent,
@@ -81481,15 +82784,23 @@ ${e?.stderr || ""}`;
81481
82784
  reconcileDirectDispatchCompletionFromTranscript: () => reconcileDirectDispatchCompletionFromTranscript,
81482
82785
  recordDebugTrace: () => recordDebugTrace,
81483
82786
  recordDirectDispatchTask: () => recordDirectDispatchTask,
82787
+ recordGraphEnqueueCommitted: () => recordGraphEnqueueCommitted,
82788
+ recordGraphEnqueueRolledBack: () => recordGraphEnqueueRolledBack,
82789
+ recordGraphEnqueueValidationFailed: () => recordGraphEnqueueValidationFailed,
82790
+ recordGraphGateClaimed: () => recordGraphGateClaimed,
82791
+ recordGraphGateExpired: () => recordGraphGateExpired,
82792
+ recordGraphGateReleased: () => recordGraphGateReleased,
81484
82793
  recordMeshToolCall: () => recordMeshToolCall,
81485
82794
  recordMissingSessionAttempt: () => recordMissingSessionAttempt2,
81486
82795
  recordSessionUsage: () => recordSessionUsage,
81487
82796
  recoverExpiredWorkspaceSagas: () => recoverExpiredWorkspaceSagas,
81488
82797
  registerExtensionProviders: () => registerExtensionProviders,
81489
82798
  registerMeshCoordinator: () => registerMeshCoordinator,
82799
+ releaseMeshGraphGate: () => releaseMeshGraphGate,
81490
82800
  removeMagiKindPanel: () => removeMagiKindPanel,
81491
82801
  removeNode: () => removeNode,
81492
82802
  removeWorktree: () => removeWorktree,
82803
+ requestUsesGraphV2: () => requestUsesGraphV2,
81493
82804
  requeueHeldMeshCoordinatorEvents: () => requeueHeldMeshCoordinatorEvents,
81494
82805
  requeueTask: () => requeueTask,
81495
82806
  requireMeshHostQueueOwner: () => requireMeshHostQueueOwner,
@@ -81524,6 +82835,7 @@ ${e?.stderr || ""}`;
81524
82835
  resolveNodeSchedulingPriority: () => resolveNodeSchedulingPriority,
81525
82836
  resolveNotBefore: () => resolveNotBefore,
81526
82837
  resolveNpmPublishedVersion: () => resolveNpmPublishedVersion,
82838
+ resolveOnDependencyFailurePolicy: () => resolveOnDependencyFailurePolicy,
81527
82839
  resolveProviderChannel: () => resolveProviderChannel,
81528
82840
  resolveProviderMaxParallel: () => resolveProviderMaxParallel,
81529
82841
  resolveScopedMeshId: () => resolveScopedMeshId,
@@ -81568,6 +82880,7 @@ ${e?.stderr || ""}`;
81568
82880
  summarizeMeshUsage: () => summarizeMeshUsage,
81569
82881
  summarizeMissionTasks: () => summarizeMissionTasks,
81570
82882
  supportsUnicodeSymbols: () => supportsUnicodeSymbols,
82883
+ sweepMeshGraphGateTimeouts: () => sweepMeshGraphGateTimeouts,
81571
82884
  taskDependenciesSatisfied: () => taskDependenciesSatisfied,
81572
82885
  tombstoneOperatingNote: () => tombstoneOperatingNote,
81573
82886
  totalTokens: () => totalTokens,
@@ -84066,10 +85379,658 @@ ${e?.stderr || ""}`;
84066
85379
  };
84067
85380
  }
84068
85381
  init_mesh_work_queue();
85382
+ init_mesh_graph_derived_failure();
84069
85383
  init_mesh_graph_workspace_saga();
84070
85384
  init_mesh_graph_workspace_safety();
84071
85385
  init_mesh_graph_workspace_identity();
84072
85386
  init_mesh_graph_workspace_ports();
85387
+ init_mesh_graph_gates();
85388
+ var import_crypto14 = require("crypto");
85389
+ init_logger();
85390
+ init_mesh_runtime_store();
85391
+ init_mesh_graph_input_binding();
85392
+ init_mesh_graph_types();
85393
+ init_mesh_graph_derived_failure();
85394
+ init_mesh_graph_transition_runner();
85395
+ init_mesh_graph_workspace_saga();
85396
+ init_mesh_work_queue();
85397
+ var MeshGraphPlanError = class extends Error {
85398
+ constructor(code, message, extra) {
85399
+ super(`${code}: ${message}`);
85400
+ this.code = code;
85401
+ this.extra = extra;
85402
+ this.name = "MeshGraphPlanError";
85403
+ }
85404
+ };
85405
+ function isAdvancedGraphTask(spec) {
85406
+ return spec.inputs_from !== void 0 || spec.run_if !== void 0 || typeof spec.workspace_ref === "string" && spec.workspace_ref.trim().length > 0 || Array.isArray(spec.gated_by) && spec.gated_by.length > 0;
85407
+ }
85408
+ function requestUsesGraphV2(req) {
85409
+ if (Array.isArray(req.gates) && req.gates.length > 0) return true;
85410
+ if (Array.isArray(req.workspaces) && req.workspaces.length > 0) return true;
85411
+ return (req.tasks ?? []).some(isAdvancedGraphTask);
85412
+ }
85413
+ function normalizeRef(value, label) {
85414
+ const ref = typeof value === "string" ? value.trim() : "";
85415
+ if (!ref) throw new MeshGraphPlanError("invalid_graph_ref", `${label} requires a non-empty ref`);
85416
+ return ref;
85417
+ }
85418
+ function pickEnum(value, allowed, fallback, code, label) {
85419
+ if (value === void 0 || value === null || value === "") return fallback;
85420
+ if (typeof value === "string" && allowed.includes(value)) return value;
85421
+ throw new MeshGraphPlanError(code, `${label} must be one of ${allowed.join(" | ")} (got ${JSON.stringify(value)})`);
85422
+ }
85423
+ function computeMeshGraphPlanDigest(req) {
85424
+ const normalized = {
85425
+ tasks: (req.tasks ?? []).map((t) => ({
85426
+ ref: typeof t.ref === "string" ? t.ref.trim() : null,
85427
+ message: t.message,
85428
+ depends_on: [...t.dependsOn ?? []].sort(),
85429
+ gated_by: [...t.gated_by ?? []].sort(),
85430
+ inputs_from: t.inputs_from ?? null,
85431
+ run_if: t.run_if ?? null,
85432
+ on_false: t.on_false ?? null,
85433
+ on_upstream_skip: t.on_upstream_skip ?? null,
85434
+ workspace_ref: t.workspace_ref ?? null,
85435
+ target_node_id: t.targetNodeId ?? null,
85436
+ task_mode: t.taskMode ?? null,
85437
+ difficulty: t.difficulty ?? null
85438
+ })),
85439
+ gates: (req.gates ?? []).map((g) => ({
85440
+ ref: g.ref,
85441
+ action: g.action ?? "custom",
85442
+ depends_on: [...g.depends_on ?? []].sort(),
85443
+ on_timeout: g.on_timeout ?? "hold",
85444
+ lease_seconds: g.lease_seconds ?? null,
85445
+ deadline_seconds: g.deadline_seconds ?? null
85446
+ })),
85447
+ workspaces: (req.workspaces ?? []).map((w) => ({
85448
+ ref: w.ref,
85449
+ source_node_id: w.source_node_id ?? null,
85450
+ base_revision: w.base_revision ?? null,
85451
+ desired_path: w.desired_path ?? null,
85452
+ cleanup_on_graph_failure: w.cleanup_on_graph_failure === true
85453
+ })),
85454
+ on_dependency_failure: parseOnDependencyFailurePolicy(req.onDependencyFailure)
85455
+ };
85456
+ return (0, import_crypto14.createHash)("sha256").update(canonicalJson(normalized)).digest("hex");
85457
+ }
85458
+ function commitMeshGraphPlan(req) {
85459
+ const store = MeshRuntimeStore.getInstance();
85460
+ const tasks = Array.isArray(req.tasks) ? req.tasks : [];
85461
+ if (tasks.length === 0) {
85462
+ throw new MeshGraphPlanError("empty_task_graph", "a graph plan requires at least one task");
85463
+ }
85464
+ const gates = Array.isArray(req.gates) ? req.gates : [];
85465
+ const workspaces = Array.isArray(req.workspaces) ? req.workspaces : [];
85466
+ const policy = { on_dependency_failure: parseOnDependencyFailurePolicy(req.onDependencyFailure) };
85467
+ const planDigest = computeMeshGraphPlanDigest(req);
85468
+ const batchId = typeof req.batchId === "string" && req.batchId.trim() ? req.batchId.trim() : newMeshGraphId();
85469
+ const nowIso = (/* @__PURE__ */ new Date()).toISOString();
85470
+ const taskRefs = /* @__PURE__ */ new Map();
85471
+ tasks.forEach((t, i) => {
85472
+ const ref = typeof t.ref === "string" ? t.ref.trim() : "";
85473
+ if (!ref) return;
85474
+ if (taskRefs.has(ref)) {
85475
+ throw new MeshGraphPlanError("duplicate_task_ref", `ref '${ref}' is used by more than one task in this batch`);
85476
+ }
85477
+ taskRefs.set(ref, i);
85478
+ });
85479
+ const gateRefs = /* @__PURE__ */ new Map();
85480
+ gates.forEach((g, i) => {
85481
+ const ref = normalizeRef(g.ref, `gates[${i}]`);
85482
+ if (taskRefs.has(ref) || gateRefs.has(ref)) {
85483
+ throw new MeshGraphPlanError(
85484
+ "duplicate_graph_ref",
85485
+ `ref '${ref}' is declared more than once \u2014 tasks, gates and workspaces share ONE ref namespace`
85486
+ );
85487
+ }
85488
+ gateRefs.set(ref, i);
85489
+ });
85490
+ const workspaceRefs = /* @__PURE__ */ new Set();
85491
+ workspaces.forEach((w, i) => {
85492
+ const ref = normalizeRef(w.ref, `workspaces[${i}]`);
85493
+ if (taskRefs.has(ref) || gateRefs.has(ref) || workspaceRefs.has(ref)) {
85494
+ throw new MeshGraphPlanError(
85495
+ "duplicate_graph_ref",
85496
+ `ref '${ref}' is declared more than once \u2014 tasks, gates and workspaces share ONE ref namespace`
85497
+ );
85498
+ }
85499
+ workspaceRefs.add(ref);
85500
+ });
85501
+ tasks.forEach((t, i) => {
85502
+ for (const dep of t.dependsOn ?? []) {
85503
+ if (gateRefs.has(dep)) {
85504
+ throw new MeshGraphPlanError(
85505
+ "gate_ref_in_depends_on",
85506
+ `task ${t.ref ? `'${t.ref}'` : `#${i}`} lists gate ref '${dep}' in depends_on \u2014 use gated_by to declare a gate edge (a gate is an intentional stop, never an ordinary queue dependency)`
85507
+ );
85508
+ }
85509
+ }
85510
+ for (const gateRef of t.gated_by ?? []) {
85511
+ if (!gateRefs.has(gateRef)) {
85512
+ throw new MeshGraphPlanError(
85513
+ "unknown_gate_ref",
85514
+ `task ${t.ref ? `'${t.ref}'` : `#${i}`} is gated_by '${gateRef}', which is not a gate in this batch` + (gateRefs.size ? ` (gates: ${[...gateRefs.keys()].join(", ")})` : "")
85515
+ );
85516
+ }
85517
+ }
85518
+ const ws = typeof t.workspace_ref === "string" ? t.workspace_ref.trim() : "";
85519
+ if (ws && !workspaceRefs.has(ws)) {
85520
+ throw new MeshGraphPlanError(
85521
+ "unknown_workspace_ref",
85522
+ `task ${t.ref ? `'${t.ref}'` : `#${i}`} names workspace_ref '${ws}', which is not declared in this batch`
85523
+ );
85524
+ }
85525
+ });
85526
+ gates.forEach((g, i) => {
85527
+ for (const dep of g.depends_on ?? []) {
85528
+ if (!taskRefs.has(dep) && !gateRefs.has(dep)) {
85529
+ throw new MeshGraphPlanError(
85530
+ "unknown_gate_dependency",
85531
+ `gate '${g.ref}' depends on '${dep}', which is not a task or gate ref in this batch`
85532
+ );
85533
+ }
85534
+ }
85535
+ pickEnum(g.action, MESH_GRAPH_GATE_ACTIONS, "custom", "invalid_gate_action", `gates[${i}].action`);
85536
+ pickEnum(g.on_timeout, MESH_GRAPH_GATE_TIMEOUT_POLICIES, "hold", "invalid_gate_on_timeout", `gates[${i}].on_timeout`);
85537
+ });
85538
+ tasks.forEach((t, i) => {
85539
+ pickEnum(t.on_upstream_skip, MESH_GRAPH_ON_UPSTREAM_SKIP_POLICIES, "skip", "invalid_on_upstream_skip", `tasks[${i}].on_upstream_skip`);
85540
+ });
85541
+ const result = store.transaction(() => {
85542
+ const graphStore = store.graphStore();
85543
+ const existing = graphStore.getGraphByBatchId(req.meshId, batchId);
85544
+ if (existing) {
85545
+ if (existing.planDigest !== planDigest) {
85546
+ throw new MeshGraphPlanError(
85547
+ "batch_id_conflict",
85548
+ `batch_id '${batchId}' already exists on this mesh with a DIFFERENT plan digest \u2014 reuse of a batch id is only idempotent for an identical plan`,
85549
+ { graphId: existing.graphId }
85550
+ );
85551
+ }
85552
+ const existingNodes = graphStore.listNodes(existing.graphId);
85553
+ const workerNodes = existingNodes.filter((n) => n.kind === "worker_task");
85554
+ const replayTasks = workerNodes.map((n) => n.queueTaskId ? store.findQueueEntryById(req.meshId, n.queueTaskId) : null).filter((e) => !!e);
85555
+ return {
85556
+ graphId: existing.graphId,
85557
+ batchId,
85558
+ tasks: replayTasks,
85559
+ nodeIdByIndex: workerNodes.map((n) => n.nodeId),
85560
+ gates: graphStore.listGatesByGraph(existing.graphId).map((g) => ({
85561
+ ref: g.ref ?? g.gateId,
85562
+ gateId: g.gateId,
85563
+ nodeId: g.nodeId,
85564
+ action: g.action
85565
+ })),
85566
+ workspaces: graphStore.listWorkspaceIntents(existing.graphId).map((w) => ({
85567
+ ref: w.workspaceRef,
85568
+ sagaState: w.sagaState,
85569
+ branchIdentity: w.branchIdentity
85570
+ })),
85571
+ dependencyEdgeCount: existing.dependencyEdgeCount,
85572
+ planDigest,
85573
+ replayed: true,
85574
+ workspacePreparation: existing.workspaceCount > 0 ? "pending" : "not_requested",
85575
+ heldNodeIds: []
85576
+ };
85577
+ }
85578
+ const queueSpecs = tasks.map((t) => {
85579
+ const {
85580
+ inputs_from: _inputsFrom,
85581
+ run_if: _runIf,
85582
+ on_false: _onFalse,
85583
+ on_upstream_skip: _onUpstreamSkip,
85584
+ workspace_ref: _workspaceRef,
85585
+ gated_by: _gatedBy,
85586
+ ...queueSpec
85587
+ } = t;
85588
+ return {
85589
+ ...queueSpec,
85590
+ missionId: queueSpec.missionId ?? req.missionId,
85591
+ ...req.sourceCoordinatorSessionId ? { sourceCoordinatorSessionId: req.sourceCoordinatorSessionId } : {}
85592
+ };
85593
+ });
85594
+ const inserted = enqueueTaskGraph(req.meshId, queueSpecs);
85595
+ const graphId = newMeshGraphId();
85596
+ const nodeIdByIndex = tasks.map(() => newMeshGraphNodeId());
85597
+ const gateNodeIdByRef = /* @__PURE__ */ new Map();
85598
+ const gateIdByRef = /* @__PURE__ */ new Map();
85599
+ gates.forEach((g) => {
85600
+ gateNodeIdByRef.set(g.ref.trim(), newMeshGraphNodeId());
85601
+ gateIdByRef.set(g.ref.trim(), newMeshGraphGateId());
85602
+ });
85603
+ const nodeIdByRef = /* @__PURE__ */ new Map();
85604
+ tasks.forEach((t, i) => {
85605
+ const ref = typeof t.ref === "string" ? t.ref.trim() : "";
85606
+ if (ref) nodeIdByRef.set(ref, nodeIdByIndex[i]);
85607
+ });
85608
+ for (const [ref, nodeId] of gateNodeIdByRef) nodeIdByRef.set(ref, nodeId);
85609
+ const edges = [];
85610
+ const addEdge = (fromNodeId, toNodeId, kind, omitOnSkip) => {
85611
+ edges.push({ graphId, meshId: req.meshId, fromNodeId, toNodeId, kind, omitOnSkip, createdAt: nowIso });
85612
+ };
85613
+ tasks.forEach((t, i) => {
85614
+ const nodeId = nodeIdByIndex[i];
85615
+ const ref = typeof t.ref === "string" ? t.ref.trim() : void 0;
85616
+ const baseSpec = { message: t.message };
85617
+ if (t.inputs_from !== void 0) baseSpec.inputs_from = t.inputs_from;
85618
+ if (t.run_if !== void 0) baseSpec.run_if = t.run_if;
85619
+ if (t.on_false !== void 0) baseSpec.on_false = t.on_false;
85620
+ if (typeof t.workspace_ref === "string" && t.workspace_ref.trim()) {
85621
+ baseSpec.workspace_ref = t.workspace_ref.trim();
85622
+ }
85623
+ const node = {
85624
+ graphId,
85625
+ nodeId,
85626
+ meshId: req.meshId,
85627
+ ...ref ? { ref } : {},
85628
+ kind: "worker_task",
85629
+ queueTaskId: inserted[i].id,
85630
+ state: "declared",
85631
+ baseSpecJson: JSON.stringify(baseSpec),
85632
+ materializationVersion: 0,
85633
+ createdAt: nowIso,
85634
+ updatedAt: nowIso
85635
+ };
85636
+ graphStore.insertNode(node);
85637
+ });
85638
+ gates.forEach((g, i) => {
85639
+ const ref = g.ref.trim();
85640
+ const nodeId = gateNodeIdByRef.get(ref);
85641
+ const gateSpec = {};
85642
+ if (typeof g.lease_seconds === "number" && g.lease_seconds > 0) gateSpec.lease_seconds = g.lease_seconds;
85643
+ if (typeof g.deadline_seconds === "number" && g.deadline_seconds > 0) gateSpec.deadline_seconds = g.deadline_seconds;
85644
+ graphStore.insertNode({
85645
+ graphId,
85646
+ nodeId,
85647
+ meshId: req.meshId,
85648
+ ref,
85649
+ kind: "coordinator_gate",
85650
+ state: "declared",
85651
+ baseSpecJson: JSON.stringify(gateSpec),
85652
+ materializationVersion: 0,
85653
+ createdAt: nowIso,
85654
+ updatedAt: nowIso
85655
+ });
85656
+ graphStore.insertGate({
85657
+ gateId: gateIdByRef.get(ref),
85658
+ graphId,
85659
+ nodeId,
85660
+ meshId: req.meshId,
85661
+ ref,
85662
+ state: "declared",
85663
+ action: pickEnum(g.action, MESH_GRAPH_GATE_ACTIONS, "custom", "invalid_gate_action", `gates[${i}].action`),
85664
+ instructions: typeof g.instructions === "string" ? g.instructions : void 0,
85665
+ eligibleCoordinatorSessionId: typeof g.eligible_coordinator_session_id === "string" ? g.eligible_coordinator_session_id : void 0,
85666
+ leaseGeneration: 0,
85667
+ onTimeout: pickEnum(g.on_timeout, MESH_GRAPH_GATE_TIMEOUT_POLICIES, "hold", "invalid_gate_on_timeout", `gates[${i}].on_timeout`),
85668
+ createdAt: nowIso,
85669
+ updatedAt: nowIso
85670
+ });
85671
+ });
85672
+ tasks.forEach((t, i) => {
85673
+ const omitOnSkip = pickEnum(
85674
+ t.on_upstream_skip,
85675
+ MESH_GRAPH_ON_UPSTREAM_SKIP_POLICIES,
85676
+ "skip",
85677
+ "invalid_on_upstream_skip",
85678
+ `tasks[${i}].on_upstream_skip`
85679
+ ) === "omit_dependency";
85680
+ for (const dep of t.dependsOn ?? []) {
85681
+ const fromNodeId = nodeIdByRef.get(dep);
85682
+ if (!fromNodeId) continue;
85683
+ addEdge(fromNodeId, nodeIdByIndex[i], "requires", omitOnSkip);
85684
+ }
85685
+ for (const sourceRef of collectRunIfSourceRefs(t.run_if)) {
85686
+ const fromNodeId = nodeIdByRef.get(sourceRef);
85687
+ if (!fromNodeId || fromNodeId === nodeIdByIndex[i]) continue;
85688
+ if (edges.some((e) => e.fromNodeId === fromNodeId && e.toNodeId === nodeIdByIndex[i])) continue;
85689
+ addEdge(fromNodeId, nodeIdByIndex[i], "conditional", omitOnSkip);
85690
+ }
85691
+ for (const sourceRef of collectInputSourceRefs(t.inputs_from)) {
85692
+ const fromNodeId = nodeIdByRef.get(sourceRef);
85693
+ if (!fromNodeId || fromNodeId === nodeIdByIndex[i]) continue;
85694
+ if (edges.some((e) => e.fromNodeId === fromNodeId && e.toNodeId === nodeIdByIndex[i] && e.kind === "requires")) continue;
85695
+ addEdge(fromNodeId, nodeIdByIndex[i], "requires", omitOnSkip);
85696
+ }
85697
+ for (const gateRef of t.gated_by ?? []) {
85698
+ const fromNodeId = gateNodeIdByRef.get(gateRef.trim());
85699
+ if (!fromNodeId) continue;
85700
+ addEdge(fromNodeId, nodeIdByIndex[i], "gate", false);
85701
+ }
85702
+ });
85703
+ gates.forEach((g) => {
85704
+ const toNodeId = gateNodeIdByRef.get(g.ref.trim());
85705
+ for (const dep of g.depends_on ?? []) {
85706
+ const fromNodeId = nodeIdByRef.get(dep);
85707
+ if (!fromNodeId) continue;
85708
+ addEdge(fromNodeId, toNodeId, "requires", false);
85709
+ }
85710
+ });
85711
+ for (const edge of edges) graphStore.insertEdge(edge);
85712
+ graphStore.insertGraph({
85713
+ graphId,
85714
+ meshId: req.meshId,
85715
+ batchId,
85716
+ missionId: req.missionId,
85717
+ sourceCoordinatorSessionId: req.sourceCoordinatorSessionId,
85718
+ enqueueSurface: req.enqueueSurface ?? "batch",
85719
+ schemaVersion: MESH_GRAPH_SCHEMA_VERSION,
85720
+ status: "active",
85721
+ taskCount: tasks.length,
85722
+ gateCount: gates.length,
85723
+ workspaceCount: workspaces.length,
85724
+ dependencyEdgeCount: edges.length,
85725
+ planDigest,
85726
+ // ★ E-2: `on_dependency_failure` is now PERSISTED on the graph row
85727
+ // (C3 only validated and echoed it). The C3 derived-failure path reads
85728
+ // it back through parseGraphPolicy/projectGraphPublicPolicy.
85729
+ policyJson: serializeGraphPolicy(policy),
85730
+ createdAt: nowIso,
85731
+ activatedAt: nowIso,
85732
+ updatedAt: nowIso
85733
+ });
85734
+ if (req.orchestrationDecision) {
85735
+ const merged = JSON.stringify({
85736
+ ...JSON.parse(serializeGraphPolicy(policy)),
85737
+ orchestration_decision: req.orchestrationDecision
85738
+ });
85739
+ graphStore.updateGraphPolicyJson(graphId, merged, nowIso);
85740
+ }
85741
+ const heldNodeIds = [];
85742
+ tasks.forEach((t, i) => {
85743
+ if (!isAdvancedGraphTask(t)) return;
85744
+ const nodeId = nodeIdByIndex[i];
85745
+ const entry = store.findQueueEntryById(req.meshId, inserted[i].id);
85746
+ if (!entry || entry.status !== "pending" || entry.blockedReason) return;
85747
+ entry.blockedReason = graphMaterializationBlockReason(nodeId, 0);
85748
+ store.updateQueueEntry(entry);
85749
+ graphStore.updateNodeState(graphId, nodeId, "blocked", nowIso);
85750
+ heldNodeIds.push(nodeId);
85751
+ });
85752
+ return {
85753
+ graphId,
85754
+ batchId,
85755
+ tasks: inserted,
85756
+ nodeIdByIndex,
85757
+ gates: gates.map((g) => ({
85758
+ ref: g.ref.trim(),
85759
+ gateId: gateIdByRef.get(g.ref.trim()),
85760
+ nodeId: gateNodeIdByRef.get(g.ref.trim()),
85761
+ action: pickEnum(g.action, MESH_GRAPH_GATE_ACTIONS, "custom", "invalid_gate_action", "gate action")
85762
+ })),
85763
+ workspaces: [],
85764
+ dependencyEdgeCount: edges.length,
85765
+ planDigest,
85766
+ replayed: false,
85767
+ workspacePreparation: workspaces.length > 0 ? "pending" : "not_requested",
85768
+ heldNodeIds
85769
+ };
85770
+ });
85771
+ if (!result.replayed && workspaces.length > 0) {
85772
+ try {
85773
+ const declared = declareWorkspaceIntents({
85774
+ graphId: result.graphId,
85775
+ meshId: req.meshId,
85776
+ workspaces
85777
+ });
85778
+ result.workspaces = declared.map((w) => ({
85779
+ ref: w.workspaceRef,
85780
+ sagaState: w.sagaState,
85781
+ branchIdentity: w.branchIdentity
85782
+ }));
85783
+ } catch (e) {
85784
+ LOG2.warn("MeshGraph", `Workspace intent declaration failed for graph ${result.graphId}: ${e?.message || e}`);
85785
+ }
85786
+ }
85787
+ return result;
85788
+ }
85789
+ function collectRunIfSourceRefs(runIf, depth = 0) {
85790
+ if (!runIf || typeof runIf !== "object" || depth > 8) return [];
85791
+ const out = [];
85792
+ const node = runIf;
85793
+ if (typeof node.from === "string" && node.from.trim()) out.push(node.from.trim());
85794
+ for (const key2 of ["all", "any", "not", "conditions"]) {
85795
+ const child = node[key2];
85796
+ if (Array.isArray(child)) {
85797
+ for (const item of child) out.push(...collectRunIfSourceRefs(item, depth + 1));
85798
+ } else if (child && typeof child === "object") {
85799
+ out.push(...collectRunIfSourceRefs(child, depth + 1));
85800
+ }
85801
+ }
85802
+ return [...new Set(out)];
85803
+ }
85804
+ function collectInputSourceRefs(inputsFrom) {
85805
+ if (!Array.isArray(inputsFrom)) return [];
85806
+ const out = [];
85807
+ for (const item of inputsFrom) {
85808
+ if (item && typeof item === "object" && typeof item.from === "string") {
85809
+ const from = item.from.trim();
85810
+ if (from) out.push(from);
85811
+ }
85812
+ }
85813
+ return [...new Set(out)];
85814
+ }
85815
+ init_mesh_runtime_store();
85816
+ init_mesh_graph_derived_failure();
85817
+ init_mesh_graph_transition_runner();
85818
+ var IN_FLIGHT_GRAPH_STATUSES = [
85819
+ "preparing",
85820
+ "active",
85821
+ "waiting_gate",
85822
+ "compensation_required"
85823
+ ];
85824
+ function buildMeshGraphViews(meshId, opts = {}) {
85825
+ const store = MeshRuntimeStore.getInstance();
85826
+ const graphStore = store.graphStore();
85827
+ const nowIso = new Date(opts.nowMs ?? Date.now()).toISOString();
85828
+ let graphs;
85829
+ if (opts.graphId) {
85830
+ const one = graphStore.getGraph(opts.graphId);
85831
+ graphs = one && one.meshId === meshId ? [one] : [];
85832
+ } else if (opts.batchId) {
85833
+ const one = graphStore.getGraphByBatchId(meshId, opts.batchId);
85834
+ graphs = one ? [one] : [];
85835
+ } else {
85836
+ graphs = graphStore.listGraphsByMesh(meshId, {
85837
+ ...opts.activeOnly === false ? {} : { statuses: IN_FLIGHT_GRAPH_STATUSES },
85838
+ limit: opts.limit ?? 20
85839
+ });
85840
+ }
85841
+ return graphs.map((graph) => {
85842
+ const nodes = graphStore.listNodes(graph.graphId);
85843
+ const edges = graphStore.listEdges(graph.graphId);
85844
+ const gates = graphStore.listGatesByGraph(graph.graphId);
85845
+ const workspaces = graphStore.listWorkspaceIntents(graph.graphId);
85846
+ const byId = new Map(nodes.map((n) => [n.nodeId, n]));
85847
+ const policy = projectGraphPublicPolicy(graph.policyJson);
85848
+ const decision = readOrchestrationDecision(graph.policyJson);
85849
+ const queueByTaskId = /* @__PURE__ */ new Map();
85850
+ for (const node of nodes) {
85851
+ if (!node.queueTaskId) continue;
85852
+ const entry = store.findQueueEntryById(meshId, node.queueTaskId);
85853
+ if (entry) {
85854
+ queueByTaskId.set(node.queueTaskId, {
85855
+ status: entry.status,
85856
+ blockedReason: entry.blockedReason,
85857
+ cancelReason: entry.cancelReason,
85858
+ dependsOn: entry.dependsOn
85859
+ });
85860
+ }
85861
+ }
85862
+ const statusById = /* @__PURE__ */ new Map();
85863
+ const depMetaById = /* @__PURE__ */ new Map();
85864
+ for (const [taskId, row] of queueByTaskId) {
85865
+ statusById.set(taskId, row.status);
85866
+ depMetaById.set(taskId, { status: row.status, blockedReason: row.blockedReason, cancelReason: row.cancelReason });
85867
+ }
85868
+ for (const row of queueByTaskId.values()) {
85869
+ for (const depId of row.dependsOn ?? []) {
85870
+ if (statusById.has(depId)) continue;
85871
+ const dep = store.findQueueEntryById(meshId, depId);
85872
+ if (!dep) continue;
85873
+ statusById.set(depId, dep.status);
85874
+ depMetaById.set(depId, {
85875
+ status: dep.status,
85876
+ blockedReason: dep.blockedReason,
85877
+ cancelReason: dep.cancelReason
85878
+ });
85879
+ }
85880
+ }
85881
+ const gateByNodeId = new Map(gates.map((g) => [g.nodeId, g]));
85882
+ const nodeViews = nodes.map((node) => {
85883
+ const queue = node.queueTaskId ? queueByTaskId.get(node.queueTaskId) : void 0;
85884
+ const gateBlock = parseCoordinatorGateBlock(queue?.blockedReason);
85885
+ const failures = queue?.dependsOn?.length ? deriveDependencyFailures(queue.dependsOn, statusById, depMetaById) : [];
85886
+ return {
85887
+ nodeId: node.nodeId,
85888
+ ...node.ref ? { ref: node.ref } : {},
85889
+ kind: node.kind,
85890
+ state: node.state,
85891
+ ...node.queueTaskId ? { taskId: node.queueTaskId } : {},
85892
+ ...queue ? { taskStatus: queue.status } : {},
85893
+ ...queue?.blockedReason ? { blockedReason: queue.blockedReason } : {},
85894
+ ...gateBlock ? { blockedByGateId: gateBlock.gateId } : {},
85895
+ materializationVersion: node.materializationVersion,
85896
+ ...node.materializedDigest ? { materializedDigest: node.materializedDigest } : {},
85897
+ ...node.skipReason ? { skipReason: node.skipReason } : {},
85898
+ ...node.failureReason ? { failureReason: node.failureReason } : {},
85899
+ ...failures.length > 0 ? { dependencyFailures: failures } : {},
85900
+ ...describeNodeFeatures(node.baseSpecJson).length > 0 ? { features: describeNodeFeatures(node.baseSpecJson) } : {}
85901
+ };
85902
+ });
85903
+ const edgeViews = edges.map((edge) => {
85904
+ const source = byId.get(edge.fromNodeId);
85905
+ const active = !(source?.state === "skipped" && edge.omitOnSkip);
85906
+ return {
85907
+ from: source?.ref ?? edge.fromNodeId,
85908
+ to: byId.get(edge.toNodeId)?.ref ?? edge.toNodeId,
85909
+ kind: edge.kind,
85910
+ omitOnSkip: edge.omitOnSkip,
85911
+ active
85912
+ };
85913
+ });
85914
+ const gateViews = gates.map((gate) => {
85915
+ const blocking = nodeViews.filter((n) => n.blockedByGateId === gate.gateId).map((n) => n.ref ?? n.nodeId);
85916
+ const leaseExpired = gate.state === "claimed" && !!gate.leaseExpiresAt && gate.leaseExpiresAt <= nowIso;
85917
+ return {
85918
+ gateId: gate.gateId,
85919
+ ...gate.ref ? { ref: gate.ref } : {},
85920
+ nodeId: gate.nodeId,
85921
+ state: gate.state,
85922
+ action: gate.action,
85923
+ ...gate.instructions ? { instructions: gate.instructions } : {},
85924
+ onTimeout: gate.onTimeout,
85925
+ leaseGeneration: gate.leaseGeneration,
85926
+ ...gate.leaseOwnerSessionId ? { leaseOwnerSessionId: gate.leaseOwnerSessionId } : {},
85927
+ ...gate.leaseExpiresAt ? { leaseExpiresAt: gate.leaseExpiresAt } : {},
85928
+ ...leaseExpired ? { leaseExpired: true } : {},
85929
+ ...gate.deadlineAt ? { deadlineAt: gate.deadlineAt } : {},
85930
+ ...gate.releaseOutcome ? { releaseOutcome: gate.releaseOutcome } : {},
85931
+ ...gate.eligibleCoordinatorSessionId ? { eligibleCoordinatorSessionId: gate.eligibleCoordinatorSessionId } : {},
85932
+ ...blocking.length > 0 ? { blocking } : {}
85933
+ };
85934
+ });
85935
+ const nodeStates = {};
85936
+ for (const node of nodes) nodeStates[node.state] = (nodeStates[node.state] ?? 0) + 1;
85937
+ const actions = [];
85938
+ for (const gate of gateViews) {
85939
+ if (gate.state === "awaiting_coordinator") {
85940
+ actions.push({
85941
+ kind: "gate_awaiting",
85942
+ gateId: gate.gateId,
85943
+ detail: `Gate '${gate.ref ?? gate.gateId}' (${gate.action}) is awaiting a coordinator. Claim it with mesh_graph_gate_claim, perform the action, then release it with mesh_graph_gate_release.`
85944
+ });
85945
+ } else if (gate.state === "claimed" && gate.leaseExpired) {
85946
+ actions.push({
85947
+ kind: "gate_reclaim",
85948
+ gateId: gate.gateId,
85949
+ detail: `Gate '${gate.ref ?? gate.gateId}' has a LAPSED lease (generation ${gate.leaseGeneration}). Reclaim it to get a higher generation; the previous owner may already have performed the external side effect, so reconcile external evidence before acting again.`
85950
+ });
85951
+ } else if (gate.state === "claimed") {
85952
+ actions.push({
85953
+ kind: "gate_claimed",
85954
+ gateId: gate.gateId,
85955
+ detail: `Gate '${gate.ref ?? gate.gateId}' is claimed by ${gate.leaseOwnerSessionId ?? "a coordinator"} until ${gate.leaseExpiresAt ?? "lease expiry"}; release it to advance the graph.`
85956
+ });
85957
+ } else if (gate.state === "expired" && gate.onTimeout === "hold") {
85958
+ actions.push({
85959
+ kind: "gate_reclaim",
85960
+ gateId: gate.gateId,
85961
+ detail: `Gate '${gate.ref ?? gate.gateId}' passed its deadline under on_timeout=hold \u2014 downstream is still held. Reclaim it (optionally with extend_deadline_seconds) to resume, or cancel the branch explicitly. A timeout is never passage: the gate cannot release itself.`
85962
+ });
85963
+ }
85964
+ }
85965
+ for (const ws of workspaces) {
85966
+ if (ws.sagaState === "compensation_required") {
85967
+ actions.push({
85968
+ kind: "workspace_compensation",
85969
+ workspaceRef: ws.workspaceRef,
85970
+ detail: `Workspace '${ws.workspaceRef}' needs manual compensation: ${ws.lastError ?? "compensation refused"}.`
85971
+ });
85972
+ }
85973
+ }
85974
+ return {
85975
+ graphId: graph.graphId,
85976
+ batchId: graph.batchId,
85977
+ status: graph.status,
85978
+ ...graph.missionId ? { missionId: graph.missionId } : {},
85979
+ enqueueSurface: graph.enqueueSurface,
85980
+ schemaVersion: graph.schemaVersion,
85981
+ createdAt: graph.createdAt,
85982
+ ...graph.terminalAt ? { terminalAt: graph.terminalAt } : {},
85983
+ onDependencyFailure: policy.on_dependency_failure,
85984
+ ...policy.policyInvalid ? { policyInvalid: policy.policyInvalid } : {},
85985
+ ...decision ? { orchestrationDecision: decision } : {},
85986
+ counts: {
85987
+ tasks: graph.taskCount,
85988
+ gates: graph.gateCount,
85989
+ workspaces: graph.workspaceCount,
85990
+ edges: graph.dependencyEdgeCount
85991
+ },
85992
+ nodeStates,
85993
+ nodes: nodeViews,
85994
+ edges: edgeViews,
85995
+ gates: gateViews,
85996
+ workspaces: workspaces.map((w) => ({
85997
+ ref: w.workspaceRef,
85998
+ sagaState: w.sagaState,
85999
+ ...w.branchIdentity ? { branchIdentity: w.branchIdentity } : {},
86000
+ ...w.createdNodeId ? { createdNodeId: w.createdNodeId } : {},
86001
+ ...w.createdWorktreePath ? { createdWorktreePath: w.createdWorktreePath } : {},
86002
+ ...w.lastError ? { lastError: w.lastError } : {}
86003
+ })),
86004
+ ...actions.length > 0 ? { nextCoordinatorAction: actions } : {}
86005
+ };
86006
+ });
86007
+ }
86008
+ function describeNodeFeatures(baseSpecJson) {
86009
+ let spec;
86010
+ try {
86011
+ const parsed = JSON.parse(baseSpecJson);
86012
+ spec = parsed && typeof parsed === "object" ? parsed : void 0;
86013
+ } catch {
86014
+ return ["invalid_base_spec"];
86015
+ }
86016
+ if (!spec) return [];
86017
+ const features = [];
86018
+ if (Array.isArray(spec.inputs_from) && spec.inputs_from.length > 0) features.push("inputs_from");
86019
+ if (spec.run_if !== void 0) features.push("run_if");
86020
+ if (typeof spec.workspace_ref === "string" && spec.workspace_ref) features.push("workspace_ref");
86021
+ return features;
86022
+ }
86023
+ function readOrchestrationDecision(policyJson) {
86024
+ if (!policyJson) return void 0;
86025
+ try {
86026
+ const parsed = JSON.parse(policyJson);
86027
+ const decision = parsed?.orchestration_decision;
86028
+ return decision && typeof decision === "object" && !Array.isArray(decision) ? decision : void 0;
86029
+ } catch {
86030
+ return void 0;
86031
+ }
86032
+ }
86033
+ init_mesh_graph_provenance();
84073
86034
  init_mesh_node_identity();
84074
86035
  init_mesh_active_work();
84075
86036
  init_mesh_idle_reminder();
@@ -111685,7 +113646,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
111685
113646
  var path47 = __toESM2(require("path"));
111686
113647
  var fs41 = __toESM2(require("fs"));
111687
113648
  var path46 = __toESM2(require("path"));
111688
- var import_crypto14 = require("crypto");
113649
+ var import_crypto16 = require("crypto");
111689
113650
  var TREE_DIGEST_ALGORITHM = "adhdev-provider-tree-sha256-v1";
111690
113651
  function computeProviderTreeDigest(rootDir, providerType) {
111691
113652
  const relPaths = [];
@@ -111698,7 +113659,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
111698
113659
  );
111699
113660
  }
111700
113661
  relPaths.sort();
111701
- const hash2 = (0, import_crypto14.createHash)("sha256");
113662
+ const hash2 = (0, import_crypto16.createHash)("sha256");
111702
113663
  for (const relPath of relPaths) {
111703
113664
  const absPath = path46.join(rootDir, ...relPath.split("/"));
111704
113665
  const bytes = fs41.readFileSync(absPath);
@@ -115775,11 +117736,11 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
115775
117736
  let node;
115776
117737
  const { migrateProviderRolesToSlots: migrateProviderRolesToSlots2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
115777
117738
  if (meshRecord.inline) {
115778
- const { randomUUID: randomUUID19 } = await import("crypto");
117739
+ const { randomUUID: randomUUID20 } = await import("crypto");
115779
117740
  const clonedPolicy = { ...sourceNode.policy || {} };
115780
117741
  migrateProviderRolesToSlots2(clonedPolicy);
115781
117742
  node = {
115782
- id: `node_${randomUUID19().replace(/-/g, "")}`,
117743
+ id: `node_${randomUUID20().replace(/-/g, "")}`,
115783
117744
  workspace: result.worktreePath,
115784
117745
  repoRoot: result.worktreePath,
115785
117746
  daemonId: sourceNode.daemonId,
@@ -116311,8 +118272,10 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
116311
118272
  const { getMeshQueueStats: getMeshQueueStats2, getQueue: getQueue2, describeTaskDependencyState: describeTaskDependencyState2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
116312
118273
  const status = Array.isArray(args?.status) ? args.status.map((s2) => typeof s2 === "string" ? s2.trim() : "").filter(Boolean) : void 0;
116313
118274
  const rawQueue = getQueue2(meshId, { status });
116314
- const statusById = new Map(getQueue2(meshId).map((task) => [task.id, task.status]));
116315
- const queue = rawQueue.map((task) => Array.isArray(task.dependsOn) && task.dependsOn.length > 0 ? { ...task, ...describeTaskDependencyState2(task, statusById) } : task);
118275
+ const allQueue = getQueue2(meshId);
118276
+ const statusById = new Map(allQueue.map((task) => [task.id, task.status]));
118277
+ const depMetaById = new Map(allQueue.map((task) => [task.id, task]));
118278
+ const queue = rawQueue.map((task) => Array.isArray(task.dependsOn) && task.dependsOn.length > 0 ? { ...task, ...describeTaskDependencyState2(task, statusById, depMetaById) } : task);
116316
118279
  const summary = getMeshQueueStats2(meshId);
116317
118280
  return {
116318
118281
  success: true,
@@ -127391,7 +129354,7 @@ data: ${JSON.stringify(msg.data)}
127391
129354
  });
127392
129355
  }
127393
129356
  };
127394
- var import_crypto15 = require("crypto");
129357
+ var import_crypto17 = require("crypto");
127395
129358
  var import_session_host_core12 = require_dist();
127396
129359
  var BASE_KEY_SEQUENCES = {
127397
129360
  enter: "\r",
@@ -127489,7 +129452,7 @@ data: ${JSON.stringify(msg.data)}
127489
129452
  const sessionId = String(options.sessionId || "").trim();
127490
129453
  if (!sessionId) throw new Error("sessionId is required");
127491
129454
  const mode = options.mode || "read";
127492
- const clientId = options.clientId || `raw-terminal-${process.pid}-${(0, import_crypto15.randomUUID)().slice(0, 8)}`;
129455
+ const clientId = options.clientId || `raw-terminal-${process.pid}-${(0, import_crypto17.randomUUID)().slice(0, 8)}`;
127493
129456
  const client = options.client || new import_session_host_core12.SessionHostClient({ endpoint: options.endpoint });
127494
129457
  await client.connect();
127495
129458
  const attachResponse = await client.request({
@@ -128253,7 +130216,7 @@ data: ${JSON.stringify(msg.data)}
128253
130216
  init_mesh_reconcile_loop();
128254
130217
  var import_fs19 = require("fs");
128255
130218
  var import_path20 = require("path");
128256
- var import_crypto16 = require("crypto");
130219
+ var import_crypto18 = require("crypto");
128257
130220
  init_logger();
128258
130221
  init_mesh_ledger();
128259
130222
  init_mesh_runtime_store();
@@ -128287,7 +130250,7 @@ data: ${JSON.stringify(msg.data)}
128287
130250
  try {
128288
130251
  const fingerprint = buildPendingEventFingerprint(event);
128289
130252
  MeshRuntimeStore.getInstance().insertPendingEvent({
128290
- id: (0, import_crypto16.randomUUID)(),
130253
+ id: (0, import_crypto18.randomUUID)(),
128291
130254
  meshId: event.meshId,
128292
130255
  coordinatorDaemonId: event.targetCoordinatorDaemonId ?? null,
128293
130256
  event: event.event,
@@ -128408,6 +130371,73 @@ data: ${JSON.stringify(msg.data)}
128408
130371
  }
128409
130372
  return newlyFrozen;
128410
130373
  }
130374
+ var import_node_perf_hooks = require("perf_hooks");
130375
+ init_logger();
130376
+ var EVENT_LOOP_MONITOR_INTERVAL_ENV = "ADHDEV_EVENT_LOOP_MONITOR_INTERVAL_MS";
130377
+ var EVENT_LOOP_LAG_WARN_ENV = "ADHDEV_EVENT_LOOP_LAG_WARN_MS";
130378
+ var DEFAULT_EVENT_LOOP_MONITOR_INTERVAL_MS = 1e4;
130379
+ var DEFAULT_EVENT_LOOP_LAG_WARN_MS = 5e3;
130380
+ function parseMs(raw, fallback) {
130381
+ if (raw === void 0 || raw.trim() === "") return fallback;
130382
+ const parsed = Number.parseInt(raw, 10);
130383
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
130384
+ }
130385
+ function resolveEventLoopMonitorIntervalMs(env2 = process.env) {
130386
+ return parseMs(env2[EVENT_LOOP_MONITOR_INTERVAL_ENV], DEFAULT_EVENT_LOOP_MONITOR_INTERVAL_MS);
130387
+ }
130388
+ function resolveEventLoopLagWarnMs(env2 = process.env) {
130389
+ return parseMs(env2[EVENT_LOOP_LAG_WARN_ENV], DEFAULT_EVENT_LOOP_LAG_WARN_MS);
130390
+ }
130391
+ function defaultLogFn(level, message) {
130392
+ if (level === "warn") LOG2.warn("EventLoop", message);
130393
+ else LOG2.debug("EventLoop", message);
130394
+ }
130395
+ function startEventLoopMonitor(opts) {
130396
+ const intervalMs = opts?.intervalMs ?? resolveEventLoopMonitorIntervalMs();
130397
+ const warnMs = opts?.warnMs ?? resolveEventLoopLagWarnMs();
130398
+ const logFn = opts?.logFn ?? defaultLogFn;
130399
+ if (intervalMs <= 0) return { stop: () => {
130400
+ } };
130401
+ let histogram;
130402
+ try {
130403
+ histogram = (0, import_node_perf_hooks.monitorEventLoopDelay)({ resolution: 20 });
130404
+ histogram.enable();
130405
+ } catch {
130406
+ return { stop: () => {
130407
+ } };
130408
+ }
130409
+ let expectedTickAt = null;
130410
+ const timer = setInterval(() => {
130411
+ try {
130412
+ const now = Date.now();
130413
+ const driftMs = expectedTickAt === null ? 0 : Math.max(0, now - expectedTickAt);
130414
+ expectedTickAt = now + intervalMs;
130415
+ const maxMs = histogram.max / 1e6;
130416
+ const p99Ms = histogram.percentile(99) / 1e6;
130417
+ const meanMs = histogram.mean / 1e6;
130418
+ histogram.reset();
130419
+ const worstMs = Math.max(driftMs, maxMs);
130420
+ const message = `event-loop lag: drift=${driftMs.toFixed(0)}ms max=${maxMs.toFixed(0)}ms p99=${p99Ms.toFixed(0)}ms mean=${meanMs.toFixed(1)}ms over ${intervalMs}ms window`;
130421
+ if (worstMs >= warnMs) {
130422
+ logFn("warn", `${message} \u2014 EXCEEDS ${warnMs}ms: the whole daemon process was frozen/unscheduled (machine saturation), not one slow handler. Expect IPC probe timeouts and reconcile-tick gaps in this window.`);
130423
+ } else {
130424
+ logFn("debug", message);
130425
+ }
130426
+ } catch {
130427
+ }
130428
+ }, intervalMs);
130429
+ expectedTickAt = Date.now() + intervalMs;
130430
+ timer.unref?.();
130431
+ return {
130432
+ stop: () => {
130433
+ clearInterval(timer);
130434
+ try {
130435
+ histogram.disable();
130436
+ } catch {
130437
+ }
130438
+ }
130439
+ };
130440
+ }
128411
130441
  init_require_whitelist();
128412
130442
  async function initDaemonComponents2(config2) {
128413
130443
  applyProcessHardening();
@@ -128707,6 +130737,7 @@ ${upgradeFailureNotice.notice}${supersededHint}`);
128707
130737
  refreshQuotaCacheOnBoot(isQuotaProviderEnabled);
128708
130738
  });
128709
130739
  setImmediate(() => void router.resumePendingRefineJobsOnStartup());
130740
+ components.eventLoopMonitor = startEventLoopMonitor();
128710
130741
  setImmediate(() => router.resumeDeferredRestartsOnStartup());
128711
130742
  return components;
128712
130743
  }
@@ -128736,10 +130767,15 @@ ${upgradeFailureNotice.notice}${supersededHint}`);
128736
130767
  meshReconcileLoop,
128737
130768
  quotaRefreshLoop,
128738
130769
  quotaEventRefresh,
128739
- providerStalenessProbe
130770
+ providerStalenessProbe,
130771
+ eventLoopMonitor
128740
130772
  } = components;
128741
130773
  poller.stop();
128742
130774
  cdpInitializer.stop();
130775
+ try {
130776
+ eventLoopMonitor?.stop();
130777
+ } catch {
130778
+ }
128743
130779
  try {
128744
130780
  meshReconcileLoop?.stop();
128745
130781
  } catch {