@adhdev/daemon-core 0.9.82-rc.209 → 0.9.82-rc.210

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.
Files changed (64) hide show
  1. package/dist/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +2 -0
  2. package/dist/commands/router.d.ts +6 -0
  3. package/dist/git/git-commands.d.ts +2 -0
  4. package/dist/git/git-diff.d.ts +6 -0
  5. package/dist/index.d.ts +11 -5
  6. package/dist/index.js +5699 -3486
  7. package/dist/index.js.map +1 -1
  8. package/dist/index.mjs +5679 -3483
  9. package/dist/index.mjs.map +1 -1
  10. package/dist/mesh/coordinator-prompt.d.ts +6 -0
  11. package/dist/mesh/mesh-delivery-policy.d.ts +5 -0
  12. package/dist/mesh/mesh-events-coordinator.d.ts +151 -0
  13. package/dist/mesh/mesh-events-pending.d.ts +33 -0
  14. package/dist/mesh/mesh-events-stale.d.ts +40 -0
  15. package/dist/mesh/mesh-events-utils.d.ts +14 -0
  16. package/dist/mesh/mesh-events.d.ts +5 -198
  17. package/dist/mesh/mesh-ledger-reconciliation.d.ts +23 -3
  18. package/dist/mesh/mesh-ledger.d.ts +19 -0
  19. package/dist/mesh/mesh-missions.d.ts +58 -0
  20. package/dist/mesh/mesh-review-inbox.d.ts +90 -0
  21. package/dist/mesh/mesh-runtime-store.d.ts +175 -0
  22. package/dist/mesh/mesh-task-stats.d.ts +49 -0
  23. package/dist/mesh/mesh-work-queue.d.ts +82 -0
  24. package/dist/mesh/refine-config.d.ts +24 -2
  25. package/dist/mesh/worktree-bootstrap-config.d.ts +22 -0
  26. package/dist/providers/acp-provider-instance.d.ts +2 -0
  27. package/dist/providers/spec/driver.d.ts +8 -0
  28. package/dist/providers/spec/evaluator.d.ts +4 -5
  29. package/dist/providers/spec/loader.d.ts +1 -0
  30. package/dist/providers/spec/schema.gen.d.ts +1409 -6
  31. package/dist/providers/spec/types.d.ts +188 -175
  32. package/dist/repo-mesh-types.d.ts +1 -0
  33. package/package.json +1 -1
  34. package/src/boot/daemon-lifecycle.ts +3 -0
  35. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +20 -7
  36. package/src/commands/router.ts +594 -66
  37. package/src/git/git-commands.ts +5 -5
  38. package/src/git/git-diff.ts +53 -0
  39. package/src/index.ts +11 -5
  40. package/src/mesh/coordinator-prompt.ts +14 -1
  41. package/src/mesh/mesh-delivery-policy.ts +17 -0
  42. package/src/mesh/mesh-events-coordinator.ts +1404 -0
  43. package/src/mesh/mesh-events-pending.ts +371 -0
  44. package/src/mesh/mesh-events-stale.ts +283 -0
  45. package/src/mesh/mesh-events-utils.ts +161 -0
  46. package/src/mesh/mesh-events.ts +27 -2143
  47. package/src/mesh/mesh-ledger-reconciliation.ts +12 -5
  48. package/src/mesh/mesh-ledger.ts +134 -2
  49. package/src/mesh/mesh-missions.ts +151 -0
  50. package/src/mesh/mesh-review-inbox.ts +307 -0
  51. package/src/mesh/mesh-runtime-store.ts +539 -3
  52. package/src/mesh/mesh-task-stats.ts +154 -0
  53. package/src/mesh/mesh-work-queue.ts +233 -17
  54. package/src/mesh/refine-config.ts +42 -5
  55. package/src/mesh/worktree-bootstrap-config.ts +79 -0
  56. package/src/providers/acp-provider-instance.ts +15 -1
  57. package/src/providers/cli-provider-instance.ts +34 -13
  58. package/src/providers/spec/driver.ts +57 -29
  59. package/src/providers/spec/evaluator.ts +302 -112
  60. package/src/providers/spec/loader.ts +226 -37
  61. package/src/providers/spec/schema.gen.ts +450 -334
  62. package/src/providers/spec/schema.json +162 -75
  63. package/src/providers/spec/types.ts +234 -183
  64. package/src/repo-mesh-types.ts +1 -0
