@wrongstack/core 0.1.9 → 0.2.0

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 (69) hide show
  1. package/dist/agent-bridge-DmBiCipY.d.ts +33 -0
  2. package/dist/compactor-DSl2FK7a.d.ts +17 -0
  3. package/dist/config-DXrqb41m.d.ts +193 -0
  4. package/dist/{provider-txgB0Oq9.d.ts → context-u0bryklF.d.ts} +540 -472
  5. package/dist/coordination/index.d.ts +892 -0
  6. package/dist/coordination/index.js +2869 -0
  7. package/dist/coordination/index.js.map +1 -0
  8. package/dist/defaults/index.d.ts +34 -2309
  9. package/dist/defaults/index.js +5610 -4608
  10. package/dist/defaults/index.js.map +1 -1
  11. package/dist/events-B6Q03pTu.d.ts +290 -0
  12. package/dist/execution/index.d.ts +260 -0
  13. package/dist/execution/index.js +1625 -0
  14. package/dist/execution/index.js.map +1 -0
  15. package/dist/index.d.ts +81 -11
  16. package/dist/index.js +7727 -6174
  17. package/dist/index.js.map +1 -1
  18. package/dist/infrastructure/index.d.ts +10 -0
  19. package/dist/infrastructure/index.js +575 -0
  20. package/dist/infrastructure/index.js.map +1 -0
  21. package/dist/input-reader-E-ffP2ee.d.ts +12 -0
  22. package/dist/kernel/index.d.ts +15 -4
  23. package/dist/kernel/index.js.map +1 -1
  24. package/dist/logger-BH6AE0W9.d.ts +24 -0
  25. package/dist/logger-BMQgxvdy.d.ts +12 -0
  26. package/dist/mcp-servers-BA1Ofmfj.d.ts +100 -0
  27. package/dist/memory-CEXuo7sz.d.ts +16 -0
  28. package/dist/mode-CV077NjV.d.ts +27 -0
  29. package/dist/models/index.d.ts +60 -0
  30. package/dist/models/index.js +621 -0
  31. package/dist/models/index.js.map +1 -0
  32. package/dist/models-registry-DqzwpBQy.d.ts +46 -0
  33. package/dist/models-registry-Y2xbog0E.d.ts +95 -0
  34. package/dist/multi-agent-BDfkxL5C.d.ts +351 -0
  35. package/dist/observability/index.d.ts +353 -0
  36. package/dist/observability/index.js +691 -0
  37. package/dist/observability/index.js.map +1 -0
  38. package/dist/observability-BhnVLBLS.d.ts +67 -0
  39. package/dist/path-resolver-CPRj4bFY.d.ts +10 -0
  40. package/dist/path-resolver-Crkt8wTQ.d.ts +54 -0
  41. package/dist/plugin-CoYYZKdn.d.ts +447 -0
  42. package/dist/renderer-0A2ZEtca.d.ts +158 -0
  43. package/dist/sdd/index.d.ts +206 -0
  44. package/dist/sdd/index.js +864 -0
  45. package/dist/sdd/index.js.map +1 -0
  46. package/dist/secret-scrubber-3TLUkiCV.d.ts +31 -0
  47. package/dist/secret-scrubber-CwYliRWd.d.ts +54 -0
  48. package/dist/secret-vault-DoISxaKO.d.ts +19 -0
  49. package/dist/security/index.d.ts +46 -0
  50. package/dist/security/index.js +536 -0
  51. package/dist/security/index.js.map +1 -0
  52. package/dist/selector-BRqzvugb.d.ts +51 -0
  53. package/dist/session-reader-C3x96CDR.d.ts +150 -0
  54. package/dist/skill-Bx8jxznf.d.ts +72 -0
  55. package/dist/storage/index.d.ts +540 -0
  56. package/dist/storage/index.js +1802 -0
  57. package/dist/storage/index.js.map +1 -0
  58. package/dist/{system-prompt-vAB0F54-.d.ts → system-prompt-CG9jU5-5.d.ts} +9 -1
  59. package/dist/task-graph-BITvWt4t.d.ts +160 -0
  60. package/dist/tool-executor-CYdZdtno.d.ts +97 -0
  61. package/dist/types/index.d.ts +26 -4
  62. package/dist/types/index.js +1787 -4
  63. package/dist/types/index.js.map +1 -1
  64. package/dist/utils/index.d.ts +49 -2
  65. package/dist/utils/index.js +100 -2
  66. package/dist/utils/index.js.map +1 -1
  67. package/package.json +34 -2
  68. package/dist/mode-Pjt5vMS6.d.ts +0 -815
  69. package/dist/session-reader-9sOTgmeC.d.ts +0 -1087
