@adhdev/daemon-core 0.9.82-rc.460 → 0.9.82-rc.462

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
@@ -409,10 +409,10 @@ function readInjected(value) {
409
409
  }
410
410
  function getDaemonBuildInfo() {
411
411
  if (cached) return cached;
412
- const commit = readInjected(true ? "f8ce1329d3bdef9564c4130a1e7f0b607738f3cd" : void 0) ?? "unknown";
413
- const commitShort = readInjected(true ? "f8ce1329" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
414
- const version = readInjected(true ? "0.9.82-rc.460" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
415
- const builtAt = readInjected(true ? "2026-07-04T14:24:11.778Z" : void 0);
412
+ const commit = readInjected(true ? "1481e2078cc0eceea283a2370cccb4cd9102e4ff" : void 0) ?? "unknown";
413
+ const commitShort = readInjected(true ? "1481e207" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
414
+ const version = readInjected(true ? "0.9.82-rc.462" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
415
+ const builtAt = readInjected(true ? "2026-07-04T16:50:21.874Z" : void 0);
416
416
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
417
417
  return cached;
418
418
  }
@@ -3261,6 +3261,12 @@ function updateNode(meshId, nodeId, opts) {
3261
3261
  if (opts.reportedPlatform && opts.reportedPlatform.trim()) node.reportedPlatform = opts.reportedPlatform.trim();
3262
3262
  if (opts.reportedArch && opts.reportedArch.trim()) node.reportedArch = opts.reportedArch.trim();
3263
3263
  if (opts.reportedMachineNickname && opts.reportedMachineNickname.trim()) node.machineNickname = opts.reportedMachineNickname.trim();
3264
+ if (opts.reportedProviderVersions && Object.keys(opts.reportedProviderVersions).length > 0) {
3265
+ node.reportedProviderVersions = { ...opts.reportedProviderVersions };
3266
+ }
3267
+ if (opts.reportedDaemonBuildVersion && opts.reportedDaemonBuildVersion.trim()) {
3268
+ node.reportedDaemonBuildVersion = opts.reportedDaemonBuildVersion.trim();
3269
+ }
3264
3270
  if (opts.policy) node.policy = { ...node.policy, ...opts.policy };
3265
3271
  if (opts.worktreeBootstrap) node.worktreeBootstrap = opts.worktreeBootstrap;
3266
3272
  if (Object.prototype.hasOwnProperty.call(opts, "systemPrompt")) {
@@ -3604,9 +3610,16 @@ function buildNodeStatusSection(nodes) {
3604
3610
  const healthIcon = n.health === "online" ? "\u{1F7E2}" : n.health === "dirty" ? "\u{1F7E1}" : n.health === "offline" ? "\u26AB" : "\u{1F534}";
3605
3611
  const sessions = n.activeSessions.length > 0 ? `sessions: ${n.activeSessions.join(", ")}` : "no active sessions";
3606
3612
  const branch = n.git?.branch ? `branch: \`${n.git.branch}\`` : "";
3613
+ const providerVersions = n.providerVersions && typeof n.providerVersions === "object" ? n.providerVersions : void 0;
3614
+ const providersRendered = n.providers?.length ? n.providers.map((p) => {
3615
+ const version = providerVersions?.[p];
3616
+ return version ? `${p}@${version}` : p;
3617
+ }).join(", ") : "";
3618
+ const buildVersion = typeof n.daemonBuildVersion === "string" && n.daemonBuildVersion ? `build: ${n.daemonBuildVersion}` : "";
3607
3619
  const context = [
3608
3620
  n.daemonId ? `daemon: \`${n.daemonId}\`` : "",
3609
- n.providers?.length ? `providers: ${n.providers.join(", ")}` : ""
3621
+ providersRendered ? `providers: ${providersRendered}` : "",
3622
+ buildVersion
3610
3623
  ].filter(Boolean).join(" | ");
3611
3624
  lines.push(`- ${healthIcon} **${n.machineLabel}** (nodeId: \`${n.nodeId}\`)`);
3612
3625
  lines.push(` workspace: \`${n.workspace}\`${context ? ` | ${context}` : ""} | ${branch} | ${sessions}`);
@@ -4174,6 +4187,98 @@ var init_load_better_sqlite3 = __esm({
4174
4187
  });
4175
4188
 
4176
4189
  // src/mesh/contracts.ts
4190
+ function isSupportedMeshProtocolVersion(value) {
4191
+ return typeof value === "string" && SUPPORTED_MESH_PROTOCOL_VERSIONS.includes(value);
4192
+ }
4193
+ function coordinatorIdentityEquals(a, b) {
4194
+ return daemonIdsEquivalent(a.daemonId, b.daemonId) && a.coordinatorRunId === b.coordinatorRunId && (a.sessionId ?? "") === (b.sessionId ?? "");
4195
+ }
4196
+ function coordinatorIdentityKey(identity) {
4197
+ const daemonCore = machineCoreFromDaemonId(identity.daemonId) ?? identity.daemonId;
4198
+ return `${daemonCore}|${identity.coordinatorRunId}|${identity.sessionId ?? ""}`;
4199
+ }
4200
+ function isMeshEventScope(value) {
4201
+ return typeof value === "string" && MESH_EVENT_SCOPES.includes(value);
4202
+ }
4203
+ function isNonEmptyString(value) {
4204
+ return typeof value === "string" && value.length > 0;
4205
+ }
4206
+ function assertCoordinatorIdentity(raw, path44) {
4207
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
4208
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, path44, "must be an object");
4209
+ }
4210
+ const obj = raw;
4211
+ if (!isNonEmptyString(obj.daemonId)) {
4212
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.daemonId`, "must be a non-empty string");
4213
+ }
4214
+ if (!isNonEmptyString(obj.coordinatorRunId)) {
4215
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.coordinatorRunId`, "must be a non-empty string");
4216
+ }
4217
+ const sessionId = obj.sessionId;
4218
+ if (sessionId !== void 0 && !isNonEmptyString(sessionId)) {
4219
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.sessionId`, "must be a non-empty string when provided");
4220
+ }
4221
+ return sessionId !== void 0 ? { daemonId: obj.daemonId, coordinatorRunId: obj.coordinatorRunId, sessionId } : { daemonId: obj.daemonId, coordinatorRunId: obj.coordinatorRunId };
4222
+ }
4223
+ function assertPendingMeshCoordinatorEventV2(raw, path44 = "$") {
4224
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
4225
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, path44, "must be an object");
4226
+ }
4227
+ const obj = raw;
4228
+ if (!isSupportedMeshProtocolVersion(obj.protocolVersion)) {
4229
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.protocolVersion`, `must be one of ${SUPPORTED_MESH_PROTOCOL_VERSIONS.join(", ")}`);
4230
+ }
4231
+ if (!isNonEmptyString(obj.eventId)) {
4232
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.eventId`, "must be a non-empty string");
4233
+ }
4234
+ if (!isMeshEventScope(obj.scope)) {
4235
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.scope`, `must be one of ${MESH_EVENT_SCOPES.join(", ")}`);
4236
+ }
4237
+ if (!isNonEmptyString(obj.event)) {
4238
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.event`, "must be a non-empty string");
4239
+ }
4240
+ if (!isNonEmptyString(obj.meshId)) {
4241
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.meshId`, "must be a non-empty string");
4242
+ }
4243
+ const dispatchedBy = assertCoordinatorIdentity(obj.dispatchedBy, `${path44}.dispatchedBy`);
4244
+ if (obj.scope === "unicast") {
4245
+ if (!obj.intendedFor) {
4246
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.intendedFor`, "unicast scope requires intendedFor");
4247
+ }
4248
+ } else if (obj.intendedFor !== void 0) {
4249
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.intendedFor`, "only unicast scope may set intendedFor");
4250
+ }
4251
+ const intendedFor = obj.intendedFor ? assertCoordinatorIdentity(obj.intendedFor, `${path44}.intendedFor`) : void 0;
4252
+ const metadata = obj.metadataEvent && typeof obj.metadataEvent === "object" && !Array.isArray(obj.metadataEvent) ? obj.metadataEvent : null;
4253
+ if (!metadata) {
4254
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.metadataEvent`, "must be an object");
4255
+ }
4256
+ const queuedAt = typeof obj.queuedAt === "number" && Number.isFinite(obj.queuedAt) ? obj.queuedAt : null;
4257
+ if (queuedAt === null) {
4258
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.queuedAt`, "must be a finite number");
4259
+ }
4260
+ return {
4261
+ event: obj.event,
4262
+ meshId: obj.meshId,
4263
+ nodeLabel: isNonEmptyString(obj.nodeLabel) ? obj.nodeLabel : "",
4264
+ nodeId: typeof obj.nodeId === "string" ? obj.nodeId : void 0,
4265
+ workspace: typeof obj.workspace === "string" ? obj.workspace : void 0,
4266
+ metadataEvent: metadata,
4267
+ coordinatorMessage: typeof obj.coordinatorMessage === "string" ? obj.coordinatorMessage : void 0,
4268
+ queuedAt,
4269
+ protocolVersion: obj.protocolVersion,
4270
+ eventId: obj.eventId,
4271
+ scope: obj.scope,
4272
+ dispatchedBy,
4273
+ ...intendedFor ? { intendedFor } : {}
4274
+ };
4275
+ }
4276
+ function shouldDeliverPendingEventToCoordinator(event, drainer) {
4277
+ if (event.scope === "system") return false;
4278
+ if (event.scope === "broadcast") return true;
4279
+ if (!event.intendedFor) return false;
4280
+ return coordinatorIdentityEquals(event.intendedFor, drainer);
4281
+ }
4177
4282
  function defaultScopeForEvent(eventName) {
4178
4283
  if (SYSTEM_EVENTS.has(eventName)) return "system";
4179
4284
  if (TERMINAL_TASK_EVENTS.has(eventName)) return "unicast";
@@ -4202,12 +4307,28 @@ function buildPendingEventEmitStamp(opts) {
4202
4307
  ...intendedFor ? { intendedFor } : {}
4203
4308
  };
4204
4309
  }
