@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.mjs CHANGED
@@ -404,10 +404,10 @@ function readInjected(value) {
404
404
  }
405
405
  function getDaemonBuildInfo() {
406
406
  if (cached) return cached;
407
- const commit = readInjected(true ? "f8ce1329d3bdef9564c4130a1e7f0b607738f3cd" : void 0) ?? "unknown";
408
- const commitShort = readInjected(true ? "f8ce1329" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
409
- const version = readInjected(true ? "0.9.82-rc.460" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
410
- const builtAt = readInjected(true ? "2026-07-04T14:24:11.778Z" : void 0);
407
+ const commit = readInjected(true ? "1481e2078cc0eceea283a2370cccb4cd9102e4ff" : void 0) ?? "unknown";
408
+ const commitShort = readInjected(true ? "1481e207" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
409
+ const version = readInjected(true ? "0.9.82-rc.462" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
410
+ const builtAt = readInjected(true ? "2026-07-04T16:50:21.874Z" : void 0);
411
411
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
412
412
  return cached;
413
413
  }
@@ -3258,6 +3258,12 @@ function updateNode(meshId, nodeId, opts) {
3258
3258
  if (opts.reportedPlatform && opts.reportedPlatform.trim()) node.reportedPlatform = opts.reportedPlatform.trim();
3259
3259
  if (opts.reportedArch && opts.reportedArch.trim()) node.reportedArch = opts.reportedArch.trim();
3260
3260
  if (opts.reportedMachineNickname && opts.reportedMachineNickname.trim()) node.machineNickname = opts.reportedMachineNickname.trim();
3261
+ if (opts.reportedProviderVersions && Object.keys(opts.reportedProviderVersions).length > 0) {
3262
+ node.reportedProviderVersions = { ...opts.reportedProviderVersions };
3263
+ }
3264
+ if (opts.reportedDaemonBuildVersion && opts.reportedDaemonBuildVersion.trim()) {
3265
+ node.reportedDaemonBuildVersion = opts.reportedDaemonBuildVersion.trim();
3266
+ }
3261
3267
  if (opts.policy) node.policy = { ...node.policy, ...opts.policy };
3262
3268
  if (opts.worktreeBootstrap) node.worktreeBootstrap = opts.worktreeBootstrap;
3263
3269
  if (Object.prototype.hasOwnProperty.call(opts, "systemPrompt")) {
@@ -3601,9 +3607,16 @@ function buildNodeStatusSection(nodes) {
3601
3607
  const healthIcon = n.health === "online" ? "\u{1F7E2}" : n.health === "dirty" ? "\u{1F7E1}" : n.health === "offline" ? "\u26AB" : "\u{1F534}";
3602
3608
  const sessions = n.activeSessions.length > 0 ? `sessions: ${n.activeSessions.join(", ")}` : "no active sessions";
3603
3609
  const branch = n.git?.branch ? `branch: \`${n.git.branch}\`` : "";
3610
+ const providerVersions = n.providerVersions && typeof n.providerVersions === "object" ? n.providerVersions : void 0;
3611
+ const providersRendered = n.providers?.length ? n.providers.map((p) => {
3612
+ const version = providerVersions?.[p];
3613
+ return version ? `${p}@${version}` : p;
3614
+ }).join(", ") : "";
3615
+ const buildVersion = typeof n.daemonBuildVersion === "string" && n.daemonBuildVersion ? `build: ${n.daemonBuildVersion}` : "";
3604
3616
  const context = [
3605
3617
  n.daemonId ? `daemon: \`${n.daemonId}\`` : "",
3606
- n.providers?.length ? `providers: ${n.providers.join(", ")}` : ""
3618
+ providersRendered ? `providers: ${providersRendered}` : "",
3619
+ buildVersion
3607
3620
  ].filter(Boolean).join(" | ");
3608
3621
  lines.push(`- ${healthIcon} **${n.machineLabel}** (nodeId: \`${n.nodeId}\`)`);
3609
3622
  lines.push(` workspace: \`${n.workspace}\`${context ? ` | ${context}` : ""} | ${branch} | ${sessions}`);
@@ -4167,6 +4180,98 @@ var init_load_better_sqlite3 = __esm({
4167
4180
  });
4168
4181
 
4169
4182
  // src/mesh/contracts.ts
4183
+ function isSupportedMeshProtocolVersion(value) {
4184
+ return typeof value === "string" && SUPPORTED_MESH_PROTOCOL_VERSIONS.includes(value);
4185
+ }
4186
+ function coordinatorIdentityEquals(a, b) {
4187
+ return daemonIdsEquivalent(a.daemonId, b.daemonId) && a.coordinatorRunId === b.coordinatorRunId && (a.sessionId ?? "") === (b.sessionId ?? "");
4188
+ }
4189
+ function coordinatorIdentityKey(identity) {
4190
+ const daemonCore = machineCoreFromDaemonId(identity.daemonId) ?? identity.daemonId;
4191
+ return `${daemonCore}|${identity.coordinatorRunId}|${identity.sessionId ?? ""}`;
4192
+ }
4193
+ function isMeshEventScope(value) {
4194
+ return typeof value === "string" && MESH_EVENT_SCOPES.includes(value);
4195
+ }
4196
+ function isNonEmptyString(value) {
4197
+ return typeof value === "string" && value.length > 0;
4198
+ }
4199
+ function assertCoordinatorIdentity(raw, path44) {
4200
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
4201
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, path44, "must be an object");
4202
+ }
4203
+ const obj = raw;
4204
+ if (!isNonEmptyString(obj.daemonId)) {
4205
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.daemonId`, "must be a non-empty string");
4206
+ }
4207
+ if (!isNonEmptyString(obj.coordinatorRunId)) {
4208
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.coordinatorRunId`, "must be a non-empty string");
4209
+ }
4210
+ const sessionId = obj.sessionId;
4211
+ if (sessionId !== void 0 && !isNonEmptyString(sessionId)) {
4212
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.sessionId`, "must be a non-empty string when provided");
4213
+ }
4214
+ return sessionId !== void 0 ? { daemonId: obj.daemonId, coordinatorRunId: obj.coordinatorRunId, sessionId } : { daemonId: obj.daemonId, coordinatorRunId: obj.coordinatorRunId };
4215
+ }
4216
+ function assertPendingMeshCoordinatorEventV2(raw, path44 = "$") {
4217
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
4218
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, path44, "must be an object");
4219
+ }
4220
+ const obj = raw;
4221
+ if (!isSupportedMeshProtocolVersion(obj.protocolVersion)) {
4222
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.protocolVersion`, `must be one of ${SUPPORTED_MESH_PROTOCOL_VERSIONS.join(", ")}`);
4223
+ }
4224
+ if (!isNonEmptyString(obj.eventId)) {
4225
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.eventId`, "must be a non-empty string");
4226
+ }
4227
+ if (!isMeshEventScope(obj.scope)) {
4228
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.scope`, `must be one of ${MESH_EVENT_SCOPES.join(", ")}`);
4229
+ }
4230
+ if (!isNonEmptyString(obj.event)) {
4231
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.event`, "must be a non-empty string");
4232
+ }
4233
+ if (!isNonEmptyString(obj.meshId)) {
4234
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.meshId`, "must be a non-empty string");
4235
+ }
4236
+ const dispatchedBy = assertCoordinatorIdentity(obj.dispatchedBy, `${path44}.dispatchedBy`);
4237
+ if (obj.scope === "unicast") {
4238
+ if (!obj.intendedFor) {
4239
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.intendedFor`, "unicast scope requires intendedFor");
4240
+ }
4241
+ } else if (obj.intendedFor !== void 0) {
4242
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.intendedFor`, "only unicast scope may set intendedFor");
4243
+ }
4244
+ const intendedFor = obj.intendedFor ? assertCoordinatorIdentity(obj.intendedFor, `${path44}.intendedFor`) : void 0;
4245
+ const metadata = obj.metadataEvent && typeof obj.metadataEvent === "object" && !Array.isArray(obj.metadataEvent) ? obj.metadataEvent : null;
4246
+ if (!metadata) {
4247
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.metadataEvent`, "must be an object");
4248
+ }
4249
+ const queuedAt = typeof obj.queuedAt === "number" && Number.isFinite(obj.queuedAt) ? obj.queuedAt : null;
4250
+ if (queuedAt === null) {
4251
+ throw new MeshContractViolationError(MESH_PROTOCOL_VERSION_V2, `${path44}.queuedAt`, "must be a finite number");
4252
+ }
4253
+ return {
4254
+ event: obj.event,
4255
+ meshId: obj.meshId,
4256
+ nodeLabel: isNonEmptyString(obj.nodeLabel) ? obj.nodeLabel : "",
4257
+ nodeId: typeof obj.nodeId === "string" ? obj.nodeId : void 0,
4258
+ workspace: typeof obj.workspace === "string" ? obj.workspace : void 0,
4259
+ metadataEvent: metadata,
4260
+ coordinatorMessage: typeof obj.coordinatorMessage === "string" ? obj.coordinatorMessage : void 0,
4261
+ queuedAt,
4262
+ protocolVersion: obj.protocolVersion,
4263
+ eventId: obj.eventId,
4264
+ scope: obj.scope,
4265
+ dispatchedBy,
4266
+ ...intendedFor ? { intendedFor } : {}
4267
+ };
4268
+ }
4269
+ function shouldDeliverPendingEventToCoordinator(event, drainer) {
4270
+ if (event.scope === "system") return false;
4271
+ if (event.scope === "broadcast") return true;
4272
+ if (!event.intendedFor) return false;
4273
+ return coordinatorIdentityEquals(event.intendedFor, drainer);
4274
+ }
4170
4275
  function defaultScopeForEvent(eventName) {
4171
4276
  if (SYSTEM_EVENTS.has(eventName)) return "system";
4172
4277
  if (TERMINAL_TASK_EVENTS.has(eventName)) return "unicast";
@@ -4195,12 +4300,28 @@ function buildPendingEventEmitStamp(opts) {
4195
4300
  ...intendedFor ? { intendedFor } : {}
4196
4301
  };
4197
4302
  }
4198
- var MESH_PROTOCOL_VERSION_V2, TERMINAL_TASK_EVENTS, SYSTEM_EVENTS;
4303
+ var MESH_PROTOCOL_VERSION_V1, MESH_PROTOCOL_VERSION_V2, SUPPORTED_MESH_PROTOCOL_VERSIONS, MESH_EVENT_SCOPES, MeshContractViolationError, TERMINAL_TASK_EVENTS, SYSTEM_EVENTS;
4199
4304
  var init_contracts = __esm({
4200
4305
  "src/mesh/contracts.ts"() {
4201
4306
  "use strict";
4202
4307
  init_dist();
4308
+ MESH_PROTOCOL_VERSION_V1 = "1.0";
4203
4309
  MESH_PROTOCOL_VERSION_V2 = "2.0";
4310
+ SUPPORTED_MESH_PROTOCOL_VERSIONS = [
4311
+ MESH_PROTOCOL_VERSION_V1,
4312
+ MESH_PROTOCOL_VERSION_V2
4313
+ ];
4314
+ MESH_EVENT_SCOPES = ["unicast", "broadcast", "system"];
4315
+ MeshContractViolationError = class extends Error {
4316
+ violationPath;
4317
+ protocolVersion;
4318
+ constructor(protocolVersion, violationPath, detail) {
4319
+ super(`mesh contract ${protocolVersion} violation at ${violationPath}: ${detail}`);
4320
+ this.name = "MeshContractViolationError";
4321
+ this.violationPath = violationPath;
4322
+ this.protocolVersion = protocolVersion;
4323
+ }
4324
+ };
4204
4325
  TERMINAL_TASK_EVENTS = /* @__PURE__ */ new Set([
4205
4326
  "agent:generating_completed",
4206
4327
  "agent:stopped",
@@ -7529,6 +7650,34 @@ var init_mesh_runtime_store = __esm({
7529
7650
  ).get(meshId, fingerprint);
7530
7651
  return row !== void 0;
7531
7652
  }
7653
+ /**
7654
+ * B3a — v2 eventId idempotency. Returns true when a row with this event_id has
7655
+ * ALREADY been drained (drained = 1) for the mesh. Drained rows are retained
7656
+ * (soft-marked, not deleted until mesh deletion), so this is a durable, restart-
7657
+ * surviving dedup: a v2 event whose eventId was already consumed is skipped on
7658
+ * re-delivery even when its content fingerprint differs. Scoped by mesh_id +
7659
+ * the partial event_id index (idx_mesh_pending_events_event_id).
7660
+ */
7661
+ hasDrainedEventId(meshId, eventId) {
7662
+ if (!eventId) return false;
7663
+ const row = this.db.prepare(
7664
+ "SELECT 1 FROM mesh_pending_events WHERE mesh_id = ? AND event_id = ? AND drained = 1 LIMIT 1"
7665
+ ).get(meshId, eventId);
7666
+ return row !== void 0;
7667
+ }
7668
+ /**
7669
+ * B3a — snapshot of the v2 event_ids ALREADY drained (drained = 1) for the mesh.
7670
+ * Taken BEFORE a drain call marks the current batch drained=1, so the resulting
7671
+ * set names only PRIOR drains — the re-delivery dedup baseline. (Reading it after
7672
+ * the drain would self-match the batch's own freshly-drained rows.) Non-v2 rows
7673
+ * have a NULL event_id and are excluded by the index/WHERE.
7674
+ */
7675
+ drainedEventIdsForMesh(meshId) {
7676
+ const rows = this.db.prepare(
7677
+ "SELECT DISTINCT event_id FROM mesh_pending_events WHERE mesh_id = ? AND drained = 1 AND event_id IS NOT NULL"
7678
+ ).all(meshId);
7679
+ return new Set(rows.map((r) => r.event_id));
7680
+ }
7532
7681
  // ── M3: Mission Records ─────────────────────────────────────────────────
7533
7682
  upsertMission(mission) {
7534
7683
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -11326,6 +11475,145 @@ import { randomUUID as randomUUID8 } from "crypto";
11326
11475
  function normalizeCoordinatorDaemonIds(coordinatorDaemonId) {
11327
11476
  return expandDaemonIdForms(coordinatorDaemonId);
11328
11477
  }
11478
+ function isMeshProtocolV2EnforceEnabled() {
11479
+ const raw = readNonEmptyString2(process.env.MESH_PROTOCOL_V2_ENFORCE);
11480
+ if (!raw) return false;
11481
+ const v = raw.trim().toLowerCase();
11482
+ return v === "1" || v === "true" || v === "on" || v === "yes";
11483
+ }
11484
+ function ledgerRecordQuarantinedEvent(event, reason) {
11485
+ try {
11486
+ const finalSummary = readMeshCompletionSummary(event.metadataEvent || {});
11487
+ appendLedgerEntry(event.meshId, {
11488
+ kind: "event_held",
11489
+ ...event.nodeId ? { nodeId: event.nodeId } : {},
11490
+ payload: {
11491
+ event: event.event,
11492
+ reason,
11493
+ recoverable: true,
11494
+ nodeLabel: event.nodeLabel,
11495
+ ...event.workspace ? { workspace: event.workspace } : {},
11496
+ targetCoordinatorDaemonId: event.targetCoordinatorDaemonId ?? null,
11497
+ ...readNonEmptyString2(event.eventId) ? { eventId: event.eventId } : {},
11498
+ queuedAt: event.queuedAt,
11499
+ ...finalSummary ? { finalSummary } : {}
11500
+ }
11501
+ });
11502
+ } catch (e) {
11503
+ LOG.warn("MeshEventsV2", `Failed to ledger-record v2-quarantined ${event.event} for mesh ${event.meshId}: ${e?.message || e}`);
11504
+ }
11505
+ }
11506
+ function getMeshV2DrainCounters() {
11507
+ return { ...meshV2DrainCounters };
11508
+ }
11509
+ function warnV2Once(key2, message) {
11510
+ if (warnedV2Violations.has(key2)) return;
11511
+ warnedV2Violations.add(key2);
11512
+ if (warnedV2Violations.size > 2e3) {
11513
+ const first = warnedV2Violations.values().next().value;
11514
+ if (first !== void 0) warnedV2Violations.delete(first);
11515
+ }
11516
+ LOG.warn("MeshEventsV2", message);
11517
+ }
11518
+ function resolveDrainerIdentity(daemonIds, explicit) {
11519
+ if (explicit) return explicit;
11520
+ return coordinatorIdentityFromEmitFields({ daemonId: daemonIds[0] });
11521
+ }
11522
+ function isV2Event(event) {
11523
+ return event.protocolVersion === MESH_PROTOCOL_VERSION_V2;
11524
+ }
11525
+ function runIdIsDaemonFormFallback(identity) {
11526
+ return daemonIdsEquivalent(identity.coordinatorRunId, identity.daemonId);
11527
+ }
11528
+ function identityDeliversTo(intendedFor, drainer) {
11529
+ if (runIdIsDaemonFormFallback(intendedFor) && runIdIsDaemonFormFallback(drainer)) {
11530
+ if (!daemonIdsEquivalent(intendedFor.daemonId, drainer.daemonId)) return false;
11531
+ if (intendedFor.sessionId && drainer.sessionId) {
11532
+ return intendedFor.sessionId === drainer.sessionId;
11533
+ }
11534
+ return true;
11535
+ }
11536
+ return coordinatorIdentityEquals(intendedFor, drainer);
11537
+ }
11538
+ function routeV2EventsForDrainer(events, drainer, ctx) {
11539
+ if (!drainer) return events;
11540
+ const enforce = isMeshProtocolV2EnforceEnabled();
11541
+ const bump = (k) => {
11542
+ if (ctx.countMetrics) meshV2DrainCounters[k]++;
11543
+ };
11544
+ const kept = [];
11545
+ for (const event of events) {
11546
+ if (!isV2Event(event)) {
11547
+ if (enforce) {
11548
+ bump("v1UnversionedQuarantined");
11549
+ if (ctx.countMetrics) ledgerRecordQuarantinedEvent(event, "v2_enforce_unversioned_quarantined");
11550
+ warnV2Once(
11551
+ `${event.meshId}::${event.eventId ?? event.event}::v1-quarantined`,
11552
+ `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.`
11553
+ );
11554
+ continue;
11555
+ }
11556
+ bump("v1BroadcastAccepted");
11557
+ kept.push(event);
11558
+ continue;
11559
+ }
11560
+ let validated;
11561
+ try {
11562
+ validated = assertPendingMeshCoordinatorEventV2(event);
11563
+ } catch (e) {
11564
+ if (enforce) {
11565
+ bump("v2ValidationFailedQuarantined");
11566
+ if (ctx.countMetrics) ledgerRecordQuarantinedEvent(event, "v2_enforce_validation_failed_quarantined");
11567
+ warnV2Once(
11568
+ `${event.meshId}::${event.eventId ?? event.event}::invalid-quarantined`,
11569
+ `v2 ENFORCE: envelope validation failed for ${event.event} on mesh ${event.meshId} \u2014 QUARANTINED (held back, not delivered; ledger-recorded recoverable): ${e?.message || e}`
11570
+ );
11571
+ continue;
11572
+ }
11573
+ bump("v2ValidationFailedAccepted");
11574
+ warnV2Once(
11575
+ `${event.meshId}::${event.eventId ?? event.event}::invalid`,
11576
+ `v2 envelope validation failed for ${event.event} on mesh ${event.meshId} \u2014 PASSED THROUGH (accept mode): ${e?.message || e}`
11577
+ );
11578
+ kept.push(event);
11579
+ continue;
11580
+ }
11581
+ const eventId = validated.eventId;
11582
+ if (ctx.batchSeen.has(eventId) || ctx.alreadyDrained(eventId)) {
11583
+ bump("v2DedupSkipped");
11584
+ continue;
11585
+ }
11586
+ if (validated.scope !== "unicast") {
11587
+ if (shouldDeliverPendingEventToCoordinator(validated, drainer)) {
11588
+ ctx.batchSeen.add(eventId);
11589
+ bump("v2Delivered");
11590
+ kept.push(event);
11591
+ } else {
11592
+ bump("v2RoutedAway");
11593
+ }
11594
+ continue;
11595
+ }
11596
+ if (validated.intendedFor && identityDeliversTo(validated.intendedFor, drainer)) {
11597
+ ctx.batchSeen.add(eventId);
11598
+ bump("v2Delivered");
11599
+ kept.push(event);
11600
+ continue;
11601
+ }
11602
+ const realRunIdMismatch = !runIdIsDaemonFormFallback(validated.intendedFor) || !runIdIsDaemonFormFallback(drainer);
11603
+ if (validated.intendedFor && realRunIdMismatch && daemonIdsEquivalent(validated.intendedFor.daemonId, drainer.daemonId)) {
11604
+ ctx.batchSeen.add(eventId);
11605
+ bump("v2ReattributedToDrainer");
11606
+ warnV2Once(
11607
+ `${event.meshId}::${eventId}::reattributed`,
11608
+ `v2 unicast ${event.event} on mesh ${event.meshId} re-attributed to current coordinator ${coordinatorIdentityKey(drainer)} (originating coordinatorRunId no longer live)`
11609
+ );
11610
+ kept.push(event);
11611
+ continue;
11612
+ }
11613
+ bump("v2RoutedAway");
11614
+ }
11615
+ return kept;
11616
+ }
11329
11617
  function readRefineJobId2(event) {
11330
11618
  const metadata = readRecord5(event.metadataEvent) || event;
11331
11619
  const result = readRecord5(metadata.result);
@@ -11544,6 +11832,36 @@ function stampPendingEventV2(event, hint) {
11544
11832
  ...stamp.intendedFor ? { intendedFor: stamp.intendedFor } : {}
11545
11833
  };
11546
11834
  }
11835
+ function readCoordinatorIdentityFromWire(raw) {
11836
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
11837
+ const obj = raw;
11838
+ const daemonId = readNonEmptyString2(obj.daemonId);
11839
+ const coordinatorRunId = readNonEmptyString2(obj.coordinatorRunId);
11840
+ if (!daemonId || !coordinatorRunId) return void 0;
11841
+ const sessionId = readNonEmptyString2(obj.sessionId);
11842
+ return { daemonId, coordinatorRunId, ...sessionId ? { sessionId } : {} };
11843
+ }
11844
+ function serializeV2EnvelopeToWire(event) {
11845
+ const out = {};
11846
+ if (event.protocolVersion) out.protocolVersion = event.protocolVersion;
11847
+ if (readNonEmptyString2(event.eventId)) out.eventId = event.eventId;
11848
+ if (event.scope) out.scope = event.scope;
11849
+ if (event.dispatchedBy) out.dispatchedBy = event.dispatchedBy;
11850
+ if (event.intendedFor) out.intendedFor = event.intendedFor;
11851
+ return out;
11852
+ }
11853
+ function readV2EnvelopeFromWire(payload) {
11854
+ const out = {};
11855
+ if (payload.protocolVersion === MESH_PROTOCOL_VERSION_V2) out.protocolVersion = MESH_PROTOCOL_VERSION_V2;
11856
+ const eventId = readNonEmptyString2(payload.eventId);
11857
+ if (eventId) out.eventId = eventId;
11858
+ if (isMeshEventScope(payload.scope)) out.scope = payload.scope;
11859
+ const dispatchedBy = readCoordinatorIdentityFromWire(payload.dispatchedBy);
11860
+ if (dispatchedBy) out.dispatchedBy = dispatchedBy;
11861
+ const intendedFor = readCoordinatorIdentityFromWire(payload.intendedFor);
11862
+ if (intendedFor) out.intendedFor = intendedFor;
11863
+ return out;
11864
+ }
11547
11865
  function queuePendingMeshCoordinatorEvent(rawEvent, hint) {
11548
11866
  const event = stampPendingEventV2(rawEvent, hint);
11549
11867
  try {
@@ -11666,6 +11984,12 @@ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId, opts) {
11666
11984
  if (!meshId) return [];
11667
11985
  const daemonIds = normalizeCoordinatorDaemonIds(coordinatorDaemonId);
11668
11986
  const primaryDaemonId = daemonIds[0];
11987
+ const drainer = resolveDrainerIdentity(daemonIds, opts?.drainerIdentity);
11988
+ let priorDrainedEventIds = /* @__PURE__ */ new Set();
11989
+ try {
11990
+ priorDrainedEventIds = MeshRuntimeStore.getInstance().drainedEventIdsForMesh(meshId);
11991
+ } catch {
11992
+ }
11669
11993
  const onlyEvents = opts?.onlyEvents;
11670
11994
  const matchesFilter = (eventName) => !onlyEvents || onlyEvents.has(eventName);
11671
11995
  const merged = [];
@@ -11712,7 +12036,12 @@ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId, opts) {
11712
12036
  for (const event of filtered) pushUnique(event);
11713
12037
  }
11714
12038
  if (merged.length === 0) return [];
11715
- return reconcilePendingMeshCoordinatorEvents(meshId, merged);
12039
+ const routed = routeV2EventsForDrainer(merged, drainer, {
12040
+ alreadyDrained: (eventId) => priorDrainedEventIds.has(eventId),
12041
+ batchSeen: /* @__PURE__ */ new Set(),
12042
+ countMetrics: true
12043
+ });
12044
+ return reconcilePendingMeshCoordinatorEvents(meshId, routed);
11716
12045
  }
11717
12046
  function retractPendingDispatchBlockedEvent(meshId, taskId, coordinatorDaemonId) {
11718
12047
  if (!meshId || !taskId) return 0;
@@ -11743,9 +12072,15 @@ function retractPendingDispatchBlockedEvent(meshId, taskId, coordinatorDaemonId)
11743
12072
  }
11744
12073
  return removed;
11745
12074
  }
11746
- function getPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
12075
+ function getPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId, opts) {
11747
12076
  if (!meshId) return [];
11748
12077
  const daemonIds = normalizeCoordinatorDaemonIds(coordinatorDaemonId);
12078
+ const drainer = resolveDrainerIdentity(daemonIds, opts?.drainerIdentity);
12079
+ let priorDrainedEventIds = /* @__PURE__ */ new Set();
12080
+ try {
12081
+ priorDrainedEventIds = MeshRuntimeStore.getInstance().drainedEventIdsForMesh(meshId);
12082
+ } catch {
12083
+ }
11749
12084
  const merged = [];
11750
12085
  const seenFingerprints = /* @__PURE__ */ new Set();
11751
12086
  const pushUnique = (event) => {
@@ -11769,7 +12104,12 @@ function getPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
11769
12104
  for (const event of readPendingMeshCoordinatorEventsFromDisk(meshId, daemonIds)) {
11770
12105
  pushUnique(event);
11771
12106
  }
11772
- return reconcilePendingMeshCoordinatorEvents(meshId, merged);
12107
+ const routed = routeV2EventsForDrainer(merged, drainer, {
12108
+ alreadyDrained: (eventId) => priorDrainedEventIds.has(eventId),
12109
+ batchSeen: /* @__PURE__ */ new Set(),
12110
+ countMetrics: false
12111
+ });
12112
+ return reconcilePendingMeshCoordinatorEvents(meshId, routed);
11773
12113
  }
11774
12114
  function clearPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
11775
12115
  if (!meshId) return;
@@ -11785,7 +12125,7 @@ function clearPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
11785
12125
  }
11786
12126
  }
11787
12127
  }
11788
- var REFINE_TERMINAL_EVENTS, TERMINAL_COMPLETION_EVENTS, MAX_PENDING_EVENTS_BYTES, MAX_PENDING_EVENTS_KEEP;
12128
+ var REFINE_TERMINAL_EVENTS, meshV2DrainCounters, warnedV2Violations, TERMINAL_COMPLETION_EVENTS, MAX_PENDING_EVENTS_BYTES, MAX_PENDING_EVENTS_KEEP;
11789
12129
  var init_mesh_events_pending = __esm({
11790
12130
  "src/mesh/mesh-events-pending.ts"() {
11791
12131
  "use strict";
@@ -11796,6 +12136,32 @@ var init_mesh_events_pending = __esm({
11796
12136
  init_dist();
11797
12137
  init_contracts();
11798
12138
  REFINE_TERMINAL_EVENTS = /* @__PURE__ */ new Set(["refine:completed", "refine:failed"]);
12139
+ meshV2DrainCounters = {
12140
+ /** v2 events that passed validation and unicast/broadcast routing → delivered. */
12141
+ v2Delivered: 0,
12142
+ /** v2 unicast events skipped because intendedFor addressed another coordinator. */
12143
+ v2RoutedAway: 0,
12144
+ /** v2 events skipped because their eventId was already drained (idempotency). */
12145
+ v2DedupSkipped: 0,
12146
+ /** v2 events that failed assertPendingMeshCoordinatorEventV2 but were PASSED
12147
+ * THROUGH (accept mode). Non-zero here is the rollout signal that a producer
12148
+ * emits a malformed envelope. */
12149
+ v2ValidationFailedAccepted: 0,
12150
+ /** unicast events re-attributed to the drainer via daemon-core match (a
12151
+ * coordinatorRunId change orphaned them). */
12152
+ v2ReattributedToDrainer: 0,
12153
+ /** v1 (unversioned) events passed through as broadcast (rollout baseline). */
12154
+ v1BroadcastAccepted: 0,
12155
+ /** T6 enforce: v2 events that FAILED validation and were QUARANTINED (held back
12156
+ * from delivery, not dropped). Non-zero here means a producer is still emitting a
12157
+ * malformed envelope after enforce was turned on. */
12158
+ v2ValidationFailedQuarantined: 0,
12159
+ /** T6 enforce: v1 (unversioned) events QUARANTINED because no v2 envelope could be
12160
+ * derived at emit time. Non-zero here means a producer path still emits v1 after
12161
+ * enforce — it should reach 0 once every node is on a v2-stamping build. */
12162
+ v1UnversionedQuarantined: 0
12163
+ };
12164
+ warnedV2Violations = /* @__PURE__ */ new Set();
11799
12165
  TERMINAL_COMPLETION_EVENTS = /* @__PURE__ */ new Set(["agent:generating_completed", "agent:stopped"]);
11800
12166
  MAX_PENDING_EVENTS_BYTES = 100 * 1024;
11801
12167
  MAX_PENDING_EVENTS_KEEP = 50;
@@ -12853,10 +13219,46 @@ 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
  }
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 PROVIDER_VERSIONS_TTL_MS, cachedProviderVersions, cachedProviderVersionsAt, providerVersionsRefreshInFlight;
12856
13254
  var init_cli_detector = __esm({
12857
13255
  "src/detection/cli-detector.ts"() {
12858
13256
  "use strict";
12859
13257
  init_provider_cli_shared();
13258
+ PROVIDER_VERSIONS_TTL_MS = 5 * 60 * 1e3;
13259
+ cachedProviderVersions = {};
13260
+ cachedProviderVersionsAt = 0;
13261
+ providerVersionsRefreshInFlight = null;
12860
13262
  }
12861
13263
  });
12862
13264
 
@@ -17545,7 +17947,13 @@ function injectMeshSystemMessage(components, args) {
17545
17947
  ...workerCoordinatorDaemonId ? { targetCoordinatorDaemonId: workerCoordinatorDaemonId } : {},
17546
17948
  // Top-level session anchor for the local PHASE 2 strict-match on the coordinator
17547
17949
  // daemon. Absent → daemon-level broadcast (legacy / single-coordinator path).
17548
- ...workerCoordinatorSessionId ? { targetCoordinatorSessionId: workerCoordinatorSessionId } : {}
17950
+ ...workerCoordinatorSessionId ? { targetCoordinatorSessionId: workerCoordinatorSessionId } : {},
17951
+ // T4 (B3b): restore the v2 envelope from the remote relay so the re-queue keeps the
17952
+ // ORIGINAL eventId. Spread LAST so its authoritative eventId/scope/identity win over
17953
+ // any default. queuePendingMeshCoordinatorEvent → stampPendingEventV2 then no-ops
17954
+ // (already-stamped short-circuit) instead of minting a fresh eventId. Empty object
17955
+ // for a v1 relay → unchanged v1 emit-stamp path (version-skew safe).
17956
+ ...args.v2Envelope ?? {}
17549
17957
  };
17550
17958
  if (queuePendingMeshCoordinatorEvent(pendingEvent)) {
17551
17959
  LOG.info("MeshEvents", `Queued ${args.event} for coordinator (mesh ${args.meshId}${workerCoordinatorDaemonId ? `, coordinator daemon ${workerCoordinatorDaemonId}` : ""}${workerCoordinatorSessionId ? `, coordinator session ${workerCoordinatorSessionId}` : ""})`);
@@ -17658,7 +18066,12 @@ function handleMeshForwardEvent(components, payload) {
17658
18066
  nodeId,
17659
18067
  nodeLabel,
17660
18068
  event: eventName,
17661
- metadataEvent: buildRelayMetadataEvent(payload)
18069
+ metadataEvent: buildRelayMetadataEvent(payload),
18070
+ // T4 (B3b): restore the v2 envelope carried at the top level of the relayed flat
18071
+ // payload (buildForwardPayloadFromPending → serializeV2EnvelopeToWire) so the
18072
+ // re-queue preserves the original eventId (idempotency) and unicast routing rather
18073
+ // than re-stamping a fresh v1/broadcast event. Empty for a v1 relay (version-skew safe).
18074
+ v2Envelope: readV2EnvelopeFromWire(payload)
17662
18075
  });
17663
18076
  }
17664
18077
  function enqueueCoordinatorForwardPush(coordinatorDaemonId, run) {
@@ -17953,6 +18366,21 @@ function resolveAckedDeathDeadlineMs() {
17953
18366
  function resolveAckedTranscriptFastTrackGraceMs() {
17954
18367
  return resolveTunedReconcileMs("MESH_INFLIGHT_ACKED_TRANSCRIPT_FASTTRACK_GRACE_MS", 4e4, 0, 5 * 6e4);
17955
18368
  }
18369
+ function getMeshV2BackstopCounters() {
18370
+ return { ...meshV2BackstopCounters };
18371
+ }
18372
+ function meshProtocolV2EnforceOn() {
18373
+ const raw = process.env.MESH_PROTOCOL_V2_ENFORCE;
18374
+ if (typeof raw !== "string") return false;
18375
+ const v = raw.trim().toLowerCase();
18376
+ return v === "1" || v === "true" || v === "on" || v === "yes";
18377
+ }
18378
+ function recordBackstopFire(kind, detail) {
18379
+ meshV2BackstopCounters[kind]++;
18380
+ if (meshProtocolV2EnforceOn()) {
18381
+ 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.`);
18382
+ }
18383
+ }
17956
18384
  function inFlightSynthKey(meshId, taskId) {
17957
18385
  return `${meshId}::${taskId}`;
17958
18386
  }
