@adhdev/daemon-core 0.9.82-rc.365 → 0.9.82-rc.367

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.
@@ -6,6 +6,33 @@ import type { CommandResult, CommandHelpers } from './handler.js';
6
6
  import { type InputEnvelope } from '../providers/contracts.js';
7
7
  export declare const READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS = 25000;
8
8
  export declare function buildSendInputSignature(input: InputEnvelope): string;
9
+ /**
10
+ * read_chat node scope verdict. One physical daemon hosts a base node plus several
11
+ * worktree nodes; mesh_read_chat always dispatches read_chat with the requested
12
+ * node's workspace (`args.workspace`). When the resolved target session actually
13
+ * lives in a DIFFERENT worktree, returning its transcript — or worse, letting the
14
+ * native-history-by-workspace fallback splice sibling worktree turns into the
15
+ * reply — makes the coordinator believe one session received every worktree's
16
+ * work. This guard refuses a CONFIRMED cross-workspace read instead of mixing.
17
+ *
18
+ * Conservative by design (mirrors the WTCLAIM fix-B "unknown → allow" rule): only
19
+ * a session id that resolves to a known workspace which is unequal to a known
20
+ * intended workspace blocks. When either side is unknown — no targetSessionId, no
21
+ * args.workspace, an unregistered session, the coordinator self-session, or a
22
+ * plain dashboard read that never passes a node workspace — the read proceeds
23
+ * untouched, so base-node and same-daemon coordinator reads never regress.
24
+ */
25
+ export declare function evaluateReadChatNodeWorkspaceScope(args: {
26
+ targetSessionId?: string;
27
+ intendedWorkspace?: string;
28
+ sessionWorkspace?: string;
29
+ }): {
30
+ scoped: false;
31
+ } | {
32
+ scoped: true;
33
+ intended: string;
34
+ actual: string;
35
+ };
9
36
  interface DebugSanitizeOptions {
10
37
  maxDepth?: number;
11
38
  maxArrayLength?: number;
@@ -0,0 +1,3 @@
1
+ import type { HighFamilyRegistry } from './types.js';
2
+ export type { HighFamilyContext, HighFamilyHandler, HighFamilyRegistry } from './types.js';
3
+ export declare const highFamilyRegistry: HighFamilyRegistry;
@@ -0,0 +1,2 @@
1
+ import type { HighFamilyHandler } from './types.js';
2
+ export declare const meshCoordinatorLaunchHandlers: Record<string, HighFamilyHandler>;
@@ -0,0 +1,2 @@
1
+ import type { HighFamilyHandler } from './types.js';
2
+ export declare const meshEventsHandlers: Record<string, HighFamilyHandler>;
@@ -0,0 +1,2 @@
1
+ import type { HighFamilyHandler } from './types.js';
2
+ export declare const meshStatusHandlers: Record<string, HighFamilyHandler>;
@@ -0,0 +1,60 @@
1
+ /**
2
+ * RF-ROUTER HIGH family — shared types for the extracted high-coupling command
3
+ * handlers. Like the LOW and MED families, each handler is a function of
4
+ * (context, args) that returns the exact CommandRouterResult the original
5
+ * `executeDaemonCommand` switch case returned, so the router facade is unchanged.
6
+ *
7
+ * HIGH handlers are the most router-coupled of the three families: in addition to
8
+ * the MED collaborators (mesh resolution, owner gating, inline-cache), they reach
9
+ * the router's aggregate-status memory cache and running-refine-job table — state
10
+ * the router owns and the `mesh_status` aggregate render and `get_mesh_review_inbox`
11
+ * re-entry both depend on. The router binds those onto HighFamilyContext at
12
+ * dispatch; they are NOT reachable from `deps`.
13
+ *
14
+ * Registry dispatch: DaemonCommandRouter.executeDaemonCommand looks up the cmd in
15
+ * highFamilyRegistry AFTER the LOW and MED registries and BEFORE its remaining
16
+ * switch; a hit returns the handler result, a miss falls through to the switch
17
+ * (and ultimately CommandHandler delegation).
18
+ */
19
+ import type { CommandRouterDeps, CommandRouterResult, MeshGitProbeCache, MeshRefineJobHandle } from '../router.js';
20
+ import type { ResolvedMeshForCommand } from '../med-family/types.js';
21
+ /**
22
+ * Router-private collaborators injected at dispatch. Each is a bound method or
23
+ * field of DaemonCommandRouter; handlers that don't need a given collaborator
24
+ * simply ignore it. The router owns this instance state (inline-mesh cache,
25
+ * aggregate-status memory cache, running-refine-job table, git-probe cache), so
26
+ * it cannot be read from `deps` — the registry receives bound references instead.
27
+ */
28
+ export interface HighFamilyContext {
29
+ deps: CommandRouterDeps;
30
+ /** Bound `DaemonCommandRouter.getMeshForCommand`. */
31
+ getMeshForCommand: (meshId: string, inlineMesh?: unknown, options?: {
32
+ preferInline?: boolean;
33
+ }) => Promise<ResolvedMeshForCommand>;
34
+ /** Bound `DaemonCommandRouter.getCachedAggregateMeshStatus`. */
35
+ getCachedAggregateMeshStatus: (meshId: string, mesh?: any, options?: {
36
+ requireDirectPeerTruth?: boolean;
37
+ }) => any | null;
38
+ /** Bound `DaemonCommandRouter.rememberAggregateMeshStatus`. */
39
+ rememberAggregateMeshStatus: (meshId: string, snapshot: any, refreshReason: string) => any;
40
+ /**
41
+ * Bound `DaemonCommandRouter.execute`. `get_mesh_review_inbox` re-enters the
42
+ * router with a `mesh_status` refresh to obtain computed node fields; this is
43
+ * the same self-call the inlined case made.
44
+ */
45
+ execute: (cmd: string, args: any, source?: string) => Promise<CommandRouterResult>;
46
+ /** Router's aggregate-status memory cache (`.has()` probe in mesh_status). */
47
+ aggregateMeshStatusCache: Map<string, {
48
+ builtAt: number;
49
+ snapshot: any;
50
+ queueRevision: string;
51
+ }>;
52
+ /** Router's running-refine-job table (surfaced as activeRefineJobs in mesh_status). */
53
+ runningRefineJobs: Map<string, MeshRefineJobHandle>;
54
+ /** Router's inline-mesh cache (launch_mesh_coordinator caches cloud inline mesh). */
55
+ inlineMeshCache: Map<string, any>;
56
+ /** Router's mesh git-probe cache (shared probe dedup for mesh_status). */
57
+ meshGitProbeCache: MeshGitProbeCache;
58
+ }
59
+ export type HighFamilyHandler = (ctx: HighFamilyContext, args: any) => Promise<CommandRouterResult | null>;
60
+ export type HighFamilyRegistry = Map<string, HighFamilyHandler>;
@@ -14,6 +14,7 @@ import { DaemonCliManager } from './cli-manager.js';
14
14
  import type { ProviderLoader } from '../providers/provider-loader.js';
15
15
  import type { ProviderInstanceManager } from '../providers/provider-instance-manager.js';
16
16
  import { SessionRegistry } from '../sessions/registry.js';
17
+ export declare function readProviderPriorityFromPolicy(policy: unknown): string[];
17
18
  /**
18
19
  * Normalize a providerRoles array (RepoMeshNodePolicy.providerRoles) from raw
19
20
  * tool args. Each entry binds a providerType to an optional `maxParallel` cap.
@@ -28,8 +29,42 @@ export declare function normalizeProviderRoles(value: unknown): Array<{
28
29
  }>;
29
30
  export declare function readObjectRecord(value: unknown): Record<string, any>;
30
31
  export declare function readStringValue(...values: unknown[]): string | undefined;
32
+ export declare function readBooleanValue(...values: unknown[]): boolean | undefined;
33
+ export declare function summarizeRepoMeshStatusDebug(status: any): Record<string, unknown>;
34
+ export declare function logRepoMeshStatusDebug(event: string, fields: Record<string, unknown>): void;
31
35
  export declare function buildMeshNodeDisplayLabel(node: Record<string, unknown>, nodeId: string, providerPriority: string[]): string;
32
36
  export declare function readMeshNodeMachineId(node: Record<string, unknown>): string | undefined;
37
+ export declare function readMeshNodeHostname(node: Record<string, unknown>): string | undefined;
38
+ export declare function buildMeshNodeMachineIdentity(node: Record<string, unknown>, opts: {
39
+ localMachineId?: string;
40
+ localDaemonId?: string;
41
+ coordinatorHostname?: string;
42
+ isSelfNode?: boolean;
43
+ }): Record<string, unknown>;
44
+ export declare function buildInlineMeshTransitGitStatus(node: any): Record<string, unknown> | undefined;
45
+ export declare function buildLivePeerGitConnection(connection: Record<string, unknown>, timestamp?: string): Record<string, unknown>;
46
+ export declare function recordInlineMeshDirectGitTruth(node: any, git: Record<string, unknown>, source: 'selected_coordinator_local_git' | 'selected_coordinator_mesh_p2p_git'): {
47
+ reporterPlatform: string | null;
48
+ reporterArch: string | null;
49
+ };
50
+ /**
51
+ * Persist the live self-reported platform/arch onto the local meshes.json node
52
+ * record so capability-tag os=/arch= self-heals across coordinator restarts.
53
+ *
54
+ * The in-memory stamp done by recordInlineMeshDirectGitTruth lives on the
55
+ * mesh_status assembly object and is discarded after the response; only a
56
+ * `local_config` mesh has a backing meshes.json node to write through to. Inline
57
+ * cache/bootstrap meshes have no local node to update, so we no-op for them.
58
+ * Fire-and-forget (same pattern as the worktreeBootstrap writer) — a persistence
59
+ * failure must never block the status response.
60
+ */
61
+ export declare function persistNodeReporterPlatform(meshSource: 'inline_cache' | 'inline_bootstrap' | 'local_config', mesh: any, nodeId: string | undefined, reporter: {
62
+ reporterPlatform: string | null;
63
+ reporterArch: string | null;
64
+ }): void;
65
+ export declare function deriveMeshNodeHealthFromGit(git: Record<string, unknown> | null | undefined): 'online' | 'dirty' | 'degraded';
66
+ export declare function applyInlineMeshBranchConvergence(mesh: any, node: any, status: Record<string, unknown>): void;
67
+ export declare function summarizeInlineMeshBranchConvergence(nodes: Array<Record<string, unknown>>): Record<string, unknown>;
33
68
  /**
34
69
  * Resolve the owning-node attribution for a mesh node record so a coordinator can
35
70
  * stamp the TRUE owner onto a synthetic session entry instead of letting the
@@ -43,6 +78,15 @@ export declare function resolveMeshNodeAttribution(node: unknown): {
43
78
  machineName?: string;
44
79
  };
45
80
  export declare function readCachedInlineMeshActiveSessionDetails(node: any): Array<Record<string, unknown>>;
81
+ export declare function finalizeMeshNodeStatus(args: {
82
+ status: Record<string, unknown>;
83
+ node: any;
84
+ daemonId?: string;
85
+ isSelfNode: boolean;
86
+ }): void;
87
+ export declare const MESH_DIRECT_PROBE_TIMEOUT_MS: number;
88
+ export declare const MESH_DIRECT_PROBE_RETRY_TIMEOUT_MS: number;
89
+ export declare const MESH_DIRECT_PROBE_CONNECT_TIMEOUT_MS: number;
46
90
  /**
47
91
  * De-duplicates and rate-limits per-peer git_status probes so a single mesh
48
92
  * refresh — or a burst of refreshes from the dashboard auto-retry loop — cannot
@@ -73,6 +117,62 @@ export declare class MeshGitProbeCache {
73
117
  */
74
118
  probe(daemonId: string, workspace: string, probe: () => Promise<Record<string, unknown> | null>): Promise<Record<string, unknown> | null>;
75
119
  }