4205
- var MESH_PROTOCOL_VERSION_V2, TERMINAL_TASK_EVENTS, SYSTEM_EVENTS;
4310
+ var MESH_PROTOCOL_VERSION_V1, MESH_PROTOCOL_VERSION_V2, SUPPORTED_MESH_PROTOCOL_VERSIONS, MESH_EVENT_SCOPES, MeshContractViolationError, TERMINAL_TASK_EVENTS, SYSTEM_EVENTS;
4206
4311
  var init_contracts = __esm({
4207
4312
  "src/mesh/contracts.ts"() {
4208
4313
  "use strict";
4209
4314
  init_dist();
4315
+ MESH_PROTOCOL_VERSION_V1 = "1.0";
4210
4316
  MESH_PROTOCOL_VERSION_V2 = "2.0";
4317
+ SUPPORTED_MESH_PROTOCOL_VERSIONS = [
4318
+ MESH_PROTOCOL_VERSION_V1,
4319
+ MESH_PROTOCOL_VERSION_V2
4320
+ ];
4321
+ MESH_EVENT_SCOPES = ["unicast", "broadcast", "system"];
4322
+ MeshContractViolationError = class extends Error {
4323
+ violationPath;
4324
+ protocolVersion;
4325
+ constructor(protocolVersion, violationPath, detail) {
4326
+ super(`mesh contract ${protocolVersion} violation at ${violationPath}: ${detail}`);
4327
+ this.name = "MeshContractViolationError";
4328
+ this.violationPath = violationPath;
4329
+ this.protocolVersion = protocolVersion;
4330
+ }
4331
+ };
4211
4332
  TERMINAL_TASK_EVENTS = /* @__PURE__ */ new Set([
4212
4333
  "agent:generating_completed",
4213
4334
  "agent:stopped",
@@ -7536,6 +7657,34 @@ var init_mesh_runtime_store = __esm({
7536
7657
  ).get(meshId, fingerprint);
7537
7658
  return row !== void 0;
7538
7659
  }
7660
+ /**
7661
+ * B3a — v2 eventId idempotency. Returns true when a row with this event_id has
7662
+ * ALREADY been drained (drained = 1) for the mesh. Drained rows are retained
7663
+ * (soft-marked, not deleted until mesh deletion), so this is a durable, restart-
7664
+ * surviving dedup: a v2 event whose eventId was already consumed is skipped on
7665
+ * re-delivery even when its content fingerprint differs. Scoped by mesh_id +
7666
+ * the partial event_id index (idx_mesh_pending_events_event_id).
7667
+ */
7668
+ hasDrainedEventId(meshId, eventId) {
7669
+ if (!eventId) return false;
7670
+ const row = this.db.prepare(
7671
+ "SELECT 1 FROM mesh_pending_events WHERE mesh_id = ? AND event_id = ? AND drained = 1 LIMIT 1"
7672
+ ).get(meshId, eventId);
7673
+ return row !== void 0;
7674
+ }
7675
+ /**
7676
+ * B3a — snapshot of the v2 event_ids ALREADY drained (drained = 1) for the mesh.
7677
+ * Taken BEFORE a drain call marks the current batch drained=1, so the resulting
7678
+ * set names only PRIOR drains — the re-delivery dedup baseline. (Reading it after
7679
+ * the drain would self-match the batch's own freshly-drained rows.) Non-v2 rows
7680
+ * have a NULL event_id and are excluded by the index/WHERE.
7681
+ */
7682
+ drainedEventIdsForMesh(meshId) {
7683
+ const rows = this.db.prepare(
7684
+ "SELECT DISTINCT event_id FROM mesh_pending_events WHERE mesh_id = ? AND drained = 1 AND event_id IS NOT NULL"
7685
+ ).all(meshId);
7686
+ return new Set(rows.map((r) => r.event_id));
7687
+ }
7539
7688
  // ── M3: Mission Records ─────────────────────────────────────────────────
7540
7689
  upsertMission(mission) {
7541
7690
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -11330,6 +11479,145 @@ var init_mesh_events_utils = __esm({
11330
11479
  function normalizeCoordinatorDaemonIds(coordinatorDaemonId) {
11331
11480
  return expandDaemonIdForms(coordinatorDaemonId);
11332
11481
  }
11482
+ function isMeshProtocolV2EnforceEnabled() {
11483
+ const raw = readNonEmptyString2(process.env.MESH_PROTOCOL_V2_ENFORCE);
11484
+ if (!raw) return false;
11485
+ const v = raw.trim().toLowerCase();
11486
+ return v === "1" || v === "true" || v === "on" || v === "yes";
11487
+ }
11488
+ function ledgerRecordQuarantinedEvent(event, reason) {
11489
+ try {
11490
+ const finalSummary = readMeshCompletionSummary(event.metadataEvent || {});
11491
+ appendLedgerEntry(event.meshId, {
11492
+ kind: "event_held",
11493
+ ...event.nodeId ? { nodeId: event.nodeId } : {},
11494
+ payload: {
11495
+ event: event.event,
11496
+ reason,
11497
+ recoverable: true,
11498
+ nodeLabel: event.nodeLabel,
11499
+ ...event.workspace ? { workspace: event.workspace } : {},
11500
+ targetCoordinatorDaemonId: event.targetCoordinatorDaemonId ?? null,
11501
+ ...readNonEmptyString2(event.eventId) ? { eventId: event.eventId } : {},
11502
+ queuedAt: event.queuedAt,
11503
+ ...finalSummary ? { finalSummary } : {}
11504
+ }
11505
+ });
11506
+ } catch (e) {
11507
+ LOG.warn("MeshEventsV2", `Failed to ledger-record v2-quarantined ${event.event} for mesh ${event.meshId}: ${e?.message || e}`);
11508
+ }
11509
+ }
11510
+ function getMeshV2DrainCounters() {
11511
+ return { ...meshV2DrainCounters };
11512
+ }
11513
+ function warnV2Once(key2, message) {
11514
+ if (warnedV2Violations.has(key2)) return;
11515
+ warnedV2Violations.add(key2);
11516
+ if (warnedV2Violations.size > 2e3) {
11517
+ const first = warnedV2Violations.values().next().value;
11518
+ if (first !== void 0) warnedV2Violations.delete(first);
11519
+ }
11520
+ LOG.warn("MeshEventsV2", message);
11521
+ }
11522
+ function resolveDrainerIdentity(daemonIds, explicit) {
11523
+ if (explicit) return explicit;
11524
+ return coordinatorIdentityFromEmitFields({ daemonId: daemonIds[0] });
11525
+ }
11526
+ function isV2Event(event) {
11527
+ return event.protocolVersion === MESH_PROTOCOL_VERSION_V2;
11528
+ }
11529
+ function runIdIsDaemonFormFallback(identity) {
11530
+ return daemonIdsEquivalent(identity.coordinatorRunId, identity.daemonId);
11531
+ }
11532
+ function identityDeliversTo(intendedFor, drainer) {
11533
+ if (runIdIsDaemonFormFallback(intendedFor) && runIdIsDaemonFormFallback(drainer)) {
11534
+ if (!daemonIdsEquivalent(intendedFor.daemonId, drainer.daemonId)) return false;
11535
+ if (intendedFor.sessionId && drainer.sessionId) {
11536
+ return intendedFor.sessionId === drainer.sessionId;
11537
+ }
11538
+ return true;
11539
+ }
11540
+ return coordinatorIdentityEquals(intendedFor, drainer);
11541
+ }
11542
+ function routeV2EventsForDrainer(events, drainer, ctx) {
11543
+ if (!drainer) return events;
11544
+ const enforce = isMeshProtocolV2EnforceEnabled();
11545
+ const bump = (k) => {
11546
+ if (ctx.countMetrics) meshV2DrainCounters[k]++;
11547
+ };
11548
+ const kept = [];
11549
+ for (const event of events) {
11550
+ if (!isV2Event(event)) {
11551
+ if (enforce) {
11552
+ bump("v1UnversionedQuarantined");
11553
+ if (ctx.countMetrics) ledgerRecordQuarantinedEvent(event, "v2_enforce_unversioned_quarantined");
11554
+ warnV2Once(
11555
+ `${event.meshId}::${event.eventId ?? event.event}::v1-quarantined`,
11556
+ `v2 ENFORCE: unversioned ${event.event} on mesh ${event.meshId} QUARANTINED (no v2 envelope \u2014 held back, not delivered; ledger-recorded recoverable). A producer path still emits v1.`
11557
+ );
11558
+ continue;
11559
+ }
11560
+ bump("v1BroadcastAccepted");
11561
+ kept.push(event);
11562
+ continue;
11563
+ }
11564
+ let validated;
11565
+ try {
11566
+ validated = assertPendingMeshCoordinatorEventV2(event);
11567
+ } catch (e) {
11568
+ if (enforce) {
11569
+ bump("v2ValidationFailedQuarantined");
11570
+ if (ctx.countMetrics) ledgerRecordQuarantinedEvent(event, "v2_enforce_validation_failed_quarantined");
11571
+ warnV2Once(
11572
+ `${event.meshId}::${event.eventId ?? event.event}::invalid-quarantined`,
11573
+ `v2 ENFORCE: envelope validation failed for ${event.event} on mesh ${event.meshId} \u2014 QUARANTINED (held back, not delivered; ledger-recorded recoverable): ${e?.message || e}`
11574
+ );
11575
+ continue;
11576
+ }
11577
+ bump("v2ValidationFailedAccepted");
11578
+ warnV2Once(
11579
+ `${event.meshId}::${event.eventId ?? event.event}::invalid`,
11580
+ `v2 envelope validation failed for ${event.event} on mesh ${event.meshId} \u2014 PASSED THROUGH (accept mode): ${e?.message || e}`
11581
+ );
11582
+ kept.push(event);
11583
+ continue;
11584
+ }
11585
+ const eventId = validated.eventId;
11586
+ if (ctx.batchSeen.has(eventId) || ctx.alreadyDrained(eventId)) {
11587
+ bump("v2DedupSkipped");
11588
+ continue;
11589
+ }
11590
+ if (validated.scope !== "unicast") {
11591
+ if (shouldDeliverPendingEventToCoordinator(validated, drainer)) {
11592
+ ctx.batchSeen.add(eventId);
11593
+ bump("v2Delivered");
11594
+ kept.push(event);
11595
+ } else {
11596
+ bump("v2RoutedAway");
11597
+ }
11598
+ continue;
11599
+ }
11600
+ if (validated.intendedFor && identityDeliversTo(validated.intendedFor, drainer)) {
11601
+ ctx.batchSeen.add(eventId);
11602
+ bump("v2Delivered");
11603
+ kept.push(event);
11604
+ continue;
11605
+ }
11606
+ const realRunIdMismatch = !runIdIsDaemonFormFallback(validated.intendedFor) || !runIdIsDaemonFormFallback(drainer);
11607
+ if (validated.intendedFor && realRunIdMismatch && daemonIdsEquivalent(validated.intendedFor.daemonId, drainer.daemonId)) {
11608
+ ctx.batchSeen.add(eventId);
11609
+ bump("v2ReattributedToDrainer");
11610
+ warnV2Once(
11611
+ `${event.meshId}::${eventId}::reattributed`,
11612
+ `v2 unicast ${event.event} on mesh ${event.meshId} re-attributed to current coordinator ${coordinatorIdentityKey(drainer)} (originating coordinatorRunId no longer live)`
11613
+ );
11614
+ kept.push(event);
11615
+ continue;
11616
+ }
11617
+ bump("v2RoutedAway");
11618
+ }
11619
+ return kept;
11620
+ }
11333
11621
  function readRefineJobId2(event) {
11334
11622
  const metadata = readRecord5(event.metadataEvent) || event;
11335
11623
  const result = readRecord5(metadata.result);
@@ -11548,6 +11836,36 @@ function stampPendingEventV2(event, hint) {
11548
11836
  ...stamp.intendedFor ? { intendedFor: stamp.intendedFor } : {}
11549
11837
  };
11550
11838
  }
11839
+ function readCoordinatorIdentityFromWire(raw) {
11840
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
11841
+ const obj = raw;
11842
+ const daemonId = readNonEmptyString2(obj.daemonId);
11843
+ const coordinatorRunId = readNonEmptyString2(obj.coordinatorRunId);
11844
+ if (!daemonId || !coordinatorRunId) return void 0;
11845
+ const sessionId = readNonEmptyString2(obj.sessionId);
11846
+ return { daemonId, coordinatorRunId, ...sessionId ? { sessionId } : {} };
11847
+ }
11848
+ function serializeV2EnvelopeToWire(event) {
11849
+ const out = {};
11850
+ if (event.protocolVersion) out.protocolVersion = event.protocolVersion;
11851
+ if (readNonEmptyString2(event.eventId)) out.eventId = event.eventId;
11852
+ if (event.scope) out.scope = event.scope;
11853
+ if (event.dispatchedBy) out.dispatchedBy = event.dispatchedBy;
11854
+ if (event.intendedFor) out.intendedFor = event.intendedFor;
11855
+ return out;
11856
+ }
11857
+ function readV2EnvelopeFromWire(payload) {
11858
+ const out = {};
11859
+ if (payload.protocolVersion === MESH_PROTOCOL_VERSION_V2) out.protocolVersion = MESH_PROTOCOL_VERSION_V2;
11860
+ const eventId = readNonEmptyString2(payload.eventId);
11861
+ if (eventId) out.eventId = eventId;
11862
+ if (isMeshEventScope(payload.scope)) out.scope = payload.scope;
11863
+ const dispatchedBy = readCoordinatorIdentityFromWire(payload.dispatchedBy);
11864
+ if (dispatchedBy) out.dispatchedBy = dispatchedBy;
11865
+ const intendedFor = readCoordinatorIdentityFromWire(payload.intendedFor);
11866
+ if (intendedFor) out.intendedFor = intendedFor;
11867
+ return out;
11868
+ }
11551
11869
  function queuePendingMeshCoordinatorEvent(rawEvent, hint) {
11552
11870
  const event = stampPendingEventV2(rawEvent, hint);
11553
11871
  try {
@@ -11670,6 +11988,12 @@ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId, opts) {
11670
11988
  if (!meshId) return [];
11671
11989
  const daemonIds = normalizeCoordinatorDaemonIds(coordinatorDaemonId);
11672
11990
  const primaryDaemonId = daemonIds[0];
11991
+ const drainer = resolveDrainerIdentity(daemonIds, opts?.drainerIdentity);
11992
+ let priorDrainedEventIds = /* @__PURE__ */ new Set();
11993
+ try {
11994
+ priorDrainedEventIds = MeshRuntimeStore.getInstance().drainedEventIdsForMesh(meshId);
11995
+ } catch {
11996
+ }
11673
11997
  const onlyEvents = opts?.onlyEvents;
11674
11998
  const matchesFilter = (eventName) => !onlyEvents || onlyEvents.has(eventName);
11675
11999
  const merged = [];
@@ -11716,7 +12040,12 @@ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId, opts) {
11716
12040
  for (const event of filtered) pushUnique(event);
11717
12041
  }
11718
12042
  if (merged.length === 0) return [];
11719
- return reconcilePendingMeshCoordinatorEvents(meshId, merged);
12043
+ const routed = routeV2EventsForDrainer(merged, drainer, {
12044
+ alreadyDrained: (eventId) => priorDrainedEventIds.has(eventId),
12045
+ batchSeen: /* @__PURE__ */ new Set(),
12046
+ countMetrics: true
12047
+ });
12048
+ return reconcilePendingMeshCoordinatorEvents(meshId, routed);
11720
12049
  }
11721
12050
  function retractPendingDispatchBlockedEvent(meshId, taskId, coordinatorDaemonId) {
11722
12051
  if (!meshId || !taskId) return 0;
@@ -11747,9 +12076,15 @@ function retractPendingDispatchBlockedEvent(meshId, taskId, coordinatorDaemonId)
11747
12076
  }
11748
12077
  return removed;
11749
12078
  }
11750
- function getPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
12079
+ function getPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId, opts) {
11751
12080
  if (!meshId) return [];
11752
12081
  const daemonIds = normalizeCoordinatorDaemonIds(coordinatorDaemonId);
12082
+ const drainer = resolveDrainerIdentity(daemonIds, opts?.drainerIdentity);
12083
+ let priorDrainedEventIds = /* @__PURE__ */ new Set();
12084
+ try {
12085
+ priorDrainedEventIds = MeshRuntimeStore.getInstance().drainedEventIdsForMesh(meshId);
12086
+ } catch {
12087
+ }
11753
12088
  const merged = [];
11754
12089
  const seenFingerprints = /* @__PURE__ */ new Set();
11755
12090
  const pushUnique = (event) => {
@@ -11773,7 +12108,12 @@ function getPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
11773
12108
  for (const event of readPendingMeshCoordinatorEventsFromDisk(meshId, daemonIds)) {
11774
12109
  pushUnique(event);
11775
12110
  }
11776
- return reconcilePendingMeshCoordinatorEvents(meshId, merged);
12111
+ const routed = routeV2EventsForDrainer(merged, drainer, {
12112
+ alreadyDrained: (eventId) => priorDrainedEventIds.has(eventId),
12113
+ batchSeen: /* @__PURE__ */ new Set(),
12114
+ countMetrics: false
12115
+ });
12116
+ return reconcilePendingMeshCoordinatorEvents(meshId, routed);
11777
12117
  }
11778
12118
  function clearPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
11779
12119
  if (!meshId) return;
@@ -11789,7 +12129,7 @@ function clearPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
11789
12129
  }
11790
12130
  }
11791
12131
  }
11792
- var import_fs11, import_path10, import_crypto8, REFINE_TERMINAL_EVENTS, TERMINAL_COMPLETION_EVENTS, MAX_PENDING_EVENTS_BYTES, MAX_PENDING_EVENTS_KEEP;
12132
+ var import_fs11, import_path10, import_crypto8, REFINE_TERMINAL_EVENTS, meshV2DrainCounters, warnedV2Violations, TERMINAL_COMPLETION_EVENTS, MAX_PENDING_EVENTS_BYTES, MAX_PENDING_EVENTS_KEEP;
11793
12133
  var init_mesh_events_pending = __esm({
11794
12134
  "src/mesh/mesh-events-pending.ts"() {
11795
12135
  "use strict";
@@ -11803,6 +12143,32 @@ var init_mesh_events_pending = __esm({
11803
12143
  init_dist();
11804
12144
  init_contracts();
11805
12145
  REFINE_TERMINAL_EVENTS = /* @__PURE__ */ new Set(["refine:completed", "refine:failed"]);
12146
+ meshV2DrainCounters = {
12147
+ /** v2 events that passed validation and unicast/broadcast routing → delivered. */
12148
+ v2Delivered: 0,
12149
+ /** v2 unicast events skipped because intendedFor addressed another coordinator. */
12150
+ v2RoutedAway: 0,
12151
+ /** v2 events skipped because their eventId was already drained (idempotency). */
12152
+ v2DedupSkipped: 0,
12153
+ /** v2 events that failed assertPendingMeshCoordinatorEventV2 but were PASSED
12154
+ * THROUGH (accept mode). Non-zero here is the rollout signal that a producer
12155
+ * emits a malformed envelope. */
12156
+ v2ValidationFailedAccepted: 0,
12157
+ /** unicast events re-attributed to the drainer via daemon-core match (a
12158
+ * coordinatorRunId change orphaned them). */
12159
+ v2ReattributedToDrainer: 0,
12160
+ /** v1 (unversioned) events passed through as broadcast (rollout baseline). */
12161
+ v1BroadcastAccepted: 0,
12162
+ /** T6 enforce: v2 events that FAILED validation and were QUARANTINED (held back
12163
+ * from delivery, not dropped). Non-zero here means a producer is still emitting a
12164
+ * malformed envelope after enforce was turned on. */
12165
+ v2ValidationFailedQuarantined: 0,
12166
+ /** T6 enforce: v1 (unversioned) events QUARANTINED because no v2 envelope could be
12167
+ * derived at emit time. Non-zero here means a producer path still emits v1 after
12168
+ * enforce — it should reach 0 once every node is on a v2-stamping build. */
12169
+ v1UnversionedQuarantined: 0
12170
+ };
12171
+ warnedV2Violations = /* @__PURE__ */ new Set();
11806
12172
  TERMINAL_COMPLETION_EVENTS = /* @__PURE__ */ new Set(["agent:generating_completed", "agent:stopped"]);
11807
12173
  MAX_PENDING_EVENTS_BYTES = 100 * 1024;
11808
12174
  MAX_PENDING_EVENTS_KEEP = 50;
@@ -12853,7 +13219,38 @@ async function detectCLI(cliId, providerLoader, options) {
12853
13219
  const all = await detectCLIs(providerLoader, options);
12854
13220
  return all.find((c) => c.id === resolvedId && c.installed) || null;
12855
13221
  }
12856
- var import_child_process2, os6, path12, import_fs12;
13222
+ function buildProviderVersions(detected) {
13223
+ const out = {};
13224
+ for (const cli of detected) {
13225
+ if (!cli.installed) continue;
13226
+ const version = typeof cli.version === "string" ? cli.version.trim() : "";
13227
+ if (!version) continue;
13228
+ out[cli.id] = version;
13229
+ }
13230
+ return out;
13231
+ }
13232
+ function refreshProviderVersionsSnapshot(providerLoader) {
13233
+ if (providerVersionsRefreshInFlight) return providerVersionsRefreshInFlight;
13234
+ providerVersionsRefreshInFlight = (async () => {
13235
+ try {
13236
+ const detected = await detectCLIs(providerLoader, { includeVersion: true });
13237
+ cachedProviderVersions = buildProviderVersions(detected);
13238
+ cachedProviderVersionsAt = Date.now();
13239
+ } catch {
13240
+ } finally {
13241
+ providerVersionsRefreshInFlight = null;
13242
+ }
13243
+ })();
13244
+ return providerVersionsRefreshInFlight;
13245
+ }
13246
+ function getCachedProviderVersions(providerLoader) {
13247
+ const stale = Date.now() - cachedProviderVersionsAt > PROVIDER_VERSIONS_TTL_MS;
13248
+ if (stale) {
13249
+ void refreshProviderVersionsSnapshot(providerLoader);
13250
+ }
13251
+ return { ...cachedProviderVersions };
13252
+ }
13253
+ var import_child_process2, os6, path12, import_fs12, PROVIDER_VERSIONS_TTL_MS, cachedProviderVersions, cachedProviderVersionsAt, providerVersionsRefreshInFlight;
12857
13254
  var init_cli_detector = __esm({
12858
13255
  "src/detection/cli-detector.ts"() {
12859
13256
  "use strict";
@@ -12862,6 +13259,10 @@ var init_cli_detector = __esm({
12862
13259
  path12 = __toESM(require("path"));
12863
13260
  import_fs12 = require("fs");
12864
13261
  init_provider_cli_shared();
13262
+ PROVIDER_VERSIONS_TTL_MS = 5 * 60 * 1e3;
13263
+ cachedProviderVersions = {};
13264
+ cachedProviderVersionsAt = 0;
13265
+ providerVersionsRefreshInFlight = null;
12865
13266
  }
12866
13267
  });
12867
13268
 
@@ -17550,7 +17951,13 @@ function injectMeshSystemMessage(components, args) {
17550
17951
  ...workerCoordinatorDaemonId ? { targetCoordinatorDaemonId: workerCoordinatorDaemonId } : {},
17551
17952
  // Top-level session anchor for the local PHASE 2 strict-match on the coordinator
17552
17953
  // daemon. Absent → daemon-level broadcast (legacy / single-coordinator path).
17553
- ...workerCoordinatorSessionId ? { targetCoordinatorSessionId: workerCoordinatorSessionId } : {}
17954
+ ...workerCoordinatorSessionId ? { targetCoordinatorSessionId: workerCoordinatorSessionId } : {},
17955
+ // T4 (B3b): restore the v2 envelope from the remote relay so the re-queue keeps the
17956
+ // ORIGINAL eventId. Spread LAST so its authoritative eventId/scope/identity win over
17957
+ // any default. queuePendingMeshCoordinatorEvent → stampPendingEventV2 then no-ops
17958
+ // (already-stamped short-circuit) instead of minting a fresh eventId. Empty object
17959
+ // for a v1 relay → unchanged v1 emit-stamp path (version-skew safe).
17960
+ ...args.v2Envelope ?? {}
17554
17961
  };
17555
17962
  if (queuePendingMeshCoordinatorEvent(pendingEvent)) {
17556
17963
  LOG.info("MeshEvents", `Queued ${args.event} for coordinator (mesh ${args.meshId}${workerCoordinatorDaemonId ? `, coordinator daemon ${workerCoordinatorDaemonId}` : ""}${workerCoordinatorSessionId ? `, coordinator session ${workerCoordinatorSessionId}` : ""})`);
@@ -17663,7 +18070,12 @@ function handleMeshForwardEvent(components, payload) {
17663
18070
  nodeId,
17664
18071
  nodeLabel,
17665
18072
  event: eventName,
17666
- metadataEvent: buildRelayMetadataEvent(payload)
18073
+ metadataEvent: buildRelayMetadataEvent(payload),
18074
+ // T4 (B3b): restore the v2 envelope carried at the top level of the relayed flat
18075
+ // payload (buildForwardPayloadFromPending → serializeV2EnvelopeToWire) so the
18076
+ // re-queue preserves the original eventId (idempotency) and unicast routing rather
18077
+ // than re-stamping a fresh v1/broadcast event. Empty for a v1 relay (version-skew safe).
18078
+ v2Envelope: readV2EnvelopeFromWire(payload)
17667
18079
  });
17668
18080
  }
17669
18081
  function enqueueCoordinatorForwardPush(coordinatorDaemonId, run) {
@@ -17958,6 +18370,21 @@ function resolveAckedDeathDeadlineMs() {
17958
18370
  function resolveAckedTranscriptFastTrackGraceMs() {
17959
18371
  return resolveTunedReconcileMs("MESH_INFLIGHT_ACKED_TRANSCRIPT_FASTTRACK_GRACE_MS", 4e4, 0, 5 * 6e4);
17960
18372
  }
18373
+ function getMeshV2BackstopCounters() {
18374
+ return { ...meshV2BackstopCounters };
18375
+ }
18376
+ function meshProtocolV2EnforceOn() {
18377
+ const raw = process.env.MESH_PROTOCOL_V2_ENFORCE;
18378
+ if (typeof raw !== "string") return false;
18379
+ const v = raw.trim().toLowerCase();
18380
+ return v === "1" || v === "true" || v === "on" || v === "yes";
18381
+ }
18382
+ function recordBackstopFire(kind, detail) {
18383
+ meshV2BackstopCounters[kind]++;
18384
+ if (meshProtocolV2EnforceOn()) {
18385
+ LOG.warn("MeshReconcileV2", `v2 ENFORCE last-resort backstop fired (${kind}): ${detail}. Under a healthy v2 completion contract this should be 0 \u2014 a worker's real terminal emit was lost/late.`);
18386
+ }
18387
+ }
17961
18388
  function inFlightSynthKey(meshId, taskId) {
17962
18389
  return `${meshId}::${taskId}`;
17963
18390
  }
@@ -18872,6 +19299,7 @@ async function reconcileUnterminatedDirectDispatches(components, mesh, selfIds,
18872
19299
  };
18873
19300
  const synthKey = inFlightSynthKey(mesh.id, taskId);
18874
19301
  const isAcked = dispatch.status === "acked";
19302
+ let backstopKind;
18875
19303
  let payload = null;
18876
19304
  let readFailed = false;
18877
19305
  try {
@@ -18936,6 +19364,7 @@ async function reconcileUnterminatedDirectDispatches(components, mesh, selfIds,
18936
19364
  const idleHeldMs = nowMs - idleSinceMs;
18937
19365
  if (idleHeldMs >= fastTrackGraceMs) {
18938
19366
  fastTrackReady = true;
19367
+ backstopKind = "ackedHoldFastTrackFired";
18939
19368
  LOG.info("MeshReconcile", `Acked-hold transcript fast-track: task ${taskId} on node ${nodeId} (mesh ${mesh.id}) read idle WITH a final assistant message for ${Math.round(idleHeldMs / 1e3)}s continuous (grace ${Math.round(fastTrackGraceMs / 1e3)}s) \u2014 promoting the synth ahead of the ${Math.round(deathDeadlineMs / 1e3)}s death backstop; the worker's real emit was lost/late and a later one no-ops idempotently.`);
18940
19369
  }
18941
19370
  } else if (holdState?.transcriptIdleSinceMs !== void 0) {
@@ -18946,6 +19375,7 @@ async function reconcileUnterminatedDirectDispatches(components, mesh, selfIds,
18946
19375
  continue;
18947
19376
  }
18948
19377
  if (!fastTrackReady) {
19378
+ backstopKind = "ackedHoldDeathDeadlineFired";
18949
19379
  LOG.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).`);
18950
19380
  }
18951
19381
  }
@@ -18990,6 +19420,7 @@ async function reconcileUnterminatedDirectDispatches(components, mesh, selfIds,
18990
19420
  source: "daemon_reconcile_transcript_completion"
18991
19421
  });
18992
19422
  if (result.reconciled) {
19423
+ recordBackstopFire(backstopKind ?? "phase4SynthesisFired", `task ${taskId} on node ${nodeId} (mesh ${mesh.id}), kind=${result.kind}`);
18993
19424
  LOG.info("MeshReconcile", `Synthesized missing completion (${result.kind}) for task ${taskId} on node ${nodeId} (mesh ${mesh.id})`);
18994
19425
  }
18995
19426
  } catch (e) {
@@ -19090,7 +19521,14 @@ function buildForwardPayloadFromPending(event) {
19090
19521
  ...(() => {
19091
19522
  const tid = readNonEmptyString2(metadata.taskId) || readNonEmptyString2(metadata.meshActiveTaskId);
19092
19523
  return tid ? { taskId: tid } : {};
19093
- })()
19524
+ })(),
19525
+ // T4 (B3b): carry the v2 envelope (protocolVersion/eventId/scope/dispatchedBy/
19526
+ // intendedFor) across the P2P relay boundary at the TOP LEVEL. These live on the
19527
+ // pending event itself, not inside metadataEvent, so without this the remote pull
19528
+ // re-queue would re-stamp a fresh eventId — breaking cross-machine idempotency and
19529
+ // downgrading the relayed completion to v1 broadcast routing. Spread LAST so the
19530
+ // authoritative envelope always wins over any stale key the metadata spread carried.
19531
+ ...serializeV2EnvelopeToWire(event)
19094
19532
  };
19095
19533
  }
19096
19534
  function setupMeshReconcileLoop(components) {
@@ -19112,7 +19550,7 @@ function setupMeshReconcileLoop(components) {
19112
19550
  }
19113
19551
  };
19114
19552
  }
19115
- var DEFAULT_RECONCILE_INTERVAL_MS, DEFAULT_AUTO_PRUNE_MIN_AGE_MS, DEFAULT_PENDING_HELD_DRAIN_ESCALATE_MS, ACKED_DEATH_CONSECUTIVE_READ_FAILURES, inFlightAckedHoldState, rehydratedHoldMeshes, coordinatorModalParkState, heldEventLedgerRecorded, ASSIGNED_STRANDED_DEADLINE_MS, DELIVERED_NO_TURN_DEADLINE_MS, RECLAIM_UNKNOWN_GRACE_TICKS, deliveredNoTurnUnknownStreak, STRICT_SESSION_MATCH_TTL_MS, unresolvedForwardRejectionCounts, MAX_FORWARD_REJECTIONS;
19553
+ var DEFAULT_RECONCILE_INTERVAL_MS, DEFAULT_AUTO_PRUNE_MIN_AGE_MS, DEFAULT_PENDING_HELD_DRAIN_ESCALATE_MS, ACKED_DEATH_CONSECUTIVE_READ_FAILURES, inFlightAckedHoldState, rehydratedHoldMeshes, meshV2BackstopCounters, coordinatorModalParkState, heldEventLedgerRecorded, ASSIGNED_STRANDED_DEADLINE_MS, DELIVERED_NO_TURN_DEADLINE_MS, RECLAIM_UNKNOWN_GRACE_TICKS, deliveredNoTurnUnknownStreak, STRICT_SESSION_MATCH_TTL_MS, unresolvedForwardRejectionCounts, MAX_FORWARD_REJECTIONS;
19116
19554
  var init_mesh_reconcile_loop = __esm({
19117
19555
  "src/mesh/mesh-reconcile-loop.ts"() {
19118
19556
  "use strict";
@@ -19140,6 +19578,14 @@ var init_mesh_reconcile_loop = __esm({
19140
19578
  ACKED_DEATH_CONSECUTIVE_READ_FAILURES = 3;
19141
19579
  inFlightAckedHoldState = /* @__PURE__ */ new Map();
19142
19580
  rehydratedHoldMeshes = /* @__PURE__ */ new Set();
19581
+ meshV2BackstopCounters = {
19582
+ /** PHASE-4 transcript synthesis actually reconciled a missing completion. */
19583
+ phase4SynthesisFired: 0,
19584
+ /** Acked-hold transcript fast-track promoted a synth ahead of the death deadline. */
19585
+ ackedHoldFastTrackFired: 0,
19586
+ /** Acked-hold death-deadline backstop released a held synth (the 8-min net). */
19587
+ ackedHoldDeathDeadlineFired: 0
19588
+ };
19143
19589
  coordinatorModalParkState = /* @__PURE__ */ new Map();
19144
19590
  heldEventLedgerRecorded = /* @__PURE__ */ new Set();
19145
19591
  ASSIGNED_STRANDED_DEADLINE_MS = 5 * 6e4;
@@ -19159,14 +19605,19 @@ __export(mesh_events_exports, {
19159
19605
  __resetMeshWorkspaceCacheForTests: () => __resetMeshWorkspaceCacheForTests,
19160
19606
  clearPendingMeshCoordinatorEvents: () => clearPendingMeshCoordinatorEvents,
19161
19607
  drainPendingMeshCoordinatorEvents: () => drainPendingMeshCoordinatorEvents,
19608
+ getMeshV2BackstopCounters: () => getMeshV2BackstopCounters,
19609
+ getMeshV2DrainCounters: () => getMeshV2DrainCounters,
19162
19610
  getPendingMeshCoordinatorEvents: () => getPendingMeshCoordinatorEvents,
19163
19611
  handleMeshForwardEvent: () => handleMeshForwardEvent,
19164
19612
  isMeshCoordinatorEvent: () => isMeshCoordinatorEvent,
19613
+ isMeshProtocolV2EnforceEnabled: () => isMeshProtocolV2EnforceEnabled,
19165
19614
  isSessionActivelyGenerating: () => isSessionActivelyGenerating,
19166
19615
  queuePendingMeshCoordinatorEvent: () => queuePendingMeshCoordinatorEvent,
19616
+ readV2EnvelopeFromWire: () => readV2EnvelopeFromWire,
19167
19617
  reconcileDirectDispatchCompletionFromTranscript: () => reconcileDirectDispatchCompletionFromTranscript,
19168
19618
  resolveCoordinatorDrainDeliverability: () => resolveCoordinatorDrainDeliverability,
19169
19619
  runMeshReconcileTick: () => runMeshReconcileTick,
19620
+ serializeV2EnvelopeToWire: () => serializeV2EnvelopeToWire,
19170
19621
  setupMeshEventForwarding: () => setupMeshEventForwarding,
19171
19622
  setupMeshReconcileLoop: () => setupMeshReconcileLoop,
19172
19623
  shouldHoldPendingDrainForBusyLocalCoordinator: () => shouldHoldPendingDrainForBusyLocalCoordinator,
@@ -25109,6 +25560,7 @@ __export(index_exports, {
25109
25560
  readLedgerSliceFromStore: () => readLedgerSliceFromStore,
25110
25561
  readMeshCompletionSummary: () => readMeshCompletionSummary,
25111
25562
  readOperatingNotes: () => readOperatingNotes,
25563
+ readV2EnvelopeFromWire: () => readV2EnvelopeFromWire,
25112
25564
  reconcileDirectDispatchCompletionFromTranscript: () => reconcileDirectDispatchCompletionFromTranscript,
25113
25565
  recordCompletionConflict: () => recordCompletionConflict,
25114
25566
  recordDebugTrace: () => recordDebugTrace,
@@ -25149,6 +25601,7 @@ __export(index_exports, {
25149
25601
  runMeshWorktreeBootstrap: () => runMeshWorktreeBootstrap,
25150
25602
  saveConfig: () => saveConfig,
25151
25603
  saveState: () => saveState,
25604
+ serializeV2EnvelopeToWire: () => serializeV2EnvelopeToWire,
25152
25605
  setDebugRuntimeConfig: () => setDebugRuntimeConfig,
25153
25606
  setLogLevel: () => setLogLevel,
25154
25607
  setMagiKindPanel: () => setMagiKindPanel,
@@ -25917,7 +26370,7 @@ var defaultSnapshotStore = createGitSnapshotStore({
25917
26370
  getStatus: (workspace) => getGitRepoStatus(workspace),
25918
26371
  getDiffSummary: (workspace) => getGitDiffSummary(workspace)
25919
26372
  });
25920
- function createDefaultGitCommandServices() {
26373
+ function createDefaultGitCommandServices(overrides) {
25921
26374
  return {
25922
26375
  getStatus: ({ workspace, refreshUpstream }) => getGitRepoStatus(workspace, { refreshUpstream }),
25923
26376
  getDiffSummary: ({ workspace, base }) => getGitDiffSummary(workspace, base ? { baseRef: base } : {}),
@@ -25935,7 +26388,8 @@ function createDefaultGitCommandServices() {
25935
26388
  stashPop: async ({ workspace, stashRef }) => gitStashPop(workspace, stashRef),
25936
26389
  checkoutFiles: async ({ workspace, paths }) => gitCheckoutFiles(workspace, paths),
25937
26390
  getRemoteUrl: async ({ workspace, remote = "origin" }) => gitGetRemoteUrl(workspace, remote),
25938
- push: async ({ workspace, remote = "origin", branch, setUpstream = false }) => gitPush(workspace, remote, branch, setUpstream)
26391
+ push: async ({ workspace, remote = "origin", branch, setUpstream = false }) => gitPush(workspace, remote, branch, setUpstream),
26392
+ ...overrides?.getReporterProviderVersions ? { getReporterProviderVersions: overrides.getReporterProviderVersions } : {}
25939
26393
  };
25940
26394
  }
25941
26395
  var defaultGitCommandServices = createDefaultGitCommandServices();
@@ -26022,12 +26476,23 @@ async function handleGitCommand(command, args, services = defaultGitCommandServi
26022
26476
  return void 0;
26023
26477
  }
26024
26478
  })();
26479
+ const reporterVersions = (() => {
26480
+ try {
26481
+ return services.getReporterProviderVersions?.() ?? {};
26482
+ } catch {
26483
+ return {};
26484
+ }
26485
+ })();
26486
+ const reporterProviderVersions = reporterVersions.providerVersions && Object.keys(reporterVersions.providerVersions).length > 0 ? reporterVersions.providerVersions : void 0;
26487
+ const reporterDaemonBuildVersion = typeof reporterVersions.daemonBuildVersion === "string" && reporterVersions.daemonBuildVersion.trim() ? reporterVersions.daemonBuildVersion.trim() : void 0;
26025
26488
  return {
26026
26489
  success: true,
26027
26490
  status,
26028
26491
  reporterPlatform: process.platform,
26029
26492
  reporterArch: process.arch,
26030
- ...reporterMachineNickname ? { reporterMachineNickname } : {}
26493
+ ...reporterMachineNickname ? { reporterMachineNickname } : {},
26494
+ ...reporterProviderVersions ? { reporterProviderVersions } : {},
26495
+ ...reporterDaemonBuildVersion ? { reporterDaemonBuildVersion } : {}
26031
26496
  };
26032
26497
  }
26033
26498
  case "git_diff_summary": {
@@ -43458,10 +43923,10 @@ var CliProviderInstance = class _CliProviderInstance {
43458
43923
  if (buttonIndex < 0 || !hasReliableConsentAnchor) {
43459
43924
  return autoApproveActive;
43460
43925
  }
43926
+ const affirmativeAnchor = normalizeApprovalLabel(buttonLabel);
43461
43927
  const modalSignature = [
43462
43928
  typeof modal?.message === "string" ? modal.message.trim() : "",
43463
- buttons.join("|"),
43464
- buttonIndex
43929
+ affirmativeAnchor
43465
43930
  ].join("::");
43466
43931
  const approvalEntrySeq = typeof adapterStatus?.approvalEntrySeq === "number" ? adapterStatus.approvalEntrySeq : 0;
43467
43932
  const busySignature = `${approvalEntrySeq}::${modalSignature}`;
@@ -53068,7 +53533,12 @@ var meshEventsHandlers = {
53068
53533
  return { success: true, events: [], heldForBusyLocalCoordinator: true, hasLiveCliCoordinator };
53069
53534
  }
53070
53535
  const events = drainPendingMeshCoordinatorEvents(meshId || void 0, coordinatorDaemonId);
53071
- return { success: true, events, hasLiveCliCoordinator, ...selfCoordinatorInboxRead ? { surfacedForSelfCoordinator: true } : {} };
53536
+ const meshProtocolV2Counters = {
53537
+ enforce: isMeshProtocolV2EnforceEnabled(),
53538
+ drain: { ...getMeshV2DrainCounters() },
53539
+ backstop: { ...getMeshV2BackstopCounters() }
53540
+ };
53541
+ return { success: true, events, hasLiveCliCoordinator, meshProtocolV2Counters, ...selfCoordinatorInboxRead ? { surfacedForSelfCoordinator: true } : {} };
53072
53542
  },
53073
53543
  interactive_prompt_response: async (ctx, args) => {
53074
53544
  const sessionId = typeof args?.targetSessionId === "string" && args.targetSessionId.trim() ? args.targetSessionId.trim() : typeof args?.sessionId === "string" && args.sessionId.trim() ? args.sessionId.trim() : "";
@@ -53900,6 +54370,12 @@ var meshStatusHandlers = {
53900
54370
  machineStatus: node.machineStatus,
53901
54371
  health: "unknown",
53902
54372
  providers: node.providers || [],
54373
+ // T7: surface self-healed provider versions + build version (from the
54374
+ // git_status envelope, persisted on the node) so the coordinator/UI can
54375
+ // spot a provider-version skew across nodes. Additive; omitted when a
54376
+ // node has never reported them.
54377
+ ...node.reportedProviderVersions && typeof node.reportedProviderVersions === "object" ? { providerVersions: node.reportedProviderVersions } : {},
54378
+ ...typeof node.reportedDaemonBuildVersion === "string" && node.reportedDaemonBuildVersion ? { daemonBuildVersion: node.reportedDaemonBuildVersion } : {},
53903
54379
  providerPriority,
53904
54380
  activeSessions: [],
53905
54381
  activeSessionDetails: [],
@@ -54088,6 +54564,11 @@ var meshStatusHandlers = {
54088
54564
  const callerCoordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : ctx.deps.statusInstanceId || void 0;
54089
54565
  const pendingCoordinatorEvents = getPendingMeshCoordinatorEvents(meshId, callerCoordinatorDaemonId);
54090
54566
  const unroutableDeliveries = getRecentUnroutableDeliveries();
54567
+ const meshProtocolV2Counters = {
54568
+ enforce: isMeshProtocolV2EnforceEnabled(),
54569
+ drain: { ...getMeshV2DrainCounters() },
54570
+ backstop: { ...getMeshV2BackstopCounters() }
54571
+ };
54091
54572
  const previewFreshness = (() => {
54092
54573
  const localRepoRoot = nodeStatuses.map((node) => readStringValue(node?.git?.repoRoot, node?.repoRoot, node?.workspace)).find((candidate) => !!candidate && fs27.existsSync(candidate));
54093
54574
  return localRepoRoot ? buildPreviewFreshness(localRepoRoot) : void 0;
@@ -54177,6 +54658,7 @@ var meshStatusHandlers = {
54177
54658
  ...historicalSessions ? { historicalSessions } : {},
54178
54659
  ...pendingCoordinatorEvents.length > 0 ? { pendingCoordinatorEvents } : {},
54179
54660
  ...unroutableDeliveries.length > 0 ? { unroutableDeliveries } : {},
54661
+ meshProtocolV2Counters,
54180
54662
  activeRefineJobs: Array.from(ctx.runningRefineJobs.values()).filter((job) => job.meshId === meshId).map((job) => ({
54181
54663
  jobId: job.jobId,
54182
54664
  nodeId: job.targetNodeId,
@@ -54186,12 +54668,13 @@ var meshStatusHandlers = {
54186
54668
  targetCoordinatorDaemonId: job.targetCoordinatorDaemonId
54187
54669
  }))
54188
54670
  };
54189
- const { pendingCoordinatorEvents: _pendingCoordinatorEvents, unroutableDeliveries: _unroutableDeliveries, ...cacheableStatusResult } = statusResult;
54671
+ const { pendingCoordinatorEvents: _pendingCoordinatorEvents, unroutableDeliveries: _unroutableDeliveries, meshProtocolV2Counters: _meshProtocolV2Counters, ...cacheableStatusResult } = statusResult;
54190
54672
  const rememberedStatus = verboseMissions ? cacheableStatusResult : ctx.rememberAggregateMeshStatus(meshId, cacheableStatusResult, refreshReason);
54191
54673
  const returnedStatus = {
54192
54674
  ...rememberedStatus,
54193
54675
  ...pendingCoordinatorEvents.length > 0 ? { pendingCoordinatorEvents } : {},
54194
- ...unroutableDeliveries.length > 0 ? { unroutableDeliveries } : {}
54676
+ ...unroutableDeliveries.length > 0 ? { unroutableDeliveries } : {},
54677
+ meshProtocolV2Counters
54195
54678
  };
54196
54679
  logRepoMeshStatusDebug("return_live", {
54197
54680
  meshId,
@@ -54673,7 +55156,13 @@ function buildLivePeerGitConnection(connection, timestamp = (/* @__PURE__ */ new
54673
55156
  }
54674
55157
  function recordInlineMeshDirectGitTruth(node, git, source) {
54675
55158
  if (!node || typeof node !== "object" || Array.isArray(node)) {
54676
- return { reporterPlatform: null, reporterArch: null, reporterMachineNickname: null };
55159
+ return {
55160
+ reporterPlatform: null,
55161
+ reporterArch: null,
55162
+ reporterMachineNickname: null,
55163
+ reporterProviderVersions: null,
55164
+ reporterDaemonBuildVersion: null
55165
+ };
54677
55166
  }
54678
55167
  const checkedAt = readNumberValue(git.lastCheckedAt) ?? Date.now();
54679
55168
  const updatedAt = new Date(checkedAt).toISOString();
@@ -54700,7 +55189,28 @@ function recordInlineMeshDirectGitTruth(node, git, source) {
54700
55189
  if (reporterArch) node.reportedArch = reporterArch;
54701
55190
  const reporterMachineNickname = readStringValue(git.reporterMachineNickname) ?? null;
54702
55191
  if (reporterMachineNickname) node.machineNickname = reporterMachineNickname;
54703
- return { reporterPlatform, reporterArch, reporterMachineNickname };
55192
+ const reporterProviderVersions = readProviderVersionsRecord(git.reporterProviderVersions);
55193
+ if (reporterProviderVersions) node.reportedProviderVersions = reporterProviderVersions;
55194
+ const reporterDaemonBuildVersion = readStringValue(git.reporterDaemonBuildVersion) ?? null;
55195
+ if (reporterDaemonBuildVersion) node.reportedDaemonBuildVersion = reporterDaemonBuildVersion;
55196
+ return {
55197
+ reporterPlatform,
55198
+ reporterArch,
55199
+ reporterMachineNickname,
55200
+ reporterProviderVersions,
55201
+ reporterDaemonBuildVersion
55202
+ };
55203
+ }
55204
+ function readProviderVersionsRecord(value) {
55205
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
55206
+ const out = {};
55207
+ for (const [key2, raw] of Object.entries(value)) {
55208
+ if (typeof key2 !== "string" || !key2.trim()) continue;
55209
+ const version = typeof raw === "string" ? raw.trim() : "";
55210
+ if (!version) continue;
55211
+ out[key2] = version;
55212
+ }
55213
+ return Object.keys(out).length > 0 ? out : null;
54704
55214
  }
54705
55215
  function stampNodeReporterPlatform(node, platform10, arch2) {
54706
55216
  if (!node || typeof node !== "object" || Array.isArray(node)) return;
@@ -54724,8 +55234,18 @@ function persistNodeReporterPlatform(meshSource, mesh, nodeId, reporter) {
54724
55234
  const reportedPlatform = reporter.reporterPlatform ?? void 0;
54725
55235
  const reportedArch = reporter.reporterArch ?? void 0;
54726
55236
  const reportedMachineNickname = reporter.reporterMachineNickname ?? void 0;
54727
- if (!reportedPlatform && !reportedArch && !reportedMachineNickname) return;
54728
- void Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports)).then(({ updateNode: updateNode2 }) => updateNode2(meshId, nodeId, { reportedPlatform, reportedArch, reportedMachineNickname })).catch(() => {
55237
+ const reportedProviderVersions = reporter.reporterProviderVersions ?? void 0;
55238
+ const reportedDaemonBuildVersion = reporter.reporterDaemonBuildVersion ?? void 0;
55239
+ if (!reportedPlatform && !reportedArch && !reportedMachineNickname && !reportedProviderVersions && !reportedDaemonBuildVersion) {
55240
+ return;
55241
+ }
55242
+ void Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports)).then(({ updateNode: updateNode2 }) => updateNode2(meshId, nodeId, {
55243
+ reportedPlatform,
55244
+ reportedArch,
55245
+ reportedMachineNickname,
55246
+ reportedProviderVersions,
55247
+ reportedDaemonBuildVersion
55248
+ })).catch(() => {
54729
55249
  });
54730
55250
  }
54731
55251
  function buildCachedInlineMeshGitStatus(node) {
@@ -55382,6 +55902,10 @@ async function probeRemoteMeshGitStatus(args) {
55382
55902
  if (reporterPlatform) git.reporterPlatform = reporterPlatform;
55383
55903
  if (reporterArch) git.reporterArch = reporterArch;
55384
55904
  if (reporterMachineNickname) git.reporterMachineNickname = reporterMachineNickname;
55905
+ const reporterProviderVersions = readProviderVersionsRecord(remoteResult?.reporterProviderVersions);
55906
+ if (reporterProviderVersions) git.reporterProviderVersions = reporterProviderVersions;
55907
+ const reporterDaemonBuildVersion = readStringValue(remoteResult?.reporterDaemonBuildVersion);
55908
+ if (reporterDaemonBuildVersion) git.reporterDaemonBuildVersion = reporterDaemonBuildVersion;
55385
55909
  return git;
55386
55910
  }
55387
55911
  var MESH_DIRECT_PROBE_MAX_RETRIES = 2;
@@ -67313,6 +67837,7 @@ function launchIDE(ide, workspacePath) {
67313
67837
 
67314
67838
  // src/boot/daemon-lifecycle.ts
67315
67839
  init_cli_detector();
67840
+ init_build_info();
67316
67841
 
67317
67842
  // src/sessions/registry.ts
67318
67843
  var SessionRegistry = class {
@@ -67514,7 +68039,19 @@ async function initDaemonComponents(config) {
67514
68039
  providerLoader,
67515
68040
  instanceManager,
67516
68041
  sessionRegistry,
67517
- gitCommandServices: createDefaultGitCommandServices(),
68042
+ gitCommandServices: createDefaultGitCommandServices({
68043
+ // T7: fold this daemon's cached provider versions + build version onto the
68044
+ // git_status envelope so the mesh coordinator self-heals each node's
68045
+ // providerVersions. Non-blocking: reads a TTL cache, lazily refreshed.
68046
+ getReporterProviderVersions: () => {
68047
+ const providerVersions = getCachedProviderVersions(providerLoader);
68048
+ const daemonBuildVersion = getDaemonBuildInfo().version;
68049
+ return {
68050
+ ...Object.keys(providerVersions).length > 0 ? { providerVersions } : {},
68051
+ ...daemonBuildVersion && daemonBuildVersion !== "unknown" ? { daemonBuildVersion } : {}
68052
+ };
68053
+ }
68054
+ }),
67518
68055
  onProviderSettingChanged: async (providerType) => {
67519
68056
  await refreshProviderAvailability(providerType);
67520
68057
  config.onStatusChange?.();
@@ -68237,6 +68774,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
68237
68774
  readLedgerSliceFromStore,
68238
68775
  readMeshCompletionSummary,
68239
68776
  readOperatingNotes,
68777
+ readV2EnvelopeFromWire,
68240
68778
  reconcileDirectDispatchCompletionFromTranscript,
68241
68779
  recordCompletionConflict,
68242
68780
  recordDebugTrace,
@@ -68277,6 +68815,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
68277
68815
  runMeshWorktreeBootstrap,
68278
68816
  saveConfig,
68279
68817
  saveState,
68818
+ serializeV2EnvelopeToWire,
68280
68819
  setDebugRuntimeConfig,
68281
68820
  setLogLevel,
68282
68821
  setMagiKindPanel,