@@ -18867,6 +19295,7 @@ async function reconcileUnterminatedDirectDispatches(components, mesh, selfIds,
18867
19295
  };
18868
19296
  const synthKey = inFlightSynthKey(mesh.id, taskId);
18869
19297
  const isAcked = dispatch.status === "acked";
19298
+ let backstopKind;
18870
19299
  let payload = null;
18871
19300
  let readFailed = false;
18872
19301
  try {
@@ -18931,6 +19360,7 @@ async function reconcileUnterminatedDirectDispatches(components, mesh, selfIds,
18931
19360
  const idleHeldMs = nowMs - idleSinceMs;
18932
19361
  if (idleHeldMs >= fastTrackGraceMs) {
18933
19362
  fastTrackReady = true;
19363
+ backstopKind = "ackedHoldFastTrackFired";
18934
19364
  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.`);
18935
19365
  }
18936
19366
  } else if (holdState?.transcriptIdleSinceMs !== void 0) {
@@ -18941,6 +19371,7 @@ async function reconcileUnterminatedDirectDispatches(components, mesh, selfIds,
18941
19371
  continue;
18942
19372
  }
18943
19373
  if (!fastTrackReady) {
19374
+ backstopKind = "ackedHoldDeathDeadlineFired";
18944
19375
  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).`);
18945
19376
  }
18946
19377
  }
