@adhdev/daemon-core 0.9.82-rc.30 → 0.9.82-rc.32
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 +216 -21
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +216 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/commands/router.ts +278 -24
package/package.json
CHANGED
package/src/commands/router.ts
CHANGED
|
@@ -114,14 +114,24 @@ function readBooleanValue(...values: unknown[]): boolean | undefined {
|
|
|
114
114
|
return undefined;
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
function
|
|
117
|
+
function joinRepoPath(root: string | undefined, relativePath: string | undefined): string | undefined {
|
|
118
|
+
const normalizedRoot = typeof root === 'string' ? root.trim().replace(/[\\/]+$/, '') : '';
|
|
119
|
+
const normalizedPath = typeof relativePath === 'string' ? relativePath.trim() : '';
|
|
120
|
+
if (!normalizedPath) return undefined;
|
|
121
|
+
if (/^(?:[A-Za-z]:[\\/]|\/)/.test(normalizedPath)) return normalizedPath;
|
|
122
|
+
if (!normalizedRoot) return undefined;
|
|
123
|
+
return `${normalizedRoot}/${normalizedPath.replace(/^[\\/]+/, '')}`;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function readGitSubmodules(value: unknown, parentRepoRoot?: string): GitSubmoduleStatus[] | undefined {
|
|
118
127
|
if (!Array.isArray(value)) return undefined;
|
|
119
128
|
const submodules = value
|
|
120
129
|
.map(entry => {
|
|
121
130
|
const submodule = readObjectRecord(entry);
|
|
122
131
|
const path = readStringValue(submodule.path);
|
|
123
132
|
const commit = readStringValue(submodule.commit);
|
|
124
|
-
const repoPath = readStringValue(submodule.repoPath, submodule.repo_root)
|
|
133
|
+
const repoPath = readStringValue(submodule.repoPath, submodule.repo_root)
|
|
134
|
+
?? joinRepoPath(parentRepoRoot, path);
|
|
125
135
|
if (!path || !commit || !repoPath) return null;
|
|
126
136
|
return {
|
|
127
137
|
path,
|
|
@@ -149,10 +159,11 @@ function normalizeInlineMeshGitStatus(
|
|
|
149
159
|
: [];
|
|
150
160
|
const conflictCount = readNumberValue(status.conflicts) ?? conflictFiles.length;
|
|
151
161
|
const hasConflicts = readBooleanValue(status.hasConflicts) ?? conflictCount > 0;
|
|
152
|
-
const
|
|
162
|
+
const repoRoot = readStringValue(status.repoRoot, status.repo_root, node?.repoRoot, node?.repo_root, status.workspace, node?.workspace) || undefined;
|
|
163
|
+
const submodules = readGitSubmodules(status.submodules, repoRoot);
|
|
153
164
|
return {
|
|
154
165
|
workspace: readStringValue(status.workspace, node?.workspace) || '',
|
|
155
|
-
repoRoot:
|
|
166
|
+
repoRoot: repoRoot ?? null,
|
|
156
167
|
isGitRepo,
|
|
157
168
|
branch: readStringValue(status.branch) ?? null,
|
|
158
169
|
headCommit: readStringValue(status.headCommit) ?? null,
|
|
@@ -195,6 +206,31 @@ function buildInlineMeshTransitGitStatus(node: any): Record<string, unknown> | u
|
|
|
195
206
|
return normalizeInlineMeshGitStatus(status, node, { lastCheckedAt: Date.now() });
|
|
196
207
|
}
|
|
197
208
|
|
|
209
|
+
function recordInlineMeshDirectGitTruth(
|
|
210
|
+
node: any,
|
|
211
|
+
git: Record<string, unknown>,
|
|
212
|
+
source: 'selected_coordinator_local_git' | 'selected_coordinator_mesh_p2p_git',
|
|
213
|
+
): void {
|
|
214
|
+
if (!node || typeof node !== 'object' || Array.isArray(node)) return;
|
|
215
|
+
const checkedAt = readNumberValue(git.lastCheckedAt) ?? Date.now();
|
|
216
|
+
const updatedAt = new Date(checkedAt).toISOString();
|
|
217
|
+
const nextGit: Record<string, unknown> = {
|
|
218
|
+
...git,
|
|
219
|
+
lastCheckedAt: checkedAt,
|
|
220
|
+
};
|
|
221
|
+
node.lastGit = {
|
|
222
|
+
source,
|
|
223
|
+
checkedAt,
|
|
224
|
+
status: nextGit,
|
|
225
|
+
};
|
|
226
|
+
node.last_git = node.lastGit;
|
|
227
|
+
node.machineStatus = 'online';
|
|
228
|
+
node.updatedAt = updatedAt;
|
|
229
|
+
node.lastSeenAt = updatedAt;
|
|
230
|
+
const repoRoot = readStringValue(nextGit.repoRoot);
|
|
231
|
+
if (repoRoot && !readStringValue(node.repoRoot)) node.repoRoot = repoRoot;
|
|
232
|
+
}
|
|
233
|
+
|
|
198
234
|
function buildCachedInlineMeshGitStatus(node: any): Record<string, unknown> | undefined {
|
|
199
235
|
const liveGit = buildInlineMeshTransitGitStatus(node);
|
|
200
236
|
if (liveGit) return liveGit;
|
|
@@ -240,7 +276,6 @@ function stripInlineMeshTransientNodeState(node: any): any {
|
|
|
240
276
|
session_id: _sessionIdLegacy,
|
|
241
277
|
providerType: _providerType,
|
|
242
278
|
provider_type: _providerTypeLegacy,
|
|
243
|
-
providers: _providers,
|
|
244
279
|
...rest
|
|
245
280
|
} = node as Record<string, unknown>;
|
|
246
281
|
if (cachedStatus && !shouldDiscardCachedInlineMeshStatus(node)) {
|
|
@@ -270,8 +305,13 @@ function hasInlineMeshTransientNodeState(node: any): boolean {
|
|
|
270
305
|
|| 'sessionId' in node
|
|
271
306
|
|| 'session_id' in node
|
|
272
307
|
|| 'providerType' in node
|
|
273
|
-
|| 'provider_type' in node
|
|
274
|
-
|
|
308
|
+
|| 'provider_type' in node;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function inlineMeshCarriesTransientNodeTruth(inlineMesh: any): boolean {
|
|
312
|
+
if (!inlineMesh || typeof inlineMesh !== 'object' || Array.isArray(inlineMesh)) return false;
|
|
313
|
+
if (!Array.isArray(inlineMesh.nodes) || inlineMesh.nodes.length === 0) return false;
|
|
314
|
+
return inlineMesh.nodes.some((node: any) => hasInlineMeshTransientNodeState(node));
|
|
275
315
|
}
|
|
276
316
|
|
|
277
317
|
function readInlineMeshNodeId(node: any): string {
|
|
@@ -415,6 +455,152 @@ function toIsoTimestamp(value: unknown): string | null {
|
|
|
415
455
|
return stringValue || null;
|
|
416
456
|
}
|
|
417
457
|
|
|
458
|
+
function synthesizeMeshNodeFreshnessFromConnection(status: Record<string, unknown>): void {
|
|
459
|
+
const connection = readObjectRecord(status.connection);
|
|
460
|
+
const connectionFreshAt = toIsoTimestamp(connection.lastCommandAt ?? connection.lastConnectedAt ?? connection.lastStateChangeAt);
|
|
461
|
+
const git = readObjectRecord(status.git);
|
|
462
|
+
const gitCheckedAt = toIsoTimestamp(git.lastCheckedAt);
|
|
463
|
+
if (!status.lastSeenAt && connectionFreshAt) status.lastSeenAt = connectionFreshAt;
|
|
464
|
+
if (!status.updatedAt && (gitCheckedAt || connectionFreshAt)) {
|
|
465
|
+
status.updatedAt = gitCheckedAt ?? connectionFreshAt;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
function finalizeMeshNodeStatus(args: {
|
|
470
|
+
status: Record<string, unknown>;
|
|
471
|
+
node: any;
|
|
472
|
+
daemonId?: string;
|
|
473
|
+
isSelfNode: boolean;
|
|
474
|
+
}): void {
|
|
475
|
+
const { status, node, daemonId, isSelfNode } = args;
|
|
476
|
+
if (!readStringValue(status.machineStatus)) {
|
|
477
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
478
|
+
const machineStatus = readStringValue(cachedStatus.machineStatus, cachedStatus.machine_status, node?.machineStatus);
|
|
479
|
+
if (machineStatus) status.machineStatus = machineStatus;
|
|
480
|
+
}
|
|
481
|
+
synthesizeMeshNodeFreshnessFromConnection(status);
|
|
482
|
+
const connectionState = readStringValue(readObjectRecord(status.connection).state);
|
|
483
|
+
status.launchReady = !!daemonId && (
|
|
484
|
+
readStringValue(status.machineStatus) === 'online'
|
|
485
|
+
|| connectionState === 'connected'
|
|
486
|
+
|| isSelfNode
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
async function probeRemoteMeshGitStatus(args: {
|
|
491
|
+
dispatchMeshCommand?: (daemonId: string, cmd: string, args: Record<string, unknown>) => Promise<unknown>;
|
|
492
|
+
daemonId: string;
|
|
493
|
+
workspace: string;
|
|
494
|
+
timeoutMs: number;
|
|
495
|
+
}): Promise<Record<string, unknown> | null> {
|
|
496
|
+
if (!args.dispatchMeshCommand) return null;
|
|
497
|
+
const remoteResult = await Promise.race([
|
|
498
|
+
args.dispatchMeshCommand(args.daemonId, 'git_status', { workspace: args.workspace }),
|
|
499
|
+
new Promise<never>((_, reject) => setTimeout(() => reject(new Error('timeout')), args.timeoutMs)),
|
|
500
|
+
]) as any;
|
|
501
|
+
const remoteGit = remoteResult?.status ?? remoteResult?.git ?? remoteResult;
|
|
502
|
+
return remoteGit && typeof remoteGit === 'object' && typeof remoteGit.isGitRepo === 'boolean'
|
|
503
|
+
? remoteGit as Record<string, unknown>
|
|
504
|
+
: null;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
async function hydrateInlineMeshDirectTruth(args: {
|
|
508
|
+
mesh: any;
|
|
509
|
+
meshSource: 'inline_cache' | 'inline_bootstrap' | 'local_config';
|
|
510
|
+
dispatchMeshCommand?: (daemonId: string, cmd: string, args: Record<string, unknown>) => Promise<unknown>;
|
|
511
|
+
statusInstanceId?: string;
|
|
512
|
+
localMachineId?: string;
|
|
513
|
+
}): Promise<{
|
|
514
|
+
directEvidenceCount: number;
|
|
515
|
+
localConfirmedCount: number;
|
|
516
|
+
peerAttemptedCount: number;
|
|
517
|
+
peerConfirmedCount: number;
|
|
518
|
+
unavailableNodeIds: string[];
|
|
519
|
+
}> {
|
|
520
|
+
const nodes = Array.isArray(args.mesh?.nodes) ? args.mesh.nodes : [];
|
|
521
|
+
if (!nodes.length) {
|
|
522
|
+
return {
|
|
523
|
+
directEvidenceCount: 0,
|
|
524
|
+
localConfirmedCount: 0,
|
|
525
|
+
peerAttemptedCount: 0,
|
|
526
|
+
peerConfirmedCount: 0,
|
|
527
|
+
unavailableNodeIds: [],
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
const selectedCoordinatorNodeId = readStringValue(
|
|
532
|
+
args.mesh?.coordinator?.preferredNodeId,
|
|
533
|
+
nodes[0]?.id,
|
|
534
|
+
nodes[0]?.nodeId,
|
|
535
|
+
);
|
|
536
|
+
|
|
537
|
+
let localConfirmedCount = 0;
|
|
538
|
+
let peerAttemptedCount = 0;
|
|
539
|
+
let peerConfirmedCount = 0;
|
|
540
|
+
const unavailableNodeIds: string[] = [];
|
|
541
|
+
|
|
542
|
+
for (const [nodeIndex, node] of nodes.entries()) {
|
|
543
|
+
const nodeId = readStringValue(node?.id, node?.nodeId) || `node_${nodeIndex}`;
|
|
544
|
+
const workspace = readStringValue(node?.workspace);
|
|
545
|
+
const daemonId = readStringValue(node?.daemonId);
|
|
546
|
+
const isSelfNode = Boolean(
|
|
547
|
+
nodeId && selectedCoordinatorNodeId && nodeId === selectedCoordinatorNodeId,
|
|
548
|
+
) || Boolean(
|
|
549
|
+
daemonId && (daemonId === args.localMachineId || daemonId === args.statusInstanceId),
|
|
550
|
+
) || Boolean(args.meshSource !== 'local_config' && nodeIndex === 0);
|
|
551
|
+
|
|
552
|
+
if (!workspace) {
|
|
553
|
+
if (!isSelfNode && daemonId) unavailableNodeIds.push(nodeId);
|
|
554
|
+
continue;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
if (isSelfNode && fs.existsSync(workspace)) {
|
|
558
|
+
try {
|
|
559
|
+
const localGit = await getGitRepoStatus(workspace, { timeoutMs: 10_000, refreshUpstream: true });
|
|
560
|
+
if (localGit?.isGitRepo) {
|
|
561
|
+
recordInlineMeshDirectGitTruth(node, localGit as unknown as Record<string, unknown>, 'selected_coordinator_local_git');
|
|
562
|
+
localConfirmedCount += 1;
|
|
563
|
+
continue;
|
|
564
|
+
}
|
|
565
|
+
} catch {
|
|
566
|
+
// Fall through to remote classification.
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
if (!daemonId || !args.dispatchMeshCommand) {
|
|
571
|
+
if (!isSelfNode) unavailableNodeIds.push(nodeId);
|
|
572
|
+
continue;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
peerAttemptedCount += 1;
|
|
576
|
+
try {
|
|
577
|
+
const remoteGit = await probeRemoteMeshGitStatus({
|
|
578
|
+
dispatchMeshCommand: args.dispatchMeshCommand,
|
|
579
|
+
daemonId,
|
|
580
|
+
workspace,
|
|
581
|
+
timeoutMs: 8_000,
|
|
582
|
+
});
|
|
583
|
+
if (remoteGit) {
|
|
584
|
+
recordInlineMeshDirectGitTruth(node, remoteGit, 'selected_coordinator_mesh_p2p_git');
|
|
585
|
+
peerConfirmedCount += 1;
|
|
586
|
+
continue;
|
|
587
|
+
}
|
|
588
|
+
} catch {
|
|
589
|
+
// Strict direct-only path: do not fall back to persisted cloud truth here.
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
unavailableNodeIds.push(nodeId);
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
return {
|
|
596
|
+
directEvidenceCount: localConfirmedCount + peerConfirmedCount,
|
|
597
|
+
localConfirmedCount,
|
|
598
|
+
peerAttemptedCount,
|
|
599
|
+
peerConfirmedCount,
|
|
600
|
+
unavailableNodeIds,
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
|
|
418
604
|
function summarizeMeshSessionRecord(record: any): Record<string, unknown> {
|
|
419
605
|
return {
|
|
420
606
|
sessionId: readStringValue(record?.sessionId) || 'unknown',
|
|
@@ -1105,8 +1291,10 @@ export class DaemonCommandRouter {
|
|
|
1105
1291
|
if (preferInline) {
|
|
1106
1292
|
const cached = this.getCachedInlineMesh(meshId);
|
|
1107
1293
|
if (cached) return { mesh: cached, inline: true, source: 'inline_cache' };
|
|
1108
|
-
|
|
1109
|
-
|
|
1294
|
+
if (inlineMeshCarriesTransientNodeTruth(inlineMesh)) {
|
|
1295
|
+
this.warmInlineMeshCache(meshId, inlineMesh);
|
|
1296
|
+
return { mesh: inlineMesh, inline: true, source: 'inline_bootstrap' };
|
|
1297
|
+
}
|
|
1110
1298
|
}
|
|
1111
1299
|
try {
|
|
1112
1300
|
const { getMesh } = await import('../config/mesh-config.js');
|
|
@@ -2285,8 +2473,43 @@ export class DaemonCommandRouter {
|
|
|
2285
2473
|
const meshId = typeof args?.meshId === 'string' ? args.meshId.trim() : '';
|
|
2286
2474
|
if (!meshId) return { success: false, error: 'meshId required' };
|
|
2287
2475
|
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
2288
|
-
if (meshRecord?.mesh) return { success:
|
|
2289
|
-
|
|
2476
|
+
if (!meshRecord?.mesh) return { success: false, error: 'Mesh not found' };
|
|
2477
|
+
|
|
2478
|
+
const requireDirectPeerTruth = args?.requireDirectPeerTruth === true;
|
|
2479
|
+
const directTruth = await hydrateInlineMeshDirectTruth({
|
|
2480
|
+
mesh: meshRecord.mesh,
|
|
2481
|
+
meshSource: meshRecord.source,
|
|
2482
|
+
dispatchMeshCommand: this.deps.dispatchMeshCommand,
|
|
2483
|
+
statusInstanceId: this.deps.statusInstanceId,
|
|
2484
|
+
localMachineId: loadConfig().machineId || '',
|
|
2485
|
+
});
|
|
2486
|
+
const directTruthSatisfied = meshRecord.source !== 'inline_bootstrap' || directTruth.directEvidenceCount > 0;
|
|
2487
|
+
const sourceOfTruth = {
|
|
2488
|
+
membership: meshRecord.source === 'inline_cache'
|
|
2489
|
+
? 'coordinator_inline_mesh_cache'
|
|
2490
|
+
: meshRecord.source === 'local_config'
|
|
2491
|
+
? 'local_mesh_config'
|
|
2492
|
+
: 'inline_bootstrap_snapshot',
|
|
2493
|
+
coordinatorOwnsLiveTruth: directTruthSatisfied,
|
|
2494
|
+
directPeerTruth: {
|
|
2495
|
+
required: requireDirectPeerTruth,
|
|
2496
|
+
satisfied: directTruthSatisfied,
|
|
2497
|
+
directEvidenceCount: directTruth.directEvidenceCount,
|
|
2498
|
+
localConfirmedCount: directTruth.localConfirmedCount,
|
|
2499
|
+
peerAttemptedCount: directTruth.peerAttemptedCount,
|
|
2500
|
+
peerConfirmedCount: directTruth.peerConfirmedCount,
|
|
2501
|
+
unavailableNodeIds: directTruth.unavailableNodeIds,
|
|
2502
|
+
},
|
|
2503
|
+
};
|
|
2504
|
+
if (requireDirectPeerTruth && !directTruthSatisfied) {
|
|
2505
|
+
return {
|
|
2506
|
+
success: false,
|
|
2507
|
+
code: 'mesh_direct_peer_truth_unavailable',
|
|
2508
|
+
error: 'Selected coordinator could not confirm direct mesh truth yet. Bootstrap inventory stays unavailable until direct get_mesh probes succeed.',
|
|
2509
|
+
sourceOfTruth,
|
|
2510
|
+
};
|
|
2511
|
+
}
|
|
2512
|
+
return { success: true, mesh: meshRecord.mesh, sourceOfTruth };
|
|
2290
2513
|
}
|
|
2291
2514
|
|
|
2292
2515
|
case 'create_mesh': {
|
|
@@ -3335,29 +3558,59 @@ export class DaemonCommandRouter {
|
|
|
3335
3558
|
}
|
|
3336
3559
|
if (workspace) {
|
|
3337
3560
|
if (!fs.existsSync(workspace)) {
|
|
3338
|
-
// Workspace not local — attempt a P2P git probe
|
|
3561
|
+
// Workspace not local — prefer direct live inline truth, then attempt a P2P git probe.
|
|
3562
|
+
const inlineTransitGit = buildInlineMeshTransitGitStatus(node);
|
|
3339
3563
|
let remoteProbeApplied = false;
|
|
3340
|
-
if (
|
|
3564
|
+
if (inlineTransitGit) {
|
|
3565
|
+
status.git = inlineTransitGit;
|
|
3566
|
+
status.health = inlineTransitGit.isGitRepo
|
|
3567
|
+
? deriveMeshNodeHealthFromGit(inlineTransitGit as unknown as Record<string, unknown>)
|
|
3568
|
+
: 'degraded';
|
|
3569
|
+
remoteProbeApplied = true;
|
|
3570
|
+
} else if (!isSelfNode && daemonId && this.deps.dispatchMeshCommand) {
|
|
3341
3571
|
try {
|
|
3342
|
-
const
|
|
3343
|
-
this.deps.dispatchMeshCommand
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3572
|
+
const remoteGit = await probeRemoteMeshGitStatus({
|
|
3573
|
+
dispatchMeshCommand: this.deps.dispatchMeshCommand,
|
|
3574
|
+
daemonId,
|
|
3575
|
+
workspace,
|
|
3576
|
+
timeoutMs: 8000,
|
|
3577
|
+
});
|
|
3578
|
+
if (remoteGit) {
|
|
3348
3579
|
status.git = remoteGit;
|
|
3349
3580
|
status.health = remoteGit.isGitRepo
|
|
3350
3581
|
? deriveMeshNodeHealthFromGit(remoteGit as unknown as Record<string, unknown>)
|
|
3351
3582
|
: 'degraded';
|
|
3583
|
+
recordInlineMeshDirectGitTruth(node, remoteGit, 'selected_coordinator_mesh_p2p_git');
|
|
3352
3584
|
remoteProbeApplied = true;
|
|
3353
3585
|
}
|
|
3354
3586
|
} catch {
|
|
3355
|
-
|
|
3587
|
+
const refreshedConnection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
|
|
3588
|
+
const refreshedConnectionState = readStringValue(refreshedConnection?.state);
|
|
3589
|
+
if (refreshedConnection && refreshedConnectionState === 'connected') {
|
|
3590
|
+
status.connection = refreshedConnection;
|
|
3591
|
+
try {
|
|
3592
|
+
const remoteGit = await probeRemoteMeshGitStatus({
|
|
3593
|
+
dispatchMeshCommand: this.deps.dispatchMeshCommand,
|
|
3594
|
+
daemonId,
|
|
3595
|
+
workspace,
|
|
3596
|
+
timeoutMs: 12000,
|
|
3597
|
+
});
|
|
3598
|
+
if (remoteGit) {
|
|
3599
|
+
status.git = remoteGit;
|
|
3600
|
+
status.health = remoteGit.isGitRepo
|
|
3601
|
+
? deriveMeshNodeHealthFromGit(remoteGit as unknown as Record<string, unknown>)
|
|
3602
|
+
: 'degraded';
|
|
3603
|
+
recordInlineMeshDirectGitTruth(node, remoteGit, 'selected_coordinator_mesh_p2p_git');
|
|
3604
|
+
remoteProbeApplied = true;
|
|
3605
|
+
}
|
|
3606
|
+
} catch {
|
|
3607
|
+
// Probe timed out again or P2P unavailable — fall back to cached status
|
|
3608
|
+
}
|
|
3609
|
+
}
|
|
3356
3610
|
}
|
|
3357
3611
|
}
|
|
3358
3612
|
if (!remoteProbeApplied) {
|
|
3359
3613
|
const connectionState = readStringValue((status.connection as any)?.state);
|
|
3360
|
-
const inlineTransitGit = buildInlineMeshTransitGitStatus(node);
|
|
3361
3614
|
const pendingPeerGitProbe = !inlineTransitGit
|
|
3362
3615
|
&& !isSelfNode
|
|
3363
3616
|
&& !!daemonId
|
|
@@ -3377,12 +3630,12 @@ export class DaemonCommandRouter {
|
|
|
3377
3630
|
node,
|
|
3378
3631
|
pendingPeerGitProbe ? { skipGit: true, skipError: true, skipHealth: true } : undefined,
|
|
3379
3632
|
)) {
|
|
3380
|
-
status
|
|
3633
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
3381
3634
|
nodeStatuses.push(status);
|
|
3382
3635
|
continue;
|
|
3383
3636
|
}
|
|
3384
3637
|
if (meshRecord?.source === 'inline_cache' && !isSelfNode) {
|
|
3385
|
-
status
|
|
3638
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
3386
3639
|
nodeStatuses.push(status);
|
|
3387
3640
|
continue;
|
|
3388
3641
|
}
|
|
@@ -3391,6 +3644,7 @@ export class DaemonCommandRouter {
|
|
|
3391
3644
|
try {
|
|
3392
3645
|
const gitStatus = await getGitRepoStatus(workspace, { timeoutMs: 10_000, refreshUpstream: true });
|
|
3393
3646
|
status.git = gitStatus;
|
|
3647
|
+
recordInlineMeshDirectGitTruth(node, gitStatus as unknown as Record<string, unknown>, 'selected_coordinator_local_git');
|
|
3394
3648
|
if (gitStatus.isGitRepo) {
|
|
3395
3649
|
status.health = deriveMeshNodeHealthFromGit(gitStatus as unknown as Record<string, unknown>);
|
|
3396
3650
|
} else {
|
|
@@ -3406,7 +3660,7 @@ export class DaemonCommandRouter {
|
|
|
3406
3660
|
} else {
|
|
3407
3661
|
applyCachedInlineMeshNodeStatus(status, node);
|
|
3408
3662
|
}
|
|
3409
|
-
status
|
|
3663
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
3410
3664
|
nodeStatuses.push(status);
|
|
3411
3665
|
}
|
|
3412
3666
|
|