@adhdev/mesh-shared 1.0.60-rc.73 → 1.0.60-rc.74

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/json.d.ts CHANGED
@@ -9,7 +9,11 @@
9
9
  */
10
10
  export type JsonRecord = Record<string, unknown>;
11
11
  export declare function readRecord(value: unknown): JsonRecord;
12
+ /** A plain-object record, or undefined — for callers that must tell "absent" from "empty". */
13
+ export declare function readOptionalRecord(value: unknown): JsonRecord | undefined;
12
14
  export declare function readString(...values: unknown[]): string | undefined;
15
+ /** The first non-blank trimmed string, or '' — readString for callers that want a plain string. */
16
+ export declare function readText(...values: unknown[]): string;
13
17
  export declare function readNumber(...values: unknown[]): number | undefined;
14
18
  export declare function readBoolean(...values: unknown[]): boolean | undefined;
15
19
  export declare function readStringArray(value: unknown): string[];
@@ -18,10 +18,10 @@
18
18
  * Order mirrors mcp-server `ALL_MESH_TOOLS` for easy visual diffing, but the consistency
19
19
  * checks are set-based (order-insensitive).
20
20
  */
21
- export declare const CANONICAL_MESH_TOOL_NAMES: readonly ["mesh_status", "mesh_route_preview", "mesh_list_nodes", "mesh_enqueue_batch", "mesh_enqueue_task", "mesh_view_queue", "mesh_graph_view", "mesh_graph_gate", "mesh_graph_node_patch", "mesh_queue_cancel", "mesh_queue_requeue", "mesh_send_task", "mesh_read_chat", "mesh_read_debug", "mesh_read_terminal", "mesh_send_keys", "mesh_launch_session", "mesh_git_status", "mesh_read_node_logs", "mesh_fast_forward_node", "mesh_restart_daemon", "mesh_checkpoint", "mesh_approve", "mesh_answer_question", "mesh_list_pending_approvals", "mesh_create", "mesh_add_node", "mesh_clone_node", "mesh_remove_node", "mesh_cleanup_worktree_nodes", "mesh_refine_node", "mesh_refine_batch", "mesh_config", "mesh_init", "mesh_refine_plan", "mesh_cleanup_sessions", "mesh_task_history", "mesh_ledger_query", "mesh_note", "mesh_reconcile_ledger", "mesh_mission_upsert", "mesh_mission_list", "mesh_review_inbox", "mesh_magi_review", "mesh_magi_collect", "mesh_magi_kind_panel", "mesh_node_slots", "mesh_coordinator_prompt_append"];
21
+ export declare const CANONICAL_MESH_TOOL_NAMES: readonly ["mesh_status", "mesh_route_preview", "mesh_list_nodes", "mesh_enqueue_batch", "mesh_enqueue_task", "mesh_view_queue", "mesh_queue_cancel", "mesh_queue_requeue", "mesh_send_task", "mesh_read_chat", "mesh_read_debug", "mesh_read_terminal", "mesh_send_keys", "mesh_launch_session", "mesh_git_status", "mesh_read_node_logs", "mesh_fast_forward_node", "mesh_restart_daemon", "mesh_checkpoint", "mesh_approve", "mesh_answer_question", "mesh_list_pending_approvals", "mesh_create", "mesh_add_node", "mesh_clone_node", "mesh_remove_node", "mesh_cleanup_worktree_nodes", "mesh_refine_node", "mesh_refine_batch", "mesh_config", "mesh_init", "mesh_refine_plan", "mesh_cleanup_sessions", "mesh_task_history", "mesh_ledger_query", "mesh_note", "mesh_reconcile_ledger", "mesh_mission_upsert", "mesh_mission_list", "mesh_review_inbox", "mesh_node_slots", "mesh_coordinator_prompt_append"];
22
22
  export type CanonicalMeshToolName = typeof CANONICAL_MESH_TOOL_NAMES[number];
23
23
  /** The count the `NN tools` barrel doc comments and consistency test assert against. */
24
- export declare const CANONICAL_MESH_TOOL_COUNT: 48;
24
+ export declare const CANONICAL_MESH_TOOL_COUNT: 42;
25
25
  /**
26
26
  * Tool names retired by the 2026-09-26 tool-surface consolidation (60 → 48).
27
27
  * Every capability behind them is still reachable: each retired name maps to the
@@ -33,8 +33,7 @@ export declare const CANONICAL_MESH_TOOL_COUNT: 48;
33
33
  * test asserts none of these names is advertised anywhere in the prompt.
34
34
  *
35
35
  * `args` is the discriminator to add; every other argument keeps its name.
36
- * `note` covers the one rename where an argument moved (the old
37
- * `mesh_graph_gate_claim({ extend_seconds })` extend-only mode).
36
+ * `note` carries any extra guidance when an argument moved in a rename.
38
37
  */