@@ -18985,6 +19416,7 @@ async function reconcileUnterminatedDirectDispatches(components, mesh, selfIds,
18985
19416
  source: "daemon_reconcile_transcript_completion"
18986
19417
  });
18987
19418
  if (result.reconciled) {
19419
+ recordBackstopFire(backstopKind ?? "phase4SynthesisFired", `task ${taskId} on node ${nodeId} (mesh ${mesh.id}), kind=${result.kind}`);
18988
19420
  LOG.info("MeshReconcile", `Synthesized missing completion (${result.kind}) for task ${taskId} on node ${nodeId} (mesh ${mesh.id})`);
18989
19421
  }
18990
19422
  } catch (e) {
@@ -19085,7 +19517,14 @@ function buildForwardPayloadFromPending(event) {
19085
19517
  ...(() => {
19086
19518
  const tid = readNonEmptyString2(metadata.taskId) || readNonEmptyString2(metadata.meshActiveTaskId);
19087
19519
  return tid ? { taskId: tid } : {};
19088
- })()
19520
+ })(),
19521
+ // T4 (B3b): carry the v2 envelope (protocolVersion/eventId/scope/dispatchedBy/
19522
+ // intendedFor) across the P2P relay boundary at the TOP LEVEL. These live on the
19523
+ // pending event itself, not inside metadataEvent, so without this the remote pull
19524
+ // re-queue would re-stamp a fresh eventId — breaking cross-machine idempotency and
19525
+ // downgrading the relayed completion to v1 broadcast routing. Spread LAST so the
19526
+ // authoritative envelope always wins over any stale key the metadata spread carried.
19527
+ ...serializeV2EnvelopeToWire(event)
19089
19528
  };
