@revealui/harnesses 0.1.7 → 0.1.8
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/LICENSE +104 -17
- package/dist/{chunk-JG6CAG4A.js → chunk-4F4ANKIZ.js} +3 -2
- package/dist/chunk-4F4ANKIZ.js.map +1 -0
- package/dist/chunk-6E2BKO6U.js +2040 -0
- package/dist/chunk-6E2BKO6U.js.map +1 -0
- package/dist/chunk-DGQ5OB6L.js +380 -0
- package/dist/chunk-DGQ5OB6L.js.map +1 -0
- package/dist/{chunk-XXEKWC6F.js → chunk-PROC6EJC.js} +10 -10
- package/dist/chunk-PROC6EJC.js.map +1 -0
- package/dist/cli.js +43 -7
- package/dist/cli.js.map +1 -1
- package/dist/content/index.js +1 -1
- package/dist/index.d.ts +259 -28
- package/dist/index.js +9 -3
- package/dist/storage/index.d.ts +170 -0
- package/dist/storage/index.js +10 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/workboard/index.js +1 -1
- package/package.json +10 -4
- package/LICENSE.commercial +0 -111
- package/dist/chunk-JG6CAG4A.js.map +0 -1
- package/dist/chunk-XLIKSLM3.js +0 -1105
- package/dist/chunk-XLIKSLM3.js.map +0 -1
- package/dist/chunk-XXEKWC6F.js.map +0 -1
package/LICENSE
CHANGED
|
@@ -1,22 +1,109 @@
|
|
|
1
|
-
MIT License
|
|
1
|
+
Functional Source License, Version 1.1, MIT Future License
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Abbreviation
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
5
|
+
FSL-1.1-MIT
|
|
11
6
|
|
|
12
|
-
|
|
13
|
-
copies or substantial portions of the Software.
|
|
7
|
+
Notice
|
|
14
8
|
|
|
15
|
-
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
9
|
+
Copyright 2025-2026 RevealUI Studio (founder@revealui.com)
|
|
22
10
|
|
|
11
|
+
Terms and Conditions
|
|
12
|
+
|
|
13
|
+
Licensor: RevealUI Studio
|
|
14
|
+
|
|
15
|
+
Licensed Work: @revealui/harnesses
|
|
16
|
+
The Licensed Work is copyright 2025-2026 RevealUI Studio.
|
|
17
|
+
|
|
18
|
+
Change Date: 2028-04-08
|
|
19
|
+
|
|
20
|
+
Change License: MIT
|
|
21
|
+
|
|
22
|
+
For information about alternative licensing arrangements for the Licensed Work,
|
|
23
|
+
please contact: founder@revealui.com
|
|
24
|
+
|
|
25
|
+
License text below is the Functional Source License, Version 1.1, MIT Future
|
|
26
|
+
License, as published at https://fsl.software/FSL-1.1-MIT.template.md
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Terms and Conditions
|
|
31
|
+
|
|
32
|
+
### Acceptance
|
|
33
|
+
|
|
34
|
+
In order to get any license under these terms, you must agree to them as
|
|
35
|
+
both strict obligations and conditions to all your licenses.
|
|
36
|
+
|
|
37
|
+
### Copyright License
|
|
38
|
+
|
|
39
|
+
The licensor grants you a non-exclusive, royalty-free, worldwide,
|
|
40
|
+
non-sublicensable, non-transferable license to use, copy, distribute, make
|
|
41
|
+
available, and prepare derivative works of the licensed work, in each case
|
|
42
|
+
subject to the limitations and conditions below.
|
|
43
|
+
|
|
44
|
+
### Limitations
|
|
45
|
+
|
|
46
|
+
You may not make the functionality of the licensed work or a modified
|
|
47
|
+
version available to third parties as a service, or distribute the
|
|
48
|
+
licensed work or a modified version in a way that makes the functionality
|
|
49
|
+
of the software available to third parties. Making the functionality of
|
|
50
|
+
the licensed work available to third parties includes, without limitation,
|
|
51
|
+
enabling third parties to interact with the functionality of the licensed
|
|
52
|
+
work remotely through a computer network, offering a service the value of
|
|
53
|
+
which entirely or primarily derives from the value of the licensed work,
|
|
54
|
+
or offering a service that accomplishes for users the primary purpose of
|
|
55
|
+
the licensed work or a modified version.
|
|
56
|
+
|
|
57
|
+
### Patents
|
|
58
|
+
|
|
59
|
+
The licensor grants you a license, under any patent claims the licensor
|
|
60
|
+
can license, or becomes able to license, to make, have made, use, sell,
|
|
61
|
+
offer for sale, import and have imported the licensed work, in each case
|
|
62
|
+
subject to the limitations and conditions in this license. This license
|
|
63
|
+
does not cover any patent claims that you cause to be infringed by
|
|
64
|
+
modifications or additions to the licensed work. If you or your company
|
|
65
|
+
make any written claim that the licensed work infringes or contributes to
|
|
66
|
+
infringement of any patent, your patent license for the licensed work
|
|
67
|
+
granted under these terms ends immediately. If your company makes such a
|
|
68
|
+
claim, your patent license ends immediately for work on behalf of your
|
|
69
|
+
company.
|
|
70
|
+
|
|
71
|
+
### Fair Use
|
|
72
|
+
|
|
73
|
+
This license is not intended to limit any right of fair use, fair
|
|
74
|
+
dealing, or other applicable copyright exception or limitation.
|
|
75
|
+
|
|
76
|
+
### No Other Rights
|
|
77
|
+
|
|
78
|
+
These terms do not allow you to sublicense or transfer any of your
|
|
79
|
+
licenses to anyone else, or prevent the licensor from granting licenses
|
|
80
|
+
to anyone else. These terms do not imply any other licenses.
|
|
81
|
+
|
|
82
|
+
### Termination
|
|
83
|
+
|
|
84
|
+
If you use the licensed work in violation of these terms, such use is
|
|
85
|
+
not licensed, and your licenses may be revoked if you do not cure the
|
|
86
|
+
violation.
|
|
87
|
+
|
|
88
|
+
The licensor may also revoke your licenses if you fail to comply with
|
|
89
|
+
these terms.
|
|
90
|
+
|
|
91
|
+
### No Liability
|
|
92
|
+
|
|
93
|
+
***As far as the law allows, the licensed work comes as is, without any
|
|
94
|
+
warranty or condition, and the licensor will not be liable to you for any
|
|
95
|
+
damages arising out of these terms or the use or nature of the licensed
|
|
96
|
+
work, under any kind of legal claim.***
|
|
97
|
+
|
|
98
|
+
### Change Date
|
|
99
|
+
|
|
100
|
+
On the Change Date, or the fourth anniversary of the first publicly
|
|
101
|
+
available distribution of a specific version of the Licensed Work under
|
|
102
|
+
this License, whichever comes first, the Licensor hereby grants you
|
|
103
|
+
rights under the terms of the Change License, and the rights granted in
|
|
104
|
+
the paragraphs above terminate.
|
|
105
|
+
|
|
106
|
+
### Change License
|
|
107
|
+
|
|
108
|
+
On the Change Date, the Licensed Work will be made available under the
|
|
109
|
+
Change License specified above (MIT).
|
|
@@ -77,7 +77,8 @@ async function withLockAsync(lockPath, fn, timeoutMs) {
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
function atomicWriteSync(filePath, content) {
|
|
80
|
-
const
|
|
80
|
+
const suffix = `${process.pid}.${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;
|
|
81
|
+
const tmpPath = `${filePath}.tmp.${suffix}`;
|
|
81
82
|
writeFileSync(tmpPath, content, "utf8");
|
|
82
83
|
renameSync(tmpPath, filePath);
|
|
83
84
|
}
|
|
@@ -537,4 +538,4 @@ export {
|
|
|
537
538
|
detectSessionType,
|
|
538
539
|
deriveSessionId
|
|
539
540
|
};
|
|
540
|
-
//# sourceMappingURL=chunk-
|
|
541
|
+
//# sourceMappingURL=chunk-4F4ANKIZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/workboard/file-lock.ts","../src/workboard/session-identity.ts","../src/workboard/workboard-manager.ts"],"sourcesContent":["import {\n closeSync,\n openSync,\n readFileSync,\n renameSync,\n unlinkSync,\n writeFileSync,\n writeSync,\n} from 'node:fs';\n\nconst DEFAULT_TIMEOUT_MS = 2000;\nconst RETRY_MS = 50;\n\n/**\n * Check whether a process is still running.\n * Uses signal 0 which doesn't actually send a signal — just checks existence.\n */\nfunction isPidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Acquire an exclusive file lock using O_EXCL (kernel-level atomic create).\n * Writes the current PID to the lock file for dead-holder detection.\n *\n * Spins with a 50ms interval until timeout. If the current lock holder\n * is dead (process no longer running), the lock is stolen.\n *\n * @returns true if the lock was acquired, false on timeout\n */\nexport function acquireLock(lockPath: string, timeoutMs = DEFAULT_TIMEOUT_MS): boolean {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n try {\n const fd = openSync(lockPath, 'wx');\n writeSync(fd, String(process.pid));\n closeSync(fd);\n return true;\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code !== 'EEXIST') return false;\n // Lock exists — check if holder is alive\n try {\n const holderPid = Number.parseInt(readFileSync(lockPath, 'utf8').trim(), 10);\n if (!(Number.isNaN(holderPid) || isPidAlive(holderPid))) {\n // Holder crashed — steal the lock\n unlinkSync(lockPath);\n continue;\n }\n } catch {\n // Lock file disappeared between checks — retry immediately\n continue;\n }\n // Busy-wait\n const spinUntil = Date.now() + RETRY_MS;\n while (Date.now() < spinUntil) {\n /* spin */\n }\n }\n }\n return false;\n}\n\n/**\n * Release a file lock. Swallows ENOENT (already released).\n */\nexport function releaseLock(lockPath: string): void {\n try {\n unlinkSync(lockPath);\n } catch {\n // Already released or never acquired — non-fatal\n }\n}\n\n/**\n * Execute a synchronous function while holding the file lock.\n * The lock is always released, even if fn throws.\n */\nexport function withLock<T>(lockPath: string, fn: () => T, timeoutMs?: number): T {\n const acquired = acquireLock(lockPath, timeoutMs);\n if (!acquired) {\n throw new Error(\n `Failed to acquire lock: ${lockPath} (timeout ${timeoutMs ?? DEFAULT_TIMEOUT_MS}ms)`,\n );\n }\n try {\n return fn();\n } finally {\n releaseLock(lockPath);\n }\n}\n\n/**\n * Execute an async function while holding the file lock.\n * The lock is always released, even if fn throws.\n */\nexport async function withLockAsync<T>(\n lockPath: string,\n fn: () => Promise<T>,\n timeoutMs?: number,\n): Promise<T> {\n const acquired = acquireLock(lockPath, timeoutMs);\n if (!acquired) {\n throw new Error(\n `Failed to acquire lock: ${lockPath} (timeout ${timeoutMs ?? DEFAULT_TIMEOUT_MS}ms)`,\n );\n }\n try {\n return await fn();\n } finally {\n releaseLock(lockPath);\n }\n}\n\n/**\n * Write a file atomically: write to a temporary file, then rename.\n * rename() on the same filesystem is atomic at the kernel level.\n */\nexport function atomicWriteSync(filePath: string, content: string): void {\n const suffix = `${process.pid}.${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;\n const tmpPath = `${filePath}.tmp.${suffix}`;\n writeFileSync(tmpPath, content, 'utf8');\n renameSync(tmpPath, filePath);\n}\n\n/**\n * Derive a lock path from a workboard path (.md → .lock).\n */\nexport function lockPathFor(workboardPath: string): string {\n return workboardPath.replace(/\\.md$/, '.lock');\n}\n","import { readFileSync } from 'node:fs';\n\n/** Type of session detected from the runtime environment. */\nexport type SessionType = 'zed' | 'cursor' | 'terminal';\n\n/**\n * Detects whether the current process is running inside an AI tool (Zed, Cursor)\n * or a plain terminal session by walking the parent process chain.\n *\n * Uses /proc/<pid>/cmdline on Linux/WSL. Falls back to TERM_PROGRAM env var.\n */\nexport function detectSessionType(): SessionType {\n // Walk parent process chain looking for known AI tool process names.\n try {\n let pid = process.ppid;\n for (let depth = 0; depth < 8; depth++) {\n if (!pid || pid <= 1) break;\n const cmdline = readFileSync(`/proc/${pid}/cmdline`, 'utf8')\n .replace(/\\0/g, ' ')\n .toLowerCase();\n if (cmdline.includes('zed')) return 'zed';\n if (cmdline.includes('cursor')) return 'cursor';\n const status = readFileSync(`/proc/${pid}/status`, 'utf8');\n const m = status.match(/PPid:\\s+(\\d+)/);\n if (!m) break;\n pid = parseInt(m[1] ?? '0', 10);\n }\n } catch {\n // /proc not available (macOS, Windows non-WSL).\n }\n\n // Fallback: TERM_PROGRAM env var (set by some terminal emulators and IDEs).\n const termProgram = (process.env.TERM_PROGRAM ?? '').toLowerCase();\n if (termProgram.includes('zed')) return 'zed';\n if (termProgram.includes('cursor')) return 'cursor';\n\n return 'terminal';\n}\n\n/**\n * Derives a session ID (e.g. \"zed-1\", \"terminal-2\") given a type and a list\n * of existing session IDs already in the workboard.\n *\n * Picks the next available numeric suffix to avoid collisions.\n */\nexport function deriveSessionId(type: SessionType, existingIds: string[]): string {\n const matching = existingIds\n .filter((id) => id.startsWith(`${type}-`))\n .map((id) => parseInt(id.split('-')[1] ?? '0', 10))\n .filter((n) => !Number.isNaN(n));\n\n const maxN = matching.length > 0 ? Math.max(...matching) : 0;\n return `${type}-${maxN + 1}`;\n}\n","import { readFileSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { atomicWriteSync, lockPathFor, withLock, withLockAsync } from './file-lock.js';\nimport type {\n ConflictResult,\n WorkboardAgent,\n WorkboardState,\n WorkboardTask,\n} from './workboard-protocol.js';\n\nconst STALE_THRESHOLD_MS = 4 * 60 * 60 * 1000; // 4 hours\nconst STARTING_STALE_MS = 60 * 60 * 1000; // 1 hour\n\n// ---------------------------------------------------------------------------\n// Section name normalization (backward compat with v1 workboard)\n// ---------------------------------------------------------------------------\n\nconst SECTION_MAP: Record<\n string,\n keyof Pick<WorkboardState, 'agents' | 'tasks' | 'blocked' | 'done' | 'log'> | null\n> = {\n agents: 'agents',\n active_sessions: 'agents',\n sessions: 'agents',\n tasks: 'tasks',\n blocked: 'blocked',\n done: 'done',\n log: 'log',\n recent: 'log',\n};\n\nfunction normalizeSectionName(title: string): string | null {\n const key = title.toLowerCase().replace(/\\s+/g, '_');\n return SECTION_MAP[key] || null;\n}\n\n// ---------------------------------------------------------------------------\n// Table parsing\n// ---------------------------------------------------------------------------\n\nfunction splitRow(line: string): string[] | null {\n if (!line.startsWith('|')) return null;\n return line\n .split('|')\n .slice(1, -1)\n .map((c) => c.trim());\n}\n\nfunction isSeparatorRow(cells: string[]): boolean {\n return cells.length > 0 && cells.every((c) => /^[-:]+$/.test(c));\n}\n\nfunction parseTable(lines: string[]): { columns: string[]; rows: Record<string, string>[] } {\n if (lines.length < 2) return { columns: [], rows: [] };\n\n const headerCells = splitRow(lines[0]!);\n if (!headerCells) return { columns: [], rows: [] };\n\n const sepCells = splitRow(lines[1]!);\n if (!(sepCells && isSeparatorRow(sepCells))) return { columns: [], rows: [] };\n\n const columns = headerCells.map((h) =>\n h\n .toLowerCase()\n .replace(/[^a-z0-9_]/g, '_')\n .replace(/_+/g, '_')\n .replace(/^_|_$/g, ''),\n );\n\n const rows: Record<string, string>[] = [];\n for (let i = 2; i < lines.length; i++) {\n const cells = splitRow(lines[i]!);\n if (!cells || isSeparatorRow(cells)) continue;\n const row: Record<string, string> = {};\n for (let j = 0; j < columns.length; j++) {\n const col = columns[j]!;\n const raw = (cells[j] || '').trim();\n row[col] = raw === '—' ? '' : raw;\n }\n rows.push(row);\n }\n\n return { columns, rows };\n}\n\n// ---------------------------------------------------------------------------\n// Parse\n// ---------------------------------------------------------------------------\n\nfunction parseWorkboard(content: string): WorkboardState {\n const lines = content.split('\\n');\n const rawSections: Array<{ title: string; line: number }> = [];\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]!;\n const m = line.match(/^##\\s+(.+)/);\n if (m?.[1]) rawSections.push({ title: m[1].trim(), line: i });\n }\n\n const state: WorkboardState = {\n preamble: [],\n agents: [],\n tasks: [],\n blocked: [],\n done: [],\n log: [],\n _extra: {},\n };\n\n const firstLine = rawSections.length > 0 ? rawSections[0]?.line : lines.length;\n state.preamble = lines.slice(0, firstLine);\n\n for (let i = 0; i < rawSections.length; i++) {\n const sec = rawSections[i]!;\n const nextLine = i + 1 < rawSections.length ? rawSections[i + 1]?.line : lines.length;\n const body = lines.slice(sec.line + 1, nextLine);\n const normalized = normalizeSectionName(sec.title);\n\n if (\n normalized === 'agents' ||\n normalized === 'tasks' ||\n normalized === 'blocked' ||\n normalized === 'done'\n ) {\n const tableLines = body.filter((l) => l.startsWith('|'));\n if (tableLines.length >= 2) {\n const { rows } = parseTable(tableLines);\n (state[normalized] as unknown as Record<string, string>[]).length = 0;\n (state[normalized] as unknown as Record<string, string>[]).push(...rows);\n }\n } else if (normalized === 'log') {\n state.log = body.filter((l) => l.startsWith('- '));\n } else {\n state._extra[sec.title] = lines.slice(sec.line, nextLine).join('\\n');\n }\n }\n\n return state;\n}\n\n// ---------------------------------------------------------------------------\n// Serialize\n// ---------------------------------------------------------------------------\n\nfunction padCell(value: string | undefined, width: number): string {\n const str = String(value || '—');\n return str.length >= width ? str : str + ' '.repeat(width - str.length);\n}\n\nfunction serializeTable(headers: string[], rows: Record<string, string>[]): string {\n if (headers.length === 0) return '(none)';\n\n const widths = headers.map((h) => {\n const dataMax = rows.reduce((max, row) => Math.max(max, String(row[h] || '—').length), 0);\n return Math.max(h.length, dataMax, 3);\n });\n\n const headerLine = `| ${headers.map((h, i) => padCell(h, widths[i]!)).join(' | ')} |`;\n const sepLine = `| ${widths.map((w) => '-'.repeat(w)).join(' | ')} |`;\n const dataLines = rows.map(\n (row) => `| ${headers.map((h, i) => padCell(row[h] || '', widths[i]!)).join(' | ')} |`,\n );\n\n return [headerLine, sepLine, ...dataLines].join('\\n');\n}\n\nfunction serializeWorkboard(state: WorkboardState): string {\n const out: string[] = [];\n\n if (state.preamble.length > 0) {\n out.push(...state.preamble);\n if (state.preamble[state.preamble.length - 1] !== '') out.push('');\n }\n\n out.push('## Agents', '');\n out.push(\n serializeTable(\n ['id', 'env', 'started', 'task', 'files', 'updated'],\n state.agents as unknown as Record<string, string>[],\n ),\n '',\n );\n\n out.push('## Tasks', '');\n if (state.tasks.length > 0) {\n out.push(\n serializeTable(\n ['id', 'task', 'pri', 'status', 'owner', 'gh', 'updated', 'notes'],\n state.tasks as unknown as Record<string, string>[],\n ),\n '',\n );\n } else {\n out.push('(none)', '');\n }\n\n out.push('## Blocked', '');\n if (state.blocked.length > 0) {\n out.push(\n serializeTable(\n ['id', 'task', 'blocker', 'gh', 'notes'],\n state.blocked as unknown as Record<string, string>[],\n ),\n '',\n );\n } else {\n out.push('(none)', '');\n }\n\n out.push('## Done', '');\n if (state.done.length > 0) {\n out.push(\n serializeTable(\n ['id', 'task', 'owner', 'completed', 'gh', 'notes'],\n state.done as unknown as Record<string, string>[],\n ),\n '',\n );\n } else {\n out.push('(none)', '');\n }\n\n out.push('## Log', '');\n if (state.log.length > 0) out.push(...state.log);\n out.push('');\n\n for (const content of Object.values(state._extra)) {\n out.push(content, '');\n }\n\n return out.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// WorkboardManager\n// ---------------------------------------------------------------------------\n\n/**\n * WorkboardManager — reads, parses, and writes .claude/workboard.md (v2).\n *\n * Supports both v1 (Sessions/Recent) and v2 (Agents/Tasks/Blocked/Done/Log)\n * formats for backward compatibility. Always serializes to v2.\n *\n * All mutating methods use file locking (O_EXCL) to prevent race conditions.\n * Writes are atomic (tmp file + rename).\n */\nexport class WorkboardManager {\n private readonly lockPath: string;\n\n constructor(private readonly workboardPath: string) {\n const resolved = resolve(workboardPath);\n if (!resolved.endsWith('.md')) {\n throw new Error('Invalid workboard path: must be a .md file');\n }\n this.lockPath = lockPathFor(resolved);\n }\n\n // ---- Read/Write ----\n\n read(): WorkboardState {\n try {\n return parseWorkboard(readFileSync(this.workboardPath, 'utf8'));\n } catch {\n return emptyState();\n }\n }\n\n write(state: WorkboardState): void {\n withLock(this.lockPath, () => {\n atomicWriteSync(this.workboardPath, serializeWorkboard(state));\n });\n }\n\n async readAsync(): Promise<WorkboardState> {\n try {\n return parseWorkboard(await readFile(this.workboardPath, 'utf8'));\n } catch {\n return emptyState();\n }\n }\n\n async writeAsync(state: WorkboardState): Promise<void> {\n await withLockAsync(this.lockPath, async () => {\n atomicWriteSync(this.workboardPath, serializeWorkboard(state));\n });\n }\n\n // ---- Agent methods ----\n\n registerAgent(agent: WorkboardAgent): void {\n withLock(this.lockPath, () => {\n const state = this.readUnlocked();\n const idx = state.agents.findIndex((a) => a.id === agent.id);\n if (idx >= 0) {\n state.agents[idx] = agent;\n } else {\n state.agents.push(agent);\n }\n this.writeUnlocked(state);\n });\n }\n\n unregisterAgent(id: string): void {\n withLock(this.lockPath, () => {\n const state = this.readUnlocked();\n state.agents = state.agents.filter((a) => a.id !== id);\n this.writeUnlocked(state);\n });\n }\n\n updateAgent(id: string, updates: Partial<WorkboardAgent>): void {\n withLock(this.lockPath, () => {\n const state = this.readUnlocked();\n const idx = state.agents.findIndex((a) => a.id === id);\n if (idx < 0) return;\n state.agents[idx] = { ...state.agents[idx]!, ...updates };\n this.writeUnlocked(state);\n });\n }\n\n // ---- Task claiming ----\n\n /** Claim an available or partial task. Returns true on success. */\n claimTask(taskId: string, agentId: string): boolean {\n let success = false;\n withLock(this.lockPath, () => {\n const state = this.readUnlocked();\n const task = state.tasks.find((t) => t.id === taskId);\n if (!task) return;\n if (task.status !== 'available' && task.status !== 'partial') return;\n task.status = 'claimed';\n task.owner = agentId;\n task.updated = new Date().toISOString().slice(0, 10);\n this.writeUnlocked(state);\n success = true;\n });\n return success;\n }\n\n /** Move a task from Tasks to Done. Returns true on success. */\n completeTask(taskId: string, agentId: string): boolean {\n let success = false;\n withLock(this.lockPath, () => {\n const state = this.readUnlocked();\n const idx = state.tasks.findIndex((t) => t.id === taskId);\n if (idx === -1) return;\n const task = state.tasks.splice(idx, 1)[0]!;\n state.done.unshift({\n id: task.id,\n task: task.task,\n owner: agentId || task.owner,\n completed: new Date().toISOString().slice(0, 10),\n gh: task.gh || '',\n notes: task.notes || '',\n });\n this.writeUnlocked(state);\n success = true;\n });\n return success;\n }\n\n /** Mark a claimed task as partial (agent stopped mid-work). */\n markPartial(taskId: string, notes: string): boolean {\n let success = false;\n withLock(this.lockPath, () => {\n const state = this.readUnlocked();\n const task = state.tasks.find((t) => t.id === taskId);\n if (!task) return;\n task.status = 'partial';\n task.updated = new Date().toISOString().slice(0, 10);\n if (notes) task.notes = notes;\n this.writeUnlocked(state);\n success = true;\n });\n return success;\n }\n\n /** Release a claimed/partial task back to available. */\n releaseTask(taskId: string): boolean {\n let success = false;\n withLock(this.lockPath, () => {\n const state = this.readUnlocked();\n const task = state.tasks.find((t) => t.id === taskId);\n if (!task) return;\n task.status = 'available';\n task.owner = '';\n task.updated = new Date().toISOString().slice(0, 10);\n this.writeUnlocked(state);\n success = true;\n });\n return success;\n }\n\n /** Move a blocked task to Tasks as available. */\n unblockTask(taskId: string, pri: string = 'P2'): boolean {\n let success = false;\n withLock(this.lockPath, () => {\n const state = this.readUnlocked();\n const idx = state.blocked.findIndex((t) => t.id === taskId);\n if (idx === -1) return;\n const blocked = state.blocked.splice(idx, 1)[0]!;\n state.tasks.push({\n id: blocked.id,\n task: blocked.task,\n pri: pri as WorkboardTask['pri'],\n status: 'available',\n owner: '',\n gh: blocked.gh || '',\n updated: new Date().toISOString().slice(0, 10),\n notes: blocked.notes || '',\n });\n this.writeUnlocked(state);\n success = true;\n });\n return success;\n }\n\n // ---- File claims ----\n\n claimFiles(id: string, files: string[]): void {\n withLock(this.lockPath, () => {\n const state = this.readUnlocked();\n const agent = state.agents.find((a) => a.id === id);\n if (!agent) return;\n agent.files = files.join(', ');\n agent.updated = `${new Date().toISOString().slice(0, 16)}Z`;\n this.writeUnlocked(state);\n });\n }\n\n releaseFiles(id: string): void {\n withLock(this.lockPath, () => {\n const state = this.readUnlocked();\n const agent = state.agents.find((a) => a.id === id);\n if (!agent) return;\n agent.files = '';\n agent.updated = `${new Date().toISOString().slice(0, 16)}Z`;\n this.writeUnlocked(state);\n });\n }\n\n // ---- Log ----\n\n addLogEntry(agentId: string, description: string): void {\n withLock(this.lockPath, () => {\n const state = this.readUnlocked();\n const now = new Date();\n const dateStr = now.toISOString().slice(0, 10);\n const timeStr = now.toISOString().slice(11, 16);\n state.log.unshift(`- [${dateStr} ${timeStr}] ${agentId}: ${description}`);\n if (state.log.length > 20) state.log.splice(20);\n this.writeUnlocked(state);\n });\n }\n\n // ---- Queries ----\n\n detectStale(): WorkboardAgent[] {\n const state = this.read();\n const now = Date.now();\n return state.agents.filter((a) => {\n try {\n const age = now - new Date(a.updated).getTime();\n const threshold = a.task === '(starting)' ? STARTING_STALE_MS : STALE_THRESHOLD_MS;\n return age > threshold;\n } catch {\n return false;\n }\n });\n }\n\n checkConflicts(mySessionId: string, files: string[]): ConflictResult {\n const state = this.read();\n const conflicts: ConflictResult['conflicts'] = [];\n\n for (const agent of state.agents) {\n if (agent.id === mySessionId) continue;\n const theirFiles = agent.files\n .split(',')\n .map((f) => f.trim())\n .filter(Boolean);\n const overlapping = files.filter((myFile) =>\n theirFiles.some(\n (theirFile) =>\n myFile === theirFile ||\n myFile.startsWith(theirFile.replace('**', '')) ||\n theirFile.startsWith(myFile.replace('**', '')),\n ),\n );\n if (overlapping.length > 0) {\n conflicts.push({\n thisSession: mySessionId,\n otherSession: agent.id,\n overlappingFiles: overlapping,\n });\n }\n }\n\n return { clean: conflicts.length === 0, conflicts };\n }\n\n getClaimedTasks(agentId: string): WorkboardTask[] {\n const state = this.read();\n return state.tasks.filter(\n (t) => t.status === 'claimed' && t.owner === agentId,\n ) as WorkboardTask[];\n }\n\n // ---- Internal ----\n\n private readUnlocked(): WorkboardState {\n try {\n return parseWorkboard(readFileSync(this.workboardPath, 'utf8'));\n } catch {\n return emptyState();\n }\n }\n\n private writeUnlocked(state: WorkboardState): void {\n atomicWriteSync(this.workboardPath, serializeWorkboard(state));\n }\n}\n\nfunction emptyState(): WorkboardState {\n return { preamble: [], agents: [], tasks: [], blocked: [], done: [], log: [], _extra: {} };\n}\n\n// Re-export for backward compat\n/** @deprecated Use registerAgent instead */\nexport const registerSession = WorkboardManager.prototype.registerAgent;\n/** @deprecated Use unregisterAgent instead */\nexport const unregisterSession = WorkboardManager.prototype.unregisterAgent;\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,IAAM,qBAAqB;AAC3B,IAAM,WAAW;AAMjB,SAAS,WAAW,KAAsB;AACxC,MAAI;AACF,YAAQ,KAAK,KAAK,CAAC;AACnB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAWO,SAAS,YAAY,UAAkB,YAAY,oBAA6B;AACrF,QAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,SAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,QAAI;AACF,YAAM,KAAK,SAAS,UAAU,IAAI;AAClC,gBAAU,IAAI,OAAO,QAAQ,GAAG,CAAC;AACjC,gBAAU,EAAE;AACZ,aAAO;AAAA,IACT,SAAS,KAAc;AACrB,UAAK,IAA8B,SAAS,SAAU,QAAO;AAE7D,UAAI;AACF,cAAM,YAAY,OAAO,SAAS,aAAa,UAAU,MAAM,EAAE,KAAK,GAAG,EAAE;AAC3E,YAAI,EAAE,OAAO,MAAM,SAAS,KAAK,WAAW,SAAS,IAAI;AAEvD,qBAAW,QAAQ;AACnB;AAAA,QACF;AAAA,MACF,QAAQ;AAEN;AAAA,MACF;AAEA,YAAM,YAAY,KAAK,IAAI,IAAI;AAC/B,aAAO,KAAK,IAAI,IAAI,WAAW;AAAA,MAE/B;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAKO,SAAS,YAAY,UAAwB;AAClD,MAAI;AACF,eAAW,QAAQ;AAAA,EACrB,QAAQ;AAAA,EAER;AACF;AAMO,SAAS,SAAY,UAAkB,IAAa,WAAuB;AAChF,QAAM,WAAW,YAAY,UAAU,SAAS;AAChD,MAAI,CAAC,UAAU;AACb,UAAM,IAAI;AAAA,MACR,2BAA2B,QAAQ,aAAa,aAAa,kBAAkB;AAAA,IACjF;AAAA,EACF;AACA,MAAI;AACF,WAAO,GAAG;AAAA,EACZ,UAAE;AACA,gBAAY,QAAQ;AAAA,EACtB;AACF;AAMA,eAAsB,cACpB,UACA,IACA,WACY;AACZ,QAAM,WAAW,YAAY,UAAU,SAAS;AAChD,MAAI,CAAC,UAAU;AACb,UAAM,IAAI;AAAA,MACR,2BAA2B,QAAQ,aAAa,aAAa,kBAAkB;AAAA,IACjF;AAAA,EACF;AACA,MAAI;AACF,WAAO,MAAM,GAAG;AAAA,EAClB,UAAE;AACA,gBAAY,QAAQ;AAAA,EACtB;AACF;AAMO,SAAS,gBAAgB,UAAkB,SAAuB;AACvE,QAAM,SAAS,GAAG,QAAQ,GAAG,IAAI,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC,GAAG,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AACjG,QAAM,UAAU,GAAG,QAAQ,QAAQ,MAAM;AACzC,gBAAc,SAAS,SAAS,MAAM;AACtC,aAAW,SAAS,QAAQ;AAC9B;AAKO,SAAS,YAAY,eAA+B;AACzD,SAAO,cAAc,QAAQ,SAAS,OAAO;AAC/C;;;ACtIA,SAAS,gBAAAA,qBAAoB;AAWtB,SAAS,oBAAiC;AAE/C,MAAI;AACF,QAAI,MAAM,QAAQ;AAClB,aAAS,QAAQ,GAAG,QAAQ,GAAG,SAAS;AACtC,UAAI,CAAC,OAAO,OAAO,EAAG;AACtB,YAAM,UAAUA,cAAa,SAAS,GAAG,YAAY,MAAM,EACxD,QAAQ,OAAO,GAAG,EAClB,YAAY;AACf,UAAI,QAAQ,SAAS,KAAK,EAAG,QAAO;AACpC,UAAI,QAAQ,SAAS,QAAQ,EAAG,QAAO;AACvC,YAAM,SAASA,cAAa,SAAS,GAAG,WAAW,MAAM;AACzD,YAAM,IAAI,OAAO,MAAM,eAAe;AACtC,UAAI,CAAC,EAAG;AACR,YAAM,SAAS,EAAE,CAAC,KAAK,KAAK,EAAE;AAAA,IAChC;AAAA,EACF,QAAQ;AAAA,EAER;AAGA,QAAM,eAAe,QAAQ,IAAI,gBAAgB,IAAI,YAAY;AACjE,MAAI,YAAY,SAAS,KAAK,EAAG,QAAO;AACxC,MAAI,YAAY,SAAS,QAAQ,EAAG,QAAO;AAE3C,SAAO;AACT;AAQO,SAAS,gBAAgB,MAAmB,aAA+B;AAChF,QAAM,WAAW,YACd,OAAO,CAAC,OAAO,GAAG,WAAW,GAAG,IAAI,GAAG,CAAC,EACxC,IAAI,CAAC,OAAO,SAAS,GAAG,MAAM,GAAG,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC,EACjD,OAAO,CAAC,MAAM,CAAC,OAAO,MAAM,CAAC,CAAC;AAEjC,QAAM,OAAO,SAAS,SAAS,IAAI,KAAK,IAAI,GAAG,QAAQ,IAAI;AAC3D,SAAO,GAAG,IAAI,IAAI,OAAO,CAAC;AAC5B;;;ACrDA,SAAS,gBAAAC,qBAAoB;AAC7B,SAAS,gBAAgB;AACzB,SAAS,eAAe;AASxB,IAAM,qBAAqB,IAAI,KAAK,KAAK;AACzC,IAAM,oBAAoB,KAAK,KAAK;AAMpC,IAAM,cAGF;AAAA,EACF,QAAQ;AAAA,EACR,iBAAiB;AAAA,EACjB,UAAU;AAAA,EACV,OAAO;AAAA,EACP,SAAS;AAAA,EACT,MAAM;AAAA,EACN,KAAK;AAAA,EACL,QAAQ;AACV;AAEA,SAAS,qBAAqB,OAA8B;AAC1D,QAAM,MAAM,MAAM,YAAY,EAAE,QAAQ,QAAQ,GAAG;AACnD,SAAO,YAAY,GAAG,KAAK;AAC7B;AAMA,SAAS,SAAS,MAA+B;AAC/C,MAAI,CAAC,KAAK,WAAW,GAAG,EAAG,QAAO;AAClC,SAAO,KACJ,MAAM,GAAG,EACT,MAAM,GAAG,EAAE,EACX,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AACxB;AAEA,SAAS,eAAe,OAA0B;AAChD,SAAO,MAAM,SAAS,KAAK,MAAM,MAAM,CAAC,MAAM,UAAU,KAAK,CAAC,CAAC;AACjE;AAEA,SAAS,WAAW,OAAwE;AAC1F,MAAI,MAAM,SAAS,EAAG,QAAO,EAAE,SAAS,CAAC,GAAG,MAAM,CAAC,EAAE;AAErD,QAAM,cAAc,SAAS,MAAM,CAAC,CAAE;AACtC,MAAI,CAAC,YAAa,QAAO,EAAE,SAAS,CAAC,GAAG,MAAM,CAAC,EAAE;AAEjD,QAAM,WAAW,SAAS,MAAM,CAAC,CAAE;AACnC,MAAI,EAAE,YAAY,eAAe,QAAQ,GAAI,QAAO,EAAE,SAAS,CAAC,GAAG,MAAM,CAAC,EAAE;AAE5E,QAAM,UAAU,YAAY;AAAA,IAAI,CAAC,MAC/B,EACG,YAAY,EACZ,QAAQ,eAAe,GAAG,EAC1B,QAAQ,OAAO,GAAG,EAClB,QAAQ,UAAU,EAAE;AAAA,EACzB;AAEA,QAAM,OAAiC,CAAC;AACxC,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,QAAQ,SAAS,MAAM,CAAC,CAAE;AAChC,QAAI,CAAC,SAAS,eAAe,KAAK,EAAG;AACrC,UAAM,MAA8B,CAAC;AACrC,aAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,YAAM,MAAM,QAAQ,CAAC;AACrB,YAAM,OAAO,MAAM,CAAC,KAAK,IAAI,KAAK;AAClC,UAAI,GAAG,IAAI,QAAQ,WAAM,KAAK;AAAA,IAChC;AACA,SAAK,KAAK,GAAG;AAAA,EACf;AAEA,SAAO,EAAE,SAAS,KAAK;AACzB;AAMA,SAAS,eAAe,SAAiC;AACvD,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,QAAM,cAAsD,CAAC;AAC7D,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,OAAO,MAAM,CAAC;AACpB,UAAM,IAAI,KAAK,MAAM,YAAY;AACjC,QAAI,IAAI,CAAC,EAAG,aAAY,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,GAAG,MAAM,EAAE,CAAC;AAAA,EAC9D;AAEA,QAAM,QAAwB;AAAA,IAC5B,UAAU,CAAC;AAAA,IACX,QAAQ,CAAC;AAAA,IACT,OAAO,CAAC;AAAA,IACR,SAAS,CAAC;AAAA,IACV,MAAM,CAAC;AAAA,IACP,KAAK,CAAC;AAAA,IACN,QAAQ,CAAC;AAAA,EACX;AAEA,QAAM,YAAY,YAAY,SAAS,IAAI,YAAY,CAAC,GAAG,OAAO,MAAM;AACxE,QAAM,WAAW,MAAM,MAAM,GAAG,SAAS;AAEzC,WAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,UAAM,MAAM,YAAY,CAAC;AACzB,UAAM,WAAW,IAAI,IAAI,YAAY,SAAS,YAAY,IAAI,CAAC,GAAG,OAAO,MAAM;AAC/E,UAAM,OAAO,MAAM,MAAM,IAAI,OAAO,GAAG,QAAQ;AAC/C,UAAM,aAAa,qBAAqB,IAAI,KAAK;AAEjD,QACE,eAAe,YACf,eAAe,WACf,eAAe,aACf,eAAe,QACf;AACA,YAAM,aAAa,KAAK,OAAO,CAAC,MAAM,EAAE,WAAW,GAAG,CAAC;AACvD,UAAI,WAAW,UAAU,GAAG;AAC1B,cAAM,EAAE,KAAK,IAAI,WAAW,UAAU;AACtC,QAAC,MAAM,UAAU,EAA0C,SAAS;AACpE,QAAC,MAAM,UAAU,EAA0C,KAAK,GAAG,IAAI;AAAA,MACzE;AAAA,IACF,WAAW,eAAe,OAAO;AAC/B,YAAM,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,WAAW,IAAI,CAAC;AAAA,IACnD,OAAO;AACL,YAAM,OAAO,IAAI,KAAK,IAAI,MAAM,MAAM,IAAI,MAAM,QAAQ,EAAE,KAAK,IAAI;AAAA,IACrE;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,QAAQ,OAA2B,OAAuB;AACjE,QAAM,MAAM,OAAO,SAAS,QAAG;AAC/B,SAAO,IAAI,UAAU,QAAQ,MAAM,MAAM,IAAI,OAAO,QAAQ,IAAI,MAAM;AACxE;AAEA,SAAS,eAAe,SAAmB,MAAwC;AACjF,MAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,QAAM,SAAS,QAAQ,IAAI,CAAC,MAAM;AAChC,UAAM,UAAU,KAAK,OAAO,CAAC,KAAK,QAAQ,KAAK,IAAI,KAAK,OAAO,IAAI,CAAC,KAAK,QAAG,EAAE,MAAM,GAAG,CAAC;AACxF,WAAO,KAAK,IAAI,EAAE,QAAQ,SAAS,CAAC;AAAA,EACtC,CAAC;AAED,QAAM,aAAa,KAAK,QAAQ,IAAI,CAAC,GAAG,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAE,CAAC,EAAE,KAAK,KAAK,CAAC;AACjF,QAAM,UAAU,KAAK,OAAO,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC;AACjE,QAAM,YAAY,KAAK;AAAA,IACrB,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,GAAG,MAAM,QAAQ,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,CAAE,CAAC,EAAE,KAAK,KAAK,CAAC;AAAA,EACpF;AAEA,SAAO,CAAC,YAAY,SAAS,GAAG,SAAS,EAAE,KAAK,IAAI;AACtD;AAEA,SAAS,mBAAmB,OAA+B;AACzD,QAAM,MAAgB,CAAC;AAEvB,MAAI,MAAM,SAAS,SAAS,GAAG;AAC7B,QAAI,KAAK,GAAG,MAAM,QAAQ;AAC1B,QAAI,MAAM,SAAS,MAAM,SAAS,SAAS,CAAC,MAAM,GAAI,KAAI,KAAK,EAAE;AAAA,EACnE;AAEA,MAAI,KAAK,aAAa,EAAE;AACxB,MAAI;AAAA,IACF;AAAA,MACE,CAAC,MAAM,OAAO,WAAW,QAAQ,SAAS,SAAS;AAAA,MACnD,MAAM;AAAA,IACR;AAAA,IACA;AAAA,EACF;AAEA,MAAI,KAAK,YAAY,EAAE;AACvB,MAAI,MAAM,MAAM,SAAS,GAAG;AAC1B,QAAI;AAAA,MACF;AAAA,QACE,CAAC,MAAM,QAAQ,OAAO,UAAU,SAAS,MAAM,WAAW,OAAO;AAAA,QACjE,MAAM;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF,OAAO;AACL,QAAI,KAAK,UAAU,EAAE;AAAA,EACvB;AAEA,MAAI,KAAK,cAAc,EAAE;AACzB,MAAI,MAAM,QAAQ,SAAS,GAAG;AAC5B,QAAI;AAAA,MACF;AAAA,QACE,CAAC,MAAM,QAAQ,WAAW,MAAM,OAAO;AAAA,QACvC,MAAM;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF,OAAO;AACL,QAAI,KAAK,UAAU,EAAE;AAAA,EACvB;AAEA,MAAI,KAAK,WAAW,EAAE;AACtB,MAAI,MAAM,KAAK,SAAS,GAAG;AACzB,QAAI;AAAA,MACF;AAAA,QACE,CAAC,MAAM,QAAQ,SAAS,aAAa,MAAM,OAAO;AAAA,QAClD,MAAM;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF,OAAO;AACL,QAAI,KAAK,UAAU,EAAE;AAAA,EACvB;AAEA,MAAI,KAAK,UAAU,EAAE;AACrB,MAAI,MAAM,IAAI,SAAS,EAAG,KAAI,KAAK,GAAG,MAAM,GAAG;AAC/C,MAAI,KAAK,EAAE;AAEX,aAAW,WAAW,OAAO,OAAO,MAAM,MAAM,GAAG;AACjD,QAAI,KAAK,SAAS,EAAE;AAAA,EACtB;AAEA,SAAO,IAAI,KAAK,IAAI;AACtB;AAeO,IAAM,mBAAN,MAAuB;AAAA,EAG5B,YAA6B,eAAuB;AAAvB;AAC3B,UAAM,WAAW,QAAQ,aAAa;AACtC,QAAI,CAAC,SAAS,SAAS,KAAK,GAAG;AAC7B,YAAM,IAAI,MAAM,4CAA4C;AAAA,IAC9D;AACA,SAAK,WAAW,YAAY,QAAQ;AAAA,EACtC;AAAA,EARiB;AAAA;AAAA,EAYjB,OAAuB;AACrB,QAAI;AACF,aAAO,eAAeC,cAAa,KAAK,eAAe,MAAM,CAAC;AAAA,IAChE,QAAQ;AACN,aAAO,WAAW;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,MAAM,OAA6B;AACjC,aAAS,KAAK,UAAU,MAAM;AAC5B,sBAAgB,KAAK,eAAe,mBAAmB,KAAK,CAAC;AAAA,IAC/D,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,YAAqC;AACzC,QAAI;AACF,aAAO,eAAe,MAAM,SAAS,KAAK,eAAe,MAAM,CAAC;AAAA,IAClE,QAAQ;AACN,aAAO,WAAW;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,OAAsC;AACrD,UAAM,cAAc,KAAK,UAAU,YAAY;AAC7C,sBAAgB,KAAK,eAAe,mBAAmB,KAAK,CAAC;AAAA,IAC/D,CAAC;AAAA,EACH;AAAA;AAAA,EAIA,cAAc,OAA6B;AACzC,aAAS,KAAK,UAAU,MAAM;AAC5B,YAAM,QAAQ,KAAK,aAAa;AAChC,YAAM,MAAM,MAAM,OAAO,UAAU,CAAC,MAAM,EAAE,OAAO,MAAM,EAAE;AAC3D,UAAI,OAAO,GAAG;AACZ,cAAM,OAAO,GAAG,IAAI;AAAA,MACtB,OAAO;AACL,cAAM,OAAO,KAAK,KAAK;AAAA,MACzB;AACA,WAAK,cAAc,KAAK;AAAA,IAC1B,CAAC;AAAA,EACH;AAAA,EAEA,gBAAgB,IAAkB;AAChC,aAAS,KAAK,UAAU,MAAM;AAC5B,YAAM,QAAQ,KAAK,aAAa;AAChC,YAAM,SAAS,MAAM,OAAO,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE;AACrD,WAAK,cAAc,KAAK;AAAA,IAC1B,CAAC;AAAA,EACH;AAAA,EAEA,YAAY,IAAY,SAAwC;AAC9D,aAAS,KAAK,UAAU,MAAM;AAC5B,YAAM,QAAQ,KAAK,aAAa;AAChC,YAAM,MAAM,MAAM,OAAO,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE;AACrD,UAAI,MAAM,EAAG;AACb,YAAM,OAAO,GAAG,IAAI,EAAE,GAAG,MAAM,OAAO,GAAG,GAAI,GAAG,QAAQ;AACxD,WAAK,cAAc,KAAK;AAAA,IAC1B,CAAC;AAAA,EACH;AAAA;AAAA;AAAA,EAKA,UAAU,QAAgB,SAA0B;AAClD,QAAI,UAAU;AACd,aAAS,KAAK,UAAU,MAAM;AAC5B,YAAM,QAAQ,KAAK,aAAa;AAChC,YAAM,OAAO,MAAM,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM;AACpD,UAAI,CAAC,KAAM;AACX,UAAI,KAAK,WAAW,eAAe,KAAK,WAAW,UAAW;AAC9D,WAAK,SAAS;AACd,WAAK,QAAQ;AACb,WAAK,WAAU,oBAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AACnD,WAAK,cAAc,KAAK;AACxB,gBAAU;AAAA,IACZ,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,aAAa,QAAgB,SAA0B;AACrD,QAAI,UAAU;AACd,aAAS,KAAK,UAAU,MAAM;AAC5B,YAAM,QAAQ,KAAK,aAAa;AAChC,YAAM,MAAM,MAAM,MAAM,UAAU,CAAC,MAAM,EAAE,OAAO,MAAM;AACxD,UAAI,QAAQ,GAAI;AAChB,YAAM,OAAO,MAAM,MAAM,OAAO,KAAK,CAAC,EAAE,CAAC;AACzC,YAAM,KAAK,QAAQ;AAAA,QACjB,IAAI,KAAK;AAAA,QACT,MAAM,KAAK;AAAA,QACX,OAAO,WAAW,KAAK;AAAA,QACvB,YAAW,oBAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AAAA,QAC/C,IAAI,KAAK,MAAM;AAAA,QACf,OAAO,KAAK,SAAS;AAAA,MACvB,CAAC;AACD,WAAK,cAAc,KAAK;AACxB,gBAAU;AAAA,IACZ,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,YAAY,QAAgB,OAAwB;AAClD,QAAI,UAAU;AACd,aAAS,KAAK,UAAU,MAAM;AAC5B,YAAM,QAAQ,KAAK,aAAa;AAChC,YAAM,OAAO,MAAM,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM;AACpD,UAAI,CAAC,KAAM;AACX,WAAK,SAAS;AACd,WAAK,WAAU,oBAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AACnD,UAAI,MAAO,MAAK,QAAQ;AACxB,WAAK,cAAc,KAAK;AACxB,gBAAU;AAAA,IACZ,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,YAAY,QAAyB;AACnC,QAAI,UAAU;AACd,aAAS,KAAK,UAAU,MAAM;AAC5B,YAAM,QAAQ,KAAK,aAAa;AAChC,YAAM,OAAO,MAAM,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM;AACpD,UAAI,CAAC,KAAM;AACX,WAAK,SAAS;AACd,WAAK,QAAQ;AACb,WAAK,WAAU,oBAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AACnD,WAAK,cAAc,KAAK;AACxB,gBAAU;AAAA,IACZ,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,YAAY,QAAgB,MAAc,MAAe;AACvD,QAAI,UAAU;AACd,aAAS,KAAK,UAAU,MAAM;AAC5B,YAAM,QAAQ,KAAK,aAAa;AAChC,YAAM,MAAM,MAAM,QAAQ,UAAU,CAAC,MAAM,EAAE,OAAO,MAAM;AAC1D,UAAI,QAAQ,GAAI;AAChB,YAAM,UAAU,MAAM,QAAQ,OAAO,KAAK,CAAC,EAAE,CAAC;AAC9C,YAAM,MAAM,KAAK;AAAA,QACf,IAAI,QAAQ;AAAA,QACZ,MAAM,QAAQ;AAAA,QACd;AAAA,QACA,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,IAAI,QAAQ,MAAM;AAAA,QAClB,UAAS,oBAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AAAA,QAC7C,OAAO,QAAQ,SAAS;AAAA,MAC1B,CAAC;AACD,WAAK,cAAc,KAAK;AACxB,gBAAU;AAAA,IACZ,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA,EAIA,WAAW,IAAY,OAAuB;AAC5C,aAAS,KAAK,UAAU,MAAM;AAC5B,YAAM,QAAQ,KAAK,aAAa;AAChC,YAAM,QAAQ,MAAM,OAAO,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAClD,UAAI,CAAC,MAAO;AACZ,YAAM,QAAQ,MAAM,KAAK,IAAI;AAC7B,YAAM,UAAU,IAAG,oBAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AACxD,WAAK,cAAc,KAAK;AAAA,IAC1B,CAAC;AAAA,EACH;AAAA,EAEA,aAAa,IAAkB;AAC7B,aAAS,KAAK,UAAU,MAAM;AAC5B,YAAM,QAAQ,KAAK,aAAa;AAChC,YAAM,QAAQ,MAAM,OAAO,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAClD,UAAI,CAAC,MAAO;AACZ,YAAM,QAAQ;AACd,YAAM,UAAU,IAAG,oBAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AACxD,WAAK,cAAc,KAAK;AAAA,IAC1B,CAAC;AAAA,EACH;AAAA;AAAA,EAIA,YAAY,SAAiB,aAA2B;AACtD,aAAS,KAAK,UAAU,MAAM;AAC5B,YAAM,QAAQ,KAAK,aAAa;AAChC,YAAM,MAAM,oBAAI,KAAK;AACrB,YAAM,UAAU,IAAI,YAAY,EAAE,MAAM,GAAG,EAAE;AAC7C,YAAM,UAAU,IAAI,YAAY,EAAE,MAAM,IAAI,EAAE;AAC9C,YAAM,IAAI,QAAQ,MAAM,OAAO,IAAI,OAAO,KAAK,OAAO,KAAK,WAAW,EAAE;AACxE,UAAI,MAAM,IAAI,SAAS,GAAI,OAAM,IAAI,OAAO,EAAE;AAC9C,WAAK,cAAc,KAAK;AAAA,IAC1B,CAAC;AAAA,EACH;AAAA;AAAA,EAIA,cAAgC;AAC9B,UAAM,QAAQ,KAAK,KAAK;AACxB,UAAM,MAAM,KAAK,IAAI;AACrB,WAAO,MAAM,OAAO,OAAO,CAAC,MAAM;AAChC,UAAI;AACF,cAAM,MAAM,MAAM,IAAI,KAAK,EAAE,OAAO,EAAE,QAAQ;AAC9C,cAAM,YAAY,EAAE,SAAS,eAAe,oBAAoB;AAChE,eAAO,MAAM;AAAA,MACf,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,eAAe,aAAqB,OAAiC;AACnE,UAAM,QAAQ,KAAK,KAAK;AACxB,UAAM,YAAyC,CAAC;AAEhD,eAAW,SAAS,MAAM,QAAQ;AAChC,UAAI,MAAM,OAAO,YAAa;AAC9B,YAAM,aAAa,MAAM,MACtB,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO;AACjB,YAAM,cAAc,MAAM;AAAA,QAAO,CAAC,WAChC,WAAW;AAAA,UACT,CAAC,cACC,WAAW,aACX,OAAO,WAAW,UAAU,QAAQ,MAAM,EAAE,CAAC,KAC7C,UAAU,WAAW,OAAO,QAAQ,MAAM,EAAE,CAAC;AAAA,QACjD;AAAA,MACF;AACA,UAAI,YAAY,SAAS,GAAG;AAC1B,kBAAU,KAAK;AAAA,UACb,aAAa;AAAA,UACb,cAAc,MAAM;AAAA,UACpB,kBAAkB;AAAA,QACpB,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO,EAAE,OAAO,UAAU,WAAW,GAAG,UAAU;AAAA,EACpD;AAAA,EAEA,gBAAgB,SAAkC;AAChD,UAAM,QAAQ,KAAK,KAAK;AACxB,WAAO,MAAM,MAAM;AAAA,MACjB,CAAC,MAAM,EAAE,WAAW,aAAa,EAAE,UAAU;AAAA,IAC/C;AAAA,EACF;AAAA;AAAA,EAIQ,eAA+B;AACrC,QAAI;AACF,aAAO,eAAeA,cAAa,KAAK,eAAe,MAAM,CAAC;AAAA,IAChE,QAAQ;AACN,aAAO,WAAW;AAAA,IACpB;AAAA,EACF;AAAA,EAEQ,cAAc,OAA6B;AACjD,oBAAgB,KAAK,eAAe,mBAAmB,KAAK,CAAC;AAAA,EAC/D;AACF;AAEA,SAAS,aAA6B;AACpC,SAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,GAAG,OAAO,CAAC,GAAG,SAAS,CAAC,GAAG,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,QAAQ,CAAC,EAAE;AAC3F;AAIO,IAAM,kBAAkB,iBAAiB,UAAU;AAEnD,IAAM,oBAAoB,iBAAiB,UAAU;","names":["readFileSync","readFileSync","readFileSync"]}
|