@adhdev/daemon-standalone 1.0.29-rc.3 → 1.0.29-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +315 -23
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/public/assets/{index-BnsnvtGz.js → index-Cono379Q.js} +46 -46
- package/public/assets/{index-Jy4W-yh-.css → index-DaANjDZS.css} +1 -1
- package/public/index.html +2 -2
- package/vendor/mcp-server/index.js +2 -0
- package/vendor/mcp-server/index.js.map +1 -1
package/dist/index.js
CHANGED
|
@@ -33311,10 +33311,10 @@ var require_dist3 = __commonJS({
|
|
|
33311
33311
|
}
|
|
33312
33312
|
function getDaemonBuildInfo() {
|
|
33313
33313
|
if (cached2) return cached2;
|
|
33314
|
-
const commit = readInjected(true ? "
|
|
33315
|
-
const commitShort = readInjected(true ? "
|
|
33316
|
-
const version2 = readInjected(true ? "1.0.29-rc.
|
|
33317
|
-
const builtAt = readInjected(true ? "2026-08-
|
|
33314
|
+
const commit = readInjected(true ? "df91f2d3a3bded96267f00003d1ee8e27dda0512" : void 0) ?? "unknown";
|
|
33315
|
+
const commitShort = readInjected(true ? "df91f2d3" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
33316
|
+
const version2 = readInjected(true ? "1.0.29-rc.4" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
33317
|
+
const builtAt = readInjected(true ? "2026-08-02T00:25:39.936Z" : void 0);
|
|
33318
33318
|
cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
|
|
33319
33319
|
return cached2;
|
|
33320
33320
|
}
|
|
@@ -36258,6 +36258,7 @@ ${error48.message || ""}`;
|
|
|
36258
36258
|
resolveScopedMeshId: () => resolveScopedMeshId,
|
|
36259
36259
|
setDifficultyBrains: () => setDifficultyBrains,
|
|
36260
36260
|
setMagiKindPanel: () => setMagiKindPanel,
|
|
36261
|
+
setMeshHostPin: () => setMeshHostPin,
|
|
36261
36262
|
tokenIdForManualPairing: () => tokenIdForManualPairing,
|
|
36262
36263
|
updateMesh: () => updateMesh,
|
|
36263
36264
|
updateNode: () => updateNode
|
|
@@ -36424,7 +36425,11 @@ ${error48.message || ""}`;
|
|
|
36424
36425
|
defaultBranch: opts.defaultBranch,
|
|
36425
36426
|
policy: mergeMeshPolicy(void 0, opts.policy),
|
|
36426
36427
|
coordinator: opts.coordinator || {},
|
|
36427
|
-
meshHost: opts.meshHost ||
|
|
36428
|
+
meshHost: opts.meshHost || (() => {
|
|
36429
|
+
const base = createDefaultMeshHostMetadata();
|
|
36430
|
+
const creatingDaemonId = typeof opts.hostDaemonId === "string" ? opts.hostDaemonId.trim() : "";
|
|
36431
|
+
return creatingDaemonId ? { ...base, hostDaemonId: creatingDaemonId } : base;
|
|
36432
|
+
})(),
|
|
36428
36433
|
nodes: [],
|
|
36429
36434
|
createdAt: now,
|
|
36430
36435
|
updatedAt: now
|
|
@@ -36610,6 +36615,86 @@ ${error48.message || ""}`;
|
|
|
36610
36615
|
saveMeshConfig(config2);
|
|
36611
36616
|
return { accepted: true, mesh, meshHost: mesh.meshHost, node, tokenId: validation.tokenId };
|
|
36612
36617
|
}
|
|
36618
|
+
function setMeshHostPin(meshId, opts) {
|
|
36619
|
+
const config2 = loadMeshConfig();
|
|
36620
|
+
const mesh = config2.meshes.find((m) => m.id === meshId);
|
|
36621
|
+
if (!mesh) return void 0;
|
|
36622
|
+
const hostDaemonId = typeof opts.hostDaemonId === "string" ? opts.hostDaemonId.trim() : "";
|
|
36623
|
+
const hostNodeId = typeof opts.hostNodeId === "string" ? opts.hostNodeId.trim() : "";
|
|
36624
|
+
const previous = mesh.meshHost || createDefaultMeshHostMetadata();
|
|
36625
|
+
if (!hostDaemonId && !hostNodeId) {
|
|
36626
|
+
return {
|
|
36627
|
+
mesh,
|
|
36628
|
+
meshHost: previous,
|
|
36629
|
+
applied: false,
|
|
36630
|
+
reason: "invalid_host_daemon_id",
|
|
36631
|
+
...previous.hostDaemonId ? { hostDaemonId: previous.hostDaemonId } : {},
|
|
36632
|
+
...previous.hostNodeId ? { hostNodeId: previous.hostNodeId } : {}
|
|
36633
|
+
};
|
|
36634
|
+
}
|
|
36635
|
+
if (previous.role === "member") {
|
|
36636
|
+
return {
|
|
36637
|
+
mesh,
|
|
36638
|
+
meshHost: previous,
|
|
36639
|
+
applied: false,
|
|
36640
|
+
reason: "not_host_role",
|
|
36641
|
+
...previous.hostDaemonId ? { hostDaemonId: previous.hostDaemonId } : {},
|
|
36642
|
+
...previous.hostNodeId ? { hostNodeId: previous.hostNodeId } : {}
|
|
36643
|
+
};
|
|
36644
|
+
}
|
|
36645
|
+
const existingDaemonId = typeof previous.hostDaemonId === "string" ? previous.hostDaemonId.trim() : "";
|
|
36646
|
+
if (existingDaemonId && !opts.force) {
|
|
36647
|
+
const sameHost = hostDaemonId ? daemonIdsEquivalent(existingDaemonId, hostDaemonId) : true;
|
|
36648
|
+
if (!sameHost) {
|
|
36649
|
+
return {
|
|
36650
|
+
mesh,
|
|
36651
|
+
meshHost: previous,
|
|
36652
|
+
applied: false,
|
|
36653
|
+
reason: "host_already_pinned",
|
|
36654
|
+
hostDaemonId: existingDaemonId,
|
|
36655
|
+
...previous.hostNodeId ? { hostNodeId: previous.hostNodeId } : {}
|
|
36656
|
+
};
|
|
36657
|
+
}
|
|
36658
|
+
const existingNodeId = typeof previous.hostNodeId === "string" ? previous.hostNodeId.trim() : "";
|
|
36659
|
+
if (!hostNodeId || hostNodeId === existingNodeId) {
|
|
36660
|
+
return {
|
|
36661
|
+
mesh,
|
|
36662
|
+
meshHost: previous,
|
|
36663
|
+
applied: false,
|
|
36664
|
+
reason: "already_pinned_same",
|
|
36665
|
+
hostDaemonId: existingDaemonId,
|
|
36666
|
+
...existingNodeId ? { hostNodeId: existingNodeId } : {}
|
|
36667
|
+
};
|
|
36668
|
+
}
|
|
36669
|
+
}
|
|
36670
|
+
const now = opts.now || (/* @__PURE__ */ new Date()).toISOString();
|
|
36671
|
+
const effectiveDaemonId = hostDaemonId || existingDaemonId;
|
|
36672
|
+
mesh.meshHost = {
|
|
36673
|
+
...previous,
|
|
36674
|
+
role: "host",
|
|
36675
|
+
...effectiveDaemonId ? { hostDaemonId: effectiveDaemonId } : {},
|
|
36676
|
+
...hostNodeId ? { hostNodeId } : previous.hostNodeId ? { hostNodeId: previous.hostNodeId } : {},
|
|
36677
|
+
...opts.hostAddress?.trim() ? { hostAddress: opts.hostAddress.trim() } : {}
|
|
36678
|
+
};
|
|
36679
|
+
const hostNode = hostNodeId ? mesh.nodes.find((n) => n.id === hostNodeId) : effectiveDaemonId ? mesh.nodes.find((n) => n.daemonId && daemonIdsEquivalent(n.daemonId, effectiveDaemonId)) : void 0;
|
|
36680
|
+
if (hostNode) {
|
|
36681
|
+
for (const node of mesh.nodes) {
|
|
36682
|
+
if (node.role === "host" && node !== hostNode) node.role = void 0;
|
|
36683
|
+
}
|
|
36684
|
+
hostNode.role = "host";
|
|
36685
|
+
if (!mesh.meshHost.hostNodeId) mesh.meshHost.hostNodeId = hostNode.id;
|
|
36686
|
+
}
|
|
36687
|
+
mesh.updatedAt = now;
|
|
36688
|
+
saveMeshConfig(config2);
|
|
36689
|
+
return {
|
|
36690
|
+
mesh,
|
|
36691
|
+
meshHost: mesh.meshHost,
|
|
36692
|
+
applied: true,
|
|
36693
|
+
reason: "pinned",
|
|
36694
|
+
...mesh.meshHost.hostDaemonId ? { hostDaemonId: mesh.meshHost.hostDaemonId } : {},
|
|
36695
|
+
...mesh.meshHost.hostNodeId ? { hostNodeId: mesh.meshHost.hostNodeId } : {}
|
|
36696
|
+
};
|
|
36697
|
+
}
|
|
36613
36698
|
function markMeshHostPairingJoined(meshId, opts) {
|
|
36614
36699
|
const config2 = loadMeshConfig();
|
|
36615
36700
|
const mesh = config2.meshes.find((m) => m.id === meshId);
|
|
@@ -36670,6 +36755,12 @@ ${error48.message || ""}`;
|
|
|
36670
36755
|
worktreeBootstrap: opts.worktreeBootstrap,
|
|
36671
36756
|
role: opts.role
|
|
36672
36757
|
};
|
|
36758
|
+
const pinnedHostDaemonId = typeof mesh.meshHost?.hostDaemonId === "string" ? mesh.meshHost.hostDaemonId.trim() : "";
|
|
36759
|
+
const anchorMissing = !(typeof mesh.meshHost?.hostNodeId === "string" && mesh.meshHost.hostNodeId.trim());
|
|
36760
|
+
if (!node.role && anchorMissing && pinnedHostDaemonId && mesh.meshHost?.role !== "member" && node.daemonId && daemonIdsEquivalent(node.daemonId, pinnedHostDaemonId) && !mesh.nodes.some((n) => n.role === "host")) {
|
|
36761
|
+
node.role = "host";
|
|
36762
|
+
mesh.meshHost = { ...mesh.meshHost || createDefaultMeshHostMetadata(), hostNodeId: node.id };
|
|
36763
|
+
}
|
|
36673
36764
|
mesh.nodes.push(node);
|
|
36674
36765
|
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
36675
36766
|
saveMeshConfig(config2);
|
|
@@ -39392,9 +39483,20 @@ Next step: ${nextStep}`;
|
|
|
39392
39483
|
}
|
|
39393
39484
|
continue;
|
|
39394
39485
|
}
|
|
39486
|
+
if (validated.intendedFor && !validated.intendedFor.sessionId && daemonIdsEquivalent(validated.intendedFor.daemonId, drainer.daemonId)) {
|
|
39487
|
+
const liveSessions = ctx.countLiveCoordinatorSessions?.(validated.intendedFor.daemonId) ?? 0;
|
|
39488
|
+
if (liveSessions > 1) {
|
|
39489
|
+
warnV2Once(
|
|
39490
|
+
`${event.meshId}::${eventId}::ambiguous-unicast`,
|
|
39491
|
+
`v2 unicast ${event.event} on mesh ${event.meshId} carries NO coordinator session but ${liveSessions} coordinator sessions are live on ${validated.intendedFor.daemonId} \u2014 delivery is first-come-first-served and may reach the wrong coordinator. Delivered to ${coordinatorIdentityKey(drainer)}. The EMITTING path must stamp targetCoordinatorSessionId.`
|
|
39492
|
+
);
|
|
39493
|
+
bump("v2AmbiguousUnicastDelivered");
|
|
39494
|
+
}
|
|
39495
|
+
}
|
|
39395
39496
|
if (validated.intendedFor && identityDeliversTo(validated.intendedFor, drainer)) {
|
|
39396
39497
|
ctx.batchSeen.add(eventId);
|
|
39397
39498
|
bump("v2Delivered");
|
|
39499
|
+
LOG2.debug("MeshEventsV2", `unicast ${event.event} (mesh ${event.meshId}, eventId ${eventId}) delivered to ${coordinatorIdentityKey(drainer)}; intendedFor=${coordinatorIdentityKey(validated.intendedFor)}`);
|
|
39398
39500
|
kept.push(event);
|
|
39399
39501
|
continue;
|
|
39400
39502
|
}
|
|
@@ -39409,6 +39511,7 @@ Next step: ${nextStep}`;
|
|
|
39409
39511
|
kept.push(event);
|
|
39410
39512
|
continue;
|
|
39411
39513
|
}
|
|
39514
|
+
LOG2.debug("MeshEventsV2", `unicast ${event.event} (mesh ${event.meshId}, eventId ${eventId}) NOT delivered to ${coordinatorIdentityKey(drainer)}; intendedFor=${validated.intendedFor ? coordinatorIdentityKey(validated.intendedFor) : "none"} \u2014 left for its own drainer`);
|
|
39412
39515
|
bump("v2RoutedAway");
|
|
39413
39516
|
}
|
|
39414
39517
|
return kept;
|
|
@@ -39861,7 +39964,12 @@ Next step: ${nextStep}`;
|
|
|
39861
39964
|
try {
|
|
39862
39965
|
const store = MeshRuntimeStore.getInstance();
|
|
39863
39966
|
if (store.pendingEventCount(meshId) > 0) {
|
|
39864
|
-
|
|
39967
|
+
const drainedBy = drainer ? JSON.stringify(drainer) : null;
|
|
39968
|
+
for (const row of store.drainPendingEvents(
|
|
39969
|
+
meshId,
|
|
39970
|
+
daemonIds.length > 0 ? daemonIds : void 0,
|
|
39971
|
+
{ ...onlyEvents ? { onlyEvents } : {}, drainedBy }
|
|
39972
|
+
)) {
|
|
39865
39973
|
const event = row.payload;
|
|
39866
39974
|
if (event) pushUnique(event);
|
|
39867
39975
|
}
|
|
@@ -39900,7 +40008,8 @@ Next step: ${nextStep}`;
|
|
|
39900
40008
|
const routed = routeV2EventsForDrainer(merged, drainer, {
|
|
39901
40009
|
alreadyDrained: (eventId) => priorDrainedEventIds.has(eventId),
|
|
39902
40010
|
batchSeen: /* @__PURE__ */ new Set(),
|
|
39903
|
-
countMetrics: true
|
|
40011
|
+
countMetrics: true,
|
|
40012
|
+
...opts?.countLiveCoordinatorSessions ? { countLiveCoordinatorSessions: opts.countLiveCoordinatorSessions } : {}
|
|
39904
40013
|
});
|
|
39905
40014
|
return reconcilePendingMeshCoordinatorEvents(meshId, routed);
|
|
39906
40015
|
}
|
|
@@ -40120,6 +40229,11 @@ Next step: ${nextStep}`;
|
|
|
40120
40229
|
/** unicast events re-attributed to the drainer via daemon-core match (a
|
|
40121
40230
|
* coordinatorRunId change orphaned them). */
|
|
40122
40231
|
v2ReattributedToDrainer: 0,
|
|
40232
|
+
/** REFINE-EVENT-SESSION-SCOPED-UNICAST: unicast events delivered while addressed only
|
|
40233
|
+
* at DAEMON granularity (no sessionId in intendedFor) even though >1 coordinator
|
|
40234
|
+
* session was live on that daemon — i.e. delivered by race, not by address. Non-zero
|
|
40235
|
+
* here names an emit path that still fails to stamp targetCoordinatorSessionId. */
|
|
40236
|
+
v2AmbiguousUnicastDelivered: 0,
|
|
40123
40237
|
/** v1 (unversioned) events passed through as broadcast (rollout baseline). */
|
|
40124
40238
|
v1BroadcastAccepted: 0,
|
|
40125
40239
|
/** T6 enforce: v2 events that FAILED validation and were QUARANTINED (held back
|
|
@@ -41878,7 +41992,15 @@ Next step: ${nextStep}`;
|
|
|
41878
41992
|
event_id TEXT,
|
|
41879
41993
|
scope TEXT,
|
|
41880
41994
|
dispatched_by TEXT,
|
|
41881
|
-
intended_for TEXT
|
|
41995
|
+
intended_for TEXT,
|
|
41996
|
+
-- REFINE-EVENT-SESSION-SCOPED-UNICAST: WHO consumed this row. The ledger
|
|
41997
|
+
-- previously recorded only THAT an event was drained, never by which
|
|
41998
|
+
-- coordinator identity \u2014 so a mis-delivered unicast (a sibling session
|
|
41999
|
+
-- consuming another coordinator's event) left no evidence and had to be
|
|
42000
|
+
-- inferred. Written at drain time as the JSON-serialized drainer
|
|
42001
|
+
-- CoordinatorIdentity. NULL on rows drained before this column existed
|
|
42002
|
+
-- and on any drain whose caller passed no identity (daemon-level drain).
|
|
42003
|
+
drained_by TEXT
|
|
41882
42004
|
);
|
|
41883
42005
|
|
|
41884
42006
|
CREATE INDEX IF NOT EXISTS idx_mesh_pending_events_mesh_drained
|
|
@@ -42124,7 +42246,7 @@ Next step: ${nextStep}`;
|
|
|
42124
42246
|
this.db.exec(`ALTER TABLE mesh_missions ADD COLUMN close_candidate_emitted_at TEXT`);
|
|
42125
42247
|
}
|
|
42126
42248
|
const pendingCols = this.tableColumns("mesh_pending_events");
|
|
42127
|
-
for (const col of ["protocol_version", "event_id", "scope", "dispatched_by", "intended_for"]) {
|
|
42249
|
+
for (const col of ["protocol_version", "event_id", "scope", "dispatched_by", "intended_for", "drained_by"]) {
|
|
42128
42250
|
if (!pendingCols.has(col)) {
|
|
42129
42251
|
this.db.exec(`ALTER TABLE mesh_pending_events ADD COLUMN ${col} TEXT`);
|
|
42130
42252
|
}
|
|
@@ -43393,8 +43515,8 @@ Next step: ${nextStep}`;
|
|
|
43393
43515
|
const ids = rows.map((r) => r.id);
|
|
43394
43516
|
const now = Date.now();
|
|
43395
43517
|
this.db.prepare(
|
|
43396
|
-
`UPDATE mesh_pending_events SET drained = 1, drained_at = ? WHERE id IN (${ids.map(() => "?").join(",")})`
|
|
43397
|
-
).run(now, ...ids);
|
|
43518
|
+
`UPDATE mesh_pending_events SET drained = 1, drained_at = ?, drained_by = ? WHERE id IN (${ids.map(() => "?").join(",")})`
|
|
43519
|
+
).run(now, opts?.drainedBy ?? null, ...ids);
|
|
43398
43520
|
return rows.map((r) => ({
|
|
43399
43521
|
id: r.id,
|
|
43400
43522
|
event: r.event,
|
|
@@ -43428,6 +43550,30 @@ Next step: ${nextStep}`;
|
|
|
43428
43550
|
})()
|
|
43429
43551
|
}));
|
|
43430
43552
|
}
|
|
43553
|
+
/**
|
|
43554
|
+
* REFINE-EVENT-SESSION-SCOPED-UNICAST — drain attribution audit. Returns the most
|
|
43555
|
+
* recent pending-event rows for a mesh with WHO drained each one, so a suspected
|
|
43556
|
+
* mis-delivery ("my refine result went to another coordinator session") is answered
|
|
43557
|
+
* from the ledger instead of inferred from timing. `drainedBy` is the serialized
|
|
43558
|
+
* drainer CoordinatorIdentity, or null when the row is still queued, was drained
|
|
43559
|
+
* before this column existed, or was drained by a caller that passed no identity.
|
|
43560
|
+
*/
|
|
43561
|
+
recentDrainedPendingEvents(meshId, limit = 100) {
|
|
43562
|
+
const rows = this.db.prepare(
|
|
43563
|
+
`SELECT id, event, scope, intended_for, drained_by, drained, queued_at, drained_at
|
|
43564
|
+
FROM mesh_pending_events WHERE mesh_id = ? ORDER BY queued_at DESC LIMIT ?`
|
|
43565
|
+
).all(meshId, Math.max(1, limit));
|
|
43566
|
+
return rows.map((r) => ({
|
|
43567
|
+
id: r.id,
|
|
43568
|
+
event: r.event,
|
|
43569
|
+
scope: r.scope ?? null,
|
|
43570
|
+
intendedFor: r.intended_for ?? null,
|
|
43571
|
+
drainedBy: r.drained_by ?? null,
|
|
43572
|
+
drained: r.drained === 1,
|
|
43573
|
+
queuedAt: r.queued_at,
|
|
43574
|
+
drainedAt: r.drained_at ?? null
|
|
43575
|
+
}));
|
|
43576
|
+
}
|
|
43431
43577
|
hasPendingEventFingerprint(meshId, fingerprint) {
|
|
43432
43578
|
const row = this.db.prepare(
|
|
43433
43579
|
"SELECT 1 FROM mesh_pending_events WHERE mesh_id = ? AND fingerprint = ? AND drained = 0 LIMIT 1"
|
|
@@ -43602,7 +43748,7 @@ Next step: ${nextStep}`;
|
|
|
43602
43748
|
requeueDrainedPendingEventByFingerprint(meshId, fingerprint) {
|
|
43603
43749
|
if (!fingerprint) return false;
|
|
43604
43750
|
const changes = this.db.prepare(
|
|
43605
|
-
`UPDATE mesh_pending_events SET drained = 0, drained_at = NULL
|
|
43751
|
+
`UPDATE mesh_pending_events SET drained = 0, drained_at = NULL, drained_by = NULL
|
|
43606
43752
|
WHERE mesh_id = ? AND fingerprint = ? AND drained = 1`
|
|
43607
43753
|
).run(meshId, fingerprint).changes;
|
|
43608
43754
|
if (changes > 0) this.maybeCheckpointWal();
|
|
@@ -61514,7 +61660,15 @@ ${cleanBody}`;
|
|
|
61514
61660
|
try {
|
|
61515
61661
|
pendingEvents = drainPendingMeshCoordinatorEvents(
|
|
61516
61662
|
meshId,
|
|
61517
|
-
drainDaemonIds.length > 0 ? drainDaemonIds : localDaemonId
|
|
61663
|
+
drainDaemonIds.length > 0 ? drainDaemonIds : localDaemonId,
|
|
61664
|
+
{
|
|
61665
|
+
// AMBIGUOUS-UNICAST guard (REFINE-EVENT-SESSION-SCOPED-UNICAST): observability
|
|
61666
|
+
// only — it warns when a session-less unicast event is delivered while several
|
|
61667
|
+
// coordinator sessions are live and racing for it. Never changes delivery, so
|
|
61668
|
+
// an event can't be stranded by it. targetCoordinators is this daemon's live
|
|
61669
|
+
// coordinator set for the mesh, which is exactly the racing population.
|
|
61670
|
+
countLiveCoordinatorSessions: () => new Set(targetCoordinators.map((c) => c.sessionId).filter(Boolean)).size
|
|
61671
|
+
}
|
|
61518
61672
|
);
|
|
61519
61673
|
} catch (e) {
|
|
61520
61674
|
LOG2.warn("MeshReconcile", `Drain failed for mesh ${meshId}: ${e?.message || e}`);
|
|
@@ -101143,7 +101297,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
101143
101297
|
}
|
|
101144
101298
|
return { success: true, mesh: meshRecord.mesh, sourceOfTruth };
|
|
101145
101299
|
},
|
|
101146
|
-
create_mesh: async (
|
|
101300
|
+
create_mesh: async (ctx, args) => {
|
|
101147
101301
|
const name = typeof args?.name === "string" ? args.name.trim() : "";
|
|
101148
101302
|
const repoIdentity = typeof args?.repoIdentity === "string" ? args.repoIdentity.trim() : "";
|
|
101149
101303
|
const repoRemoteUrl = typeof args?.repoRemoteUrl === "string" ? args.repoRemoteUrl.trim() : void 0;
|
|
@@ -101152,12 +101306,71 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
101152
101306
|
try {
|
|
101153
101307
|
const { createMesh: createMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
101154
101308
|
const meshHost = args?.meshHost && typeof args.meshHost === "object" && !Array.isArray(args.meshHost) ? args.meshHost : void 0;
|
|
101155
|
-
const
|
|
101309
|
+
const requestedHostDaemonId = typeof args?.hostDaemonId === "string" && args.hostDaemonId.trim() ? args.hostDaemonId.trim() : ctx.deps.statusInstanceId || "";
|
|
101310
|
+
const mesh = createMesh2({
|
|
101311
|
+
name,
|
|
101312
|
+
repoIdentity,
|
|
101313
|
+
repoRemoteUrl,
|
|
101314
|
+
defaultBranch,
|
|
101315
|
+
policy: args?.policy,
|
|
101316
|
+
meshHost,
|
|
101317
|
+
...requestedHostDaemonId ? { hostDaemonId: requestedHostDaemonId } : {}
|
|
101318
|
+
});
|
|
101156
101319
|
return { success: true, mesh };
|
|
101157
101320
|
} catch (e) {
|
|
101158
101321
|
return { success: false, error: e.message };
|
|
101159
101322
|
}
|
|
101160
101323
|
},
|
|
101324
|
+
// HOST-PIN-WRITER — establish this mesh's host daemon as a DELIBERATE operator act.
|
|
101325
|
+
//
|
|
101326
|
+
// The dashboard's first-setup flow lets the operator pick which connected daemon
|
|
101327
|
+
// becomes the host; this is the command that actually persists that choice. It is a
|
|
101328
|
+
// separate surface from coordinator launch on purpose: the pin is effectively
|
|
101329
|
+
// permanent ("Fixed when the mesh is created — it cannot be reassigned here"), so it
|
|
101330
|
+
// must not be an incidental side effect of a button whose stated job is launching a
|
|
101331
|
+
// session. A mis-click must not permanently re-home a mesh.
|
|
101332
|
+
//
|
|
101333
|
+
// Reassignment to a DIFFERENT daemon is refused unless the caller passes
|
|
101334
|
+
// force:true — the mutator returns code 'host_already_pinned' and changes nothing.
|
|
101335
|
+
// Re-pinning the same daemon is a no-op, so retries/races are safe.
|
|
101336
|
+
set_mesh_host: async (ctx, args) => {
|
|
101337
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
101338
|
+
const hostDaemonId = typeof args?.hostDaemonId === "string" ? args.hostDaemonId.trim() : "";
|
|
101339
|
+
const hostNodeId = typeof args?.hostNodeId === "string" ? args.hostNodeId.trim() : "";
|
|
101340
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
101341
|
+
if (!hostDaemonId && !hostNodeId) return { success: false, error: "hostDaemonId or hostNodeId required" };
|
|
101342
|
+
try {
|
|
101343
|
+
const { setMeshHostPin: setMeshHostPin2, getMesh: getMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
101344
|
+
const result = setMeshHostPin2(meshId, {
|
|
101345
|
+
...hostDaemonId ? { hostDaemonId } : {},
|
|
101346
|
+
...hostNodeId ? { hostNodeId } : {},
|
|
101347
|
+
force: args?.force === true
|
|
101348
|
+
});
|
|
101349
|
+
if (!result) return { success: false, error: "Mesh not found" };
|
|
101350
|
+
if (!result.applied && result.reason !== "already_pinned_same") {
|
|
101351
|
+
return {
|
|
101352
|
+
success: false,
|
|
101353
|
+
code: result.reason,
|
|
101354
|
+
error: result.reason === "host_already_pinned" ? `Mesh host is already pinned to ${result.hostDaemonId}. Pass force:true to reassign it.` : result.reason === "not_host_role" ? "This daemon joined the mesh as a member; its host lives on the daemon it paired with." : "hostDaemonId or hostNodeId required",
|
|
101355
|
+
meshId,
|
|
101356
|
+
meshHost: resolveMeshHostStatus(result.mesh)
|
|
101357
|
+
};
|
|
101358
|
+
}
|
|
101359
|
+
const fresh = getMesh2(meshId) || result.mesh;
|
|
101360
|
+
if (ctx.getCachedInlineMesh(meshId)) ctx.inlineMeshCache.set(meshId, fresh);
|
|
101361
|
+
ctx.invalidateAggregateMeshStatus(meshId);
|
|
101362
|
+
return {
|
|
101363
|
+
success: true,
|
|
101364
|
+
code: result.reason,
|
|
101365
|
+
meshId,
|
|
101366
|
+
applied: result.applied,
|
|
101367
|
+
meshHost: resolveMeshHostStatus(fresh),
|
|
101368
|
+
mesh: fresh
|
|
101369
|
+
};
|
|
101370
|
+
} catch (e) {
|
|
101371
|
+
return { success: false, error: e.message };
|
|
101372
|
+
}
|
|
101373
|
+
},
|
|
101161
101374
|
update_mesh: async (ctx, args) => {
|
|
101162
101375
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
101163
101376
|
if (!meshId) return { success: false, error: "meshId required" };
|
|
@@ -103102,6 +103315,26 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
103102
103315
|
init_mesh_coordinator();
|
|
103103
103316
|
init_dist();
|
|
103104
103317
|
init_repo_mesh_types();
|
|
103318
|
+
async function backfillMeshHostPinAfterLaunch(opts) {
|
|
103319
|
+
try {
|
|
103320
|
+
const existingPin = typeof opts.mesh?.meshHost?.hostDaemonId === "string" ? opts.mesh.meshHost.hostDaemonId.trim() : "";
|
|
103321
|
+
if (existingPin) return;
|
|
103322
|
+
const { getMesh: getMesh2, setMeshHostPin: setMeshHostPin2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
103323
|
+
if (!getMesh2(opts.meshId)) return;
|
|
103324
|
+
const nodeDaemonId = typeof opts.coordinatorNode?.daemonId === "string" && opts.coordinatorNode.daemonId.trim() ? opts.coordinatorNode.daemonId.trim() : typeof opts.coordinatorNode?.daemon_id === "string" && opts.coordinatorNode.daemon_id.trim() ? opts.coordinatorNode.daemon_id.trim() : opts.localDaemonId || "";
|
|
103325
|
+
const nodeId = String(normalizeMeshNodeId(opts.coordinatorNode) || "");
|
|
103326
|
+
if (!nodeDaemonId && !nodeId) return;
|
|
103327
|
+
const result = setMeshHostPin2(opts.meshId, {
|
|
103328
|
+
...nodeDaemonId ? { hostDaemonId: nodeDaemonId } : {},
|
|
103329
|
+
...nodeId ? { hostNodeId: nodeId } : {}
|
|
103330
|
+
});
|
|
103331
|
+
if (result?.applied) {
|
|
103332
|
+
LOG2.info("MeshCoordinator", `Pinned mesh ${opts.meshId} host to ${result.hostDaemonId || nodeDaemonId} (node ${result.hostNodeId || nodeId}) after coordinator launch`);
|
|
103333
|
+
}
|
|
103334
|
+
} catch (error48) {
|
|
103335
|
+
LOG2.warn("MeshCoordinator", `Host pin backfill skipped for mesh ${opts.meshId}: ${error48?.message || String(error48)}`);
|
|
103336
|
+
}
|
|
103337
|
+
}
|
|
103105
103338
|
var meshCoordinatorLaunchHandlers = {
|
|
103106
103339
|
launch_mesh_coordinator: async (ctx, args) => {
|
|
103107
103340
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
@@ -103461,6 +103694,12 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
103461
103694
|
});
|
|
103462
103695
|
} catch {
|
|
103463
103696
|
}
|
|
103697
|
+
await backfillMeshHostPinAfterLaunch({
|
|
103698
|
+
meshId,
|
|
103699
|
+
mesh,
|
|
103700
|
+
coordinatorNode,
|
|
103701
|
+
localDaemonId: ctx.deps.statusInstanceId
|
|
103702
|
+
});
|
|
103464
103703
|
return {
|
|
103465
103704
|
success: true,
|
|
103466
103705
|
meshId,
|
|
@@ -103659,6 +103898,12 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
103659
103898
|
});
|
|
103660
103899
|
} catch {
|
|
103661
103900
|
}
|
|
103901
|
+
await backfillMeshHostPinAfterLaunch({
|
|
103902
|
+
meshId,
|
|
103903
|
+
mesh,
|
|
103904
|
+
coordinatorNode,
|
|
103905
|
+
localDaemonId: ctx.deps.statusInstanceId
|
|
103906
|
+
});
|
|
103662
103907
|
return {
|
|
103663
103908
|
success: true,
|
|
103664
103909
|
meshId,
|
|
@@ -106061,6 +106306,7 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
106061
106306
|
...args.completedAt ? { completedAt: args.completedAt } : {},
|
|
106062
106307
|
...args.retryOfJobId ? { retryOfJobId: args.retryOfJobId } : {},
|
|
106063
106308
|
...args.coordinatorDaemonId ? { targetCoordinatorDaemonId: args.coordinatorDaemonId } : {},
|
|
106309
|
+
...args.coordinatorSessionId ? { targetCoordinatorSessionId: args.coordinatorSessionId } : {},
|
|
106064
106310
|
eventDelivery: { pendingEvents: true, ledger: true },
|
|
106065
106311
|
evidence: {
|
|
106066
106312
|
pendingEventsCommand: "get_pending_mesh_events",
|
|
@@ -106159,9 +106405,23 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
106159
106405
|
nodeLabel: handle.targetNodeId,
|
|
106160
106406
|
nodeId: handle.targetNodeId,
|
|
106161
106407
|
workspace: handle.workspace,
|
|
106162
|
-
metadataEvent
|
|
106408
|
+
metadataEvent: {
|
|
106409
|
+
...metadataEvent,
|
|
106410
|
+
// REFINE-EVENT-SESSION-SCOPED-UNICAST: mirror the session INSIDE
|
|
106411
|
+
// metadataEvent too. handleMeshForwardEvent reads the coordinator session
|
|
106412
|
+
// anchor from `metadataEvent.meshCoordinatorSessionId` (a top-level field
|
|
106413
|
+
// alone is dropped when the event crosses a machine boundary), so this is
|
|
106414
|
+
// what survives the P2P relay for a remote-executing refine.
|
|
106415
|
+
...handle.targetCoordinatorSessionId ? { meshCoordinatorSessionId: handle.targetCoordinatorSessionId } : {}
|
|
106416
|
+
},
|
|
106163
106417
|
queuedAt: Date.now(),
|
|
106164
|
-
...handle.targetCoordinatorDaemonId ? { targetCoordinatorDaemonId: handle.targetCoordinatorDaemonId } : {}
|
|
106418
|
+
...handle.targetCoordinatorDaemonId ? { targetCoordinatorDaemonId: handle.targetCoordinatorDaemonId } : {},
|
|
106419
|
+
// THE FIX: address the terminal event to the requesting coordinator SESSION,
|
|
106420
|
+
// not just its daemon. stampPendingEventV2 folds this into the v2 unicast
|
|
106421
|
+
// `intendedFor`, so identityDeliversTo's both-sides-session branch excludes a
|
|
106422
|
+
// sibling coordinator session on the same daemon. Absent (legacy requester) →
|
|
106423
|
+
// session-less intendedFor → daemon-level delivery exactly as before.
|
|
106424
|
+
...handle.targetCoordinatorSessionId ? { targetCoordinatorSessionId: handle.targetCoordinatorSessionId } : {}
|
|
106165
106425
|
};
|
|
106166
106426
|
if (typeof self.deps.instanceManager?.getByCategory === "function") {
|
|
106167
106427
|
const forwarded = handleMeshForwardEvent(
|
|
@@ -106185,6 +106445,14 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
106185
106445
|
// re-queued event self-fallbacks to THIS (the executing/worker)
|
|
106186
106446
|
// daemon and the real coordinator's drain excludes it.
|
|
106187
106447
|
...handle.targetCoordinatorDaemonId ? { targetCoordinatorDaemonId: handle.targetCoordinatorDaemonId } : {},
|
|
106448
|
+
// REFINE-EVENT-SESSION-SCOPED-UNICAST: carry the SESSION half of the
|
|
106449
|
+
// return address across the relay as well. buildRelayMetadataEvent
|
|
106450
|
+
// reads meshCoordinatorSessionId (falling back to
|
|
106451
|
+
// targetCoordinatorSessionId), so both spellings are supplied.
|
|
106452
|
+
...handle.targetCoordinatorSessionId ? {
|
|
106453
|
+
targetCoordinatorSessionId: handle.targetCoordinatorSessionId,
|
|
106454
|
+
meshCoordinatorSessionId: handle.targetCoordinatorSessionId
|
|
106455
|
+
} : {},
|
|
106188
106456
|
...slimResult ? { result: slimResult } : {}
|
|
106189
106457
|
}
|
|
106190
106458
|
);
|
|
@@ -107609,6 +107877,7 @@ ${e?.stderr || ""}`;
|
|
|
107609
107877
|
startedAt: args.startedAt || (/* @__PURE__ */ new Date()).toISOString(),
|
|
107610
107878
|
...args.completedAt ? { completedAt: args.completedAt } : {},
|
|
107611
107879
|
...args.coordinatorDaemonId ? { targetCoordinatorDaemonId: args.coordinatorDaemonId } : {},
|
|
107880
|
+
...args.coordinatorSessionId ? { targetCoordinatorSessionId: args.coordinatorSessionId } : {},
|
|
107612
107881
|
eventDelivery: { pendingEvents: true, ledger: true },
|
|
107613
107882
|
evidence: {
|
|
107614
107883
|
pendingEventsCommand: "get_pending_mesh_events",
|
|
@@ -107638,9 +107907,16 @@ ${e?.stderr || ""}`;
|
|
|
107638
107907
|
meshId: handle.meshId,
|
|
107639
107908
|
nodeLabel: handle.batchLabel,
|
|
107640
107909
|
nodeId: handle.batchLabel,
|
|
107641
|
-
metadataEvent
|
|
107910
|
+
metadataEvent: {
|
|
107911
|
+
...metadataEvent,
|
|
107912
|
+
// REFINE-EVENT-SESSION-SCOPED-UNICAST — see queueRefineJobEvent.
|
|
107913
|
+
...handle.targetCoordinatorSessionId ? { meshCoordinatorSessionId: handle.targetCoordinatorSessionId } : {}
|
|
107914
|
+
},
|
|
107642
107915
|
queuedAt: Date.now(),
|
|
107643
|
-
...handle.targetCoordinatorDaemonId ? { targetCoordinatorDaemonId: handle.targetCoordinatorDaemonId } : {}
|
|
107916
|
+
...handle.targetCoordinatorDaemonId ? { targetCoordinatorDaemonId: handle.targetCoordinatorDaemonId } : {},
|
|
107917
|
+
// THE FIX (batch half) — address the batch terminal event to the requesting
|
|
107918
|
+
// coordinator SESSION so a sibling session cannot consume it.
|
|
107919
|
+
...handle.targetCoordinatorSessionId ? { targetCoordinatorSessionId: handle.targetCoordinatorSessionId } : {}
|
|
107644
107920
|
};
|
|
107645
107921
|
if (typeof self.deps.instanceManager?.getByCategory === "function") {
|
|
107646
107922
|
const forwarded = handleMeshForwardEvent(
|
|
@@ -107658,6 +107934,12 @@ ${e?.stderr || ""}`;
|
|
|
107658
107934
|
// the sessionless batch job's terminal event must stay targeted
|
|
107659
107935
|
// at the originating coordinator, not self-fallback to this daemon.
|
|
107660
107936
|
...handle.targetCoordinatorDaemonId ? { targetCoordinatorDaemonId: handle.targetCoordinatorDaemonId } : {},
|
|
107937
|
+
// REFINE-EVENT-SESSION-SCOPED-UNICAST — session half of the return
|
|
107938
|
+
// address, both spellings (see queueRefineJobEvent).
|
|
107939
|
+
...handle.targetCoordinatorSessionId ? {
|
|
107940
|
+
targetCoordinatorSessionId: handle.targetCoordinatorSessionId,
|
|
107941
|
+
meshCoordinatorSessionId: handle.targetCoordinatorSessionId
|
|
107942
|
+
} : {},
|
|
107661
107943
|
...result ? { result } : {}
|
|
107662
107944
|
}
|
|
107663
107945
|
);
|
|
@@ -107730,7 +108012,10 @@ ${e?.stderr || ""}`;
|
|
|
107730
108012
|
completedAt,
|
|
107731
108013
|
jobId: handle.jobId,
|
|
107732
108014
|
interactionId: handle.interactionId,
|
|
107733
|
-
coordinatorDaemonId: handle.targetCoordinatorDaemonId
|
|
108015
|
+
coordinatorDaemonId: handle.targetCoordinatorDaemonId,
|
|
108016
|
+
// REFINE-EVENT-SESSION-SCOPED-UNICAST — carry the requester's session onto the
|
|
108017
|
+
// terminal batch handle (see the single-node path).
|
|
108018
|
+
coordinatorSessionId: handle.targetCoordinatorSessionId
|
|
107734
108019
|
});
|
|
107735
108020
|
const terminal = { ...terminalHandle, result: normalizedResult };
|
|
107736
108021
|
self.terminalRefineBatchJobs.set(key2, terminal);
|
|
@@ -107764,7 +108049,8 @@ ${e?.stderr || ""}`;
|
|
|
107764
108049
|
rationale: planRecord.orderingRationale
|
|
107765
108050
|
};
|
|
107766
108051
|
const coordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : self.deps.statusInstanceId || void 0;
|
|
107767
|
-
const
|
|
108052
|
+
const coordinatorSessionId = typeof args?.coordinatorSessionId === "string" && args.coordinatorSessionId.trim() ? args.coordinatorSessionId.trim() : void 0;
|
|
108053
|
+
const handle = buildRefineBatchJobHandle(self, { meshId, nodeIds, order, coordinatorDaemonId, coordinatorSessionId });
|
|
107768
108054
|
self.runningRefineBatchJobs.set(key2, handle);
|
|
107769
108055
|
await appendRefineBatchJobLedger(self, "task_dispatched", handle);
|
|
107770
108056
|
queueRefineBatchJobEvent(self, "refine:accepted", handle);
|
|
@@ -107855,7 +108141,12 @@ ${e?.stderr || ""}`;
|
|
|
107855
108141
|
interactionId: handle.interactionId,
|
|
107856
108142
|
retryOfJobId: handle.retryOfJobId,
|
|
107857
108143
|
node: { daemonId: handle.targetDaemonId, workspace: handle.workspace },
|
|
107858
|
-
coordinatorDaemonId: handle.targetCoordinatorDaemonId
|
|
108144
|
+
coordinatorDaemonId: handle.targetCoordinatorDaemonId,
|
|
108145
|
+
// REFINE-EVENT-SESSION-SCOPED-UNICAST: carry the requester's session from the
|
|
108146
|
+
// accepted handle onto the TERMINAL handle. Dropping it here would leave the
|
|
108147
|
+
// completed/failed event — the one the coordinator actually waits on — back at
|
|
108148
|
+
// daemon-level addressing, i.e. the original defect.
|
|
108149
|
+
coordinatorSessionId: handle.targetCoordinatorSessionId
|
|
107859
108150
|
});
|
|
107860
108151
|
const terminal = { ...terminalHandle, result: normalizedResult };
|
|
107861
108152
|
self.terminalRefineJobs.set(key2, terminal);
|
|
@@ -107875,7 +108166,8 @@ ${e?.stderr || ""}`;
|
|
|
107875
108166
|
if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
|
|
107876
108167
|
if (!node.isLocalWorktree || !node.workspace) return { success: false, error: `Refinery requires a local worktree node` };
|
|
107877
108168
|
const coordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : self.deps.statusInstanceId || void 0;
|
|
107878
|
-
const
|
|
108169
|
+
const coordinatorSessionId = typeof args?.coordinatorSessionId === "string" && args.coordinatorSessionId.trim() ? args.coordinatorSessionId.trim() : void 0;
|
|
108170
|
+
const handle = buildRefineJobHandle(self, { meshId, nodeId, node, retryOfJobId: terminal?.jobId, coordinatorDaemonId, coordinatorSessionId });
|
|
107879
108171
|
self.runningRefineJobs.set(key2, handle);
|
|
107880
108172
|
await appendRefineJobLedger(self, "task_dispatched", handle);
|
|
107881
108173
|
queueRefineJobEvent(self, "refine:accepted", handle);
|