120
+ /**
121
+ * Await `work` under a warmup-aware deadline so a cold-open DataChannel handshake
122
+ * is NOT charged against the command response budget — the root cause of the
123
+ * "first mesh probe to a cold peer false-times-out, the warm retry succeeds"
124
+ * signature. Two budgets, switched by the live peer connection state:
125
+ *
126
+ * - While `isConnected()` returns false the peer's channel is still opening; the
127
+ * cold-open `connectTimeoutMs` budget applies. This phase is deliberately
128
+ * generous because a TURN-relayed cross-machine handshake legitimately needs
129
+ * many seconds — but a genuine connect *failure* is surfaced by `work`
130
+ * rejecting on its own (the mesh manager fails the peer the instant its
131
+ * PeerConnection state goes terminal), so a real failure is never masked for
132
+ * the whole window.
133
+ * - The first time `isConnected()` returns true the channel is warm; from that
134
+ * instant the tight `responseTimeoutMs` governs how long the handler may take.
135
+ * Warm-channel callers therefore see behavior identical to the old single
136
+ * `Promise.race(work, responseTimeoutMs)`.
137
+ *
138
+ * Rejects with `Error('timeout')` when either budget is exhausted, mirroring the
139
+ * previous single-race contract. Pure except for timers + the injected
140
+ * `isConnected` probe, so it is unit-testable under fake timers without any real
141
+ * WebRTC. When no connection getter is wired `isConnected` should be `() => true`
142
+ * (the caller's choice) so the response deadline governs from t0 — the legacy
143
+ * single-budget behavior, never a combined connect+response window.
144
+ */
145
+ export declare function awaitWithWarmupDeadline<T>(work: Promise<T>, opts: {
146
+ isConnected: () => boolean;
147
+ connectTimeoutMs: number;
148
+ responseTimeoutMs: number;
149
+ pollIntervalMs?: number;
150
+ }): Promise<T>;
151
+ /**
152
+ * Probe a remote peer's git_status with a bounded retry budget, but only while
153
+ * the peer is reported `connected`. A single slow (often TURN-relayed) peer can
154
+ * exceed one probe window; retrying — with the connection re-checked before each
155
+ * attempt so we abandon a peer that dropped — recovers it without blocking the
156
+ * mesh forever. Shared by the bootstrap hydrate path and the per-node render
157
+ * path so both treat a connected-but-slow peer identically.
158
+ *
159
+ * Returns the git status on success, or null if every attempt failed/timed out
160
+ * (caller decides how to classify). `getConnection` is consulted before each
161
+ * attempt; a non-`connected` state short-circuits the retry loop (the very first
162
+ * attempt always runs so a missing connection getter still gets one try).
163
+ */
164
+ export declare function probeRemoteMeshGitStatusWithRetry(args: {
165
+ dispatchMeshCommand?: (daemonId: string, cmd: string, args: Record<string, unknown>) => Promise<unknown>;
166
+ daemonId: string;
167
+ workspace: string;
168
+ timeoutMs: number;
169
+ /** Per-attempt timeout for retries (attempts > 0); defaults to timeoutMs. */
170
+ retryTimeoutMs?: number;
171
+ /** Cold-open warmup budget per attempt; defaults to MESH_DIRECT_PROBE_CONNECT_TIMEOUT_MS. */
172
+ connectTimeoutMs?: number;
173
+ getConnection?: (daemonId: string) => Record<string, unknown> | null;
174
+ onConnection?: (connection: Record<string, unknown>) => void;
175
+ }): Promise<Record<string, unknown> | null>;
76
176
  export declare function hydrateInlineMeshDirectTruth(args: {
77
177
  mesh: any;
78
178
  meshSource: 'inline_cache' | 'inline_bootstrap' | 'local_config';
@@ -91,6 +191,44 @@ export declare function hydrateInlineMeshDirectTruth(args: {
91
191
  unavailableNodeIds: string[];
92
192
  deadNodeIds: string[];
93
193
  }>;
194
+ export declare function summarizeMeshSessionRecord(record: any): Record<string, unknown>;
195
+ export declare function readLiveMeshNodeWorkspace(args: {
196
+ meshId: string;
197
+ nodeId: string;
198
+ liveSessionRecords: any[];
199
+ allowCoordinatorSession?: boolean;
200
+ }): string;
201
+ export declare function collectLiveMeshSessionRecords(args: {
202
+ meshId: string;
203
+ node: any;
204
+ nodeId: string;
205
+ liveSessionRecords: any[];
206
+ allowCoordinatorSession?: boolean;
207
+ }): any[];
208
+ export declare function buildHistoricalMeshSessions(args: {
209
+ meshId: string;
210
+ nodes: any[];
211
+ liveSessionRecords: any[];
212
+ }): {
213
+ count: number;
214
+ sessions: Record<string, unknown>[];
215
+ instruction: string;
216
+ } | undefined;
217
+ export declare function applyCachedInlineMeshNodeStatus(status: Record<string, unknown>, node: any, options?: {
218
+ skipGit?: boolean;
219
+ skipError?: boolean;
220
+ skipHealth?: boolean;
221
+ }): boolean;
222
+ export declare function resolveProviderTypeFromPriority(args: {
223
+ nodeId: string;
224
+ providerPriority: string[];
225
+ providerLoader: ProviderLoader;
226
+ onStatusChange?: () => void;
227
+ }): Promise<{
228
+ providerType?: string;
229
+ error?: string;
230
+ }>;
231
+ export type MeshCoordinatorConfigFormat = 'claude_mcp_json' | 'hermes_config_yaml';
94
232
  type MeshRefineStageStatus = 'passed' | 'failed' | 'skipped';
95
233
  type MeshRefinePatchEquivalenceSummary = {
96
234
  status: MeshRefineStageStatus;
@@ -149,6 +287,38 @@ type MeshRefineSubmoduleConflictHint = {
149
287
  }>;
150
288
  nextSteps: string[];
151
289
  };
290
+ type MeshRefineAsyncJobStatus = 'accepted' | 'completed' | 'failed';
291
+ export type MeshRefineJobHandle = {
292
+ success: true;
293
+ async: true;
294
+ status: MeshRefineAsyncJobStatus;
295
+ jobId: string;
296
+ interactionId: string;
297
+ meshId: string;
298
+ nodeId: string;
299
+ targetNodeId: string;
300
+ targetDaemonId?: string;
301
+ workspace?: string;
302
+ startedAt: string;
303
+ completedAt?: string;
304
+ duplicate?: boolean;
305
+ retryOfJobId?: string;
306
+ /**
307
+ * The coordinator daemon ID that initiated this refine job.
308
+ * When set, events for this job are scoped to that coordinator's
309
+ * pending-events queue instead of the shared broadcast queue.
310
+ */
311
+ targetCoordinatorDaemonId?: string;
312
+ eventDelivery: {
313
+ pendingEvents: true;
314
+ ledger: true;
315
+ };
316
+ evidence: {
317
+ pendingEventsCommand: 'get_pending_mesh_events';
318
+ ledgerCommand: 'get_mesh_ledger_slice';
319
+ taskHistoryKind: 'task_dispatched' | 'task_completed' | 'task_failed';
320
+ };
321
+ };
152
322
  /**
153
323
  * A spawn-resolution failure is when the executable itself could not be found by
154
324
  * the OS spawn boundary — `spawn <cmd> ENOENT` — as opposed to the command
@@ -270,6 +440,16 @@ export declare function collectFastForwardGitlinkPaths(repoRoot: string, baseHea
270
440
  */
271
441
  export declare function evaluateGitlinkTrivialFastForward(repoRoot: string, baseHead: string, branchHead: string): GitlinkTrivialFastForwardEvaluation;
272
442
  export declare function buildMeshRefineValidationPlan(mesh: any, workspace: string): Record<string, unknown>;
443
+ export declare function getMcpServersKey(format: MeshCoordinatorConfigFormat): 'mcpServers' | 'mcp_servers';
444
+ export declare function parseMeshCoordinatorMcpConfig(text: string, format: MeshCoordinatorConfigFormat): Record<string, any>;
445
+ export declare function serializeMeshCoordinatorMcpConfig(config: Record<string, any>, format: MeshCoordinatorConfigFormat): string;
446
+ export declare function loadHermesCoordinatorBaseConfig(targetConfigPath: string): {
447
+ config: Record<string, any>;
448
+ sourceHome: string;
449
+ sourceConfigPath: string;
450
+ };
451
+ export declare function stripHermesCoordinatorTempModelProviderOverrides(config: Record<string, any>): Record<string, any>;
452
+ export declare function copyHermesCoordinatorCredentialFiles(sourceHome: string, targetHome: string): void;
273
453
  export interface SessionHostControlPlane {
274
454
  getDiagnostics(payload?: {
275
455
  includeSessions?: boolean;
@@ -432,6 +612,17 @@ export declare class DaemonCommandRouter {
432
612
  * executeDaemonCommand('launch_ide').
433
613
  */
434
614
  private buildMedFamilyContext;
615
+ /**
616
+ * Build the HighFamilyContext handed to RF-ROUTER HIGH family handlers. Binds
617
+ * the router-private collaborators those handlers need (mesh resolution, the
618
+ * aggregate-status memory cache + its bound read/write helpers, the
619
+ * running-refine-job table, inline-mesh + git-probe caches, and the router's
620
+ * own `execute` for the get_mesh_review_inbox mesh_status re-entry). HIGH
621
+ * handlers reach more router-owned state than MED, but the binding shape is
622
+ * the same: bound methods + direct field references, none reachable from
623
+ * `deps`.
624
+ */
625
+ private buildHighFamilyContext;
435
626
  private requireMeshHostMutationOwner;
436
627
  private updateInlineMeshNode;
437
628
  private removeInlineMeshNode;
@@ -482,7 +673,58 @@ export declare class DaemonCommandRouter {
482
673
  * so the job runs to completion automatically without coordinator intervention.
483
674
  */
484
675
  resumePendingRefineJobsOnStartup(): Promise<void>;
676
+ /**
677
+ * Synchronous refinery for a single worktree node — the gate pipeline that
678
+ * validates, preflights (patch-equivalence / submodule-reachability /
679
+ * no-op), merges, aligns submodules, cleans up the worktree node and
680
+ * (optionally) pushes. The body is a flat sequence of stage methods; each
681
+ * stage either returns a terminal CommandRouterResult (gate failure or a
682
+ * successful already-merged short-circuit) or `continue` with the extended
683
+ * context. Behavior — stage order, every early-exit, and every result shape —
684
+ * is identical to the previous single inlined body.
685
+ */
485
686
  private executeMeshRefineNodeSynchronously;
687
+ /**
688
+ * resolve_refs stage: resolve the mesh / worktree node / source node /
689
+ * repoRoot, then the worktree branch, base branch, fetched base head and
690
+ * branch head. Seeds the RefineContext consumed by every later stage.
691
+ */
692
+ private refineResolveRefsStage;
693
+ /**
694
+ * validation stage: run the refinery validation gate (typecheck / test /
695
+ * lint / build per node config) and block on failure or when no allowlisted
696
+ * command was available. On pass, stores the summary on the context.
697
+ */
698
+ private refineValidationStage;
699
+ /**
700
+ * patch_equivalence stage: preflight that the worktree branch's cumulative
701
+ * patch is equivalent to base+branch. On a "behind base" branch, auto-rebase
702
+ * once and re-check; on an empty merge-tree with real branch changes, treat as
703
+ * already-merged-via-another-path and short-circuit to cleanup. Mutates the
704
+ * context's branchHead (after rebase) and patchEquivalence (rebased gate).
705
+ */
706
+ private refinePatchEquivalenceStage;
707
+ /**
708
+ * submodule_reachability stage: verify every submodule gitlink commit that
709
+ * would land via the merge is reachable from its configured remote main
710
+ * branch (optionally auto-publishing when policy allows). Blocks the merge
711
+ * when any commit is unreachable. Stores the result on the context.
712
+ */
713
+ private refineSubmoduleReachabilityStage;
714
+ /**
715
+ * effective_diff stage (no-op guard): block a silent no-op merge where the
716
+ * branch produces no effective root-tree diff against base — typically a
717
+ * submodule that has commits but whose root-level gitlink (pointer) bump was
718
+ * never committed, so the merge would land nothing real on main.
719
+ */
720
+ private refineEffectiveDiffStage;
721
+ /**
722
+ * merge + finalize stage: perform the --no-ff merge, align submodule
723
+ * checkouts after merge, clean up (remove) the worktree node per policy,
724
+ * append the refinery ledger entry, and (unless approval is required) push the
725
+ * base branch. Always terminal — produces the final CommandRouterResult.
726
+ */
727
+ private refineMergeAndFinalizeStage;
486
728
  /**
487
729
  * Batch refinery: converge multiple sibling worktree nodes onto the base branch
488
730
  * in one sequential pipeline, absorbing the rebase + patch-equivalence churn that