39
38
  export declare const RETIRED_MESH_TOOLS: Readonly<Record<string, {
40
39
  readonly tool: CanonicalMeshToolName;
@@ -42,8 +41,13 @@ export declare const RETIRED_MESH_TOOLS: Readonly<Record<string, {
42
41
  readonly note?: string;
43
42
  }>>;
44
43
  /**
45
- * The error text for a call to a retired tool name, or null when `name` is not
46
- * retired. One wording shared by every MCP mode so the redirect reads the same
47
- * wherever an old prompt calls it.
44
+ * Tool names removed outright (no merged replacement), mapped to the guidance a
45
+ * coordinator on an old prompt needs to do the same job with the remaining tools.
46
+ */
47
+ export declare const REMOVED_MESH_TOOLS: Readonly<Record<string, string>>;
48
+ /**
49
+ * The error text for a call to a retired or removed tool name, or null when
50
+ * `name` is neither. One wording shared by every MCP mode so the redirect reads
51
+ * the same wherever an old prompt calls it.
48
52
  */
49
53
  export declare function retiredMeshToolError(name: string): string | null;
@@ -38,8 +38,7 @@ export type MeshThinkingLevel = typeof MESH_THINKING_LEVELS[number];
38
38
  export declare const MESH_DELIVERY_MODES: readonly ["when_idle", "interrupt"];
39
39
  export type MeshDeliveryMode = typeof MESH_DELIVERY_MODES[number];
40
40
  /**
41
- * What to do with a node's sessions when the node is removed or a MAGI fan-out
42
- * settles. Declared here so daemon-core (`RepoMeshSessionCleanupMode`), the
41
+ * What to do with a node's sessions when the node is removed. Declared here so daemon-core (`RepoMeshSessionCleanupMode`), the
43
42
  * web dashboard picker and the MCP schemas all read one list.
44
43
  */
45
44
  export declare const MESH_SESSION_CLEANUP_MODES: readonly ["preserve", "stop", "delete_stopped", "stop_and_delete"];
@@ -132,9 +132,8 @@ export type SendRefusal = 'not_ready' | 'send_in_flight' | 'not_generating' | 'n
132
132
  * a turn is generating (`send_now`). Written, not yet answered;
133
133
  * `interrupt` — the turn in flight was stopped first, then this body was
134
134
  * written (or re-parked) as a new turn;
135
- * `acp` — handed to an ACP agent's `session/prompt`.
136
135
  */
137
- export type SubmitRoute = 'pty' | 'agent_queue' | 'interrupt' | 'acp';
136
+ export type SubmitRoute = 'pty' | 'agent_queue' | 'interrupt';
138
137
  /** The stop key pressed by an `interrupt` submit (logs / operator display). */
139
138
  export interface SubmitInterruptDetail {
140
139
  keyName: string;
@@ -157,11 +157,6 @@ export type AuthOkWirePayload = {
157
157
  machineNickname: string | null;
158
158
  seqscribeFleetSecret?: string;
159
159
  seqscribeFleetSecretVersion?: number;
160
- /** Beacon board seed for cold start (advisory, may be absent). */
161
- beaconSeed?: {
162
- reports: unknown[];
163
- truncated: number;
164
- };
165
160
  limits: AuthOkPlanLimits;
166
161
  };
167
162
  export type AuthErrorWirePayload = {
@@ -207,14 +202,6 @@ export type DaemonErrorWirePayload = {
207
202
  message?: string;
208
203
  detail?: unknown;
209
204
  };
210
- export type BeaconVectorsWirePayload = {
211
- op: 'put';
212
- report: unknown;
213
- } | {
214
- op: 'get';
215
- topics: string[];
216
- requestId: string;
217
- };
218
205
  export declare const P2P_SIGNAL_TYPES: readonly ["p2p_ready", "p2p_offer", "p2p_answer", "p2p_ice"];
219
206
  export type P2PSignalType = typeof P2P_SIGNAL_TYPES[number];
220
207
  export declare const isP2PSignalType: (value: unknown) => value is "p2p_ready" | "p2p_offer" | "p2p_answer" | "p2p_ice";
@@ -258,9 +245,9 @@ export declare const isMeshP2PSignalType: (value: unknown) => value is "mesh_p2p
258
245
  export type MeshP2PSignalWirePayload = {
259
246
  senderDaemonId: string;
260
247
  } & Record<string, unknown>;
261
- export declare const DAEMON_TO_SERVER_TYPES: readonly ["auth", "status_report", "status_heartbeat", "status_event", "command_result", "error", "agent_event", "beacon_vectors", "daemon_mesh_command", "p2p_offer", "p2p_ice"];
248
+ export declare const DAEMON_TO_SERVER_TYPES: readonly ["auth", "status_report", "status_heartbeat", "status_event", "command_result", "error", "agent_event", "daemon_mesh_command", "p2p_offer", "p2p_ice"];
262
249
  export type DaemonToServerType = typeof DAEMON_TO_SERVER_TYPES[number];
263
- export declare const isDaemonToServerType: (value: unknown) => value is "error" | "p2p_offer" | "p2p_ice" | "auth" | "status_report" | "status_heartbeat" | "status_event" | "command_result" | "agent_event" | "beacon_vectors" | "daemon_mesh_command";
250
+ export declare const isDaemonToServerType: (value: unknown) => value is "error" | "p2p_offer" | "p2p_ice" | "auth" | "status_report" | "status_heartbeat" | "status_event" | "command_result" | "agent_event" | "daemon_mesh_command";
264
251
  export type DaemonAuthMsg = Envelope<'auth', DaemonAuthWirePayload>;
265
252
  export type StatusReportMsg = Envelope<'status_report', CloudStatusReportWirePayload>;
266
253
  export type StatusHeartbeatMsg = Envelope<'status_heartbeat', StatusHeartbeatWirePayload>;
@@ -269,7 +256,6 @@ export type CommandResultMsg = Envelope<'command_result', CommandResultWirePaylo
269
256
  export type DaemonErrorMsg = Envelope<'error', DaemonErrorWirePayload>;
270
257
  /** Agent-level event forwarded verbatim to the `agent:status` webhook (throttled server-side). Dynamic by design. */
271
258
  export type AgentEventMsg = Envelope<'agent_event', CommandPayload>;
272
- export type BeaconVectorsMsg = Envelope<'beacon_vectors', BeaconVectorsWirePayload>;
273
259
  export type DaemonP2POfferMsg = Envelope<'p2p_offer', P2POfferWirePayload>;
274
260
  export type DaemonP2PIceMsg = Envelope<'p2p_ice', P2PIceWirePayload>;
275
261
  /**
@@ -285,7 +271,7 @@ export type DaemonMeshCommandMsg = {
285
271
  args: Record<string, unknown>;
286
272
  timestamp: number;
287
273
  };
288
- export type DaemonToServerMsg = DaemonAuthMsg | StatusReportMsg | StatusHeartbeatMsg | DaemonStatusEventMsg | CommandResultMsg | DaemonErrorMsg | AgentEventMsg | BeaconVectorsMsg | DaemonMeshCommandMsg | DaemonP2POfferMsg | DaemonP2PIceMsg;
274
+ export type DaemonToServerMsg = DaemonAuthMsg | StatusReportMsg | StatusHeartbeatMsg | DaemonStatusEventMsg | CommandResultMsg | DaemonErrorMsg | AgentEventMsg | DaemonMeshCommandMsg | DaemonP2POfferMsg | DaemonP2PIceMsg;
289
275
  /** Members that carry a `payload` object (everything except `daemon_mesh_command`). */
290
276
  export type DaemonToServerPayloadType = Exclude<DaemonToServerMsg, DaemonMeshCommandMsg>['type'];
291
277
  export type DaemonToServerPayloadOf<T extends DaemonToServerPayloadType> = Extract<DaemonToServerMsg, {
@@ -297,9 +283,9 @@ export type DaemonToServerPayloadOf<T extends DaemonToServerPayloadType> = Extra
297
283
  * token string because nothing downstream can proceed without one.
298
284
  */
299
285
  export declare function decodeDaemonToServer(raw: unknown): DaemonToServerMsg | null;
300
- export declare const SERVER_TO_DAEMON_CONTROL_TYPES: readonly ["auth_ok", "auth_error", "machine_evicted", "force_disconnect", "token_revoked", "version_mismatch", "force_update_required", "command", "agent_command", "resolve_action", "beacon_vectors_result", "daemon_mesh_result", "p2p_ready", "p2p_offer", "p2p_answer", "p2p_ice", "mesh_p2p_ready", "mesh_p2p_offer", "mesh_p2p_answer", "mesh_p2p_ice"];
286
+ export declare const SERVER_TO_DAEMON_CONTROL_TYPES: readonly ["auth_ok", "auth_error", "machine_evicted", "force_disconnect", "token_revoked", "version_mismatch", "force_update_required", "command", "agent_command", "resolve_action", "daemon_mesh_result", "p2p_ready", "p2p_offer", "p2p_answer", "p2p_ice", "mesh_p2p_ready", "mesh_p2p_offer", "mesh_p2p_answer", "mesh_p2p_ice"];
301
287
  export type ServerToDaemonControlType = typeof SERVER_TO_DAEMON_CONTROL_TYPES[number];
302
- export declare const isServerToDaemonControlType: (value: unknown) => value is "p2p_ready" | "p2p_offer" | "p2p_answer" | "p2p_ice" | "mesh_p2p_ready" | "mesh_p2p_offer" | "mesh_p2p_answer" | "mesh_p2p_ice" | "command" | "auth_ok" | "auth_error" | "machine_evicted" | "force_disconnect" | "token_revoked" | "version_mismatch" | "force_update_required" | "agent_command" | "resolve_action" | "beacon_vectors_result" | "daemon_mesh_result";
288
+ export declare const isServerToDaemonControlType: (value: unknown) => value is "p2p_ready" | "p2p_offer" | "p2p_answer" | "p2p_ice" | "mesh_p2p_ready" | "mesh_p2p_offer" | "mesh_p2p_answer" | "mesh_p2p_ice" | "command" | "auth_ok" | "auth_error" | "machine_evicted" | "force_disconnect" | "token_revoked" | "version_mismatch" | "force_update_required" | "agent_command" | "resolve_action" | "daemon_mesh_result";
303
289
  /** Optional routing fields the server stamps on relayed commands. */
304
290
  type ServerRelayFields = {
305
291
  id?: MessageId;
@@ -324,15 +310,6 @@ export type ServerAgentCommandMsg = Envelope<'agent_command', {
324
310
  export type ServerResolveActionMsg = Envelope<'resolve_action', CommandPayload> & ServerRelayFields;
325
311
  export type ServerP2PSignalMsg = Envelope<P2PSignalType, RelayedP2PSignalWirePayload> & ServerRelayFields;
326
312
  export type ServerMeshP2PSignalMsg = Envelope<MeshP2PSignalType, MeshP2PSignalWirePayload> & ServerRelayFields;
327
- /** Reply to a `beacon_vectors` GET, correlated by `requestId` (top-level, no payload). A PUT gets no reply. */
328
- export type BeaconVectorsResultMsg = {
329
- type: 'beacon_vectors_result';
330
- requestId: string;
331
- success: boolean;
332
- reports?: unknown[];
333
- truncated?: number;
334
- error?: string;
335
- };
336
313
  /** Correlated ack/nack of a `daemon_mesh_command` (top-level, no payload). */
337
314
  export type DaemonMeshResultMsg = {
338
315
  type: 'daemon_mesh_result';
@@ -341,7 +318,7 @@ export type DaemonMeshResultMsg = {
341
318
  result?: unknown;
342
319
  error?: string;
343
320
  };
344
- export type ServerToDaemonControlMsg = AuthOkMsg | AuthErrorMsg | MachineEvictedMsg | ForceDisconnectMsg | TokenRevokedMsg | VersionMismatchMsg | ForceUpdateRequiredMsg | ServerCommandMsg | ServerAgentCommandMsg | ServerResolveActionMsg | BeaconVectorsResultMsg | DaemonMeshResultMsg | ServerP2PSignalMsg | ServerMeshP2PSignalMsg;
321
+ export type ServerToDaemonControlMsg = AuthOkMsg | AuthErrorMsg | MachineEvictedMsg | ForceDisconnectMsg | TokenRevokedMsg | VersionMismatchMsg | ForceUpdateRequiredMsg | ServerCommandMsg | ServerAgentCommandMsg | ServerResolveActionMsg | DaemonMeshResultMsg | ServerP2PSignalMsg | ServerMeshP2PSignalMsg;
345
322
  declare const directCommandBrand: unique symbol;
346
323
  /**
347
324
  * A command name relayed as the frame `type` — the OPEN namespace the REST API
@@ -364,7 +341,7 @@ export type ServerToDaemonMsg = ServerToDaemonControlMsg | ServerDirectCommandMs
364
341
  export type ServerToDaemonType = ServerToDaemonMsg['type'];
365
342
  export declare function isServerDirectCommandMsg(msg: ServerToDaemonMsg): msg is ServerDirectCommandMsg;
366
343
  /** Members of the control set that carry a `payload` object. */
367
- export type ServerToDaemonPayloadType = Exclude<ServerToDaemonControlMsg, BeaconVectorsResultMsg | DaemonMeshResultMsg>['type'];
344
+ export type ServerToDaemonPayloadType = Exclude<ServerToDaemonControlMsg, DaemonMeshResultMsg>['type'];
368
345
  export type ServerToDaemonPayloadOf<T extends ServerToDaemonPayloadType> = Extract<ServerToDaemonControlMsg, {
369
346
  type: T;
370
347
  }>['payload'];
@@ -372,7 +349,7 @@ export declare function isDaemonDirectCommandType(value: unknown): value is Daem
372
349
  /**
373
350
  * Parse boundary for the daemon: is `raw` a frame this link accepts from the server?
374
351
  * Control members are checked for their discriminant and envelope shape; the
375
- * two payload-less replies need their `requestId`; any other well-formed
352
+ * payload-less `daemon_mesh_result` reply needs its `requestId`; any other well-formed
376
353
  * command name becomes a `ServerDirectCommandMsg`.
377
354
  */
378
355
  export declare function decodeServerToDaemon(raw: unknown): ServerToDaemonMsg | null;
@@ -19,14 +19,6 @@
19
19
  * passed through {@link sanitizeModelIdentifier}) and `modelSource` (an enum,
20
20
  * passed through {@link isModelAxisSource}). Never widen that to the record.
21
21
  */
22
- /**
23
- * Where a model / thinking-level value came from.
24
- *
25
- * `restore` is deliberately NOT a member: a hosted session re-attached after a
26
- * daemon restart keeps the ORIGINAL source (the user still picked that model);
27
- * only `SessionLaunchRecord.launchedBy` records that the session came back via
28
- * restore.
29
- */
30
22
  export declare const MODEL_AXIS_SOURCES: readonly ["user", "remembered", "mesh_slot", "task_override", "provider_default", "unspecified"];
31
23
  export type ModelAxisSource = typeof MODEL_AXIS_SOURCES[number];
32
24
  export declare function isModelAxisSource(value: unknown): value is ModelAxisSource;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * CLI auto-detect → capability-slot / MAGI-panel PROPOSAL generator.
2
+ * CLI auto-detect → capability-slot PROPOSAL generator.
3
3
  *
4
4
  * Detection of installed CLI providers already exists per node (the status
5
5
  * snapshot's `availableProviders`), and applying a slot profile already exists
@@ -27,7 +27,6 @@
27
27
  * need it, and it is pure data + pure functions on plain objects.
28
28
  */
29
29
  import { type MeshTaskDifficulty, type NodeCapabilitySlot } from './brain-routing';
30
- import type { MagiSlot } from './magi';
31
30
  /**
32
31
  * One provider's seeded slot recipe. A provider may map to MORE THAN ONE slot
33
32
  * (claude-cli does: a wide sonnet slot plus a narrow opus slot for the hard
@@ -120,28 +119,3 @@ export interface SlotProposal {
120
119
  * returned proposal can report what a wholesale write would destroy.
121
120
  */
122
121
  export declare function buildSlotProposal(detected: readonly DetectedCliProvider[], currentSlots?: readonly NodeCapabilitySlot[]): SlotProposal;
123
- /**
124
- * Build a MAGI panel proposal from the same detections.
125
- *
126
- * ─── Deliberately narrow ──────────────────────────────────────────────────────
127
- *
128
- * MAGI's value is provider INDEPENDENCE: replicas from different providers
129
- * (ideally different machines) answering the same question, so agreement means
130
- * something. Detection tells us which providers exist — that is exactly enough
131
- * to propose one panel of distinct providers, and no more.
132
- *
133
- * What detection does NOT tell us is which provider suits which review KIND
134
- * (rca vs design vs claim_audit). Nothing in any manifest grades a provider for
135
- * root-cause analysis over design review, and inventing a per-kind assignment
136
- * would fabricate a rationale that does not exist. So this proposes ONE panel of
137
- * the detected providers and leaves the kind binding to the operator; the caller
138
- * decides which `task_kind` to bind it to via the existing dry-run tool.
139
- *
140
- * Ordering follows {@link CLI_SLOT_RECIPES} insertion order (recipe-known
141
- * providers first, in table order), so the panel leads with the providers whose
142
- * suitability is actually attested.
143
- */
144
- export declare function buildMagiPanelProposal(detected: readonly DetectedCliProvider[], opts?: {
145
- nodeId?: string;
146
- maxSlots?: number;
147
- }): MagiSlot[];
@@ -7,8 +7,6 @@ import { TURN_IPC_PROTOCOL_VERSION } from './turn-ipc-guards';
7
7
  export declare const MESH_MISSION_STATUSES: readonly ["active", "paused", "completed", "abandoned"];
8
8
  export type MeshMissionStatusValue = typeof MESH_MISSION_STATUSES[number];
9
9
  export declare const isMeshMissionStatusValue: (value: unknown) => value is "active" | "completed" | "paused" | "abandoned";
10
- export declare const MESH_MISSION_SOURCES: readonly ["magi", "coordinator"];
11
- export type MeshMissionSourceValue = typeof MESH_MISSION_SOURCES[number];
12
10
  export interface MissionBriefWire {
13
11
  goal: string;
14
12
  constraints?: readonly string[];
@@ -25,7 +23,6 @@ export interface MissionUpsertRequest {
25
23
  /** Free text — see file-header note on why this is fine over local IPC. */
26
24
  goal?: string;
27
25
  status?: MeshMissionStatusValue;
28
- source?: MeshMissionSourceValue;
29
26
  /**
30
27
  * H2: `undefined` = do not touch the stored brief. `null` = explicitly clear it.
31
28
  * A present object with no usable `goal` is treated by the daemon's own
@@ -40,7 +37,6 @@ export interface MeshMissionRecordWire {
40
37
  title: string;
41
38
  goal: string;
42
39
  status: MeshMissionStatusValue;
43
- source?: MeshMissionSourceValue;
44
40
  /** H2: absent = no brief attached to this mission. */
45
41
  brief?: MissionBriefWire;
46
42
  }
@@ -68,7 +64,6 @@ export interface MissionListQueryRequest {
68
64
  meshId: string;
69
65
  statuses?: readonly MeshMissionStatusValue[];
70
66
  verbose?: boolean;
71
- includeMagi?: boolean;
72
67
  withStats?: boolean;
73
68
  limit?: number;
74
69
  historyIdLimit?: number;
@@ -110,7 +105,6 @@ export interface MissionListSummaryVerboseWire {
110
105
  title: string;
111
106
  goal: string;
112
107
  status: MeshMissionStatusValue;
113
- source?: MeshMissionSourceValue;
114
108
  tasks: MeshMissionTaskAggregateWire;
115
109
  stats?: MeshMissionStatsWire;
116
110
  /** H2: absent = no brief attached. */
@@ -128,7 +122,6 @@ export interface MissionListSummarySlimWire {
128
122
  goalPreview: string;
129
123
  goalTruncated: boolean;
130
124
  status: MeshMissionStatusValue;
131
- source?: MeshMissionSourceValue;
132
125
  tasks: MeshMissionTaskAggregateWire;
133
126
  stats?: MeshMissionStatsWire;
134
127
  /** H2: absent = no brief attached. */
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * turn-ipc — local records, queue composites and active work (C-W9a):
3
- * record_local, queue_query, queue_enqueue, queue_enqueue_graph, queue_cancel,
4
- * queue_requeue, direct_dispatch_record, graph_audit_record, active_work_query,
3
+ * record_local, queue_query, queue_enqueue, queue_enqueue_batch, queue_cancel,
4
+ * queue_requeue, direct_dispatch_record, active_work_query,
5
5
  * recovery_context_query. Part of the turn-ipc wire contract (./turn-ipc.ts).
6
6
  */
7
7
  import { TURN_IPC_PROTOCOL_VERSION } from './turn-ipc-guards';
@@ -47,7 +47,7 @@ export interface QueueQueryRequest {
47
47
  /** With `withCounts`: also count terminal rows whose `updated_at` is older than this age. */
48
48
  historicalOlderThanMs?: number;
49
49
  /**
50
- * Also return `dependencyHeads`: id/status/blockedReason/cancelReason of every
50
+ * Also return `dependencyHeads`: id/status/cancelReason of every
51
51
  * row the returned entries list in `dependsOn` that is not itself returned —
52
52
  * enough to annotate dependency state without reading the whole queue.
53
53
  */
@@ -57,7 +57,6 @@ export interface QueueQueryRequest {
57
57
  export interface QueueDependencyHeadWire {
58
58
  id: string;
59
59
  status: string;
60
- blockedReason?: string;
61
60
  cancelReason?: string;
62
61
  }
63
62
  export interface QueueQueryResponse {
@@ -77,37 +76,29 @@ export interface QueueEnqueueRequest {
77
76
  /** Free text (the task message — see the section note). */
78
77
  message: string;
79
78
  options?: Record<string, unknown>;
80
- /** `recordSingleEnqueueDecision` args minus `taskId` (the daemon fills it). */
81
- decision?: Record<string, unknown>;
82
79
  }
83
80
  export interface QueueEnqueueResponse {
84
81
  entry: QueueEntryWire;
85
82
  }
86
83
  export declare function decodeQueueEnqueueRequest(value: unknown): QueueEnqueueRequest | null;
87
84
  export declare function decodeQueueEnqueueResponse(value: unknown): QueueEnqueueResponse | null;
88
- export interface QueueEnqueueGraphRequest {
85
+ export interface QueueEnqueueBatchRequest {
89
86
  v: typeof TURN_IPC_PROTOCOL_VERSION;
90
87
  meshId: string;
91
- mode: 'compat' | 'graph';
92
- /** compat: `MeshTaskGraphEntrySpec[]` (JSON passthrough). */
93
- specs?: readonly Record<string, unknown>[];
94
- /** graph: `commitMeshGraphPlan` input minus `meshId` (JSON passthrough). */
95
- plan?: Record<string, unknown>;
96
- /** Audit context: batchId / missionId / coordinatorSessionId / onDependencyFailure / orchestrationDecision / taskCount. */
97
- audit?: Record<string, unknown>;
98
- }
99
- export type QueueEnqueueGraphResponse = {
88
+ /** `MeshTaskBatchEntrySpec[]` (daemon-core, JSON passthrough). */
89
+ specs: readonly Record<string, unknown>[];
90
+ }
91
+ export type QueueEnqueueBatchResponse = {
100
92
  ok: true;
101
93
  tasks: readonly QueueEntryWire[];
102
- graph?: Record<string, unknown>;
103
94
  } | {
104
95
  ok: false;
105
96
  refusalCode?: string;
106
97
  message: string;
107
98
  extra?: Record<string, unknown>;
108
99
  };
109
- export declare function decodeQueueEnqueueGraphRequest(value: unknown): QueueEnqueueGraphRequest | null;
110
- export declare function decodeQueueEnqueueGraphResponse(value: unknown): QueueEnqueueGraphResponse | null;
100
+ export declare function decodeQueueEnqueueBatchRequest(value: unknown): QueueEnqueueBatchRequest | null;
101
+ export declare function decodeQueueEnqueueBatchResponse(value: unknown): QueueEnqueueBatchResponse | null;
111
102
  export interface QueueCancelRequest {
112
103
  v: typeof TURN_IPC_PROTOCOL_VERSION;
113
104
  meshId: string;
@@ -143,28 +134,12 @@ export interface DirectDispatchRecordRequest {
143
134
  message: string;
144
135
  /** `recordDirectDispatchTask` options minus `id` (JSON passthrough). */
145
136
  task?: Record<string, unknown>;
146
- /** `recordDirectDispatchDecision` args minus `taskId` (JSON passthrough). */
147
- decision?: Record<string, unknown>;
148
137
  }
149
138
  export interface DirectDispatchRecordResponse {
150
139
  taskRecorded: boolean;
151
- decisionRecorded: boolean;
152
140
  }
153
141
  export declare function decodeDirectDispatchRecordRequest(value: unknown): DirectDispatchRecordRequest | null;
154
142
  export declare function decodeDirectDispatchRecordResponse(value: unknown): DirectDispatchRecordResponse | null;
155
- export declare const GRAPH_AUDIT_EVENTS: readonly ["gate_claimed", "gate_released", "gate_abandoned", "node_patched"];
156
- export type GraphAuditEvent = typeof GRAPH_AUDIT_EVENTS[number];
157
- export interface GraphAuditRecordRequest {
158
- v: typeof TURN_IPC_PROTOCOL_VERSION;
159
- meshId: string;
160
- event: GraphAuditEvent;
161
- fields: Record<string, unknown>;
162
- }
163
- export interface GraphAuditRecordResponse {
164
- recorded: boolean;
165
- }
166
- export declare function decodeGraphAuditRecordRequest(value: unknown): GraphAuditRecordRequest | null;
167
- export declare function decodeGraphAuditRecordResponse(value: unknown): GraphAuditRecordResponse | null;
168
143
  export interface ActiveWorkQueryRequest {
169
144
  v: typeof TURN_IPC_PROTOCOL_VERSION;
170
145
  meshId: string;
@@ -0,0 +1,72 @@
1
+ /**
2
+ * turn-ipc — task stats and maintenance commands: task_stats_query,
3
+ * prune_stale_direct, orphaned_pin_notify. Part of the turn-ipc wire contract
4
+ * (./turn-ipc.ts).
5
+ */
6
+ import { TURN_IPC_PROTOCOL_VERSION } from './turn-ipc-guards';
7
+ export interface TaskStatsQueryRequest {
8
+ v: typeof TURN_IPC_PROTOCOL_VERSION;
9
+ meshId: string;
10
+ taskIds?: readonly string[];
11
+ missionId?: string;
12
+ tail?: number;
13
+ /** Also compute `computeMeshMissionStats` — requires `missionId`. */
14
+ rollup?: boolean;
15
+ /**
16
+ * Batch rollups: `computeMeshMissionStats` for every id, over ONE queue read and
17
+ * ONE record read (answers `missions`, `tasks` empty). Exclusive with
18
+ * `taskIds`/`missionId`. An older daemon rejects the key.
19
+ */
20
+ missionIds?: readonly string[];
21
+ }
22
+ export interface TaskStatsQueryResponse {
23
+ /** `MeshTaskStats[]`, JSON passthrough. */
24
+ tasks: readonly Record<string, unknown>[];
25
+ /** `MeshMissionStats`, JSON passthrough; present only when `rollup: true` was requested and satisfiable. */
26
+ mission?: Record<string, unknown>;
27
+ /** Batch mode: `MeshMissionStats` per requested mission id, JSON passthrough. */
28
+ missions?: Record<string, Record<string, unknown>>;
29
+ }
30
+ export declare function decodeTaskStatsQueryRequest(value: unknown): TaskStatsQueryRequest | null;
31
+ export declare function decodeTaskStatsQueryResponse(value: unknown): TaskStatsQueryResponse | null;
32
+ export interface PruneStaleDirectRequest {
33
+ v: typeof TURN_IPC_PROTOCOL_VERSION;
34
+ meshId: string;
35
+ execute?: boolean;
36
+ includeTerminal?: boolean;
37
+ source?: string;
38
+ }
39
+ export interface PruneStaleDirectResponse {
40
+ mode: 'execute' | 'dry_run';
41
+ includeTerminal: boolean;
42
+ candidateCount: number;
43
+ /** `MeshActiveWorkRecord[]`, JSON passthrough. */
44
+ prunable: readonly Record<string, unknown>[];
45
+ prunedCount: number;
46
+ preservedUnacknowledged: readonly Record<string, unknown>[];
47
+ preservedLedgerOnly: readonly Record<string, unknown>[];
48
+ preservedNotOrphan: readonly Record<string, unknown>[];
49
+ }
50
+ export declare function decodePruneStaleDirectRequest(value: unknown): PruneStaleDirectRequest | null;
51
+ export declare function decodePruneStaleDirectResponse(value: unknown): PruneStaleDirectResponse | null;
52
+ export interface OrphanedPinNotifyRequest {
53
+ v: typeof TURN_IPC_PROTOCOL_VERSION;
54
+ meshId: string;
55
+ stoppedSessionId: string;
56
+ excludeTaskId?: string;
57
+ cause?: string;
58
+ nodeId?: string;
59
+ coordinatorSessionId?: string;
60
+ }
61
+ export interface OrphanedPinnedTaskWire {
62
+ taskId: string;
63
+ title: string;
64
+ targetSessionId: string;
65
+ targetNodeId?: string;
66
+ missionId?: string;
67
+ }
68
+ export interface OrphanedPinNotifyResponse {
69
+ orphans: readonly OrphanedPinnedTaskWire[];
70
+ }
71
+ export declare function decodeOrphanedPinNotifyRequest(value: unknown): OrphanedPinNotifyRequest | null;
72
+ export declare function decodeOrphanedPinNotifyResponse(value: unknown): OrphanedPinNotifyResponse | null;
@@ -52,14 +52,14 @@
52
52
  * LAYOUT
53
53
  * -------
54
54
  * This module holds the error codes and the command registry; the per-command
55
- * contracts live in ./turn-ipc-{turn,mission,queue,graph}.ts (re-exported here)
55
+ * contracts live in ./turn-ipc-{turn,mission,queue,stats}.ts (re-exported here)
56
56
  * over the shared guard primitives in ./turn-ipc-guards.ts.
57
57
  */
58
58
  export { TURN_IPC_PROTOCOL_VERSION } from './turn-ipc-guards';
59
59
  export * from './turn-ipc-turn';
60
60
  export * from './turn-ipc-mission';
61
61
  export * from './turn-ipc-queue';
62
- export * from './turn-ipc-graph';
62
+ export * from './turn-ipc-stats';
63
63
  /**
64
64
  * Closed error-code union every command response may carry instead of (or in
65
65
  * addition to, for the client-side wrapper) a result.
@@ -85,6 +85,6 @@ export interface TurnIpcError {
85
85
  }
86
86
  export declare function isTurnIpcError(value: unknown): value is TurnIpcError;
87
87
  /** The complete, closed set of IPC command names this contract defines. */
88
- export declare const TURN_IPC_COMMANDS: readonly ["turn_observe", "mesh_record", "turn_cancel", "operator_status", "turn_query", "mesh_index_query", "mission_upsert", "mission_query", "note_upsert", "note_forget", "tool_call_record", "ledger_query", "mission_list_query", "record_local", "queue_query", "queue_enqueue", "queue_enqueue_graph", "queue_cancel", "queue_requeue", "direct_dispatch_record", "graph_audit_record", "active_work_query", "recovery_context_query", "graph_gate_claim", "graph_gate_release", "graph_gate_abandon", "graph_node_patch", "graph_view_query", "task_stats_query", "prune_stale_direct", "orphaned_pin_notify"];
88
+ export declare const TURN_IPC_COMMANDS: readonly ["turn_observe", "mesh_record", "turn_cancel", "operator_status", "turn_query", "mesh_index_query", "mission_upsert", "mission_query", "note_upsert", "note_forget", "tool_call_record", "ledger_query", "mission_list_query", "record_local", "queue_query", "queue_enqueue", "queue_enqueue_batch", "queue_cancel", "queue_requeue", "direct_dispatch_record", "active_work_query", "recovery_context_query", "task_stats_query", "prune_stale_direct", "orphaned_pin_notify"];
89
89
  export type TurnIpcCommand = typeof TURN_IPC_COMMANDS[number];
90
- export declare const isTurnIpcCommand: (value: unknown) => value is "prune_stale_direct" | "operator_status" | "turn_observe" | "mesh_record" | "turn_cancel" | "turn_query" | "mesh_index_query" | "mission_upsert" | "mission_query" | "note_upsert" | "note_forget" | "tool_call_record" | "ledger_query" | "mission_list_query" | "record_local" | "queue_query" | "queue_enqueue" | "queue_enqueue_graph" | "queue_cancel" | "queue_requeue" | "direct_dispatch_record" | "graph_audit_record" | "active_work_query" | "recovery_context_query" | "graph_gate_claim" | "graph_gate_release" | "graph_gate_abandon" | "graph_node_patch" | "graph_view_query" | "task_stats_query" | "orphaned_pin_notify";
90
+ export declare const isTurnIpcCommand: (value: unknown) => value is "prune_stale_direct" | "operator_status" | "turn_observe" | "mesh_record" | "turn_cancel" | "turn_query" | "mesh_index_query" | "mission_upsert" | "mission_query" | "note_upsert" | "note_forget" | "tool_call_record" | "ledger_query" | "mission_list_query" | "record_local" | "queue_query" | "queue_enqueue" | "queue_enqueue_batch" | "queue_cancel" | "queue_requeue" | "direct_dispatch_record" | "active_work_query" | "recovery_context_query" | "task_stats_query" | "orphaned_pin_notify";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/mesh-shared",
3
- "version": "1.0.60-rc.73",
3
+ "version": "1.0.60-rc.74",
4
4
  "description": "ADHDev mesh-shared — pure mesh/git status normalizers shared by daemon-core and web-core",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -5,10 +5,8 @@
5
5
  * per-difficulty "brain" preset resolves that into a concrete provider / model /
6
6
  * thinking-level for the launched session. The goal is token economy: an `easy`
7
7
  * task runs on a cheaper model at low reasoning effort; a `difficult` task gets a
8
- * stronger model at high effort. This is a separate axis from MAGI's review kinds
9
- * (rca/design/…) — MAGI fans out review replicas; this picks the single brain that
10
- * *executes* a task — but it reuses the same slot shape (provider/model) and the
11
- * same machine-local storage (`~/.adhdev/meshes.json`).
8
+ * stronger model at high effort. This picks the single brain that *executes* a
9
+ * task, stored machine-local (`~/.adhdev/meshes.json`).
12
10
  */
13
11
 
14
12
  /** The fixed difficulty axis the coordinator classifies a task into. */
@@ -33,8 +31,8 @@ export interface BrainSlot {
33
31
 
34
32
  /**
35
33
  * Per-difficulty brain bindings for ONE mesh, stored machine-local in
36
- * `~/.adhdev/meshes.json` under that mesh's entry (`meshes[].difficultyBrains`,
37
- * sibling of `magiKindPanels`). The scope is per mesh: two meshes on the same
34
+ * `~/.adhdev/meshes.json` under that mesh's entry (`meshes[].difficultyBrains`).
35
+ * The scope is per mesh: two meshes on the same
38
36
  * machine hold independent presets, so one can pin `difficult` to a cheaper model
39
37
  * without changing what any other mesh runs. (It formerly sat at the config root
40
38
  * keyed by difficulty alone — and since this map picks the MODEL a task runs on,
@@ -118,8 +116,8 @@ export function normalizeDifficultyBrainMap(raw: unknown): DifficultyBrainMap {
118
116
  // capability slots. Each slot bundles what used to be scattered across
119
117
  // providerPriority (order), a per-provider maxParallel cap, and the
120
118
  // the owning mesh's difficultyBrains (difficulty → model/thinking). Slot order =
121
- // preference. This single profile is the source of truth for task routing, MAGI
122
- // fan-out, and orchestrator-proposed edits.
119
+ // preference. This single profile is the source of truth for task routing and
120
+ // orchestrator-proposed edits.
123
121
  // ─────────────────────────────────────────────────────────────────────────────
124
122
 
125
123
  /**
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Projection of a daemon `git_diff_file` answer into the per-file row the MCP
3
+ * `git_diff` tool and the cloud git-diff shortcut both return: the diff text
4
+ * capped at `maxLines` (with a visible truncation marker), plus the file's
5
+ * change metadata from the diff summary.
6
+ */
7
+
8
+ import { readRecord } from './json'
9
+
10
+ export interface GitFileDiffRow {
11
+ path: string
12
+ old_path?: string | null
13
+ status?: string
14
+ diff: string
15
+ truncated: boolean
16
+ binary: boolean
17
+ error?: string
18
+ }
19
+
20
+ /** Cap diff text at `maxLines`; a truncated diff ends with a `... (truncated)` marker line. */
21
+ function truncateDiffText(text: string, maxLines: number): { diff: string; truncated: boolean } {
22
+ const lines = text.split('\n')
23
+ const truncated = lines.length > maxLines
24
+ return {
25
+ diff: truncated ? lines.slice(0, maxLines).join('\n') + '\n... (truncated)' : text,
26
+ truncated,
27
+ }
28
+ }
29
+
30
+ /** One changed file's row from its `git_diff_file` answer (either `{ diff: {...} }` or the bare diff record). */
31
+ export function projectFileDiffRow(
32
+ file: { path: string; oldPath?: string | null; status?: string },
33
+ rawResult: unknown,
34
+ maxLines: number,
35
+ ): GitFileDiffRow {
36
+ const raw = readRecord(rawResult)
37
+ const d = readRecord(raw.diff ?? rawResult)
38
+ const text = typeof d.diff === 'string' ? d.diff : ''
39
+ const { diff, truncated } = truncateDiffText(text, maxLines)
40
+ return {
41
+ path: file.path,
42
+ old_path: file.oldPath ?? null,
43
+ status: file.status ?? 'M',
44
+ diff,
45
+ truncated,
46
+ binary: typeof d.binary === 'boolean' ? d.binary : false,
47
+ }
48
+ }
package/src/index.ts CHANGED
@@ -19,7 +19,7 @@ export * from './node-facts'
19
19
  export * from './workspace-normalize'
20
20
  export * from './daemon-normalize'
21
21
  export * from './git-summarize'
22
- export * from './magi'
22
+ export * from './git-diff'
23
23
  export * from './brain-routing'
24
24
  export * from './slot-proposal'
25
25
  export * from './interpolation'
package/src/json.ts CHANGED
@@ -14,6 +14,11 @@ export function readRecord(value: unknown): JsonRecord {
14
14
  return value && typeof value === 'object' && !Array.isArray(value) ? value as JsonRecord : {}
15
15
  }
16
16
 
17
+ /** A plain-object record, or undefined — for callers that must tell "absent" from "empty". */
18
+ export function readOptionalRecord(value: unknown): JsonRecord | undefined {
19
+ return value && typeof value === 'object' && !Array.isArray(value) ? value as JsonRecord : undefined
20
+ }
21
+
17
22
  export function readString(...values: unknown[]): string | undefined {
18
23
  for (const value of values) {
19
24
  if (typeof value !== 'string') continue
@@ -23,6 +28,11 @@ export function readString(...values: unknown[]): string | undefined {
23
28
  return undefined
24
29
  }
25
30
 
31
+ /** The first non-blank trimmed string, or '' — readString for callers that want a plain string. */
32
+ export function readText(...values: unknown[]): string {
33
+ return readString(...values) ?? ''
34
+ }
35
+
26
36
  export function readNumber(...values: unknown[]): number | undefined {
27
37
  for (const value of values) {
28
38
  if (typeof value === 'number' && Number.isFinite(value)) return value