@adhdev/daemon-core 0.9.82-rc.30 → 0.9.82-rc.31
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 +207 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +207 -19
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/commands/router.ts +268 -22
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,7 @@ 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
|
-
|| 'providers' in node;
|
|
308
|
+
|| 'provider_type' in node;
|
|
275
309
|
}
|
|
276
310
|
|
|
277
311
|
function readInlineMeshNodeId(node: any): string {
|
|
@@ -415,6 +449,152 @@ function toIsoTimestamp(value: unknown): string | null {
|
|
|
415
449
|
return stringValue || null;
|
|
416
450
|
}
|
|
417
451
|
|
|
452
|
+
function synthesizeMeshNodeFreshnessFromConnection(status: Record<string, unknown>): void {
|
|
453
|
+
const connection = readObjectRecord(status.connection);
|
|
454
|
+
const connectionFreshAt = toIsoTimestamp(connection.lastCommandAt ?? connection.lastConnectedAt ?? connection.lastStateChangeAt);
|
|
455
|
+
const git = readObjectRecord(status.git);
|
|
456
|
+
const gitCheckedAt = toIsoTimestamp(git.lastCheckedAt);
|
|
457
|
+
if (!status.lastSeenAt && connectionFreshAt) status.lastSeenAt = connectionFreshAt;
|
|
458
|
+
if (!status.updatedAt && (gitCheckedAt || connectionFreshAt)) {
|
|
459
|
+
status.updatedAt = gitCheckedAt ?? connectionFreshAt;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
function finalizeMeshNodeStatus(args: {
|
|
464
|
+
status: Record<string, unknown>;
|
|
465
|
+
node: any;
|
|
466
|
+
daemonId?: string;
|
|
467
|
+
isSelfNode: boolean;
|
|
468
|
+
}): void {
|
|
469
|
+
const { status, node, daemonId, isSelfNode } = args;
|
|
470
|
+
if (!readStringValue(status.machineStatus)) {
|
|
471
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
472
|
+
const machineStatus = readStringValue(cachedStatus.machineStatus, cachedStatus.machine_status, node?.machineStatus);
|
|
473
|
+
if (machineStatus) status.machineStatus = machineStatus;
|
|
474
|
+
}
|
|
475
|
+
synthesizeMeshNodeFreshnessFromConnection(status);
|
|
476
|
+
const connectionState = readStringValue(readObjectRecord(status.connection).state);
|
|
477
|
+
status.launchReady = !!daemonId && (
|
|
478
|
+
readStringValue(status.machineStatus) === 'online'
|
|
479
|
+
|| connectionState === 'connected'
|
|
480
|
+
|| isSelfNode
|
|
481
|
+
);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
async function probeRemoteMeshGitStatus(args: {
|
|
485
|
+
dispatchMeshCommand?: (daemonId: string, cmd: string, args: Record<string, unknown>) => Promise<unknown>;
|
|
486
|
+
daemonId: string;
|
|
487
|
+
workspace: string;
|
|
488
|
+
timeoutMs: number;
|
|
489
|
+
}): Promise<Record<string, unknown> | null> {
|
|
490
|
+
if (!args.dispatchMeshCommand) return null;
|
|
491
|
+
const remoteResult = await Promise.race([
|
|
492
|
+
args.dispatchMeshCommand(args.daemonId, 'git_status', { workspace: args.workspace }),
|
|
493
|
+
new Promise<never>((_, reject) => setTimeout(() => reject(new Error('timeout')), args.timeoutMs)),
|
|
494
|
+
]) as any;
|
|
495
|
+
const remoteGit = remoteResult?.status ?? remoteResult?.git ?? remoteResult;
|
|
496
|
+
return remoteGit && typeof remoteGit === 'object' && typeof remoteGit.isGitRepo === 'boolean'
|
|
497
|
+
? remoteGit as Record<string, unknown>
|
|
498
|
+
: null;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
async function hydrateInlineMeshDirectTruth(args: {
|
|
502
|
+
mesh: any;
|
|
503
|
+
meshSource: 'inline_cache' | 'inline_bootstrap' | 'local_config';
|
|
504
|
+
dispatchMeshCommand?: (daemonId: string, cmd: string, args: Record<string, unknown>) => Promise<unknown>;
|
|
505
|
+
statusInstanceId?: string;
|
|
506
|
+
localMachineId?: string;
|
|
507
|
+
}): Promise<{
|
|
508
|
+
directEvidenceCount: number;
|
|
509
|
+
localConfirmedCount: number;
|
|
510
|
+
peerAttemptedCount: number;
|
|
511
|
+
peerConfirmedCount: number;
|
|
512
|
+
unavailableNodeIds: string[];
|
|
513
|
+
}> {
|
|
514
|
+
const nodes = Array.isArray(args.mesh?.nodes) ? args.mesh.nodes : [];
|
|
515
|
+
if (!nodes.length) {
|
|
516
|
+
return {
|
|
517
|
+
directEvidenceCount: 0,
|
|
518
|
+
localConfirmedCount: 0,
|
|
519
|
+
peerAttemptedCount: 0,
|
|
520
|
+
peerConfirmedCount: 0,
|
|
521
|
+
unavailableNodeIds: [],
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
const selectedCoordinatorNodeId = readStringValue(
|
|
526
|
+
args.mesh?.coordinator?.preferredNodeId,
|
|
527
|
+
nodes[0]?.id,
|
|
528
|
+
nodes[0]?.nodeId,
|
|
529
|
+
);
|
|
530
|
+
|
|
531
|
+
let localConfirmedCount = 0;
|
|
532
|
+
let peerAttemptedCount = 0;
|
|
533
|
+
let peerConfirmedCount = 0;
|
|
534
|
+
const unavailableNodeIds: string[] = [];
|
|
535
|
+
|
|
536
|
+
for (const [nodeIndex, node] of nodes.entries()) {
|
|
537
|
+
const nodeId = readStringValue(node?.id, node?.nodeId) || `node_${nodeIndex}`;
|
|
538
|
+
const workspace = readStringValue(node?.workspace);
|
|
539
|
+
const daemonId = readStringValue(node?.daemonId);
|
|
540
|
+
const isSelfNode = Boolean(
|
|
541
|
+
nodeId && selectedCoordinatorNodeId && nodeId === selectedCoordinatorNodeId,
|
|
542
|
+
) || Boolean(
|
|
543
|
+
daemonId && (daemonId === args.localMachineId || daemonId === args.statusInstanceId),
|
|
544
|
+
) || Boolean(args.meshSource !== 'local_config' && nodeIndex === 0);
|
|
545
|
+
|
|
546
|
+
if (!workspace) {
|
|
547
|
+
if (!isSelfNode && daemonId) unavailableNodeIds.push(nodeId);
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
if (isSelfNode && fs.existsSync(workspace)) {
|
|
552
|
+
try {
|
|
553
|
+
const localGit = await getGitRepoStatus(workspace, { timeoutMs: 10_000, refreshUpstream: true });
|
|
554
|
+
if (localGit?.isGitRepo) {
|
|
555
|
+
recordInlineMeshDirectGitTruth(node, localGit as unknown as Record<string, unknown>, 'selected_coordinator_local_git');
|
|
556
|
+
localConfirmedCount += 1;
|
|
557
|
+
continue;
|
|
558
|
+
}
|
|
559
|
+
} catch {
|
|
560
|
+
// Fall through to remote classification.
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
if (!daemonId || !args.dispatchMeshCommand) {
|
|
565
|
+
if (!isSelfNode) unavailableNodeIds.push(nodeId);
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
peerAttemptedCount += 1;
|
|
570
|
+
try {
|
|
571
|
+
const remoteGit = await probeRemoteMeshGitStatus({
|
|
572
|
+
dispatchMeshCommand: args.dispatchMeshCommand,
|
|
573
|
+
daemonId,
|
|
574
|
+
workspace,
|
|
575
|
+
timeoutMs: 8_000,
|
|
576
|
+
});
|
|
577
|
+
if (remoteGit) {
|
|
578
|
+
recordInlineMeshDirectGitTruth(node, remoteGit, 'selected_coordinator_mesh_p2p_git');
|
|
579
|
+
peerConfirmedCount += 1;
|
|
580
|
+
continue;
|
|
581
|
+
}
|
|
582
|
+
} catch {
|
|
583
|
+
// Strict direct-only path: do not fall back to persisted cloud truth here.
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
unavailableNodeIds.push(nodeId);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
return {
|
|
590
|
+
directEvidenceCount: localConfirmedCount + peerConfirmedCount,
|
|
591
|
+
localConfirmedCount,
|
|
592
|
+
peerAttemptedCount,
|
|
593
|
+
peerConfirmedCount,
|
|
594
|
+
unavailableNodeIds,
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
|
|
418
598
|
function summarizeMeshSessionRecord(record: any): Record<string, unknown> {
|
|
419
599
|
return {
|
|
420
600
|
sessionId: readStringValue(record?.sessionId) || 'unknown',
|
|
@@ -2285,8 +2465,43 @@ export class DaemonCommandRouter {
|
|
|
2285
2465
|
const meshId = typeof args?.meshId === 'string' ? args.meshId.trim() : '';
|
|
2286
2466
|
if (!meshId) return { success: false, error: 'meshId required' };
|
|
2287
2467
|
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
2288
|
-
if (meshRecord?.mesh) return { success:
|
|
2289
|
-
|
|
2468
|
+
if (!meshRecord?.mesh) return { success: false, error: 'Mesh not found' };
|
|
2469
|
+
|
|
2470
|
+
const requireDirectPeerTruth = args?.requireDirectPeerTruth === true;
|
|
2471
|
+
const directTruth = await hydrateInlineMeshDirectTruth({
|
|
2472
|
+
mesh: meshRecord.mesh,
|
|
2473
|
+
meshSource: meshRecord.source,
|
|
2474
|
+
dispatchMeshCommand: this.deps.dispatchMeshCommand,
|
|
2475
|
+
statusInstanceId: this.deps.statusInstanceId,
|
|
2476
|
+
localMachineId: loadConfig().machineId || '',
|
|
2477
|
+
});
|
|
2478
|
+
const directTruthSatisfied = meshRecord.source !== 'inline_bootstrap' || directTruth.directEvidenceCount > 0;
|
|
2479
|
+
const sourceOfTruth = {
|
|
2480
|
+
membership: meshRecord.source === 'inline_cache'
|
|
2481
|
+
? 'coordinator_inline_mesh_cache'
|
|
2482
|
+
: meshRecord.source === 'local_config'
|
|
2483
|
+
? 'local_mesh_config'
|
|
2484
|
+
: 'inline_bootstrap_snapshot',
|
|
2485
|
+
coordinatorOwnsLiveTruth: directTruthSatisfied,
|
|
2486
|
+
directPeerTruth: {
|
|
2487
|
+
required: requireDirectPeerTruth,
|
|
2488
|
+
satisfied: directTruthSatisfied,
|
|
2489
|
+
directEvidenceCount: directTruth.directEvidenceCount,
|
|
2490
|
+
localConfirmedCount: directTruth.localConfirmedCount,
|
|
2491
|
+
peerAttemptedCount: directTruth.peerAttemptedCount,
|
|
2492
|
+
peerConfirmedCount: directTruth.peerConfirmedCount,
|
|
2493
|
+
unavailableNodeIds: directTruth.unavailableNodeIds,
|
|
2494
|
+
},
|
|
2495
|
+
};
|
|
2496
|
+
if (requireDirectPeerTruth && !directTruthSatisfied) {
|
|
2497
|
+
return {
|
|
2498
|
+
success: false,
|
|
2499
|
+
code: 'mesh_direct_peer_truth_unavailable',
|
|
2500
|
+
error: 'Selected coordinator could not confirm direct mesh truth yet. Bootstrap inventory stays unavailable until direct get_mesh probes succeed.',
|
|
2501
|
+
sourceOfTruth,
|
|
2502
|
+
};
|
|
2503
|
+
}
|
|
2504
|
+
return { success: true, mesh: meshRecord.mesh, sourceOfTruth };
|
|
2290
2505
|
}
|
|
2291
2506
|
|
|
2292
2507
|
case 'create_mesh': {
|
|
@@ -3335,29 +3550,59 @@ export class DaemonCommandRouter {
|
|
|
3335
3550
|
}
|
|
3336
3551
|
if (workspace) {
|
|
3337
3552
|
if (!fs.existsSync(workspace)) {
|
|
3338
|
-
// Workspace not local — attempt a P2P git probe
|
|
3553
|
+
// Workspace not local — prefer direct live inline truth, then attempt a P2P git probe.
|
|
3554
|
+
const inlineTransitGit = buildInlineMeshTransitGitStatus(node);
|
|
3339
3555
|
let remoteProbeApplied = false;
|
|
3340
|
-
if (
|
|
3556
|
+
if (inlineTransitGit) {
|
|
3557
|
+
status.git = inlineTransitGit;
|
|
3558
|
+
status.health = inlineTransitGit.isGitRepo
|
|
3559
|
+
? deriveMeshNodeHealthFromGit(inlineTransitGit as unknown as Record<string, unknown>)
|
|
3560
|
+
: 'degraded';
|
|
3561
|
+
remoteProbeApplied = true;
|
|
3562
|
+
} else if (!isSelfNode && daemonId && this.deps.dispatchMeshCommand) {
|
|
3341
3563
|
try {
|
|
3342
|
-
const
|
|
3343
|
-
this.deps.dispatchMeshCommand
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3564
|
+
const remoteGit = await probeRemoteMeshGitStatus({
|
|
3565
|
+
dispatchMeshCommand: this.deps.dispatchMeshCommand,
|
|
3566
|
+
daemonId,
|
|
3567
|
+
workspace,
|
|
3568
|
+
timeoutMs: 8000,
|
|
3569
|
+
});
|
|
3570
|
+
if (remoteGit) {
|
|
3348
3571
|
status.git = remoteGit;
|
|
3349
3572
|
status.health = remoteGit.isGitRepo
|
|
3350
3573
|
? deriveMeshNodeHealthFromGit(remoteGit as unknown as Record<string, unknown>)
|
|
3351
3574
|
: 'degraded';
|
|
3575
|
+
recordInlineMeshDirectGitTruth(node, remoteGit, 'selected_coordinator_mesh_p2p_git');
|
|
3352
3576
|
remoteProbeApplied = true;
|
|
3353
3577
|
}
|
|
3354
3578
|
} catch {
|
|
3355
|
-
|
|
3579
|
+
const refreshedConnection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
|
|
3580
|
+
const refreshedConnectionState = readStringValue(refreshedConnection?.state);
|
|
3581
|
+
if (refreshedConnection && refreshedConnectionState === 'connected') {
|
|
3582
|
+
status.connection = refreshedConnection;
|
|
3583
|
+
try {
|
|
3584
|
+
const remoteGit = await probeRemoteMeshGitStatus({
|
|
3585
|
+
dispatchMeshCommand: this.deps.dispatchMeshCommand,
|
|
3586
|
+
daemonId,
|
|
3587
|
+
workspace,
|
|
3588
|
+
timeoutMs: 12000,
|
|
3589
|
+
});
|
|
3590
|
+
if (remoteGit) {
|
|
3591
|
+
status.git = remoteGit;
|
|
3592
|
+
status.health = remoteGit.isGitRepo
|
|
3593
|
+
? deriveMeshNodeHealthFromGit(remoteGit as unknown as Record<string, unknown>)
|
|
3594
|
+
: 'degraded';
|
|
3595
|
+
recordInlineMeshDirectGitTruth(node, remoteGit, 'selected_coordinator_mesh_p2p_git');
|
|
3596
|
+
remoteProbeApplied = true;
|
|
3597
|
+
}
|
|
3598
|
+
} catch {
|
|
3599
|
+
// Probe timed out again or P2P unavailable — fall back to cached status
|
|
3600
|
+
}
|
|
3601
|
+
}
|
|
3356
3602
|
}
|
|
3357
3603
|
}
|
|
3358
3604
|
if (!remoteProbeApplied) {
|
|
3359
3605
|
const connectionState = readStringValue((status.connection as any)?.state);
|
|
3360
|
-
const inlineTransitGit = buildInlineMeshTransitGitStatus(node);
|
|
3361
3606
|
const pendingPeerGitProbe = !inlineTransitGit
|
|
3362
3607
|
&& !isSelfNode
|
|
3363
3608
|
&& !!daemonId
|
|
@@ -3377,12 +3622,12 @@ export class DaemonCommandRouter {
|
|
|
3377
3622
|
node,
|
|
3378
3623
|
pendingPeerGitProbe ? { skipGit: true, skipError: true, skipHealth: true } : undefined,
|
|
3379
3624
|
)) {
|
|
3380
|
-
status
|
|
3625
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
3381
3626
|
nodeStatuses.push(status);
|
|
3382
3627
|
continue;
|
|
3383
3628
|
}
|
|
3384
3629
|
if (meshRecord?.source === 'inline_cache' && !isSelfNode) {
|
|
3385
|
-
status
|
|
3630
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
3386
3631
|
nodeStatuses.push(status);
|
|
3387
3632
|
continue;
|
|
3388
3633
|
}
|
|
@@ -3391,6 +3636,7 @@ export class DaemonCommandRouter {
|
|
|
3391
3636
|
try {
|
|
3392
3637
|
const gitStatus = await getGitRepoStatus(workspace, { timeoutMs: 10_000, refreshUpstream: true });
|
|
3393
3638
|
status.git = gitStatus;
|
|
3639
|
+
recordInlineMeshDirectGitTruth(node, gitStatus as unknown as Record<string, unknown>, 'selected_coordinator_local_git');
|
|
3394
3640
|
if (gitStatus.isGitRepo) {
|
|
3395
3641
|
status.health = deriveMeshNodeHealthFromGit(gitStatus as unknown as Record<string, unknown>);
|
|
3396
3642
|
} else {
|
|
@@ -3406,7 +3652,7 @@ export class DaemonCommandRouter {
|
|
|
3406
3652
|
} else {
|
|
3407
3653
|
applyCachedInlineMeshNodeStatus(status, node);
|
|
3408
3654
|
}
|
|
3409
|
-
status
|
|
3655
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
3410
3656
|
nodeStatuses.push(status);
|
|
3411
3657
|
}
|
|
3412
3658
|
|