@@ -1,67 +1,20 @@
1
1
  /**
2
- * Type mirror of adhdev:cli/spec@1. Keep in sync with schema.json.
3
- * Adding a field here without also adding it to schema.json (or vice
4
- * versa) is a bug — the loader rejects specs that don't match the
5
- * schema, so a missing field would fail at load time.
2
+ * Type mirror of adhdev:cli/spec@1 (v1) and adhdev:cli/spec@3 (v3).
3
+ * Keep in sync with schema.gen.ts.
4
+ *
5
+ * v1 uses layout.sections[] and debounce{}.
6
+ * v3 uses sections{} (object) and timing{}, with composable conditions.
7
+ *
8
+ * The loader auto-migrates v1 → v3. Callers receive a CliSpec (v3) after
9
+ * loadSpec; the v1 raw shape is only used during migration.
6
10
  */
7
11
  'use strict';
8
12
 
9
- export type Size = number | string;
13
+ // ─────────────────────────────────────────────────────────────────────────────
14
+ // Shared / unchanged types
15
+ // ─────────────────────────────────────────────────────────────────────────────
10
16
 
11
- export interface Section {
12
- id: string;
13
- from_top?: Size;
14
- from_bottom?: Size;
15
- until?: { section: string };
16
- /** Scan the screen for the first (or last, if anchor_last=true) line
17
- * matching this regex and use that line as the section start.
18
- * Combine with `lines`, `until_regex`, or leave alone (defaults to
19
- * end-of-screen) to control how far it extends. */
20
- anchor_regex?: string;
21
- anchor_flags?: string;
22
- /** If true, use the LAST matching line instead of the first. Useful
23
- * when the anchor pattern appears multiple times (e.g. separator
24
- * lines) and you want the one closest to the bottom. */
25
- anchor_last?: boolean;
26
- /** Optional neighbouring-line guards that must also match for the
27
- * anchor to be accepted. Reduces false positives when the anchor
28
- * pattern could appear elsewhere on screen (e.g. `>` in body text).
29
- * `prev` checks the line immediately above; `next` the line below. */
30
- anchor_context?: {
31
- prev?: string;
32
- prev_flags?: string;
33
- next?: string;
34
- next_flags?: string;
35
- };
36
- /** When used with anchor_regex: take at most this many lines from the
37
- * anchor point. */
38
- lines?: number;
39
- /** When used with anchor_regex: extend until the first line matching
40
- * this regex (exclusive). Takes precedence over `lines`. */
41
- until_regex?: string;
42
- until_regex_flags?: string;
43
- }
44
-
45
- export interface SectionRegex {
46
- section?: string;
47
- regex: string;
48
- flags?: string;
49
- /**
50
- * Optional cursor-position guards. When present, the state is only
51
- * considered matched if the terminal cursor row/column satisfies the
52
- * bounds (0-based, inclusive). Missing or undefined means "no constraint".
53
- *
54
- * Use case: distinguish modal zone from body zone for TUIs that use
55
- * cursor position rather than distinct text to locate the active prompt
56
- * (e.g. Antigravity cursor lands in modal_zone rows 8-31 when approval
57
- * is visible, never in body rows 0-7). Without this guard, body text
58
- * containing "Do you want to proceed?" could false-positive a modal match.
59
- */
60
- cursor_row_min?: number;
61
- cursor_row_max?: number;
62
- cursor_col_min?: number;
63
- cursor_col_max?: number;
64
- }
17
+ export type Size = number | string;
65
18
 
