@oh-my-matrix/autopilot 3.0.0 → 3.0.3

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.
@@ -0,0 +1,117 @@
1
+ import type { AutopilotState } from './types';
2
+ import type { WorkspaceRecord, RetryEntry, WorkflowConfig } from './types';
3
+ export declare function getCheckpointWriteFailureCount(): number;
4
+ export declare function _resetCheckpointFailureCountForTest(): void;
5
+ export declare function _disableCheckpointingForTest(): void;
6
+ export declare function _enableCheckpointingForTest(): void;
7
+ export declare function _isCheckpointingDisabledForTest(): boolean;
8
+ /**
9
+ * The slim persisted shape. Intentionally a SUBSET of AutopilotState — we do NOT
10
+ * persist permissionAudit (it has its own JSONL via audit-persister), nor status
11
+ * (re-derived on load). Large/ephemeral fields (canaryFired, noUsageWarned) are
12
+ * session-scoped and never persisted.
13
+ */
14
+ export interface AutopilotCheckpoint {
15
+ runId: string;
16
+ sessionKey: string;
17
+ orchestrationState?: AutopilotState['orchestrationState'];
18
+ blockedReason?: AutopilotState['blockedReason'];
19
+ goal?: string;
20
+ goalSnapshot?: string;
21
+ progress?: string;
22
+ progressSnapshot?: string;
23
+ turnAttempts: number;
24
+ totalContinuations: number;
25
+ maxAttemptsPerTurn: number;
26
+ maxTotalContinuations: number;
27
+ needsCrossTurnResume: boolean;
28
+ enabled: boolean;
29
+ totalTokensUsed: number;
30
+ tokenBudget?: number;
31
+ inputTokensUsed?: number;
32
+ outputTokensUsed?: number;
33
+ evidenceStatus?: AutopilotState['evidence'] extends infer E ? (E extends {
34
+ status: infer S;
35
+ } ? S : undefined) : undefined;
36
+ startedAt?: number;
37
+ lastActivityAt?: number;
38
+ /** Forensic only — loaders overwrite with deriveStatus(). Never trusted. */
39
+ status?: AutopilotState['status'];
40
+ workspaceRoot?: string;
41
+ workspacePath?: string;
42
+ /** Full workspace record (Reviewer #1 Finding 2a fix): restored runs MUST retain
43
+ * their permission-containment boundary + checkpoint-root. Persisting flat fields
44
+ * alone left state.workspace undefined after restore, widening the tool-call
45
+ * containment to process.cwd() — a security regression. */
46
+ workspace?: WorkspaceRecord;
47
+ /** Retry entry (Reviewer #1 Finding 2b fix): without this, restored retry_queued
48
+ * runs lose state.retry → the stall interval's retry_due guard
49
+ * (state.retry?.nextRetryAt != null) is never satisfied → the run wedges forever. */
50
+ retry?: RetryEntry;
51
+ /** Workflow config (Reviewer #1 Finding 2c fix): restored runs otherwise skip
52
+ * validation commands, reset stallTimeoutMs, and lose modelRouting. */
53
+ workflow?: WorkflowConfig;
54
+ /** Millisecond epoch of the checkpoint write. */
55
+ savedAt: number;
56
+ }
57
+ /**
58
+ * Build a slim checkpoint from a full AutopilotState. Extracts only the fields
59
+ * needed to resume a run; drops the bulky/ephemeral ones.
60
+ */
61
+ export declare function buildCheckpoint(state: AutopilotState, runId: string, workspaceRoot: string): AutopilotCheckpoint;
62
+ /**
63
+ * Persist a checkpoint + update the sessionKey→runId index. Fail-silent.
64
+ * Serialized per-runId so concurrent setState firings don't interleave writes.
65
+ *
66
+ * Returns a Promise (rather than sync) because the lock chain is async; callers
67
+ * that don't need to await (the common case from setState) fire-and-forget via
68
+ * void. The internal _writeSyncLocked does the actual sync I/O under the lock.
69
+ */
70
+ export declare function saveCheckpoint(state: AutopilotState, runId: string, workspaceRoot: string): void;
71
+ /**
72
+ * Load a checkpoint and rebuild an AutopilotState. ADR-016 BLOCKER #1 fix:
73
+ * `status` is NEVER trusted from the persisted field — always re-derived.
74
+ *
75
+ * Returns null if the checkpoint is missing, corrupt, or fails workspace
76
+ * validation (Review #4 #4: stale-run guard).
77
+ */
78
+ export declare function loadCheckpoint(runId: string, workspaceRoot: string, options?: {
79
+ validateWorkspace?: boolean;
80
+ }): AutopilotState | null;
81
+ /**
82
+ * Delete a checkpoint file (Review #4 #6: called on terminal transitions to
83
+ * prevent done-run file leaks). Fail-silent.
84
+ */
85
+ export declare function deleteCheckpoint(runId: string, workspaceRoot: string): void;
86
+ /**
87
+ * Remove a sessionKey→runId entry from the index. Used when a run terminates
88
+ * so a future session_start for the same sessionKey doesn't resurrect a dead run.
89
+ */
90
+ export declare function clearSessionIndexEntry(workspaceRoot: string, sessionKey: string): void;
91
+ /**
92
+ * Look up runId by sessionKey from the durable index. Returns null if the
93
+ * index is missing, corrupt, or has no entry. This is BLOCKER #2's recovery
94
+ * path: after a process restart, the in-memory sessionKeyToRunId Map is empty,
95
+ * so session_start must consult this file to find the checkpoint.
96
+ */
97
+ export declare function lookupRunIdBySessionKey(workspaceRoot: string, sessionKey: string): string | null;
98
+ /**
99
+ * Scan the checkpoints directory and return all runIds whose checkpoint is
100
+ * resumable (orchestrationState in the active family) and whose workspace still
101
+ * exists. Used by register() at process init to restore ALL resumable runs,
102
+ * not just the one whose session_start fired (Review #3 multi-run gap).
103
+ *
104
+ * Also sweeps terminal checkpoints older than TERMINAL_CHECKPOINT_TTL_MS to
105
+ * reclaim disk (Review #4 #6c).
106
+ */
107
+ export declare function listResumableCheckpoints(workspaceRoot: string): string[];
108
+ /** Test-only: clear the write-lock map between tests. */
109
+ export declare function _clearWriteLocksForTest(): void;
110
+ /**
111
+ * Test-only: deterministically await all in-flight checkpoint writes. Reviewer
112
+ * #2 Finding 5 fix — replaces the fragile "two setImmediate ticks" drain with
113
+ * `Promise.all` over the lock map so tests don't flake if the lock chain grows
114
+ * another async hop.
115
+ */
116
+ export declare function _flushAllWritesForTest(): Promise<void>;
117
+ //# sourceMappingURL=state-persister.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-persister.d.ts","sourceRoot":"","sources":["../../src/state-persister.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,454 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getCheckpointWriteFailureCount = getCheckpointWriteFailureCount;
37
+ exports._resetCheckpointFailureCountForTest = _resetCheckpointFailureCountForTest;
38
+ exports._disableCheckpointingForTest = _disableCheckpointingForTest;
39
+ exports._enableCheckpointingForTest = _enableCheckpointingForTest;
40
+ exports._isCheckpointingDisabledForTest = _isCheckpointingDisabledForTest;
41
+ exports.buildCheckpoint = buildCheckpoint;
42
+ exports.saveCheckpoint = saveCheckpoint;
43
+ exports.loadCheckpoint = loadCheckpoint;
44
+ exports.deleteCheckpoint = deleteCheckpoint;
45
+ exports.clearSessionIndexEntry = clearSessionIndexEntry;
46
+ exports.lookupRunIdBySessionKey = lookupRunIdBySessionKey;
47
+ exports.listResumableCheckpoints = listResumableCheckpoints;
48
+ exports._clearWriteLocksForTest = _clearWriteLocksForTest;
49
+ exports._flushAllWritesForTest = _flushAllWritesForTest;
50
+ /**
51
+ * Crash-recovery checkpoint persistence for autopilot run state.
52
+ *
53
+ * Writes a SLIM pointer of AutopilotState to
54
+ * {workspaceRoot}/.autopilot/checkpoints/{runId}.json
55
+ * plus a sessionKey→runId index at
56
+ * {workspaceRoot}/.autopilot/checkpoints/session-index.json
57
+ *
58
+ * Design (mirrors @oh-my-matrix/permission-policy/src/audit-persister.ts):
59
+ * - synchronous file I/O (plugin runs in main process; simplicity > async)
60
+ * - fail-silent (never throws; persistence is best-effort recovery, not authoritative)
61
+ * - no external dependencies
62
+ *
63
+ * ADR-016 invariant (status sole-writer): `status` is NEVER trusted from disk.
64
+ * On load, status is re-derived via deriveStatus(). We persist a `status` field
65
+ * only as a forensic hint; loaders MUST overwrite it with the derived value.
66
+ * This prevents the H1 false-completion class from recurring via stale checkpoints.
67
+ *
68
+ * Review #4 BLOCKERs addressed here:
69
+ * #1 (status re-derive) — loadCheckpoint re-derives via deriveStatus
70
+ * #2 (runId recovery) — session-index.json maps sessionKey→runId durably
71
+ * #3 (write concurrency) — per-runId Promise lock serializes writes
72
+ * #5 (atomic same-dir write) — tmp written next to target, not os.tmpdir()
73
+ * #6 (done-run leak) — deleteCheckpoint called on terminal transitions
74
+ */
75
+ const fs = __importStar(require("fs"));
76
+ const path = __importStar(require("path"));
77
+ const orchestrator_1 = require("./orchestrator");
78
+ const CHECKPOINT_SUBDIR = path.join('.autopilot', 'checkpoints');
79
+ const SESSION_INDEX_FILE = 'session-index.json';
80
+ const TERMINAL_CHECKPOINT_TTL_MS = 24 * 60 * 60 * 1000; // sweep terminal checkpoints older than 24h
81
+ let _writeFailureCount = 0;
82
+ function getCheckpointWriteFailureCount() { return _writeFailureCount; }
83
+ function _resetCheckpointFailureCountForTest() { _writeFailureCount = 0; }
84
+ /**
85
+ * Test-only kill switch. When true, saveCheckpoint/deleteCheckpoint/listResumableCheckpoints
86
+ * become no-ops so the existing 50+ test suite (which runs in the repo root and would
87
+ * otherwise leak checkpoint files across tests, polluting stateByRun via the
88
+ * register()-time restore) stays isolated. Production never sets this. Flipped to
89
+ * true by index.ts _resetForTest(); flipped back false by _enableCheckpointingForTest()
90
+ * in tests that exercise persistence (state-persister.test.ts).
91
+ */
92
+ let _checkpointingDisabledForTest = false;
93
+ function _disableCheckpointingForTest() { _checkpointingDisabledForTest = true; }
94
+ function _enableCheckpointingForTest() { _checkpointingDisabledForTest = false; }
95
+ function _isCheckpointingDisabledForTest() { return _checkpointingDisabledForTest; }
96
+ /**
97
+ * Resolve the checkpoint directory for a workspace root, following symlinks
98
+ * (S12: same canonical-path discipline as audit-persister).
99
+ */
100
+ function getCheckpointDir(workspaceRoot) {
101
+ let resolved = workspaceRoot;
102
+ try {
103
+ resolved = fs.realpathSync(workspaceRoot);
104
+ }
105
+ catch {
106
+ // Path may not exist yet (mkdirSync creates it downstream).
107
+ }
108
+ return path.join(resolved, CHECKPOINT_SUBDIR);
109
+ }
110
+ function getCheckpointPath(workspaceRoot, runId) {
111
+ return path.join(getCheckpointDir(workspaceRoot), `${runId}.json`);
112
+ }
113
+ function getSessionIndexPath(workspaceRoot) {
114
+ return path.join(getCheckpointDir(workspaceRoot), SESSION_INDEX_FILE);
115
+ }
116
+ /**
117
+ * Build a slim checkpoint from a full AutopilotState. Extracts only the fields
118
+ * needed to resume a run; drops the bulky/ephemeral ones.
119
+ */
120
+ function buildCheckpoint(state, runId, workspaceRoot) {
121
+ return {
122
+ runId,
123
+ sessionKey: state.sessionKey,
124
+ orchestrationState: state.orchestrationState,
125
+ blockedReason: state.blockedReason,
126
+ goal: state.goal,
127
+ goalSnapshot: state.goalSnapshot,
128
+ progress: state.progress,
129
+ progressSnapshot: state.progressSnapshot,
130
+ turnAttempts: state.turnAttempts,
131
+ totalContinuations: state.totalContinuations,
132
+ maxAttemptsPerTurn: state.maxAttemptsPerTurn,
133
+ maxTotalContinuations: state.maxTotalContinuations,
134
+ needsCrossTurnResume: state.needsCrossTurnResume,
135
+ enabled: state.enabled,
136
+ totalTokensUsed: state.totalTokensUsed,
137
+ tokenBudget: state.tokenBudget,
138
+ inputTokensUsed: state.inputTokensUsed,
139
+ outputTokensUsed: state.outputTokensUsed,
140
+ evidenceStatus: state.evidence?.status,
141
+ startedAt: state.startedAt,
142
+ lastActivityAt: state.lastActivityAt,
143
+ // Forensic hint only — loadCheckpoint overwrites this with deriveStatus().
144
+ status: state.status,
145
+ workspaceRoot,
146
+ workspacePath: state.workspace?.path,
147
+ workspace: state.workspace,
148
+ retry: state.retry,
149
+ workflow: state.workflow,
150
+ savedAt: Date.now(),
151
+ };
152
+ }
153
+ // ─── Per-runId write lock (Review #4 #3a) ──────────────────────────────
154
+ // Serializes concurrent saveCheckpoint calls for the same runId across the
155
+ // 60s stall timer context and async hook handler contexts. A bare Map<runId,
156
+ // Promise> chain — each write awaits the previous one before starting.
157
+ const writeLocks = new Map();
158
+ /**
159
+ * Atomic write: tmp file in the SAME directory as the target (NOT os.tmpdir(),
160
+ * which can be on a different volume on Windows → EXDEV). renameSync is atomic
161
+ * on POSIX same-filesystem; Node ≥10 overwrites the target.
162
+ */
163
+ function atomicWriteFileSync(targetPath, data) {
164
+ const dir = path.dirname(targetPath);
165
+ fs.mkdirSync(dir, { recursive: true });
166
+ // PID + random suffix guards against same-dir tmp collisions under concurrency.
167
+ const tmpPath = `${targetPath}.tmp.${process.pid}.${Math.random().toString(36).slice(2)}`;
168
+ fs.writeFileSync(tmpPath, data, 'utf-8');
169
+ fs.renameSync(tmpPath, targetPath);
170
+ }
171
+ /**
172
+ * Persist a checkpoint + update the sessionKey→runId index. Fail-silent.
173
+ * Serialized per-runId so concurrent setState firings don't interleave writes.
174
+ *
175
+ * Returns a Promise (rather than sync) because the lock chain is async; callers
176
+ * that don't need to await (the common case from setState) fire-and-forget via
177
+ * void. The internal _writeSyncLocked does the actual sync I/O under the lock.
178
+ */
179
+ function saveCheckpoint(state, runId, workspaceRoot) {
180
+ if (_checkpointingDisabledForTest)
181
+ return; // test isolation: don't touch disk
182
+ const checkpoint = buildCheckpoint(state, runId, workspaceRoot);
183
+ const targetPath = getCheckpointPath(workspaceRoot, runId);
184
+ // Chain onto any in-flight write for this runId.
185
+ const prev = writeLocks.get(runId) ?? Promise.resolve();
186
+ const next = prev.then(() => {
187
+ try {
188
+ atomicWriteFileSync(targetPath, JSON.stringify(checkpoint));
189
+ updateSessionIndex(workspaceRoot, checkpoint.sessionKey, runId);
190
+ }
191
+ catch (e) {
192
+ _writeFailureCount++;
193
+ try {
194
+ console.error('[autopilot] checkpoint save failed:', e);
195
+ }
196
+ catch { /* noop */ }
197
+ }
198
+ }).catch(() => {
199
+ // Lock chain errors are already logged inside _writeSyncLocked; swallow to
200
+ // keep the chain alive for the next write.
201
+ });
202
+ writeLocks.set(runId, next);
203
+ // Auto-clean the lock entry once settled so the Map doesn't grow unbounded.
204
+ void next.then(() => {
205
+ if (writeLocks.get(runId) === next)
206
+ writeLocks.delete(runId);
207
+ });
208
+ }
209
+ /** Update the sessionKey→runId index atomically. Fail-silent. */
210
+ function updateSessionIndex(workspaceRoot, sessionKey, runId) {
211
+ const indexPath = getSessionIndexPath(workspaceRoot);
212
+ let index = {};
213
+ try {
214
+ if (fs.existsSync(indexPath)) {
215
+ index = JSON.parse(fs.readFileSync(indexPath, 'utf-8'));
216
+ }
217
+ }
218
+ catch {
219
+ // Corrupt index — start fresh rather than crash.
220
+ index = {};
221
+ }
222
+ if (index[sessionKey] === runId)
223
+ return; // no-op if unchanged
224
+ index[sessionKey] = runId;
225
+ try {
226
+ atomicWriteFileSync(indexPath, JSON.stringify(index));
227
+ }
228
+ catch (e) {
229
+ _writeFailureCount++;
230
+ try {
231
+ console.error('[autopilot] session-index update failed:', e);
232
+ }
233
+ catch { /* noop */ }
234
+ }
235
+ }
236
+ /**
237
+ * Load a checkpoint and rebuild an AutopilotState. ADR-016 BLOCKER #1 fix:
238
+ * `status` is NEVER trusted from the persisted field — always re-derived.
239
+ *
240
+ * Returns null if the checkpoint is missing, corrupt, or fails workspace
241
+ * validation (Review #4 #4: stale-run guard).
242
+ */
243
+ function loadCheckpoint(runId, workspaceRoot, options) {
244
+ const cpPath = getCheckpointPath(workspaceRoot, runId);
245
+ let cp;
246
+ try {
247
+ const raw = fs.readFileSync(cpPath, 'utf-8');
248
+ cp = JSON.parse(raw);
249
+ }
250
+ catch {
251
+ return null; // missing or corrupt — nothing to resume
252
+ }
253
+ // Review #4 #4: stale-run guard. If the workspace path recorded at checkpoint
254
+ // time no longer exists (deleted between crash and restart), refuse to resume
255
+ // rather than resurrecting a run against a vanished workspace.
256
+ if (options?.validateWorkspace !== false && cp.workspacePath) {
257
+ try {
258
+ const stat = fs.statSync(cp.workspacePath);
259
+ if (!stat.isDirectory())
260
+ return null;
261
+ }
262
+ catch {
263
+ return null;
264
+ }
265
+ }
266
+ // Rebuild a minimal AutopilotState. Many fields have safe defaults; the
267
+ // load-bearing ones (orchestrationState, blockedReason, goal, counters,
268
+ // workspace, retry, workflow) come from the checkpoint.
269
+ const partial = {
270
+ sessionKey: cp.sessionKey,
271
+ runId: cp.runId,
272
+ orchestrationState: cp.orchestrationState,
273
+ blockedReason: cp.blockedReason,
274
+ goal: cp.goal,
275
+ goalSnapshot: cp.goalSnapshot,
276
+ progress: cp.progress,
277
+ progressSnapshot: cp.progressSnapshot,
278
+ turnAttempts: cp.turnAttempts,
279
+ totalContinuations: cp.totalContinuations,
280
+ maxAttemptsPerTurn: cp.maxAttemptsPerTurn,
281
+ maxTotalContinuations: cp.maxTotalContinuations,
282
+ maxConcurrentAutopilot: 5, // default; per-run override not persisted
283
+ needsCrossTurnResume: cp.needsCrossTurnResume,
284
+ enabled: cp.enabled,
285
+ totalTokensUsed: cp.totalTokensUsed,
286
+ tokenBudget: cp.tokenBudget,
287
+ inputTokensUsed: cp.inputTokensUsed,
288
+ outputTokensUsed: cp.outputTokensUsed,
289
+ startedAt: cp.startedAt,
290
+ lastActivityAt: cp.lastActivityAt,
291
+ degraded: true, // mark resumed runs — operators can tell a restored run
292
+ toolErrorCount: 0,
293
+ toolErrorThreshold: 5,
294
+ // Reviewer #1 Finding 2a/2b/2c fixes: restore the three load-bearing
295
+ // objects the original "slim pointer" design dropped. Without workspace,
296
+ // the permission containment boundary widens to process.cwd(); without
297
+ // retry, retry_queued runs wedge; without workflow, validation is skipped.
298
+ workspace: cp.workspace,
299
+ retry: cp.retry,
300
+ workflow: cp.workflow,
301
+ };
302
+ // BLOCKER #1: re-derive status. Never trust cp.status.
303
+ const derivedStatus = (0, orchestrator_1.deriveStatus)(partial);
304
+ return { ...partial, status: derivedStatus };
305
+ }
306
+ /**
307
+ * Delete a checkpoint file (Review #4 #6: called on terminal transitions to
308
+ * prevent done-run file leaks). Fail-silent.
309
+ */
310
+ function deleteCheckpoint(runId, workspaceRoot) {
311
+ if (_checkpointingDisabledForTest)
312
+ return; // test isolation: don't touch disk
313
+ const cpPath = getCheckpointPath(workspaceRoot, runId);
314
+ try {
315
+ if (fs.existsSync(cpPath))
316
+ fs.unlinkSync(cpPath);
317
+ }
318
+ catch (e) {
319
+ try {
320
+ console.error('[autopilot] checkpoint delete failed:', e);
321
+ }
322
+ catch { /* noop */ }
323
+ }
324
+ // Best-effort index cleanup — leave stale sessionKey→runId entries; they're
325
+ // cheap and the index is rewritten on every save. A full GC pass would risk
326
+ // racing an in-flight save for a different runId.
327
+ }
328
+ /**
329
+ * Remove a sessionKey→runId entry from the index. Used when a run terminates
330
+ * so a future session_start for the same sessionKey doesn't resurrect a dead run.
331
+ */
332
+ function clearSessionIndexEntry(workspaceRoot, sessionKey) {
333
+ const indexPath = getSessionIndexPath(workspaceRoot);
334
+ try {
335
+ if (!fs.existsSync(indexPath))
336
+ return;
337
+ const index = JSON.parse(fs.readFileSync(indexPath, 'utf-8'));
338
+ if (!(sessionKey in index))
339
+ return;
340
+ delete index[sessionKey];
341
+ atomicWriteFileSync(indexPath, JSON.stringify(index));
342
+ }
343
+ catch {
344
+ // fail-silent
345
+ }
346
+ }
347
+ /**
348
+ * Look up runId by sessionKey from the durable index. Returns null if the
349
+ * index is missing, corrupt, or has no entry. This is BLOCKER #2's recovery
350
+ * path: after a process restart, the in-memory sessionKeyToRunId Map is empty,
351
+ * so session_start must consult this file to find the checkpoint.
352
+ */
353
+ function lookupRunIdBySessionKey(workspaceRoot, sessionKey) {
354
+ const indexPath = getSessionIndexPath(workspaceRoot);
355
+ try {
356
+ if (!fs.existsSync(indexPath))
357
+ return null;
358
+ const index = JSON.parse(fs.readFileSync(indexPath, 'utf-8'));
359
+ return index[sessionKey] ?? null;
360
+ }
361
+ catch {
362
+ return null;
363
+ }
364
+ }
365
+ /**
366
+ * Scan the checkpoints directory and return all runIds whose checkpoint is
367
+ * resumable (orchestrationState in the active family) and whose workspace still
368
+ * exists. Used by register() at process init to restore ALL resumable runs,
369
+ * not just the one whose session_start fired (Review #3 multi-run gap).
370
+ *
371
+ * Also sweeps terminal checkpoints older than TERMINAL_CHECKPOINT_TTL_MS to
372
+ * reclaim disk (Review #4 #6c).
373
+ */
374
+ function listResumableCheckpoints(workspaceRoot) {
375
+ if (_checkpointingDisabledForTest)
376
+ return []; // test isolation: don't read disk
377
+ const dir = getCheckpointDir(workspaceRoot);
378
+ if (!fs.existsSync(dir))
379
+ return [];
380
+ let files;
381
+ try {
382
+ files = fs.readdirSync(dir).filter(f => f.endsWith('.json') && f !== SESSION_INDEX_FILE);
383
+ }
384
+ catch {
385
+ return [];
386
+ }
387
+ const resumable = [];
388
+ const now = Date.now();
389
+ for (const f of files) {
390
+ const runId = f.replace(/\.json$/, '');
391
+ const fullPath = path.join(dir, f);
392
+ try {
393
+ const cp = JSON.parse(fs.readFileSync(fullPath, 'utf-8'));
394
+ const orch = cp.orchestrationState;
395
+ const isResumable = orch === 'running' || orch === 'claimed' || orch === 'retry_queued' || orch === 'released' || orch === 'unclaimed';
396
+ const isTerminal = orch === 'done' || (orch === 'blocked' && cp.blockedReason && !isResumableBlockedReason(cp.blockedReason));
397
+ if (isTerminal) {
398
+ // Review #4 #6c: sweep stale terminal checkpoints.
399
+ if (cp.savedAt && (now - cp.savedAt) > TERMINAL_CHECKPOINT_TTL_MS) {
400
+ try {
401
+ fs.unlinkSync(fullPath);
402
+ }
403
+ catch { /* fail-silent */ }
404
+ }
405
+ continue;
406
+ }
407
+ if (isResumable) {
408
+ // Validate workspace still exists before offering to resume.
409
+ if (cp.workspacePath) {
410
+ try {
411
+ const stat = fs.statSync(cp.workspacePath);
412
+ if (!stat.isDirectory())
413
+ continue;
414
+ }
415
+ catch {
416
+ continue; // workspace gone — skip
417
+ }
418
+ }
419
+ resumable.push(runId);
420
+ }
421
+ }
422
+ catch {
423
+ // corrupt checkpoint — skip
424
+ }
425
+ }
426
+ return resumable;
427
+ }
428
+ // Mirror of RESUMABLE_BLOCKED_REASONS from orchestrator.ts (kept local to avoid
429
+ // a circular import: orchestrator.ts imports nothing from this module, and we
430
+ // don't want to widen its dep surface). If the set in orchestrator.ts changes,
431
+ // update this too. (Documented linkage, not duplication-for-its-own-sake.)
432
+ const RESUMABLE_BLOCKED_LOCAL = new Set([
433
+ 'stalled',
434
+ 'validation_failed',
435
+ 'evidence_missing',
436
+ 'injection_rejected',
437
+ ]);
438
+ function isResumableBlockedReason(reason) {
439
+ return RESUMABLE_BLOCKED_LOCAL.has(reason);
440
+ }
441
+ /** Test-only: clear the write-lock map between tests. */
442
+ function _clearWriteLocksForTest() {
443
+ writeLocks.clear();
444
+ }
445
+ /**
446
+ * Test-only: deterministically await all in-flight checkpoint writes. Reviewer
447
+ * #2 Finding 5 fix — replaces the fragile "two setImmediate ticks" drain with
448
+ * `Promise.all` over the lock map so tests don't flake if the lock chain grows
449
+ * another async hop.
450
+ */
451
+ async function _flushAllWritesForTest() {
452
+ await Promise.all([...writeLocks.values()]);
453
+ }
454
+ //# sourceMappingURL=state-persister.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-persister.js","sourceRoot":"","sources":["../../src/state-persister.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,wEAAuF;AACvF,kFAAuF;AAWvF,oEAA8F;AAC9F,kEAA8F;AAC9F,0EAAoG;AA4EpG,0CAgCC;AA8BD,wCAwBC;AA+BD,wCAkEC;AAMD,4CAWC;AAMD,wDAWC;AAQD,0DASC;AAWD,4DA6CC;AAiBD,0DAEC;AAQD,wDAEC;AA7bD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,uCAAyB;AACzB,2CAA6B;AAG7B,iDAA8C;AAE9C,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;AACjE,MAAM,kBAAkB,GAAG,oBAAoB,CAAC;AAChD,MAAM,0BAA0B,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,4CAA4C;AAEpG,IAAI,kBAAkB,GAAG,CAAC,CAAC;AAC3B,SAAgB,8BAA8B,KAAa,OAAO,kBAAkB,CAAC,CAAC,CAAC;AACvF,SAAgB,mCAAmC,KAAW,kBAAkB,GAAG,CAAC,CAAC,CAAC,CAAC;AAEvF;;;;;;;GAOG;AACH,IAAI,6BAA6B,GAAG,KAAK,CAAC;AAC1C,SAAgB,4BAA4B,KAAW,6BAA6B,GAAG,IAAI,CAAC,CAAC,CAAC;AAC9F,SAAgB,2BAA2B,KAAW,6BAA6B,GAAG,KAAK,CAAC,CAAC,CAAC;AAC9F,SAAgB,+BAA+B,KAAc,OAAO,6BAA6B,CAAC,CAAC,CAAC;AAEpG;;;GAGG;AACH,SAAS,gBAAgB,CAAC,aAAqB;IAC7C,IAAI,QAAQ,GAAG,aAAa,CAAC;IAC7B,IAAI,CAAC;QACH,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,4DAA4D;IAC9D,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,iBAAiB,CAAC,aAAqB,EAAE,KAAa;IAC7D,OAAO,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,aAAa,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC;AACrE,CAAC;AAED,SAAS,mBAAmB,CAAC,aAAqB;IAChD,OAAO,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,aAAa,CAAC,EAAE,kBAAkB,CAAC,CAAC;AACxE,CAAC;AAkDD;;;GAGG;AACH,SAAgB,eAAe,CAAC,KAAqB,EAAE,KAAa,EAAE,aAAqB;IACzF,OAAO;QACL,KAAK;QACL,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;QAC5C,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;QACxC,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;QAC5C,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;QAC5C,qBAAqB,EAAE,KAAK,CAAC,qBAAqB;QAClD,oBAAoB,EAAE,KAAK,CAAC,oBAAoB;QAChD,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,eAAe,EAAE,KAAK,CAAC,eAAe;QACtC,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,eAAe,EAAE,KAAK,CAAC,eAAe;QACtC,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;QACxC,cAAc,EAAE,KAAK,CAAC,QAAQ,EAAE,MAAM;QACtC,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,2EAA2E;QAC3E,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,aAAa;QACb,aAAa,EAAE,KAAK,CAAC,SAAS,EAAE,IAAI;QACpC,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE;KACpB,CAAC;AACJ,CAAC;AAED,0EAA0E;AAC1E,2EAA2E;AAC3E,6EAA6E;AAC7E,uEAAuE;AACvE,MAAM,UAAU,GAAG,IAAI,GAAG,EAAyB,CAAC;AAEpD;;;;GAIG;AACH,SAAS,mBAAmB,CAAC,UAAkB,EAAE,IAAY;IAC3D,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACrC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,gFAAgF;IAChF,MAAM,OAAO,GAAG,GAAG,UAAU,QAAQ,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1F,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACzC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AACrC,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,cAAc,CAAC,KAAqB,EAAE,KAAa,EAAE,aAAqB;IACxF,IAAI,6BAA6B;QAAE,OAAO,CAAC,mCAAmC;IAC9E,MAAM,UAAU,GAAG,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;IAChE,MAAM,UAAU,GAAG,iBAAiB,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;IAE3D,iDAAiD;IACjD,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IACxD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;QAC1B,IAAI,CAAC;YACH,mBAAmB,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;YAC5D,kBAAkB,CAAC,aAAa,EAAE,UAAU,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QAClE,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,kBAAkB,EAAE,CAAC;YACrB,IAAI,CAAC;gBAAC,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,CAAC,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;QACvF,CAAC;IACH,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;QACZ,2EAA2E;QAC3E,2CAA2C;IAC7C,CAAC,CAAC,CAAC;IACH,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC5B,4EAA4E;IAC5E,KAAK,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;QAClB,IAAI,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI;YAAE,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;AACL,CAAC;AAED,iEAAiE;AACjE,SAAS,kBAAkB,CAAC,aAAqB,EAAE,UAAkB,EAAE,KAAa;IAClF,MAAM,SAAS,GAAG,mBAAmB,CAAC,aAAa,CAAC,CAAC;IACrD,IAAI,KAAK,GAA2B,EAAE,CAAC;IACvC,IAAI,CAAC;QACH,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAA2B,CAAC;QACpF,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,iDAAiD;QACjD,KAAK,GAAG,EAAE,CAAC;IACb,CAAC;IACD,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,KAAK;QAAE,OAAO,CAAC,qBAAqB;IAC9D,KAAK,CAAC,UAAU,CAAC,GAAG,KAAK,CAAC;IAC1B,IAAI,CAAC;QACH,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IACxD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,kBAAkB,EAAE,CAAC;QACrB,IAAI,CAAC;YAAC,OAAO,CAAC,KAAK,CAAC,0CAA0C,EAAE,CAAC,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;IAC5F,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,cAAc,CAC5B,KAAa,EACb,aAAqB,EACrB,OAAyC;IAEzC,MAAM,MAAM,GAAG,iBAAiB,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;IACvD,IAAI,EAAuB,CAAC;IAC5B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC7C,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAwB,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,yCAAyC;IACxD,CAAC;IAED,8EAA8E;IAC9E,8EAA8E;IAC9E,+DAA+D;IAC/D,IAAI,OAAO,EAAE,iBAAiB,KAAK,KAAK,IAAI,EAAE,CAAC,aAAa,EAAE,CAAC;QAC7D,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC;YAC3C,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;gBAAE,OAAO,IAAI,CAAC;QACvC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,wEAAwE;IACxE,wEAAwE;IACxE,wDAAwD;IACxD,MAAM,OAAO,GAAG;QACd,UAAU,EAAE,EAAE,CAAC,UAAU;QACzB,KAAK,EAAE,EAAE,CAAC,KAAK;QACf,kBAAkB,EAAE,EAAE,CAAC,kBAAkB;QACzC,aAAa,EAAE,EAAE,CAAC,aAAa;QAC/B,IAAI,EAAE,EAAE,CAAC,IAAI;QACb,YAAY,EAAE,EAAE,CAAC,YAAY;QAC7B,QAAQ,EAAE,EAAE,CAAC,QAAQ;QACrB,gBAAgB,EAAE,EAAE,CAAC,gBAAgB;QACrC,YAAY,EAAE,EAAE,CAAC,YAAY;QAC7B,kBAAkB,EAAE,EAAE,CAAC,kBAAkB;QACzC,kBAAkB,EAAE,EAAE,CAAC,kBAAkB;QACzC,qBAAqB,EAAE,EAAE,CAAC,qBAAqB;QAC/C,sBAAsB,EAAE,CAAC,EAAE,0CAA0C;QACrE,oBAAoB,EAAE,EAAE,CAAC,oBAAoB;QAC7C,OAAO,EAAE,EAAE,CAAC,OAAO;QACnB,eAAe,EAAE,EAAE,CAAC,eAAe;QACnC,WAAW,EAAE,EAAE,CAAC,WAAW;QAC3B,eAAe,EAAE,EAAE,CAAC,eAAe;QACnC,gBAAgB,EAAE,EAAE,CAAC,gBAAgB;QACrC,SAAS,EAAE,EAAE,CAAC,SAAS;QACvB,cAAc,EAAE,EAAE,CAAC,cAAc;QACjC,QAAQ,EAAE,IAAI,EAAE,wDAAwD;QACxE,cAAc,EAAE,CAAC;QACjB,kBAAkB,EAAE,CAAC;QACrB,qEAAqE;QACrE,yEAAyE;QACzE,uEAAuE;QACvE,2EAA2E;QAC3E,SAAS,EAAE,EAAE,CAAC,SAAS;QACvB,KAAK,EAAE,EAAE,CAAC,KAAK;QACf,QAAQ,EAAE,EAAE,CAAC,QAAQ;KACJ,CAAC;IAEpB,uDAAuD;IACvD,MAAM,aAAa,GAAG,IAAA,2BAAY,EAAC,OAAO,CAAC,CAAC;IAC5C,OAAO,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;AAC/C,CAAC;AAED;;;GAGG;AACH,SAAgB,gBAAgB,CAAC,KAAa,EAAE,aAAqB;IACnE,IAAI,6BAA6B;QAAE,OAAO,CAAC,mCAAmC;IAC9E,MAAM,MAAM,GAAG,iBAAiB,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;IACvD,IAAI,CAAC;QACH,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC;YAAE,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC;YAAC,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,CAAC,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;IACzF,CAAC;IACD,4EAA4E;IAC5E,4EAA4E;IAC5E,kDAAkD;AACpD,CAAC;AAED;;;GAGG;AACH,SAAgB,sBAAsB,CAAC,aAAqB,EAAE,UAAkB;IAC9E,MAAM,SAAS,GAAG,mBAAmB,CAAC,aAAa,CAAC,CAAC;IACrD,IAAI,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO;QACtC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAA2B,CAAC;QACxF,IAAI,CAAC,CAAC,UAAU,IAAI,KAAK,CAAC;YAAE,OAAO;QACnC,OAAO,KAAK,CAAC,UAAU,CAAC,CAAC;QACzB,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,cAAc;IAChB,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAgB,uBAAuB,CAAC,aAAqB,EAAE,UAAkB;IAC/E,MAAM,SAAS,GAAG,mBAAmB,CAAC,aAAa,CAAC,CAAC;IACrD,IAAI,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,IAAI,CAAC;QAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAA2B,CAAC;QACxF,OAAO,KAAK,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,wBAAwB,CAAC,aAAqB;IAC5D,IAAI,6BAA6B;QAAE,OAAO,EAAE,CAAC,CAAC,kCAAkC;IAChF,MAAM,GAAG,GAAG,gBAAgB,CAAC,aAAa,CAAC,CAAC;IAC5C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IACnC,IAAI,KAAe,CAAC;IACpB,IAAI,CAAC;QACH,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,kBAAkB,CAAC,CAAC;IAC3F,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACnC,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAwB,CAAC;YACjF,MAAM,IAAI,GAAG,EAAE,CAAC,kBAAkB,CAAC;YACnC,MAAM,WAAW,GAAG,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,cAAc,IAAI,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,WAAW,CAAC;YACvI,MAAM,UAAU,GAAG,IAAI,KAAK,MAAM,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,EAAE,CAAC,aAAa,IAAI,CAAC,wBAAwB,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;YAE9H,IAAI,UAAU,EAAE,CAAC;gBACf,mDAAmD;gBACnD,IAAI,EAAE,CAAC,OAAO,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,0BAA0B,EAAE,CAAC;oBAClE,IAAI,CAAC;wBAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;oBAAC,CAAC;oBAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;gBAC9D,CAAC;gBACD,SAAS;YACX,CAAC;YACD,IAAI,WAAW,EAAE,CAAC;gBAChB,6DAA6D;gBAC7D,IAAI,EAAE,CAAC,aAAa,EAAE,CAAC;oBACrB,IAAI,CAAC;wBACH,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC;wBAC3C,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;4BAAE,SAAS;oBACpC,CAAC;oBAAC,MAAM,CAAC;wBACP,SAAS,CAAC,wBAAwB;oBACpC,CAAC;gBACH,CAAC;gBACD,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,4BAA4B;QAC9B,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,gFAAgF;AAChF,8EAA8E;AAC9E,+EAA+E;AAC/E,2EAA2E;AAC3E,MAAM,uBAAuB,GAAwB,IAAI,GAAG,CAAC;IAC3D,SAAS;IACT,mBAAmB;IACnB,kBAAkB;IAClB,oBAAoB;CACrB,CAAC,CAAC;AACH,SAAS,wBAAwB,CAAC,MAAc;IAC9C,OAAO,uBAAuB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AAC7C,CAAC;AAED,yDAAyD;AACzD,SAAgB,uBAAuB;IACrC,UAAU,CAAC,KAAK,EAAE,CAAC;AACrB,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,sBAAsB;IAC1C,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AAC9C,CAAC"}