@adhdev/daemon-core 0.9.82-rc.326 → 0.9.82-rc.327
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/config/mesh-config.d.ts +5 -0
- package/dist/index.js +36 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +36 -11
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-work-queue.d.ts +2 -0
- package/dist/repo-mesh-types.d.ts +12 -0
- package/package.json +2 -2
- package/src/commands/router.ts +47 -6
- package/src/config/mesh-config.ts +7 -0
- package/src/mesh/mesh-work-queue.ts +28 -8
- package/src/repo-mesh-types.ts +12 -0
|
@@ -84,6 +84,8 @@ export declare function buildMeshNodeCapabilityTags(node: {
|
|
|
84
84
|
isLocalWorktree?: unknown;
|
|
85
85
|
worktreeBranch?: unknown;
|
|
86
86
|
userOverrides?: unknown;
|
|
87
|
+
reportedPlatform?: unknown;
|
|
88
|
+
reportedArch?: unknown;
|
|
87
89
|
} | undefined, providerType?: string): string[];
|
|
88
90
|
export declare function nodeSatisfiesRequiredTags(requiredTags: unknown, capabilityTags: unknown): boolean;
|
|
89
91
|
/**
|
|
@@ -418,6 +418,18 @@ export interface LocalMeshNodeEntry {
|
|
|
418
418
|
/** Operator-defined capability tags used by mesh queue matching. */
|
|
419
419
|
capabilities?: string[];
|
|
420
420
|
userOverrides: Partial<RepoMeshNodeCapabilities>;
|
|
421
|
+
/**
|
|
422
|
+
* Live, self-healed platform/arch reported by the daemon that owns this
|
|
423
|
+
* node's workspace (its own process.platform/process.arch), carried on the
|
|
424
|
+
* git_status envelope and persisted by the coordinator on each direct git
|
|
425
|
+
* probe. This is auto-detected truth, kept DISTINCT from `userOverrides`
|
|
426
|
+
* (operator intent) so capability-tag derivation can prefer an explicit
|
|
427
|
+
* operator override while still self-correcting auto-detected nodes — and so
|
|
428
|
+
* a stale value is overwritten by the next report rather than sticking.
|
|
429
|
+
* Absent until the first direct probe succeeds.
|
|
430
|
+
*/
|
|
431
|
+
reportedPlatform?: string;
|
|
432
|
+
reportedArch?: string;
|
|
421
433
|
policy: RepoMeshNodePolicy;
|
|
422
434
|
/**
|
|
423
435
|
* Per-node instruction surfaced in the coordinator prompt so the LLM
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adhdev/daemon-core",
|
|
3
|
-
"version": "0.9.82-rc.
|
|
3
|
+
"version": "0.9.82-rc.327",
|
|
4
4
|
"description": "ADHDev daemon core — CDP, IDE detection, providers, command execution",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"author": "vilmire",
|
|
47
47
|
"license": "AGPL-3.0-or-later",
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@adhdev/mesh-shared": "0.9.82-rc.
|
|
49
|
+
"@adhdev/mesh-shared": "0.9.82-rc.327",
|
|
50
50
|
"@adhdev/session-host-core": "*",
|
|
51
51
|
"@agentclientprotocol/sdk": "^0.16.1",
|
|
52
52
|
"ajv": "^8.20.0",
|
package/src/commands/router.ts
CHANGED
|
@@ -407,8 +407,10 @@ function recordInlineMeshDirectGitTruth(
|
|
|
407
407
|
node: any,
|
|
408
408
|
git: Record<string, unknown>,
|
|
409
409
|
source: 'selected_coordinator_local_git' | 'selected_coordinator_mesh_p2p_git',
|
|
410
|
-
):
|
|
411
|
-
if (!node || typeof node !== 'object' || Array.isArray(node))
|
|
410
|
+
): { reporterPlatform: string | null; reporterArch: string | null } {
|
|
411
|
+
if (!node || typeof node !== 'object' || Array.isArray(node)) {
|
|
412
|
+
return { reporterPlatform: null, reporterArch: null };
|
|
413
|
+
}
|
|
412
414
|
const checkedAt = readNumberValue(git.lastCheckedAt) ?? Date.now();
|
|
413
415
|
const updatedAt = new Date(checkedAt).toISOString();
|
|
414
416
|
const nextGit: Record<string, unknown> = {
|
|
@@ -439,6 +441,13 @@ function recordInlineMeshDirectGitTruth(
|
|
|
439
441
|
const reporterPlatform = readStringValue(git.reporterPlatform) ?? (isLocalSource ? process.platform : null);
|
|
440
442
|
const reporterArch = readStringValue(git.reporterArch) ?? (isLocalSource ? process.arch : null);
|
|
441
443
|
stampNodeReporterPlatform(node, reporterPlatform, reporterArch);
|
|
444
|
+
// Mirror onto the in-memory node's dedicated reporter fields too (distinct
|
|
445
|
+
// from userOverrides). For a local_config mesh the caller also persists these
|
|
446
|
+
// to meshes.json via updateNode so the value survives a coordinator restart;
|
|
447
|
+
// for an inline/cache mesh this keeps the runtime object self-consistent.
|
|
448
|
+
if (reporterPlatform) node.reportedPlatform = reporterPlatform;
|
|
449
|
+
if (reporterArch) node.reportedArch = reporterArch;
|
|
450
|
+
return { reporterPlatform, reporterArch };
|
|
442
451
|
}
|
|
443
452
|
|
|
444
453
|
/**
|
|
@@ -460,6 +469,34 @@ function stampNodeReporterPlatform(node: any, platform: string | null, arch: str
|
|
|
460
469
|
if (changed) node.userOverrides = overrides;
|
|
461
470
|
}
|
|
462
471
|
|
|
472
|
+
/**
|
|
473
|
+
* Persist the live self-reported platform/arch onto the local meshes.json node
|
|
474
|
+
* record so capability-tag os=/arch= self-heals across coordinator restarts.
|
|
475
|
+
*
|
|
476
|
+
* The in-memory stamp done by recordInlineMeshDirectGitTruth lives on the
|
|
477
|
+
* mesh_status assembly object and is discarded after the response; only a
|
|
478
|
+
* `local_config` mesh has a backing meshes.json node to write through to. Inline
|
|
479
|
+
* cache/bootstrap meshes have no local node to update, so we no-op for them.
|
|
480
|
+
* Fire-and-forget (same pattern as the worktreeBootstrap writer) — a persistence
|
|
481
|
+
* failure must never block the status response.
|
|
482
|
+
*/
|
|
483
|
+
function persistNodeReporterPlatform(
|
|
484
|
+
meshSource: 'inline_cache' | 'inline_bootstrap' | 'local_config',
|
|
485
|
+
mesh: any,
|
|
486
|
+
nodeId: string | undefined,
|
|
487
|
+
reporter: { reporterPlatform: string | null; reporterArch: string | null },
|
|
488
|
+
): void {
|
|
489
|
+
if (meshSource !== 'local_config') return;
|
|
490
|
+
const meshId = readStringValue(mesh?.id);
|
|
491
|
+
if (!meshId || !nodeId) return;
|
|
492
|
+
const reportedPlatform = reporter.reporterPlatform ?? undefined;
|
|
493
|
+
const reportedArch = reporter.reporterArch ?? undefined;
|
|
494
|
+
if (!reportedPlatform && !reportedArch) return;
|
|
495
|
+
void import('../config/mesh-config.js')
|
|
496
|
+
.then(({ updateNode }) => updateNode(meshId, nodeId, { reportedPlatform, reportedArch }))
|
|
497
|
+
.catch(() => { /* best-effort self-heal; never block status assembly */ });
|
|
498
|
+
}
|
|
499
|
+
|
|
463
500
|
function buildCachedInlineMeshGitStatus(node: any): Record<string, unknown> | undefined {
|
|
464
501
|
const liveGit = buildInlineMeshTransitGitStatus(node);
|
|
465
502
|
if (liveGit) return liveGit;
|
|
@@ -1323,7 +1360,8 @@ async function hydrateInlineMeshDirectTruth(args: {
|
|
|
1323
1360
|
try {
|
|
1324
1361
|
const localGit = await getGitRepoStatus(workspace, { timeoutMs: 10_000, refreshUpstream: true });
|
|
1325
1362
|
if (localGit?.isGitRepo) {
|
|
1326
|
-
recordInlineMeshDirectGitTruth(node, localGit as unknown as Record<string, unknown>, 'selected_coordinator_local_git');
|
|
1363
|
+
const reporter = recordInlineMeshDirectGitTruth(node, localGit as unknown as Record<string, unknown>, 'selected_coordinator_local_git');
|
|
1364
|
+
persistNodeReporterPlatform(args.meshSource, args.mesh, nodeId, reporter);
|
|
1327
1365
|
localConfirmedCount += 1;
|
|
1328
1366
|
continue;
|
|
1329
1367
|
}
|
|
@@ -1375,7 +1413,8 @@ async function hydrateInlineMeshDirectTruth(args: {
|
|
|
1375
1413
|
? await args.probeCache.probe(daemonId, workspace, runProbe)
|
|
1376
1414
|
: await runProbe();
|
|
1377
1415
|
if (remoteGit) {
|
|
1378
|
-
recordInlineMeshDirectGitTruth(node, remoteGit, 'selected_coordinator_mesh_p2p_git');
|
|
1416
|
+
const reporter = recordInlineMeshDirectGitTruth(node, remoteGit, 'selected_coordinator_mesh_p2p_git');
|
|
1417
|
+
persistNodeReporterPlatform(args.meshSource, args.mesh, nodeId, reporter);
|
|
1379
1418
|
peerConfirmedCount += 1;
|
|
1380
1419
|
continue;
|
|
1381
1420
|
}
|
|
@@ -9299,7 +9338,8 @@ export class DaemonCommandRouter {
|
|
|
9299
9338
|
if (!connectionReported || connectionState === 'unknown') {
|
|
9300
9339
|
status.connection = buildLivePeerGitConnection(connection, refreshedAt);
|
|
9301
9340
|
}
|
|
9302
|
-
recordInlineMeshDirectGitTruth(node, remoteGit, 'selected_coordinator_mesh_p2p_git');
|
|
9341
|
+
const reporter = recordInlineMeshDirectGitTruth(node, remoteGit, 'selected_coordinator_mesh_p2p_git');
|
|
9342
|
+
persistNodeReporterPlatform(meshRecord.source, mesh, nodeId, reporter);
|
|
9303
9343
|
remoteProbeApplied = true;
|
|
9304
9344
|
}
|
|
9305
9345
|
}
|
|
@@ -9340,7 +9380,8 @@ export class DaemonCommandRouter {
|
|
|
9340
9380
|
try {
|
|
9341
9381
|
const gitStatus = await getGitRepoStatus(workspace, { timeoutMs: 10_000, refreshUpstream: true });
|
|
9342
9382
|
status.git = gitStatus;
|
|
9343
|
-
recordInlineMeshDirectGitTruth(node, gitStatus as unknown as Record<string, unknown>, 'selected_coordinator_local_git');
|
|
9383
|
+
const reporter = recordInlineMeshDirectGitTruth(node, gitStatus as unknown as Record<string, unknown>, 'selected_coordinator_local_git');
|
|
9384
|
+
persistNodeReporterPlatform(meshRecord.source, mesh, nodeId, reporter);
|
|
9344
9385
|
if (gitStatus.isGitRepo) {
|
|
9345
9386
|
status.health = deriveMeshNodeHealthFromGit(gitStatus as unknown as Record<string, unknown>);
|
|
9346
9387
|
} else {
|
|
@@ -604,6 +604,11 @@ export function updateNode(
|
|
|
604
604
|
/** Per-node instruction surfaced in the coordinator prompt. Pass an
|
|
605
605
|
* empty string or undefined to clear it. */
|
|
606
606
|
systemPrompt?: string;
|
|
607
|
+
/** Live self-reported platform/arch from the owning daemon's git_status
|
|
608
|
+
* envelope. Persisted distinctly from userOverrides (auto-detected, not
|
|
609
|
+
* operator intent) so capability-tag os=/arch= self-heals across loads. */
|
|
610
|
+
reportedPlatform?: string;
|
|
611
|
+
reportedArch?: string;
|
|
607
612
|
},
|
|
608
613
|
): LocalMeshNodeEntry | undefined {
|
|
609
614
|
const config = loadMeshConfig();
|
|
@@ -614,6 +619,8 @@ export function updateNode(
|
|
|
614
619
|
if (!node) return undefined;
|
|
615
620
|
|
|
616
621
|
if (opts.userOverrides) node.userOverrides = { ...node.userOverrides, ...opts.userOverrides };
|
|
622
|
+
if (opts.reportedPlatform && opts.reportedPlatform.trim()) node.reportedPlatform = opts.reportedPlatform.trim();
|
|
623
|
+
if (opts.reportedArch && opts.reportedArch.trim()) node.reportedArch = opts.reportedArch.trim();
|
|
617
624
|
if (opts.policy) node.policy = { ...node.policy, ...opts.policy };
|
|
618
625
|
if (opts.worktreeBootstrap) node.worktreeBootstrap = opts.worktreeBootstrap;
|
|
619
626
|
if (Object.prototype.hasOwnProperty.call(opts, 'systemPrompt')) {
|
|
@@ -385,8 +385,20 @@ function readNodeOverride(node: { userOverrides?: unknown } | undefined, key: 'p
|
|
|
385
385
|
return typeof value === 'string' && value.trim() ? value.trim() : null;
|
|
386
386
|
}
|
|
387
387
|
|
|
388
|
+
/**
|
|
389
|
+
* Live, self-reported platform/arch the owning daemon stamped onto the node from
|
|
390
|
+
* its own process.platform/process.arch via the git_status envelope. Kept on a
|
|
391
|
+
* field DISTINCT from userOverrides so capability-tag derivation can prefer an
|
|
392
|
+
* explicit operator override while still self-healing auto-detected nodes — and
|
|
393
|
+
* so the value reflects the node's real OS rather than the coordinator's.
|
|
394
|
+
*/
|
|
395
|
+
function readNodeReporter(node: { reportedPlatform?: unknown; reportedArch?: unknown } | undefined, key: 'platform' | 'arch'): string | null {
|
|
396
|
+
const value = key === 'platform' ? node?.reportedPlatform : node?.reportedArch;
|
|
397
|
+
return typeof value === 'string' && value.trim() ? value.trim() : null;
|
|
398
|
+
}
|
|
399
|
+
|
|
388
400
|
export function buildMeshNodeCapabilityTags(
|
|
389
|
-
node: { capabilities?: unknown; policy?: unknown; isLocalWorktree?: unknown; worktreeBranch?: unknown; userOverrides?: unknown } | undefined,
|
|
401
|
+
node: { capabilities?: unknown; policy?: unknown; isLocalWorktree?: unknown; worktreeBranch?: unknown; userOverrides?: unknown; reportedPlatform?: unknown; reportedArch?: unknown } | undefined,
|
|
390
402
|
providerType?: string,
|
|
391
403
|
): string[] {
|
|
392
404
|
const provider = typeof providerType === 'string' && providerType.trim()
|
|
@@ -395,17 +407,25 @@ export function buildMeshNodeCapabilityTags(
|
|
|
395
407
|
const worktreeBranch = typeof node?.worktreeBranch === 'string' && node.worktreeBranch.trim()
|
|
396
408
|
? node.worktreeBranch.trim()
|
|
397
409
|
: null;
|
|
398
|
-
// Per-node platform/arch
|
|
399
|
-
//
|
|
400
|
-
//
|
|
401
|
-
//
|
|
402
|
-
//
|
|
410
|
+
// Per-node platform/arch precedence (highest → lowest):
|
|
411
|
+
// 1. userOverrides.platform/arch — an EXPLICIT operator override always wins.
|
|
412
|
+
// 2. reportedPlatform/reportedArch — the live OS the owning daemon
|
|
413
|
+
// self-reported (its own process.platform/process.arch via the git_status
|
|
414
|
+
// envelope), persisted to the node record on each direct probe. This is
|
|
415
|
+
// why a Windows member advertises os=win32 even though the COORDINATOR
|
|
416
|
+
// computing these tags runs on darwin — without it the consumer reads the
|
|
417
|
+
// persistent node (operator userOverrides empty) and would fall straight
|
|
418
|
+
// through to the coordinator's own process.platform, mislabeling every
|
|
419
|
+
// node os=darwin. We prefer this LIVE value over any stale auto-stamp.
|
|
420
|
+
// 3. process.platform/process.arch — last-resort fallback, correct only for
|
|
421
|
+
// the local coordinator node / local worktree nodes that have not yet
|
|
422
|
+
// been probed (their workspace lives on THIS machine anyway).
|
|
403
423
|
// Vocabulary is raw process.platform/process.arch ("darwin"/"win32"/"linux",
|
|
404
424
|
// "arm64"/"x64") on both the advertiser and the required_tags matcher, which
|
|
405
425
|
// compares with plain string equality (nodeSatisfiesRequiredTags) — so this
|
|
406
426
|
// keeps the win32/darwin/linux vocabulary the matcher already expects.
|
|
407
|
-
const os = readNodeOverride(node, 'platform') ?? process.platform;
|
|
408
|
-
const arch = readNodeOverride(node, 'arch') ?? process.arch;
|
|
427
|
+
const os = readNodeOverride(node, 'platform') ?? readNodeReporter(node, 'platform') ?? process.platform;
|
|
428
|
+
const arch = readNodeOverride(node, 'arch') ?? readNodeReporter(node, 'arch') ?? process.arch;
|
|
409
429
|
return normalizeMeshCapabilityTags([
|
|
410
430
|
...(Array.isArray(node?.capabilities) ? node.capabilities : []),
|
|
411
431
|
`os=${os}`,
|
package/src/repo-mesh-types.ts
CHANGED
|
@@ -533,6 +533,18 @@ export interface LocalMeshNodeEntry {
|
|
|
533
533
|
/** Operator-defined capability tags used by mesh queue matching. */
|
|
534
534
|
capabilities?: string[];
|
|
535
535
|
userOverrides: Partial<RepoMeshNodeCapabilities>;
|
|
536
|
+
/**
|
|
537
|
+
* Live, self-healed platform/arch reported by the daemon that owns this
|
|
538
|
+
* node's workspace (its own process.platform/process.arch), carried on the
|
|
539
|
+
* git_status envelope and persisted by the coordinator on each direct git
|
|
540
|
+
* probe. This is auto-detected truth, kept DISTINCT from `userOverrides`
|
|
541
|
+
* (operator intent) so capability-tag derivation can prefer an explicit
|
|
542
|
+
* operator override while still self-correcting auto-detected nodes — and so
|
|
543
|
+
* a stale value is overwritten by the next report rather than sticking.
|
|
544
|
+
* Absent until the first direct probe succeeds.
|
|
545
|
+
*/
|
|
546
|
+
reportedPlatform?: string;
|
|
547
|
+
reportedArch?: string;
|
|
536
548
|
policy: RepoMeshNodePolicy;
|
|
537
549
|
/**
|
|
538
550
|
* Per-node instruction surfaced in the coordinator prompt so the LLM
|