@@ -0,0 +1,540 @@
1
+ import { E as EventBus } from '../events-B6Q03pTu.js';
2
+ import { o as SessionStore, n as SessionMetadata, q as SessionWriter, k as ResumedSession, S as SessionData, p as SessionSummary, b as ContentBlock, m as SessionEvent, aa as TodoItem, a4 as ConversationState } from '../context-u0bryklF.js';
3
+ import { e as AttachmentStore, A as AddAttachmentInput, d as AttachmentRef, a as Attachment } from '../session-reader-C3x96CDR.js';
4
+ export { D as DefaultSessionReader } from '../session-reader-C3x96CDR.js';
5
+ import { b as MemoryStore, a as MemoryScope } from '../memory-CEXuo7sz.js';
6
+ import { a as WstackPaths } from '../wstack-paths-BGu2INTm.js';
7
+ import { b as ConfigStore, C as Config, a as ConfigLoader } from '../config-DXrqb41m.js';
8
+ import { S as SecretVault } from '../secret-vault-DoISxaKO.js';
9
+ import '../models-registry-Y2xbog0E.js';
10
+
11
+ interface SessionStoreOptions {
12
+ dir: string;
13
+ /** Optional EventBus for emitting session diagnostics. */
14
+ events?: EventBus;
15
+ }
16
+ declare class DefaultSessionStore implements SessionStore {
17
+ private readonly dir;
18
+ private readonly events?;
19
+ constructor(opts: SessionStoreOptions);
20
+ create(meta: Omit<SessionMetadata, 'startedAt'>): Promise<SessionWriter>;
21
+ resume(id: string): Promise<ResumedSession>;
22
+ load(id: string): Promise<SessionData>;
23
+ list(limit?: number): Promise<SessionSummary[]>;
24
+ private summaryFor;
25
+ delete(id: string): Promise<void>;
26
+ private summarize;
27
+ private metaFromEvents;
28
+ private replay;
29
+ }
30
+
31
+ /**
32
+ * The persisted form of a single queued user message. The TUI's
33
+ * in-memory QueueItem has a render id; that's pure UI bookkeeping, so
34
+ * we drop it when serializing — fresh ids are assigned on rehydrate.
35
+ */
36
+ interface PersistedQueueItem {
37
+ displayText: string;
38
+ blocks: ContentBlock[];
39
+ }
40
+ /**
41
+ * Side-file storage for a session's pending input queue. Lives at
42
+ * `<sessionDir>/queue.json` next to the attachment spool. Reads are
43
+ * tolerant (missing/malformed file → empty array); writes are atomic
44
+ * (tmp + rename) so a crash mid-write can never leave a partial file
45
+ * the next launch would choke on.
46
+ *
47
+ * The contract is "snapshot replacement": every mutation hands the
48
+ * full queue and we rewrite the file. The queue is small (rarely more
49
+ * than a handful of messages), so this is cheaper than delta logging
50
+ * and avoids the replay complexity.
51
+ */
52
+ declare class QueueStore {
53
+ private readonly file;
54
+ constructor(opts: {
55
+ dir: string;
56
+ });
57
+ write(items: PersistedQueueItem[]): Promise<void>;
58
+ read(): Promise<PersistedQueueItem[]>;
59
+ clear(): Promise<void>;
60
+ }
61
+
62
+ interface AttachmentStoreOptions {
63
+ /**
64
+ * Directory for spooling payloads larger than `spoolThresholdBytes`.
65
+ * When omitted, all payloads stay in memory.
66
+ */
67
+ spoolDir?: string;
68
+ spoolThresholdBytes?: number;
69
+ }
70
+ /**
71
+ * In-memory attachment store with optional disk spool. Placeholder syntax
72
+ * is `[<kind> #<seq>]` where kind is `pasted` / `image` / `file`. Unknown
73
+ * placeholders are passed through as-is so users can write that literal
74
+ * text without losing it.
75
+ */
76
+ declare class DefaultAttachmentStore implements AttachmentStore {
77
+ private readonly items;
78
+ private readonly refs;
79
+ private nextSeq;
80
+ private readonly spoolDir;
81
+ private readonly spoolThreshold;
82
+ constructor(opts?: AttachmentStoreOptions);
83
+ add(input: AddAttachmentInput): Promise<AttachmentRef>;
84
+ get(id: string): Promise<Attachment | undefined>;
85
+ list(): AttachmentRef[];
86
+ expand(text: string): Promise<ContentBlock[]>;
87
+ clear(): Promise<void>;
88
+ private toBlock;
89
+ }
90
+
91
+ interface MemoryStoreOptions {
92
+ paths: WstackPaths;
93
+ }
94
+ /**
95
+ * Three scopes:
96
+ * project-agents → <project>/.wrongstack/AGENTS.md (committed)
97
+ * project-memory → ~/.wrongstack/projects/<hash>/memory.md (per-project agent notes)
98
+ * user-memory → ~/.wrongstack/memory.md (global personal memory)
99
+ */
100
+ declare class DefaultMemoryStore implements MemoryStore {
101
+ private readonly files;
102
+ /**
103
+ * Per-scope serialization queue. `remember` / `forget` / `consolidate` /
104
+ * `clear` are read-modify-write against a single file; without a lock,
105
+ * two concurrent calls on the same scope can read the same baseline and
106
+ * the later write silently drops the earlier entry. We chain each
107
+ * mutation onto the prior promise for the same scope so they run in
108
+ * issue order. Different scopes still proceed in parallel.
109
+ *
110
+ * The chain tracks only the last pending write. If a write fails, its
111
+ * error is caught and swallowed (line 43) so the chain stays alive for
112
+ * subsequent calls. A crash between atomicWrite() and backup copy leaves
113
+ * the file at its new content with no backup — acceptable for an optional
114
+ * backup whose worst case is losing a memory consolidation pass.
115
+ */
116
+ private readonly writeChain;
117
+ constructor(opts: MemoryStoreOptions);
118
+ private runSerialized;
119
+ readAll(): Promise<string>;
120
+ read(scope: MemoryScope): Promise<string>;
121
+ remember(text: string, scope?: MemoryScope): Promise<void>;
122
+ forget(query: string, scope?: MemoryScope): Promise<number>;
123
+ private forgetUnsafe;
124
+ consolidate(scope: MemoryScope): Promise<void>;
125
+ private consolidateUnsafe;
126
+ clear(scope?: MemoryScope): Promise<void>;
127
+ }
128
+
129
+ /**
130
+ * Reference implementation of `ConfigStore`. Stores a single frozen Config
131
+ * and notifies watchers synchronously on every update. Updates use a deep
132
+ * clone so callers can mutate their `partial` argument freely without
133
+ * tainting state.
134
+ *
135
+ * For the CLI: instantiate once at boot, pass the store (not the Config)
136
+ * to subsystems that care about runtime changes (provider switching,
137
+ * extension reload).
138
+ */
139
+ declare class DefaultConfigStore implements ConfigStore {
140
+ private current;
141
+ private watchers;
142
+ constructor(initial: Config);
143
+ get(): Readonly<Config>;
144
+ getSection<K extends keyof Config>(key: K): Readonly<Config[K]>;
145
+ getExtension(pluginName: string): Readonly<Record<string, unknown>>;
146
+ update(partial: Partial<Config>): Readonly<Config>;
147
+ watch(cb: (next: Readonly<Config>, prev: Readonly<Config>) => void): () => void;
148
+ }
149
+
150
+ /**
151
+ * A single config source. Higher priority wins in merges.
152
+ * Sources are applied in priority order (lowest first), so a source
153
+ * with priority=10 overrides one with priority=1.
154
+ */
155
+ interface ConfigSource {
156
+ /** Unique name for debugging and error messages. */
157
+ name: string;
158
+ /** Lower numbers merge first, higher numbers override lower. Default: 50. */
159
+ priority?: number;
160
+ /**
161
+ * Read the raw config patch. Return an empty object if unavailable.
162
+ * Errors are surfaced but do not abort loading — the source is skipped.
163
+ */
164
+ read(): Promise<Partial<Config>>;
165
+ }
166
+ interface ConfigLoaderOptions {
167
+ paths: WstackPaths;
168
+ strict?: boolean;
169
+ vault?: SecretVault;
170
+ /** Extra sources merged after the built-in layers. */
171
+ sources?: ConfigSource[];
172
+ }
173
+ declare class DefaultConfigLoader implements ConfigLoader {
174
+ private readonly paths;
175
+ private readonly strict;
176
+ private readonly vault;
177
+ private readonly extraSources;
178
+ constructor(opts: ConfigLoaderOptions);
179
+ load(opts?: {
180
+ cliFlags?: Partial<Config>;
181
+ cwd?: string;
182
+ }): Promise<Config>;
183
+ private readJson;
184
+ private validateBehavior;
185
+ private validateIdentity;
186
+ }
187
+
188
+ /**
189
+ * L2-D: Config version migration framework. Pure functions, decoupled
190
+ * from disk/CLI — caller passes a parsed JSON object and gets back the
191
+ * up-to-date `Config` shape (or a structured error explaining why
192
+ * migration failed).
193
+ *
194
+ * Migrations are registered as `{ from, to, migrate }` triples and run
195
+ * sequentially. Each migration is independently testable. Adding a new
196
+ * version means appending one migration; existing user configs are
197
+ * upgraded in place at load time.
198
+ */
199
+ interface MigrationContext {
200
+ /**
201
+ * Original on-disk version of the input. Migrations may use this to
202
+ * decide between in-place patches and rewrites.
203
+ */
204
+ fromVersion: number;
205
+ /**
206
+ * Set when the migration writes back to disk. Callers persist the
207
+ * migrated config when this is true so the user doesn't see the same
208
+ * migration banner on every boot.
209
+ */
210
+ shouldPersist: boolean;
211
+ }
212
+ interface ConfigMigration {
213
+ /** Version of the input this migration accepts. */
214
+ from: number;
215
+ /** Version of the output it produces. */
216
+ to: number;
217
+ /** Pure transform — no I/O. */
218
+ migrate(input: Record<string, unknown>, ctx: MigrationContext): Record<string, unknown>;
219
+ /** Optional human-readable description for migration logs / banners. */
220
+ describe?: string;
221
+ }
222
+ interface MigrationResult {
223
+ /** Final config (still typed as `unknown`-keyed — caller validates). */
224
+ config: Record<string, unknown>;
225
+ /** Ordered list of `from→to` versions that ran. */
226
+ applied: string[];
227
+ /** True when at least one migration produced changes worth persisting. */
228
+ shouldPersist: boolean;
229
+ }
230
+ declare class ConfigMigrationError extends Error {
231
+ readonly fromVersion: number;
232
+ readonly targetVersion: number;
233
+ readonly missingStep: number | null;
234
+ constructor(opts: {
235
+ message: string;
236
+ fromVersion: number;
237
+ targetVersion: number;
238
+ missingStep: number | null;
239
+ });
240
+ }
241
+ /**
242
+ * Run registered migrations until the input reaches `targetVersion`.
243
+ *
244
+ * Resolution rules:
245
+ * 1. If `input.version === targetVersion`, no migrations run; `shouldPersist`
246
+ * is false.
247
+ * 2. Otherwise walk the migration chain from `input.version` upward,
248
+ * picking the migration whose `from` matches the current version.
249
+ * 3. Stop when `current.version === targetVersion`.
250
+ * 4. If no migration matches at some point, throw `ConfigMigrationError`
251
+ * with the missing step recorded for diagnostics.
252
+ *
253
+ * Migrations may be downward (e.g. for staged rollouts), but `targetVersion`
254
+ * must be reachable strictly via the registered chain — there's no implicit
255
+ * "skip" or transitive resolution.
256
+ */
257
+ declare function runConfigMigrations(input: Record<string, unknown>, targetVersion: number, migrations: readonly ConfigMigration[]): MigrationResult;
258
+ /**
259
+ * Default empty migration registry. Real migrations are appended as new
260
+ * Config versions are introduced. Example (when v2 lands):
261
+ *
262
+ * export const CONFIG_MIGRATIONS: readonly ConfigMigration[] = [
263
+ * {
264
+ * from: 1, to: 2, describe: 'rename `apiKey` → `auth.apiKey`',
265
+ * migrate(cfg) {
266
+ * const apiKey = cfg.apiKey;
267
+ * delete cfg.apiKey;
268
+ * return { ...cfg, auth: { ...(cfg.auth ?? {}), apiKey } };
269
+ * },
270
+ * },
271
+ * ];
272
+ */
273
+ declare const DEFAULT_CONFIG_MIGRATIONS: readonly ConfigMigration[];
274
+
275
+ /**
276
+ * Per-project lockfile used for crash detection. The CLI writes one of
277
+ * these alongside the session JSONLs (`<projectSessions>/active.json`)
278
+ * when an interactive run starts, and deletes it on clean exit. If we
279
+ * find one on the next launch whose owning PID is dead (or whose host
280
+ * doesn't match), we know the previous run was killed mid-flight and
281
+ * the session it was writing to is a recovery candidate.
282
+ *
283
+ * The lockfile is intentionally per-project (already isolated by
284
+ * `wpaths.projectSessions`), so two TUIs in two different repos do not
285
+ * fight each other.
286
+ */
287
+ interface RecoveryLockOptions {
288
+ /** Directory the lockfile lives in. Usually `wpaths.projectSessions`. */
289
+ dir: string;
290
+ /** This process's PID. Default: `process.pid`. */
291
+ pid?: number;
292
+ /** Hostname recorded for the lock. Default: `os.hostname()`. */
293
+ hostname?: string;
294
+ /** Locks older than this are considered orphaned (disk wiped, etc.). Default 24h. */
295
+ maxAgeMs?: number;
296
+ /** Used to check whether the abandoned session was actually closed cleanly. */
297
+ sessionStore?: SessionStore;
298
+ /**
299
+ * Override the PID-liveness probe. Default: `process.kill(pid, 0)` —
300
+ * succeeds (or throws EPERM) when the PID is alive, throws ESRCH when
301
+ * it is gone. Tests inject a deterministic stub.
302
+ */
303
+ isPidAlive?: (pid: number) => boolean;
304
+ }
305
+ interface AbandonedSession {
306
+ sessionId: string;
307
+ pid: number;
308
+ startedAt: string;
309
+ /** Lockfile age in ms at the time of the check. */
310
+ ageMs: number;
311
+ /** Number of messages already on disk for this session. */
312
+ messageCount: number;
313
+ }
314
+ declare class RecoveryLock {
315
+ private readonly file;
316
+ private readonly pid;
317
+ private readonly hostname;
318
+ private readonly maxAgeMs;
319
+ private readonly sessionStore?;
320
+ private readonly probe;
321
+ constructor(opts: RecoveryLockOptions);
322
+ /**
323
+ * Examine the lockfile and decide whether it represents an abandoned
324
+ * session. Returns `null` if the file is missing, points to a live
325
+ * instance, references a clean-closed session, is too old, or is
326
+ * malformed. Otherwise returns enough detail to prompt the user.
327
+ *
328
+ * Important: this is a read-only check. We never delete an active
329
+ * lock from here — if another wstack instance is alive, the caller
330
+ * should bail or run with a fresh session instead.
331
+ */
332
+ checkAbandoned(): Promise<AbandonedSession | null>;
333
+ /**
334
+ * Claim the lock for the given session. Overwrites any existing lock
335
+ * — the caller should have already handled abandonment (via
336
+ * `checkAbandoned`) before calling this.
337
+ */
338
+ write(sessionId: string): Promise<void>;
339
+ /**
340
+ * Release the lock. Idempotent — silently succeeds if the file is
341
+ * already gone (e.g. someone else cleared it, or the directory was
342
+ * wiped).
343
+ */
344
+ clear(): Promise<void>;
345
+ private readLock;
346
+ }
347
+
348
+ interface QueryFilter {
349
+ eventTypes?: string[];
350
+ toolNames?: string[];
351
+ timeRange?: {
352
+ start: string;
353
+ end: string;
354
+ };
355
+ }
356
+ interface ModeChange {
357
+ ts: string;
358
+ from: string;
359
+ to: string;
360
+ }
361
+ interface TaskSummary {
362
+ taskId: string;
363
+ title: string;
364
+ status: string;
365
+ createdAt: string;
366
+ completedAt?: string;
367
+ }
368
+ interface SessionAnalysis {
369
+ sessionId: string;
370
+ totalDuration: number;
371
+ toolUsageCount: Record<string, number>;
372
+ errorCount: number;
373
+ modeChanges: ModeChange[];
374
+ tasks: TaskSummary[];
375
+ }
376
+ declare class SessionAnalyzer {
377
+ analyze(events: SessionEvent[]): SessionAnalysis;
378
+ query(events: SessionEvent[], filter: QueryFilter): SessionEvent[];
379
+ private calcDuration;
380
+ }
381
+
382
+ /**
383
+ * On-disk checkpoint for `ctx.todos`. Written atomically every time the
384
+ * todo list changes, read once on session resume. This is the missing
385
+ * piece that lets `wstack resume <id>` rehydrate where the previous run
386
+ * stopped instead of starting with an empty board.
387
+ *
388
+ * Schema is intentionally small — a single JSON object so a future
389
+ * format bump is easy. The `version` field is the only contract; the
390
+ * shape under `todos` mirrors `TodoItem` so reading is a straight assign.
391
+ */
392
+ interface TodosCheckpointFile {
393
+ version: 1;
394
+ sessionId: string;
395
+ updatedAt: string;
396
+ todos: TodoItem[];
397
+ }
398
+ /** Read a checkpoint from disk. Returns null when the file doesn't
399
+ * exist or is corrupt — callers treat both cases as "no prior state".
400
+ */
401
+ declare function loadTodosCheckpoint(filePath: string): Promise<TodoItem[] | null>;
402
+ /** Write the checkpoint atomically. Best-effort: a write failure is
403
+ * logged but does not throw — losing one checkpoint shouldn't bring
404
+ * down the agent run.
405
+ */
406
+ declare function saveTodosCheckpoint(filePath: string, sessionId: string, todos: readonly TodoItem[]): Promise<void>;
407
+ /**
408
+ * Subscribe a `ConversationState` so every `todos_replaced` mutation
409
+ * triggers an atomic write to disk. Returns the unsubscribe function.
410
+ *
411
+ * Writes are debounced by 150ms so a flurry of edits (e.g. the LLM
412
+ * marking three items done in the same tool call) coalesces into one
413
+ * disk hit.
414
+ */
415
+ declare function attachTodosCheckpoint(state: ConversationState, filePath: string, sessionId: string): () => void;
416
+
417
+ /**
418
+ * Plan items are the strategic counterpart to todos. Where `ctx.todos`
419
+ * is the moment-to-moment task board the LLM mutates per-turn, a plan
420
+ * captures the higher-level approach — the steps the user (or LLM)
421
+ * laid out before any work began.
422
+ *
423
+ * Plans persist by default (per session) so a resumed session can show
424
+ * "you were on step 3 of 5". Todos are derived/transient. Both can
425
+ * coexist: think roadmap (plan) vs. sprint board (todos).
426
+ */
427
+ interface PlanItem {
428
+ id: string;
429
+ title: string;
430
+ /** Optional longer-form context or rationale. */
431
+ details?: string;
432
+ status: 'open' | 'in_progress' | 'done';
433
+ createdAt: string;
434
+ updatedAt: string;
435
+ }
436
+ interface PlanFile {
437
+ version: 1;
438
+ sessionId: string;
439
+ title?: string;
440
+ updatedAt: string;
441
+ items: PlanItem[];
442
+ }
443
+ declare function loadPlan(filePath: string): Promise<PlanFile | null>;
444
+ declare function savePlan(filePath: string, plan: PlanFile): Promise<void>;
445
+ /** Create a new PlanFile when none exists on disk. */
446
+ declare function emptyPlan(sessionId: string, title?: string): PlanFile;
447
+ declare function addPlanItem(plan: PlanFile, title: string, details?: string): {
448
+ plan: PlanFile;
449
+ item: PlanItem;
450
+ };
451
+ declare function removePlanItem(plan: PlanFile, idOrIndex: string): PlanFile;
452
+ declare function setPlanItemStatus(plan: PlanFile, idOrIndex: string, status: PlanItem['status']): PlanFile;
453
+ declare function clearPlan(plan: PlanFile): PlanFile;
454
+ /** Render the plan as a short markdown-ish string suitable for slash output. */
455
+ declare function formatPlan(plan: PlanFile): string;
456
+ /**
457
+ * Optional: attach a state-listener so meta operations (storing a plan
458
+ * id on ctx.meta) trigger a save. Currently a stub — plans don't live
459
+ * on Context, but this keeps the API surface symmetric with the todos
460
+ * checkpoint so future refactors can flip plans into Context if needed.
461
+ */
462
+ declare function attachPlanCheckpoint(_state: ConversationState, _filePath: string, _sessionId: string): () => void;
463
+
464
+ /**
465
+ * Director state checkpoint — written incrementally throughout a fleet
466
+ * run so a crashed director can be inspected (and eventually resumed)
467
+ * instead of leaving only a final `fleet.json` manifest after `shutdown()`.
468
+ *
469
+ * Schema is JSON-friendly and deliberately denormalized. Each mutation
470
+ * triggers an atomic-write of the whole file — small payloads (typically
471
+ * < 10 KB even with dozens of subagents) make this cheap.
472
+ */
473
+ interface DirectorSubagentState {
474
+ id: string;
475
+ name?: string;
476
+ role?: string;
477
+ provider?: string;
478
+ model?: string;
479
+ spawnedAt: string;
480
+ }
481
+ interface DirectorTaskState {
482
+ taskId: string;
483
+ subagentId?: string;
484
+ description?: string;
485
+ status: 'pending' | 'running' | 'completed' | 'failed' | 'stopped' | 'timeout';
486
+ assignedAt?: string;
487
+ completedAt?: string;
488
+ iterations?: number;
489
+ toolCalls?: number;
490
+ durationMs?: number;
491
+ error?: string;
492
+ }
493
+ interface DirectorStateSnapshot {
494
+ version: 1;
495
+ directorRunId: string;
496
+ updatedAt: string;
497
+ spawnCount: number;
498
+ maxSpawns?: number;
499
+ spawnDepth: number;
500
+ maxSpawnDepth: number;
501
+ subagents: DirectorSubagentState[];
502
+ tasks: DirectorTaskState[];
503
+ /** Aggregated usage snapshot. Optional — populated by the Director on save when available. */
504
+ usage?: unknown;
505
+ }
506
+ declare function loadDirectorState(filePath: string): Promise<DirectorStateSnapshot | null>;
507
+ /**
508
+ * In-memory accumulator with atomic-write checkpoint. The Director keeps
509
+ * an instance, mutates it on every spawn/assign/complete/fail event, and
510
+ * the instance debounces writes so a burst of activity collapses into a
511
+ * single disk hit.
512
+ */
513
+ declare class DirectorStateCheckpoint {
514
+ private snapshot;
515
+ private readonly filePath;
516
+ private timer;
517
+ private readonly debounceMs;
518
+ private writing;
519
+ private rewriteRequested;
520
+ constructor(filePath: string, init: {
521
+ directorRunId: string;
522
+ maxSpawns?: number;
523
+ spawnDepth: number;
524
+ maxSpawnDepth: number;
525
+ }, debounceMs?: number);
526
+ current(): DirectorStateSnapshot;
527
+ recordSpawn(sub: DirectorSubagentState, spawnCount: number): void;
528
+ recordTaskAssigned(task: DirectorTaskState): void;
529
+ recordTaskStatus(taskId: string, patch: Partial<DirectorTaskState> & {
530
+ status: DirectorTaskState['status'];
531
+ }): void;
532
+ setUsage(usage: unknown): void;
533
+ /** Force a synchronous flush — used by Director.shutdown(). */
534
+ flush(): Promise<void>;
535
+ private bumpUpdatedAt;
536
+ private schedule;
537
+ private persist;
538
+ }
539
+
540
+ export { type AbandonedSession, type AttachmentStoreOptions, type ConfigLoaderOptions, type ConfigMigration, ConfigMigrationError, type ConfigSource, DEFAULT_CONFIG_MIGRATIONS, DefaultAttachmentStore, DefaultConfigLoader, DefaultConfigStore, DefaultMemoryStore, DefaultSessionStore, DirectorStateCheckpoint, type DirectorStateSnapshot, type DirectorSubagentState, type DirectorTaskState, type MemoryStoreOptions, type MigrationContext, type MigrationResult, type PersistedQueueItem, type PlanFile, type PlanItem, QueueStore, RecoveryLock, type RecoveryLockOptions, SessionAnalyzer, type SessionStoreOptions, type TodosCheckpointFile, addPlanItem, attachPlanCheckpoint, attachTodosCheckpoint, clearPlan, emptyPlan, formatPlan, loadDirectorState, loadPlan, loadTodosCheckpoint, removePlanItem, runConfigMigrations, savePlan, saveTodosCheckpoint, setPlanItemStatus };