66
19
  export interface SectionPattern {
67
20
  section?: string;
@@ -69,27 +22,6 @@ export interface SectionPattern {
69
22
  flags?: string;
70
23
  }
71
24
 
72
- export interface ModalButtonsRule {
73
- section?: string;
74
- /** Single pattern (original). Use `patterns` for multi-format fallback. */
75
- pattern?: string;
76
- flags?: string;
77
- /** Ordered list of pattern alternatives. Evaluated in order; first that
78
- * yields >= min_count buttons wins. Mutually exclusive with `pattern`. */
79
- patterns?: Array<{ pattern: string; flags?: string }>;
80
- key_for_index: string;
81
- min_count?: number;
82
- continuation_lines?: boolean;
83
- }
84
-
85
- export interface SpecState {
86
- id: string;
87
- label: string;
88
- when: SectionRegex;
89
- extract_title?: SectionRegex;
90
- modal_buttons?: ModalButtonsRule;
91
- }
92
-
93
25
  export type ControlAction =
94
26
  | { type: 'send_keys'; keys: string }
95
27
  | {
@@ -130,23 +62,10 @@ export interface DelegateTrigger {
130
62
  * Native history config — three modes, picked by which fields are present:
131
63
  *
132
64
  * 1. `reader`: built-in reader id (claude-cli / codex-cli / antigravity-cli / hermes-cli).
133
- * Backwards-compatible path used by the four shipped providers.
134
65
  *
135
- * 2. `source`: declarative source descriptor. The daemon's spec native-history
136
- * executor reads the on-disk store (jsonl file / sqlite db) directly using
137
- * paths + jsonpath maps from this block. New providers should prefer this
138
- * mode — no daemon changes required.
66
+ * 2. `source`: declarative source descriptor.
139
67
  *
140
- * 3. `override_path`: relative path to a provider-supplied reader module
141
- * (e.g. "./native_history/index.js"). Escape hatch for formats too
142
- * exotic for the declarative executor. The module must default-export
143
- * a function with the signature
144
- * (input: NativeHistoryInput) => NativeHistoryResult | null
145
- * and runs under provider-script-root sandboxing (same gate as
146
- * scripts.js).
147
- *
148
- * The three modes are mutually exclusive — set exactly one. Loader rejects
149
- * specs that set zero or more than one.
68
+ * 3. `override_path`: relative path to a provider-supplied reader module.
150
69
  */
151
70
  export interface NativeHistoryConfig {
152
71
  reader?: 'claude-cli' | 'codex-cli' | 'antigravity-cli' | 'hermes-cli';
@@ -158,37 +77,17 @@ export type NativeHistorySource =
158
77
  | NativeHistoryJsonlSource
159
78
  | NativeHistorySqliteSource;
160
79
 
161
- /**
162
- * JSONL source — each line in the resolved file is one record.
163
- *
164
- * `path` accepts ~/, environment variables (${HOME}), and a small set of
165
- * runtime variables:
166
- * {cwd} — the session's working directory, raw
167
- * {cwd_dashed} — cwd with `/` replaced by `-` (claude's per-project key)
168
- * {session_id} — providerSessionId, when known
169
- * {yyyy} {mm} {dd} — UTC date components
170
- *
171
- * When `path` resolves to a directory, the daemon picks the newest file
172
- * matching `file_pattern` whose mtime is inside `recent_window_ms` (default
173
- * 5min) — prevents the wrong session's transcript from leaking through.
174
- */
175
80
  export interface NativeHistoryJsonlSource {
176
81
  kind: 'jsonl';
177
82
  path: string;
178
83
  file_pattern?: string;
179
84
  recent_window_ms?: number;
180
85
  session_id_from?: 'filename_uuid' | 'first_record';
181
- session_id_path?: string; // jsonpath into the first record when session_id_from='first_record'
182
- message_filter?: { where: string }; // tiny expression: field op value joined by && / ||
86
+ session_id_path?: string;
87
+ message_filter?: { where: string };
183
88
  message_map: NativeHistoryMessageMap;
184
89
  }
185
90
 
186
- /**
187
- * SQLite source — provider runs two queries on a read-only handle: one to
188
- * pick the session row (`session_query` — first row's first column is the
189
- * sessionId), then one to fetch messages (`message_query` — `?` is bound
190
- * to the sessionId). Output rows are projected through `message_map`.
191
- */
192
91
  export interface NativeHistorySqliteSource {
193
92
  kind: 'sqlite';
194
93
  path: string;
@@ -197,109 +96,261 @@ export interface NativeHistorySqliteSource {
197
96
  message_map: NativeHistoryMessageMap;
198
97
  }
199
98
 
200
- /**
201
- * Maps a source record (jsonl line object / sqlite row) to a daemon
202
- * native-history message. Values are jsonpath-lite strings: `$.foo.bar`
203
- * or `$.items[0].text`. Literal strings (no leading `$`) pass through.
204
- *
205
- * `content_strip` lets a spec drop wrapper tags that the agent injects
206
- * into its own transcript (claude's `<local-command-caveat>`, agy's
207
- * `<USER_REQUEST>` / `<ADDITIONAL_METADATA>` / `<USER_SETTINGS_CHANGE>`).
208
- * Each entry is a tag name; the executor removes `<tag>…</tag>` segments
209
- * non-greedily before the value is handed to the dashboard. After all
210
- * strips, leading/trailing whitespace is trimmed. If the result is empty
211
- * the message is dropped.
212
- */
213
99
  export interface NativeHistoryMessageMap {
214
- role: string; // → 'user' | 'assistant' | 'system' after normalize
100
+ role: string;
215
101
  content: string;
216
- /**
217
- * Tags whose entire `<tag>…</tag>` segment is removed from content.
218
- * Use for noise wrappers the agent ships alongside the real message
219
- * (claude's `<local-command-caveat>`, agy's `<ADDITIONAL_METADATA>`).
220
- */
221
102
  content_strip?: string[];
222
- /**
223
- * Tags whose open/close markers are removed but inner content is kept.
224
- * Use when the *real* user/assistant message is wrapped in a tag
225
- * the agent uses for routing (agy wraps user input in `<USER_REQUEST>`).
226
- */
227
103
  content_unwrap?: string[];
228
- timestamp_ms?: string; // optional; falls back to receivedAt = now
229
- kind?: string; // optional; defaults to 'standard'
104
+ timestamp_ms?: string;
105
+ kind?: string;
106
+ }
107
+
108
+ // ─────────────────────────────────────────────────────────────────────────────
109
+ // v1 types (legacy — used internally during migration)
110
+ // ─────────────────────────────────────────────────────────────────────────────
111
+
112
+ export interface Section {
113
+ id: string;
114
+ from_top?: Size;
115
+ from_bottom?: Size;
116
+ until?: { section: string };
117
+ anchor_regex?: string;
118
+ anchor_flags?: string;
119
+ anchor_last?: boolean;
120
+ anchor_context?: {
121
+ prev?: string;
122
+ prev_flags?: string;
123
+ next?: string;
124
+ next_flags?: string;
125
+ };
126
+ lines?: number;
127
+ until_regex?: string;
128
+ until_regex_flags?: string;
129
+ }
130
+
131
+ /** v1 condition — flat SectionRegex object. Also used in control_bar.wait_for. */
132
+ export interface SectionRegex {
133
+ section?: string;
134
+ regex?: string;
135
+ flags?: string;
136
+ cursor_row_min?: number;
137
+ cursor_row_max?: number;
138
+ cursor_col_min?: number;
139
+ cursor_col_max?: number;
140
+ /** v1 delta detection (cursor_above_lines + changed). */
141
+ cursor_above_lines?: number;
142
+ /** Required when cursor_above_lines is set. */
143
+ changed?: true;
144
+ }
145
+
146
+ export interface ModalButtonsRule {
147
+ section?: string;
148
+ pattern?: string;
149
+ flags?: string;
150
+ patterns?: Array<{ pattern: string; flags?: string }>;
151
+ key_for_index: string;
152
+ min_count?: number;
153
+ continuation_lines?: boolean;
230
154
  }
231
155
 
156
+ // ─────────────────────────────────────────────────────────────────────────────
157
+ // v3 types (current)
158
+ // ─────────────────────────────────────────────────────────────────────────────
159
+
160
+ /**
161
+ * v3 section definition — keyed by id in `sections{}` object.
162
+ * `until` is EITHER a section-id string (no `^` prefix) OR a regex string (starts with `^`).
163
+ */
164
+ export interface SectionDef {
165
+ // positional
166
+ from_top?: Size;
167
+ from_bottom?: Size;
168
+ until?: string; // section id OR regex (starts with ^)
169
+ // anchor-based
170
+ anchor?: string; // regex (replaces anchor_regex)
171
+ anchor_flags?: string;
172
+ anchor_last?: boolean;
173
+ anchor_context?: {
174
+ prev?: string;
175
+ next?: string;
176
+ prev_flags?: string;
177
+ next_flags?: string;
178
+ };
179
+ lines?: number;
180
+ until_regex?: string; // kept for anchor-based extension
181
+ until_regex_flags?: string;
182
+ }
183
+
184
+ /** v3 regex condition against a section (or full screen). */
185
+ export interface RegexCondition {
186
+ section?: string;
187
+ matches: string; // regex string
188
+ flags?: string;
189
+ cursor_row_min?: number;
190
+ cursor_row_max?: number;
191
+ cursor_col_min?: number;
192
+ cursor_col_max?: number;
193
+ }
194
+
195
+ /** v3 delta condition: N lines above cursor changed vs prevLines. */
196
+ export interface ChangedCondition {
197
+ cursor_above: number;
198
+ changed: true;
199
+ }
200
+
201
+ /** v3 AND composite. */
202
+ export interface AllCondition {
203
+ all: Condition[];
204
+ }
205
+
206
+ /** v3 OR composite. */
207
+ export interface AnyCondition {
208
+ any: Condition[];
209
+ }
210
+
211
+ export type Condition = RegexCondition | ChangedCondition | AllCondition | AnyCondition;
212
+
213
+ /** v3 extract_title config. */
214
+ export interface ExtractTitle {
215
+ section?: string;
216
+ regex?: string;
217
+ flags?: string;
218
+ first_line?: true;
219
+ }
220
+
221
+ /** v3 extract_buttons config. */
222
+ export interface ExtractButtons {
223
+ section?: string;
224
+ pattern: string;
225
+ flags?: string;
226
+ key_for_index: string;
227
+ min_count?: number;
228
+ continuation_lines?: boolean;
229
+ }
230
+
231
+ /** v3 state. */
232
+ export interface SpecStateV3 {
233
+ id: string;
234
+ label: string;
235
+ when: AllCondition | AnyCondition;
236
+ extract?: {
237
+ title?: ExtractTitle;
238
+ buttons?: ExtractButtons;
239
+ };
240
+ }
241
+
242
+ // ─────────────────────────────────────────────────────────────────────────────
243
+ // CliSpec — v3 (the canonical runtime type after loading)
244
+ // ─────────────────────────────────────────────────────────────────────────────
245
+
232
246
  export interface CliSpec {
233
- $schema: 'adhdev:cli/spec@1';
247
+ $schema: 'adhdev:cli/spec@3';
234
248
  id: string;
235
249
  name: string;
236
250
  binary: string;
237
251
  spawn_args?: string[];
238
252
  env?: Record<string, string>;
239
- /**
240
- * Optional version constraint this spec is authored for, e.g. ">=2.1.0".
241
- * Pure metadata used by tooling/UI — the actual version-to-spec match
242
- * happens in provider-loader via the manifest's compatibility array.
243
- * Spec authors include this so a misrouted spec is easy to spot.
244
- */
245
253
  cli_version_range?: string;
246
254
  send_message: {
247
255
  submit_key: string;
248
256
  delay_ms_before_submit?: number;
249
257
  delay_ms_per_char?: number;
250
258
  };
251
- layout: { sections: Section[] };
252
- states: SpecState[];
259
+ sections: Record<string, SectionDef>;
260
+ states: SpecStateV3[];
253
261
  default_state: string;
254
262
  control_bar?: Control[];
255
263
  notifications?: NotificationRule[];
256
264
  delegate?: DelegateTrigger[];
257
265
  native_history?: NativeHistoryConfig;
266
+ requiresFinalAssistantBeforeIdle?: boolean;
258
267
  /**
259
- * When true, the daemon's completed-finalization gate will not emit
260
- * `generating_completed` until native history confirms the last message
261
- * role is `assistant`. Prevents PTY quiet-period from triggering idle
262
- * before the CLI has finished writing its response to disk.
268
+ * Per-spec timing knobs. Replaces v1 `debounce`.
269
+ * Also accessible via the legacy `debounce` alias in the driver for
270
+ * backward compat with older callers.
263
271
  */
264
- requiresFinalAssistantBeforeIdle?: boolean;
272
+ timing?: {
273
+ busy_hold_ms?: number;
274
+ idle_hold_ms?: number;
275
+ startup_grace_ms?: number;
276
+ completion_marker?: {
277
+ section?: string;
278
+ matches: string;
279
+ flags?: string;
280
+ hold_ms: number;
281
+ force_after_ms?: number;
282
+ };
283
+ };
265
284
  /**
266
- * Per-spec debounce knobs. Defaults are conservative (busy_hold_ms
267
- * 6000) and live in SpecDriver. Spec authors override here when a
268
- * particular CLI flickers slower/faster than the default.
285
+ * Legacy alias: v1 callers (tests, tooling) may read `debounce`.
286
+ * The loader populates both `timing` and `debounce` pointing at the
287
+ * same object so callers that use either field see consistent values.
288
+ * @deprecated Use `timing` instead.
269
289
  */
270
290
  debounce?: {
271
- /** Min time to stay in busy after the evaluator last reported it.
272
- * Absorbs per-frame flicker in TUIs that stream output through
273
- * the same region as the spinner. */
274
291
  busy_hold_ms?: number;
275
- /** Min time the idle state must remain matched before it is
276
- * committed. Filters transient idle flickers that appear during
277
- * approval dismissals, layout reflows, or brief spinner gaps.
278
- * Any non-idle reading within the window cancels the transition.
279
- * When omitted the idle transition is immediate (legacy behaviour). */
280
292
  idle_hold_ms?: number;
281
- /** Min time after start() before a send_message is allowed to
282
- * reach the PTY. Banner paints + auth flows + skill listings
283
- * can keep the agent unable to accept input for several seconds
284
- * even though the idle regex matches a transient empty prompt.
285
- * Send_messages issued before this window are queued and drained
286
- * once the window passes and an idle state has actually been
287
- * observed. */
288
293
  startup_grace_ms?: number;
289
- /** Treat a provider-specific completion marker as idle after it has
290
- * remained visible for hold_ms. This handles TUIs that leave their
291
- * last spinner glyph next to a completed timer, causing the normal
292
- * busy regex to keep matching after the turn is done. */
294
+ /**
295
+ * Legacy field name for completion_marker. Populated by the loader
296
+ * from `timing.completion_marker` for backward compat.
297
+ */
298
+ completion_idle_after?: {
299
+ section?: string;
300
+ regex: string;
301
+ flags?: string;
302
+ hold_ms: number;
303
+ force_after_ms?: number;
304
+ };
305
+ };
306
+ }
307
+
308
+ // ─────────────────────────────────────────────────────────────────────────────
309
+ // v1 CliSpec raw shape (for migration only — not exported as the primary type)
310
+ // ─────────────────────────────────────────────────────────────────────────────
311
+
312
+ /** Raw v1 spec shape as loaded from JSON. Used only in migrateV1toV3. */
313
+ export interface RawCliSpecV1 {
314
+ $schema: 'adhdev:cli/spec@1';
315
+ id: string;
316
+ name: string;
317
+ binary: string;
318
+ spawn_args?: string[];
319
+ env?: Record<string, string>;
320
+ cli_version_range?: string;
321
+ send_message: {
322
+ submit_key: string;
323
+ delay_ms_before_submit?: number;
324
+ delay_ms_per_char?: number;
325
+ };
326
+ layout: { sections: Section[] };
327
+ states: Array<{
328
+ id: string;
329
+ label: string;
330
+ when: SectionRegex;
331
+ extract_title?: SectionRegex;
332
+ modal_buttons?: ModalButtonsRule;
333
+ }>;
334
+ default_state: string;
335
+ control_bar?: Control[];
336
+ notifications?: NotificationRule[];
337
+ delegate?: DelegateTrigger[];
338
+ native_history?: NativeHistoryConfig;
339
+ requiresFinalAssistantBeforeIdle?: boolean;
340
+ debounce?: {
341
+ busy_hold_ms?: number;
342
+ idle_hold_ms?: number;
343
+ startup_grace_ms?: number;
293
344
  completion_idle_after?: {
294
345
  section?: string;
295
346
  regex: string;
296
347
  flags?: string;
297
348
  hold_ms: number;
298
- /** If the target-state check still fails this many ms after hold_ms
299
- * expired, force an idle transition anyway. Guards against TUIs that
300
- * show transient UI (pickers, option lists) after the completion
301
- * marker appears, keeping the target-state regex from matching. */
302
349
  force_after_ms?: number;
303
350
  };
304
351
  };
305
352
  }
353
+
354
+ // Keep SpecState as alias for backward compat with cli-adapter.ts and other code
355
+ // that imports SpecState from types.ts. In v3 we use SpecStateV3.
356
+ export type SpecState = SpecStateV3;
@@ -418,6 +418,7 @@ export interface RepoMeshNodeStatus {
418
418
  worktreeBootstrap?: LocalMeshNodeEntry['worktreeBootstrap'];
419
419
  launchBlockedReason?: string;
420
420
  launchBlockedMessage?: string;
421
+ recoveryHint?: string;
421
422
  lastSeenAt?: string;
422
423
  updatedAt?: string;
423
424
  connection?: RepoMeshPeerConnectionStatus;