19090
19529
  }
19091
19530
  function setupMeshReconcileLoop(components) {
@@ -19107,7 +19546,7 @@ function setupMeshReconcileLoop(components) {
19107
19546
  }
19108
19547
  };
19109
19548
  }
19110
- 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;
19549
+ 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;
19111
19550
  var init_mesh_reconcile_loop = __esm({
19112
19551
  "src/mesh/mesh-reconcile-loop.ts"() {
19113
19552
  "use strict";
@@ -19135,6 +19574,14 @@ var init_mesh_reconcile_loop = __esm({
19135
19574
  ACKED_DEATH_CONSECUTIVE_READ_FAILURES = 3;
19136
19575
  inFlightAckedHoldState = /* @__PURE__ */ new Map();
19137
19576
  rehydratedHoldMeshes = /* @__PURE__ */ new Set();
19577
+ meshV2BackstopCounters = {
19578
+ /** PHASE-4 transcript synthesis actually reconciled a missing completion. */
19579
+ phase4SynthesisFired: 0,
19580
+ /** Acked-hold transcript fast-track promoted a synth ahead of the death deadline. */
19581
+ ackedHoldFastTrackFired: 0,
19582
+ /** Acked-hold death-deadline backstop released a held synth (the 8-min net). */
19583
+ ackedHoldDeathDeadlineFired: 0
19584
+ };
19138
19585
  coordinatorModalParkState = /* @__PURE__ */ new Map();
19139
19586
  heldEventLedgerRecorded = /* @__PURE__ */ new Set();
19140
19587
  ASSIGNED_STRANDED_DEADLINE_MS = 5 * 6e4;
@@ -19154,14 +19601,19 @@ __export(mesh_events_exports, {
19154
19601
  __resetMeshWorkspaceCacheForTests: () => __resetMeshWorkspaceCacheForTests,
19155
19602
  clearPendingMeshCoordinatorEvents: () => clearPendingMeshCoordinatorEvents,
19156
19603
  drainPendingMeshCoordinatorEvents: () => drainPendingMeshCoordinatorEvents,
19604
+ getMeshV2BackstopCounters: () => getMeshV2BackstopCounters,
19605
+ getMeshV2DrainCounters: () => getMeshV2DrainCounters,
19157
19606
  getPendingMeshCoordinatorEvents: () => getPendingMeshCoordinatorEvents,
19158
19607
  handleMeshForwardEvent: () => handleMeshForwardEvent,
19159
19608
  isMeshCoordinatorEvent: () => isMeshCoordinatorEvent,
19609
+ isMeshProtocolV2EnforceEnabled: () => isMeshProtocolV2EnforceEnabled,
19160
19610
  isSessionActivelyGenerating: () => isSessionActivelyGenerating,
19161
19611
  queuePendingMeshCoordinatorEvent: () => queuePendingMeshCoordinatorEvent,
19612
+ readV2EnvelopeFromWire: () => readV2EnvelopeFromWire,
19162
19613
  reconcileDirectDispatchCompletionFromTranscript: () => reconcileDirectDispatchCompletionFromTranscript,
19163
19614
  resolveCoordinatorDrainDeliverability: () => resolveCoordinatorDrainDeliverability,
19164
19615
  runMeshReconcileTick: () => runMeshReconcileTick,
19616
+ serializeV2EnvelopeToWire: () => serializeV2EnvelopeToWire,
19165
19617
  setupMeshEventForwarding: () => setupMeshEventForwarding,
19166
19618
  setupMeshReconcileLoop: () => setupMeshReconcileLoop,
19167
19619
  shouldHoldPendingDrainForBusyLocalCoordinator: () => shouldHoldPendingDrainForBusyLocalCoordinator,
@@ -25501,7 +25953,7 @@ var defaultSnapshotStore = createGitSnapshotStore({
25501
25953
  getStatus: (workspace) => getGitRepoStatus(workspace),
25502
25954
  getDiffSummary: (workspace) => getGitDiffSummary(workspace)
25503
25955
  });
25504
- function createDefaultGitCommandServices() {
25956
+ function createDefaultGitCommandServices(overrides) {
25505
25957
  return {
25506
25958
  getStatus: ({ workspace, refreshUpstream }) => getGitRepoStatus(workspace, { refreshUpstream }),
25507
25959
  getDiffSummary: ({ workspace, base }) => getGitDiffSummary(workspace, base ? { baseRef: base } : {}),
@@ -25519,7 +25971,8 @@ function createDefaultGitCommandServices() {
25519
25971
  stashPop: async ({ workspace, stashRef }) => gitStashPop(workspace, stashRef),
25520
25972
  checkoutFiles: async ({ workspace, paths }) => gitCheckoutFiles(workspace, paths),
25521
25973
  getRemoteUrl: async ({ workspace, remote = "origin" }) => gitGetRemoteUrl(workspace, remote),
25522
- push: async ({ workspace, remote = "origin", branch, setUpstream = false }) => gitPush(workspace, remote, branch, setUpstream)
25974
+ push: async ({ workspace, remote = "origin", branch, setUpstream = false }) => gitPush(workspace, remote, branch, setUpstream),
25975
+ ...overrides?.getReporterProviderVersions ? { getReporterProviderVersions: overrides.getReporterProviderVersions } : {}
25523
25976
  };
25524
25977
  }
25525
25978
  var defaultGitCommandServices = createDefaultGitCommandServices();
@@ -25606,12 +26059,23 @@ async function handleGitCommand(command, args, services = defaultGitCommandServi
25606
26059
  return void 0;
25607
26060
  }
25608
26061
  })();
26062
+ const reporterVersions = (() => {
26063
+ try {
26064
+ return services.getReporterProviderVersions?.() ?? {};
26065
+ } catch {
26066
+ return {};
26067
+ }
26068
+ })();
26069
+ const reporterProviderVersions = reporterVersions.providerVersions && Object.keys(reporterVersions.providerVersions).length > 0 ? reporterVersions.providerVersions : void 0;
26070
+ const reporterDaemonBuildVersion = typeof reporterVersions.daemonBuildVersion === "string" && reporterVersions.daemonBuildVersion.trim() ? reporterVersions.daemonBuildVersion.trim() : void 0;
25609
26071
  return {
25610
26072
  success: true,
25611
26073
  status,
25612
26074
  reporterPlatform: process.platform,
25613
26075
  reporterArch: process.arch,
25614
- ...reporterMachineNickname ? { reporterMachineNickname } : {}
26076
+ ...reporterMachineNickname ? { reporterMachineNickname } : {},
26077
+ ...reporterProviderVersions ? { reporterProviderVersions } : {},
26078
+ ...reporterDaemonBuildVersion ? { reporterDaemonBuildVersion } : {}
25615
26079
  };
25616
26080
  }
25617
26081
  case "git_diff_summary": {
@@ -43049,10 +43513,10 @@ var CliProviderInstance = class _CliProviderInstance {
43049
43513
  if (buttonIndex < 0 || !hasReliableConsentAnchor) {
43050
43514
  return autoApproveActive;
43051
43515
  }
43516
+ const affirmativeAnchor = normalizeApprovalLabel(buttonLabel);
43052
43517
  const modalSignature = [
43053
43518
  typeof modal?.message === "string" ? modal.message.trim() : "",
43054
- buttons.join("|"),
43055
- buttonIndex
43519
+ affirmativeAnchor
43056
43520
  ].join("::");
43057
43521
  const approvalEntrySeq = typeof adapterStatus?.approvalEntrySeq === "number" ? adapterStatus.approvalEntrySeq : 0;
43058
43522
  const busySignature = `${approvalEntrySeq}::${modalSignature}`;
@@ -52664,7 +53128,12 @@ var meshEventsHandlers = {
52664
53128
  return { success: true, events: [], heldForBusyLocalCoordinator: true, hasLiveCliCoordinator };
52665
53129
  }
52666
53130
  const events = drainPendingMeshCoordinatorEvents(meshId || void 0, coordinatorDaemonId);
52667
- return { success: true, events, hasLiveCliCoordinator, ...selfCoordinatorInboxRead ? { surfacedForSelfCoordinator: true } : {} };
53131
+ const meshProtocolV2Counters = {
53132
+ enforce: isMeshProtocolV2EnforceEnabled(),
53133
+ drain: { ...getMeshV2DrainCounters() },
53134
+ backstop: { ...getMeshV2BackstopCounters() }
53135
+ };
53136
+ return { success: true, events, hasLiveCliCoordinator, meshProtocolV2Counters, ...selfCoordinatorInboxRead ? { surfacedForSelfCoordinator: true } : {} };
52668
53137
  },
52669
53138
  interactive_prompt_response: async (ctx, args) => {
52670
53139
  const sessionId = typeof args?.targetSessionId === "string" && args.targetSessionId.trim() ? args.targetSessionId.trim() : typeof args?.sessionId === "string" && args.sessionId.trim() ? args.sessionId.trim() : "";
@@ -53496,6 +53965,12 @@ var meshStatusHandlers = {
53496
53965
  machineStatus: node.machineStatus,
53497
53966
  health: "unknown",
53498
53967
  providers: node.providers || [],
53968
+ // T7: surface self-healed provider versions + build version (from the
53969
+ // git_status envelope, persisted on the node) so the coordinator/UI can
53970
+ // spot a provider-version skew across nodes. Additive; omitted when a
53971
+ // node has never reported them.
53972
+ ...node.reportedProviderVersions && typeof node.reportedProviderVersions === "object" ? { providerVersions: node.reportedProviderVersions } : {},
53973
+ ...typeof node.reportedDaemonBuildVersion === "string" && node.reportedDaemonBuildVersion ? { daemonBuildVersion: node.reportedDaemonBuildVersion } : {},
53499
53974
  providerPriority,
53500
53975
  activeSessions: [],
53501
53976
  activeSessionDetails: [],
@@ -53684,6 +54159,11 @@ var meshStatusHandlers = {
53684
54159
  const callerCoordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : ctx.deps.statusInstanceId || void 0;
53685
54160
  const pendingCoordinatorEvents = getPendingMeshCoordinatorEvents(meshId, callerCoordinatorDaemonId);
53686
54161
  const unroutableDeliveries = getRecentUnroutableDeliveries();
54162
+ const meshProtocolV2Counters = {
54163
+ enforce: isMeshProtocolV2EnforceEnabled(),
54164
+ drain: { ...getMeshV2DrainCounters() },
54165
+ backstop: { ...getMeshV2BackstopCounters() }
54166
+ };
53687
54167
  const previewFreshness = (() => {
53688
54168
  const localRepoRoot = nodeStatuses.map((node) => readStringValue(node?.git?.repoRoot, node?.repoRoot, node?.workspace)).find((candidate) => !!candidate && fs27.existsSync(candidate));
53689
54169
  return localRepoRoot ? buildPreviewFreshness(localRepoRoot) : void 0;
@@ -53773,6 +54253,7 @@ var meshStatusHandlers = {
53773
54253
  ...historicalSessions ? { historicalSessions } : {},
53774
54254
  ...pendingCoordinatorEvents.length > 0 ? { pendingCoordinatorEvents } : {},
53775
54255
  ...unroutableDeliveries.length > 0 ? { unroutableDeliveries } : {},
54256
+ meshProtocolV2Counters,
53776
54257
  activeRefineJobs: Array.from(ctx.runningRefineJobs.values()).filter((job) => job.meshId === meshId).map((job) => ({
53777
54258
  jobId: job.jobId,
53778
54259
  nodeId: job.targetNodeId,
@@ -53782,12 +54263,13 @@ var meshStatusHandlers = {
53782
54263
  targetCoordinatorDaemonId: job.targetCoordinatorDaemonId
53783
54264
  }))
53784
54265
  };
53785
- const { pendingCoordinatorEvents: _pendingCoordinatorEvents, unroutableDeliveries: _unroutableDeliveries, ...cacheableStatusResult } = statusResult;
54266
+ const { pendingCoordinatorEvents: _pendingCoordinatorEvents, unroutableDeliveries: _unroutableDeliveries, meshProtocolV2Counters: _meshProtocolV2Counters, ...cacheableStatusResult } = statusResult;
53786
54267
  const rememberedStatus = verboseMissions ? cacheableStatusResult : ctx.rememberAggregateMeshStatus(meshId, cacheableStatusResult, refreshReason);
53787
54268
  const returnedStatus = {
53788
54269
  ...rememberedStatus,
53789
54270
  ...pendingCoordinatorEvents.length > 0 ? { pendingCoordinatorEvents } : {},
53790
- ...unroutableDeliveries.length > 0 ? { unroutableDeliveries } : {}
54271
+ ...unroutableDeliveries.length > 0 ? { unroutableDeliveries } : {},
54272
+ meshProtocolV2Counters
53791
54273
  };
53792
54274
  logRepoMeshStatusDebug("return_live", {
53793
54275
  meshId,
@@ -54269,7 +54751,13 @@ function buildLivePeerGitConnection(connection, timestamp = (/* @__PURE__ */ new
54269
54751
  }
54270
54752
  function recordInlineMeshDirectGitTruth(node, git, source) {
54271
54753
  if (!node || typeof node !== "object" || Array.isArray(node)) {
54272
- return { reporterPlatform: null, reporterArch: null, reporterMachineNickname: null };
54754
+ return {
54755
+ reporterPlatform: null,
54756
+ reporterArch: null,
54757
+ reporterMachineNickname: null,
54758
+ reporterProviderVersions: null,
54759
+ reporterDaemonBuildVersion: null
54760
+ };
54273
54761
  }
54274
54762
  const checkedAt = readNumberValue(git.lastCheckedAt) ?? Date.now();
54275
54763
  const updatedAt = new Date(checkedAt).toISOString();
@@ -54296,7 +54784,28 @@ function recordInlineMeshDirectGitTruth(node, git, source) {
54296
54784
  if (reporterArch) node.reportedArch = reporterArch;
54297
54785
  const reporterMachineNickname = readStringValue(git.reporterMachineNickname) ?? null;
54298
54786
  if (reporterMachineNickname) node.machineNickname = reporterMachineNickname;
54299
- return { reporterPlatform, reporterArch, reporterMachineNickname };
54787
+ const reporterProviderVersions = readProviderVersionsRecord(git.reporterProviderVersions);
54788
+ if (reporterProviderVersions) node.reportedProviderVersions = reporterProviderVersions;
54789
+ const reporterDaemonBuildVersion = readStringValue(git.reporterDaemonBuildVersion) ?? null;
54790
+ if (reporterDaemonBuildVersion) node.reportedDaemonBuildVersion = reporterDaemonBuildVersion;
54791
+ return {
54792
+ reporterPlatform,
54793
+ reporterArch,
54794
+ reporterMachineNickname,
54795
+ reporterProviderVersions,
54796
+ reporterDaemonBuildVersion
54797
+ };
54798
+ }
54799
+ function readProviderVersionsRecord(value) {
54800
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
54801
+ const out = {};
54802
+ for (const [key2, raw] of Object.entries(value)) {
54803
+ if (typeof key2 !== "string" || !key2.trim()) continue;
54804
+ const version = typeof raw === "string" ? raw.trim() : "";
54805
+ if (!version) continue;
54806
+ out[key2] = version;
54807
+ }
54808
+ return Object.keys(out).length > 0 ? out : null;
54300
54809
  }
54301
54810
  function stampNodeReporterPlatform(node, platform10, arch2) {
54302
54811
  if (!node || typeof node !== "object" || Array.isArray(node)) return;
@@ -54320,8 +54829,18 @@ function persistNodeReporterPlatform(meshSource, mesh, nodeId, reporter) {
54320
54829
  const reportedPlatform = reporter.reporterPlatform ?? void 0;
54321
54830
  const reportedArch = reporter.reporterArch ?? void 0;
54322
54831
  const reportedMachineNickname = reporter.reporterMachineNickname ?? void 0;
54323
- if (!reportedPlatform && !reportedArch && !reportedMachineNickname) return;
54324
- void Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports)).then(({ updateNode: updateNode2 }) => updateNode2(meshId, nodeId, { reportedPlatform, reportedArch, reportedMachineNickname })).catch(() => {
54832
+ const reportedProviderVersions = reporter.reporterProviderVersions ?? void 0;
54833
+ const reportedDaemonBuildVersion = reporter.reporterDaemonBuildVersion ?? void 0;
54834
+ if (!reportedPlatform && !reportedArch && !reportedMachineNickname && !reportedProviderVersions && !reportedDaemonBuildVersion) {
54835
+ return;
54836
+ }
54837
+ void Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports)).then(({ updateNode: updateNode2 }) => updateNode2(meshId, nodeId, {
54838
+ reportedPlatform,
54839
+ reportedArch,
54840
+ reportedMachineNickname,
54841
+ reportedProviderVersions,
54842
+ reportedDaemonBuildVersion
54843
+ })).catch(() => {
54325
54844
  });
54326
54845
  }
54327
54846
  function buildCachedInlineMeshGitStatus(node) {
@@ -54978,6 +55497,10 @@ async function probeRemoteMeshGitStatus(args) {
54978
55497
  if (reporterPlatform) git.reporterPlatform = reporterPlatform;
54979
55498
  if (reporterArch) git.reporterArch = reporterArch;
54980
55499
  if (reporterMachineNickname) git.reporterMachineNickname = reporterMachineNickname;
55500
+ const reporterProviderVersions = readProviderVersionsRecord(remoteResult?.reporterProviderVersions);
55501
+ if (reporterProviderVersions) git.reporterProviderVersions = reporterProviderVersions;
55502
+ const reporterDaemonBuildVersion = readStringValue(remoteResult?.reporterDaemonBuildVersion);
55503
+ if (reporterDaemonBuildVersion) git.reporterDaemonBuildVersion = reporterDaemonBuildVersion;
54981
55504
  return git;
54982
55505
  }
54983
55506
  var MESH_DIRECT_PROBE_MAX_RETRIES = 2;
@@ -66919,6 +67442,7 @@ function launchIDE(ide, workspacePath) {
66919
67442
 
66920
67443
  // src/boot/daemon-lifecycle.ts
66921
67444
  init_cli_detector();
67445
+ init_build_info();
66922
67446
 
66923
67447
  // src/sessions/registry.ts
66924
67448
  var SessionRegistry = class {
@@ -67120,7 +67644,19 @@ async function initDaemonComponents(config) {
67120
67644
  providerLoader,
67121
67645
  instanceManager,
67122
67646
  sessionRegistry,
67123
- gitCommandServices: createDefaultGitCommandServices(),
67647
+ gitCommandServices: createDefaultGitCommandServices({
67648
+ // T7: fold this daemon's cached provider versions + build version onto the
67649
+ // git_status envelope so the mesh coordinator self-heals each node's
67650
+ // providerVersions. Non-blocking: reads a TTL cache, lazily refreshed.
67651
+ getReporterProviderVersions: () => {
67652
+ const providerVersions = getCachedProviderVersions(providerLoader);
67653
+ const daemonBuildVersion = getDaemonBuildInfo().version;
67654
+ return {
67655
+ ...Object.keys(providerVersions).length > 0 ? { providerVersions } : {},
67656
+ ...daemonBuildVersion && daemonBuildVersion !== "unknown" ? { daemonBuildVersion } : {}
67657
+ };
67658
+ }
67659
+ }),
67124
67660
  onProviderSettingChanged: async (providerType) => {
67125
67661
  await refreshProviderAvailability(providerType);
67126
67662
  config.onStatusChange?.();
@@ -67842,6 +68378,7 @@ export {
67842
68378
  readLedgerSliceFromStore,
67843
68379
  readMeshCompletionSummary,
67844
68380
  readOperatingNotes,
68381
+ readV2EnvelopeFromWire,
67845
68382
  reconcileDirectDispatchCompletionFromTranscript,
67846
68383
  recordCompletionConflict,
67847
68384
  recordDebugTrace,
@@ -67882,6 +68419,7 @@ export {
67882
68419
  runMeshWorktreeBootstrap,
67883
68420
  saveConfig,
67884
68421
  saveState,
68422
+ serializeV2EnvelopeToWire,
67885
68423
  setDebugRuntimeConfig,
67886
68424
  setLogLevel,
67887
68425
  setMagiKindPanel,