codemem 0.25.2 → 0.25.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.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/help-style.ts","../src/shared-options.ts","../src/commands/claude-hook-plugin-log.ts","../src/commands/claude-hook-ingest-spool.ts","../src/commands/claude-hook-session-state.ts","../src/commands/claude-hook-ingest.ts","../src/commands/claude-hook-inject.ts","../src/commands/config.ts","../src/commands/coordinator.ts","../src/commands/db.ts","../src/commands/embed.ts","../src/commands/enqueue-raw-event.ts","../src/commands/export-memories.ts","../src/commands/import-memories.ts","../src/commands/mcp.ts","../src/commands/pack-shared.ts","../src/commands/memory.ts","../src/commands/pack.ts","../src/commands/recent.ts","../src/commands/search.ts","../src/commands/serve-invocation.ts","../src/commands/serve.ts","../src/commands/setup-config.ts","../src/commands/setup.ts","../src/commands/stats.ts","../src/commands/sync-helpers.ts","../src/commands/sync.ts","../src/commands/version.ts","../src/index.ts"],"sourcesContent":["/**\n * Shared Commander help style configuration.\n *\n * Applied to every Command instance so subcommand --help\n * output gets the same colors as the root.\n */\n\nimport { styleText } from \"node:util\";\nimport type { HelpConfiguration } from \"commander\";\n\nexport const helpStyle: HelpConfiguration = {\n\tstyleTitle: (str) => styleText(\"bold\", str),\n\tstyleCommandText: (str) => styleText(\"cyan\", str),\n\tstyleCommandDescription: (str) => str,\n\tstyleDescriptionText: (str) => styleText(\"dim\", str),\n\tstyleOptionText: (str) => styleText(\"green\", str),\n\tstyleOptionTerm: (str) => styleText(\"green\", str),\n\tstyleSubcommandText: (str) => styleText(\"cyan\", str),\n\tstyleArgumentText: (str) => styleText(\"yellow\", str),\n};\n","/**\n * Shared CLI option builders.\n *\n * Defines standard flags once with consistent short forms, descriptions,\n * and hidden legacy aliases. Every command module should use these instead\n * of ad-hoc .option() calls.\n *\n * See docs/cli-design-conventions.md for the full spec.\n */\n\nimport type { Command } from \"commander\";\nimport { Option } from \"commander\";\n\n// ---------------------------------------------------------------------------\n// --db-path / -d (with hidden --db alias)\n// ---------------------------------------------------------------------------\n\n/** Add -d/--db-path and hidden --db alias to a command. */\nexport function addDbOption(cmd: Command): Command {\n\tcmd.addOption(new Option(\"-d, --db-path <path>\", \"database path (overrides $CODEMEM_DB)\"));\n\t// Hidden legacy alias\n\tcmd.addOption(new Option(\"--db <path>\", \"database path\").hideHelp());\n\treturn cmd;\n}\n\n/** Resolve the db path from parsed opts that may have --db or --db-path. */\nexport function resolveDbOpt(opts: { db?: string; dbPath?: string }): string | undefined {\n\treturn opts.dbPath ?? opts.db;\n}\n\n// ---------------------------------------------------------------------------\n// --config / -c\n// ---------------------------------------------------------------------------\n\n/** Add -c/--config to a command. */\nexport function addConfigOption(cmd: Command): Command {\n\tcmd.addOption(new Option(\"-c, --config <path>\", \"config file path (overrides $CODEMEM_CONFIG)\"));\n\treturn cmd;\n}\n\n// ---------------------------------------------------------------------------\n// --json / -j\n// ---------------------------------------------------------------------------\n\n/** Add -j/--json to a command. */\nexport function addJsonOption(cmd: Command): Command {\n\tcmd.addOption(new Option(\"-j, --json\", \"output as JSON\"));\n\treturn cmd;\n}\n\n// ---------------------------------------------------------------------------\n// Host / port (viewer — the default service)\n// ---------------------------------------------------------------------------\n\n/** Add --host and --port for the viewer/serve service. */\nexport function addViewerHostOptions(\n\tcmd: Command,\n\tdefaults: { host?: string; port?: string } = {},\n): Command {\n\tcmd.option(\"--host <host>\", \"viewer host\", defaults.host ?? \"127.0.0.1\");\n\tcmd.option(\"--port <port>\", \"viewer port\", defaults.port ?? \"38888\");\n\treturn cmd;\n}\n\n// ---------------------------------------------------------------------------\n// Hidden legacy aliases (accept silently, ignore)\n// ---------------------------------------------------------------------------\n\n/** Add hidden --user/--system Typer-era compatibility flags. */\nexport function addLegacyServiceFlags(cmd: Command): Command {\n\tcmd.addOption(new Option(\"--user\", \"accepted for compatibility\").default(true).hideHelp());\n\tcmd.addOption(new Option(\"--system\", \"accepted for compatibility\").hideHelp());\n\treturn cmd;\n}\n\n// ---------------------------------------------------------------------------\n// Deprecation warning helper\n// ---------------------------------------------------------------------------\n\n/** Emit a deprecation warning to stderr. */\nexport function emitDeprecationWarning(oldForm: string, newForm: string): void {\n\tconsole.error(`Warning: '${oldForm}' is deprecated, use '${newForm}' instead.`);\n}\n\n// ---------------------------------------------------------------------------\n// Structured JSON error helper\n// ---------------------------------------------------------------------------\n\n/** Print a structured JSON error to stdout and set the exit code. */\nexport function emitJsonError(errorCode: string, message: string, exitCode = 1): void {\n\tconsole.log(JSON.stringify({ error: errorCode, message }));\n\tprocess.exitCode = exitCode;\n}\n\n// ---------------------------------------------------------------------------\n// Common option type for action handlers\n// ---------------------------------------------------------------------------\n\nexport interface DbOpts {\n\tdb?: string;\n\tdbPath?: string;\n}\n\nexport interface ConfigOpts {\n\tconfig?: string;\n}\n\nexport interface JsonOpts {\n\tjson?: boolean;\n}\n\nexport interface ViewerHostOpts {\n\thost: string;\n\tport: string;\n}\n","/**\n * Append-only plugin failure log used by both `claude-hook-inject` and\n * `claude-hook-ingest` to record errors that don't justify crashing the\n * hook command itself.\n *\n * Behavior:\n * - Default log path is `~/.codemem/plugin.log`.\n * - `CODEMEM_PLUGIN_LOG_PATH` (preferred) or `CODEMEM_PLUGIN_LOG` may\n * override the path. Boolean-shaped values (`0/1/true/false/yes/no/on/off`\n * and empty) are treated as toggles, not paths, so the default is used.\n * - All I/O is best-effort: failures are swallowed.\n */\n\nimport { appendFileSync, mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nconst BOOLEAN_TOGGLE_VALUES = new Set([\"\", \"0\", \"false\", \"off\", \"1\", \"true\", \"yes\", \"on\", \"no\"]);\n\nfunction expandHome(value: string): string {\n\tif (value === \"~\") return homedir();\n\tif (value.startsWith(\"~/\")) return join(homedir(), value.slice(2));\n\treturn value;\n}\n\nexport function pluginLogPath(): string {\n\tconst raw = process.env.CODEMEM_PLUGIN_LOG_PATH ?? process.env.CODEMEM_PLUGIN_LOG ?? \"\";\n\tconst normalized = raw.trim().toLowerCase();\n\tif (BOOLEAN_TOGGLE_VALUES.has(normalized)) {\n\t\treturn expandHome(\"~/.codemem/plugin.log\");\n\t}\n\treturn expandHome(raw.trim());\n}\n\n/**\n * Append a single timestamped line to the plugin log. Best-effort: any\n * filesystem error is swallowed so a logging failure can never bubble up\n * into a Claude hook crash.\n */\nexport function logHookFailure(message: string): void {\n\tconst path = pluginLogPath();\n\ttry {\n\t\tmkdirSync(dirname(path), { recursive: true });\n\t\tappendFileSync(path, `${new Date().toISOString()} ${message}\\n`, { encoding: \"utf8\" });\n\t} catch {\n\t\t// best-effort\n\t}\n}\n","/**\n * Durability layer for `claude-hook-ingest`: file-based mutex to\n * serialize concurrent invocations, on-disk spool that captures\n * payloads when both HTTP and direct ingestion paths fail, and a\n * recovery routine that promotes stale temp files back into the queue.\n */\n\nimport { randomInt } from \"node:crypto\";\nimport {\n\tmkdirSync,\n\treaddirSync,\n\treadFileSync,\n\trenameSync,\n\trmdirSync,\n\tstatSync,\n\tunlinkSync,\n\twriteFileSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { logHookFailure } from \"./claude-hook-plugin-log.js\";\n\nconst DEFAULT_LOCK_TTL_S = 300;\nconst DEFAULT_LOCK_GRACE_S = 2;\nconst LOCK_ACQUIRE_ATTEMPTS = 100;\nconst LOCK_ACQUIRE_BACKOFF_MS = 50;\n\ntype LockSnapshot = {\n\tpid: string;\n\tts: number | null;\n\towner: string;\n};\n\ntype LockConfig = {\n\tlockDir: string;\n\tttlSeconds: number;\n\tgraceSeconds: number;\n};\n\nexport class LockBusyError extends Error {\n\tconstructor() {\n\t\tsuper(\"claude-hook-ingest lock busy\");\n\t\tthis.name = \"LockBusyError\";\n\t}\n}\n\nfunction expandHome(value: string): string {\n\tif (value === \"~\") return homedir();\n\tif (value.startsWith(\"~/\")) return join(homedir(), value.slice(2));\n\treturn value;\n}\n\nfunction envInt(name: string, fallback: number): number {\n\tconst raw = process.env[name];\n\tif (raw === undefined) return fallback;\n\tconst parsed = Number.parseInt(raw, 10);\n\treturn Number.isFinite(parsed) ? parsed : fallback;\n}\n\nfunction envTruthy(name: string, fallback: boolean): boolean {\n\tconst raw = process.env[name];\n\tif (raw === undefined) return fallback;\n\tconst normalized = raw.trim().toLowerCase();\n\tif ([\"1\", \"true\", \"yes\", \"on\"].includes(normalized)) return true;\n\tif ([\"0\", \"false\", \"no\", \"off\"].includes(normalized)) return false;\n\treturn fallback;\n}\n\nfunction lockConfig(): LockConfig {\n\tconst lockDir = expandHome(\n\t\tprocess.env.CODEMEM_CLAUDE_HOOK_LOCK_DIR?.trim() || \"~/.codemem/claude-hook-ingest.lock\",\n\t);\n\treturn {\n\t\tlockDir,\n\t\tttlSeconds: Math.max(1, envInt(\"CODEMEM_CLAUDE_HOOK_LOCK_TTL_S\", DEFAULT_LOCK_TTL_S)),\n\t\tgraceSeconds: Math.max(1, envInt(\"CODEMEM_CLAUDE_HOOK_LOCK_GRACE_S\", DEFAULT_LOCK_GRACE_S)),\n\t};\n}\n\nexport function spoolDir(): string {\n\treturn expandHome(\n\t\tprocess.env.CODEMEM_CLAUDE_HOOK_SPOOL_DIR?.trim() || \"~/.codemem/claude-hook-spool\",\n\t);\n}\n\n/**\n * Cheap pre-check used by the unlocked HTTP-success path to decide\n * whether it needs to acquire the ingest lock and drain queued\n * payloads. Returns true when the spool directory contains at least\n * one active entry (a `*.json` file that is neither an in-flight\n * `.hook-tmp-*` nor a quarantined `.bad-*` file). Any I/O failure\n * is treated as \"no entries\" so callers stay on the fast path.\n */\nexport function hasSpooledEntries(): boolean {\n\tconst dir = spoolDir();\n\tlet entries: string[];\n\ttry {\n\t\tentries = readdirSync(dir);\n\t} catch {\n\t\treturn false;\n\t}\n\tfor (const name of entries) {\n\t\tif (!name.endsWith(\".json\")) continue;\n\t\tif (name.startsWith(\".hook-tmp-\") || name.startsWith(\".bad-\")) continue;\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nfunction readFileTrimmedOrEmpty(path: string): string {\n\ttry {\n\t\treturn readFileSync(path, \"utf8\").trim();\n\t} catch {\n\t\treturn \"\";\n\t}\n}\n\nfunction readLockMetadata(lockDir: string): LockSnapshot {\n\tconst pid = readFileTrimmedOrEmpty(join(lockDir, \"pid\"));\n\tconst owner = readFileTrimmedOrEmpty(join(lockDir, \"owner\"));\n\tconst tsRaw = readFileTrimmedOrEmpty(join(lockDir, \"ts\"));\n\tconst ts = tsRaw === \"\" ? null : Number.parseInt(tsRaw, 10);\n\treturn {\n\t\tpid,\n\t\tts: ts === null || !Number.isFinite(ts) ? null : ts,\n\t\towner,\n\t};\n}\n\nfunction isPidAlive(pidText: string): boolean {\n\tconst pid = Number.parseInt(pidText, 10);\n\tif (!Number.isFinite(pid) || pid <= 0) return false;\n\ttry {\n\t\t// Signal 0 performs the existence check without delivering a signal.\n\t\tprocess.kill(pid, 0);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction lockIsStale(cfg: LockConfig): { stale: boolean; snapshot: LockSnapshot } {\n\tconst snapshot = readLockMetadata(cfg.lockDir);\n\tconst nowS = Math.floor(Date.now() / 1000);\n\n\tif (snapshot.pid) {\n\t\tif (isPidAlive(snapshot.pid)) {\n\t\t\tif (snapshot.ts === null) return { stale: false, snapshot };\n\t\t\treturn { stale: nowS - snapshot.ts > cfg.ttlSeconds, snapshot };\n\t\t}\n\t\treturn { stale: true, snapshot };\n\t}\n\n\tif (snapshot.ts !== null) {\n\t\treturn { stale: nowS - snapshot.ts > cfg.graceSeconds, snapshot };\n\t}\n\n\tlet mtimeS: number;\n\ttry {\n\t\tmtimeS = Math.floor(statSync(cfg.lockDir).mtimeMs / 1000);\n\t} catch {\n\t\treturn { stale: true, snapshot };\n\t}\n\treturn { stale: nowS - mtimeS > cfg.graceSeconds, snapshot };\n}\n\nfunction cleanupLockDir(lockDir: string): void {\n\tfor (const name of [\"pid\", \"ts\", \"owner\"]) {\n\t\ttry {\n\t\t\tunlinkSync(join(lockDir, name));\n\t\t} catch {\n\t\t\t// best-effort\n\t\t}\n\t}\n\ttry {\n\t\trmdirSync(lockDir);\n\t} catch {\n\t\t// best-effort\n\t}\n}\n\nfunction snapshotsEqual(a: LockSnapshot, b: LockSnapshot): boolean {\n\treturn a.pid === b.pid && a.ts === b.ts && a.owner === b.owner;\n}\n\nfunction cleanupLockDirIfUnchanged(lockDir: string, snapshot: LockSnapshot): void {\n\tconst current = readLockMetadata(lockDir);\n\tif (snapshotsEqual(current, snapshot)) {\n\t\tcleanupLockDir(lockDir);\n\t}\n}\n\nfunction isErrnoException(err: unknown): err is NodeJS.ErrnoException {\n\treturn typeof err === \"object\" && err !== null && \"code\" in err;\n}\n\nasync function sleep(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Run `fn` while holding the claude-hook-ingest lock. Throws\n * `LockBusyError` when the lock cannot be acquired within\n * `LOCK_ACQUIRE_ATTEMPTS` attempts.\n *\n * The lock is a directory at `lockDir`, with three sentinel files\n * (`pid`, `ts`, `owner`) recording who currently holds it. Stale locks\n * are detected via PID liveness, TTL, and a grace window for the\n * race between mkdir and writing pid/ts.\n */\nexport async function withClaudeHookIngestLock<T>(fn: () => Promise<T> | T): Promise<T> {\n\tconst cfg = lockConfig();\n\tmkdirSync(dirname(cfg.lockDir), { recursive: true });\n\tconst ownerToken = `${process.pid}-${Math.floor(Date.now() / 1000)}-${randomInt(1000, 10000)}`;\n\n\tlet acquired = false;\n\tfor (let attempt = 0; attempt < LOCK_ACQUIRE_ATTEMPTS; attempt++) {\n\t\ttry {\n\t\t\tmkdirSync(cfg.lockDir);\n\t\t} catch (err) {\n\t\t\tif (isErrnoException(err) && err.code === \"EEXIST\") {\n\t\t\t\tconst { stale, snapshot } = lockIsStale(cfg);\n\t\t\t\tif (stale) {\n\t\t\t\t\tcleanupLockDirIfUnchanged(cfg.lockDir, snapshot);\n\t\t\t\t}\n\t\t\t\tawait sleep(LOCK_ACQUIRE_BACKOFF_MS);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tawait sleep(LOCK_ACQUIRE_BACKOFF_MS);\n\t\t\tcontinue;\n\t\t}\n\n\t\ttry {\n\t\t\twriteFileSync(join(cfg.lockDir, \"ts\"), String(Math.floor(Date.now() / 1000)), {\n\t\t\t\tencoding: \"utf8\",\n\t\t\t});\n\t\t\twriteFileSync(join(cfg.lockDir, \"pid\"), String(process.pid), { encoding: \"utf8\" });\n\t\t\twriteFileSync(join(cfg.lockDir, \"owner\"), ownerToken, { encoding: \"utf8\" });\n\t\t\tacquired = true;\n\t\t\tbreak;\n\t\t} catch {\n\t\t\tcleanupLockDir(cfg.lockDir);\n\t\t\tawait sleep(LOCK_ACQUIRE_BACKOFF_MS);\n\t\t}\n\t}\n\n\tif (!acquired) {\n\t\tthrow new LockBusyError();\n\t}\n\n\ttry {\n\t\treturn await fn();\n\t} finally {\n\t\tconst currentOwner = readFileTrimmedOrEmpty(join(cfg.lockDir, \"owner\"));\n\t\tif (currentOwner === ownerToken) {\n\t\t\tcleanupLockDir(cfg.lockDir);\n\t\t}\n\t}\n}\n\n/**\n * Persist a payload to the spool directory using a tmp+rename so that\n * a partially-written file is never visible to the drainer. Returns\n * true on success, false on any I/O failure.\n */\nexport function spoolPayload(payload: Record<string, unknown>): boolean {\n\tconst dir = spoolDir();\n\ttry {\n\t\tmkdirSync(dir, { recursive: true });\n\t} catch {\n\t\tlogHookFailure(\"codemem claude-hook-ingest failed to create spool dir\");\n\t\treturn false;\n\t}\n\n\tconst payloadText = JSON.stringify(payload);\n\tconst tmpName = `.hook-tmp-${process.pid}-${Date.now()}-${randomInt(1000, 10000)}.json`;\n\tconst tmpPath = join(dir, tmpName);\n\ttry {\n\t\twriteFileSync(tmpPath, payloadText, { encoding: \"utf8\" });\n\t} catch {\n\t\tlogHookFailure(\"codemem claude-hook-ingest failed to allocate spool temp file\");\n\t\treturn false;\n\t}\n\n\tconst finalName = `hook-${Math.floor(Date.now() / 1000)}-${process.pid}-${randomInt(1000, 10000)}.json`;\n\tconst finalPath = join(dir, finalName);\n\ttry {\n\t\trenameSync(tmpPath, finalPath);\n\t} catch {\n\t\ttry {\n\t\t\tunlinkSync(tmpPath);\n\t\t} catch {\n\t\t\t// best-effort\n\t\t}\n\t\tlogHookFailure(\"codemem claude-hook-ingest failed to spool payload\");\n\t\treturn false;\n\t}\n\tlogHookFailure(`codemem claude-hook-ingest spooled payload: ${finalPath}`);\n\treturn true;\n}\n\n/**\n * Promote any `.hook-tmp-*.json` files older than `ttlSeconds` to a\n * recovered name so they are picked up by the next drain. Caller is\n * responsible for passing the same TTL used by lock acquisition so\n * that an in-flight write inside an active locked region is never\n * mistaken for a crashed-writer leftover.\n */\nexport function recoverStaleTmpSpool(ttlSeconds: number): void {\n\tconst dir = spoolDir();\n\ttry {\n\t\tmkdirSync(dir, { recursive: true });\n\t} catch {\n\t\treturn;\n\t}\n\n\tlet entries: string[];\n\ttry {\n\t\tentries = readdirSync(dir);\n\t} catch {\n\t\treturn;\n\t}\n\n\tconst nowS = Date.now() / 1000;\n\tfor (const name of entries) {\n\t\tif (!name.startsWith(\".hook-tmp-\") || !name.endsWith(\".json\")) continue;\n\t\tconst tmpPath = join(dir, name);\n\t\tlet mtimeS: number;\n\t\ttry {\n\t\t\tmtimeS = statSync(tmpPath).mtimeMs / 1000;\n\t\t} catch {\n\t\t\tcontinue;\n\t\t}\n\t\tif (nowS - mtimeS <= ttlSeconds) continue;\n\n\t\tconst recoveredName = `hook-recovered-${Math.floor(nowS)}-${process.pid}-${randomInt(1000, 10000)}.json`;\n\t\tconst recoveredPath = join(dir, recoveredName);\n\t\ttry {\n\t\t\trenameSync(tmpPath, recoveredPath);\n\t\t\tlogHookFailure(\n\t\t\t\t`codemem claude-hook-ingest recovered stale temp spool payload: ${recoveredPath}`,\n\t\t\t);\n\t\t} catch {\n\t\t\t// best-effort\n\t\t}\n\t}\n}\n\n/**\n * Move a permanently-broken spool entry out of the queue so that it\n * stops being picked up by future drains. The entry is renamed in\n * place with a `.bad-<reason>-` prefix so an operator can inspect or\n * delete it manually.\n */\nfunction quarantineSpoolEntry(dir: string, name: string, reason: string): void {\n\tconst sourcePath = join(dir, name);\n\tconst quarantineName = `.bad-${reason}-${Date.now()}-${randomInt(1000, 10000)}-${name}`;\n\ttry {\n\t\trenameSync(sourcePath, join(dir, quarantineName));\n\t\tlogHookFailure(\n\t\t\t`codemem claude-hook-ingest quarantined corrupt spool payload (${reason}): ${quarantineName}`,\n\t\t);\n\t} catch {\n\t\t// If rename fails, fall back to delete; either way the broken\n\t\t// entry must not stay in the active queue.\n\t\ttry {\n\t\t\tunlinkSync(sourcePath);\n\t\t\tlogHookFailure(\n\t\t\t\t`codemem claude-hook-ingest dropped corrupt spool payload (${reason}): ${name}`,\n\t\t\t);\n\t\t} catch {\n\t\t\t// best-effort\n\t\t}\n\t}\n}\n\nexport type SpoolHandler = (payload: Record<string, unknown>) => Promise<boolean> | boolean;\n\nexport type SpoolDrainResult = {\n\tprocessed: number;\n\tfailed: number;\n};\n\n/**\n * Process every queued payload in the spool directory in lexicographic\n * order (which approximates oldest-first because filenames embed the\n * second-precision creation timestamp). The handler returns true to\n * indicate the payload has been durably accepted; only then is the\n * spool entry deleted. Failed entries are left on disk for the next\n * drain attempt.\n */\nexport async function drainSpool(handler: SpoolHandler): Promise<SpoolDrainResult> {\n\tconst dir = spoolDir();\n\ttry {\n\t\tmkdirSync(dir, { recursive: true });\n\t} catch {\n\t\treturn { processed: 0, failed: 0 };\n\t}\n\n\tlet entries: string[];\n\ttry {\n\t\tentries = readdirSync(dir);\n\t} catch {\n\t\treturn { processed: 0, failed: 0 };\n\t}\n\n\tconst queued = entries\n\t\t.filter(\n\t\t\t(name) =>\n\t\t\t\tname.endsWith(\".json\") && !name.startsWith(\".hook-tmp-\") && !name.startsWith(\".bad-\"),\n\t\t)\n\t\t.sort();\n\n\tconst result: SpoolDrainResult = { processed: 0, failed: 0 };\n\tfor (const name of queued) {\n\t\tconst path = join(dir, name);\n\t\tlet raw: string;\n\t\ttry {\n\t\t\traw = readFileSync(path, \"utf8\");\n\t\t} catch {\n\t\t\t// Genuine I/O failure — leave the file alone so the next drain\n\t\t\t// can retry, and surface the failure to the plugin log.\n\t\t\tlogHookFailure(`codemem claude-hook-ingest failed to read spooled payload: ${path}`);\n\t\t\tresult.failed++;\n\t\t\tcontinue;\n\t\t}\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(raw);\n\t\t} catch {\n\t\t\t// Permanently corrupt content — keeping the file around would\n\t\t\t// loop forever every drain. Quarantine it under a `.bad-` prefix\n\t\t\t// so an operator can inspect it without it being picked up again.\n\t\t\tquarantineSpoolEntry(dir, name, \"parse-error\");\n\t\t\tresult.failed++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (parsed == null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\t\t// Parseable but wrong shape — same problem, same fix.\n\t\t\tquarantineSpoolEntry(dir, name, \"wrong-shape\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tlet ok = false;\n\t\ttry {\n\t\t\tok = await handler(parsed as Record<string, unknown>);\n\t\t} catch {\n\t\t\tok = false;\n\t\t}\n\n\t\tif (ok) {\n\t\t\ttry {\n\t\t\t\tunlinkSync(path);\n\t\t\t\tresult.processed++;\n\t\t\t} catch {\n\t\t\t\t// best-effort\n\t\t\t}\n\t\t} else {\n\t\t\tlogHookFailure(`codemem claude-hook-ingest failed processing spooled payload: ${path}`);\n\t\t\tresult.failed++;\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Whether the boundary-flush write-through should run for this hook\n * payload. SessionEnd defaults to forcing a flush; Stop only flushes\n * when both CODEMEM_CLAUDE_HOOK_FLUSH and CODEMEM_CLAUDE_HOOK_FLUSH_ON_STOP\n * are truthy.\n */\nexport function shouldForceBoundaryFlush(payload: Record<string, unknown>): boolean {\n\tconst eventName =\n\t\ttypeof payload.hook_event_name === \"string\" ? payload.hook_event_name.trim() : \"\";\n\tif (eventName !== \"Stop\" && eventName !== \"SessionEnd\") return false;\n\tif (eventName === \"SessionEnd\") {\n\t\treturn envTruthy(\"CODEMEM_CLAUDE_HOOK_FLUSH\", true);\n\t}\n\tif (!envTruthy(\"CODEMEM_CLAUDE_HOOK_FLUSH\", false)) return false;\n\treturn envTruthy(\"CODEMEM_CLAUDE_HOOK_FLUSH_ON_STOP\", false);\n}\n\n/**\n * Returns the configured lock TTL so callers (`claude-hook-ingest`)\n * can pass the same value to `recoverStaleTmpSpool` without re-reading\n * the env.\n */\nexport function lockTtlSeconds(): number {\n\treturn lockConfig().ttlSeconds;\n}\n","/**\n * Session-state tracking for Claude Code hook commands.\n *\n * Persists per-session signal (first prompt, latest prompt, recently\n * modified files) to disk so that retrieval inside `claude-hook-inject`\n * can build a query richer than the bare current prompt and so that\n * file-locality boosts can target files the user just edited.\n */\n\nimport { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport type SessionState = {\n\tfirst_prompt: string;\n\tlast_prompt: string;\n\tfiles_modified: string[];\n\tupdated_at: string;\n};\n\nconst MAX_FILES_MODIFIED = 64;\nconst MAX_WORKING_SET_PATHS = 8;\nconst MAX_QUERY_CHARS = 500;\nconst MAX_QUERY_FILE_BASENAMES = 5;\n\nconst MUTATING_TOOL_NAMES = new Set([\"edit\", \"write\", \"multiedit\", \"notebookedit\", \"apply_patch\"]);\n\nconst APPLY_PATCH_PATH_PREFIXES = [\"*** Add File: \", \"*** Update File: \", \"*** Delete File: \"];\n\nexport function defaultSessionState(): SessionState {\n\treturn {\n\t\tfirst_prompt: \"\",\n\t\tlast_prompt: \"\",\n\t\tfiles_modified: [],\n\t\tupdated_at: \"\",\n\t};\n}\n\nfunction expandHome(value: string): string {\n\tif (value === \"~\") return homedir();\n\tif (value.startsWith(\"~/\")) return join(homedir(), value.slice(2));\n\treturn value;\n}\n\nexport function contextDir(): string {\n\tconst override = process.env.CODEMEM_CLAUDE_HOOK_CONTEXT_DIR;\n\treturn expandHome(override?.trim() ? override : \"~/.codemem/claude-hook-context\");\n}\n\nexport function statePathForSession(sessionId: string): string {\n\tconst digest = createHash(\"sha1\").update(sessionId).digest(\"hex\").slice(0, 16);\n\treturn join(contextDir(), `${digest}.json`);\n}\n\n/**\n * Normalize a prompt-shaped payload field: drop non-strings, trim\n * leading/trailing whitespace, and collapse newlines to spaces so that\n * prompts compared across the inject + ingest paths and across turns\n * within a session use the same canonical form.\n */\nexport function normalizePromptText(value: unknown): string {\n\tif (typeof value !== \"string\") return \"\";\n\treturn value.trim().replace(/\\n/g, \" \");\n}\n\nfunction normalizeStringList(value: unknown, cap: number): string[] {\n\tif (!Array.isArray(value)) return [];\n\tconst out: string[] = [];\n\tfor (const item of value) {\n\t\tif (typeof item !== \"string\") continue;\n\t\tconst trimmed = item.trim();\n\t\tif (trimmed) out.push(trimmed);\n\t}\n\treturn out.slice(0, cap);\n}\n\nexport function loadSessionState(sessionId: string): SessionState {\n\tconst path = statePathForSession(sessionId);\n\tif (!existsSync(path)) return defaultSessionState();\n\ttry {\n\t\tconst raw = readFileSync(path, \"utf8\");\n\t\tconst parsed: unknown = JSON.parse(raw);\n\t\tif (parsed == null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\t\treturn defaultSessionState();\n\t\t}\n\t\tconst obj = parsed as Record<string, unknown>;\n\t\treturn {\n\t\t\tfirst_prompt: typeof obj.first_prompt === \"string\" ? obj.first_prompt.trim() : \"\",\n\t\t\tlast_prompt: typeof obj.last_prompt === \"string\" ? obj.last_prompt.trim() : \"\",\n\t\t\tfiles_modified: normalizeStringList(obj.files_modified, MAX_FILES_MODIFIED),\n\t\t\tupdated_at: typeof obj.updated_at === \"string\" ? obj.updated_at.trim() : \"\",\n\t\t};\n\t} catch {\n\t\treturn defaultSessionState();\n\t}\n}\n\nfunction nowIso(): string {\n\treturn new Date().toISOString();\n}\n\nexport function saveSessionState(sessionId: string, state: SessionState): void {\n\tconst dir = contextDir();\n\tmkdirSync(dir, { recursive: true });\n\tconst path = statePathForSession(sessionId);\n\tconst tmpPath = `${path}.tmp`;\n\tconst payload = {\n\t\tfirst_prompt: String(state.first_prompt ?? \"\"),\n\t\tlast_prompt: String(state.last_prompt ?? \"\"),\n\t\tfiles_modified: normalizeStringList(state.files_modified, MAX_FILES_MODIFIED),\n\t\tupdated_at: String(state.updated_at ?? \"\"),\n\t};\n\twriteFileSync(tmpPath, JSON.stringify(payload), { encoding: \"utf8\" });\n\trenameSync(tmpPath, path);\n}\n\nexport function clearSessionState(sessionId: string): void {\n\tconst path = statePathForSession(sessionId);\n\ttry {\n\t\trmSync(path, { force: true });\n\t} catch {\n\t\t// best-effort: failure to clear an unreachable file is non-fatal\n\t}\n}\n\nfunction extractApplyPatchPaths(patchText: string): string[] {\n\tconst out: string[] = [];\n\tfor (const line of patchText.split(\"\\n\")) {\n\t\tfor (const prefix of APPLY_PATCH_PATH_PREFIXES) {\n\t\t\tif (line.startsWith(prefix)) {\n\t\t\t\tconst path = line.slice(prefix.length).trim();\n\t\t\t\tif (path) out.push(path);\n\t\t\t}\n\t\t}\n\t}\n\treturn out;\n}\n\nexport function extractModifiedPathsFromHook(payload: Record<string, unknown>): string[] {\n\tconst toolName = String(payload.tool_name ?? \"\")\n\t\t.trim()\n\t\t.toLowerCase();\n\tif (!MUTATING_TOOL_NAMES.has(toolName)) return [];\n\n\tconst toolInput = payload.tool_input;\n\tif (toolInput == null || typeof toolInput !== \"object\" || Array.isArray(toolInput)) {\n\t\treturn [];\n\t}\n\tconst obj = toolInput as Record<string, unknown>;\n\n\tconst collected: string[] = [];\n\tfor (const key of [\"filePath\", \"file_path\", \"path\"]) {\n\t\tconst value = obj[key];\n\t\tif (typeof value === \"string\") {\n\t\t\tconst trimmed = value.trim();\n\t\t\tif (trimmed) collected.push(trimmed);\n\t\t}\n\t}\n\tif (toolName === \"apply_patch\") {\n\t\t// `patchText` is the canonical key, but some agents send an empty\n\t\t// `patchText` alongside the real patch in `patch`. Use a falsy\n\t\t// fallback (not `??`) so an empty `patchText` doesn't shadow it.\n\t\tconst primary =\n\t\t\ttypeof obj.patchText === \"string\" && obj.patchText.trim() ? obj.patchText : null;\n\t\tconst patchText = primary ?? (typeof obj.patch === \"string\" ? obj.patch : null);\n\t\tif (patchText?.trim()) {\n\t\t\tcollected.push(...extractApplyPatchPaths(patchText));\n\t\t}\n\t}\n\n\tconst seen = new Set<string>();\n\tconst ordered: string[] = [];\n\tfor (const path of collected) {\n\t\tif (seen.has(path)) continue;\n\t\tseen.add(path);\n\t\tordered.push(path);\n\t}\n\treturn ordered;\n}\n\n/**\n * Update the on-disk session state for a hook payload and return the\n * resulting state. Returns null when the payload has no usable session_id\n * or when SessionEnd just cleared the state. Failures are swallowed —\n * hook commands must never crash on state I/O errors.\n */\nexport function trackHookSessionState(payload: Record<string, unknown>): SessionState | null {\n\tconst sessionRaw = payload.session_id;\n\tif (typeof sessionRaw !== \"string\") return null;\n\tconst sessionId = sessionRaw.trim();\n\tif (!sessionId) return null;\n\n\tconst hookEventName =\n\t\ttypeof payload.hook_event_name === \"string\" ? payload.hook_event_name.trim() : \"\";\n\n\tif (hookEventName === \"SessionEnd\") {\n\t\tclearSessionState(sessionId);\n\t\treturn null;\n\t}\n\n\tconst state = loadSessionState(sessionId);\n\tlet changed = false;\n\n\tif (hookEventName === \"UserPromptSubmit\") {\n\t\tconst prompt = normalizePromptText(payload.prompt);\n\t\tif (prompt) {\n\t\t\tif (!state.first_prompt) {\n\t\t\t\tstate.first_prompt = prompt;\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t\tif (state.last_prompt !== prompt) {\n\t\t\t\tstate.last_prompt = prompt;\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t}\n\t} else if (hookEventName === \"PostToolUse\" || hookEventName === \"PostToolUseFailure\") {\n\t\tconst existing = state.files_modified.filter((path) => path.trim().length > 0);\n\t\tconst seen = new Set(existing);\n\t\tfor (const path of extractModifiedPathsFromHook(payload)) {\n\t\t\tif (seen.has(path)) continue;\n\t\t\texisting.push(path);\n\t\t\tseen.add(path);\n\t\t\tchanged = true;\n\t\t}\n\t\tstate.files_modified = existing.slice(-MAX_FILES_MODIFIED);\n\t}\n\n\tif (changed) {\n\t\tstate.updated_at = nowIso();\n\t\ttry {\n\t\t\tsaveSessionState(sessionId, state);\n\t\t} catch {\n\t\t\t// best-effort: dropping a state update is preferable to crashing the hook\n\t\t}\n\t}\n\treturn state;\n}\n\nfunction pathBasename(value: string): string {\n\tconst normalized = value.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n\tif (!normalized) return \"\";\n\tconst parts = normalized.split(\"/\");\n\treturn parts[parts.length - 1] ?? \"\";\n}\n\n/**\n * Compose a retrieval query that combines the original session intent,\n * the current prompt, the project, and recent modified file basenames.\n * Caps the result at 500 characters.\n */\nexport function buildInjectQuery(args: {\n\tprompt: string;\n\tproject: string | null;\n\tstate: SessionState | null;\n}): string {\n\tconst parts: string[] = [];\n\tconst firstPrompt = args.state ? normalizePromptText(args.state.first_prompt) : \"\";\n\tconst filesModified = args.state\n\t\t? args.state.files_modified.filter((item) => item.trim().length > 0)\n\t\t: [];\n\n\tif (firstPrompt) parts.push(firstPrompt);\n\tif (args.prompt && args.prompt !== firstPrompt && args.prompt.length > 5) {\n\t\tparts.push(args.prompt);\n\t}\n\tif (args.project) parts.push(args.project);\n\tif (filesModified.length > 0) {\n\t\tconst names = filesModified\n\t\t\t.slice(-MAX_QUERY_FILE_BASENAMES)\n\t\t\t.map(pathBasename)\n\t\t\t.filter((name) => name.length > 0);\n\t\tif (names.length > 0) parts.push(names.join(\" \"));\n\t}\n\n\tif (parts.length === 0) return \"recent work\";\n\tconst query = parts.join(\" \");\n\treturn query.length > MAX_QUERY_CHARS ? query.slice(0, MAX_QUERY_CHARS) : query;\n}\n\n/** Return the working set paths (last N modified files) for pack filters. */\nexport function workingSetPathsFromState(state: SessionState | null): string[] {\n\tif (!state) return [];\n\tconst files = state.files_modified.filter((path) => path.trim().length > 0);\n\treturn files.slice(-MAX_WORKING_SET_PATHS);\n}\n","/**\n * codemem claude-hook-ingest — read a single Claude Code hook payload\n * from stdin and enqueue it for processing.\n *\n * HTTP-first strategy: POST to the running viewer's /api/claude-hooks\n * endpoint, then fall back to direct raw-event enqueue via the local\n * store when the viewer is unreachable.\n *\n * Usage (from Claude hooks config):\n * echo '{\"hook_event_name\":\"Stop\",\"session_id\":\"...\",\"last_assistant_message\":\"...\"}' \\\n * | codemem claude-hook-ingest\n */\n\nimport { readFileSync } from \"node:fs\";\nimport {\n\tbuildRawEventEnvelopeFromHook,\n\tconnect,\n\tflushRawEvents,\n\tloadSqliteVec,\n\tMemoryStore,\n\tObserverClient,\n\tresolveDbPath,\n\tstripPrivateObj,\n} from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport { addDbOption, addViewerHostOptions, type DbOpts, resolveDbOpt } from \"../shared-options.js\";\nimport {\n\tdrainSpool,\n\thasSpooledEntries,\n\tLockBusyError,\n\tlockTtlSeconds,\n\trecoverStaleTmpSpool,\n\tshouldForceBoundaryFlush,\n\tspoolPayload,\n\twithClaudeHookIngestLock,\n} from \"./claude-hook-ingest-spool.js\";\nimport { logHookFailure } from \"./claude-hook-plugin-log.js\";\nimport { trackHookSessionState } from \"./claude-hook-session-state.js\";\n\ntype IngestVia = \"http\" | \"direct\" | \"spool\" | \"spool_lock_busy\";\n\ntype IngestResult = { inserted: number; skipped: number; via: IngestVia };\n\ntype IngestOpts = {\n\thost: string;\n\tport: string | number;\n} & DbOpts;\n\ntype IngestDeps = {\n\thttpIngest?: typeof tryHttpIngest;\n\tdirectIngest?: typeof directEnqueue;\n\tresolveDb?: typeof resolveDbPath;\n\tboundaryFlush?: (payload: Record<string, unknown>, dbPath: string) => Promise<void> | void;\n};\n\nfunction emitStructuredError(errorCode: string, message: string): void {\n\tconsole.log(JSON.stringify({ error: errorCode, message }));\n\tprocess.exitCode = 1;\n}\n\n/** Try to POST the hook payload to the running viewer server.\n *\n * Returns `ok: true` only when the viewer accepted the payload AND\n * actually inserted it. The viewer may legitimately accept a request\n * but report `skipped > 0` when the payload was deduped or otherwise\n * rejected after parse — those cases must trigger the locked\n * fallback so the durability layer can decide whether to spool.\n */\nasync function tryHttpIngest(\n\tpayload: Record<string, unknown>,\n\thost: string,\n\tport: number,\n): Promise<{ ok: boolean; inserted: number; skipped: number }> {\n\tconst url = `http://${host}:${port}/api/claude-hooks`;\n\tconst controller = new AbortController();\n\tconst timeout = setTimeout(() => controller.abort(), 5000);\n\ttry {\n\t\tconst res = await fetch(url, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify(payload),\n\t\t\tsignal: controller.signal,\n\t\t});\n\t\tif (!res.ok) return { ok: false, inserted: 0, skipped: 0 };\n\n\t\tlet body: unknown;\n\t\ttry {\n\t\t\tbody = await res.json();\n\t\t} catch {\n\t\t\tlogHookFailure(\"codemem claude-hook-ingest HTTP accepted with invalid response body\");\n\t\t\treturn { ok: false, inserted: 0, skipped: 0 };\n\t\t}\n\t\tif (body == null || typeof body !== \"object\" || Array.isArray(body)) {\n\t\t\tlogHookFailure(\"codemem claude-hook-ingest HTTP accepted with invalid response type\");\n\t\t\treturn { ok: false, inserted: 0, skipped: 0 };\n\t\t}\n\t\tconst obj = body as Record<string, unknown>;\n\t\tif (typeof obj.inserted !== \"number\" || typeof obj.skipped !== \"number\") {\n\t\t\tlogHookFailure(\"codemem claude-hook-ingest HTTP accepted with unexpected response body\");\n\t\t\treturn { ok: false, inserted: 0, skipped: 0 };\n\t\t}\n\t\tif (obj.skipped > 0) {\n\t\t\tlogHookFailure(\"codemem claude-hook-ingest HTTP accepted but skipped payload\");\n\t\t\treturn { ok: false, inserted: obj.inserted, skipped: obj.skipped };\n\t\t}\n\t\treturn { ok: true, inserted: obj.inserted, skipped: obj.skipped };\n\t} catch {\n\t\treturn { ok: false, inserted: 0, skipped: 0 };\n\t} finally {\n\t\tclearTimeout(timeout);\n\t}\n}\n\n/** Fall back to direct raw-event enqueue via the local SQLite store. */\nexport function directEnqueue(\n\tpayload: Record<string, unknown>,\n\tdbPath: string,\n): { inserted: number; skipped: number } {\n\tconst envelope = buildRawEventEnvelopeFromHook(payload);\n\tif (!envelope) return { inserted: 0, skipped: 1 };\n\n\tconst db = connect(dbPath);\n\ttry {\n\t\ttry {\n\t\t\tloadSqliteVec(db);\n\t\t} catch {\n\t\t\t// sqlite-vec not available — non-fatal for raw event enqueue\n\t\t}\n\t\tconst strippedPayload = stripPrivateObj(envelope.payload) as Record<string, unknown>;\n\t\tconst existing = db\n\t\t\t.prepare(\n\t\t\t\t\"SELECT 1 FROM raw_events WHERE source = ? AND stream_id = ? AND event_id = ? LIMIT 1\",\n\t\t\t)\n\t\t\t.get(envelope.source, envelope.session_stream_id, envelope.event_id);\n\t\tif (existing) return { inserted: 0, skipped: 0 };\n\n\t\tdb.prepare(\n\t\t\t`INSERT INTO raw_events(\n\t\t\t\tsource, stream_id, opencode_session_id, event_id, event_seq,\n\t\t\t\tevent_type, ts_wall_ms, payload_json, created_at\n\t\t\t) VALUES (?, ?, ?, ?, (\n\t\t\t\tSELECT COALESCE(MAX(event_seq), 0) + 1\n\t\t\t\tFROM raw_events WHERE source = ? AND stream_id = ?\n\t\t\t), ?, ?, ?, datetime('now'))`,\n\t\t).run(\n\t\t\tenvelope.source,\n\t\t\tenvelope.session_stream_id,\n\t\t\tenvelope.opencode_session_id,\n\t\t\tenvelope.event_id,\n\t\t\tenvelope.source,\n\t\t\tenvelope.session_stream_id,\n\t\t\t\"claude.hook\",\n\t\t\tenvelope.ts_wall_ms,\n\t\t\tJSON.stringify(strippedPayload),\n\t\t);\n\n\t\t// Query actual max event_seq for this stream to keep session metadata in sync\n\t\tconst maxSeqRow = db\n\t\t\t.prepare(\n\t\t\t\t\"SELECT COALESCE(MAX(event_seq), 0) AS max_seq FROM raw_events WHERE source = ? AND stream_id = ?\",\n\t\t\t)\n\t\t\t.get(envelope.source, envelope.session_stream_id) as { max_seq: number };\n\t\tconst currentMaxSeq = maxSeqRow.max_seq;\n\n\t\t// Upsert session metadata with accurate sequence tracking\n\t\tdb.prepare(\n\t\t\t`INSERT INTO raw_event_sessions(\n\t\t\t\tsource, stream_id, opencode_session_id, cwd, project, started_at,\n\t\t\t\tlast_seen_ts_wall_ms, last_received_event_seq, last_flushed_event_seq, updated_at\n\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, -1, datetime('now'))\n\t\t\tON CONFLICT(source, stream_id) DO UPDATE SET\n\t\t\t\tcwd = COALESCE(excluded.cwd, cwd),\n\t\t\t\tproject = COALESCE(excluded.project, project),\n\t\t\t\tstarted_at = COALESCE(excluded.started_at, started_at),\n\t\t\t\tlast_seen_ts_wall_ms = MAX(COALESCE(excluded.last_seen_ts_wall_ms, 0), COALESCE(last_seen_ts_wall_ms, 0)),\n\t\t\t\tlast_received_event_seq = MAX(excluded.last_received_event_seq, last_received_event_seq),\n\t\t\t\tupdated_at = datetime('now')`,\n\t\t).run(\n\t\t\tenvelope.source,\n\t\t\tenvelope.session_stream_id,\n\t\t\tenvelope.opencode_session_id,\n\t\t\tenvelope.cwd,\n\t\t\tenvelope.project,\n\t\t\tenvelope.started_at,\n\t\t\tenvelope.ts_wall_ms,\n\t\t\tcurrentMaxSeq,\n\t\t);\n\n\t\treturn { inserted: 1, skipped: 0 };\n\t} finally {\n\t\tdb.close();\n\t}\n}\n\n/**\n * Best-effort boundary flush: write the payload through to the local\n * store (so the just-fired SessionEnd / Stop event is durable in\n * raw_events) and then run a synchronous flushRawEvents pass so that\n * the latest memories are extracted before the hook process exits and\n * the user closes their terminal.\n *\n * Any failure here \\u2014 observer construction, store I/O, flush errors,\n * or simply running without observer credentials \\u2014 is logged to\n * `~/.codemem/plugin.log` and swallowed. The hook command must never\n * crash on a boundary flush failure.\n */\nasync function flushBoundaryRawEvents(\n\tpayload: Record<string, unknown>,\n\tdbPath: string,\n): Promise<void> {\n\tconst envelope = buildRawEventEnvelopeFromHook(payload);\n\tif (!envelope) return;\n\n\tlet observer: ObserverClient;\n\ttry {\n\t\tobserver = new ObserverClient();\n\t} catch (err) {\n\t\tlogHookFailure(\n\t\t\t`codemem claude-hook-ingest boundary flush observer init failed: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t\treturn;\n\t}\n\n\tlet store: MemoryStore;\n\ttry {\n\t\tstore = new MemoryStore(dbPath);\n\t} catch (err) {\n\t\tlogHookFailure(\n\t\t\t`codemem claude-hook-ingest boundary flush store init failed: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t\treturn;\n\t}\n\n\ttry {\n\t\tawait flushRawEvents(\n\t\t\tstore,\n\t\t\t{ observer },\n\t\t\t{\n\t\t\t\topencodeSessionId: envelope.session_stream_id,\n\t\t\t\tsource: envelope.source,\n\t\t\t\tcwd: envelope.cwd ?? null,\n\t\t\t\tproject: envelope.project ?? null,\n\t\t\t\tstartedAt: envelope.started_at ?? null,\n\t\t\t\tmaxEvents: null,\n\t\t\t},\n\t\t);\n\t} catch (err) {\n\t\tlogHookFailure(\n\t\t\t`codemem claude-hook-ingest boundary flush raw events failed: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t} finally {\n\t\tstore.close();\n\t}\n}\n\n/**\n * Ingest one Claude hook payload using the TS contract:\n * HTTP enqueue first, then locked drain + retry + direct fallback +\n * disk spool durability.\n */\nexport async function ingestClaudeHookPayload(\n\tpayload: Record<string, unknown>,\n\topts: IngestOpts,\n\tdeps: IngestDeps = {},\n): Promise<IngestResult> {\n\tconst httpIngest = deps.httpIngest ?? tryHttpIngest;\n\tconst directIngest = deps.directIngest ?? directEnqueue;\n\tconst resolveDb = deps.resolveDb ?? resolveDbPath;\n\tconst boundaryFlush = deps.boundaryFlush ?? flushBoundaryRawEvents;\n\n\t// Update per-session state alongside ingestion so claude-hook-inject's\n\t// retrieval query can draw on prompts/files seen on the ingest path.\n\t// Failures must never crash the hook command.\n\ttry {\n\t\ttrackHookSessionState(payload);\n\t} catch {\n\t\t// best-effort\n\t}\n\n\tconst port = typeof opts.port === \"number\" ? opts.port : Number.parseInt(opts.port, 10);\n\n\t// Resolve DB path lazily so the unlocked HTTP-success path doesn't\n\t// touch the filesystem when the viewer is up.\n\tlet cachedDbPath: string | null = null;\n\tconst getDbPath = (): string => {\n\t\tif (cachedDbPath === null) cachedDbPath = resolveDb(resolveDbOpt(opts));\n\t\treturn cachedDbPath;\n\t};\n\n\tconst tryDirectFallback = (\n\t\tqueued: Record<string, unknown>,\n\t): { ok: true; result: { inserted: number; skipped: number } } | { ok: false } => {\n\t\ttry {\n\t\t\treturn { ok: true, result: directIngest(queued, getDbPath()) };\n\t\t} catch (err) {\n\t\t\tlogHookFailure(\n\t\t\t\t`codemem claude-hook-ingest direct fallback failed: ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t);\n\t\t\treturn { ok: false };\n\t\t}\n\t};\n\n\tconst flushOnBoundaryIfRequested = async (): Promise<void> => {\n\t\tif (!shouldForceBoundaryFlush(payload)) return;\n\t\t// Best-effort write-through of the boundary payload to the local\n\t\t// store, then a synchronous flushRawEvents pass so memory state\n\t\t// is durable even when the viewer process is the one being shut\n\t\t// down. Both halves are logged with a boundary-specific message\n\t\t// so operators can distinguish them from regular fallback errors.\n\t\ttry {\n\t\t\tdirectIngest(payload, getDbPath());\n\t\t} catch (err) {\n\t\t\tlogHookFailure(\n\t\t\t\t`codemem claude-hook-ingest boundary flush direct write failed: ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t);\n\t\t}\n\t\ttry {\n\t\t\tawait boundaryFlush(payload, getDbPath());\n\t\t} catch (err) {\n\t\t\tlogHookFailure(\n\t\t\t\t`codemem claude-hook-ingest boundary flush failed: ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t);\n\t\t}\n\t};\n\n\t// Drain any backlog spooled by previous failed invocations. Runs on\n\t// every successful HTTP path so the queue is recovered as soon as\n\t// the viewer comes back up; if a previous run had to spool because\n\t// both HTTP and direct ingest failed, those payloads must not sit\n\t// stranded just because the next call happens to hit a healthy\n\t// viewer. Cheap pre-check avoids the lock acquisition cost on the\n\t// fast path when the spool is empty (the common case).\n\tconst drainBacklogIfPresent = async (): Promise<void> => {\n\t\tif (!hasSpooledEntries()) return;\n\t\ttry {\n\t\t\tawait withClaudeHookIngestLock(async () => {\n\t\t\t\trecoverStaleTmpSpool(lockTtlSeconds());\n\t\t\t\tawait drainSpool(async (queuedPayload) => {\n\t\t\t\t\tconst queuedHttp = await httpIngest(queuedPayload, opts.host, port);\n\t\t\t\t\tif (queuedHttp.ok) return true;\n\t\t\t\t\treturn tryDirectFallback(queuedPayload).ok;\n\t\t\t\t});\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tif (err instanceof LockBusyError) {\n\t\t\t\t// Another invocation is already draining; nothing to do.\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlogHookFailure(\n\t\t\t\t`codemem claude-hook-ingest backlog drain failed: ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t);\n\t\t}\n\t};\n\n\t// 1. Unlocked HTTP attempt — fast path when the viewer is up.\n\tconst httpResult = await httpIngest(payload, opts.host, port);\n\tif (httpResult.ok) {\n\t\tawait flushOnBoundaryIfRequested();\n\t\tawait drainBacklogIfPresent();\n\t\treturn { inserted: httpResult.inserted, skipped: httpResult.skipped, via: \"http\" };\n\t}\n\n\t// 2. Locked failure path: drain spool, retry HTTP, fall back to\n\t// direct, spool the payload as last resort.\n\ttry {\n\t\treturn await withClaudeHookIngestLock(async () => {\n\t\t\trecoverStaleTmpSpool(lockTtlSeconds());\n\n\t\t\tawait drainSpool(async (queuedPayload) => {\n\t\t\t\tconst queuedHttp = await httpIngest(queuedPayload, opts.host, port);\n\t\t\t\tif (queuedHttp.ok) return true;\n\t\t\t\tconst direct = tryDirectFallback(queuedPayload);\n\t\t\t\treturn direct.ok;\n\t\t\t});\n\n\t\t\tconst secondHttp = await httpIngest(payload, opts.host, port);\n\t\t\tif (secondHttp.ok) {\n\t\t\t\tawait flushOnBoundaryIfRequested();\n\t\t\t\treturn {\n\t\t\t\t\tinserted: secondHttp.inserted,\n\t\t\t\t\tskipped: secondHttp.skipped,\n\t\t\t\t\tvia: \"http\" as const,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst direct = tryDirectFallback(payload);\n\t\t\tif (direct.ok) {\n\t\t\t\tawait flushOnBoundaryIfRequested();\n\t\t\t\treturn { ...direct.result, via: \"direct\" as const };\n\t\t\t}\n\n\t\t\tif (spoolPayload(payload)) {\n\t\t\t\treturn { inserted: 0, skipped: 0, via: \"spool\" as const };\n\t\t\t}\n\n\t\t\tlogHookFailure(\"codemem claude-hook-ingest failed: fallback and spool failed\");\n\t\t\tthrow new Error(\"claude-hook-ingest: fallback and spool both failed\");\n\t\t});\n\t} catch (err) {\n\t\tif (!(err instanceof LockBusyError)) throw err;\n\n\t\tlogHookFailure(\"codemem claude-hook-ingest lock busy; trying unlocked fallback\");\n\t\tconst direct = tryDirectFallback(payload);\n\t\tif (direct.ok) {\n\t\t\treturn { ...direct.result, via: \"direct\" };\n\t\t}\n\t\tif (spoolPayload(payload)) {\n\t\t\treturn { inserted: 0, skipped: 0, via: \"spool_lock_busy\" };\n\t\t}\n\t\tlogHookFailure(\"codemem claude-hook-ingest failed: unlocked fallback and spool failed\");\n\t\tthrow err;\n\t}\n}\n\nconst claudeHookCmd = new Command(\"claude-hook-ingest\")\n\t.configureHelp(helpStyle)\n\t.description(\"Ingest Claude hook payload: HTTP first, direct DB fallback\");\n\naddDbOption(claudeHookCmd);\naddViewerHostOptions(claudeHookCmd);\n\nfunction envTruthyValue(value: string | undefined): boolean {\n\tconst normalized = String(value ?? \"\")\n\t\t.trim()\n\t\t.toLowerCase();\n\treturn normalized === \"1\" || normalized === \"true\" || normalized === \"yes\" || normalized === \"on\";\n}\n\nexport const claudeHookIngestCommand = claudeHookCmd.action(\n\tasync (opts: DbOpts & { host: string; port: string }) => {\n\t\t// Honor the global plugin-ignore kill switch first so users can\n\t\t// disable every codemem hook side effect by exporting\n\t\t// CODEMEM_PLUGIN_IGNORE=1 without having to know which subcommand\n\t\t// is wired to which hook. Mirrors the inject command.\n\t\tif (envTruthyValue(process.env.CODEMEM_PLUGIN_IGNORE)) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Read payload from stdin\n\t\tlet raw: string;\n\t\ttry {\n\t\t\traw = readFileSync(0, \"utf8\").trim();\n\t\t} catch {\n\t\t\temitStructuredError(\"read_error\", \"failed to read stdin\");\n\t\t\treturn;\n\t\t}\n\t\tif (!raw) {\n\t\t\temitStructuredError(\"read_error\", \"empty stdin\");\n\t\t\treturn;\n\t\t}\n\n\t\tlet payload: Record<string, unknown>;\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(raw) as unknown;\n\t\t\tif (parsed == null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\t\t\temitStructuredError(\"parse_error\", \"payload must be a JSON object\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpayload = parsed as Record<string, unknown>;\n\t\t} catch {\n\t\t\temitStructuredError(\"parse_error\", \"invalid JSON\");\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst result = await ingestClaudeHookPayload(payload, opts);\n\t\t\tconsole.log(JSON.stringify(result));\n\t\t} catch (err) {\n\t\t\temitStructuredError(\"ingest_error\", err instanceof Error ? err.message : String(err));\n\t\t}\n\t},\n);\n","import { MemoryStore, resolveDbPath, resolveHookProject } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport { addDbOption, type DbOpts, resolveDbOpt } from \"../shared-options.js\";\nimport { logHookFailure } from \"./claude-hook-plugin-log.js\";\nimport {\n\tbuildInjectQuery,\n\tnormalizePromptText,\n\ttype SessionState,\n\ttrackHookSessionState,\n\tworkingSetPathsFromState,\n} from \"./claude-hook-session-state.js\";\n\ntype InjectResult = {\n\tcontinue: true;\n\thookSpecificOutput?: {\n\t\thookEventName: \"UserPromptSubmit\";\n\t\tadditionalContext: string;\n\t};\n};\n\n// claude-hook-inject is wired exclusively to UserPromptSubmit. The\n// hookSpecificOutput schema is event-specific (additionalContext is a\n// UserPromptSubmit-only field), so emitting any other event name would\n// produce invalid output regardless of what the payload claims.\nconst HOOK_EVENT_NAME = \"UserPromptSubmit\" as const;\n\ntype InjectOpts = DbOpts;\n\ntype HttpPackResponse = {\n\tpack_text?: string;\n};\n\ntype InjectDeps = {\n\tbuildLocalPack?: typeof buildLocalPack;\n\thttpPack?: typeof tryHttpPack;\n\tresolveDb?: typeof resolveDbPath;\n};\n\nconst DEFAULT_VIEWER_HOST = \"127.0.0.1\";\nconst DEFAULT_VIEWER_PORT = 38888;\nconst DEFAULT_MAX_CHARS = 16000;\nconst DEFAULT_HTTP_MAX_TIME_S = 2;\n\nfunction emitJson(value: InjectResult | { error: string; message: string }): void {\n\tconsole.log(JSON.stringify(value));\n}\n\nfunction envNotDisabled(value: string | undefined): boolean {\n\tconst normalized = String(value ?? \"\")\n\t\t.trim()\n\t\t.toLowerCase();\n\treturn normalized !== \"0\" && normalized !== \"false\" && normalized !== \"off\";\n}\n\nfunction envTruthy(value: string | undefined): boolean {\n\tconst normalized = String(value ?? \"\")\n\t\t.trim()\n\t\t.toLowerCase();\n\treturn normalized === \"1\" || normalized === \"true\" || normalized === \"yes\" || normalized === \"on\";\n}\n\nfunction parsePositiveInt(value: string | undefined, fallback: number): number {\n\tconst parsed = Number.parseInt(String(value ?? \"\"), 10);\n\tif (!Number.isFinite(parsed) || parsed <= 0) {\n\t\treturn fallback;\n\t}\n\treturn parsed;\n}\n\nfunction continueResult(additionalContext?: string): InjectResult {\n\tif (!additionalContext) {\n\t\treturn { continue: true };\n\t}\n\treturn {\n\t\tcontinue: true,\n\t\thookSpecificOutput: {\n\t\t\thookEventName: HOOK_EVENT_NAME,\n\t\t\tadditionalContext,\n\t\t},\n\t};\n}\n\nfunction truncateAdditionalContext(text: string, maxChars: number): string {\n\tconst normalized = text.trim();\n\tif (!normalized) {\n\t\treturn \"\";\n\t}\n\tif (!Number.isFinite(maxChars) || maxChars <= 0 || normalized.length <= maxChars) {\n\t\treturn normalized;\n\t}\n\t// Strip trailing whitespace from the slice before appending the marker\n\t// so the boundary stays readable in chat output.\n\treturn `${normalized.slice(0, maxChars).trimEnd()}\\n\\n[pack truncated]`;\n}\n\nfunction extractInjectContext(payload: Record<string, unknown>): string | null {\n\t// Reuse the same normalization the session-state tracker applies so the\n\t// `prompt !== first_prompt` comparison in buildInjectQuery is robust to\n\t// multi-line prompts (otherwise a \"fix\\nauth\" current prompt would never\n\t// match a stored \"fix auth\" first_prompt and would be appended on every\n\t// turn).\n\tconst prompt = normalizePromptText(payload.prompt);\n\treturn prompt || null;\n}\n\nfunction resolveInjectProject(payload: Record<string, unknown>): string | null {\n\tconst cwd = typeof payload.cwd === \"string\" ? payload.cwd : null;\n\treturn resolveHookProject(cwd, payload.project);\n}\n\nasync function buildLocalPack(\n\tcontext: string,\n\tproject: string | null,\n\tdbPath: string,\n\tworkingSetPaths: string[] = [],\n): Promise<string> {\n\tconst store = new MemoryStore(dbPath);\n\ttry {\n\t\tconst limit = parsePositiveInt(process.env.CODEMEM_INJECT_LIMIT, 8);\n\t\tconst budget = parsePositiveInt(process.env.CODEMEM_INJECT_TOKEN_BUDGET, 800);\n\t\tconst filters: { project?: string; working_set_paths?: string[] } = {};\n\t\tif (project) {\n\t\t\tfilters.project = project;\n\t\t}\n\t\tif (workingSetPaths.length > 0) {\n\t\t\tfilters.working_set_paths = workingSetPaths;\n\t\t}\n\t\tconst pack = await store.buildMemoryPackAsync(context, limit, budget, filters);\n\t\treturn String(pack.pack_text ?? \"\").trim();\n\t} finally {\n\t\tstore.close();\n\t}\n}\n\nasync function tryHttpPack(\n\tcontext: string,\n\tproject: string | null,\n\tmaxTimeMs = DEFAULT_HTTP_MAX_TIME_S * 1000,\n): Promise<string> {\n\tconst host = process.env.CODEMEM_VIEWER_HOST || DEFAULT_VIEWER_HOST;\n\tconst port = parsePositiveInt(process.env.CODEMEM_VIEWER_PORT, DEFAULT_VIEWER_PORT);\n\tconst url = new URL(`http://${host}:${port}/api/pack`);\n\turl.searchParams.set(\"context\", context);\n\turl.searchParams.set(\"limit\", String(parsePositiveInt(process.env.CODEMEM_INJECT_LIMIT, 8)));\n\turl.searchParams.set(\n\t\t\"token_budget\",\n\t\tString(parsePositiveInt(process.env.CODEMEM_INJECT_TOKEN_BUDGET, 800)),\n\t);\n\tif (project) {\n\t\turl.searchParams.set(\"project\", project);\n\t}\n\n\tconst controller = new AbortController();\n\tconst timeout = setTimeout(() => controller.abort(), maxTimeMs);\n\ttry {\n\t\tconst res = await fetch(url, { signal: controller.signal });\n\t\tif (!res.ok) {\n\t\t\treturn \"\";\n\t\t}\n\t\tconst body = (await res.json()) as HttpPackResponse;\n\t\treturn String(body.pack_text ?? \"\").trim();\n\t} catch {\n\t\treturn \"\";\n\t} finally {\n\t\tclearTimeout(timeout);\n\t}\n}\n\nexport async function buildClaudeHookInjection(\n\tpayload: Record<string, unknown>,\n\topts: InjectOpts,\n\tdeps: InjectDeps = {},\n): Promise<InjectResult> {\n\t// Honor the global plugin-ignore kill switch first so users can disable\n\t// every codemem hook side effect by exporting CODEMEM_PLUGIN_IGNORE=1\n\t// without having to know which subcommand is wired to which hook.\n\tif (envTruthy(process.env.CODEMEM_PLUGIN_IGNORE)) {\n\t\treturn continueResult();\n\t}\n\tif (!envNotDisabled(process.env.CODEMEM_INJECT_CONTEXT || \"1\")) {\n\t\treturn continueResult();\n\t}\n\n\t// Track session state before the prompt-presence check so SessionEnd /\n\t// PostToolUse / SessionStart events still update the per-session store.\n\tlet state: SessionState | null = null;\n\ttry {\n\t\tstate = trackHookSessionState(payload);\n\t} catch {\n\t\tstate = null;\n\t}\n\n\tconst promptText = extractInjectContext(payload);\n\tif (!promptText) {\n\t\treturn continueResult();\n\t}\n\n\tconst buildPack = deps.buildLocalPack ?? buildLocalPack;\n\tconst httpPack = deps.httpPack ?? tryHttpPack;\n\tconst resolveDb = deps.resolveDb ?? resolveDbPath;\n\tconst project = resolveInjectProject(payload);\n\tconst query = buildInjectQuery({ prompt: promptText, project, state });\n\tconst workingSetPaths = workingSetPathsFromState(state);\n\tconst maxChars = parsePositiveInt(process.env.CODEMEM_INJECT_MAX_CHARS, DEFAULT_MAX_CHARS);\n\tconst httpMaxTimeMs =\n\t\tparsePositiveInt(process.env.CODEMEM_INJECT_HTTP_MAX_TIME_S, DEFAULT_HTTP_MAX_TIME_S) * 1000;\n\n\tlet additionalContext = \"\";\n\ttry {\n\t\tconst dbPath = resolveDb(resolveDbOpt(opts));\n\t\tadditionalContext = await buildPack(query, project, dbPath, workingSetPaths);\n\t} catch (err) {\n\t\tadditionalContext = \"\";\n\t\tlogHookFailure(\n\t\t\t`codemem claude-hook-inject local pack failed: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t}\n\n\tif (!additionalContext && envNotDisabled(process.env.CODEMEM_INJECT_HTTP_FALLBACK || \"1\")) {\n\t\t// tryHttpPack swallows its own network errors and returns \"\" on\n\t\t// failure; don't wrap it here so tests that throw from a stub mock\n\t\t// still surface as failures (the existing\n\t\t// \"should not run\" assertions rely on this).\n\t\tadditionalContext = await httpPack(query, project, httpMaxTimeMs);\n\t}\n\n\treturn continueResult(truncateAdditionalContext(additionalContext, maxChars));\n}\n\nconst claudeHookInjectCmd = new Command(\"claude-hook-inject\")\n\t.configureHelp(helpStyle)\n\t.description(\"Return Claude hook additionalContext from local pack generation\");\n\naddDbOption(claudeHookInjectCmd);\n\nexport const claudeHookInjectCommand = claudeHookInjectCmd.action(async (opts: InjectOpts) => {\n\tlet raw = \"\";\n\tfor await (const chunk of process.stdin) {\n\t\traw += String(chunk);\n\t}\n\tconst trimmed = raw.trim();\n\tif (!trimmed) {\n\t\temitJson(continueResult());\n\t\treturn;\n\t}\n\n\tlet payload: Record<string, unknown>;\n\ttry {\n\t\tconst parsed = JSON.parse(trimmed) as unknown;\n\t\tif (parsed == null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\t\temitJson({ error: \"parse_error\", message: \"payload must be a JSON object\" });\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\t\tpayload = parsed as Record<string, unknown>;\n\t} catch {\n\t\temitJson({ error: \"parse_error\", message: \"invalid JSON\" });\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\n\tconst result = await buildClaudeHookInjection(payload, opts);\n\temitJson(result);\n});\n","import { existsSync } from \"node:fs\";\nimport {\n\ttype ConfigResolutionResult,\n\tgetWorkspaceCodememConfigPath,\n\treadCodememConfigFile,\n\treadCodememConfigFileAtPath,\n\tresolveCodememConfigPath,\n\twriteCodememConfigFile,\n} from \"@codemem/core\";\nimport { Command, Option } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddConfigOption,\n\taddJsonOption,\n\ttype ConfigOpts,\n\ttype JsonOpts,\n} from \"../shared-options.js\";\n\ntype WorkspaceConfigOptions = JsonOpts & {\n\tworkspaceId?: string;\n\tsyncEnabled?: boolean;\n\tsyncHost?: string;\n\tsyncPort?: string;\n\tsyncIntervalS?: string;\n\tcoordinatorUrl?: string;\n\tcoordinatorGroup?: string;\n};\n\ntype WorkspaceConfigResult = {\n\tworkspace_id: string;\n\tconfig_path: string;\n\tupdated_keys: string[];\n\tconfig: Record<string, unknown>;\n};\n\nfunction parseIntegerOption(value: string | undefined, flagName: string): number | undefined {\n\tif (value == null) return undefined;\n\tconst trimmed = value.trim();\n\tif (!/^\\d+$/.test(trimmed)) {\n\t\tthrow new Error(`Invalid ${flagName}: ${value}`);\n\t}\n\treturn Number.parseInt(trimmed, 10);\n}\n\nfunction buildWorkspaceConfigPatch(opts: WorkspaceConfigOptions): Record<string, unknown> {\n\tconst patch: Record<string, unknown> = {};\n\tif (opts.syncEnabled === true) patch.sync_enabled = true;\n\tif (opts.syncEnabled === false) patch.sync_enabled = false;\n\tif (opts.syncHost?.trim()) patch.sync_host = opts.syncHost.trim();\n\tconst syncPort = parseIntegerOption(opts.syncPort, \"--sync-port\");\n\tif (syncPort != null) patch.sync_port = syncPort;\n\tconst syncInterval = parseIntegerOption(opts.syncIntervalS, \"--sync-interval-s\");\n\tif (syncInterval != null) patch.sync_interval_s = syncInterval;\n\tif (opts.coordinatorUrl?.trim()) patch.sync_coordinator_url = opts.coordinatorUrl.trim();\n\tif (opts.coordinatorGroup?.trim()) patch.sync_coordinator_group = opts.coordinatorGroup.trim();\n\treturn patch;\n}\n\nfunction mergeWorkspaceConfig(\n\texistingConfig: Record<string, unknown>,\n\tpatch: Record<string, unknown>,\n): Record<string, unknown> {\n\treturn { ...existingConfig, ...patch };\n}\n\nfunction runWorkspaceConfigCommand(\n\topts: WorkspaceConfigOptions & { enableSync?: boolean; disableSync?: boolean },\n): WorkspaceConfigResult {\n\tif (opts.enableSync && opts.disableSync) {\n\t\tthrow new Error(\"Use only one of --enable-sync or --disable-sync\");\n\t}\n\tconst workspaceId = opts.workspaceId;\n\tif (!workspaceId) {\n\t\tthrow new Error(\"workspace-id is required\");\n\t}\n\tconst configPath = getWorkspaceCodememConfigPath(workspaceId);\n\t// Seeds new workspace config from legacy global config on first write,\n\t// so existing settings are inherited.\n\tconst existingConfig = existsSync(configPath)\n\t\t? readCodememConfigFileAtPath(configPath)\n\t\t: readCodememConfigFile();\n\tconst patch = buildWorkspaceConfigPatch({\n\t\tworkspaceId,\n\t\tsyncEnabled: opts.enableSync ? true : opts.disableSync ? false : undefined,\n\t\tsyncHost: opts.syncHost,\n\t\tsyncPort: opts.syncPort,\n\t\tsyncIntervalS: opts.syncIntervalS,\n\t\tcoordinatorUrl: opts.coordinatorUrl,\n\t\tcoordinatorGroup: opts.coordinatorGroup,\n\t\tjson: opts.json,\n\t});\n\tif (Object.keys(patch).length === 0) {\n\t\tthrow new Error(\"Provide at least one config field to update\");\n\t}\n\tconst nextConfig = mergeWorkspaceConfig(existingConfig, patch);\n\tconst savedPath = writeCodememConfigFile(nextConfig, configPath);\n\treturn {\n\t\tworkspace_id: workspaceId,\n\t\tconfig_path: savedPath,\n\t\tupdated_keys: Object.keys(patch).sort(),\n\t\tconfig: nextConfig,\n\t};\n}\n\nexport const configCommand = new Command(\"config\")\n\t.configureHelp(helpStyle)\n\t.description(\"Manage codemem configuration\");\n\nconst workspaceCmd = new Command(\"workspace\")\n\t.configureHelp(helpStyle)\n\t.description(\"Create or update workspace-scoped codemem config\")\n\t.argument(\"[workspace-id]\", \"workspace identifier\")\n\t.option(\"--enable-sync\", \"set sync_enabled=true\")\n\t.option(\"--disable-sync\", \"set sync_enabled=false\")\n\t.option(\"--sync-host <host>\", \"set sync_host\")\n\t.option(\"--sync-port <port>\", \"set sync_port\")\n\t.option(\"--sync-interval-s <seconds>\", \"set sync_interval_s\")\n\t.option(\"--coordinator-url <url>\", \"set sync_coordinator_url\")\n\t.option(\"--coordinator-group <group>\", \"set sync_coordinator_group\");\n\n// Hidden backwards-compat alias for --workspace-id <id>\nworkspaceCmd.addOption(\n\tnew Option(\"--workspace-id <id>\", \"workspace identifier (use positional instead)\").hideHelp(),\n);\n\naddJsonOption(workspaceCmd);\n\nworkspaceCmd.action(\n\t(\n\t\tworkspaceIdArg: string | undefined,\n\t\topts: WorkspaceConfigOptions & { enableSync?: boolean; disableSync?: boolean },\n\t) => {\n\t\ttry {\n\t\t\t// Positional takes precedence over hidden flag alias\n\t\t\tconst workspaceId = workspaceIdArg || opts.workspaceId;\n\t\t\tif (!workspaceId) {\n\t\t\t\tconsole.error(\"Error: missing required argument 'workspace-id'\");\n\t\t\t\tprocess.exitCode = 2;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst result = runWorkspaceConfigCommand({ ...opts, workspaceId });\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconsole.log(`Updated workspace config: ${result.config_path}`);\n\t\t\tconsole.log(`Updated keys: ${result.updated_keys.join(\", \")}`);\n\t\t} catch (err) {\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(\n\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\terror: \"config_error\",\n\t\t\t\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tconsole.error(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t},\n);\n\nconfigCommand.addCommand(workspaceCmd);\n\n// ---------------------------------------------------------------------------\n// config where — show resolved config path with full traceability\n// ---------------------------------------------------------------------------\n\ntype WhereOptions = ConfigOpts & JsonOpts;\n\nfunction formatWhereHuman(result: ConfigResolutionResult): string {\n\tconst lines: string[] = [];\n\tconst allEntries = [result.resolved, ...result.fallbackChain];\n\t// Sort by original precedence order for display\n\tconst sourceOrder: Record<string, number> = {\n\t\t\"cli-flag\": 0,\n\t\t\"env-codemem-config\": 1,\n\t\t\"env-runtime-root\": 2,\n\t\t\"env-workspace-id\": 3,\n\t\t\"legacy-global\": 4,\n\t};\n\tallEntries.sort((a, b) => (sourceOrder[a.source] ?? 99) - (sourceOrder[b.source] ?? 99));\n\n\tfor (const entry of allEntries) {\n\t\tconst isSelected = entry === result.resolved;\n\t\tconst marker = isSelected ? \">>>\" : \" \";\n\t\tconst existsLabel = entry.exists ? \"exists\" : \"missing\";\n\t\tlines.push(`${marker} [${entry.source}] ${entry.path}`);\n\t\tlines.push(` ${entry.reason} (${existsLabel})`);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nconst whereCmd = new Command(\"where\")\n\t.configureHelp(helpStyle)\n\t.description(\"show resolved config file path\");\n\naddConfigOption(whereCmd);\naddJsonOption(whereCmd);\n\nwhereCmd.action((opts: WhereOptions) => {\n\ttry {\n\t\tconst result = resolveCodememConfigPath(opts.config, \"read\");\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t} else {\n\t\t\tconsole.log(formatWhereHuman(result));\n\t\t}\n\t} catch (err) {\n\t\tif (opts.json) {\n\t\t\tconsole.log(\n\t\t\t\tJSON.stringify({\n\t\t\t\t\terror: \"config_error\",\n\t\t\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t\t\t}),\n\t\t\t);\n\t\t} else {\n\t\t\tconsole.error(err instanceof Error ? err.message : String(err));\n\t\t}\n\t\tprocess.exitCode = 1;\n\t}\n});\n\nconfigCommand.addCommand(whereCmd);\n\nexport { buildWorkspaceConfigPatch, mergeWorkspaceConfig, runWorkspaceConfigCommand };\n","/**\n * Coordinator CLI commands — manage coordinator invites, join requests, and relay server.\n *\n * Extracted from sync.ts to give coordinator admin its own top-level group\n * per cli-design-conventions.md (operator/admin surfaces belong in their own group).\n *\n * buildCoordinatorCommand() is a factory that creates a fresh command tree.\n * This allows both the canonical top-level `coordinator` and the deprecated\n * `sync coordinator` alias to have independent Commander instances (Commander\n * re-parents commands on addCommand, so sharing instances between two parents\n * is not possible).\n */\n\nimport { readFileSync } from \"node:fs\";\n\nimport * as p from \"@clack/prompts\";\nimport {\n\tcoordinatorCreateGroupAction,\n\tcoordinatorCreateInviteAction,\n\tcoordinatorDisableDeviceAction,\n\tcoordinatorEnrollDeviceAction,\n\tcoordinatorImportInviteAction,\n\tcoordinatorListBootstrapGrantsAction,\n\tcoordinatorListDevicesAction,\n\tcoordinatorListGroupsAction,\n\tcoordinatorListJoinRequestsAction,\n\tcoordinatorRemoveDeviceAction,\n\tcoordinatorRenameDeviceAction,\n\tcoordinatorReviewJoinRequestAction,\n\tcoordinatorRevokeBootstrapGrantAction,\n\tcreateBetterSqliteCoordinatorApp,\n\tDEFAULT_COORDINATOR_DB_PATH,\n\tfingerprintPublicKey,\n} from \"@codemem/core\";\nimport { serve as honoServe } from \"@hono/node-server\";\nimport { Command, Option } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddConfigOption,\n\taddDbOption,\n\taddJsonOption,\n\temitJsonError,\n\tresolveDbOpt,\n} from \"../shared-options.js\";\n\nfunction readCoordinatorPublicKey(opts: { publicKey?: string; publicKeyFile?: string }): string {\n\tconst inline = String(opts.publicKey ?? \"\").trim();\n\tconst filePath = String(opts.publicKeyFile ?? \"\").trim();\n\tif (inline && filePath) throw new Error(\"Use only one of --public-key or --public-key-file\");\n\tif (filePath) {\n\t\tconst text = readFileSync(filePath, \"utf8\").trim();\n\t\tif (!text) throw new Error(`Public key file is empty: ${filePath}`);\n\t\treturn text;\n\t}\n\tif (!inline) throw new Error(\"Public key required via --public-key or --public-key-file\");\n\treturn inline;\n}\n\n/**\n * Build a fresh coordinator command tree. Each call returns independent\n * Commander instances so the tree can be mounted under multiple parents.\n */\nexport function buildCoordinatorCommand(): Command {\n\tconst cmd = new Command(\"coordinator\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Manage coordinator invites, join requests, and relay server\");\n\n\t// ---- group-create ----\n\n\tconst groupCreateCmd = new Command(\"group-create\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Create a coordinator group in the local store\")\n\t\t.argument(\"<group>\", \"group id\")\n\t\t.option(\"--name <name>\", \"display name override\");\n\taddDbOption(groupCreateCmd);\n\taddJsonOption(groupCreateCmd);\n\tgroupCreateCmd.action(\n\t\tasync (\n\t\t\tgroupId: string,\n\t\t\topts: { name?: string; db?: string; dbPath?: string; json?: boolean },\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst group = await coordinatorCreateGroupAction({\n\t\t\t\t\tgroupId,\n\t\t\t\t\tdisplayName: opts.name?.trim() || null,\n\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t});\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(group, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem coordinator group-create\");\n\t\t\t\tp.log.success(`Group ready: ${groupId.trim()}`);\n\t\t\t\tp.outro(String(group.display_name ?? group.group_id ?? groupId.trim()));\n\t\t\t} catch (err) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"group_create_failed\", err instanceof Error ? err.message : String(err));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t},\n\t);\n\tcmd.addCommand(groupCreateCmd);\n\n\t// ---- list-groups ----\n\n\tconst listGroupsCmd = new Command(\"list-groups\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"List coordinator groups from the local store\");\n\taddDbOption(listGroupsCmd);\n\taddJsonOption(listGroupsCmd);\n\tlistGroupsCmd.action(async (opts: { db?: string; dbPath?: string; json?: boolean }) => {\n\t\ttry {\n\t\t\tconst groups = await coordinatorListGroupsAction({ dbPath: resolveDbOpt(opts) ?? null });\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(groups, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.intro(\"codemem coordinator list-groups\");\n\t\t\tif (groups.length === 0) {\n\t\t\t\tp.outro(\"No coordinator groups found\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (const group of groups) {\n\t\t\t\tp.log.message(\n\t\t\t\t\t`- ${String(group.group_id ?? \"\")}${group.display_name ? ` (${String(group.display_name)})` : \"\"}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tp.outro(`${groups.length} group(s)`);\n\t\t} catch (err) {\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\"list_groups_failed\", err instanceof Error ? err.message : String(err));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t});\n\tcmd.addCommand(listGroupsCmd);\n\n\t// ---- enroll-device ----\n\n\tconst enrollDeviceCmd = new Command(\"enroll-device\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Enroll a device in a local coordinator group\")\n\t\t.argument(\"<group>\", \"group id\")\n\t\t.argument(\"<device-id>\", \"device id\")\n\t\t.option(\"--fingerprint <fingerprint>\", \"device fingerprint\")\n\t\t.option(\"--public-key <key>\", \"device public key\")\n\t\t.option(\"--public-key-file <path>\", \"path to device public key\")\n\t\t.option(\"--name <name>\", \"display name\");\n\taddDbOption(enrollDeviceCmd);\n\taddJsonOption(enrollDeviceCmd);\n\tenrollDeviceCmd.action(\n\t\tasync (\n\t\t\tgroupId: string,\n\t\t\tdeviceId: string,\n\t\t\topts: {\n\t\t\t\tfingerprint?: string;\n\t\t\t\tpublicKey?: string;\n\t\t\t\tpublicKeyFile?: string;\n\t\t\t\tname?: string;\n\t\t\t\tdb?: string;\n\t\t\t\tdbPath?: string;\n\t\t\t\tjson?: boolean;\n\t\t\t},\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst publicKey = readCoordinatorPublicKey(opts);\n\t\t\t\tconst fingerprint = String(opts.fingerprint ?? \"\").trim();\n\t\t\t\tif (!fingerprint) {\n\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\temitJsonError(\"usage_error\", \"Fingerprint required via --fingerprint\", 2);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tp.log.error(\"Fingerprint required via --fingerprint\");\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst actualFingerprint = fingerprintPublicKey(publicKey);\n\t\t\t\tif (actualFingerprint !== fingerprint) {\n\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\temitJsonError(\n\t\t\t\t\t\t\t\"fingerprint_mismatch\",\n\t\t\t\t\t\t\t\"Fingerprint does not match the provided public key\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tp.log.error(\"Fingerprint does not match the provided public key\");\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst enrollment = await coordinatorEnrollDeviceAction({\n\t\t\t\t\tgroupId,\n\t\t\t\t\tdeviceId,\n\t\t\t\t\tfingerprint,\n\t\t\t\t\tpublicKey,\n\t\t\t\t\tdisplayName: opts.name?.trim() || null,\n\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t});\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(enrollment, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem coordinator enroll-device\");\n\t\t\t\tp.log.success(`Enrolled ${deviceId.trim()} in ${groupId.trim()}`);\n\t\t\t\tp.outro(String(enrollment.display_name ?? enrollment.device_id ?? deviceId.trim()));\n\t\t\t} catch (err) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"enroll_failed\", err instanceof Error ? err.message : String(err));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t},\n\t);\n\tcmd.addCommand(enrollDeviceCmd);\n\n\t// ---- list-devices ----\n\n\tconst listDevicesCmd = new Command(\"list-devices\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"List enrolled devices in a local coordinator group\")\n\t\t.argument(\"<group>\", \"group id\")\n\t\t.option(\"--include-disabled\", \"include disabled devices\");\n\taddDbOption(listDevicesCmd);\n\taddJsonOption(listDevicesCmd);\n\tlistDevicesCmd.action(\n\t\tasync (\n\t\t\tgroupId: string,\n\t\t\topts: { includeDisabled?: boolean; db?: string; dbPath?: string; json?: boolean },\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst rows = await coordinatorListDevicesAction({\n\t\t\t\t\tgroupId,\n\t\t\t\t\tincludeDisabled: opts.includeDisabled === true,\n\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t});\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(rows, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem coordinator list-devices\");\n\t\t\t\tif (rows.length === 0) {\n\t\t\t\t\tp.outro(`No enrolled devices for ${groupId.trim()}`);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (const row of rows) {\n\t\t\t\t\tconst label =\n\t\t\t\t\t\tString(row.display_name ?? row.device_id ?? \"\").trim() || String(row.device_id ?? \"\");\n\t\t\t\t\tconst enabled = Number(row.enabled ?? 1) === 1 ? \"enabled\" : \"disabled\";\n\t\t\t\t\tp.log.message(`- ${label} (${String(row.device_id ?? \"\")}) ${enabled}`);\n\t\t\t\t}\n\t\t\t\tp.outro(`${rows.length} device(s)`);\n\t\t\t} catch (err) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"list_devices_failed\", err instanceof Error ? err.message : String(err));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t},\n\t);\n\tcmd.addCommand(listDevicesCmd);\n\n\t// ---- rename-device ----\n\n\tconst renameDeviceCmd = new Command(\"rename-device\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Rename an enrolled device in the local coordinator store\")\n\t\t.argument(\"<group>\", \"group id\")\n\t\t.argument(\"<device-id>\", \"device id\")\n\t\t.requiredOption(\"--name <name>\", \"display name\");\n\taddDbOption(renameDeviceCmd);\n\taddJsonOption(renameDeviceCmd);\n\trenameDeviceCmd.action(\n\t\tasync (\n\t\t\tgroupId: string,\n\t\t\tdeviceId: string,\n\t\t\topts: { name: string; db?: string; dbPath?: string; json?: boolean },\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst result = await coordinatorRenameDeviceAction({\n\t\t\t\t\tgroupId,\n\t\t\t\t\tdeviceId,\n\t\t\t\t\tdisplayName: opts.name.trim(),\n\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t});\n\t\t\t\tif (!result) {\n\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\temitJsonError(\"device_not_found\", `Device not found: ${deviceId.trim()}`);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tp.log.error(`Device not found: ${deviceId.trim()}`);\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem coordinator rename-device\");\n\t\t\t\tp.log.success(`Renamed ${deviceId.trim()} in ${groupId.trim()}`);\n\t\t\t\tp.outro(String(result.display_name ?? result.device_id ?? deviceId.trim()));\n\t\t\t} catch (err) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"rename_failed\", err instanceof Error ? err.message : String(err));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t},\n\t);\n\tcmd.addCommand(renameDeviceCmd);\n\n\t// ---- disable-device ----\n\n\tconst disableDeviceCmd = new Command(\"disable-device\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Disable an enrolled device in the local coordinator store\")\n\t\t.argument(\"<group>\", \"group id\")\n\t\t.argument(\"<device-id>\", \"device id\");\n\taddDbOption(disableDeviceCmd);\n\taddJsonOption(disableDeviceCmd);\n\tdisableDeviceCmd.action(\n\t\tasync (\n\t\t\tgroupId: string,\n\t\t\tdeviceId: string,\n\t\t\topts: { db?: string; dbPath?: string; json?: boolean },\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst ok = await coordinatorDisableDeviceAction({\n\t\t\t\t\tgroupId,\n\t\t\t\t\tdeviceId,\n\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t});\n\t\t\t\tif (!ok) {\n\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\temitJsonError(\"device_not_found\", `Device not found: ${deviceId.trim()}`);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tp.log.error(`Device not found: ${deviceId.trim()}`);\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\tJSON.stringify(\n\t\t\t\t\t\t\t{ ok: true, group_id: groupId.trim(), device_id: deviceId.trim() },\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t2,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem coordinator disable-device\");\n\t\t\t\tp.log.success(`Disabled ${deviceId.trim()} in ${groupId.trim()}`);\n\t\t\t\tp.outro(\"disabled\");\n\t\t\t} catch (err) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"disable_failed\", err instanceof Error ? err.message : String(err));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t},\n\t);\n\tcmd.addCommand(disableDeviceCmd);\n\n\t// ---- remove-device ----\n\n\tconst removeDeviceCmd = new Command(\"remove-device\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Remove an enrolled device from the local coordinator store\")\n\t\t.argument(\"<group>\", \"group id\")\n\t\t.argument(\"<device-id>\", \"device id\");\n\taddDbOption(removeDeviceCmd);\n\taddJsonOption(removeDeviceCmd);\n\tremoveDeviceCmd.action(\n\t\tasync (\n\t\t\tgroupId: string,\n\t\t\tdeviceId: string,\n\t\t\topts: { db?: string; dbPath?: string; json?: boolean },\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst ok = await coordinatorRemoveDeviceAction({\n\t\t\t\t\tgroupId,\n\t\t\t\t\tdeviceId,\n\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t});\n\t\t\t\tif (!ok) {\n\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\temitJsonError(\"device_not_found\", `Device not found: ${deviceId.trim()}`);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tp.log.error(`Device not found: ${deviceId.trim()}`);\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\tJSON.stringify(\n\t\t\t\t\t\t\t{ ok: true, group_id: groupId.trim(), device_id: deviceId.trim() },\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t2,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem coordinator remove-device\");\n\t\t\t\tp.log.success(`Removed ${deviceId.trim()} from ${groupId.trim()}`);\n\t\t\t\tp.outro(\"removed\");\n\t\t\t} catch (err) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"remove_failed\", err instanceof Error ? err.message : String(err));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t},\n\t);\n\tcmd.addCommand(removeDeviceCmd);\n\n\t// ---- serve (coordinator relay) ----\n\n\tconst coordServeCmd = new Command(\"serve\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Run the coordinator relay HTTP server\")\n\t\t.option(\"--coordinator-host <host>\", \"bind host\")\n\t\t.option(\"--coordinator-port <port>\", \"bind port\");\n\t// Coordinator serve uses its own DB, not the main codemem DB\n\tcoordServeCmd.addOption(new Option(\"-d, --db-path <path>\", \"coordinator database path\"));\n\tcoordServeCmd.addOption(new Option(\"--db <path>\", \"coordinator database path\").hideHelp());\n\t// Hidden host/port aliases for backwards compat\n\tcoordServeCmd.addOption(new Option(\"--host <host>\", \"bind host\").hideHelp());\n\tcoordServeCmd.addOption(new Option(\"--port <port>\", \"bind port\").hideHelp());\n\tcoordServeCmd.action(\n\t\tasync (opts: {\n\t\t\tdb?: string;\n\t\t\tdbPath?: string;\n\t\t\tcoordinatorHost?: string;\n\t\t\tcoordinatorPort?: string;\n\t\t\thost?: string;\n\t\t\tport?: string;\n\t\t}) => {\n\t\t\t// Prefer canonical flags; fall back to hidden aliases; then defaults.\n\t\t\t// Defaults must NOT be set on the Option definitions, otherwise Commander\n\t\t\t// populates them and ?? cannot distinguish \"explicitly passed\" from \"default\".\n\t\t\tconst host = String(opts.coordinatorHost ?? opts.host ?? \"127.0.0.1\").trim() || \"127.0.0.1\";\n\t\t\tconst port = Number.parseInt(String(opts.coordinatorPort ?? opts.port ?? \"7347\"), 10);\n\t\t\tconst dbPath = resolveDbOpt(opts) ?? DEFAULT_COORDINATOR_DB_PATH;\n\t\t\tconst app = createBetterSqliteCoordinatorApp({ dbPath });\n\t\t\tp.intro(\"codemem coordinator serve\");\n\t\t\tp.log.success(`Coordinator listening at http://${host}:${port}`);\n\t\t\tp.log.info(`DB: ${dbPath}`);\n\t\t\thonoServe({ fetch: app.fetch, hostname: host, port });\n\t\t},\n\t);\n\tcmd.addCommand(coordServeCmd);\n\n\t// ---- list-bootstrap-grants ----\n\n\tconst listBootstrapGrantsCmd = new Command(\"list-bootstrap-grants\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"List bootstrap grants for a coordinator group\")\n\t\t.argument(\"<group>\", \"group id\")\n\t\t.option(\"--remote-url <url>\", \"remote coordinator URL override\")\n\t\t.option(\"--admin-secret <secret>\", \"remote coordinator admin secret override\");\n\taddDbOption(listBootstrapGrantsCmd);\n\taddJsonOption(listBootstrapGrantsCmd);\n\tlistBootstrapGrantsCmd.action(\n\t\tasync (\n\t\t\tgroupId: string,\n\t\t\topts: {\n\t\t\t\tdb?: string;\n\t\t\t\tdbPath?: string;\n\t\t\t\tremoteUrl?: string;\n\t\t\t\tadminSecret?: string;\n\t\t\t\tjson?: boolean;\n\t\t\t},\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst rows = await coordinatorListBootstrapGrantsAction({\n\t\t\t\t\tgroupId,\n\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t\tremoteUrl: opts.remoteUrl?.trim() || null,\n\t\t\t\t\tadminSecret: opts.adminSecret?.trim() || null,\n\t\t\t\t});\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(rows, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem coordinator list-bootstrap-grants\");\n\t\t\t\tif (rows.length === 0) {\n\t\t\t\t\tp.outro(`No bootstrap grants for ${groupId.trim()}`);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (const row of rows) {\n\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t`- ${row.grant_id} seed=${row.seed_device_id} worker=${row.worker_device_id} expires=${row.expires_at} revoked=${row.revoked_at ?? \"no\"}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tp.outro(`${rows.length} bootstrap grant(s)`);\n\t\t\t} catch (err) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\n\t\t\t\t\t\t\"list_bootstrap_grants_failed\",\n\t\t\t\t\t\terr instanceof Error ? err.message : String(err),\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t},\n\t);\n\tcmd.addCommand(listBootstrapGrantsCmd);\n\n\t// ---- revoke-bootstrap-grant ----\n\n\tconst revokeBootstrapGrantCmd = new Command(\"revoke-bootstrap-grant\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Revoke a bootstrap grant\")\n\t\t.argument(\"<grant-id>\", \"bootstrap grant id\")\n\t\t.option(\"--remote-url <url>\", \"remote coordinator URL override\")\n\t\t.option(\"--admin-secret <secret>\", \"remote coordinator admin secret override\");\n\taddDbOption(revokeBootstrapGrantCmd);\n\taddJsonOption(revokeBootstrapGrantCmd);\n\trevokeBootstrapGrantCmd.action(\n\t\tasync (\n\t\t\tgrantId: string,\n\t\t\topts: {\n\t\t\t\tdb?: string;\n\t\t\t\tdbPath?: string;\n\t\t\t\tremoteUrl?: string;\n\t\t\t\tadminSecret?: string;\n\t\t\t\tjson?: boolean;\n\t\t\t},\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst ok = await coordinatorRevokeBootstrapGrantAction({\n\t\t\t\t\tgrantId,\n\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t\tremoteUrl: opts.remoteUrl?.trim() || null,\n\t\t\t\t\tadminSecret: opts.adminSecret?.trim() || null,\n\t\t\t\t});\n\t\t\t\tif (!ok) {\n\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\temitJsonError(\"grant_not_found\", `Bootstrap grant not found: ${grantId.trim()}`);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tp.log.error(`Bootstrap grant not found: ${grantId.trim()}`);\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify({ ok: true, grant_id: grantId.trim() }, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem coordinator revoke-bootstrap-grant\");\n\t\t\t\tp.log.success(`Revoked ${grantId.trim()}`);\n\t\t\t\tp.outro(\"revoked\");\n\t\t\t} catch (err) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"revoke_failed\", err instanceof Error ? err.message : String(err));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t},\n\t);\n\tcmd.addCommand(revokeBootstrapGrantCmd);\n\n\t// ---- create-invite ----\n\n\tconst createInviteCmd = new Command(\"create-invite\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Create a coordinator team invite\")\n\t\t.argument(\"[group]\", \"group id\")\n\t\t.option(\"--group <group>\", \"group id\")\n\t\t.option(\"--coordinator-url <url>\", \"coordinator URL override\")\n\t\t.option(\"--policy <policy>\", \"invite policy\", \"auto_admit\")\n\t\t.option(\"--ttl-hours <hours>\", \"invite TTL hours\", \"24\")\n\t\t.option(\"--remote-url <url>\", \"remote coordinator URL override\")\n\t\t.option(\"--admin-secret <secret>\", \"remote coordinator admin secret override\");\n\taddDbOption(createInviteCmd);\n\taddJsonOption(createInviteCmd);\n\tcreateInviteCmd.action(\n\t\tasync (\n\t\t\tgroupArg: string | undefined,\n\t\t\topts: {\n\t\t\t\tgroup?: string;\n\t\t\t\tcoordinatorUrl?: string;\n\t\t\t\tpolicy?: string;\n\t\t\t\tttlHours?: string;\n\t\t\t\tdb?: string;\n\t\t\t\tdbPath?: string;\n\t\t\t\tremoteUrl?: string;\n\t\t\t\tadminSecret?: string;\n\t\t\t\tjson?: boolean;\n\t\t\t},\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst ttlHours = Number.parseInt(String(opts.ttlHours ?? \"24\"), 10);\n\t\t\t\tconst groupId = String(opts.group ?? \"\").trim() || String(groupArg ?? \"\").trim();\n\t\t\t\tconst result = await coordinatorCreateInviteAction({\n\t\t\t\t\tgroupId,\n\t\t\t\t\tcoordinatorUrl: opts.coordinatorUrl?.trim() || null,\n\t\t\t\t\tpolicy: String(opts.policy ?? \"auto_admit\").trim(),\n\t\t\t\t\tttlHours,\n\t\t\t\t\tcreatedBy: null,\n\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t\tremoteUrl: opts.remoteUrl?.trim() || null,\n\t\t\t\t\tadminSecret: opts.adminSecret?.trim() || null,\n\t\t\t\t});\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem coordinator create-invite\");\n\t\t\t\tp.log.success(`Invite created for ${groupId}`);\n\t\t\t\tif (typeof result.link === \"string\") p.log.message(`- link: ${result.link}`);\n\t\t\t\tif (typeof result.encoded === \"string\") p.log.message(`- invite: ${result.encoded}`);\n\t\t\t\tfor (const warning of Array.isArray(result.warnings) ? result.warnings : []) {\n\t\t\t\t\tp.log.warn(String(warning));\n\t\t\t\t}\n\t\t\t\tp.outro(\"Invite ready\");\n\t\t\t} catch (err) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"create_invite_failed\", err instanceof Error ? err.message : String(err));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t},\n\t);\n\tcmd.addCommand(createInviteCmd);\n\n\t// ---- import-invite ----\n\n\tconst importInviteCmd = new Command(\"import-invite\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Import a coordinator invite\")\n\t\t.argument(\"<invite>\", \"invite value or link\")\n\t\t.option(\"--keys-dir <path>\", \"keys directory\");\n\taddDbOption(importInviteCmd);\n\taddConfigOption(importInviteCmd);\n\taddJsonOption(importInviteCmd);\n\timportInviteCmd.action(\n\t\tasync (\n\t\t\tinvite: string,\n\t\t\topts: {\n\t\t\t\tdb?: string;\n\t\t\t\tdbPath?: string;\n\t\t\t\tkeysDir?: string;\n\t\t\t\tconfig?: string;\n\t\t\t\tjson?: boolean;\n\t\t\t},\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst result = await coordinatorImportInviteAction({\n\t\t\t\t\tinviteValue: invite,\n\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t\tkeysDir: opts.keysDir ?? null,\n\t\t\t\t\tconfigPath: opts.config ?? null,\n\t\t\t\t});\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem coordinator import-invite\");\n\t\t\t\tp.log.success(`Invite imported for ${result.group_id}`);\n\t\t\t\tp.log.message(`- coordinator: ${result.coordinator_url}`);\n\t\t\t\tp.log.message(`- status: ${result.status}`);\n\t\t\t\tp.outro(\"Coordinator config updated\");\n\t\t\t} catch (err) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"import_invite_failed\", err instanceof Error ? err.message : String(err));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t},\n\t);\n\tcmd.addCommand(importInviteCmd);\n\n\t// ---- list-join-requests ----\n\n\tconst listJoinRequestsCmd = new Command(\"list-join-requests\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"List pending coordinator join requests\")\n\t\t.argument(\"[group]\", \"group id\")\n\t\t.option(\"--group <group>\", \"group id\")\n\t\t.option(\"--remote-url <url>\", \"remote coordinator URL override\")\n\t\t.option(\"--admin-secret <secret>\", \"remote coordinator admin secret override\");\n\taddDbOption(listJoinRequestsCmd);\n\taddJsonOption(listJoinRequestsCmd);\n\tlistJoinRequestsCmd.action(\n\t\tasync (\n\t\t\tgroupArg: string | undefined,\n\t\t\topts: {\n\t\t\t\tgroup?: string;\n\t\t\t\tdb?: string;\n\t\t\t\tdbPath?: string;\n\t\t\t\tremoteUrl?: string;\n\t\t\t\tadminSecret?: string;\n\t\t\t\tjson?: boolean;\n\t\t\t},\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst groupId = String(opts.group ?? \"\").trim() || String(groupArg ?? \"\").trim();\n\t\t\t\tconst rows = await coordinatorListJoinRequestsAction({\n\t\t\t\t\tgroupId,\n\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t\tremoteUrl: opts.remoteUrl?.trim() || null,\n\t\t\t\t\tadminSecret: opts.adminSecret?.trim() || null,\n\t\t\t\t});\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(rows, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem coordinator list-join-requests\");\n\t\t\t\tif (rows.length === 0) {\n\t\t\t\t\tp.outro(`No pending join requests for ${groupId}`);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (const row of rows) {\n\t\t\t\t\tconst displayName = row.display_name || row.device_id;\n\t\t\t\t\tp.log.message(`- ${displayName} (${row.device_id}) request_id=${row.request_id}`);\n\t\t\t\t}\n\t\t\t\tp.outro(`${rows.length} pending join request(s)`);\n\t\t\t} catch (err) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\n\t\t\t\t\t\t\"list_join_requests_failed\",\n\t\t\t\t\t\terr instanceof Error ? err.message : String(err),\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t},\n\t);\n\tcmd.addCommand(listJoinRequestsCmd);\n\n\t// ---- approve-join-request / deny-join-request ----\n\n\tfunction addReviewJoinRequestCommand(\n\t\tname: \"approve-join-request\" | \"deny-join-request\",\n\t\tapprove: boolean,\n\t) {\n\t\tconst reviewCmd = new Command(name)\n\t\t\t.configureHelp(helpStyle)\n\t\t\t.description(`${approve ? \"Approve\" : \"Deny\"} a coordinator join request`)\n\t\t\t.argument(\"<request-id>\", \"join request id\")\n\t\t\t.option(\"--remote-url <url>\", \"remote coordinator URL override\")\n\t\t\t.option(\"--admin-secret <secret>\", \"remote coordinator admin secret override\");\n\t\taddDbOption(reviewCmd);\n\t\taddJsonOption(reviewCmd);\n\t\treviewCmd.action(\n\t\t\tasync (\n\t\t\t\trequestId: string,\n\t\t\t\topts: {\n\t\t\t\t\tdb?: string;\n\t\t\t\t\tdbPath?: string;\n\t\t\t\t\tremoteUrl?: string;\n\t\t\t\t\tadminSecret?: string;\n\t\t\t\t\tjson?: boolean;\n\t\t\t\t},\n\t\t\t) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst request = await coordinatorReviewJoinRequestAction({\n\t\t\t\t\t\trequestId: requestId.trim(),\n\t\t\t\t\t\tapprove,\n\t\t\t\t\t\treviewedBy: null,\n\t\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t\t\tremoteUrl: opts.remoteUrl?.trim() || null,\n\t\t\t\t\t\tadminSecret: opts.adminSecret?.trim() || null,\n\t\t\t\t\t});\n\t\t\t\t\tif (!request) {\n\t\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\t\temitJsonError(\n\t\t\t\t\t\t\t\t\"join_request_not_found\",\n\t\t\t\t\t\t\t\t`Join request not found: ${requestId.trim()}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tp.log.error(`Join request not found: ${requestId.trim()}`);\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\tconsole.log(JSON.stringify(request, null, 2));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tp.intro(`codemem coordinator ${name}`);\n\t\t\t\t\tp.log.success(`${approve ? \"Approved\" : \"Denied\"} join request ${requestId.trim()}`);\n\t\t\t\t\tp.outro(String(request.status ?? \"updated\"));\n\t\t\t\t} catch (err) {\n\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\temitJsonError(\"review_failed\", err instanceof Error ? err.message : String(err));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\t\tcmd.addCommand(reviewCmd);\n\t}\n\n\taddReviewJoinRequestCommand(\"approve-join-request\", true);\n\taddReviewJoinRequestCommand(\"deny-join-request\", false);\n\n\treturn cmd;\n}\n\n/** Canonical top-level coordinator command for registration in index.ts. */\nexport const coordinatorCommand = buildCoordinatorCommand();\n","import { statSync } from \"node:fs\";\nimport * as p from \"@clack/prompts\";\nimport {\n\taiBackfillStructuredContent,\n\tbackfillMemoryDedupKeys,\n\tbackfillNarrativeFromBody,\n\tbackfillTagsText,\n\tconnect,\n\tdeactivateLowSignalMemories,\n\tdeactivateLowSignalObservations,\n\tdedupNearDuplicateMemories,\n\tgetRawEventStatus,\n\tinitDatabase,\n\tMemoryStore,\n\tplanReplicationOpsAgePrune,\n\tpruneReplicationOpsUntilCaughtUp,\n\trawEventsGate,\n\tresolveDbPath,\n\tresolveProject,\n\tretryRawEventFailures,\n\tvacuumDatabase,\n} from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddDbOption,\n\taddJsonOption,\n\ttype DbOpts,\n\ttype JsonOpts,\n\tresolveDbOpt,\n} from \"../shared-options.js\";\n\nfunction formatBytes(bytes: number): string {\n\tif (bytes < 1024) return `${bytes} B`;\n\tif (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction parseOptionalPositiveInt(value: string | undefined): number | undefined {\n\tif (!value) return undefined;\n\tconst parsed = Number.parseInt(value, 10);\n\tif (!Number.isFinite(parsed) || parsed <= 0) {\n\t\tthrow new Error(`invalid positive integer: ${value}`);\n\t}\n\treturn parsed;\n}\n\nfunction parseKindsCsv(value: string | undefined): string[] | undefined {\n\tif (!value) return undefined;\n\tconst kinds = value\n\t\t.split(\",\")\n\t\t.map((kind) => kind.trim())\n\t\t.filter((kind) => kind.length > 0);\n\treturn kinds.length > 0 ? kinds : undefined;\n}\n\nfunction estimateReplicationOpsBytes(db: ReturnType<typeof connect>): number {\n\ttry {\n\t\tconst row = db\n\t\t\t.prepare(\n\t\t\t\t`SELECT COALESCE(SUM(pgsize), 0) AS total_bytes\n\t\t\t\t FROM dbstat\n\t\t\t\t WHERE name = 'replication_ops'\n\t\t\t\t OR name LIKE 'idx_replication_ops_%'\n\t\t\t\t OR name LIKE 'sqlite_autoindex_replication_ops_%'`,\n\t\t\t)\n\t\t\t.get() as { total_bytes?: number } | undefined;\n\t\treturn Number(row?.total_bytes ?? 0);\n\t} catch {\n\t\treturn 0;\n\t}\n}\n\nexport const dbCommand = new Command(\"db\")\n\t.configureHelp(helpStyle)\n\t.description(\"Database maintenance\");\n\n// --- db init ---\nconst initCmd = new Command(\"init\")\n\t.configureHelp(helpStyle)\n\t.description(\"Create or verify the SQLite database and schema\");\naddDbOption(initCmd);\ninitCmd.action((opts: DbOpts) => {\n\tconst result = initDatabase(resolveDbOpt(opts));\n\tp.intro(\"codemem db init\");\n\tp.log.success(`Database ready: ${result.path}`);\n\tp.outro(`Size: ${result.sizeBytes.toLocaleString()} bytes`);\n});\ndbCommand.addCommand(initCmd);\n\n// --- db vacuum ---\nconst vacuumCmd = new Command(\"vacuum\")\n\t.configureHelp(helpStyle)\n\t.description(\"Run VACUUM on the SQLite database\");\naddDbOption(vacuumCmd);\nvacuumCmd.action((opts: DbOpts) => {\n\tconst result = vacuumDatabase(resolveDbOpt(opts));\n\tp.intro(\"codemem db vacuum\");\n\tp.log.success(`Vacuumed: ${result.path}`);\n\tp.outro(`Size: ${result.sizeBytes.toLocaleString()} bytes`);\n});\ndbCommand.addCommand(vacuumCmd);\n\n// --- db prune-replication-ops ---\nconst pruneReplCmd = new Command(\"prune-replication-ops\")\n\t.configureHelp(helpStyle)\n\t.description(\n\t\t\"Prune replication op history with approximate oldest-first retention, dry-run, and progress reporting\",\n\t)\n\t.option(\"--dry-run\", \"show current size/targets without deleting\")\n\t.option(\"--max-age-days <days>\", \"retention age threshold in days\", \"30\")\n\t.option(\"--max-size-mb <mb>\", \"target replication log budget in MB\", \"512\")\n\t.option(\"--batch-ops <n>\", \"max ops deleted per batch\", \"5000\")\n\t.option(\"--batch-runtime-ms <ms>\", \"max runtime per batch in ms\", \"2000\")\n\t.option(\"--vacuum\", \"run VACUUM explicitly after prune completes\");\naddDbOption(pruneReplCmd);\npruneReplCmd.action(\n\t(\n\t\topts: DbOpts & {\n\t\t\tdryRun?: boolean;\n\t\t\tmaxAgeDays: string;\n\t\t\tmaxSizeMb: string;\n\t\t\tbatchOps: string;\n\t\t\tbatchRuntimeMs: string;\n\t\t\tvacuum?: boolean;\n\t\t},\n\t) => {\n\t\tconst dbPath = resolveDbPath(resolveDbOpt(opts));\n\t\tconst db = connect(dbPath);\n\t\tlet dbOpen = true;\n\t\ttry {\n\t\t\tconst maxAgeDays = Number.parseInt(opts.maxAgeDays, 10) || 30;\n\t\t\tconst maxSizeMb = Number.parseInt(opts.maxSizeMb, 10) || 512;\n\t\t\tconst batchOps = Number.parseInt(opts.batchOps, 10) || 5000;\n\t\t\tconst batchRuntimeMs = Number.parseInt(opts.batchRuntimeMs, 10) || 2000;\n\t\t\tconst beforeBytes = estimateReplicationOpsBytes(db);\n\t\t\tp.intro(\"codemem db prune-replication-ops\");\n\t\t\tp.log.info(`Replication ops size: ${formatBytes(beforeBytes)}`);\n\t\t\tp.log.info(\n\t\t\t\t`Policy: approximately prune oldest-first toward <= ${maxSizeMb} MB while removing history older than ${maxAgeDays} day(s), subject to per-pass batch/runtime limits`,\n\t\t\t);\n\t\t\tconst agePlan = planReplicationOpsAgePrune(db, maxAgeDays, batchOps);\n\t\t\tif (agePlan.candidate_ops > 0) {\n\t\t\t\tp.log.info(\n\t\t\t\t\t`Age pass plan: ${agePlan.candidate_ops.toLocaleString()} ops, ~${formatBytes(agePlan.estimated_candidate_bytes)} in ~${agePlan.estimated_batches.toLocaleString()} batch(es), cutoff ${agePlan.cutoff_cursor}`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tp.log.info(\"Age pass plan: no ops older than cutoff\");\n\t\t\t}\n\n\t\t\tif (opts.dryRun) {\n\t\t\t\tp.outro(\"Dry run only; no changes made\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst loopResult = pruneReplicationOpsUntilCaughtUp(db, {\n\t\t\t\tmaxAgeDays,\n\t\t\t\tmaxSizeBytes: maxSizeMb * 1024 * 1024,\n\t\t\t\tmaxDeleteOps: batchOps,\n\t\t\t\tmaxRuntimeMs: batchRuntimeMs,\n\t\t\t\tonPass: (pass) => {\n\t\t\t\t\tif (pass.deleted === 0 && !pass.stoppedByBudget) return;\n\t\t\t\t\tconst suffix = pass.stoppedByBudget ? \" (budget-limited)\" : \"\";\n\t\t\t\t\tp.log.step(\n\t\t\t\t\t\t`Pass ${pass.passNumber}: deleted ${pass.deleted.toLocaleString()} ops, remaining size ~${formatBytes(pass.afterBytes)}${suffix}`,\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tp.log.info(`Deleted ops: ${loopResult.totalDeleted.toLocaleString()}`);\n\t\t\tp.log.info(\n\t\t\t\t`Estimated replication ops size after prune: ${formatBytes(loopResult.afterBytes)} (approximate)`,\n\t\t\t);\n\t\t\tif (loopResult.lastFloor) p.log.info(`Retained floor: ${loopResult.lastFloor}`);\n\t\t\tif (loopResult.stoppedByBudget) {\n\t\t\t\tp.log.warn(\n\t\t\t\t\t\"Prune stopped because the current batch/runtime budget was exhausted before retention caught up. Re-run with higher --batch-ops or --batch-runtime-ms for faster catch-up.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (opts.vacuum) {\n\t\t\t\tp.log.step(\"Running VACUUM as requested...\");\n\t\t\t\tdb.close();\n\t\t\t\tdbOpen = false;\n\t\t\t\tconst vacuumed = vacuumDatabase(dbPath);\n\t\t\t\tp.outro(`Done. VACUUM complete. File size is now ${formatBytes(vacuumed.sizeBytes)}.`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.outro(\n\t\t\t\t\"Done. Retention is approximate oldest-first pruning. SQLite file size may not shrink until you run `codemem db vacuum` explicitly (or re-run this command with --vacuum).\",\n\t\t\t);\n\t\t} finally {\n\t\t\tif (dbOpen) db.close();\n\t\t}\n\t},\n);\ndbCommand.addCommand(pruneReplCmd);\n\n// --- db raw-events-status ---\nconst rawEventsStatusCmd = new Command(\"raw-events-status\")\n\t.configureHelp(helpStyle)\n\t.description(\"Show pending raw-event backlog by source stream\")\n\t.option(\"-n, --limit <n>\", \"max rows to show\", \"25\");\naddDbOption(rawEventsStatusCmd);\naddJsonOption(rawEventsStatusCmd);\nrawEventsStatusCmd.action((opts: DbOpts & JsonOpts & { limit: string }) => {\n\tconst result = getRawEventStatus(resolveDbOpt(opts), Number.parseInt(opts.limit, 10) || 25);\n\tif (opts.json) {\n\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\treturn;\n\t}\n\tp.intro(\"codemem db raw-events-status\");\n\tp.log.info(\n\t\t`Totals: ${result.totals.pending.toLocaleString()} pending across ${result.totals.sessions.toLocaleString()} session(s)`,\n\t);\n\tif (result.items.length === 0) {\n\t\tp.outro(\"No pending raw events\");\n\t\treturn;\n\t}\n\tfor (const item of result.items) {\n\t\tp.log.message(\n\t\t\t`${item.source}:${item.stream_id} pending=${Math.max(0, item.last_received_event_seq - item.last_flushed_event_seq)} ` +\n\t\t\t\t`received=${item.last_received_event_seq} flushed=${item.last_flushed_event_seq} project=${item.project ?? \"\"}`,\n\t\t);\n\t}\n\tp.outro(\"done\");\n});\ndbCommand.addCommand(rawEventsStatusCmd);\n\n// --- db raw-events-retry ---\nconst rawEventsRetryCmd = new Command(\"raw-events-retry\")\n\t.configureHelp(helpStyle)\n\t.description(\"Requeue failed raw-event flush batches\")\n\t.option(\"-n, --limit <n>\", \"max failed batches to requeue\", \"25\");\naddDbOption(rawEventsRetryCmd);\nrawEventsRetryCmd.action((opts: DbOpts & { limit: string }) => {\n\tconst result = retryRawEventFailures(resolveDbOpt(opts), Number.parseInt(opts.limit, 10) || 25);\n\tp.intro(\"codemem db raw-events-retry\");\n\tp.outro(`Requeued ${result.retried.toLocaleString()} failed batch(es)`);\n});\ndbCommand.addCommand(rawEventsRetryCmd);\n\n// --- db raw-events-gate ---\nconst rawEventsGateCmd = new Command(\"raw-events-gate\")\n\t.configureHelp(helpStyle)\n\t.description(\"Validate raw-event reliability thresholds (non-zero exit on failure)\")\n\t.option(\"--min-flush-success-rate <rate>\", \"minimum flush success rate\", \"0.95\")\n\t.option(\"--max-dropped-event-rate <rate>\", \"maximum dropped event rate\", \"0.05\")\n\t.option(\"--min-session-boundary-accuracy <rate>\", \"minimum session boundary accuracy\", \"0.9\")\n\t.option(\"--window-hours <hours>\", \"lookback window in hours\", \"24\");\naddDbOption(rawEventsGateCmd);\naddJsonOption(rawEventsGateCmd);\nrawEventsGateCmd.action(\n\t(\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\tminFlushSuccessRate: string;\n\t\t\t\tmaxDroppedEventRate: string;\n\t\t\t\tminSessionBoundaryAccuracy: string;\n\t\t\t\twindowHours: string;\n\t\t\t},\n\t) => {\n\t\tconst result = rawEventsGate(resolveDbOpt(opts), {\n\t\t\tminFlushSuccessRate: Number.parseFloat(opts.minFlushSuccessRate),\n\t\t\tmaxDroppedEventRate: Number.parseFloat(opts.maxDroppedEventRate),\n\t\t\tminSessionBoundaryAccuracy: Number.parseFloat(opts.minSessionBoundaryAccuracy),\n\t\t\twindowHours: Number.parseFloat(opts.windowHours),\n\t\t});\n\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\tif (!result.passed) process.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\n\t\tp.intro(\"codemem db raw-events-gate\");\n\t\tp.log.info(\n\t\t\t[\n\t\t\t\t`flush_success_rate: ${result.metrics.rates.flush_success_rate.toFixed(4)}`,\n\t\t\t\t`dropped_event_rate: ${result.metrics.rates.dropped_event_rate.toFixed(4)}`,\n\t\t\t\t`session_boundary_accuracy: ${result.metrics.rates.session_boundary_accuracy.toFixed(4)}`,\n\t\t\t\t`window_hours: ${result.metrics.window_hours ?? \"all\"}`,\n\t\t\t].join(\"\\n\"),\n\t\t);\n\n\t\tif (result.passed) {\n\t\t\tp.outro(\"reliability gate passed\");\n\t\t} else {\n\t\t\tfor (const f of result.failures) {\n\t\t\t\tp.log.error(f);\n\t\t\t}\n\t\t\tp.outro(\"reliability gate FAILED\");\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t},\n);\ndbCommand.addCommand(rawEventsGateCmd);\n\n// --- db rename-project ---\nconst renameProjectCmd = new Command(\"rename-project\")\n\t.configureHelp(helpStyle)\n\t.description(\"Rename a project across sessions and related tables\")\n\t.argument(\"<old-name>\", \"current project name\")\n\t.argument(\"<new-name>\", \"new project name\")\n\t.option(\"--apply\", \"apply changes (default is dry-run)\");\naddDbOption(renameProjectCmd);\nrenameProjectCmd.action((oldName: string, newName: string, opts: DbOpts & { apply?: boolean }) => {\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\ttry {\n\t\tconst dryRun = !opts.apply;\n\t\tconst escapedOld = oldName.replace(/%/g, \"\\\\%\").replace(/_/g, \"\\\\_\");\n\t\tconst suffixPattern = `%/${escapedOld}`;\n\t\tconst tables = [\"sessions\", \"raw_event_sessions\"] as const;\n\t\tconst counts: Record<string, number> = {};\n\t\tconst run = () => {\n\t\t\tfor (const table of tables) {\n\t\t\t\tconst rows = store.db\n\t\t\t\t\t.prepare(\n\t\t\t\t\t\t`SELECT COUNT(*) as cnt FROM ${table} WHERE project = ? OR project LIKE ? ESCAPE '\\\\'`,\n\t\t\t\t\t)\n\t\t\t\t\t.get(oldName, suffixPattern) as { cnt: number };\n\t\t\t\tcounts[table] = rows.cnt;\n\t\t\t\tif (!dryRun && rows.cnt > 0) {\n\t\t\t\t\tstore.db\n\t\t\t\t\t\t.prepare(`UPDATE ${table} SET project = ? WHERE project = ?`)\n\t\t\t\t\t\t.run(newName, oldName);\n\t\t\t\t\tstore.db\n\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t`UPDATE ${table} SET project = ? WHERE project LIKE ? ESCAPE '\\\\' AND project != ?`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.run(newName, suffixPattern, newName);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tif (dryRun) {\n\t\t\trun();\n\t\t} else {\n\t\t\tstore.db.transaction(run)();\n\t\t}\n\t\tconst action = dryRun ? \"Will rename\" : \"Renamed\";\n\t\tp.intro(\"codemem db rename-project\");\n\t\tp.log.info(`${action} ${oldName} → ${newName}`);\n\t\tp.log.info(\n\t\t\t[`Sessions: ${counts.sessions}`, `Raw event sessions: ${counts.raw_event_sessions}`].join(\n\t\t\t\t\"\\n\",\n\t\t\t),\n\t\t);\n\t\tif (dryRun) {\n\t\t\tp.outro(\"Pass --apply to execute\");\n\t\t} else {\n\t\t\tp.outro(\"done\");\n\t\t}\n\t} finally {\n\t\tstore.close();\n\t}\n});\ndbCommand.addCommand(renameProjectCmd);\n\n// --- db normalize-projects ---\nconst normalizeProjectsCmd = new Command(\"normalize-projects\")\n\t.configureHelp(helpStyle)\n\t.description(\"Normalize path-like project identifiers to their basename\")\n\t.option(\"--apply\", \"apply changes (default is dry-run)\");\naddDbOption(normalizeProjectsCmd);\nnormalizeProjectsCmd.action((opts: DbOpts & { apply?: boolean }) => {\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\ttry {\n\t\tconst dryRun = !opts.apply;\n\t\tconst tables = [\"sessions\", \"raw_event_sessions\"] as const;\n\t\tconst rewrites: Map<string, string> = new Map();\n\t\tconst counts: Record<string, number> = {};\n\n\t\tconst run = () => {\n\t\t\tfor (const table of tables) {\n\t\t\t\tconst projects = store.db\n\t\t\t\t\t.prepare(\n\t\t\t\t\t\t`SELECT DISTINCT project FROM ${table} WHERE project IS NOT NULL AND project LIKE '%/%'`,\n\t\t\t\t\t)\n\t\t\t\t\t.all() as Array<{ project: string }>;\n\t\t\t\tlet updated = 0;\n\t\t\t\tfor (const row of projects) {\n\t\t\t\t\tconst basename = row.project.split(\"/\").pop() ?? row.project;\n\t\t\t\t\tif (basename !== row.project) {\n\t\t\t\t\t\trewrites.set(row.project, basename);\n\t\t\t\t\t\tif (!dryRun) {\n\t\t\t\t\t\t\tconst info = store.db\n\t\t\t\t\t\t\t\t.prepare(`UPDATE ${table} SET project = ? WHERE project = ?`)\n\t\t\t\t\t\t\t\t.run(basename, row.project);\n\t\t\t\t\t\t\tupdated += info.changes;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst cnt = store.db\n\t\t\t\t\t\t\t\t.prepare(`SELECT COUNT(*) as cnt FROM ${table} WHERE project = ?`)\n\t\t\t\t\t\t\t\t.get(row.project) as { cnt: number };\n\t\t\t\t\t\t\tupdated += cnt.cnt;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcounts[table] = updated;\n\t\t\t}\n\t\t};\n\t\tif (dryRun) {\n\t\t\trun();\n\t\t} else {\n\t\t\tstore.db.transaction(run)();\n\t\t}\n\n\t\tp.intro(\"codemem db normalize-projects\");\n\t\tp.log.info(`Dry run: ${dryRun}`);\n\t\tp.log.info(\n\t\t\t[\n\t\t\t\t`Sessions to update: ${counts.sessions}`,\n\t\t\t\t`Raw event sessions to update: ${counts.raw_event_sessions}`,\n\t\t\t].join(\"\\n\"),\n\t\t);\n\t\tif (rewrites.size > 0) {\n\t\t\tp.log.info(\"Rewritten paths:\");\n\t\t\tfor (const [from, to] of [...rewrites.entries()].sort()) {\n\t\t\t\tp.log.message(` ${from} → ${to}`);\n\t\t\t}\n\t\t}\n\t\tif (dryRun) {\n\t\t\tp.outro(\"Pass --apply to execute\");\n\t\t} else {\n\t\t\tp.outro(\"done\");\n\t\t}\n\t} finally {\n\t\tstore.close();\n\t}\n});\ndbCommand.addCommand(normalizeProjectsCmd);\n\n// --- db size-report ---\nconst sizeReportCmd = new Command(\"size-report\")\n\t.configureHelp(helpStyle)\n\t.description(\"Show SQLite file size and major storage consumers\")\n\t.option(\"--limit <n>\", \"number of largest tables/indexes to show\", \"12\");\naddDbOption(sizeReportCmd);\naddJsonOption(sizeReportCmd);\nsizeReportCmd.action((opts: DbOpts & JsonOpts & { limit: string }) => {\n\tconst dbPath = resolveDbPath(resolveDbOpt(opts));\n\tconst db = connect(dbPath);\n\ttry {\n\t\tconst limit = Math.max(1, Number.parseInt(opts.limit, 10) || 12);\n\t\tconst fileSizeBytes = statSync(dbPath).size;\n\t\tconst pageInfo = db\n\t\t\t.prepare(\"SELECT page_count * page_size as total FROM pragma_page_count, pragma_page_size\")\n\t\t\t.get() as { total: number } | undefined;\n\t\tconst freePages = db.prepare(\"SELECT freelist_count FROM pragma_freelist_count\").get() as\n\t\t\t| { freelist_count: number }\n\t\t\t| undefined;\n\t\tconst pageSize = db.prepare(\"PRAGMA page_size\").get() as { page_size: number } | undefined;\n\t\tconst tables = db\n\t\t\t.prepare(\n\t\t\t\t`SELECT name, SUM(pgsize) as size_bytes\n\t\t\t\t FROM dbstat\n\t\t\t\t GROUP BY name\n\t\t\t\t ORDER BY size_bytes DESC\n\t\t\t\t LIMIT ?`,\n\t\t\t)\n\t\t\t.all(limit) as Array<{ name: string; size_bytes: number }>;\n\n\t\tif (opts.json) {\n\t\t\tconsole.log(\n\t\t\t\tJSON.stringify(\n\t\t\t\t\t{\n\t\t\t\t\t\tfile_size_bytes: fileSizeBytes,\n\t\t\t\t\t\tdb_size_bytes: pageInfo?.total ?? 0,\n\t\t\t\t\t\tfree_bytes: (freePages?.freelist_count ?? 0) * (pageSize?.page_size ?? 4096),\n\t\t\t\t\t\ttables: tables.map((t) => ({ name: t.name, size_bytes: t.size_bytes })),\n\t\t\t\t\t},\n\t\t\t\t\tnull,\n\t\t\t\t\t2,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tp.intro(\"codemem db size-report\");\n\t\tp.log.info(\n\t\t\t[\n\t\t\t\t`File size: ${formatBytes(fileSizeBytes)}`,\n\t\t\t\t`DB size: ${formatBytes(pageInfo?.total ?? 0)}`,\n\t\t\t\t`Free space: ${formatBytes((freePages?.freelist_count ?? 0) * (pageSize?.page_size ?? 4096))}`,\n\t\t\t].join(\"\\n\"),\n\t\t);\n\t\tif (tables.length > 0) {\n\t\t\tp.log.info(\"Largest objects:\");\n\t\t\tfor (const t of tables) {\n\t\t\t\tp.log.message(` ${t.name.padEnd(40)} ${formatBytes(t.size_bytes).padStart(10)}`);\n\t\t\t}\n\t\t}\n\t\tp.outro(\"done\");\n\t} finally {\n\t\tdb.close();\n\t}\n});\ndbCommand.addCommand(sizeReportCmd);\n\n// --- db backfill-tags ---\nconst backfillTagsCmd = new Command(\"backfill-tags\")\n\t.configureHelp(helpStyle)\n\t.description(\"Populate tags_text for memories where tags are empty\")\n\t.option(\"--limit <n>\", \"max memories to check\")\n\t.option(\"--since <iso>\", \"only memories created at/after this ISO timestamp\")\n\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t.option(\"--all-projects\", \"backfill across all projects\")\n\t.option(\"--inactive\", \"include inactive memories\")\n\t.option(\"--dry-run\", \"preview updates without writing\");\naddDbOption(backfillTagsCmd);\naddJsonOption(backfillTagsCmd);\nbackfillTagsCmd.action(\n\t(\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\tlimit?: string;\n\t\t\t\tsince?: string;\n\t\t\t\tproject?: string;\n\t\t\t\tallProjects?: boolean;\n\t\t\t\tinactive?: boolean;\n\t\t\t\tdryRun?: boolean;\n\t\t\t},\n\t) => {\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tconst limit = parseOptionalPositiveInt(opts.limit);\n\t\t\tconst project =\n\t\t\t\topts.allProjects === true\n\t\t\t\t\t? null\n\t\t\t\t\t: opts.project?.trim() ||\n\t\t\t\t\t\tprocess.env.CODEMEM_PROJECT?.trim() ||\n\t\t\t\t\t\tresolveProject(process.cwd(), null);\n\t\t\tconst result = backfillTagsText(store.db, {\n\t\t\t\tlimit,\n\t\t\t\tsince: opts.since ?? null,\n\t\t\t\tproject,\n\t\t\t\tactiveOnly: !opts.inactive,\n\t\t\t\tdryRun: opts.dryRun === true,\n\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst action = opts.dryRun ? \"Would update\" : \"Updated\";\n\t\t\tp.intro(\"codemem db backfill-tags\");\n\t\t\tp.log.success(`${action} ${result.updated} memories (skipped ${result.skipped})`);\n\t\t\tp.outro(`Checked ${result.checked} memories`);\n\t\t} catch (error) {\n\t\t\tp.log.error(error instanceof Error ? error.message : String(error));\n\t\t\tprocess.exitCode = 1;\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\ndbCommand.addCommand(backfillTagsCmd);\n\n// --- db prune-observations ---\nconst pruneObsCmd = new Command(\"prune-observations\")\n\t.configureHelp(helpStyle)\n\t.description(\"Deactivate low-signal observations (does not delete rows)\")\n\t.option(\"--limit <n>\", \"max observations to check\")\n\t.option(\"--dry-run\", \"preview deactivations without writing\");\naddDbOption(pruneObsCmd);\naddJsonOption(pruneObsCmd);\npruneObsCmd.action(\n\t(\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\tlimit?: string;\n\t\t\t\tdryRun?: boolean;\n\t\t\t},\n\t) => {\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tconst limit = parseOptionalPositiveInt(opts.limit);\n\t\t\tconst result = deactivateLowSignalObservations(store.db, limit ?? null, opts.dryRun === true);\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst action = opts.dryRun ? \"Would deactivate\" : \"Deactivated\";\n\t\t\tp.intro(\"codemem db prune-observations\");\n\t\t\tp.outro(`${action} ${result.deactivated} of ${result.checked} observations`);\n\t\t} catch (error) {\n\t\t\tp.log.error(error instanceof Error ? error.message : String(error));\n\t\t\tprocess.exitCode = 1;\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\ndbCommand.addCommand(pruneObsCmd);\n\n// --- db prune-memories ---\nconst pruneMemCmd = new Command(\"prune-memories\")\n\t.configureHelp(helpStyle)\n\t.description(\"Deactivate low-signal memories across selected kinds\")\n\t.option(\"--limit <n>\", \"max memories to check\")\n\t.option(\"--kinds <csv>\", \"comma-separated memory kinds (default set when omitted)\")\n\t.option(\"--dry-run\", \"preview deactivations without writing\");\naddDbOption(pruneMemCmd);\naddJsonOption(pruneMemCmd);\npruneMemCmd.action(\n\t(\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\tlimit?: string;\n\t\t\t\tkinds?: string;\n\t\t\t\tdryRun?: boolean;\n\t\t\t},\n\t) => {\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tconst limit = parseOptionalPositiveInt(opts.limit);\n\t\t\tconst kinds = parseKindsCsv(opts.kinds);\n\t\t\tconst result = deactivateLowSignalMemories(store.db, {\n\t\t\t\tkinds,\n\t\t\t\tlimit: limit ?? null,\n\t\t\t\tdryRun: opts.dryRun === true,\n\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst action = opts.dryRun ? \"Would deactivate\" : \"Deactivated\";\n\t\t\tp.intro(\"codemem db prune-memories\");\n\t\t\tp.outro(`${action} ${result.deactivated} of ${result.checked} memories`);\n\t\t} catch (error) {\n\t\t\tp.log.error(error instanceof Error ? error.message : String(error));\n\t\t\tprocess.exitCode = 1;\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\ndbCommand.addCommand(pruneMemCmd);\n\n// --- db dedup-memories ---\nconst dedupCmd = new Command(\"dedup-memories\")\n\t.configureHelp(helpStyle)\n\t.description(\n\t\t\"Deactivate near-duplicate memories (cross-session, same normalized title within time window)\",\n\t)\n\t.option(\"--window <ms>\", \"max time gap in milliseconds between duplicates (default: 3600000)\")\n\t.option(\"--limit <n>\", \"max pairs to check\")\n\t.option(\"--dry-run\", \"preview deactivations without writing\");\naddDbOption(dedupCmd);\naddJsonOption(dedupCmd);\ndedupCmd.action(\n\t(\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\twindow?: string;\n\t\t\t\tlimit?: string;\n\t\t\t\tdryRun?: boolean;\n\t\t\t},\n\t) => {\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tconst windowMs = parseOptionalPositiveInt(opts.window);\n\t\t\tconst limit = parseOptionalPositiveInt(opts.limit);\n\t\t\tconst result = dedupNearDuplicateMemories(store.db, {\n\t\t\t\twindowMs,\n\t\t\t\tlimit,\n\t\t\t\tdryRun: opts.dryRun === true,\n\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst action = opts.dryRun ? \"Would deactivate\" : \"Deactivated\";\n\t\t\tp.intro(\"codemem db dedup-memories\");\n\t\t\tif (result.pairs.length > 0 && result.pairs.length <= 20) {\n\t\t\t\tfor (const pair of result.pairs) {\n\t\t\t\t\tp.log.info(\n\t\t\t\t\t\t`${action} [${pair.deactivated_id}] (kept [${pair.kept_id}]): ${pair.title.slice(0, 80)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tp.outro(`${action} ${result.deactivated} duplicates from ${result.checked} pairs`);\n\t\t} catch (error) {\n\t\t\tp.log.error(error instanceof Error ? error.message : String(error));\n\t\t\tprocess.exitCode = 1;\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\ndbCommand.addCommand(dedupCmd);\n\nconst backfillDedupKeysCmd = new Command(\"backfill-dedup-keys\")\n\t.configureHelp(helpStyle)\n\t.description(\"Populate missing memory_items.dedup_key values for legacy rows\")\n\t.option(\"--limit <n>\", \"max memories to check\")\n\t.option(\"--dry-run\", \"preview updates without writing\");\naddDbOption(backfillDedupKeysCmd);\naddJsonOption(backfillDedupKeysCmd);\nbackfillDedupKeysCmd.action(\n\t(\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\tlimit?: string;\n\t\t\t\tdryRun?: boolean;\n\t\t\t},\n\t) => {\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tconst limit = parseOptionalPositiveInt(opts.limit);\n\t\t\tconst result = backfillMemoryDedupKeys(store.db, {\n\t\t\t\tlimit,\n\t\t\t\tdryRun: opts.dryRun === true,\n\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst action = opts.dryRun ? \"Would update\" : \"Updated\";\n\t\t\tp.intro(\"codemem db backfill-dedup-keys\");\n\t\t\tp.log.success(`${action} ${result.updated} memories (skipped ${result.skipped})`);\n\t\t\tp.outro(`Checked ${result.checked} memories`);\n\t\t} catch (error) {\n\t\t\tp.log.error(error instanceof Error ? error.message : String(error));\n\t\t\tprocess.exitCode = 1;\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\ndbCommand.addCommand(backfillDedupKeysCmd);\n\n// --- db backfill-narrative ---\nconst backfillNarrativeCmd = new Command(\"backfill-narrative\")\n\t.configureHelp(helpStyle)\n\t.description(\n\t\t\"Extract narrative from session_summary body_text (## Completed / ## Learned sections)\",\n\t)\n\t.option(\"--limit <n>\", \"max memories to check\")\n\t.option(\"--dry-run\", \"preview updates without writing\");\naddDbOption(backfillNarrativeCmd);\naddJsonOption(backfillNarrativeCmd);\nbackfillNarrativeCmd.action(\n\t(\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\tlimit?: string;\n\t\t\t\tdryRun?: boolean;\n\t\t\t},\n\t) => {\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tconst limit = parseOptionalPositiveInt(opts.limit);\n\t\t\tconst result = backfillNarrativeFromBody(store.db, {\n\t\t\t\tlimit,\n\t\t\t\tdryRun: opts.dryRun === true,\n\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst action = opts.dryRun ? \"Would update\" : \"Updated\";\n\t\t\tp.intro(\"codemem db backfill-narrative\");\n\t\t\tp.log.success(`${action} ${result.updated} memories (skipped ${result.skipped})`);\n\t\t\tp.outro(`Checked ${result.checked} memories`);\n\t\t} catch (error) {\n\t\t\tp.log.error(error instanceof Error ? error.message : String(error));\n\t\t\tprocess.exitCode = 1;\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\ndbCommand.addCommand(backfillNarrativeCmd);\n\n// --- db ai-backfill-structured ---\nconst aiBackfillStructuredCmd = new Command(\"ai-backfill-structured\")\n\t.configureHelp(helpStyle)\n\t.description(\n\t\t\"Use GPT-5.4 to populate missing narrative/facts/concepts for older non-session-summary memories\",\n\t)\n\t.option(\"--limit <n>\", \"max memories to check\")\n\t.option(\"--kinds <csv>\", \"comma-separated kinds to target\")\n\t.option(\n\t\t\"--overwrite\",\n\t\t\"overwrite existing structured fields instead of only filling missing ones\",\n\t)\n\t.option(\"--dry-run\", \"preview updates without writing\");\naddDbOption(aiBackfillStructuredCmd);\naddJsonOption(aiBackfillStructuredCmd);\naiBackfillStructuredCmd.action(\n\tasync (\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\tlimit?: string;\n\t\t\t\tkinds?: string;\n\t\t\t\toverwrite?: boolean;\n\t\t\t\tdryRun?: boolean;\n\t\t\t},\n\t) => {\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tconst limit = parseOptionalPositiveInt(opts.limit);\n\t\t\tconst kinds = parseKindsCsv(opts.kinds);\n\t\t\tconst result = await aiBackfillStructuredContent(store.db, {\n\t\t\t\tlimit,\n\t\t\t\tkinds,\n\t\t\t\toverwrite: opts.overwrite === true,\n\t\t\t\tdryRun: opts.dryRun === true,\n\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst action = opts.dryRun ? \"Would update\" : \"Updated\";\n\t\t\tp.intro(\"codemem db ai-backfill-structured\");\n\t\t\tp.log.success(\n\t\t\t\t`${action} ${result.updated} memories (skipped ${result.skipped}, failed ${result.failed})`,\n\t\t\t);\n\t\t\tp.outro(`Checked ${result.checked} memories`);\n\t\t} catch (error) {\n\t\t\tp.log.error(error instanceof Error ? error.message : String(error));\n\t\t\tprocess.exitCode = 1;\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\ndbCommand.addCommand(aiBackfillStructuredCmd);\n","import * as p from \"@clack/prompts\";\nimport { backfillVectors, MemoryStore, resolveDbPath, resolveProject } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddDbOption,\n\taddJsonOption,\n\ttype DbOpts,\n\ttype JsonOpts,\n\tresolveDbOpt,\n} from \"../shared-options.js\";\n\nfunction parseOptionalPositiveInt(value: string | undefined): number | undefined {\n\tif (!value) return undefined;\n\tconst parsed = Number.parseInt(value, 10);\n\tif (!Number.isFinite(parsed) || parsed <= 0) {\n\t\tthrow new Error(`invalid positive integer: ${value}`);\n\t}\n\treturn parsed;\n}\n\nexport function resolveEmbedProjectScope(\n\tcwd: string,\n\tprojectOpt: string | undefined,\n\tallProjects: boolean | undefined,\n): string | null {\n\tif (allProjects === true) return null;\n\tconst explicit = projectOpt?.trim();\n\tif (explicit) return explicit;\n\tconst envProject = process.env.CODEMEM_PROJECT?.trim();\n\tif (envProject) return envProject;\n\treturn resolveProject(cwd, null);\n}\n\nconst embedCmd = new Command(\"embed\")\n\t.configureHelp(helpStyle)\n\t.description(\"Backfill semantic embeddings\")\n\t.option(\"--limit <n>\", \"max memories to check\")\n\t.option(\"--since <iso>\", \"only memories created at/after this ISO timestamp\")\n\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t.option(\"--all-projects\", \"embed across all projects\")\n\t.option(\"--inactive\", \"include inactive memories\")\n\t.option(\"--dry-run\", \"preview work without writing vectors\");\n\naddDbOption(embedCmd);\naddJsonOption(embedCmd);\n\nexport const embedCommand = embedCmd.action(\n\tasync (\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\tlimit?: string;\n\t\t\t\tsince?: string;\n\t\t\t\tproject?: string;\n\t\t\t\tallProjects?: boolean;\n\t\t\t\tinactive?: boolean;\n\t\t\t\tdryRun?: boolean;\n\t\t\t},\n\t) => {\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tconst limit = parseOptionalPositiveInt(opts.limit);\n\t\t\tconst project = resolveEmbedProjectScope(process.cwd(), opts.project, opts.allProjects);\n\n\t\t\tconst result = await backfillVectors(store.db, {\n\t\t\t\tlimit,\n\t\t\t\tsince: opts.since ?? null,\n\t\t\t\tproject,\n\t\t\t\tactiveOnly: !opts.inactive,\n\t\t\t\tdryRun: opts.dryRun === true,\n\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst action = opts.dryRun ? \"Would embed\" : \"Embedded\";\n\t\t\tp.intro(\"codemem embed\");\n\t\t\tp.log.success(\n\t\t\t\t`${action} ${result.embedded} vectors (${result.inserted} inserted, ${result.skipped} skipped)`,\n\t\t\t);\n\t\t\tp.outro(`Checked ${result.checked} memories`);\n\t\t} catch (error) {\n\t\t\tp.log.error(error instanceof Error ? error.message : String(error));\n\t\t\tprocess.exitCode = 1;\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\n","import { MemoryStore, resolveDbPath, stripPrivateObj } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport { addDbOption, type DbOpts, resolveDbOpt } from \"../shared-options.js\";\n\nconst SESSION_ID_KEYS = [\n\t\"session_stream_id\",\n\t\"session_id\",\n\t\"stream_id\",\n\t\"opencode_session_id\",\n] as const;\n\nfunction resolveSessionStreamId(payload: Record<string, unknown>): string | null {\n\tconst values = new Map<string, string>();\n\tfor (const key of SESSION_ID_KEYS) {\n\t\tconst value = payload[key];\n\t\tif (typeof value !== \"string\") continue;\n\t\tconst text = value.trim();\n\t\tif (text) values.set(key, text);\n\t}\n\tif (values.size === 0) return null;\n\tconst unique = new Set(values.values());\n\tif (unique.size > 1) return null;\n\tfor (const key of SESSION_ID_KEYS) {\n\t\tconst value = values.get(key);\n\t\tif (value) return value;\n\t}\n\treturn null;\n}\n\nasync function readStdinJson(): Promise<Record<string, unknown>> {\n\tconst chunks: Buffer[] = [];\n\tfor await (const chunk of process.stdin) {\n\t\tchunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));\n\t}\n\tconst raw = Buffer.concat(chunks).toString(\"utf-8\").trim();\n\tif (!raw) throw new Error(\"stdin JSON required\");\n\tconst parsed = JSON.parse(raw) as unknown;\n\tif (parsed == null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(\"payload must be an object\");\n\t}\n\treturn parsed as Record<string, unknown>;\n}\n\nfunction emitStructuredError(errorCode: string, message: string): void {\n\tconsole.log(JSON.stringify({ error: errorCode, message }));\n\tprocess.exitCode = 1;\n}\n\nconst enqueueCmd = new Command(\"enqueue-raw-event\")\n\t.configureHelp(helpStyle)\n\t.description(\"Enqueue one raw event from stdin into the durable queue\");\n\naddDbOption(enqueueCmd);\n\nexport const enqueueRawEventCommand = enqueueCmd.action(async (opts: DbOpts) => {\n\ttry {\n\t\tconst payload = await readStdinJson();\n\t\tconst sessionId = resolveSessionStreamId(payload);\n\t\tif (!sessionId) {\n\t\t\temitStructuredError(\"validation_error\", \"session id required\");\n\t\t\treturn;\n\t\t}\n\t\tif (sessionId.startsWith(\"msg_\")) {\n\t\t\temitStructuredError(\"validation_error\", \"invalid session id\");\n\t\t\treturn;\n\t\t}\n\n\t\tconst eventType = typeof payload.event_type === \"string\" ? payload.event_type.trim() : \"\";\n\t\tif (!eventType) {\n\t\t\temitStructuredError(\"validation_error\", \"event_type required\");\n\t\t\treturn;\n\t\t}\n\n\t\tconst cwd = typeof payload.cwd === \"string\" ? payload.cwd : null;\n\t\tconst project = typeof payload.project === \"string\" ? payload.project : null;\n\t\tconst startedAt = typeof payload.started_at === \"string\" ? payload.started_at : null;\n\t\tconst tsWallMs = Number.isFinite(Number(payload.ts_wall_ms))\n\t\t\t? Math.floor(Number(payload.ts_wall_ms))\n\t\t\t: null;\n\t\tconst tsMonoMs = Number.isFinite(Number(payload.ts_mono_ms))\n\t\t\t? Number(payload.ts_mono_ms)\n\t\t\t: null;\n\t\tconst eventId = typeof payload.event_id === \"string\" ? payload.event_id.trim() : \"\";\n\t\tconst eventPayload =\n\t\t\tpayload.payload && typeof payload.payload === \"object\" && !Array.isArray(payload.payload)\n\t\t\t\t? (stripPrivateObj(payload.payload) as Record<string, unknown>)\n\t\t\t\t: {};\n\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tstore.updateRawEventSessionMeta({\n\t\t\t\topencodeSessionId: sessionId,\n\t\t\t\tsource: \"opencode\",\n\t\t\t\tcwd,\n\t\t\t\tproject,\n\t\t\t\tstartedAt,\n\t\t\t\tlastSeenTsWallMs: tsWallMs,\n\t\t\t});\n\t\t\tstore.recordRawEventsBatch(sessionId, [\n\t\t\t\t{\n\t\t\t\t\tevent_id: eventId,\n\t\t\t\t\tevent_type: eventType,\n\t\t\t\t\tpayload: eventPayload,\n\t\t\t\t\tts_wall_ms: tsWallMs,\n\t\t\t\t\tts_mono_ms: tsMonoMs,\n\t\t\t\t},\n\t\t\t]);\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t} catch (err) {\n\t\temitStructuredError(\"enqueue_error\", err instanceof Error ? err.message : String(err));\n\t}\n});\n","import { writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { exportMemories, resolveDbPath } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport { addDbOption, type DbOpts, resolveDbOpt } from \"../shared-options.js\";\n\nfunction expandUserPath(value: string): string {\n\treturn value.startsWith(\"~/\") ? join(homedir(), value.slice(2)) : value;\n}\n\nconst cmd = new Command(\"export-memories\")\n\t.configureHelp(helpStyle)\n\t.description(\"Export memories to a JSON file for sharing or backup\")\n\t.argument(\"<output>\", \"output file path (use '-' for stdout)\")\n\t.option(\"--project <project>\", \"filter by project (defaults to git repo root)\")\n\t.option(\"--all-projects\", \"export all projects\")\n\t.option(\"--include-inactive\", \"include deactivated memories\")\n\t.option(\"--since <iso>\", \"only export memories created after this ISO timestamp\");\n\naddDbOption(cmd);\n\ncmd.action(\n\t(\n\t\toutput: string,\n\t\topts: DbOpts & {\n\t\t\tproject?: string;\n\t\t\tallProjects?: boolean;\n\t\t\tincludeInactive?: boolean;\n\t\t\tsince?: string;\n\t\t},\n\t) => {\n\t\tconst payload = exportMemories({\n\t\t\tdbPath: resolveDbPath(resolveDbOpt(opts)),\n\t\t\tproject: opts.project,\n\t\t\tallProjects: opts.allProjects,\n\t\t\tincludeInactive: opts.includeInactive,\n\t\t\tsince: opts.since,\n\t\t});\n\t\tconst text = `${JSON.stringify(payload, null, 2)}\\n`;\n\t\tif (output === \"-\") {\n\t\t\tprocess.stdout.write(text);\n\t\t\treturn;\n\t\t}\n\t\tconst outputPath = expandUserPath(output);\n\t\twriteFileSync(outputPath, text, \"utf8\");\n\t\tp.intro(\"codemem export-memories\");\n\t\tp.log.success(\n\t\t\t[\n\t\t\t\t`Output: ${outputPath}`,\n\t\t\t\t`Sessions: ${payload.sessions.length.toLocaleString()}`,\n\t\t\t\t`Memories: ${payload.memory_items.length.toLocaleString()}`,\n\t\t\t\t`Summaries: ${payload.session_summaries.length.toLocaleString()}`,\n\t\t\t\t`Prompts: ${payload.user_prompts.length.toLocaleString()}`,\n\t\t\t].join(\"\\n\"),\n\t\t);\n\t\tp.outro(\"done\");\n\t},\n);\n\nexport const exportMemoriesCommand = cmd;\n","import * as p from \"@clack/prompts\";\nimport type { ExportPayload } from \"@codemem/core\";\nimport { importMemories, readImportPayload, resolveDbPath } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddDbOption,\n\taddJsonOption,\n\ttype DbOpts,\n\temitJsonError,\n\ttype JsonOpts,\n\tresolveDbOpt,\n} from \"../shared-options.js\";\n\nconst cmd = new Command(\"import-memories\")\n\t.configureHelp(helpStyle)\n\t.description(\"Import memories from an exported JSON file\")\n\t.argument(\"<inputFile>\", \"input JSON file (use '-' for stdin)\")\n\t.option(\"--remap-project <path>\", \"remap all projects to this path on import\")\n\t.option(\"--dry-run\", \"preview import without writing\");\n\naddDbOption(cmd);\naddJsonOption(cmd);\n\ncmd.action(\n\t(\n\t\tinputFile: string,\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\tremapProject?: string;\n\t\t\t\tdryRun?: boolean;\n\t\t\t},\n\t) => {\n\t\tlet payload: ExportPayload;\n\t\ttry {\n\t\t\tpayload = readImportPayload(inputFile);\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : \"Invalid import file\";\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\"invalid_input\", message);\n\t\t\t} else {\n\t\t\t\tp.log.error(message);\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (!opts.json) {\n\t\t\tp.intro(\"codemem import-memories\");\n\t\t\tp.log.info(\n\t\t\t\t[\n\t\t\t\t\t`Export version: ${payload.version}`,\n\t\t\t\t\t`Exported at: ${payload.exported_at}`,\n\t\t\t\t\t`Sessions: ${payload.sessions.length.toLocaleString()}`,\n\t\t\t\t\t`Memories: ${payload.memory_items.length.toLocaleString()}`,\n\t\t\t\t\t`Summaries: ${payload.session_summaries.length.toLocaleString()}`,\n\t\t\t\t\t`Prompts: ${payload.user_prompts.length.toLocaleString()}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t}\n\n\t\tconst result = importMemories(payload, {\n\t\t\tdbPath: resolveDbPath(resolveDbOpt(opts)),\n\t\t\tremapProject: opts.remapProject,\n\t\t\tdryRun: opts.dryRun,\n\t\t});\n\n\t\tif (opts.json) {\n\t\t\tconsole.log(\n\t\t\t\tJSON.stringify({\n\t\t\t\t\tsessions: result.sessions,\n\t\t\t\t\tmemory_items: result.memory_items,\n\t\t\t\t\tskipped: result.dryRun,\n\t\t\t\t}),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (result.dryRun) {\n\t\t\tp.outro(\"dry run complete\");\n\t\t\treturn;\n\t\t}\n\t\tp.log.success(\n\t\t\t[\n\t\t\t\t`Imported sessions: ${result.sessions.toLocaleString()}`,\n\t\t\t\t`Imported prompts: ${result.user_prompts.toLocaleString()}`,\n\t\t\t\t`Imported memories: ${result.memory_items.toLocaleString()}`,\n\t\t\t\t`Imported summaries: ${result.session_summaries.toLocaleString()}`,\n\t\t\t].join(\"\\n\"),\n\t\t);\n\t\tp.outro(\"done\");\n\t},\n);\n\nexport const importMemoriesCommand = cmd;\n","import { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport { addDbOption, type DbOpts, resolveDbOpt } from \"../shared-options.js\";\n\nconst mcpCmd = new Command(\"mcp\")\n\t.configureHelp(helpStyle)\n\t.description(\"Start the MCP stdio server\");\n\naddDbOption(mcpCmd);\n\nexport const mcpCommand = mcpCmd.action(async (opts: DbOpts) => {\n\tconst dbPath = resolveDbOpt(opts);\n\tif (dbPath) process.env.CODEMEM_DB = dbPath;\n\ttry {\n\t\tawait import(\"@codemem/mcp\");\n\t} catch (err) {\n\t\tconsole.error(\n\t\t\t`Failed to start MCP server: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t\tprocess.exitCode = 1;\n\t}\n});\n","import type { PackRenderOptions } from \"@codemem/core\";\nimport { resolveProject } from \"@codemem/core\";\nimport type { Command } from \"commander\";\n\nexport type PackFilters = { project?: string; working_set_paths?: string[] };\n\nexport type PackRequestOptions = {\n\tlimit: number;\n\tbudget: number | undefined;\n\tfilters: PackFilters;\n\trenderOptions?: PackRenderOptions;\n};\n\nexport class PackUsageError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"PackUsageError\";\n\t}\n}\n\nexport function collectWorkingSetFile(value: string, previous: string[]): string[] {\n\treturn [...previous, value];\n}\n\nexport function addPackRequestOptions(command: Command): Command {\n\treturn command\n\t\t.option(\"-n, --limit <n>\", \"max items\", \"10\")\n\t\t.option(\"--budget <tokens>\", \"token budget\")\n\t\t.option(\"--token-budget <tokens>\", \"token budget\")\n\t\t.option(\n\t\t\t\"--working-set-file <path>\",\n\t\t\t\"recently modified file path used as ranking hint\",\n\t\t\tcollectWorkingSetFile,\n\t\t\t[],\n\t\t)\n\t\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t\t.option(\"--all-projects\", \"search across all projects\")\n\t\t.option(\"--compact\", \"render a scannable index with full detail only for top N items\")\n\t\t.option(\"--compact-detail <n>\", \"items to show in full detail in compact mode (default 3)\");\n}\n\nexport function buildPackRequestOptions(\n\topts: {\n\t\tlimit?: string;\n\t\tbudget?: string;\n\t\ttokenBudget?: string;\n\t\tworkingSetFile?: string[];\n\t\tproject?: string;\n\t\tallProjects?: boolean;\n\t\tcompact?: boolean;\n\t\tcompactDetail?: string;\n\t},\n\tctx: {\n\t\tcwd?: string;\n\t\tenvProject?: string | null;\n\t\tresolveProjectFn?: typeof resolveProject;\n\t} = {},\n): PackRequestOptions {\n\tconst limit = parsePositiveInt(opts.limit ?? \"10\", \"limit\");\n\tconst budgetRaw = opts.tokenBudget ?? opts.budget;\n\tconst budget = budgetRaw ? parseNonNegativeInt(budgetRaw, \"token budget\") : undefined;\n\tconst filters: PackFilters = {};\n\n\tif (!opts.allProjects) {\n\t\tconst defaultProject = ctx.envProject?.trim() || null;\n\t\tconst resolveProjectFn = ctx.resolveProjectFn ?? resolveProject;\n\t\tconst cwd = ctx.cwd ?? process.cwd();\n\t\tconst project = defaultProject || resolveProjectFn(cwd, opts.project ?? null);\n\t\tif (project) {\n\t\t\tfilters.project = project;\n\t\t}\n\t}\n\n\tif ((opts.workingSetFile?.length ?? 0) > 0) {\n\t\tfilters.working_set_paths = opts.workingSetFile;\n\t}\n\n\tlet renderOptions: PackRenderOptions | undefined;\n\tif (opts.compact || opts.compactDetail != null) {\n\t\trenderOptions = { compact: true };\n\t\tif (opts.compactDetail != null) {\n\t\t\trenderOptions.compactDetailCount = parseNonNegativeInt(\n\t\t\t\topts.compactDetail,\n\t\t\t\t\"compact detail count\",\n\t\t\t);\n\t\t}\n\t}\n\n\treturn { limit, budget, filters, renderOptions };\n}\n\nfunction parsePositiveInt(value: string, label: string): number {\n\tif (!/^\\d+$/.test(value.trim())) {\n\t\tthrow new PackUsageError(`${label} must be a positive integer`);\n\t}\n\tconst parsed = Number.parseInt(value, 10);\n\tif (!Number.isFinite(parsed) || parsed < 1) {\n\t\tthrow new PackUsageError(`${label} must be a positive integer`);\n\t}\n\treturn parsed;\n}\n\nfunction parseNonNegativeInt(value: string, label: string): number {\n\tif (!/^\\d+$/.test(value.trim())) {\n\t\tthrow new PackUsageError(`${label} must be a non-negative integer`);\n\t}\n\tconst parsed = Number.parseInt(value, 10);\n\tif (!Number.isFinite(parsed) || parsed < 0) {\n\t\tthrow new PackUsageError(`${label} must be a non-negative integer`);\n\t}\n\treturn parsed;\n}\n","/**\n * Memory management CLI commands — show, forget, remember, inject.\n *\n * Ports codemem/commands/memory_cmds.py (show_cmd, forget_cmd, remember_cmd).\n * Inject is deprecated in favor of `codemem pack`.\n */\n\nimport * as p from \"@clack/prompts\";\nimport {\n\tcompareMemoryRoleReports,\n\tgetExtractionBenchmarkProfile,\n\tgetInjectionEvalScenarioPack,\n\tgetInjectionEvalScenarioPrompts,\n\tgetMemoryRoleReport,\n\tgetRawEventRelinkPlan,\n\tgetRawEventRelinkReport,\n\tgetSessionExtractionEval,\n\tgetSessionExtractionEvalScenario,\n\tloadObserverConfig,\n\tMemoryStore,\n\tObserverClient,\n\treplayBatchExtraction,\n\treplayBatchExtractionWithTierRouting,\n\tresolveDbPath,\n\tresolveProject,\n} from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddDbOption,\n\taddJsonOption,\n\ttype DbOpts,\n\temitDeprecationWarning,\n\temitJsonError,\n\ttype JsonOpts,\n\tresolveDbOpt,\n} from \"../shared-options.js\";\nimport { buildPackRequestOptions, collectWorkingSetFile } from \"./pack-shared.js\";\n\n/** Parse a strict positive integer, rejecting prefixes like \"12abc\". */\nfunction parseStrictPositiveId(value: string): number | null {\n\tif (!/^\\d+$/.test(value.trim())) return null;\n\tconst n = Number(value.trim());\n\treturn Number.isFinite(n) && n >= 1 && Number.isInteger(n) ? n : null;\n}\n\nfunction showMemoryAction(idStr: string, opts: DbOpts & JsonOpts): void {\n\tconst memoryId = parseStrictPositiveId(idStr);\n\tif (memoryId === null) {\n\t\tif (opts.json) {\n\t\t\temitJsonError(\"invalid_id\", `Invalid memory ID: ${idStr}`);\n\t\t} else {\n\t\t\tp.log.error(`Invalid memory ID: ${idStr}`);\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t\treturn;\n\t}\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\ttry {\n\t\tconst item = store.get(memoryId);\n\t\tif (!item) {\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\"not_found\", `Memory ${memoryId} not found`);\n\t\t\t} else {\n\t\t\t\tp.log.error(`Memory ${memoryId} not found`);\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify(item, null, 2));\n\t\t} else {\n\t\t\t// Human-readable format\n\t\t\tconsole.log(`#${item.id} [${item.kind}] ${item.title}`);\n\t\t\tif (item.subtitle) console.log(` ${item.subtitle}`);\n\t\t\tconsole.log(` created: ${item.created_at} confidence: ${item.confidence}`);\n\t\t\tif (item.tags_text) console.log(` tags: ${item.tags_text}`);\n\t\t\tif (item.body_text) {\n\t\t\t\tconst preview =\n\t\t\t\t\titem.body_text.length > 300 ? `${item.body_text.slice(0, 300)}…` : item.body_text;\n\t\t\t\tconsole.log(`\\n${preview}`);\n\t\t\t}\n\t\t}\n\t} finally {\n\t\tstore.close();\n\t}\n}\n\nfunction forgetMemoryAction(idStr: string, opts: DbOpts & JsonOpts): void {\n\tconst memoryId = parseStrictPositiveId(idStr);\n\tif (memoryId === null) {\n\t\tif (opts.json) {\n\t\t\temitJsonError(\"invalid_id\", `Invalid memory ID: ${idStr}`);\n\t\t} else {\n\t\t\tp.log.error(`Invalid memory ID: ${idStr}`);\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t\treturn;\n\t}\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\ttry {\n\t\tstore.forget(memoryId);\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify({ id: memoryId, status: \"forgotten\" }));\n\t\t} else {\n\t\t\tp.log.success(`Memory ${memoryId} marked inactive`);\n\t\t}\n\t} finally {\n\t\tstore.close();\n\t}\n}\n\ninterface RememberMemoryOptions extends DbOpts, JsonOpts {\n\tkind: string;\n\ttitle: string;\n\tbody: string;\n\ttags?: string[];\n\tproject?: string;\n}\n\nasync function rememberMemoryAction(opts: RememberMemoryOptions): Promise<void> {\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\tlet sessionId: number | null = null;\n\ttry {\n\t\tconst project = resolveProject(process.cwd(), opts.project ?? null);\n\t\tsessionId = store.startSession({\n\t\t\tcwd: process.cwd(),\n\t\t\tproject,\n\t\t\tuser: process.env.USER ?? \"unknown\",\n\t\t\ttoolVersion: \"manual\",\n\t\t\tmetadata: { manual: true },\n\t\t});\n\t\tconst memId = store.remember(sessionId, opts.kind, opts.title, opts.body, 0.5, opts.tags);\n\t\tawait store.flushPendingVectorWrites();\n\t\tstore.endSession(sessionId, { manual: true });\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify({ id: memId }));\n\t\t} else {\n\t\t\tp.log.success(`Stored memory ${memId}`);\n\t\t}\n\t} catch (err) {\n\t\tif (sessionId !== null) {\n\t\t\ttry {\n\t\t\t\tstore.endSession(sessionId, { manual: true, error: true });\n\t\t\t} catch {\n\t\t\t\t// ignore — already in error path\n\t\t\t}\n\t\t}\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tif (opts.json) {\n\t\t\temitJsonError(\"remember_failed\", message);\n\t\t} else {\n\t\t\tp.log.error(`Failed to store memory: ${message}`);\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t} finally {\n\t\tstore.close();\n\t}\n}\n\nfunction createShowMemoryCommand(): Command {\n\tconst cmd = new Command(\"show\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Show a memory item\")\n\t\t.argument(\"<id>\", \"memory ID\");\n\taddDbOption(cmd);\n\taddJsonOption(cmd);\n\tcmd.action(showMemoryAction);\n\treturn cmd;\n}\n\nfunction createForgetMemoryCommand(): Command {\n\tconst cmd = new Command(\"forget\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Deactivate a memory item\")\n\t\t.argument(\"<id>\", \"memory ID\");\n\taddDbOption(cmd);\n\taddJsonOption(cmd);\n\tcmd.action(forgetMemoryAction);\n\treturn cmd;\n}\n\nfunction createRememberMemoryCommand(): Command {\n\tconst cmd = new Command(\"remember\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Manually add a memory item\")\n\t\t.requiredOption(\"-k, --kind <kind>\", \"memory kind (discovery, decision, feature, bugfix, etc.)\")\n\t\t.requiredOption(\"-t, --title <title>\", \"memory title\")\n\t\t.requiredOption(\"-b, --body <body>\", \"memory body text\")\n\t\t.option(\"--tags <tags...>\", \"tags (space-separated)\")\n\t\t.option(\"--project <project>\", \"project name (defaults to git repo root)\");\n\taddDbOption(cmd);\n\taddJsonOption(cmd);\n\tcmd.action(rememberMemoryAction);\n\treturn cmd;\n}\n\nfunction createInjectMemoryCommand(): Command {\n\tconst cmd = new Command(\"inject\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Build raw memory context text for manual prompt injection\")\n\t\t.argument(\"<context>\", \"context string to search for\")\n\t\t.option(\"-n, --limit <n>\", \"max items\", \"10\")\n\t\t.option(\"--budget <tokens>\", \"token budget\")\n\t\t.option(\"--token-budget <tokens>\", \"token budget\")\n\t\t.option(\n\t\t\t\"--working-set-file <path>\",\n\t\t\t\"recently modified file path used as ranking hint\",\n\t\t\tcollectWorkingSetFile,\n\t\t\t[],\n\t\t)\n\t\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t\t.option(\"--all-projects\", \"search across all projects\")\n\t\t.allowUnknownOption(true)\n\t\t.allowExcessArguments(true);\n\taddDbOption(cmd);\n\tcmd.action(\n\t\tasync (\n\t\t\tcontext: string,\n\t\t\topts: DbOpts & {\n\t\t\t\tlimit?: string;\n\t\t\t\tbudget?: string;\n\t\t\t\ttokenBudget?: string;\n\t\t\t\tworkingSetFile?: string[];\n\t\t\t\tproject?: string;\n\t\t\t\tallProjects?: boolean;\n\t\t\t},\n\t\t) => {\n\t\t\temitDeprecationWarning(\"codemem memory inject\", \"codemem pack\");\n\t\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\t\ttry {\n\t\t\t\tconst { limit, budget, filters } = buildPackRequestOptions(opts, {\n\t\t\t\t\tenvProject: process.env.CODEMEM_PROJECT,\n\t\t\t\t});\n\t\t\t\tconst pack = await store.buildMemoryPackAsync(context, limit, budget, filters);\n\t\t\t\tconsole.log(pack.pack_text ?? \"\");\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t},\n\t);\n\treturn cmd;\n}\n\nfunction createMemoryRoleReportCommand(): Command {\n\tconst cmd = new Command(\"role-report\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Analyze inferred memory roles in a DB snapshot\")\n\t\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t\t.option(\"--all-projects\", \"analyze across all projects\")\n\t\t.option(\n\t\t\t\"--probe <query>\",\n\t\t\t\"run a retrieval probe query against the snapshot\",\n\t\t\t(value, prev: string[]) => [...prev, value],\n\t\t\t[],\n\t\t)\n\t\t.option(\n\t\t\t\"--scenario <id>\",\n\t\t\t\"run a named injection-first eval scenario pack (can be repeated)\",\n\t\t\t(value, prev: string[]) => [...prev, value],\n\t\t\t[],\n\t\t)\n\t\t.option(\"--inactive\", \"include inactive memories\");\n\taddDbOption(cmd);\n\taddJsonOption(cmd);\n\tcmd.action(\n\t\t(\n\t\t\topts: DbOpts &\n\t\t\t\tJsonOpts & {\n\t\t\t\t\tproject?: string;\n\t\t\t\t\tallProjects?: boolean;\n\t\t\t\t\tprobe?: string[];\n\t\t\t\t\tscenario?: string[];\n\t\t\t\t\tinactive?: boolean;\n\t\t\t\t},\n\t\t) => {\n\t\t\tconst project =\n\t\t\t\topts.allProjects === true\n\t\t\t\t\t? null\n\t\t\t\t\t: opts.project?.trim() ||\n\t\t\t\t\t\tprocess.env.CODEMEM_PROJECT?.trim() ||\n\t\t\t\t\t\tresolveProject(process.cwd(), null);\n\t\t\tconst invalidScenario = (opts.scenario ?? []).find(\n\t\t\t\t(id) => getInjectionEvalScenarioPack(id) == null,\n\t\t\t);\n\t\t\tif (invalidScenario) {\n\t\t\t\tthrow new Error(`Unknown eval scenario pack: ${invalidScenario}`);\n\t\t\t}\n\t\t\tconst probes = [\n\t\t\t\t...(opts.probe ?? []),\n\t\t\t\t...getInjectionEvalScenarioPrompts(opts.scenario ?? []),\n\t\t\t];\n\t\t\tconst result = getMemoryRoleReport(resolveDbOpt(opts), {\n\t\t\t\tproject,\n\t\t\t\tallProjects: opts.allProjects === true,\n\t\t\t\tincludeInactive: opts.inactive === true,\n\t\t\t\tprobes,\n\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tp.intro(\"codemem memory role-report\");\n\t\t\tp.log.info(\n\t\t\t\t[\n\t\t\t\t\t`Memories: ${result.totals.memories}`,\n\t\t\t\t\t`Active: ${result.totals.active}`,\n\t\t\t\t\t`Sessions: ${result.totals.sessions}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t\tp.log.info(\"Counts by role:\");\n\t\t\tfor (const [role, count] of Object.entries(result.counts_by_role)) {\n\t\t\t\tp.log.message(` ${role.padEnd(10)} ${String(count)}`);\n\t\t\t}\n\t\t\tp.log.info(\"Counts by mapping:\");\n\t\t\tp.log.message(` mapped ${result.counts_by_mapping.mapped}`);\n\t\t\tp.log.message(` unmapped ${result.counts_by_mapping.unmapped}`);\n\t\t\tp.log.info(\"Summary lineages:\");\n\t\t\tp.log.message(` session_summary ${result.summary_lineages.session_summary}`);\n\t\t\tp.log.message(` legacy_metadata_summary ${result.summary_lineages.legacy_metadata_summary}`);\n\t\t\tp.log.message(` summary_mapped ${result.summary_mapping.mapped}`);\n\t\t\tp.log.message(` summary_unmapped ${result.summary_mapping.unmapped}`);\n\t\t\tp.log.info(\"Project quality:\");\n\t\t\tfor (const [bucket, count] of Object.entries(result.project_quality)) {\n\t\t\t\tp.log.message(` ${bucket.padEnd(12)} ${String(count)}`);\n\t\t\t}\n\t\t\tp.log.info(\"Session classes:\");\n\t\t\tfor (const [bucket, count] of Object.entries(result.session_class_buckets)) {\n\t\t\t\tp.log.message(` ${bucket.padEnd(20)} ${String(count)}`);\n\t\t\t}\n\t\t\tp.log.info(\"Summary dispositions:\");\n\t\t\tfor (const [bucket, count] of Object.entries(result.summary_disposition_buckets)) {\n\t\t\t\tp.log.message(` ${bucket.padEnd(20)} ${String(count)}`);\n\t\t\t}\n\t\t\tif (result.probe_results.length > 0) {\n\t\t\t\tp.log.info(\"Probe results:\");\n\t\t\t\tfor (const probe of result.probe_results) {\n\t\t\t\t\tp.log.message(` query: ${probe.query}`);\n\t\t\t\t\tif (probe.scenario_id) {\n\t\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t\t` scenario: ${probe.scenario_id} (${probe.scenario_category ?? \"unknown\"})${probe.scenario_title ? ` — ${probe.scenario_title}` : \"\"}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tp.log.message(` mode: ${probe.mode}`);\n\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t` top roles: durable=${probe.top_role_counts.durable} recap=${probe.top_role_counts.recap} ephemeral=${probe.top_role_counts.ephemeral} general=${probe.top_role_counts.general}`,\n\t\t\t\t\t);\n\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t` top mapping: mapped=${probe.top_mapping_counts.mapped} unmapped=${probe.top_mapping_counts.unmapped}`,\n\t\t\t\t\t);\n\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t` burden: recap_share=${probe.top_burden.recap_share.toFixed(2)} unmapped_share=${probe.top_burden.unmapped_share.toFixed(2)} recap_unmapped_share=${probe.top_burden.recap_unmapped_share.toFixed(2)}`,\n\t\t\t\t\t);\n\t\t\t\t\tif (probe.simulated_demoted_unmapped_recap) {\n\t\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t\t` simulated demote-unmapped-recap burden: recap_share=${probe.simulated_demoted_unmapped_recap.top_burden.recap_share.toFixed(2)} unmapped_share=${probe.simulated_demoted_unmapped_recap.top_burden.unmapped_share.toFixed(2)} recap_unmapped_share=${probe.simulated_demoted_unmapped_recap.top_burden.recap_unmapped_share.toFixed(2)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (probe.simulated_demoted_unmapped_recap_and_ephemeral) {\n\t\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t\t` simulated demote-unmapped-recap+ephemeral burden: recap_share=${probe.simulated_demoted_unmapped_recap_and_ephemeral.top_burden.recap_share.toFixed(2)} unmapped_share=${probe.simulated_demoted_unmapped_recap_and_ephemeral.top_burden.unmapped_share.toFixed(2)} recap_unmapped_share=${probe.simulated_demoted_unmapped_recap_and_ephemeral.top_burden.recap_unmapped_share.toFixed(2)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (probe.scenario_score) {\n\t\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t\t` scenario score: mode_match=${probe.scenario_score.mode_match ? \"yes\" : \"no\"} top1_primary=${probe.scenario_score.primary_in_top1 ? \"yes\" : \"no\"} top3_primary=${probe.scenario_score.primary_in_top3_count} top1_anti=${probe.scenario_score.anti_signal_in_top1 ? \"yes\" : \"no\"} primary=${probe.scenario_score.primary_match_count} anti=${probe.scenario_score.anti_signal_count} recap=${probe.scenario_score.recap_count} unmapped_recap=${probe.scenario_score.unmapped_recap_count} chatter=${probe.scenario_score.administrative_chatter_count} net=${probe.scenario_score.score}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tfor (const item of probe.items.slice(0, 5)) {\n\t\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t\t` [${item.id}] (${item.kind}/${item.role}/${item.mapping}/${item.session_class}/${item.summary_disposition}) ${item.title} — ${item.role_reason}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tp.outro(\"done\");\n\t\t},\n\t);\n\treturn cmd;\n}\n\nfunction createMemoryRoleCompareCommand(): Command {\n\tconst cmd = new Command(\"role-compare\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Compare inferred memory-role and probe metrics across two DB snapshots\")\n\t\t.argument(\"<baseline_db>\", \"baseline sqlite database path\")\n\t\t.argument(\"<candidate_db>\", \"candidate sqlite database path\")\n\t\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t\t.option(\"--all-projects\", \"analyze across all projects\")\n\t\t.option(\n\t\t\t\"--probe <query>\",\n\t\t\t\"run a retrieval probe query against both snapshots\",\n\t\t\t(value, prev: string[]) => [...prev, value],\n\t\t\t[],\n\t\t)\n\t\t.option(\n\t\t\t\"--scenario <id>\",\n\t\t\t\"run a named injection-first eval scenario pack (can be repeated)\",\n\t\t\t(value, prev: string[]) => [...prev, value],\n\t\t\t[],\n\t\t)\n\t\t.option(\"--inactive\", \"include inactive memories\");\n\taddJsonOption(cmd);\n\tcmd.action(\n\t\t(\n\t\t\tbaselineDb: string,\n\t\t\tcandidateDb: string,\n\t\t\topts: JsonOpts & {\n\t\t\t\tproject?: string;\n\t\t\t\tallProjects?: boolean;\n\t\t\t\tprobe?: string[];\n\t\t\t\tscenario?: string[];\n\t\t\t\tinactive?: boolean;\n\t\t\t},\n\t\t) => {\n\t\t\tconst project =\n\t\t\t\topts.allProjects === true\n\t\t\t\t\t? null\n\t\t\t\t\t: opts.project?.trim() ||\n\t\t\t\t\t\tprocess.env.CODEMEM_PROJECT?.trim() ||\n\t\t\t\t\t\tresolveProject(process.cwd(), null);\n\t\t\tconst invalidScenario = (opts.scenario ?? []).find(\n\t\t\t\t(id) => getInjectionEvalScenarioPack(id) == null,\n\t\t\t);\n\t\t\tif (invalidScenario) {\n\t\t\t\tthrow new Error(`Unknown eval scenario pack: ${invalidScenario}`);\n\t\t\t}\n\t\t\tconst probes = [\n\t\t\t\t...(opts.probe ?? []),\n\t\t\t\t...getInjectionEvalScenarioPrompts(opts.scenario ?? []),\n\t\t\t];\n\t\t\tconst result = compareMemoryRoleReports(baselineDb, candidateDb, {\n\t\t\t\tproject,\n\t\t\t\tallProjects: opts.allProjects === true,\n\t\t\t\tincludeInactive: opts.inactive === true,\n\t\t\t\tprobes,\n\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tp.intro(\"codemem memory role-compare\");\n\t\t\tp.log.info(\n\t\t\t\t[\n\t\t\t\t\t`Baseline sessions: ${result.baseline.totals.sessions}`,\n\t\t\t\t\t`Candidate sessions: ${result.candidate.totals.sessions}`,\n\t\t\t\t\t`Delta sessions: ${result.delta.totals.sessions}`,\n\t\t\t\t\t`Mapped delta: ${result.delta.counts_by_mapping.mapped}`,\n\t\t\t\t\t`Unmapped delta: ${result.delta.counts_by_mapping.unmapped}`,\n\t\t\t\t\t`Summary mapped delta: ${result.delta.summary_mapping.mapped}`,\n\t\t\t\t\t`Summary unmapped delta: ${result.delta.summary_mapping.unmapped}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t\tp.log.info(\"Role deltas:\");\n\t\t\tfor (const [role, count] of Object.entries(result.delta.counts_by_role)) {\n\t\t\t\tp.log.message(` ${role.padEnd(10)} ${String(count)}`);\n\t\t\t}\n\t\t\tp.log.info(\"Session class deltas:\");\n\t\t\tfor (const [bucket, count] of Object.entries(result.delta.session_class_buckets)) {\n\t\t\t\tp.log.message(` ${bucket.padEnd(20)} ${String(count)}`);\n\t\t\t}\n\t\t\tp.log.info(\"Summary disposition deltas:\");\n\t\t\tfor (const [bucket, count] of Object.entries(result.delta.summary_disposition_buckets)) {\n\t\t\t\tp.log.message(` ${bucket.padEnd(20)} ${String(count)}`);\n\t\t\t}\n\t\t\tif (result.probe_comparisons.length > 0) {\n\t\t\t\tp.log.info(\"Probe comparisons:\");\n\t\t\t\tfor (const probe of result.probe_comparisons) {\n\t\t\t\t\tp.log.message(` query: ${probe.query}`);\n\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t` modes: baseline=${probe.baseline_mode ?? \"-\"} candidate=${probe.candidate_mode ?? \"-\"}`,\n\t\t\t\t\t);\n\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t` overlap: shared_top_keys=${probe.shared_item_keys.length} baseline_top=${probe.baseline_item_ids.slice(0, 5).join(\",\") || \"-\"} candidate_top=${probe.candidate_item_ids.slice(0, 5).join(\",\") || \"-\"}`,\n\t\t\t\t\t);\n\t\t\t\t\tif (probe.delta_top_burden) {\n\t\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t\t` burden delta: recap_share=${probe.delta_top_burden.recap_share.toFixed(2)} unmapped_share=${probe.delta_top_burden.unmapped_share.toFixed(2)} recap_unmapped_share=${probe.delta_top_burden.recap_unmapped_share.toFixed(2)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (probe.delta_top_mapping_counts) {\n\t\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t\t` mapping delta: mapped=${probe.delta_top_mapping_counts.mapped} unmapped=${probe.delta_top_mapping_counts.unmapped}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (probe.baseline_scenario_score || probe.candidate_scenario_score) {\n\t\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t\t` scenario scores: baseline=${probe.baseline_scenario_score?.score ?? \"-\"} candidate=${probe.candidate_scenario_score?.score ?? \"-\"}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (probe.delta_scenario_score) {\n\t\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t\t` scenario delta: mode_match=${probe.delta_scenario_score.mode_match ?? \"-\"} top1_primary=${probe.delta_scenario_score.primary_in_top1 ?? \"-\"} top3_primary=${probe.delta_scenario_score.primary_in_top3_count ?? \"-\"} top1_anti=${probe.delta_scenario_score.anti_signal_in_top1 ?? \"-\"} primary=${probe.delta_scenario_score.primary_match_count ?? \"-\"} anti=${probe.delta_scenario_score.anti_signal_count ?? \"-\"} recap=${probe.delta_scenario_score.recap_count ?? \"-\"} unmapped_recap=${probe.delta_scenario_score.unmapped_recap_count ?? \"-\"} chatter=${probe.delta_scenario_score.administrative_chatter_count ?? \"-\"} net=${probe.delta_scenario_score.score ?? \"-\"}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tp.outro(\"done\");\n\t\t},\n\t);\n\treturn cmd;\n}\n\nfunction createMemoryExtractionReportCommand(): Command {\n\tconst cmd = new Command(\"extraction-report\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Score extracted memories for a session against a built-in extraction eval rubric\")\n\t\t.option(\"--session-id <id>\", \"session ID to evaluate\")\n\t\t.option(\"--batch-id <id>\", \"raw-event flush batch ID to evaluate\")\n\t\t.requiredOption(\"--scenario <id>\", \"built-in extraction eval scenario ID\")\n\t\t.option(\"--inactive\", \"include inactive memories\");\n\taddDbOption(cmd);\n\taddJsonOption(cmd);\n\tcmd.action(\n\t\t(\n\t\t\topts: DbOpts &\n\t\t\t\tJsonOpts & {\n\t\t\t\t\tsessionId: string;\n\t\t\t\t\tbatchId?: string;\n\t\t\t\t\tscenario: string;\n\t\t\t\t\tinactive?: boolean;\n\t\t\t\t},\n\t\t) => {\n\t\t\tconst sessionIdInput = opts.sessionId?.trim() ?? \"\";\n\t\t\tconst batchIdInput = opts.batchId?.trim() ?? \"\";\n\t\t\tconst hasSessionId = sessionIdInput.length > 0;\n\t\t\tconst hasBatchId = batchIdInput.length > 0;\n\t\t\tif (hasSessionId === hasBatchId) {\n\t\t\t\tthrow new Error(\"Provide exactly one of --session-id or --batch-id\");\n\t\t\t}\n\t\t\tconst sessionId = hasSessionId ? parseStrictPositiveId(sessionIdInput) : null;\n\t\t\tif (hasSessionId && sessionId === null) {\n\t\t\t\tthrow new Error(`Invalid session ID: ${sessionIdInput || opts.sessionId}`);\n\t\t\t}\n\t\t\tconst batchId = hasBatchId ? parseStrictPositiveId(batchIdInput) : null;\n\t\t\tif (hasBatchId && batchId === null) {\n\t\t\t\tthrow new Error(`Invalid batch ID: ${batchIdInput || opts.batchId}`);\n\t\t\t}\n\t\t\tconst scenarioId = opts.scenario?.trim() ?? \"\";\n\t\t\tconst scenario = getSessionExtractionEvalScenario(scenarioId);\n\t\t\tif (!scenario) {\n\t\t\t\tthrow new Error(`Unknown extraction eval scenario: ${scenarioId || opts.scenario}`);\n\t\t\t}\n\t\t\tconst result =\n\t\t\t\tbatchId != null\n\t\t\t\t\t? getSessionExtractionEval(resolveDbOpt(opts), {\n\t\t\t\t\t\t\tbatchId,\n\t\t\t\t\t\t\tscenarioId: scenario.id,\n\t\t\t\t\t\t\tincludeInactive: opts.inactive === true,\n\t\t\t\t\t\t})\n\t\t\t\t\t: getSessionExtractionEval(resolveDbOpt(opts), {\n\t\t\t\t\t\t\tsessionId: sessionId as number,\n\t\t\t\t\t\t\tscenarioId: scenario.id,\n\t\t\t\t\t\t\tincludeInactive: opts.inactive === true,\n\t\t\t\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tp.intro(\"codemem memory extraction-report\");\n\t\t\tp.log.info(\n\t\t\t\t[\n\t\t\t\t\t`Scenario: ${result.scenario.id} — ${result.scenario.title}`,\n\t\t\t\t\t`Target: ${result.target.type}${result.target.batchId != null ? ` #${result.target.batchId}` : \"\"}`,\n\t\t\t\t\t`Session: ${result.session.id} (${result.session.project ?? \"no-project\"})`,\n\t\t\t\t\t`Session class: ${result.session.sessionClass}`,\n\t\t\t\t\t`Summary disposition: ${result.session.summaryDisposition}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t\tp.log.info(\n\t\t\t\t[\n\t\t\t\t\t`Pass: ${result.pass ? \"yes\" : \"no\"}`,\n\t\t\t\t\t`Summary count: ${result.counts.summaries}`,\n\t\t\t\t\t`Observation count: ${result.counts.observations}`,\n\t\t\t\t\t`Summary thread coverage: ${result.coverage.summaryThreadCoverage}`,\n\t\t\t\t\t`Observation thread coverage: ${result.coverage.observationThreadCoverage}`,\n\t\t\t\t\t`Total thread coverage: ${result.coverage.totalThreadCoverage}`,\n\t\t\t\t\t`Duplicate observation threads: ${result.coverage.duplicateObservationThreads}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t\tif (result.failureReasons.length > 0) {\n\t\t\t\tp.log.warn(\"Failure reasons:\");\n\t\t\t\tfor (const reason of result.failureReasons) {\n\t\t\t\t\tp.log.message(` - ${reason}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tp.log.info(\"Thread coverage:\");\n\t\t\tfor (const thread of result.threads) {\n\t\t\t\tp.log.message(\n\t\t\t\t\t` ${thread.id.padEnd(22)} summary=${thread.summaryMatch ? \"yes\" : \"no\"} observations=${thread.observationMatch ? \"yes\" : \"no\"}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tp.outro(\"done\");\n\t\t},\n\t);\n\treturn cmd;\n}\n\nfunction createMemoryExtractionReplayCommand(): Command {\n\tconst cmd = new Command(\"extraction-replay\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\n\t\t\t\"Re-run the observer on a historical flush batch without persisting, then score the fresh output\",\n\t\t)\n\t\t.requiredOption(\"--batch-id <id>\", \"raw-event flush batch ID to replay\")\n\t\t.option(\n\t\t\t\"--transcript-budget <chars>\",\n\t\t\t\"override replay transcript budget in characters (replay only)\",\n\t\t)\n\t\t.option(\"--observer-tier-routing\", \"use replay-only benchmark-backed observer tier routing\")\n\t\t.option(\"--observer-temperature <value>\", \"override observer temperature for replay only\")\n\t\t.option(\"--openai-responses\", \"use OpenAI Responses API for replay only\")\n\t\t.option(\n\t\t\t\"--reasoning-effort <level>\",\n\t\t\t\"set OpenAI reasoning.effort for replay only (responses path)\",\n\t\t)\n\t\t.option(\n\t\t\t\"--reasoning-summary <mode>\",\n\t\t\t\"set OpenAI reasoning.summary for replay only (responses path)\",\n\t\t)\n\t\t.option(\n\t\t\t\"--max-output-tokens <n>\",\n\t\t\t\"override OpenAI max_output_tokens for replay only (responses path)\",\n\t\t)\n\t\t.requiredOption(\"--scenario <id>\", \"built-in extraction eval scenario ID\");\n\taddDbOption(cmd);\n\taddJsonOption(cmd);\n\tcmd.action(\n\t\tasync (\n\t\t\topts: DbOpts &\n\t\t\t\tJsonOpts & {\n\t\t\t\t\tbatchId: string;\n\t\t\t\t\tobserverTierRouting?: boolean;\n\t\t\t\t\topenaiResponses?: boolean;\n\t\t\t\t\treasoningEffort?: string;\n\t\t\t\t\treasoningSummary?: string;\n\t\t\t\t\tmaxOutputTokens?: string;\n\t\t\t\t\tobserverTemperature?: string;\n\t\t\t\t\ttranscriptBudget?: string;\n\t\t\t\t\tscenario: string;\n\t\t\t\t},\n\t\t) => {\n\t\t\tconst batchIdInput = opts.batchId?.trim() ?? \"\";\n\t\t\tconst batchId = parseStrictPositiveId(batchIdInput);\n\t\t\tif (batchId === null) {\n\t\t\t\tthrow new Error(`Invalid batch ID: ${batchIdInput || opts.batchId}`);\n\t\t\t}\n\t\t\tconst scenarioId = opts.scenario?.trim() ?? \"\";\n\t\t\tconst scenario = getSessionExtractionEvalScenario(scenarioId);\n\t\t\tif (!scenario) {\n\t\t\t\tthrow new Error(`Unknown extraction eval scenario: ${scenarioId || opts.scenario}`);\n\t\t\t}\n\t\t\tconst transcriptBudgetInput = opts.transcriptBudget?.trim() ?? \"\";\n\t\t\tconst transcriptBudget =\n\t\t\t\ttranscriptBudgetInput.length > 0 ? parseStrictPositiveId(transcriptBudgetInput) : null;\n\t\t\tif (transcriptBudgetInput.length > 0 && transcriptBudget === null) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid transcript budget: ${transcriptBudgetInput || opts.transcriptBudget}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst observerTemperatureInput = opts.observerTemperature?.trim() ?? \"\";\n\t\t\tlet observerTemperature: number | undefined;\n\t\t\tif (observerTemperatureInput.length > 0) {\n\t\t\t\tconst parsed = Number(observerTemperatureInput);\n\t\t\t\tif (!Number.isFinite(parsed)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Invalid observer temperature: ${observerTemperatureInput || opts.observerTemperature}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tobserverTemperature = parsed;\n\t\t\t}\n\t\t\tconst maxOutputTokensInput = opts.maxOutputTokens?.trim() ?? \"\";\n\t\t\tconst maxOutputTokens =\n\t\t\t\tmaxOutputTokensInput.length > 0 ? parseStrictPositiveId(maxOutputTokensInput) : null;\n\t\t\tif (maxOutputTokensInput.length > 0 && maxOutputTokens === null) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid max output tokens: ${maxOutputTokensInput || opts.maxOutputTokens}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst observerConfig = loadObserverConfig();\n\t\t\tconst observerConfigWithOverrides = {\n\t\t\t\t...observerConfig,\n\t\t\t\tobserverTemperature: observerTemperature ?? observerConfig.observerTemperature,\n\t\t\t\tobserverOpenAIUseResponses: opts.openaiResponses === true,\n\t\t\t\tobserverReasoningEffort: opts.reasoningEffort?.trim() || null,\n\t\t\t\tobserverReasoningSummary: opts.reasoningSummary?.trim() || null,\n\t\t\t\tobserverMaxOutputTokens: maxOutputTokens ?? observerConfig.observerMaxTokens,\n\t\t\t};\n\t\t\tconst observer = new ObserverClient(observerConfigWithOverrides);\n\t\t\tconst result =\n\t\t\t\topts.observerTierRouting === true\n\t\t\t\t\t? await replayBatchExtractionWithTierRouting(\n\t\t\t\t\t\t\tresolveDbOpt(opts),\n\t\t\t\t\t\t\tobserverConfigWithOverrides,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbatchId,\n\t\t\t\t\t\t\t\tscenarioId: scenario.id,\n\t\t\t\t\t\t\t\ttranscriptBudget: transcriptBudget ?? undefined,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t)\n\t\t\t\t\t: await replayBatchExtraction(resolveDbOpt(opts), observer, {\n\t\t\t\t\t\t\tbatchId,\n\t\t\t\t\t\t\tscenarioId: scenario.id,\n\t\t\t\t\t\t\ttranscriptBudget: transcriptBudget ?? undefined,\n\t\t\t\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tp.intro(\"codemem memory extraction-replay\");\n\t\t\tp.log.info(\n\t\t\t\t[\n\t\t\t\t\t`Scenario: ${result.scenario.id} — ${result.scenario.title}`,\n\t\t\t\t\t`Batch: ${result.target.batchId}`,\n\t\t\t\t\t`Session: ${result.target.sessionId}`,\n\t\t\t\t\t`Observer: ${result.observer.provider}/${result.observer.model}`,\n\t\t\t\t\t`Tier: ${result.observer.tier ?? \"manual\"}`,\n\t\t\t\t\t`OpenAI Responses: ${result.observer.openaiUseResponses ? \"yes\" : \"no\"}`,\n\t\t\t\t\t`Reasoning effort: ${result.observer.reasoningEffort ?? \"none\"}`,\n\t\t\t\t\t`Classification: ${result.classification.status}`,\n\t\t\t\t\t`Pass: ${result.evaluation.pass ? \"yes\" : \"no\"}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t\tif (result.classification.reason) {\n\t\t\t\tp.log.message(`Classification reason: ${result.classification.reason}`);\n\t\t\t}\n\t\t\tif (result.evaluation.failureReasons.length > 0) {\n\t\t\t\tp.log.warn(\"Failure reasons:\");\n\t\t\t\tfor (const reason of result.evaluation.failureReasons) {\n\t\t\t\t\tp.log.message(` - ${reason}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tp.log.info(\n\t\t\t\t[\n\t\t\t\t\t`Fresh summaries: ${result.evaluation.counts.summaries}`,\n\t\t\t\t\t`Fresh observations: ${result.evaluation.counts.observations}`,\n\t\t\t\t\t`Summary thread coverage: ${result.evaluation.coverage.summaryThreadCoverage}`,\n\t\t\t\t\t`Observation thread coverage: ${result.evaluation.coverage.observationThreadCoverage}`,\n\t\t\t\t\t`Total thread coverage: ${result.evaluation.coverage.totalThreadCoverage}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t\tp.outro(\"done\");\n\t\t},\n\t);\n\treturn cmd;\n}\n\nfunction createMemoryExtractionBenchmarkCommand(): Command {\n\tconst cmd = new Command(\"extraction-benchmark\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\n\t\t\t\"Run the formal extraction replay benchmark set and print a cost/quality scoreboard\",\n\t\t)\n\t\t.requiredOption(\"--benchmark <id>\", \"benchmark profile id\")\n\t\t.option(\"--observer-provider <provider>\", \"override observer provider for this benchmark run\")\n\t\t.option(\"--observer-model <model>\", \"override observer model for this benchmark run\")\n\t\t.option(\"--observer-tier-routing\", \"use replay-only benchmark-backed observer tier routing\")\n\t\t.option(\"--openai-responses\", \"use OpenAI Responses API for this benchmark run\")\n\t\t.option(\n\t\t\t\"--reasoning-effort <level>\",\n\t\t\t\"set OpenAI reasoning.effort for this benchmark run (responses path)\",\n\t\t)\n\t\t.option(\n\t\t\t\"--reasoning-summary <mode>\",\n\t\t\t\"set OpenAI reasoning.summary for this benchmark run (responses path)\",\n\t\t)\n\t\t.option(\n\t\t\t\"--max-output-tokens <n>\",\n\t\t\t\"override OpenAI max_output_tokens for this benchmark run (responses path)\",\n\t\t)\n\t\t.option(\n\t\t\t\"--observer-temperature <value>\",\n\t\t\t\"override observer temperature for this benchmark run\",\n\t\t)\n\t\t.option(\n\t\t\t\"--transcript-budget <chars>\",\n\t\t\t\"override replay transcript budget in characters for this benchmark run\",\n\t\t);\n\taddDbOption(cmd);\n\taddJsonOption(cmd);\n\tcmd.action(\n\t\tasync (\n\t\t\topts: DbOpts &\n\t\t\t\tJsonOpts & {\n\t\t\t\t\tbenchmark: string;\n\t\t\t\t\tobserverProvider?: string;\n\t\t\t\t\tobserverModel?: string;\n\t\t\t\t\tobserverTierRouting?: boolean;\n\t\t\t\t\topenaiResponses?: boolean;\n\t\t\t\t\treasoningEffort?: string;\n\t\t\t\t\treasoningSummary?: string;\n\t\t\t\t\tmaxOutputTokens?: string;\n\t\t\t\t\tobserverTemperature?: string;\n\t\t\t\t\ttranscriptBudget?: string;\n\t\t\t\t},\n\t\t) => {\n\t\t\tconst benchmarkId = opts.benchmark?.trim() ?? \"\";\n\t\t\tconst benchmark = getExtractionBenchmarkProfile(benchmarkId);\n\t\t\tif (!benchmark) {\n\t\t\t\tthrow new Error(`Unknown extraction benchmark: ${benchmarkId || opts.benchmark}`);\n\t\t\t}\n\t\t\tconst transcriptBudgetInput = opts.transcriptBudget?.trim() ?? \"\";\n\t\t\tconst transcriptBudget =\n\t\t\t\ttranscriptBudgetInput.length > 0 ? parseStrictPositiveId(transcriptBudgetInput) : null;\n\t\t\tif (transcriptBudgetInput.length > 0 && transcriptBudget === null) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid transcript budget: ${transcriptBudgetInput || opts.transcriptBudget}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst observerTemperatureInput = opts.observerTemperature?.trim() ?? \"\";\n\t\t\tlet observerTemperature: number | undefined;\n\t\t\tif (observerTemperatureInput.length > 0) {\n\t\t\t\tconst parsed = Number(observerTemperatureInput);\n\t\t\t\tif (!Number.isFinite(parsed)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Invalid observer temperature: ${observerTemperatureInput || opts.observerTemperature}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tobserverTemperature = parsed;\n\t\t\t}\n\t\t\tconst maxOutputTokensInput = opts.maxOutputTokens?.trim() ?? \"\";\n\t\t\tconst maxOutputTokens =\n\t\t\t\tmaxOutputTokensInput.length > 0 ? parseStrictPositiveId(maxOutputTokensInput) : null;\n\t\t\tif (maxOutputTokensInput.length > 0 && maxOutputTokens === null) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid max output tokens: ${maxOutputTokensInput || opts.maxOutputTokens}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst observerConfig = loadObserverConfig();\n\t\t\tconst observerConfigWithOverrides = {\n\t\t\t\t...observerConfig,\n\t\t\t\tobserverProvider: opts.observerProvider?.trim() || observerConfig.observerProvider,\n\t\t\t\tobserverModel: opts.observerModel?.trim() || observerConfig.observerModel,\n\t\t\t\tobserverTemperature: observerTemperature ?? observerConfig.observerTemperature,\n\t\t\t\tobserverOpenAIUseResponses: opts.openaiResponses === true,\n\t\t\t\tobserverReasoningEffort: opts.reasoningEffort?.trim() || null,\n\t\t\t\tobserverReasoningSummary: opts.reasoningSummary?.trim() || null,\n\t\t\t\tobserverMaxOutputTokens: maxOutputTokens ?? observerConfig.observerMaxTokens,\n\t\t\t};\n\t\t\tconst observer = new ObserverClient(observerConfigWithOverrides);\n\t\t\tconst runs = [] as Array<{\n\t\t\t\tbatchId: number;\n\t\t\t\tsessionId: number;\n\t\t\t\tlabel: string;\n\t\t\t\tpurpose: \"shape_quality\" | \"replay_robustness\";\n\t\t\t\tcomplexity: string;\n\t\t\t\tscenarioId: string;\n\t\t\t\texpectedTier: string | null;\n\t\t\t\tanalysis: {\n\t\t\t\t\teventSpan: number;\n\t\t\t\t\tpromptCount: number;\n\t\t\t\t\ttoolCount: number;\n\t\t\t\t\ttranscriptLength: number;\n\t\t\t\t};\n\t\t\t\tstatus: \"pass\" | \"shape_fail\" | \"observer_no_output\";\n\t\t\t\treason: string;\n\t\t\t\ttier: string;\n\t\t\t\tprovider: string;\n\t\t\t\tmodel: string;\n\t\t\t\topenaiUseResponses: boolean;\n\t\t\t\treasoningEffort: string | null;\n\t\t\t\treasoningSummary: string | null;\n\t\t\t\tmaxOutputTokens: number;\n\t\t\t\ttemperature: number | null;\n\t\t\t\tsummaries: number;\n\t\t\t\tobservations: number;\n\t\t\t\trepairApplied: boolean;\n\t\t\t}>;\n\t\t\tfor (const batch of benchmark.batches) {\n\t\t\t\tconst scenarioId = batch.scenarioId ?? benchmark.scenarioId;\n\t\t\t\tconst result =\n\t\t\t\t\topts.observerTierRouting === true\n\t\t\t\t\t\t? await replayBatchExtractionWithTierRouting(\n\t\t\t\t\t\t\t\tresolveDbOpt(opts),\n\t\t\t\t\t\t\t\tobserverConfigWithOverrides,\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tbatchId: batch.batchId,\n\t\t\t\t\t\t\t\t\tscenarioId,\n\t\t\t\t\t\t\t\t\ttranscriptBudget: transcriptBudget ?? undefined,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: await replayBatchExtraction(resolveDbOpt(opts), observer, {\n\t\t\t\t\t\t\t\tbatchId: batch.batchId,\n\t\t\t\t\t\t\t\tscenarioId,\n\t\t\t\t\t\t\t\ttranscriptBudget: transcriptBudget ?? undefined,\n\t\t\t\t\t\t\t});\n\t\t\t\truns.push({\n\t\t\t\t\tbatchId: batch.batchId,\n\t\t\t\t\tsessionId: batch.sessionId,\n\t\t\t\t\tlabel: batch.label,\n\t\t\t\t\tpurpose: batch.purpose,\n\t\t\t\t\tcomplexity: batch.complexity,\n\t\t\t\t\tscenarioId,\n\t\t\t\t\texpectedTier: batch.expectedTier ?? null,\n\t\t\t\t\tanalysis: {\n\t\t\t\t\t\teventSpan: result.analysis.eventSpan,\n\t\t\t\t\t\tpromptCount: result.analysis.promptCount,\n\t\t\t\t\t\ttoolCount: result.analysis.toolCount,\n\t\t\t\t\t\ttranscriptLength: result.analysis.transcriptLength,\n\t\t\t\t\t},\n\t\t\t\t\tstatus: result.classification.status,\n\t\t\t\t\treason: result.classification.reason,\n\t\t\t\t\ttier: result.observer.tier ?? \"manual\",\n\t\t\t\t\tprovider: result.observer.provider,\n\t\t\t\t\tmodel: result.observer.model,\n\t\t\t\t\topenaiUseResponses: result.observer.openaiUseResponses,\n\t\t\t\t\treasoningEffort: result.observer.reasoningEffort,\n\t\t\t\t\treasoningSummary: result.observer.reasoningSummary,\n\t\t\t\t\tmaxOutputTokens: result.observer.maxOutputTokens,\n\t\t\t\t\ttemperature: result.observer.temperature,\n\t\t\t\t\tsummaries: result.evaluation.counts.summaries,\n\t\t\t\t\tobservations: result.evaluation.counts.observations,\n\t\t\t\t\trepairApplied: result.observer.repairApplied,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst summary = {\n\t\t\t\ttotal: runs.length,\n\t\t\t\tshapeQualityTotal: runs.filter((run) => run.purpose === \"shape_quality\").length,\n\t\t\t\tshapeQualityPasses: runs.filter(\n\t\t\t\t\t(run) => run.purpose === \"shape_quality\" && run.status === \"pass\",\n\t\t\t\t).length,\n\t\t\t\tshapeQualityFails: runs.filter(\n\t\t\t\t\t(run) => run.purpose === \"shape_quality\" && run.status === \"shape_fail\",\n\t\t\t\t).length,\n\t\t\t\texpectedTierTotal: runs.filter((run) => run.expectedTier != null).length,\n\t\t\t\texpectedTierMatches: runs.filter(\n\t\t\t\t\t(run) => run.expectedTier != null && run.expectedTier === run.tier,\n\t\t\t\t).length,\n\t\t\t\trobustnessNoOutput: runs.filter((run) => run.status === \"observer_no_output\").length,\n\t\t\t};\n\t\t\tconst uniqueObserverKeys = Array.from(\n\t\t\t\tnew Set(\n\t\t\t\t\truns.map(\n\t\t\t\t\t\t(run) =>\n\t\t\t\t\t\t\t`${run.provider}::${run.model}::${run.openaiUseResponses ? \"responses\" : \"chat\"}`,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t);\n\t\t\tconst observerSummary =\n\t\t\t\topts.observerTierRouting === true\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tprovider:\n\t\t\t\t\t\t\t\tuniqueObserverKeys.length === 1\n\t\t\t\t\t\t\t\t\t? (runs[0]?.provider ?? observer.provider)\n\t\t\t\t\t\t\t\t\t: \"mixed\",\n\t\t\t\t\t\t\tmodel: uniqueObserverKeys.length === 1 ? (runs[0]?.model ?? observer.model) : \"mixed\",\n\t\t\t\t\t\t\ttierRouting: true,\n\t\t\t\t\t\t\topenaiUseResponses:\n\t\t\t\t\t\t\t\tuniqueObserverKeys.length === 1\n\t\t\t\t\t\t\t\t\t? (runs[0]?.openaiUseResponses ?? observer.openaiUseResponses)\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\treasoningEffort:\n\t\t\t\t\t\t\t\tuniqueObserverKeys.length === 1\n\t\t\t\t\t\t\t\t\t? (runs[0]?.reasoningEffort ?? observer.reasoningEffort)\n\t\t\t\t\t\t\t\t\t: \"mixed\",\n\t\t\t\t\t\t\treasoningSummary:\n\t\t\t\t\t\t\t\tuniqueObserverKeys.length === 1\n\t\t\t\t\t\t\t\t\t? (runs[0]?.reasoningSummary ?? observer.reasoningSummary)\n\t\t\t\t\t\t\t\t\t: \"mixed\",\n\t\t\t\t\t\t\tmaxOutputTokens:\n\t\t\t\t\t\t\t\tuniqueObserverKeys.length === 1\n\t\t\t\t\t\t\t\t\t? (runs[0]?.maxOutputTokens ?? observer.maxOutputTokens)\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\ttemperature:\n\t\t\t\t\t\t\t\tuniqueObserverKeys.length === 1\n\t\t\t\t\t\t\t\t\t? (runs[0]?.temperature ?? observer.temperature)\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\ttranscriptBudget: transcriptBudget ?? null,\n\t\t\t\t\t\t\tselectedObservers: uniqueObserverKeys,\n\t\t\t\t\t\t}\n\t\t\t\t\t: {\n\t\t\t\t\t\t\tprovider: observer.provider,\n\t\t\t\t\t\t\tmodel: observer.model,\n\t\t\t\t\t\t\ttierRouting: false,\n\t\t\t\t\t\t\topenaiUseResponses: observer.openaiUseResponses,\n\t\t\t\t\t\t\treasoningEffort: observer.reasoningEffort,\n\t\t\t\t\t\t\treasoningSummary: observer.reasoningSummary,\n\t\t\t\t\t\t\tmaxOutputTokens: observer.maxOutputTokens,\n\t\t\t\t\t\t\ttemperature: observer.temperature,\n\t\t\t\t\t\t\ttranscriptBudget: transcriptBudget ?? null,\n\t\t\t\t\t\t\tselectedObservers: uniqueObserverKeys,\n\t\t\t\t\t\t};\n\t\t\tconst output = {\n\t\t\t\tbenchmark: {\n\t\t\t\t\tid: benchmark.id,\n\t\t\t\t\ttitle: benchmark.title,\n\t\t\t\t\tscenarioId: benchmark.scenarioId,\n\t\t\t\t},\n\t\t\t\tobserver: observerSummary,\n\t\t\t\tsummary,\n\t\t\t\truns,\n\t\t\t};\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(output, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tp.intro(\"codemem memory extraction-benchmark\");\n\t\t\tp.log.info(\n\t\t\t\t[\n\t\t\t\t\t`Benchmark: ${benchmark.id} — ${benchmark.title}`,\n\t\t\t\t\t`Observer: ${observerSummary.provider}/${observerSummary.model}`,\n\t\t\t\t\t`Tier routing: ${opts.observerTierRouting === true ? \"yes\" : \"no\"}`,\n\t\t\t\t\t`OpenAI Responses: ${observerSummary.openaiUseResponses === null ? \"mixed\" : observerSummary.openaiUseResponses ? \"yes\" : \"no\"}`,\n\t\t\t\t\t`Reasoning effort: ${observerSummary.reasoningEffort ?? \"none\"}`,\n\t\t\t\t\t`Reasoning summary: ${observerSummary.reasoningSummary ?? \"none\"}`,\n\t\t\t\t\t`Max output tokens: ${observerSummary.maxOutputTokens ?? \"mixed\"}`,\n\t\t\t\t\t`Temperature: ${observerSummary.temperature ?? \"mixed\"}`,\n\t\t\t\t\t`Transcript budget override: ${transcriptBudget ?? \"default\"}`,\n\t\t\t\t\t`Shape-quality passes: ${summary.shapeQualityPasses}/${summary.shapeQualityTotal}`,\n\t\t\t\t\t`Shape-quality fails: ${summary.shapeQualityFails}`,\n\t\t\t\t\t`Expected-tier matches: ${summary.expectedTierMatches}/${summary.expectedTierTotal}`,\n\t\t\t\t\t`Observer no-output cases: ${summary.robustnessNoOutput}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t\tfor (const run of runs) {\n\t\t\t\tp.log.message(\n\t\t\t\t\t` [${run.batchId}] ${run.status.padEnd(18)} ${run.complexity.padEnd(10)} tier=${run.tier.padEnd(6)} expected=${(run.expectedTier ?? \"n/a\").padEnd(6)} span=${String(run.analysis.eventSpan).padEnd(3)} prompts=${run.analysis.promptCount} tools=${String(run.analysis.toolCount).padEnd(2)} transcript=${run.analysis.transcriptLength} ${run.provider}/${run.model}${run.openaiUseResponses ? \" [responses]\" : \"\"} summaries=${run.summaries} observations=${run.observations} repair=${run.repairApplied ? \"yes\" : \"no\"} — ${run.label}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tp.outro(\"done\");\n\t\t},\n\t);\n\treturn cmd;\n}\n\nfunction createMemoryRelinkReportCommand(): Command {\n\tconst cmd = new Command(\"relink-report\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Analyze dry-run raw-event session relinking and compaction opportunities\")\n\t\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t\t.option(\"--all-projects\", \"analyze across all projects\")\n\t\t.option(\"--limit <n>\", \"max groups to print\", \"25\");\n\taddDbOption(cmd);\n\taddJsonOption(cmd);\n\tcmd.action(\n\t\t(\n\t\t\topts: DbOpts &\n\t\t\t\tJsonOpts & {\n\t\t\t\t\tproject?: string;\n\t\t\t\t\tallProjects?: boolean;\n\t\t\t\t\tlimit?: string;\n\t\t\t\t},\n\t\t) => {\n\t\t\tconst project =\n\t\t\t\topts.allProjects === true\n\t\t\t\t\t? null\n\t\t\t\t\t: opts.project?.trim() ||\n\t\t\t\t\t\tprocess.env.CODEMEM_PROJECT?.trim() ||\n\t\t\t\t\t\tresolveProject(process.cwd(), null);\n\t\t\tconst limit = Number.parseInt(opts.limit ?? \"25\", 10) || 25;\n\t\t\tconst result = getRawEventRelinkReport(resolveDbOpt(opts), {\n\t\t\t\tproject,\n\t\t\t\tallProjects: opts.allProjects === true,\n\t\t\t\tlimit,\n\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tp.intro(\"codemem memory relink-report\");\n\t\t\tp.log.info(\n\t\t\t\t[\n\t\t\t\t\t`Recoverable sessions: ${result.totals.recoverable_sessions}`,\n\t\t\t\t\t`Distinct stable ids: ${result.totals.distinct_stable_ids}`,\n\t\t\t\t\t`Groups with multiple sessions: ${result.totals.groups_with_multiple_sessions}`,\n\t\t\t\t\t`Groups with mapped session: ${result.totals.groups_with_mapped_session}`,\n\t\t\t\t\t`Groups without mapped session: ${result.totals.groups_without_mapped_session}`,\n\t\t\t\t\t`Active memories in groups: ${result.totals.active_memories}`,\n\t\t\t\t\t`Repointable active memories: ${result.totals.repointable_active_memories}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t\tp.log.info(\"Top relink groups:\");\n\t\t\tfor (const group of result.groups) {\n\t\t\t\tp.log.message(\n\t\t\t\t\t` ${group.stable_id} -> canonical ${group.canonical_session_id} | local=${group.local_sessions} mapped=${group.mapped_sessions} unmapped=${group.unmapped_sessions} active=${group.active_memories} repointable=${group.repointable_active_memories}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tp.outro(\"done\");\n\t\t},\n\t);\n\treturn cmd;\n}\n\nfunction createMemoryRelinkPlanCommand(): Command {\n\tconst cmd = new Command(\"relink-plan\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Emit dry-run raw-event relink remediation actions\")\n\t\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t\t.option(\"--all-projects\", \"analyze across all projects\")\n\t\t.option(\"--limit <n>\", \"max groups to include\", \"25\");\n\taddDbOption(cmd);\n\taddJsonOption(cmd);\n\tcmd.action(\n\t\t(\n\t\t\topts: DbOpts &\n\t\t\t\tJsonOpts & {\n\t\t\t\t\tproject?: string;\n\t\t\t\t\tallProjects?: boolean;\n\t\t\t\t\tlimit?: string;\n\t\t\t\t},\n\t\t) => {\n\t\t\tconst project =\n\t\t\t\topts.allProjects === true\n\t\t\t\t\t? null\n\t\t\t\t\t: opts.project?.trim() ||\n\t\t\t\t\t\tprocess.env.CODEMEM_PROJECT?.trim() ||\n\t\t\t\t\t\tresolveProject(process.cwd(), null);\n\t\t\tconst limit = Number.parseInt(opts.limit ?? \"25\", 10) || 25;\n\t\t\tconst result = getRawEventRelinkPlan(resolveDbOpt(opts), {\n\t\t\t\tproject,\n\t\t\t\tallProjects: opts.allProjects === true,\n\t\t\t\tlimit,\n\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tp.intro(\"codemem memory relink-plan\");\n\t\t\tp.log.info(\n\t\t\t\t[\n\t\t\t\t\t`Groups: ${result.totals.groups}`,\n\t\t\t\t\t`Eligible groups: ${result.totals.eligible_groups}`,\n\t\t\t\t\t`Skipped groups: ${result.totals.skipped_groups}`,\n\t\t\t\t\t`Actions: ${result.totals.actions}`,\n\t\t\t\t\t`Bridge creations: ${result.totals.bridge_creations}`,\n\t\t\t\t\t`Memory repoints: ${result.totals.memory_repoints}`,\n\t\t\t\t\t`Session compactions: ${result.totals.session_compactions}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t\tp.log.info(\"Planned actions:\");\n\t\t\tfor (const action of result.actions.slice(0, 15)) {\n\t\t\t\tp.log.message(\n\t\t\t\t\t` ${action.action} ${action.stable_id} -> canonical ${action.canonical_session_id} | sessions=${action.session_ids.join(\",\") || \"-\"} memories=${action.memory_count} reason=${action.reason}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (result.skipped_groups.length > 0) {\n\t\t\t\tp.log.info(\"Skipped groups:\");\n\t\t\t\tfor (const group of result.skipped_groups.slice(0, 10)) {\n\t\t\t\t\tp.log.message(` ${group.stable_id} | blockers=${group.blockers.join(\",\")}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tp.outro(\"done\");\n\t\t},\n\t);\n\treturn cmd;\n}\n\nexport const showMemoryCommand = createShowMemoryCommand();\nexport const forgetMemoryCommand = createForgetMemoryCommand();\nexport const rememberMemoryCommand = createRememberMemoryCommand();\n\nexport const memoryCommand = new Command(\"memory\")\n\t.configureHelp(helpStyle)\n\t.description(\"Memory item management\");\n\nmemoryCommand.addCommand(createShowMemoryCommand());\nmemoryCommand.addCommand(createForgetMemoryCommand());\nmemoryCommand.addCommand(createRememberMemoryCommand());\nmemoryCommand.addCommand(createInjectMemoryCommand());\nmemoryCommand.addCommand(createMemoryRoleReportCommand());\nmemoryCommand.addCommand(createMemoryRoleCompareCommand());\nmemoryCommand.addCommand(createMemoryExtractionReportCommand());\nmemoryCommand.addCommand(createMemoryExtractionReplayCommand());\nmemoryCommand.addCommand(createMemoryExtractionBenchmarkCommand());\nmemoryCommand.addCommand(createMemoryRelinkReportCommand());\nmemoryCommand.addCommand(createMemoryRelinkPlanCommand());\n","import * as p from \"@clack/prompts\";\nimport type { PackTrace } from \"@codemem/core\";\nimport { MemoryStore, resolveDbPath } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddDbOption,\n\taddJsonOption,\n\ttype DbOpts,\n\temitJsonError,\n\ttype JsonOpts,\n\tresolveDbOpt,\n} from \"../shared-options.js\";\nimport { addPackRequestOptions, buildPackRequestOptions, PackUsageError } from \"./pack-shared.js\";\n\ntype PackCommandOptions = DbOpts &\n\tJsonOpts & {\n\t\tlimit: string;\n\t\tbudget?: string;\n\t\ttokenBudget?: string;\n\t\tworkingSetFile?: string[];\n\t\tproject?: string;\n\t\tallProjects?: boolean;\n\t\tcompact?: boolean;\n\t\tcompactDetail?: string;\n\t};\n\nfunction describeCandidate(candidate: PackTrace[\"retrieval\"][\"candidates\"][number]): string[] {\n\tconst scoreParts = [\n\t\tcandidate.scores.combined_score != null\n\t\t\t? `combined=${candidate.scores.combined_score.toFixed(2)}`\n\t\t\t: null,\n\t\tcandidate.scores.base_score != null ? `base=${candidate.scores.base_score.toFixed(2)}` : null,\n\t\tcandidate.scores.text_overlap > 0 ? `text=${candidate.scores.text_overlap}` : null,\n\t\tcandidate.scores.tag_overlap > 0 ? `tag=${candidate.scores.tag_overlap}` : null,\n\t\tcandidate.scores.working_set_overlap > 0\n\t\t\t? `working_set=${candidate.scores.working_set_overlap.toFixed(2)}`\n\t\t\t: null,\n\t]\n\t\t.filter(Boolean)\n\t\t.join(\" \");\n\n\tconst lines = [`${candidate.rank}. [${candidate.id}] (${candidate.kind}) ${candidate.title}`];\n\tif (candidate.section) lines.push(` - section: ${candidate.section}`);\n\tif (candidate.reasons.length > 0) lines.push(` - reasons: ${candidate.reasons.join(\", \")}`);\n\tif (scoreParts) lines.push(` - scores: ${scoreParts}`);\n\tif (candidate.preview) lines.push(` - preview: ${candidate.preview}`);\n\treturn lines;\n}\n\nexport function renderPackTrace(trace: PackTrace): string {\n\tconst workingSet =\n\t\ttrace.inputs.working_set_files.length > 0\n\t\t\t? trace.inputs.working_set_files.join(\", \")\n\t\t\t: \"(none)\";\n\tconst lines = [\n\t\t\"Pack trace\",\n\t\t`- Query: ${trace.inputs.query}`,\n\t\t`- Project: ${trace.inputs.project ?? \"(default)\"}`,\n\t\t`- Working set: ${workingSet}`,\n\t\t`- Mode: ${trace.mode.selected}`,\n\t\t`- Mode reasons: ${trace.mode.reasons.join(\", \") || \"(none)\"}`,\n\t\t`- Token budget: ${trace.inputs.token_budget ?? \"(none)\"}`,\n\t\t\"\",\n\t];\n\n\tfor (const disposition of [\"selected\", \"dropped\", \"deduped\", \"trimmed\"] as const) {\n\t\tconst group = trace.retrieval.candidates.filter(\n\t\t\t(candidate) => candidate.disposition === disposition,\n\t\t);\n\t\tif (group.length === 0) continue;\n\t\tlines.push(disposition.charAt(0).toUpperCase() + disposition.slice(1));\n\t\tfor (const candidate of group) {\n\t\t\tlines.push(...describeCandidate(candidate));\n\t\t}\n\t\tlines.push(\"\");\n\t}\n\n\tlines.push(\"Assembly\");\n\tlines.push(`- deduped ids: ${trace.assembly.deduped_ids.join(\", \") || \"(none)\"}`);\n\tlines.push(`- trimmed ids: ${trace.assembly.trimmed_ids.join(\", \") || \"(none)\"}`);\n\tlines.push(`- trim reasons: ${trace.assembly.trim_reasons.join(\", \") || \"(none)\"}`);\n\tlines.push(\n\t\t`- section counts: summary=${trace.output.section_counts.summary} timeline=${trace.output.section_counts.timeline} observations=${trace.output.section_counts.observations}`,\n\t);\n\tlines.push(`- estimated tokens: ${trace.output.estimated_tokens}`);\n\tlines.push(`- truncated: ${trace.output.truncated ? \"yes\" : \"no\"}`);\n\tlines.push(\"\");\n\tlines.push(\"Final pack\");\n\tlines.push(trace.output.pack_text);\n\treturn lines.join(\"\\n\");\n}\n\nasync function withStore(\n\topts: PackCommandOptions,\n\terrorCode: string,\n\trun: (store: MemoryStore) => Promise<void>,\n): Promise<void> {\n\tlet store: MemoryStore | null = null;\n\ttry {\n\t\tstore = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\tawait run(store);\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tconst usageError = error instanceof PackUsageError;\n\t\tif (opts.json) {\n\t\t\temitJsonError(usageError ? \"usage_error\" : errorCode, message, usageError ? 2 : 1);\n\t\t\treturn;\n\t\t}\n\t\tp.log.error(message);\n\t\tprocess.exitCode = usageError ? 2 : 1;\n\t} finally {\n\t\tstore?.close();\n\t}\n}\n\nasync function packAction(context: string, opts: PackCommandOptions): Promise<void> {\n\tawait withStore(opts, \"pack_failed\", async (store) => {\n\t\tconst { limit, budget, filters, renderOptions } = buildPackRequestOptions(opts, {\n\t\t\tenvProject: process.env.CODEMEM_PROJECT,\n\t\t});\n\t\tconst result = await store.buildMemoryPackAsync(context, limit, budget, filters, renderOptions);\n\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\treturn;\n\t\t}\n\n\t\tp.intro(`Memory pack for \"${context}\"`);\n\n\t\tif (result.items.length === 0) {\n\t\t\tp.log.warn(\"No relevant memories found.\");\n\t\t\tp.outro(\"done\");\n\t\t\treturn;\n\t\t}\n\n\t\tconst metrics = result.metrics;\n\t\tp.log.info(\n\t\t\t`${metrics.total_items} items, ~${metrics.pack_tokens} tokens` +\n\t\t\t\t(metrics.fallback_used ? \" (fallback)\" : \"\") +\n\t\t\t\t` [fts:${metrics.sources.fts} sem:${metrics.sources.semantic} fuzzy:${metrics.sources.fuzzy}]`,\n\t\t);\n\n\t\tfor (const item of result.items) {\n\t\t\tp.log.step(`#${item.id} ${item.kind} ${item.title}`);\n\t\t}\n\n\t\tp.note(result.pack_text, \"pack_text\");\n\t\tp.outro(\"done\");\n\t});\n}\n\nasync function traceAction(context: string, opts: PackCommandOptions): Promise<void> {\n\tawait withStore(opts, \"pack_trace_failed\", async (store) => {\n\t\tconst { limit, budget, filters, renderOptions } = buildPackRequestOptions(opts, {\n\t\t\tenvProject: process.env.CODEMEM_PROJECT,\n\t\t});\n\t\tconst trace = await store.buildMemoryPackTraceAsync(\n\t\t\tcontext,\n\t\t\tlimit,\n\t\t\tbudget,\n\t\t\tfilters,\n\t\t\trenderOptions,\n\t\t);\n\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify(trace, null, 2));\n\t\t\treturn;\n\t\t}\n\n\t\tconsole.log(renderPackTrace(trace));\n\t});\n}\n\nconst packCmd = addPackRequestOptions(\n\tnew Command(\"pack\")\n\t\t.enablePositionalOptions()\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Build a context-aware memory pack\")\n\t\t.argument(\"<context>\", \"context string to search for\"),\n);\n\naddDbOption(packCmd);\naddJsonOption(packCmd);\npackCmd.action(packAction);\n\nconst traceCmd = addPackRequestOptions(\n\tnew Command(\"trace\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Trace retrieval and assembly for a memory pack\")\n\t\t.argument(\"<context>\", \"context string to trace\"),\n);\n\naddDbOption(traceCmd);\naddJsonOption(traceCmd);\ntraceCmd.action(traceAction);\npackCmd.addCommand(traceCmd);\n\nexport const packCommand = packCmd;\n","import { MemoryStore, resolveDbPath, resolveProject } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddDbOption,\n\taddJsonOption,\n\ttype DbOpts,\n\ttype JsonOpts,\n\tresolveDbOpt,\n} from \"../shared-options.js\";\n\nconst cmd = new Command(\"recent\")\n\t.configureHelp(helpStyle)\n\t.description(\"Show recent memories\")\n\t.option(\"--limit <n>\", \"max results\", \"5\")\n\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t.option(\"--all-projects\", \"search across all projects\")\n\t.option(\"--kind <kind>\", \"filter by memory kind\");\n\naddDbOption(cmd);\naddJsonOption(cmd);\n\ncmd.action(\n\t(\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\tlimit: string;\n\t\t\t\tproject?: string;\n\t\t\t\tallProjects?: boolean;\n\t\t\t\tkind?: string;\n\t\t\t},\n\t) => {\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tconst limit = Math.max(1, Number.parseInt(opts.limit, 10) || 5);\n\t\t\tconst filters: { kind?: string; project?: string } = {};\n\t\t\tif (opts.kind) filters.kind = opts.kind;\n\t\t\tif (!opts.allProjects) {\n\t\t\t\tconst defaultProject = process.env.CODEMEM_PROJECT?.trim() || null;\n\t\t\t\tconst project = defaultProject || resolveProject(process.cwd(), opts.project ?? null);\n\t\t\t\tif (project) filters.project = project;\n\t\t\t}\n\t\t\tconst items = store.recent(limit, filters);\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(items));\n\t\t\t} else {\n\t\t\t\tfor (const item of items) {\n\t\t\t\t\tconsole.log(`#${item.id} [${item.kind}] ${item.title}`);\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\n\nexport const recentCommand = cmd;\n","import * as p from \"@clack/prompts\";\nimport { MemoryStore, resolveDbPath, resolveProject } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddDbOption,\n\taddJsonOption,\n\ttype DbOpts,\n\ttype JsonOpts,\n\tresolveDbOpt,\n} from \"../shared-options.js\";\n\nconst searchCmd = new Command(\"search\")\n\t.configureHelp(helpStyle)\n\t.description(\"Search memories by query\")\n\t.argument(\"<query>\", \"search query\")\n\t.option(\"-n, --limit <n>\", \"max results\", \"5\")\n\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t.option(\"--all-projects\", \"search across all projects\")\n\t.option(\"--kind <kind>\", \"filter by memory kind\");\n\naddDbOption(searchCmd);\naddJsonOption(searchCmd);\n\nexport const searchCommand = searchCmd.action(\n\t(\n\t\tquery: string,\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\tlimit: string;\n\t\t\t\tproject?: string;\n\t\t\t\tallProjects?: boolean;\n\t\t\t\tkind?: string;\n\t\t\t},\n\t) => {\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tconst limit = Math.max(1, Number.parseInt(opts.limit, 10) || 5);\n\t\t\tconst filters: { kind?: string; project?: string } = {};\n\t\t\tif (opts.kind) filters.kind = opts.kind;\n\t\t\tif (!opts.allProjects) {\n\t\t\t\tconst defaultProject = process.env.CODEMEM_PROJECT?.trim() || null;\n\t\t\t\tconst project = defaultProject || resolveProject(process.cwd(), opts.project ?? null);\n\t\t\t\tif (project) filters.project = project;\n\t\t\t}\n\t\t\tconst results = store.search(query, limit, filters);\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(results, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (results.length === 0) {\n\t\t\t\tp.log.warn(\"No results found.\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tp.intro(`${results.length} result(s) for \"${query}\"`);\n\n\t\t\tfor (const item of results) {\n\t\t\t\tconst score = item.score.toFixed(3);\n\t\t\t\tconst age = timeSince(item.created_at);\n\t\t\t\tconst preview =\n\t\t\t\t\titem.body_text.length > 120 ? `${item.body_text.slice(0, 120)}…` : item.body_text;\n\n\t\t\t\tp.log.message(\n\t\t\t\t\t[`#${item.id} ${item.kind} ${age} [${score}]`, item.title, preview].join(\"\\n\"),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tp.outro(\"done\");\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\n\nfunction timeSince(isoDate: string): string {\n\tconst ms = Date.now() - new Date(isoDate).getTime();\n\tconst days = Math.floor(ms / 86_400_000);\n\tif (days === 0) return \"today\";\n\tif (days === 1) return \"1d ago\";\n\tif (days < 30) return `${days}d ago`;\n\tconst months = Math.floor(days / 30);\n\treturn `${months}mo ago`;\n}\n","import { type DbOpts, resolveDbOpt } from \"../shared-options.js\";\n\nexport type ServeMode = \"start\" | \"stop\" | \"restart\";\n\nexport type ServeAction = ServeMode | undefined;\n\nexport interface LegacyServeOptions extends DbOpts {\n\tconfig?: string;\n\thost: string;\n\tport: string;\n\tbackground?: boolean;\n\tforeground?: boolean;\n\tstop?: boolean;\n\trestart?: boolean;\n}\n\nexport interface StartServeOptions extends DbOpts {\n\tconfig?: string;\n\thost: string;\n\tport: string;\n\tforeground?: boolean;\n}\n\nexport interface StopRestartServeOptions extends DbOpts {\n\tconfig?: string;\n\thost: string;\n\tport: string;\n}\n\nexport interface ResolvedServeInvocation {\n\tmode: ServeMode;\n\tdbPath: string | null;\n\tconfigPath: string | null;\n\thost: string;\n\tport: number;\n\tbackground: boolean;\n}\n\n/**\n * Parse and validate a port string. Throws a user-friendly message (no stack trace)\n * that callers in serve.ts catch at the action boundary.\n */\nexport function parsePort(rawPort: string): number {\n\tconst port = Number.parseInt(rawPort, 10);\n\tif (!Number.isFinite(port) || port < 1 || port > 65535) {\n\t\tthrow new Error(`Invalid port: ${rawPort}`);\n\t}\n\treturn port;\n}\n\nexport function resolveLegacyServeInvocation(opts: LegacyServeOptions): ResolvedServeInvocation {\n\tif (opts.stop && opts.restart) {\n\t\tthrow new Error(\"Use only one of --stop or --restart\");\n\t}\n\tif (opts.foreground && opts.background) {\n\t\tthrow new Error(\"Use only one of --background or --foreground\");\n\t}\n\tconst dbPath = resolveDbOpt(opts) ?? null;\n\treturn {\n\t\tmode: opts.stop ? \"stop\" : opts.restart ? \"restart\" : \"start\",\n\t\tdbPath,\n\t\tconfigPath: opts.config ?? null,\n\t\thost: opts.host,\n\t\tport: parsePort(opts.port),\n\t\tbackground: opts.restart ? true : opts.background ? true : false,\n\t};\n}\n\nexport function resolveServeInvocation(\n\taction: ServeAction,\n\topts: LegacyServeOptions,\n): ResolvedServeInvocation {\n\tif (action === undefined) {\n\t\treturn resolveLegacyServeInvocation(opts);\n\t}\n\tif (opts.stop || opts.restart) {\n\t\tthrow new Error(\"Do not combine lifecycle flags with a serve action\");\n\t}\n\tif (action === \"start\") {\n\t\treturn resolveStartServeInvocation(opts);\n\t}\n\treturn resolveStopRestartInvocation(action, opts);\n}\n\nexport function resolveStartServeInvocation(opts: StartServeOptions): ResolvedServeInvocation {\n\tconst dbPath = resolveDbOpt(opts) ?? null;\n\treturn {\n\t\tmode: \"start\",\n\t\tdbPath,\n\t\tconfigPath: opts.config ?? null,\n\t\thost: opts.host,\n\t\tport: parsePort(opts.port),\n\t\tbackground: !opts.foreground,\n\t};\n}\n\nexport function resolveStopRestartInvocation(\n\tmode: \"stop\" | \"restart\",\n\topts: StopRestartServeOptions,\n): ResolvedServeInvocation {\n\tconst dbPath = resolveDbOpt(opts) ?? null;\n\treturn {\n\t\tmode,\n\t\tdbPath,\n\t\tconfigPath: opts.config ?? null,\n\t\thost: opts.host,\n\t\tport: parsePort(opts.port),\n\t\tbackground: mode === \"restart\",\n\t};\n}\n","import { spawn, spawnSync } from \"node:child_process\";\nimport { existsSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport net from \"node:net\";\nimport { dirname, join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport {\n\tDedupKeyBackfillRunner,\n\thasPendingDedupKeyBackfill,\n\tinitDatabase,\n\tisEmbeddingDisabled,\n\ttype MemoryStore,\n\tObserverClient,\n\tRawEventSweeper,\n\treadCodememConfigFile,\n\treadCodememConfigFileAtPath,\n\treadCoordinatorSyncConfig,\n\tresolveDbPath,\n\trunSyncDaemon,\n\tSyncRetentionRunner,\n\tVectorModelMigrationRunner,\n} from \"@codemem/core\";\nimport { Command, Option } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddConfigOption,\n\taddDbOption,\n\taddViewerHostOptions,\n\temitDeprecationWarning,\n} from \"../shared-options.js\";\nimport {\n\ttype LegacyServeOptions,\n\ttype ResolvedServeInvocation,\n\tresolveServeInvocation,\n\ttype ServeAction,\n} from \"./serve-invocation.js\";\n\ninterface ViewerPidRecord {\n\tpid: number;\n\thost: string;\n\tport: number;\n}\n\nexport function extractViewerPid(payload: unknown): number | null {\n\tif (!payload || typeof payload !== \"object\") return null;\n\tconst rawPid = (payload as { viewer_pid?: unknown }).viewer_pid;\n\tif (typeof rawPid !== \"number\" || !Number.isFinite(rawPid) || rawPid <= 0) return null;\n\treturn Math.trunc(rawPid);\n}\n\nexport function isLocalHost(host: string): boolean {\n\tconst normalized = host.trim().toLowerCase();\n\treturn (\n\t\tnormalized === \"127.0.0.1\" ||\n\t\tnormalized === \"localhost\" ||\n\t\tnormalized === \"::1\" ||\n\t\tnormalized === \"0.0.0.0\" ||\n\t\tnormalized === \"::\"\n\t);\n}\n\nexport function isLoopbackOnlyHost(host: string): boolean {\n\tconst normalized = host.trim().toLowerCase();\n\treturn (\n\t\tnormalized === \"localhost\" ||\n\t\t/^127(?:\\.\\d{1,3}){0,3}$/.test(normalized) ||\n\t\tnormalized === \"::1\" ||\n\t\tnormalized === \"0:0:0:0:0:0:0:1\"\n\t);\n}\n\nfunction warnIfViewerExposed(host: string, port: number): void {\n\tif (isLoopbackOnlyHost(host)) return;\n\tp.log.warn(\n\t\t`Viewer bound to ${host}:${port}. codemem's viewer trust model assumes localhost-only access; do not expose it through a reverse proxy, tunnel, or public bind without adding your own auth layer.`,\n\t);\n}\n\nexport function isLikelyViewerCommand(command: string): boolean {\n\tconst lowered = command.toLowerCase();\n\tif (!/\\bserve\\s+start\\b/.test(lowered)) return false;\n\treturn (\n\t\tlowered.includes(\"codemem\") ||\n\t\tlowered.includes(\"packages/cli/dist/index.js\") ||\n\t\tlowered.includes(\"/cli/dist/index.js\")\n\t);\n}\n\nexport function prepareViewerDatabase(dbPath?: string | null): string {\n\treturn initDatabase(dbPath ?? undefined).path;\n}\n\nexport function pickViewerPidCandidate(\n\tstatsPid: number | null,\n\tlistenerPid: number | null,\n): number | null {\n\tif (statsPid && listenerPid && statsPid !== listenerPid) return null;\n\treturn statsPid ?? listenerPid ?? null;\n}\n\nfunction lookupListeningPid(host: string, port: number): number | null {\n\tif (!isLocalHost(host)) return null;\n\tconst result = spawnSync(\"lsof\", [\"-nP\", `-iTCP:${port}`, \"-sTCP:LISTEN\", \"-t\"], {\n\t\tencoding: \"utf-8\",\n\t\ttimeout: 1000,\n\t});\n\tif (result.status !== 0) return null;\n\tconst first = (result.stdout || \"\")\n\t\t.split(/\\r?\\n/)\n\t\t.map((line) => line.trim())\n\t\t.find((line) => line.length > 0);\n\tif (!first) return null;\n\tconst parsed = Number.parseInt(first, 10);\n\treturn Number.isFinite(parsed) && parsed > 0 ? parsed : null;\n}\n\nfunction readProcessCommand(pid: number): string | null {\n\tconst result = spawnSync(\"ps\", [\"-p\", String(pid), \"-o\", \"command=\"], {\n\t\tencoding: \"utf-8\",\n\t\ttimeout: 1000,\n\t});\n\tif (result.status !== 0) return null;\n\tconst cmd = (result.stdout || \"\").trim();\n\treturn cmd.length > 0 ? cmd : null;\n}\n\nfunction isTrustedViewerPid(\n\tpid: number,\n\ttarget: { host: string; port: number },\n\tlistenerPid: number | null,\n): boolean {\n\tif (!isLocalHost(target.host)) return false;\n\tif (listenerPid && listenerPid !== pid) return false;\n\tconst command = readProcessCommand(pid);\n\tif (!command) return false;\n\treturn isLikelyViewerCommand(command);\n}\n\nfunction pidFilePath(dbPath: string): string {\n\treturn join(dirname(dbPath), \"viewer.pid\");\n}\n\nfunction readViewerPidRecord(dbPath: string): ViewerPidRecord | null {\n\tconst pidPath = pidFilePath(dbPath);\n\tif (!existsSync(pidPath)) return null;\n\tconst raw = readFileSync(pidPath, \"utf-8\").trim();\n\ttry {\n\t\tconst parsed = JSON.parse(raw) as Partial<ViewerPidRecord>;\n\t\tif (\n\t\t\ttypeof parsed.pid === \"number\" &&\n\t\t\ttypeof parsed.host === \"string\" &&\n\t\t\ttypeof parsed.port === \"number\"\n\t\t) {\n\t\t\treturn { pid: parsed.pid, host: parsed.host, port: parsed.port };\n\t\t}\n\t} catch {\n\t\tconst pid = Number.parseInt(raw, 10);\n\t\tif (Number.isFinite(pid) && pid > 0) {\n\t\t\treturn { pid, host: \"127.0.0.1\", port: 38888 };\n\t\t}\n\t}\n\treturn null;\n}\n\nfunction isProcessRunning(pid: number): boolean {\n\ttry {\n\t\tprocess.kill(pid, 0);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function respondsLikeCodememViewer(record: ViewerPidRecord): Promise<boolean> {\n\ttry {\n\t\tconst controller = new AbortController();\n\t\tconst timer = setTimeout(() => controller.abort(), 1000);\n\t\tconst res = await fetch(`http://${record.host}:${record.port}/api/stats`, {\n\t\t\tsignal: controller.signal,\n\t\t});\n\t\tclearTimeout(timer);\n\t\treturn res.ok;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function lookupViewerPidFromStats(host: string, port: number): Promise<number | null> {\n\ttry {\n\t\tconst controller = new AbortController();\n\t\tconst timer = setTimeout(() => controller.abort(), 1000);\n\t\tconst res = await fetch(`http://${host}:${port}/api/stats`, {\n\t\t\tsignal: controller.signal,\n\t\t});\n\t\tclearTimeout(timer);\n\t\tif (!res.ok) return null;\n\t\tconst payload = await res.json();\n\t\treturn extractViewerPid(payload);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function isPortOpen(host: string, port: number): Promise<boolean> {\n\treturn new Promise((resolve) => {\n\t\tconst socket = net.createConnection({ host, port });\n\t\tconst done = (open: boolean) => {\n\t\t\tsocket.removeAllListeners();\n\t\t\tsocket.destroy();\n\t\t\tresolve(open);\n\t\t};\n\t\tsocket.setTimeout(300);\n\t\tsocket.once(\"connect\", () => done(true));\n\t\tsocket.once(\"timeout\", () => done(false));\n\t\tsocket.once(\"error\", () => done(false));\n\t});\n}\n\nasync function waitForProcessExit(pid: number, timeoutMs = 30000): Promise<boolean> {\n\tconst deadline = Date.now() + timeoutMs;\n\twhile (Date.now() < deadline) {\n\t\tif (!isProcessRunning(pid)) return true;\n\t\tawait new Promise((resolve) => setTimeout(resolve, 100));\n\t}\n\treturn !isProcessRunning(pid);\n}\n\nasync function waitForPortRelease(host: string, port: number, timeoutMs = 10000): Promise<boolean> {\n\tconst deadline = Date.now() + timeoutMs;\n\twhile (Date.now() < deadline) {\n\t\tif (!(await isPortOpen(host, port))) return true;\n\t\tawait new Promise((resolve) => setTimeout(resolve, 200));\n\t}\n\treturn false;\n}\n\nasync function stopExistingViewer(\n\tdbPath: string,\n\ttarget: { host: string; port: number },\n): Promise<{ stopped: boolean; pid: number | null }> {\n\tconst terminatePid = async (pid: number): Promise<boolean> => {\n\t\ttry {\n\t\t\tprocess.kill(pid, \"SIGTERM\");\n\t\t\treturn await waitForProcessExit(pid);\n\t\t} catch {\n\t\t\treturn true;\n\t\t}\n\t};\n\n\tconst pidPath = pidFilePath(dbPath);\n\tconst record = readViewerPidRecord(dbPath);\n\tconst viewerPidFromStats = await lookupViewerPidFromStats(target.host, target.port);\n\tconst listenerPid = lookupListeningPid(target.host, target.port);\n\tconst viewerPid = pickViewerPidCandidate(viewerPidFromStats, listenerPid);\n\tif (viewerPid && isTrustedViewerPid(viewerPid, target, listenerPid)) {\n\t\tconst stopped = await terminatePid(viewerPid);\n\t\tif (!stopped) return { stopped: false, pid: viewerPid };\n\t\ttry {\n\t\t\trmSync(pidPath);\n\t\t} catch {\n\t\t\t// ignore\n\t\t}\n\t\treturn { stopped: true, pid: viewerPid };\n\t}\n\n\tif (!record) return { stopped: false, pid: null };\n\n\tif (await respondsLikeCodememViewer(record)) {\n\t\tconst stopped = await terminatePid(record.pid);\n\t\tif (!stopped) return { stopped: false, pid: record.pid };\n\t}\n\ttry {\n\t\trmSync(pidPath);\n\t} catch {\n\t\t// ignore\n\t}\n\treturn { stopped: true, pid: record.pid };\n}\n\nexport function buildForegroundRunnerArgs(\n\tscriptPath: string,\n\tinvocation: ResolvedServeInvocation,\n\texecArgv: string[] = process.execArgv,\n): string[] {\n\tconst args = [\n\t\t...execArgv,\n\t\tscriptPath,\n\t\t\"serve\",\n\t\t\"start\",\n\t\t\"--foreground\",\n\t\t\"--host\",\n\t\tinvocation.host,\n\t\t\"--port\",\n\t\tString(invocation.port),\n\t];\n\tif (invocation.dbPath) {\n\t\targs.push(\"--db-path\", invocation.dbPath);\n\t}\n\treturn args;\n}\n\nexport function isSqliteVecLoadFailure(error: unknown): boolean {\n\tif (!(error instanceof Error)) return false;\n\tconst text = error.message.toLowerCase();\n\treturn (\n\t\ttext.includes(\"sqlite-vec\") ||\n\t\ttext.includes(\"vec_version\") ||\n\t\ttext.includes(\"vec0\") ||\n\t\t(text.includes(\"sqlite\") && text.includes(\"vec\"))\n\t);\n}\n\nexport function sqliteVecFailureDiagnostics(error: unknown, dbPath: string): string[] {\n\tconst message = error instanceof Error ? error.message : String(error);\n\treturn [\n\t\t`db=${dbPath}`,\n\t\t`node=${process.version}`,\n\t\t`exec=${process.execPath}`,\n\t\t`cwd=${process.cwd()}`,\n\t\t`embedding_disabled=${process.env.CODEMEM_EMBEDDING_DISABLED ?? \"\"}`,\n\t\t`error=${message}`,\n\t];\n}\n\nasync function startBackgroundViewer(invocation: ResolvedServeInvocation): Promise<void> {\n\twarnIfViewerExposed(invocation.host, invocation.port);\n\tif (await isPortOpen(invocation.host, invocation.port)) {\n\t\tp.log.warn(`Viewer already running at http://${invocation.host}:${invocation.port}`);\n\t\treturn;\n\t}\n\tconst scriptPath = process.argv[1];\n\tif (!scriptPath) {\n\t\tp.log.error(\"Unable to resolve CLI entrypoint for background launch\");\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\tconst child = spawn(process.execPath, buildForegroundRunnerArgs(scriptPath, invocation), {\n\t\tcwd: process.cwd(),\n\t\tdetached: true,\n\t\tstdio: \"ignore\",\n\t\tenv: {\n\t\t\t...process.env,\n\t\t\t...(invocation.dbPath ? { CODEMEM_DB: invocation.dbPath } : {}),\n\t\t\t...(invocation.configPath ? { CODEMEM_CONFIG: invocation.configPath } : {}),\n\t\t},\n\t});\n\tchild.unref();\n\tif (invocation.dbPath) {\n\t\twriteFileSync(\n\t\t\tpidFilePath(invocation.dbPath),\n\t\t\tJSON.stringify({ pid: child.pid, host: invocation.host, port: invocation.port }),\n\t\t\t\"utf-8\",\n\t\t);\n\t}\n\tp.intro(\"codemem viewer\");\n\tp.outro(\n\t\t`Viewer started in background (pid ${child.pid}) at http://${invocation.host}:${invocation.port}`,\n\t);\n}\n\nasync function startForegroundViewer(invocation: ResolvedServeInvocation): Promise<void> {\n\tconst { createApp, createSyncApp, closeStore, getStore } = await import(\"@codemem/server\");\n\tconst { serve } = await import(\"@hono/node-server\");\n\n\tif (invocation.dbPath) process.env.CODEMEM_DB = invocation.dbPath;\n\tif (invocation.configPath) process.env.CODEMEM_CONFIG = invocation.configPath;\n\twarnIfViewerExposed(invocation.host, invocation.port);\n\tif (await isPortOpen(invocation.host, invocation.port)) {\n\t\tp.log.warn(`Viewer already running at http://${invocation.host}:${invocation.port}`);\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\tconst preparedDb = prepareViewerDatabase(invocation.dbPath);\n\n\tconst observer = new ObserverClient();\n\tlet store: MemoryStore;\n\ttry {\n\t\tstore = getStore();\n\t} catch (err) {\n\t\tif (isEmbeddingDisabled() || !isSqliteVecLoadFailure(err)) {\n\t\t\tthrow err;\n\t\t}\n\n\t\tp.log.warn(\"sqlite-vec failed to load; retrying viewer startup with embeddings disabled\");\n\t\tfor (const line of sqliteVecFailureDiagnostics(\n\t\t\terr,\n\t\t\tresolveDbPath(invocation.dbPath ?? undefined),\n\t\t)) {\n\t\t\tp.log.warn(`sqlite-vec diagnostic: ${line}`);\n\t\t}\n\t\tprocess.env.CODEMEM_EMBEDDING_DISABLED = \"1\";\n\t\tcloseStore();\n\t\tstore = getStore();\n\t\tp.log.warn(\"Embeddings disabled for this viewer process; raw-event ingestion remains active.\");\n\t}\n\n\tconst sweeper = new RawEventSweeper(store, { observer });\n\tsweeper.start();\n\n\tconst syncAbort = new AbortController();\n\tconst retentionAbort = new AbortController();\n\tconst config = invocation.configPath\n\t\t? readCodememConfigFileAtPath(invocation.configPath)\n\t\t: readCodememConfigFile();\n\tconst syncConfig = readCoordinatorSyncConfig(config);\n\tconst syncEnabled = syncConfig.syncEnabled;\n\tconst retentionRunner = new SyncRetentionRunner({\n\t\tdbPath: resolveDbPath(invocation.dbPath ?? undefined),\n\t\tsignal: retentionAbort.signal,\n\t});\n\tconst vectorMigrationRunner = new VectorModelMigrationRunner({\n\t\tdbPath: resolveDbPath(invocation.dbPath ?? undefined),\n\t});\n\tconst dedupKeyBackfillRunner = new DedupKeyBackfillRunner({\n\t\tdbPath: resolveDbPath(invocation.dbPath ?? undefined),\n\t});\n\tconst syncRuntimeStatus: {\n\t\tphase: \"starting\" | \"running\" | \"stopping\" | \"error\" | \"disabled\" | null;\n\t\tdetail: string | null;\n\t} = {\n\t\tphase: syncEnabled ? \"starting\" : \"disabled\",\n\t\tdetail: syncEnabled ? \"Waiting for viewer startup to finish\" : \"Sync is disabled\",\n\t};\n\n\tconst appOpts = {\n\t\tstoreFactory: () => store,\n\t\tsweeper,\n\t\tobserver,\n\t\tgetSyncRuntimeStatus: () => syncRuntimeStatus,\n\t};\n\tconst app = createApp(appOpts);\n\tconst dbPath = resolveDbPath(invocation.dbPath ?? undefined);\n\tconst pidPath = pidFilePath(dbPath);\n\n\t// Sync protocol listener — separate port, network-accessible for peers.\n\t// syncServerRef is never nulled after creation so shutdown always drains it.\n\tlet syncServer: ReturnType<typeof serve> | null = null;\n\tlet syncListenerReady = false;\n\tif (syncEnabled) {\n\t\tconst syncApp = createSyncApp(appOpts);\n\t\tsyncServer = serve(\n\t\t\t{ fetch: syncApp.fetch, hostname: syncConfig.syncHost, port: syncConfig.syncPort },\n\t\t\t(info) => {\n\t\t\t\tsyncListenerReady = true;\n\t\t\t\tp.log.step(`Sync protocol listening on http://${info.address}:${info.port}`);\n\t\t\t},\n\t\t);\n\t\tsyncServer.on(\"error\", (err: NodeJS.ErrnoException) => {\n\t\t\tif (!syncListenerReady && err.code === \"EADDRINUSE\") {\n\t\t\t\tp.log.warn(\n\t\t\t\t\t`Sync port ${syncConfig.syncPort} already in use; peer sync protocol unavailable`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tp.log.warn(`Sync listener error: ${err.message}`);\n\t\t\t}\n\t\t\t// Non-fatal — viewer continues. syncServer ref is kept for shutdown drain.\n\t\t});\n\t}\n\n\tconst server = serve(\n\t\t{ fetch: app.fetch, hostname: invocation.host, port: invocation.port },\n\t\t(info) => {\n\t\t\twriteFileSync(\n\t\t\t\tpidPath,\n\t\t\t\tJSON.stringify({ pid: process.pid, host: invocation.host, port: invocation.port }),\n\t\t\t\t\"utf-8\",\n\t\t\t);\n\t\t\tp.intro(\"codemem viewer\");\n\t\t\tp.log.success(`Listening on http://${info.address}:${info.port}`);\n\t\t\tp.log.info(`Database: ${preparedDb}`);\n\t\t\tp.log.step(\"Raw event sweeper started\");\n\t\t\tif (!isEmbeddingDisabled()) {\n\t\t\t\tvectorMigrationRunner.start();\n\t\t\t\tp.log.step(\"Vector maintenance runner started\");\n\t\t\t}\n\t\t\tif (hasPendingDedupKeyBackfill(store.db)) {\n\t\t\t\tdedupKeyBackfillRunner.start();\n\t\t\t\tp.log.step(\"Dedup-key maintenance runner started\");\n\t\t\t}\n\t\t\tif (syncConfig.syncRetentionEnabled) {\n\t\t\t\tretentionRunner.start();\n\t\t\t\tp.log.step(\"Retention maintenance runner started\");\n\t\t\t}\n\t\t\tif (syncEnabled) {\n\t\t\t\tconst syncStartDelayMs = 3000;\n\t\t\t\tp.log.step(`Sync daemon will start in background (${syncStartDelayMs / 1000}s delay)`);\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tsyncRuntimeStatus.phase = \"starting\";\n\t\t\t\t\tsyncRuntimeStatus.detail = \"Starting sync in background\";\n\t\t\t\t\tvoid runSyncDaemon({\n\t\t\t\t\t\tdbPath: resolveDbPath(invocation.dbPath ?? undefined),\n\t\t\t\t\t\tintervalS: syncConfig.syncIntervalS,\n\t\t\t\t\t\thost: syncConfig.syncHost,\n\t\t\t\t\t\tport: syncConfig.syncPort,\n\t\t\t\t\t\tsignal: syncAbort.signal,\n\t\t\t\t\t\tonPhaseChange: (phase) => {\n\t\t\t\t\t\t\tif (phase === \"running\") {\n\t\t\t\t\t\t\t\tsyncRuntimeStatus.phase = null;\n\t\t\t\t\t\t\t\tsyncRuntimeStatus.detail = null;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tsyncRuntimeStatus.phase = phase;\n\t\t\t\t\t\t\t\tsyncRuntimeStatus.detail =\n\t\t\t\t\t\t\t\t\tphase === \"starting\"\n\t\t\t\t\t\t\t\t\t\t? \"Running initial sync in background\"\n\t\t\t\t\t\t\t\t\t\t: \"Stopping sync daemon\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\t\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\t\t\t\t\t\tsyncRuntimeStatus.phase = \"error\";\n\t\t\t\t\t\t\tsyncRuntimeStatus.detail = msg;\n\t\t\t\t\t\t\tp.log.error(`Sync daemon failed: ${msg}`);\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.finally(() => {\n\t\t\t\t\t\t\tif (syncRuntimeStatus.phase !== \"error\") {\n\t\t\t\t\t\t\t\tsyncRuntimeStatus.phase = syncAbort.signal.aborted ? \"stopping\" : null;\n\t\t\t\t\t\t\t\tsyncRuntimeStatus.detail = syncAbort.signal.aborted ? \"Sync stopped\" : null;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t}, syncStartDelayMs).unref();\n\t\t\t}\n\t\t},\n\t);\n\n\tserver.on(\"error\", (err: NodeJS.ErrnoException) => {\n\t\tif (err.code === \"EADDRINUSE\") {\n\t\t\tp.log.warn(`Viewer already running at http://${invocation.host}:${invocation.port}`);\n\t\t} else {\n\t\t\tp.log.error(err.message);\n\t\t}\n\t\tprocess.exit(1);\n\t});\n\n\t// Periodic WAL checkpoint — keeps the WAL file bounded.\n\t// Without this, long-running viewer processes accumulate a WAL that can\n\t// grow to match the main DB size when concurrent readers hold it open.\n\tconst WAL_CHECKPOINT_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes\n\tconst walCheckpointTimer = setInterval(() => {\n\t\ttry {\n\t\t\tstore.db.pragma(\"wal_checkpoint(TRUNCATE)\");\n\t\t} catch (err) {\n\t\t\tp.log.warn(`WAL checkpoint failed: ${err instanceof Error ? err.message : String(err)}`);\n\t\t}\n\t}, WAL_CHECKPOINT_INTERVAL_MS);\n\twalCheckpointTimer.unref();\n\n\tconst shutdown = async () => {\n\t\tp.outro(\"shutting down\");\n\t\tclearInterval(walCheckpointTimer);\n\t\tsyncAbort.abort();\n\t\tretentionAbort.abort();\n\t\tawait sweeper.stop();\n\t\tawait dedupKeyBackfillRunner.stop();\n\t\tawait vectorMigrationRunner.stop();\n\t\tawait retentionRunner.stop();\n\n\t\t// Drain both listeners before closing the shared store.\n\t\tawait new Promise<void>((resolve) => {\n\t\t\tlet remaining = syncServer ? 2 : 1;\n\t\t\tconst done = () => {\n\t\t\t\tif (--remaining === 0) resolve();\n\t\t\t};\n\t\t\tsyncServer?.close(done);\n\t\t\tserver.close(done);\n\t\t}).catch(() => {\n\t\t\t// Best-effort drain — proceed to cleanup.\n\t\t});\n\n\t\ttry {\n\t\t\trmSync(pidPath);\n\t\t} catch {\n\t\t\t// ignore\n\t\t}\n\t\tcloseStore();\n\t\tprocess.exit(0);\n\t};\n\n\t// Force-exit safety net if graceful shutdown stalls for an unusually long time.\n\tconst forceShutdown = () => {\n\t\tsetTimeout(() => {\n\t\t\ttry {\n\t\t\t\trmSync(pidPath);\n\t\t\t} catch {\n\t\t\t\t// ignore\n\t\t\t}\n\t\t\tcloseStore();\n\t\t\tprocess.exit(1);\n\t\t}, 30000).unref();\n\t};\n\tprocess.on(\"SIGINT\", () => {\n\t\tforceShutdown();\n\t\tvoid shutdown();\n\t});\n\tprocess.on(\"SIGTERM\", () => {\n\t\tforceShutdown();\n\t\tvoid shutdown();\n\t});\n}\n\nasync function runServeInvocation(invocation: ResolvedServeInvocation): Promise<void> {\n\tconst dbPath = resolveDbPath(invocation.dbPath ?? undefined);\n\tif (invocation.mode === \"stop\" || invocation.mode === \"restart\") {\n\t\tconst result = await stopExistingViewer(dbPath, {\n\t\t\thost: invocation.host,\n\t\t\tport: invocation.port,\n\t\t});\n\t\tif (result.stopped) {\n\t\t\tp.intro(\"codemem viewer\");\n\t\t\tp.log.success(`Stopped viewer${result.pid ? ` (pid ${result.pid})` : \"\"}`);\n\t\t\tif (invocation.mode === \"stop\") {\n\t\t\t\tp.outro(\"done\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Wait for port to be fully released before restarting.\n\t\t\tconst released = await waitForPortRelease(invocation.host, invocation.port);\n\t\t\tif (!released) {\n\t\t\t\tp.log.warn(`Port ${invocation.port} still in use after stop — restart may fail`);\n\t\t\t}\n\t\t} else if (result.pid) {\n\t\t\tp.intro(\"codemem viewer\");\n\t\t\tp.log.error(`Viewer is still shutting down (pid ${result.pid})`);\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t} else if (invocation.mode === \"stop\") {\n\t\t\tp.intro(\"codemem viewer\");\n\t\t\tp.outro(\"No background viewer found\");\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif (invocation.mode === \"start\" || invocation.mode === \"restart\") {\n\t\tif (invocation.background) {\n\t\t\tawait startBackgroundViewer({ ...invocation, dbPath });\n\t\t\treturn;\n\t\t}\n\t\tawait startForegroundViewer({ ...invocation, dbPath });\n\t}\n}\n\nconst serveCmd = new Command(\"serve\")\n\t.configureHelp(helpStyle)\n\t.description(\"Run or manage the viewer\")\n\t.argument(\"[action]\", \"lifecycle action (start|stop|restart)\");\n\naddDbOption(serveCmd);\naddConfigOption(serveCmd);\naddViewerHostOptions(serveCmd);\n\n// Legacy lifecycle flags — hidden from --help, emit deprecation warnings when used.\nserveCmd.addOption(new Option(\"--background\", \"run viewer in background\").hideHelp());\nserveCmd.addOption(new Option(\"--foreground\", \"run viewer in foreground\").hideHelp());\nserveCmd.addOption(new Option(\"--stop\", \"stop background viewer\").hideHelp());\nserveCmd.addOption(new Option(\"--restart\", \"restart background viewer\").hideHelp());\n\nexport const serveCommand = serveCmd.action(\n\tasync (action: string | undefined, opts: LegacyServeOptions) => {\n\t\ttry {\n\t\t\t// Emit deprecation warnings for legacy flags\n\t\t\tif (opts.stop) emitDeprecationWarning(\"--stop\", \"codemem serve stop\");\n\t\t\tif (opts.restart) emitDeprecationWarning(\"--restart\", \"codemem serve restart\");\n\t\t\tif (opts.background) emitDeprecationWarning(\"--background\", \"codemem serve start\");\n\t\t\tif (opts.foreground)\n\t\t\t\temitDeprecationWarning(\"--foreground\", \"codemem serve start --foreground\");\n\n\t\t\tconst normalizedAction =\n\t\t\t\taction === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: action === \"start\" || action === \"stop\" || action === \"restart\"\n\t\t\t\t\t\t? (action as ServeAction)\n\t\t\t\t\t\t: null;\n\t\t\tif (normalizedAction === null) {\n\t\t\t\tp.log.error(`Unknown serve action: ${action}`);\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait runServeInvocation(resolveServeInvocation(normalizedAction, opts));\n\t\t} catch (err) {\n\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t},\n);\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { stripJsonComments, stripTrailingCommas } from \"@codemem/core\";\n\nexport function resolveOpencodeConfigPath(configDir: string): string {\n\tconst jsonPath = join(configDir, \"opencode.json\");\n\tif (existsSync(jsonPath)) return jsonPath;\n\tconst jsoncPath = join(configDir, \"opencode.jsonc\");\n\tif (existsSync(jsoncPath)) return jsoncPath;\n\treturn jsoncPath;\n}\n\nexport function loadJsoncConfig(path: string): Record<string, unknown> {\n\tif (!existsSync(path)) return {};\n\tconst raw = readFileSync(path, \"utf-8\");\n\ttry {\n\t\treturn JSON.parse(raw) as Record<string, unknown>;\n\t} catch {\n\t\tconst cleaned = stripTrailingCommas(stripJsonComments(raw));\n\t\treturn JSON.parse(cleaned) as Record<string, unknown>;\n\t}\n}\n\nexport function writeJsonConfig(path: string, data: Record<string, unknown>): void {\n\tmkdirSync(dirname(path), { recursive: true });\n\twriteFileSync(path, `${JSON.stringify(data, null, 2)}\\n`, \"utf-8\");\n}\n","/**\n * codemem setup — one-command installation for OpenCode plugin + MCP config.\n *\n * Replaces Python's install_plugin_cmd + install_mcp_cmd.\n *\n * What it does:\n * 1. Adds \"@codemem/opencode-plugin\" to the plugin array in ~/.config/opencode/opencode.jsonc\n * 2. Adds/updates the MCP entry in ~/.config/opencode/opencode.jsonc\n * 3. For Claude Code: installs MCP config and guides marketplace plugin install\n *\n * Designed to be safe to run repeatedly (idempotent unless --force).\n */\n\nimport { existsSync, rmSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { VERSION } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport { loadJsoncConfig, resolveOpencodeConfigPath, writeJsonConfig } from \"./setup-config.js\";\n\nfunction opencodeConfigDir(): string {\n\treturn join(homedir(), \".config\", \"opencode\");\n}\n\nfunction claudeConfigDir(): string {\n\treturn join(homedir(), \".claude\");\n}\n\n/** The npm package name used in the OpenCode plugin array. */\nconst OPENCODE_PLUGIN_SPEC = \"@codemem/opencode-plugin\";\nconst LEGACY_OPENCODE_PLUGIN_SPECS = [\"codemem\", \"@kunickiaj/codemem\"];\n\n// ---------------------------------------------------------------------------\n// Legacy migration helpers\n// ---------------------------------------------------------------------------\n\n/** Remove legacy copied plugin JS file from ~/.config/opencode/plugins/codemem.js */\nfunction migrateLegacyOpencodePlugin(): void {\n\tconst legacyPlugin = join(opencodeConfigDir(), \"plugins\", \"codemem.js\");\n\tconst legacyCompat = join(opencodeConfigDir(), \"lib\", \"compat.js\");\n\tif (existsSync(legacyPlugin)) {\n\t\ttry {\n\t\t\trmSync(legacyPlugin);\n\t\t\tp.log.step(\"Removed legacy copied plugin: ~/.config/opencode/plugins/codemem.js\");\n\t\t} catch {\n\t\t\tp.log.warn(\"Could not remove legacy plugin file — remove manually if needed\");\n\t\t}\n\t}\n\tif (existsSync(legacyCompat)) {\n\t\ttry {\n\t\t\trmSync(legacyCompat);\n\t\t\tp.log.step(\"Removed legacy compat lib: ~/.config/opencode/lib/compat.js\");\n\t\t} catch {\n\t\t\t// Non-fatal.\n\t\t}\n\t}\n}\n\n/** Detect and upgrade legacy uvx/uv-based MCP entries in OpenCode config. */\nfunction migrateLegacyOpencodeMcp(config: Record<string, unknown>): boolean {\n\tconst mcpConfig = config.mcp as Record<string, unknown> | undefined;\n\tif (!mcpConfig || typeof mcpConfig !== \"object\") return false;\n\tconst entry = mcpConfig.codemem as Record<string, unknown> | undefined;\n\tif (!entry || typeof entry !== \"object\") return false;\n\n\tconst command = entry.command;\n\tconst isLegacy =\n\t\t(Array.isArray(command) &&\n\t\t\tcommand.some((arg) => typeof arg === \"string\" && (arg === \"uvx\" || arg === \"uv\"))) ||\n\t\t(typeof command === \"string\" && (command === \"uvx\" || command === \"uv\"));\n\n\tif (isLegacy) {\n\t\tp.log.step(\"Upgrading legacy uvx MCP entry to npx\");\n\t\tmcpConfig.codemem = {\n\t\t\ttype: \"local\",\n\t\t\tcommand: [\"npx\", \"codemem\", \"mcp\"],\n\t\t\tenabled: true,\n\t\t};\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/** Detect and upgrade legacy uvx-based MCP entries in Claude settings. */\nfunction migrateLegacyClaudeMcp(settings: Record<string, unknown>): boolean {\n\tconst mcpServers = settings.mcpServers as Record<string, unknown> | undefined;\n\tif (!mcpServers || typeof mcpServers !== \"object\") return false;\n\tconst entry = mcpServers.codemem as Record<string, unknown> | undefined;\n\tif (!entry || typeof entry !== \"object\") return false;\n\n\tconst command = entry.command;\n\tconst args = entry.args;\n\tconst isLegacy =\n\t\t(typeof command === \"string\" && (command === \"uvx\" || command === \"uv\")) ||\n\t\t(Array.isArray(args) &&\n\t\t\targs.some(\n\t\t\t\t(arg) => typeof arg === \"string\" && (arg.startsWith(\"codemem==\") || arg === \"uvx\"),\n\t\t\t));\n\n\tif (isLegacy) {\n\t\tp.log.step(\"Upgrading legacy uvx Claude MCP entry to npx\");\n\t\tmcpServers.codemem = {\n\t\t\tcommand: \"npx\",\n\t\t\targs: [\"-y\", \"codemem\", \"mcp\"],\n\t\t};\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n// ---------------------------------------------------------------------------\n// Install functions\n// ---------------------------------------------------------------------------\n\nfunction installPlugin(force: boolean): boolean {\n\t// Clean up legacy copied plugin files first.\n\tmigrateLegacyOpencodePlugin();\n\n\tconst configPath = resolveOpencodeConfigPath(opencodeConfigDir());\n\tlet config: Record<string, unknown>;\n\ttry {\n\t\tconfig = loadJsoncConfig(configPath);\n\t} catch (err) {\n\t\tp.log.error(\n\t\t\t`Failed to parse ${configPath}: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t\treturn false;\n\t}\n\n\tlet plugins = config.plugin as unknown;\n\tif (!Array.isArray(plugins)) {\n\t\tplugins = [];\n\t}\n\n\tconst isManagedPluginSpec = (entry: unknown): entry is string =>\n\t\ttypeof entry === \"string\" &&\n\t\t[OPENCODE_PLUGIN_SPEC, ...LEGACY_OPENCODE_PLUGIN_SPECS].some(\n\t\t\t(spec) => entry === spec || entry.startsWith(`${spec}@`),\n\t\t);\n\n\tconst hasCanonicalSpec = (plugins as string[]).some(\n\t\t(entry) =>\n\t\t\ttypeof entry === \"string\" &&\n\t\t\t(entry === OPENCODE_PLUGIN_SPEC || entry.startsWith(`${OPENCODE_PLUGIN_SPEC}@`)),\n\t);\n\tconst hasLegacySpec = (plugins as string[]).some(\n\t\t(entry) =>\n\t\t\ttypeof entry === \"string\" &&\n\t\t\tLEGACY_OPENCODE_PLUGIN_SPECS.some((spec) => entry === spec || entry.startsWith(`${spec}@`)),\n\t);\n\n\tif (hasCanonicalSpec && !hasLegacySpec && !force) {\n\t\tp.log.info(`Plugin \"${OPENCODE_PLUGIN_SPEC}\" already in plugin array`);\n\t\treturn true;\n\t}\n\n\tplugins = (plugins as string[]).filter((entry) => !isManagedPluginSpec(entry));\n\tif (hasLegacySpec) {\n\t\tp.log.step(\"Removed legacy OpenCode plugin spec(s): codemem / @kunickiaj/codemem\");\n\t}\n\n\t(plugins as string[]).push(OPENCODE_PLUGIN_SPEC);\n\tconfig.plugin = plugins;\n\n\ttry {\n\t\twriteJsonConfig(configPath, config);\n\t\tp.log.success(`Plugin \"${OPENCODE_PLUGIN_SPEC}\" added to ${configPath}`);\n\t} catch (err) {\n\t\tp.log.error(\n\t\t\t`Failed to write ${configPath}: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nfunction installMcp(force: boolean): boolean {\n\tconst configPath = resolveOpencodeConfigPath(opencodeConfigDir());\n\tlet config: Record<string, unknown>;\n\ttry {\n\t\tconfig = loadJsoncConfig(configPath);\n\t} catch (err) {\n\t\tp.log.error(\n\t\t\t`Failed to parse ${configPath}: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t\treturn false;\n\t}\n\n\tlet mcpConfig = config.mcp as Record<string, unknown> | undefined;\n\tif (mcpConfig == null || typeof mcpConfig !== \"object\" || Array.isArray(mcpConfig)) {\n\t\tmcpConfig = {};\n\t}\n\n\t// Auto-upgrade legacy uvx-based MCP entries.\n\tconst migrated = migrateLegacyOpencodeMcp(config);\n\n\tif (\"codemem\" in mcpConfig && !force && !migrated) {\n\t\tp.log.info(`MCP entry already exists in ${configPath}`);\n\t\treturn true;\n\t}\n\n\tif (!migrated) {\n\t\tmcpConfig.codemem = {\n\t\t\ttype: \"local\",\n\t\t\tcommand: [\"npx\", \"codemem\", \"mcp\"],\n\t\t\tenabled: true,\n\t\t};\n\t\tconfig.mcp = mcpConfig;\n\t}\n\n\ttry {\n\t\twriteJsonConfig(configPath, config);\n\t\tp.log.success(`MCP entry installed: ${configPath}`);\n\t} catch (err) {\n\t\tp.log.error(\n\t\t\t`Failed to write ${configPath}: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nfunction isClaudeHooksPluginInstalled(): boolean {\n\t// Check if the marketplace hooks plugin is installed by looking for\n\t// the hooks directory — NOT for MCP config (which we write ourselves).\n\tconst pluginDir = join(claudeConfigDir(), \"plugins\", \"codemem\");\n\tif (existsSync(pluginDir)) return true;\n\t// Also check for hook scripts installed by the marketplace plugin.\n\tconst hooksJson = join(pluginDir, \"hooks\", \"hooks.json\");\n\tif (existsSync(hooksJson)) return true;\n\treturn false;\n}\n\nfunction installClaudeMcp(force: boolean): boolean {\n\tconst settingsPath = join(claudeConfigDir(), \"settings.json\");\n\tlet settings: Record<string, unknown>;\n\ttry {\n\t\tsettings = loadJsoncConfig(settingsPath);\n\t} catch {\n\t\tsettings = {};\n\t}\n\n\tlet mcpServers = settings.mcpServers as Record<string, unknown> | undefined;\n\tif (mcpServers == null || typeof mcpServers !== \"object\" || Array.isArray(mcpServers)) {\n\t\tmcpServers = {};\n\t}\n\n\t// Auto-upgrade legacy uvx-based Claude MCP entries.\n\tconst migrated = migrateLegacyClaudeMcp(settings);\n\n\tif (\"codemem\" in mcpServers && !force && !migrated) {\n\t\tp.log.info(`Claude MCP entry already exists in ${settingsPath}`);\n\t} else {\n\t\tif (!migrated) {\n\t\t\tmcpServers.codemem = {\n\t\t\t\tcommand: \"npx\",\n\t\t\t\targs: [\"-y\", \"codemem\", \"mcp\"],\n\t\t\t};\n\t\t\tsettings.mcpServers = mcpServers;\n\t\t}\n\n\t\ttry {\n\t\t\twriteJsonConfig(settingsPath, settings);\n\t\t\tp.log.success(`Claude MCP entry installed: ${settingsPath}`);\n\t\t} catch (err) {\n\t\t\tp.log.error(\n\t\t\t\t`Failed to write ${settingsPath}: ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// Guide marketplace plugin install for hooks integration.\n\tif (!isClaudeHooksPluginInstalled() || force) {\n\t\tp.log.info(\"To install the Claude Code hooks plugin, run in Claude Code:\");\n\t\tp.log.info(\" /plugin marketplace add kunickiaj/codemem\");\n\t\tp.log.info(\" /plugin install codemem\");\n\t\tp.log.info(\"\");\n\t\tp.log.info(\"To update an existing install:\");\n\t\tp.log.info(\" /plugin marketplace update codemem-marketplace\");\n\t} else {\n\t\tp.log.info(\"Claude Code hooks plugin appears to be installed\");\n\t}\n\n\treturn true;\n}\n\nexport const setupCommand = new Command(\"setup\")\n\t.configureHelp(helpStyle)\n\t.description(\"Install codemem plugin + MCP config for OpenCode and Claude Code\")\n\t.option(\"--force\", \"overwrite existing installations\")\n\t.option(\"--opencode-only\", \"only install for OpenCode\")\n\t.option(\"--claude-only\", \"only install for Claude Code\")\n\t.action((opts: { force?: boolean; opencodeOnly?: boolean; claudeOnly?: boolean }) => {\n\t\tp.intro(`codemem setup v${VERSION}`);\n\t\tconst force = opts.force ?? false;\n\t\tlet ok = true;\n\n\t\tif (!opts.claudeOnly) {\n\t\t\tp.log.step(\"Installing OpenCode plugin...\");\n\t\t\tok = installPlugin(force) && ok;\n\t\t\tp.log.step(\"Installing OpenCode MCP config...\");\n\t\t\tok = installMcp(force) && ok;\n\t\t}\n\n\t\tif (!opts.opencodeOnly) {\n\t\t\tp.log.step(\"Installing Claude Code MCP config...\");\n\t\t\tok = installClaudeMcp(force) && ok;\n\t\t}\n\n\t\tif (ok) {\n\t\t\tp.outro(\"Setup complete — restart your editor to load the plugin\");\n\t\t} else {\n\t\t\tp.outro(\"Setup completed with warnings\");\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t});\n","import * as p from \"@clack/prompts\";\nimport { MemoryStore, resolveDbPath } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddDbOption,\n\taddJsonOption,\n\ttype DbOpts,\n\ttype JsonOpts,\n\tresolveDbOpt,\n} from \"../shared-options.js\";\n\nfunction fmtPct(n: number): string {\n\treturn `${Math.round(n * 100)}%`;\n}\n\nfunction fmtTokens(n: number): string {\n\tif (n >= 1_000_000_000) return `~${(n / 1_000_000_000).toFixed(1)}B`;\n\tif (n >= 1_000_000) return `~${(n / 1_000_000).toFixed(1)}M`;\n\tif (n >= 1_000) return `~${(n / 1_000).toFixed(0)}K`;\n\treturn `${n}`;\n}\n\nconst statsCmd = new Command(\"stats\")\n\t.configureHelp(helpStyle)\n\t.description(\"Show database statistics\");\n\naddDbOption(statsCmd);\naddJsonOption(statsCmd);\n\nexport const statsCommand = statsCmd.action((opts: DbOpts & JsonOpts) => {\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\ttry {\n\t\tconst result = store.stats();\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\treturn;\n\t\t}\n\n\t\tconst db = result.database;\n\t\tconst sizeMb = (db.size_bytes / 1_048_576).toFixed(1);\n\n\t\tp.intro(\"codemem stats\");\n\n\t\tp.log.info([`Path: ${db.path}`, `Size: ${sizeMb} MB`].join(\"\\n\"));\n\n\t\tp.log.success(\n\t\t\t[\n\t\t\t\t`Sessions: ${db.sessions.toLocaleString()}`,\n\t\t\t\t`Memories: ${db.active_memory_items.toLocaleString()} active / ${db.memory_items.toLocaleString()} total`,\n\t\t\t\t`Tags: ${db.tags_filled.toLocaleString()} filled (${fmtPct(db.tags_coverage)} of active)`,\n\t\t\t\t`Artifacts: ${db.artifacts.toLocaleString()}`,\n\t\t\t\t`Vectors: ${db.vector_rows.toLocaleString()} (${fmtPct(db.vector_coverage)} coverage)`,\n\t\t\t\t`Raw events: ${db.raw_events.toLocaleString()}`,\n\t\t\t].join(\"\\n\"),\n\t\t);\n\n\t\tif (result.usage.events.length > 0) {\n\t\t\tconst lines = result.usage.events.map((e: (typeof result.usage.events)[number]) => {\n\t\t\t\tconst parts = [`${e.event}: ${e.count.toLocaleString()}`];\n\t\t\t\tif (e.tokens_read > 0) parts.push(`read ${fmtTokens(e.tokens_read)} tokens`);\n\t\t\t\tif (e.tokens_saved > 0) parts.push(`est. saved ${fmtTokens(e.tokens_saved)} tokens`);\n\t\t\t\treturn ` ${parts.join(\", \")}`;\n\t\t\t});\n\n\t\t\tconst t = result.usage.totals;\n\t\t\tlines.push(\"\");\n\t\t\tlines.push(\n\t\t\t\t` Total: ${t.events.toLocaleString()} events, read ${fmtTokens(t.tokens_read)} tokens, est. saved ${fmtTokens(t.tokens_saved)} tokens`,\n\t\t\t);\n\n\t\t\tp.log.step(`Usage\\n${lines.join(\"\\n\")}`);\n\t\t}\n\n\t\tp.outro(\"done\");\n\t} finally {\n\t\tstore.close();\n\t}\n});\n","import { resolveDbOpt } from \"../shared-options.js\";\n\nexport interface SyncAttemptRow {\n\tpeer_device_id: string;\n\tok: number;\n\tops_in: number;\n\tops_out: number;\n\terror: string | null;\n\tfinished_at: string | null;\n}\n\nexport function formatSyncAttempt(row: SyncAttemptRow): string {\n\tconst status = row.ok ? \"ok\" : \"error\";\n\tconst error = String(row.error || \"\");\n\tconst suffix = error ? ` | ${error}` : \"\";\n\treturn `${row.peer_device_id}|${status}|in=${row.ops_in}|out=${row.ops_out}|${row.finished_at ?? \"\"}${suffix}`;\n}\n\nexport interface SyncLifecycleOptions {\n\tdb?: string;\n\tdbPath?: string;\n\tconfig?: string;\n\thost?: string;\n\tport?: string;\n\tuser?: boolean;\n\tsystem?: boolean;\n}\n\nexport function buildServeLifecycleArgs(\n\taction: \"start\" | \"stop\" | \"restart\",\n\topts: SyncLifecycleOptions,\n\tscriptPath: string,\n\texecArgv: string[] = [],\n): string[] {\n\tif (!scriptPath) throw new Error(\"Unable to resolve CLI entrypoint for sync lifecycle command\");\n\tconst args = [...execArgv, scriptPath, \"serve\"];\n\tif (action === \"start\") {\n\t\targs.push(\"--restart\");\n\t} else if (action === \"stop\") {\n\t\targs.push(\"--stop\");\n\t} else {\n\t\targs.push(\"--restart\");\n\t}\n\tconst dbResolved = resolveDbOpt(opts);\n\tif (dbResolved) args.push(\"--db-path\", dbResolved);\n\tif (opts.config) args.push(\"--config\", opts.config);\n\tif (opts.host) args.push(\"--host\", opts.host);\n\tif (opts.port) args.push(\"--port\", opts.port);\n\treturn args;\n}\n\nexport function formatSyncOnceResult(\n\tpeerDeviceId: string,\n\tresult: { ok: boolean; error?: string },\n): string {\n\tif (result.ok) return `- ${peerDeviceId}: ok`;\n\tconst suffix = result.error ? `: ${result.error}` : \"\";\n\treturn `- ${peerDeviceId}: error${suffix}`;\n}\n\nexport function parseProjectList(value: string | undefined): string[] {\n\tif (!value) return [];\n\treturn value\n\t\t.split(\",\")\n\t\t.map((item) => item.trim())\n\t\t.filter(Boolean);\n}\n\ntype InterfaceMap = Record<\n\tstring,\n\tArray<{ address: string; family?: string | number; internal?: boolean }> | undefined\n>;\n\nexport function collectAdvertiseAddresses(\n\texplicitAddress: string | null,\n\tconfiguredHost: string | null,\n\tport: number,\n\tinterfaces: InterfaceMap,\n): string[] {\n\tif (explicitAddress && ![\"auto\", \"default\"].includes(explicitAddress.toLowerCase())) {\n\t\treturn [explicitAddress];\n\t}\n\tif (configuredHost && configuredHost !== \"0.0.0.0\") {\n\t\treturn [`${configuredHost}:${port}`];\n\t}\n\tconst addresses = Object.values(interfaces)\n\t\t.flatMap((entries) => entries ?? [])\n\t\t.filter((entry) => !entry.internal)\n\t\t.map((entry) => entry.address)\n\t\t.filter((address) => address && address !== \"127.0.0.1\" && address !== \"::1\")\n\t\t.map((address) => `${address}:${port}`);\n\treturn [...new Set(addresses)];\n}\n","/**\n * Sync CLI commands — enable/disable/status/peers/connect.\n */\n\nimport { spawn } from \"node:child_process\";\nimport { readFileSync } from \"node:fs\";\nimport net from \"node:net\";\nimport { networkInterfaces } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport * as p from \"@clack/prompts\";\nimport {\n\tapplyBootstrapSnapshot,\n\tbuildAuthHeaders,\n\tbuildBaseUrl,\n\tensureDeviceIdentity,\n\tfetchAllSnapshotPages,\n\tfingerprintPublicKey,\n\thasUnsyncedSharedMemoryChanges,\n\tloadPublicKey,\n\tMemoryStore,\n\treadCodememConfigFile,\n\treadCodememConfigFileAtPath,\n\treadCoordinatorSyncConfig,\n\trequestJson,\n\tresolveDbPath,\n\trunSyncPass,\n\tschema,\n\tsetPeerProjectFilter,\n\tsyncPassPreflight,\n\tupdatePeerAddresses,\n\twriteCodememConfigFile,\n} from \"@codemem/core\";\nimport { Command, Option } from \"commander\";\nimport { desc, eq } from \"drizzle-orm\";\nimport { drizzle } from \"drizzle-orm/better-sqlite3\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddConfigOption,\n\taddDbOption,\n\taddJsonOption,\n\taddLegacyServiceFlags,\n\taddViewerHostOptions,\n\temitDeprecationWarning,\n\temitJsonError,\n\tresolveDbOpt,\n} from \"../shared-options.js\";\nimport { buildCoordinatorCommand } from \"./coordinator.js\";\nimport {\n\tbuildServeLifecycleArgs,\n\tcollectAdvertiseAddresses,\n\tformatSyncAttempt,\n\tformatSyncOnceResult,\n\tparseProjectList,\n\ttype SyncLifecycleOptions,\n} from \"./sync-helpers.js\";\n\nfunction readCliConfig(configPath?: string): Record<string, unknown> {\n\treturn configPath ? readCodememConfigFileAtPath(configPath) : readCodememConfigFile();\n}\n\nfunction writeCliConfig(config: Record<string, unknown>, configPath?: string): string {\n\treturn writeCodememConfigFile(config, configPath || undefined);\n}\n\nfunction parseAttemptsLimit(value: string): number {\n\tif (!/^\\d+$/.test(value.trim())) {\n\t\tthrow new Error(`Invalid --limit: ${value}`);\n\t}\n\treturn Number.parseInt(value, 10);\n}\n\nfunction parsePositiveIntegerOption(\n\tvalue: string | undefined,\n\tflagName: string,\n): number | undefined {\n\tif (value == null) return undefined;\n\tconst trimmed = value.trim();\n\tif (!/^\\d+$/.test(trimmed)) {\n\t\tthrow new Error(`Invalid ${flagName}: ${value}`);\n\t}\n\treturn Number.parseInt(trimmed, 10);\n}\n\ninterface SyncPairOptions {\n\taccept?: string;\n\tacceptFile?: string;\n\tpayloadOnly?: boolean;\n\tname?: string;\n\taddress?: string;\n\tinclude?: string;\n\texclude?: string;\n\tall?: boolean;\n\tdefault?: boolean;\n\tconfig?: string;\n\tdb?: string;\n\tdbPath?: string;\n\tjson?: boolean;\n}\n\nfunction resolvePeerMatch(\n\tdb: ReturnType<typeof drizzle>,\n\tpeerRef: string,\n): { peer_device_id: string; name: string | null } | null | \"ambiguous\" {\n\tconst trimmed = peerRef.trim();\n\tif (!trimmed) return null;\n\tconst byId = db\n\t\t.select({ peer_device_id: schema.syncPeers.peer_device_id, name: schema.syncPeers.name })\n\t\t.from(schema.syncPeers)\n\t\t.where(eq(schema.syncPeers.peer_device_id, trimmed))\n\t\t.get();\n\tif (byId) return byId;\n\tconst byName = db\n\t\t.select({ peer_device_id: schema.syncPeers.peer_device_id, name: schema.syncPeers.name })\n\t\t.from(schema.syncPeers)\n\t\t.where(eq(schema.syncPeers.name, trimmed))\n\t\t.all();\n\tif (byName.length > 1) return \"ambiguous\";\n\treturn byName[0] ?? null;\n}\n\nasync function portOpen(host: string, port: number): Promise<boolean> {\n\treturn new Promise((resolve) => {\n\t\tconst socket = net.createConnection({ host, port });\n\t\tconst done = (ok: boolean) => {\n\t\t\tsocket.removeAllListeners();\n\t\t\tsocket.destroy();\n\t\t\tresolve(ok);\n\t\t};\n\t\tsocket.setTimeout(300);\n\t\tsocket.once(\"connect\", () => done(true));\n\t\tsocket.once(\"timeout\", () => done(false));\n\t\tsocket.once(\"error\", () => done(false));\n\t});\n}\n\nfunction readViewerBinding(dbPath: string): { host: string; port: number } | null {\n\ttry {\n\t\tconst raw = readFileSync(join(dirname(dbPath), \"viewer.pid\"), \"utf8\");\n\t\tconst parsed = JSON.parse(raw) as Partial<{ host: string; port: number }>;\n\t\tif (typeof parsed.host === \"string\" && typeof parsed.port === \"number\") {\n\t\t\treturn { host: parsed.host, port: parsed.port };\n\t\t}\n\t} catch {\n\t\t// ignore malformed or missing pidfile\n\t}\n\treturn null;\n}\n\nfunction parseStoredAddressEndpoint(value: string): { host: string; port: number } | null {\n\ttry {\n\t\tconst normalized = value.includes(\"://\") ? value : `http://${value}`;\n\t\tconst url = new URL(normalized);\n\t\tconst port = url.port ? Number.parseInt(url.port, 10) : url.protocol === \"https:\" ? 443 : 80;\n\t\tif (!url.hostname || !Number.isFinite(port)) return null;\n\t\treturn { host: url.hostname, port };\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function runServeLifecycle(\n\taction: \"start\" | \"stop\" | \"restart\",\n\topts: SyncLifecycleOptions,\n): Promise<void> {\n\tif (opts.user === false || opts.system === true) {\n\t\tp.log.warn(\n\t\t\t\"TS sync lifecycle currently manages the local viewer process, not separate user/system services.\",\n\t\t);\n\t}\n\tif (action === \"start\") {\n\t\tconst config = readCoordinatorSyncConfig(readCliConfig(opts.config));\n\t\tif (config.syncEnabled !== true) {\n\t\t\tp.log.error(\"Sync is disabled. Run `codemem sync enable` first.\");\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\t\t// Don't pass sync_host/sync_port as viewer bind values.\n\t\t// The viewer binds its own host/port (default 127.0.0.1:38888)\n\t\t// and the sync protocol listener reads sync_host/sync_port\n\t\t// internally from readCoordinatorSyncConfig().\n\t}\n\tconst dbResolved = resolveDbOpt(opts);\n\tconst args = buildServeLifecycleArgs(action, opts, process.argv[1] ?? \"\", process.execArgv);\n\tawait new Promise<void>((resolve, reject) => {\n\t\tconst child = spawn(process.execPath, args, {\n\t\t\tcwd: process.cwd(),\n\t\t\tstdio: \"inherit\",\n\t\t\tenv: {\n\t\t\t\t...process.env,\n\t\t\t\t...(dbResolved ? { CODEMEM_DB: dbResolved } : {}),\n\t\t\t\t...(opts.config ? { CODEMEM_CONFIG: opts.config } : {}),\n\t\t\t},\n\t\t});\n\t\tchild.once(\"error\", reject);\n\t\tchild.once(\"exit\", (code: number | null) => {\n\t\t\tif (code && code !== 0) {\n\t\t\t\tprocess.exitCode = code;\n\t\t\t}\n\t\t\tresolve();\n\t\t});\n\t});\n}\n\nexport const syncCommand = new Command(\"sync\")\n\t.configureHelp(helpStyle)\n\t.description(\"Sync configuration and peer management\");\n\n// ---- sync attempts ----\n\nconst attemptsCmd = new Command(\"attempts\")\n\t.configureHelp(helpStyle)\n\t.description(\"Show recent sync attempts\")\n\t.option(\"--limit <n>\", \"max attempts\", \"10\");\naddDbOption(attemptsCmd);\naddJsonOption(attemptsCmd);\nattemptsCmd.action((opts: { db?: string; dbPath?: string; limit: string; json?: boolean }) => {\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\ttry {\n\t\tconst d = drizzle(store.db, { schema });\n\t\tconst limit = parseAttemptsLimit(opts.limit);\n\t\tconst rows = d\n\t\t\t.select({\n\t\t\t\tpeer_device_id: schema.syncAttempts.peer_device_id,\n\t\t\t\tok: schema.syncAttempts.ok,\n\t\t\t\tops_in: schema.syncAttempts.ops_in,\n\t\t\t\tops_out: schema.syncAttempts.ops_out,\n\t\t\t\terror: schema.syncAttempts.error,\n\t\t\t\tfinished_at: schema.syncAttempts.finished_at,\n\t\t\t})\n\t\t\t.from(schema.syncAttempts)\n\t\t\t.orderBy(desc(schema.syncAttempts.finished_at))\n\t\t\t.limit(limit)\n\t\t\t.all();\n\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify(rows, null, 2));\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const row of rows) {\n\t\t\tconsole.log(formatSyncAttempt(row));\n\t\t}\n\t} finally {\n\t\tstore.close();\n\t}\n});\nsyncCommand.addCommand(attemptsCmd);\n\n// ---- sync start/stop/restart [deprecated] ----\n\nfunction addDeprecatedLifecycleCommand(action: \"start\" | \"stop\" | \"restart\") {\n\tconst cmd = new Command(action)\n\t\t.configureHelp(helpStyle)\n\t\t.description(`[deprecated] ${action} sync daemon — use 'codemem serve ${action}'`);\n\taddDbOption(cmd);\n\taddConfigOption(cmd);\n\taddViewerHostOptions(cmd);\n\taddLegacyServiceFlags(cmd);\n\tcmd.action(async (opts: SyncLifecycleOptions) => {\n\t\temitDeprecationWarning(`codemem sync ${action}`, `codemem serve ${action}`);\n\t\tawait runServeLifecycle(action, opts);\n\t});\n\tsyncCommand.addCommand(cmd, { hidden: true });\n}\n\naddDeprecatedLifecycleCommand(\"start\");\naddDeprecatedLifecycleCommand(\"stop\");\naddDeprecatedLifecycleCommand(\"restart\");\n\n// ---- sync once ----\n\nconst onceCmd = new Command(\"once\")\n\t.configureHelp(helpStyle)\n\t.description(\"Run a single sync pass\")\n\t.option(\"--peer <peer>\", \"peer device id or name\");\naddDbOption(onceCmd);\naddJsonOption(onceCmd);\nonceCmd.action(async (opts: { db?: string; dbPath?: string; peer?: string; json?: boolean }) => {\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\ttry {\n\t\tconst keysDir = process.env.CODEMEM_KEYS_DIR?.trim() || undefined;\n\t\tsyncPassPreflight(store.db);\n\t\tconst d = drizzle(store.db, { schema });\n\t\tconst rows = opts.peer\n\t\t\t? (() => {\n\t\t\t\t\tconst deviceMatches = d\n\t\t\t\t\t\t.select({ peer_device_id: schema.syncPeers.peer_device_id })\n\t\t\t\t\t\t.from(schema.syncPeers)\n\t\t\t\t\t\t.where(eq(schema.syncPeers.peer_device_id, opts.peer))\n\t\t\t\t\t\t.all();\n\t\t\t\t\tif (deviceMatches.length > 0) return deviceMatches;\n\t\t\t\t\tconst nameMatches = d\n\t\t\t\t\t\t.select({ peer_device_id: schema.syncPeers.peer_device_id })\n\t\t\t\t\t\t.from(schema.syncPeers)\n\t\t\t\t\t\t.where(eq(schema.syncPeers.name, opts.peer))\n\t\t\t\t\t\t.all();\n\t\t\t\t\tif (nameMatches.length > 1) {\n\t\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\t\temitJsonError(\"ambiguous_peer\", `Peer name is ambiguous: ${opts.peer}`);\n\t\t\t\t\t\t\treturn [];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tp.log.error(`Peer name is ambiguous: ${opts.peer}`);\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\t\t\t\t\treturn nameMatches;\n\t\t\t\t})()\n\t\t\t: d.select({ peer_device_id: schema.syncPeers.peer_device_id }).from(schema.syncPeers).all();\n\n\t\tif (rows.length === 0) {\n\t\t\tif (process.exitCode) return; // already set by ambiguous peer\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\"no_peers\", \"No peers available for sync\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.warn(\"No peers available for sync\");\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\n\t\tlet hadFailure = false;\n\t\tconst results: Array<{\n\t\t\tpeer_device_id: string;\n\t\t\tok: boolean;\n\t\t\terror?: string;\n\t\t}> = [];\n\t\tfor (const row of rows) {\n\t\t\tconst result = await runSyncPass(store.db, row.peer_device_id, { keysDir });\n\t\t\tif (!result.ok) hadFailure = true;\n\t\t\tresults.push({\n\t\t\t\tpeer_device_id: row.peer_device_id,\n\t\t\t\tok: result.ok,\n\t\t\t\t...(result.error ? { error: result.error } : {}),\n\t\t\t});\n\t\t\tif (!opts.json) {\n\t\t\t\tconsole.log(formatSyncOnceResult(row.peer_device_id, result));\n\t\t\t}\n\t\t}\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify({ ok: !hadFailure, results }, null, 2));\n\t\t}\n\t\tif (hadFailure) {\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t} finally {\n\t\tstore.close();\n\t}\n});\nsyncCommand.addCommand(onceCmd);\n\n// ---- sync pair ----\n\nconst pairCmd = new Command(\"pair\")\n\t.configureHelp(helpStyle)\n\t.description(\"Print pairing payload or accept a peer payload\")\n\t.option(\"--accept <json>\", \"accept pairing payload JSON from another device\")\n\t.option(\"--accept-file <path>\", \"accept pairing payload from file path, or '-' for stdin\")\n\t.option(\"--payload-only\", \"when generating pairing payload, print JSON only\")\n\t.option(\"--name <name>\", \"label for the peer\")\n\t.option(\"--address <host:port>\", \"override peer address (host:port)\")\n\t.option(\"--include <projects>\", \"outbound-only allowlist for accepted peer\")\n\t.option(\"--exclude <projects>\", \"outbound-only blocklist for accepted peer\")\n\t.option(\"--all\", \"with --accept, push all projects to that peer\")\n\t.option(\"--default\", \"with --accept, use default/global push filters\");\naddDbOption(pairCmd);\naddConfigOption(pairCmd);\naddJsonOption(pairCmd);\npairCmd.action(async (opts: SyncPairOptions) => {\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\ttry {\n\t\tconst acceptModeRequested = opts.accept != null || opts.acceptFile != null;\n\t\tif (opts.payloadOnly && acceptModeRequested) {\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\n\t\t\t\t\t\"usage_error\",\n\t\t\t\t\t\"--payload-only cannot be combined with --accept or --accept-file\",\n\t\t\t\t\t2,\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.error(\"--payload-only cannot be combined with --accept or --accept-file\");\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\t\tif (opts.accept && opts.acceptFile) {\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\"usage_error\", \"Use only one of --accept or --accept-file\", 2);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.error(\"Use only one of --accept or --accept-file\");\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\n\t\tlet acceptText = opts.accept;\n\t\tif (opts.acceptFile) {\n\t\t\ttry {\n\t\t\t\tacceptText =\n\t\t\t\t\topts.acceptFile === \"-\"\n\t\t\t\t\t\t? await new Promise<string>((resolve, reject) => {\n\t\t\t\t\t\t\t\tlet text = \"\";\n\t\t\t\t\t\t\t\tprocess.stdin.setEncoding(\"utf8\");\n\t\t\t\t\t\t\t\tprocess.stdin.on(\"data\", (chunk) => {\n\t\t\t\t\t\t\t\t\ttext += chunk;\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tprocess.stdin.on(\"end\", () => resolve(text));\n\t\t\t\t\t\t\t\tprocess.stdin.on(\"error\", reject);\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t: readFileSync(opts.acceptFile, \"utf8\");\n\t\t\t} catch (error) {\n\t\t\t\tconst msg =\n\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t? `Failed to read pairing payload from ${opts.acceptFile}: ${error.message}`\n\t\t\t\t\t\t: `Failed to read pairing payload from ${opts.acceptFile}`;\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"read_error\", msg);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(msg);\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (acceptModeRequested && !(acceptText ?? \"\").trim()) {\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\n\t\t\t\t\t\"usage_error\",\n\t\t\t\t\t\"Empty pairing payload; provide JSON via --accept or --accept-file\",\n\t\t\t\t\t2,\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.error(\"Empty pairing payload; provide JSON via --accept or --accept-file\");\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\n\t\tif (!acceptText && (opts.include || opts.exclude || opts.all || opts.default)) {\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\n\t\t\t\t\t\"usage_error\",\n\t\t\t\t\t\"Project filters are outbound-only and must be set on the device running --accept\",\n\t\t\t\t\t2,\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.error(\n\t\t\t\t\"Project filters are outbound-only and must be set on the device running --accept\",\n\t\t\t);\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\n\t\tif (acceptText?.trim()) {\n\t\t\tif (opts.all && opts.default) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"usage_error\", \"Use only one of --all or --default\", 2);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(\"Use only one of --all or --default\");\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ((opts.all || opts.default) && (opts.include || opts.exclude)) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\n\t\t\t\t\t\t\"usage_error\",\n\t\t\t\t\t\t\"--include/--exclude cannot be combined with --all/--default\",\n\t\t\t\t\t\t2,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(\"--include/--exclude cannot be combined with --all/--default\");\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet payload: Record<string, unknown>;\n\t\t\ttry {\n\t\t\t\tpayload = JSON.parse(acceptText) as Record<string, unknown>;\n\t\t\t} catch (error) {\n\t\t\t\tconst msg =\n\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t? `Invalid pairing payload: ${error.message}`\n\t\t\t\t\t\t: \"Invalid pairing payload\";\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"invalid_payload\", msg);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(msg);\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst deviceId = String(payload.device_id || \"\").trim();\n\t\t\tconst fingerprint = String(payload.fingerprint || \"\").trim();\n\t\t\tconst publicKey = String(payload.public_key || \"\").trim();\n\t\t\tconst resolvedAddresses = opts.address?.trim()\n\t\t\t\t? [opts.address.trim()]\n\t\t\t\t: Array.isArray(payload.addresses)\n\t\t\t\t\t? (payload.addresses as unknown[])\n\t\t\t\t\t\t\t.filter((item): item is string => typeof item === \"string\" && item.trim().length > 0)\n\t\t\t\t\t\t\t.map((item) => item.trim())\n\t\t\t\t\t: [];\n\t\t\tif (!deviceId || !fingerprint || !publicKey || resolvedAddresses.length === 0) {\n\t\t\t\tconst msg = \"Pairing payload missing device_id, fingerprint, public_key, or addresses\";\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"invalid_payload\", msg);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(msg);\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (fingerprintPublicKey(publicKey) !== fingerprint) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"fingerprint_mismatch\", \"Pairing payload fingerprint mismatch\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(\"Pairing payload fingerprint mismatch\");\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tupdatePeerAddresses(store.db, deviceId, resolvedAddresses, {\n\t\t\t\tname: opts.name,\n\t\t\t\tpinnedFingerprint: fingerprint,\n\t\t\t\tpublicKey,\n\t\t\t});\n\n\t\t\tif (opts.default) {\n\t\t\t\tsetPeerProjectFilter(store.db, deviceId, { include: null, exclude: null });\n\t\t\t} else if (opts.all || opts.include || opts.exclude) {\n\t\t\t\tsetPeerProjectFilter(store.db, deviceId, {\n\t\t\t\t\tinclude: opts.all ? [] : parseProjectList(opts.include),\n\t\t\t\t\texclude: opts.all ? [] : parseProjectList(opts.exclude),\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify({ ok: true, peer_device_id: deviceId }));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.success(`Paired with ${deviceId}`);\n\t\t\treturn;\n\t\t}\n\n\t\tconst keysDir = process.env.CODEMEM_KEYS_DIR?.trim() || undefined;\n\t\tconst [deviceId, fingerprint] = ensureDeviceIdentity(store.db, { keysDir });\n\t\tconst publicKey = loadPublicKey(keysDir);\n\t\tif (!publicKey) {\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\"missing_key\", \"Public key missing\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.error(\"Public key missing\");\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\n\t\tconst config = readCliConfig(opts.config);\n\t\tconst explicitAddress = opts.address?.trim();\n\t\tconst configuredHost = typeof config.sync_host === \"string\" ? config.sync_host : null;\n\t\tconst configuredPort = typeof config.sync_port === \"number\" ? config.sync_port : 7337;\n\t\tconst addresses = collectAdvertiseAddresses(\n\t\t\texplicitAddress ?? null,\n\t\t\tconfiguredHost,\n\t\t\tconfiguredPort,\n\t\t\tnetworkInterfaces(),\n\t\t);\n\t\tconst payloadObj = {\n\t\t\tdevice_id: deviceId,\n\t\t\tfingerprint,\n\t\t\tpublic_key: publicKey,\n\t\t\taddress: addresses[0] ?? \"\",\n\t\t\taddresses,\n\t\t};\n\t\tconst payloadText = JSON.stringify(payloadObj);\n\n\t\tif (opts.payloadOnly || opts.json) {\n\t\t\tprocess.stdout.write(`${payloadText}\\n`);\n\t\t\treturn;\n\t\t}\n\n\t\tconst escaped = payloadText.replaceAll(\"'\", \"'\\\\''\");\n\t\tconsole.log(\"Pairing payload\");\n\t\tconsole.log(payloadText);\n\t\tconsole.log(\"On the other device, save this JSON to pairing.json, then run:\");\n\t\tconsole.log(\" codemem sync pair --accept-file pairing.json\");\n\t\tconsole.log(\"If you prefer inline JSON, run:\");\n\t\tconsole.log(` codemem sync pair --accept '${escaped}'`);\n\t\tconsole.log(\"For machine-friendly output next time, run:\");\n\t\tconsole.log(\" codemem sync pair --payload-only\");\n\t\tconsole.log(\n\t\t\t\"On the accepting device, --include/--exclude control both what it sends and what it accepts from that peer.\",\n\t\t);\n\t} finally {\n\t\tstore.close();\n\t}\n});\nsyncCommand.addCommand(pairCmd);\n\n// ---- sync doctor ----\n\nconst doctorCmd = new Command(\"doctor\")\n\t.configureHelp(helpStyle)\n\t.description(\"Diagnose common sync setup and connectivity issues\");\naddDbOption(doctorCmd);\naddConfigOption(doctorCmd);\naddJsonOption(doctorCmd);\ndoctorCmd.action(\n\tasync (opts: { db?: string; dbPath?: string; config?: string; json?: boolean }) => {\n\t\tconst config = readCliConfig(opts.config);\n\t\tconst dbPath = resolveDbPath(resolveDbOpt(opts));\n\t\tconst store = new MemoryStore(dbPath);\n\t\ttry {\n\t\t\tconst d = drizzle(store.db, { schema });\n\t\t\tconst device = d\n\t\t\t\t.select({ device_id: schema.syncDevice.device_id })\n\t\t\t\t.from(schema.syncDevice)\n\t\t\t\t.limit(1)\n\t\t\t\t.get();\n\t\t\tconst daemonState = d\n\t\t\t\t.select()\n\t\t\t\t.from(schema.syncDaemonState)\n\t\t\t\t.where(eq(schema.syncDaemonState.id, 1))\n\t\t\t\t.get();\n\t\t\tconst peers = d\n\t\t\t\t.select({\n\t\t\t\t\tpeer_device_id: schema.syncPeers.peer_device_id,\n\t\t\t\t\taddresses_json: schema.syncPeers.addresses_json,\n\t\t\t\t\tpinned_fingerprint: schema.syncPeers.pinned_fingerprint,\n\t\t\t\t\tpublic_key: schema.syncPeers.public_key,\n\t\t\t\t})\n\t\t\t\t.from(schema.syncPeers)\n\t\t\t\t.all();\n\n\t\t\tconst issues: string[] = [];\n\t\t\tconst syncHost = typeof config.sync_host === \"string\" ? config.sync_host : \"0.0.0.0\";\n\t\t\tconst syncPort = typeof config.sync_port === \"number\" ? config.sync_port : 7337;\n\t\t\tconst viewerBinding = readViewerBinding(dbPath);\n\n\t\t\tconst reachable = viewerBinding\n\t\t\t\t? await portOpen(viewerBinding.host, viewerBinding.port)\n\t\t\t\t: false;\n\n\t\t\tif (!reachable) issues.push(\"daemon not running\");\n\t\t\tif (!device) issues.push(\"identity missing\");\n\t\t\tif (\n\t\t\t\tdaemonState?.last_error &&\n\t\t\t\t(!daemonState.last_ok_at || daemonState.last_ok_at < (daemonState.last_error_at ?? \"\"))\n\t\t\t) {\n\t\t\t\tissues.push(\"daemon error\");\n\t\t\t}\n\t\t\tif (peers.length === 0) issues.push(\"no peers\");\n\t\t\tif (!config.sync_enabled) issues.push(\"sync is disabled\");\n\n\t\t\tconst peerDetails: Array<{\n\t\t\t\tpeer_device_id: string;\n\t\t\t\taddresses: number;\n\t\t\t\treachable: string;\n\t\t\t\tpinned: boolean;\n\t\t\t\thas_public_key: boolean;\n\t\t\t}> = [];\n\n\t\t\tfor (const peer of peers) {\n\t\t\t\tconst addresses = peer.addresses_json ? (JSON.parse(peer.addresses_json) as string[]) : [];\n\t\t\t\tconst endpoint = parseStoredAddressEndpoint(addresses[0] ?? \"\");\n\t\t\t\tconst reach = endpoint\n\t\t\t\t\t? (await portOpen(endpoint.host, endpoint.port))\n\t\t\t\t\t\t? \"ok\"\n\t\t\t\t\t\t: \"unreachable\"\n\t\t\t\t\t: \"unknown\";\n\t\t\t\tconst pinned = Boolean(peer.pinned_fingerprint);\n\t\t\t\tconst hasKey = Boolean(peer.public_key);\n\t\t\t\tpeerDetails.push({\n\t\t\t\t\tpeer_device_id: peer.peer_device_id,\n\t\t\t\t\taddresses: addresses.length,\n\t\t\t\t\treachable: reach,\n\t\t\t\t\tpinned,\n\t\t\t\t\thas_public_key: hasKey,\n\t\t\t\t});\n\t\t\t\tif (reach !== \"ok\") issues.push(`peer ${peer.peer_device_id} unreachable`);\n\t\t\t\tif (!pinned || !hasKey) issues.push(`peer ${peer.peer_device_id} not pinned`);\n\t\t\t}\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(\n\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\tenabled: config.sync_enabled === true,\n\t\t\t\t\t\tlisten: `${syncHost}:${syncPort}`,\n\t\t\t\t\t\tmdns: process.env.CODEMEM_SYNC_MDNS ? \"env-configured\" : \"default/off\",\n\t\t\t\t\t\tdaemon: reachable ? \"running\" : \"not running\",\n\t\t\t\t\t\tidentity: device?.device_id ?? null,\n\t\t\t\t\t\tdaemon_error: daemonState?.last_error ?? null,\n\t\t\t\t\t\tpeers: peerDetails,\n\t\t\t\t\t\tissues: [...new Set(issues)],\n\t\t\t\t\t\tok: issues.length === 0,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconsole.log(\"Sync doctor\");\n\t\t\tconsole.log(`- Enabled: ${config.sync_enabled === true}`);\n\t\t\tconsole.log(`- Listen: ${syncHost}:${syncPort}`);\n\t\t\tconsole.log(`- mDNS: ${process.env.CODEMEM_SYNC_MDNS ? \"env-configured\" : \"default/off\"}`);\n\t\t\tconsole.log(`- Daemon: ${reachable ? \"running\" : \"not running\"}`);\n\n\t\t\tif (!device) {\n\t\t\t\tconsole.log(\"- Identity: missing (run `codemem sync enable`)\");\n\t\t\t} else {\n\t\t\t\tconsole.log(`- Identity: ${device.device_id}`);\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tdaemonState?.last_error &&\n\t\t\t\t(!daemonState.last_ok_at || daemonState.last_ok_at < (daemonState.last_error_at ?? \"\"))\n\t\t\t) {\n\t\t\t\tconsole.log(\n\t\t\t\t\t`- Daemon error: ${daemonState.last_error} (at ${daemonState.last_error_at ?? \"unknown\"})`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (peers.length === 0) {\n\t\t\t\tconsole.log(\"- Peers: none (pair a device first)\");\n\t\t\t} else {\n\t\t\t\tconsole.log(`- Peers: ${peers.length}`);\n\t\t\t\tfor (const detail of peerDetails) {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t` - ${detail.peer_device_id}: addresses=${detail.addresses} reach=${detail.reachable} pinned=${detail.pinned} public_key=${detail.has_public_key}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (issues.length > 0) {\n\t\t\t\tconsole.log(`WARN: ${[...new Set(issues)].slice(0, 3).join(\", \")}`);\n\t\t\t} else {\n\t\t\t\tconsole.log(\"OK: sync looks healthy\");\n\t\t\t}\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\nsyncCommand.addCommand(doctorCmd);\n\n// ---- sync status ----\n\nconst statusCmd = new Command(\"status\")\n\t.configureHelp(helpStyle)\n\t.description(\"Show sync configuration and peer summary\");\naddDbOption(statusCmd);\naddConfigOption(statusCmd);\naddJsonOption(statusCmd);\nstatusCmd.action((opts: { db?: string; dbPath?: string; config?: string; json?: boolean }) => {\n\tconst config = readCliConfig(opts.config);\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\ttry {\n\t\tconst d = drizzle(store.db, { schema });\n\t\tconst deviceRow = d\n\t\t\t.select({\n\t\t\t\tdevice_id: schema.syncDevice.device_id,\n\t\t\t\tfingerprint: schema.syncDevice.fingerprint,\n\t\t\t})\n\t\t\t.from(schema.syncDevice)\n\t\t\t.limit(1)\n\t\t\t.get();\n\t\tconst peers = d\n\t\t\t.select({\n\t\t\t\tpeer_device_id: schema.syncPeers.peer_device_id,\n\t\t\t\tname: schema.syncPeers.name,\n\t\t\t\tlast_sync_at: schema.syncPeers.last_sync_at,\n\t\t\t\tlast_error: schema.syncPeers.last_error,\n\t\t\t})\n\t\t\t.from(schema.syncPeers)\n\t\t\t.all();\n\n\t\tif (opts.json) {\n\t\t\tconsole.log(\n\t\t\t\tJSON.stringify(\n\t\t\t\t\t{\n\t\t\t\t\t\tenabled: config.sync_enabled === true,\n\t\t\t\t\t\thost: config.sync_host ?? \"0.0.0.0\",\n\t\t\t\t\t\tport: config.sync_port ?? 7337,\n\t\t\t\t\t\tinterval_s: config.sync_interval_s ?? 120,\n\t\t\t\t\t\tdevice_id: deviceRow?.device_id ?? null,\n\t\t\t\t\t\tfingerprint: deviceRow?.fingerprint ?? null,\n\t\t\t\t\t\tcoordinator_url: config.sync_coordinator_url ?? null,\n\t\t\t\t\t\tpeers: peers.map((peer) => ({\n\t\t\t\t\t\t\tdevice_id: peer.peer_device_id,\n\t\t\t\t\t\t\tname: peer.name,\n\t\t\t\t\t\t\tlast_sync: peer.last_sync_at,\n\t\t\t\t\t\t\tstatus: peer.last_error ?? \"ok\",\n\t\t\t\t\t\t})),\n\t\t\t\t\t},\n\t\t\t\t\tnull,\n\t\t\t\t\t2,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tp.intro(\"codemem sync status\");\n\t\tp.log.info(\n\t\t\t[\n\t\t\t\t`Enabled: ${config.sync_enabled === true ? \"yes\" : \"no\"}`,\n\t\t\t\t`Host: ${config.sync_host ?? \"0.0.0.0\"}`,\n\t\t\t\t`Port: ${config.sync_port ?? 7337}`,\n\t\t\t\t`Interval: ${config.sync_interval_s ?? 120}s`,\n\t\t\t\t`Coordinator: ${config.sync_coordinator_url ?? \"(not configured)\"}`,\n\t\t\t].join(\"\\n\"),\n\t\t);\n\t\tif (deviceRow) {\n\t\t\tp.log.info(`Device ID: ${deviceRow.device_id}\\nFingerprint: ${deviceRow.fingerprint}`);\n\t\t} else {\n\t\t\tp.log.warn(\"Device identity not initialized (run `codemem sync enable`)\");\n\t\t}\n\t\tif (peers.length === 0) {\n\t\t\tp.log.info(\"Peers: none\");\n\t\t} else {\n\t\t\tfor (const peer of peers) {\n\t\t\t\tconst label = peer.name || peer.peer_device_id;\n\t\t\t\tp.log.message(\n\t\t\t\t\t` ${label}: last_sync=${peer.last_sync_at ?? \"never\"}, status=${peer.last_error ?? \"ok\"}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tp.outro(`${peers.length} peer(s)`);\n\t} finally {\n\t\tstore.close();\n\t}\n});\nsyncCommand.addCommand(statusCmd);\n\n// ---- sync enable ----\n\nconst enableCmd = new Command(\"enable\")\n\t.configureHelp(helpStyle)\n\t.description(\"Enable sync and initialize device identity\")\n\t.option(\"--sync-host <host>\", \"sync listen host\")\n\t.option(\"--sync-port <port>\", \"sync listen port\")\n\t.option(\"--interval <seconds>\", \"sync interval in seconds\");\naddDbOption(enableCmd);\naddConfigOption(enableCmd);\naddJsonOption(enableCmd);\n// Hidden aliases for backwards compat\nenableCmd.addOption(new Option(\"--host <host>\", \"sync listen host\").hideHelp());\nenableCmd.addOption(new Option(\"--port <port>\", \"sync listen port\").hideHelp());\nenableCmd.action(\n\t(opts: {\n\t\tdb?: string;\n\t\tdbPath?: string;\n\t\tconfig?: string;\n\t\tsyncHost?: string;\n\t\tsyncPort?: string;\n\t\thost?: string;\n\t\tport?: string;\n\t\tinterval?: string;\n\t\tjson?: boolean;\n\t}) => {\n\t\t// Emit deprecation warnings for legacy --host/--port\n\t\tif (opts.host && !opts.syncHost) {\n\t\t\temitDeprecationWarning(\"--host on sync enable\", \"--sync-host\");\n\t\t}\n\t\tif (opts.port && !opts.syncPort) {\n\t\t\temitDeprecationWarning(\"--port on sync enable\", \"--sync-port\");\n\t\t}\n\t\tconst effectiveHost = opts.syncHost ?? opts.host;\n\t\tconst effectivePort = opts.syncPort ?? opts.port;\n\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tconst [deviceId, fingerprint] = ensureDeviceIdentity(store.db);\n\t\t\tconst config = readCliConfig(opts.config);\n\t\t\tconfig.sync_enabled = true;\n\t\t\tif (effectiveHost) config.sync_host = effectiveHost;\n\t\t\tconst syncPort = parsePositiveIntegerOption(effectivePort, \"--sync-port\");\n\t\t\tconst syncInterval = parsePositiveIntegerOption(opts.interval, \"--interval\");\n\t\t\tif (syncPort != null) config.sync_port = syncPort;\n\t\t\tif (syncInterval != null) config.sync_interval_s = syncInterval;\n\t\t\twriteCliConfig(config, opts.config);\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(\n\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\tok: true,\n\t\t\t\t\t\tdevice_id: deviceId,\n\t\t\t\t\t\tfingerprint,\n\t\t\t\t\t\thost: config.sync_host ?? \"0.0.0.0\",\n\t\t\t\t\t\tport: config.sync_port ?? 7337,\n\t\t\t\t\t\tinterval_s: config.sync_interval_s ?? 120,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tp.intro(\"codemem sync enable\");\n\t\t\tp.log.success(\n\t\t\t\t[\n\t\t\t\t\t`Device ID: ${deviceId}`,\n\t\t\t\t\t`Fingerprint: ${fingerprint}`,\n\t\t\t\t\t`Host: ${config.sync_host ?? \"0.0.0.0\"}`,\n\t\t\t\t\t`Port: ${config.sync_port ?? 7337}`,\n\t\t\t\t\t`Interval: ${config.sync_interval_s ?? 120}s`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t\tp.outro(\"Sync enabled — restart `codemem serve` to activate\");\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\nsyncCommand.addCommand(enableCmd);\n\n// ---- sync disable ----\n\nconst disableCmd = new Command(\"disable\")\n\t.configureHelp(helpStyle)\n\t.description(\"Disable sync without deleting keys or peers\");\naddConfigOption(disableCmd);\ndisableCmd.action((opts: { config?: string }) => {\n\tconst config = readCliConfig(opts.config);\n\tconfig.sync_enabled = false;\n\twriteCliConfig(config, opts.config);\n\tp.intro(\"codemem sync disable\");\n\tp.outro(\"Sync disabled — restart `codemem serve` to take effect\");\n});\nsyncCommand.addCommand(disableCmd);\n\n// ---- sync peers ----\n\nconst peersCommand = new Command(\"peers\")\n\t.configureHelp(helpStyle)\n\t.description(\"List known sync peers\");\naddDbOption(peersCommand);\naddJsonOption(peersCommand);\npeersCommand.action((opts: { db?: string; dbPath?: string; json?: boolean }) => {\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\ttry {\n\t\tconst d = drizzle(store.db, { schema });\n\t\tconst peers = d\n\t\t\t.select({\n\t\t\t\tpeer_device_id: schema.syncPeers.peer_device_id,\n\t\t\t\tname: schema.syncPeers.name,\n\t\t\t\taddresses: schema.syncPeers.addresses_json,\n\t\t\t\tlast_sync_at: schema.syncPeers.last_sync_at,\n\t\t\t\tlast_error: schema.syncPeers.last_error,\n\t\t\t})\n\t\t\t.from(schema.syncPeers)\n\t\t\t.orderBy(desc(schema.syncPeers.last_sync_at))\n\t\t\t.all();\n\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify(peers, null, 2));\n\t\t\treturn;\n\t\t}\n\n\t\tp.intro(\"codemem sync peers\");\n\t\tif (peers.length === 0) {\n\t\t\tp.outro(\"No peers configured\");\n\t\t\treturn;\n\t\t}\n\t\tfor (const peer of peers) {\n\t\t\tconst label = peer.name || peer.peer_device_id;\n\t\t\tconst addrs = peer.addresses || \"(no addresses)\";\n\t\t\tp.log.message(\n\t\t\t\t`${label}\\n addresses: ${addrs}\\n last_sync: ${peer.last_sync_at ?? \"never\"}\\n status: ${peer.last_error ?? \"ok\"}`,\n\t\t\t);\n\t\t}\n\t\tp.outro(`${peers.length} peer(s)`);\n\t} finally {\n\t\tstore.close();\n\t}\n});\n\nconst peersRemoveCmd = new Command(\"remove\")\n\t.configureHelp(helpStyle)\n\t.description(\"Remove a sync peer by device id or exact name\")\n\t.argument(\"<peer>\", \"peer device id or exact name\");\naddDbOption(peersRemoveCmd);\naddJsonOption(peersRemoveCmd);\npeersRemoveCmd.action((peerRef: string, opts: { db?: string; dbPath?: string; json?: boolean }) => {\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\ttry {\n\t\tconst d = drizzle(store.db, { schema });\n\t\tconst match = resolvePeerMatch(d, peerRef);\n\t\tif (match === \"ambiguous\") {\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\"ambiguous_peer\", `Peer name is ambiguous: ${peerRef.trim()}`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.error(`Peer name is ambiguous: ${peerRef.trim()}`);\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\t\tif (!match) {\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\"peer_not_found\", `Peer not found: ${peerRef.trim()}`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.error(`Peer not found: ${peerRef.trim()}`);\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\t\td.delete(schema.replicationCursors)\n\t\t\t.where(eq(schema.replicationCursors.peer_device_id, match.peer_device_id))\n\t\t\t.run();\n\t\td.delete(schema.syncPeers)\n\t\t\t.where(eq(schema.syncPeers.peer_device_id, match.peer_device_id))\n\t\t\t.run();\n\t\tconst payload = {\n\t\t\tok: true,\n\t\t\tpeer_device_id: match.peer_device_id,\n\t\t\tname: match.name,\n\t\t};\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify(payload, null, 2));\n\t\t\treturn;\n\t\t}\n\t\tp.intro(\"codemem sync peers remove\");\n\t\tp.log.success(`Removed peer ${match.name || match.peer_device_id}`);\n\t\tp.outro(match.peer_device_id);\n\t} finally {\n\t\tstore.close();\n\t}\n});\npeersCommand.addCommand(peersRemoveCmd);\nsyncCommand.addCommand(peersCommand);\n\n// ---- sync bootstrap <peer-device-id> ----\n\nconst bootstrapCmd = new Command(\"bootstrap\")\n\t.configureHelp(helpStyle)\n\t.description(\"Fast-bootstrap memories from a peer (full snapshot transfer)\")\n\t.argument(\"[peer-device-id]\", \"peer device ID to bootstrap from\")\n\t.option(\"--bootstrap-grant <grant-id>\", \"bootstrap grant id for seed-authorized bootstrap\")\n\t.option(\"--page-size <n>\", \"items per snapshot page (default: 2000)\", \"2000\")\n\t.option(\"--keys-dir <path>\", \"keys directory\")\n\t.option(\"--force\", \"skip dirty-local-state safety check\");\naddDbOption(bootstrapCmd);\naddJsonOption(bootstrapCmd);\n// Hidden alias for backwards compat\nbootstrapCmd.addOption(new Option(\"--peer <device-id>\", \"peer device ID\").hideHelp());\nbootstrapCmd.action(\n\tasync (\n\t\tpeerArg: string | undefined,\n\t\topts: {\n\t\t\tpeer?: string;\n\t\t\tbootstrapGrant?: string;\n\t\t\tpageSize: string;\n\t\t\tdb?: string;\n\t\t\tdbPath?: string;\n\t\t\tkeysDir?: string;\n\t\t\tforce?: boolean;\n\t\t\tjson?: boolean;\n\t\t},\n\t) => {\n\t\t// Resolve peer from positional or hidden --peer alias\n\t\tconst peerDeviceId = (peerArg || opts.peer || \"\").trim();\n\t\tif (!peerDeviceId) {\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\"usage_error\", \"missing required argument: <peer-device-id>\", 2);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.error(\"missing required argument: <peer-device-id>\");\n\t\t\tprocess.exitCode = 2;\n\t\t\treturn;\n\t\t}\n\n\t\tconst dbPath = resolveDbPath(resolveDbOpt(opts));\n\t\tconst store = new MemoryStore(dbPath);\n\t\ttry {\n\t\t\tconst pageSize = Math.max(1, Number.parseInt(opts.pageSize, 10) || 2000);\n\t\t\tconst keysDir = opts.keysDir ?? undefined;\n\t\t\tconst d = drizzle(store.db, { schema });\n\n\t\t\t// Look up peer\n\t\t\tconst peer = d\n\t\t\t\t.select()\n\t\t\t\t.from(schema.syncPeers)\n\t\t\t\t.where(eq(schema.syncPeers.peer_device_id, peerDeviceId))\n\t\t\t\t.get();\n\t\t\tif (!peer) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"peer_not_found\", `Peer ${peerDeviceId} not found in sync_peers.`);\n\t\t\t\t} else {\n\t\t\t\t\tp.log.error(`Peer ${peerDeviceId} not found in sync_peers.`);\n\t\t\t\t}\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!peer.pinned_fingerprint) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\n\t\t\t\t\t\t\"peer_not_pinned\",\n\t\t\t\t\t\t`Peer ${peerDeviceId} has no pinned fingerprint. Accept it first.`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tp.log.error(`Peer ${peerDeviceId} has no pinned fingerprint. Accept it first.`);\n\t\t\t\t}\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Safety check\n\t\t\tif (!opts.force) {\n\t\t\t\tconst dirty = hasUnsyncedSharedMemoryChanges(store.db);\n\t\t\t\tif (dirty.dirty) {\n\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\temitJsonError(\n\t\t\t\t\t\t\t\"local_unsynced_changes\",\n\t\t\t\t\t\t\t`${dirty.count} unsynced shared memory change(s) would be lost. Use --force to override.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tp.log.error(\n\t\t\t\t\t\t\t`${dirty.count} unsynced shared memory change(s) would be lost. Use --force to override.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Resolve device identity\n\t\t\tconst [deviceId] = ensureDeviceIdentity(store.db, { keysDir });\n\n\t\t\t// Get peer status to obtain reset boundary\n\t\t\tconst addresses = JSON.parse(String(peer.addresses_json ?? \"[]\")) as string[];\n\t\t\tif (!addresses.length) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\n\t\t\t\t\t\t\"no_peer_addresses\",\n\t\t\t\t\t\t\"Peer has no known addresses. Run a sync first or add addresses.\",\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tp.log.error(\"Peer has no known addresses. Run a sync first or add addresses.\");\n\t\t\t\t}\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet boundary: {\n\t\t\t\tgeneration: number;\n\t\t\t\tsnapshot_id: string;\n\t\t\t\tbaseline_cursor: string | null;\n\t\t\t} | null = null;\n\t\t\tlet baseUrl = \"\";\n\t\t\tconst addressResults: Array<{ address: string; result: string }> = [];\n\n\t\t\tfor (const address of addresses) {\n\t\t\t\tconst candidate = buildBaseUrl(address);\n\t\t\t\tif (!candidate) continue;\n\t\t\t\tconst statusUrl = `${candidate}/v1/status`;\n\t\t\t\tconst headers = buildAuthHeaders({\n\t\t\t\t\tdeviceId,\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\turl: statusUrl,\n\t\t\t\t\tbodyBytes: Buffer.alloc(0),\n\t\t\t\t\tbootstrapGrantId: opts.bootstrapGrant,\n\t\t\t\t\tkeysDir,\n\t\t\t\t});\n\t\t\t\ttry {\n\t\t\t\t\tconst [code, payload] = await requestJson(\"GET\", statusUrl, { headers });\n\t\t\t\t\tif (code !== 200 || !payload) {\n\t\t\t\t\t\taddressResults.push({ address: candidate, result: `status ${code}` });\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (payload.fingerprint !== peer.pinned_fingerprint) {\n\t\t\t\t\t\taddressResults.push({ address: candidate, result: \"fingerprint mismatch\" });\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst reset = payload.sync_reset as Record<string, unknown> | undefined;\n\t\t\t\t\tif (\n\t\t\t\t\t\treset &&\n\t\t\t\t\t\ttypeof reset.generation === \"number\" &&\n\t\t\t\t\t\ttypeof reset.snapshot_id === \"string\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tboundary = {\n\t\t\t\t\t\t\tgeneration: reset.generation,\n\t\t\t\t\t\t\tsnapshot_id: reset.snapshot_id,\n\t\t\t\t\t\t\tbaseline_cursor:\n\t\t\t\t\t\t\t\ttypeof reset.baseline_cursor === \"string\" ? reset.baseline_cursor : null,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tbaseUrl = candidate;\n\t\t\t\t\t\taddressResults.push({ address: candidate, result: \"ok\" });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\taddressResults.push({ address: candidate, result: \"missing sync_reset boundary\" });\n\t\t\t\t} catch (err) {\n\t\t\t\t\taddressResults.push({\n\t\t\t\t\t\taddress: candidate,\n\t\t\t\t\t\tresult: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!boundary || !baseUrl) {\n\t\t\t\tconst summary = addressResults.map((r) => `${r.address}: ${r.result}`).join(\"; \");\n\t\t\t\tconst detail = summary\n\t\t\t\t\t? `no reachable peer with valid reset boundary. Tried: ${summary}`\n\t\t\t\t\t: \"peer unreachable or missing reset boundary\";\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify({ ok: false, error: detail, addresses: addressResults }));\n\t\t\t\t} else {\n\t\t\t\t\tp.log.error(detail);\n\t\t\t\t}\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!opts.json) {\n\t\t\t\tp.intro(\"codemem sync bootstrap\");\n\t\t\t\tp.log.step(`Bootstrapping from ${peer.name || peerDeviceId}...`);\n\t\t\t}\n\n\t\t\tconst resetInfo = {\n\t\t\t\tgeneration: boundary.generation,\n\t\t\t\tsnapshot_id: boundary.snapshot_id,\n\t\t\t\tbaseline_cursor: boundary.baseline_cursor,\n\t\t\t\tretained_floor_cursor: null,\n\t\t\t\treset_required: true as const,\n\t\t\t\treason: \"initial_bootstrap\" as const,\n\t\t\t};\n\n\t\t\tconst { items } = await fetchAllSnapshotPages(baseUrl, resetInfo, deviceId, {\n\t\t\t\tkeysDir,\n\t\t\t\tbootstrapGrantId: opts.bootstrapGrant,\n\t\t\t\tpageSize,\n\t\t\t});\n\n\t\t\tconst result = applyBootstrapSnapshot(store.db, peerDeviceId, items, resetInfo);\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(\n\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\tok: result.ok,\n\t\t\t\t\t\tapplied: result.applied,\n\t\t\t\t\t\tdeleted: result.deleted,\n\t\t\t\t\t\terror: result.error ?? null,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tp.log.success(`Applied ${result.applied} memories (removed ${result.deleted} stale).`);\n\t\t\t\t} else {\n\t\t\t\t\tp.log.error(result.error || \"Bootstrap apply failed.\");\n\t\t\t\t}\n\t\t\t\tp.outro(result.ok ? \"Bootstrap complete\" : \"Bootstrap failed\");\n\t\t\t}\n\t\t\tif (!result.ok) process.exitCode = 1;\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\nsyncCommand.addCommand(bootstrapCmd);\n\n// ---- sync connect <coordinator-url> ----\n\nconst connectCmd = new Command(\"connect\")\n\t.configureHelp(helpStyle)\n\t.description(\"Configure coordinator URL for cloud sync\")\n\t.argument(\"<url>\", \"coordinator URL (e.g. https://coordinator.example.com)\")\n\t.option(\"--group <group>\", \"sync group ID\");\naddConfigOption(connectCmd);\nconnectCmd.action((url: string, opts: { group?: string; config?: string }) => {\n\tconst config = readCliConfig(opts.config);\n\tconfig.sync_coordinator_url = url.trim();\n\tif (opts.group) config.sync_coordinator_group = opts.group.trim();\n\twriteCliConfig(config, opts.config);\n\tp.intro(\"codemem sync connect\");\n\tp.log.success(`Coordinator: ${url.trim()}`);\n\tif (opts.group) p.log.info(`Group: ${opts.group.trim()}`);\n\tp.outro(\"Restart `codemem serve` to activate coordinator sync\");\n});\nsyncCommand.addCommand(connectCmd);\n\n// ---- Deprecation alias: sync coordinator → coordinator ----\n// Build a separate coordinator command tree for the sync alias (Commander\n// re-parents commands on addCommand, so sharing instances is not possible).\n// The canonical coordinatorCommand lives in coordinator.ts and is registered\n// at the top level by index.ts.\n\nconst syncCoordinatorAlias = buildCoordinatorCommand();\n\nsyncCoordinatorAlias.hook(\"preAction\", (_thisCmd: Command, actionCmd: Command) => {\n\tconst subName = actionCmd.name();\n\temitDeprecationWarning(`codemem sync coordinator ${subName}`, `codemem coordinator ${subName}`);\n});\n\nsyncCommand.addCommand(syncCoordinatorAlias);\n","import { VERSION } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nexport const versionCommand = new Command(\"version\")\n\t.configureHelp(helpStyle)\n\t.description(\"Print codemem version\")\n\t.action(() => {\n\t\tconsole.log(VERSION);\n\t});\n","#!/usr/bin/env node\n\n/**\n * @codemem/cli — CLI entry point.\n *\n * Commands:\n * codemem stats → database statistics\n * codemem search → FTS5 memory search\n * codemem pack → context-aware memory pack\n * codemem serve → viewer server\n * codemem mcp → MCP stdio server\n */\n\nimport { VERSION } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport omelette from \"omelette\";\nimport { claudeHookIngestCommand } from \"./commands/claude-hook-ingest.js\";\nimport { claudeHookInjectCommand } from \"./commands/claude-hook-inject.js\";\nimport { configCommand } from \"./commands/config.js\";\nimport { coordinatorCommand } from \"./commands/coordinator.js\";\nimport { dbCommand } from \"./commands/db.js\";\nimport { embedCommand } from \"./commands/embed.js\";\nimport { enqueueRawEventCommand } from \"./commands/enqueue-raw-event.js\";\nimport { exportMemoriesCommand } from \"./commands/export-memories.js\";\nimport { importMemoriesCommand } from \"./commands/import-memories.js\";\nimport { mcpCommand } from \"./commands/mcp.js\";\nimport {\n\tforgetMemoryCommand,\n\tmemoryCommand,\n\trememberMemoryCommand,\n\tshowMemoryCommand,\n} from \"./commands/memory.js\";\nimport { packCommand } from \"./commands/pack.js\";\nimport { recentCommand } from \"./commands/recent.js\";\nimport { searchCommand } from \"./commands/search.js\";\nimport { serveCommand } from \"./commands/serve.js\";\nimport { setupCommand } from \"./commands/setup.js\";\nimport { statsCommand } from \"./commands/stats.js\";\nimport { syncCommand } from \"./commands/sync.js\";\nimport { versionCommand } from \"./commands/version.js\";\nimport { helpStyle } from \"./help-style.js\";\n\ntype CompletionWithScriptGenerators = ReturnType<typeof omelette> & {\n\tgenerateCompletionCode: () => string;\n\tgenerateCompletionCodeFish: () => string;\n};\n\n// Shell completion (bash/zsh/fish)\nconst completion = omelette(\"codemem <command>\") as CompletionWithScriptGenerators;\ncompletion.on(\"command\", ({ reply }) => {\n\treply([\n\t\t\"claude-hook-inject\",\n\t\t\"claude-hook-ingest\",\n\t\t\"config\",\n\t\t\"coordinator\",\n\t\t\"db\",\n\t\t\"embed\",\n\t\t\"enqueue-raw-event\",\n\t\t\"export-memories\",\n\t\t\"import-memories\",\n\t\t\"mcp\",\n\t\t\"memory\",\n\t\t\"pack\",\n\t\t\"recent\",\n\t\t\"search\",\n\t\t\"serve\",\n\t\t\"setup\",\n\t\t\"stats\",\n\t\t\"sync\",\n\t\t\"version\",\n\t\t\"help\",\n\t\t\"--help\",\n\t\t\"--version\",\n\t]);\n});\ncompletion.init();\n\nfunction hasRootFlag(flag: string): boolean {\n\tfor (const arg of process.argv.slice(2)) {\n\t\tif (arg === \"--\") return false;\n\t\tif (arg === flag) return true;\n\t\tif (!arg.startsWith(\"-\")) return false;\n\t}\n\treturn false;\n}\n\nfunction getShellCompletionScript(): string {\n\tconst shellPath = process.env.SHELL ?? \"\";\n\tif (shellPath.includes(\"fish\")) {\n\t\treturn completion.generateCompletionCodeFish();\n\t}\n\treturn completion.generateCompletionCode();\n}\n\nconst program = new Command();\n\nprogram\n\t.name(\"codemem\")\n\t.description(\"codemem — persistent memory for AI coding agents\")\n\t.enablePositionalOptions()\n\t.option(\"--install-completion\", \"install shell completion\")\n\t.option(\"--show-completion\", \"show shell completion install guidance\")\n\t.version(VERSION)\n\t.configureHelp(helpStyle);\n\nif (hasRootFlag(\"--setup-completion\") || hasRootFlag(\"--install-completion\")) {\n\tcompletion.setupShellInitFile();\n\tprocess.exit(0);\n}\n\nif (hasRootFlag(\"--show-completion\")) {\n\tconsole.log(getShellCompletionScript());\n\tprocess.exit(0);\n}\n\nif (hasRootFlag(\"--cleanup-completion\")) {\n\tcompletion.cleanupShellInitFile();\n\tprocess.exit(0);\n}\n\n// --- Memory subcommands: export/import registered under `memory` group ---\n// Per cli-design-conventions.md, export/import belong under their noun group.\n// The top-level export-memories/import-memories remain as compatibility aliases.\n//\n// We create thin wrapper commands that replicate the same argument/option shape\n// and delegate to the original command's parseAsync with synthetic argv.\n// This avoids accessing Commander internals while keeping a single source of\n// truth for the action logic in the original command modules.\n{\n\tconst memExport = new Command(\"export\")\n\t\t.description(\"Export memories to a JSON file for sharing or backup\")\n\t\t.argument(\"<output>\", \"output file path (use '-' for stdout)\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.option(\"--db-path <path>\", \"database path\")\n\t\t.option(\"--project <project>\", \"filter by project\")\n\t\t.option(\"--all-projects\", \"export all projects\")\n\t\t.option(\"--include-inactive\", \"include deactivated memories\")\n\t\t.option(\"--since <iso>\", \"only export memories created after this ISO timestamp\")\n\t\t.configureHelp(helpStyle)\n\t\t.allowUnknownOption(true)\n\t\t.allowExcessArguments(true)\n\t\t.action(async () => {\n\t\t\t// Forward to the original command by re-parsing the raw argv tail.\n\t\t\t// `memory export <args>` → `export-memories <args>`\n\t\t\tconst idx = process.argv.indexOf(\"export\");\n\t\t\tconst tail = idx >= 0 ? process.argv.slice(idx + 1) : [];\n\t\t\tawait exportMemoriesCommand.parseAsync([\"node\", \"export-memories\", ...tail]);\n\t\t});\n\n\tconst memImport = new Command(\"import\")\n\t\t.description(\"Import memories from an exported JSON file\")\n\t\t.argument(\"<inputFile>\", \"input JSON file (use '-' for stdin)\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.option(\"--db-path <path>\", \"database path\")\n\t\t.option(\"--remap-project <path>\", \"remap all projects to this path on import\")\n\t\t.option(\"--dry-run\", \"preview import without writing\")\n\t\t.configureHelp(helpStyle)\n\t\t.allowUnknownOption(true)\n\t\t.allowExcessArguments(true)\n\t\t.action(async () => {\n\t\t\tconst idx = process.argv.indexOf(\"import\");\n\t\t\tconst tail = idx >= 0 ? process.argv.slice(idx + 1) : [];\n\t\t\tawait importMemoriesCommand.parseAsync([\"node\", \"import-memories\", ...tail]);\n\t\t});\n\n\tmemoryCommand.addCommand(memExport);\n\tmemoryCommand.addCommand(memImport);\n}\n\nprogram.addCommand(serveCommand);\nprogram.addCommand(configCommand);\nprogram.addCommand(coordinatorCommand);\nprogram.addCommand(mcpCommand);\nprogram.addCommand(claudeHookInjectCommand);\nprogram.addCommand(claudeHookIngestCommand);\nprogram.addCommand(dbCommand);\nprogram.addCommand(exportMemoriesCommand);\nprogram.addCommand(importMemoriesCommand);\nprogram.addCommand(statsCommand);\nprogram.addCommand(embedCommand);\nprogram.addCommand(recentCommand);\nprogram.addCommand(searchCommand);\nprogram.addCommand(packCommand);\n// Deprecated top-level aliases — use `memory show`, `memory forget`, `memory remember` instead.\n// These are hidden from --help and shell completion but still functional for backwards compat.\nprogram.addCommand(showMemoryCommand, { hidden: true });\nprogram.addCommand(forgetMemoryCommand, { hidden: true });\nprogram.addCommand(rememberMemoryCommand, { hidden: true });\nprogram.addCommand(memoryCommand);\nprogram.addCommand(syncCommand);\nprogram.addCommand(setupCommand);\nprogram.addCommand(enqueueRawEventCommand);\nprogram.addCommand(versionCommand);\n\nprogram.parse();\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAUA,IAAa,YAA+B;CAC3C,aAAa,QAAQ,UAAU,QAAQ,IAAI;CAC3C,mBAAmB,QAAQ,UAAU,QAAQ,IAAI;CACjD,0BAA0B,QAAQ;CAClC,uBAAuB,QAAQ,UAAU,OAAO,IAAI;CACpD,kBAAkB,QAAQ,UAAU,SAAS,IAAI;CACjD,kBAAkB,QAAQ,UAAU,SAAS,IAAI;CACjD,sBAAsB,QAAQ,UAAU,QAAQ,IAAI;CACpD,oBAAoB,QAAQ,UAAU,UAAU,IAAI;CACpD;;;;ACDD,SAAgB,YAAY,KAAuB;AAClD,KAAI,UAAU,IAAI,OAAO,wBAAwB,wCAAwC,CAAC;AAE1F,KAAI,UAAU,IAAI,OAAO,eAAe,gBAAgB,CAAC,UAAU,CAAC;AACpE,QAAO;;;AAIR,SAAgB,aAAa,MAA4D;AACxF,QAAO,KAAK,UAAU,KAAK;;;AAQ5B,SAAgB,gBAAgB,KAAuB;AACtD,KAAI,UAAU,IAAI,OAAO,uBAAuB,+CAA+C,CAAC;AAChG,QAAO;;;AAQR,SAAgB,cAAc,KAAuB;AACpD,KAAI,UAAU,IAAI,OAAO,cAAc,iBAAiB,CAAC;AACzD,QAAO;;;AAQR,SAAgB,qBACf,KACA,WAA6C,EAAE,EACrC;AACV,KAAI,OAAO,iBAAiB,eAAe,SAAS,QAAQ,YAAY;AACxE,KAAI,OAAO,iBAAiB,eAAe,SAAS,QAAQ,QAAQ;AACpE,QAAO;;;AAQR,SAAgB,sBAAsB,KAAuB;AAC5D,KAAI,UAAU,IAAI,OAAO,UAAU,6BAA6B,CAAC,QAAQ,KAAK,CAAC,UAAU,CAAC;AAC1F,KAAI,UAAU,IAAI,OAAO,YAAY,6BAA6B,CAAC,UAAU,CAAC;AAC9E,QAAO;;;AAQR,SAAgB,uBAAuB,SAAiB,SAAuB;AAC9E,SAAQ,MAAM,aAAa,QAAQ,wBAAwB,QAAQ,YAAY;;;AAQhF,SAAgB,cAAc,WAAmB,SAAiB,WAAW,GAAS;AACrF,SAAQ,IAAI,KAAK,UAAU;EAAE,OAAO;EAAW;EAAS,CAAC,CAAC;AAC1D,SAAQ,WAAW;;;;;;;;;;;;;;;;AC1EpB,IAAM,wBAAwB,IAAI,IAAI;CAAC;CAAI;CAAK;CAAS;CAAO;CAAK;CAAQ;CAAO;CAAM;CAAK,CAAC;AAEhG,SAAS,aAAW,OAAuB;AAC1C,KAAI,UAAU,IAAK,QAAO,SAAS;AACnC,KAAI,MAAM,WAAW,KAAK,CAAE,QAAO,KAAK,SAAS,EAAE,MAAM,MAAM,EAAE,CAAC;AAClE,QAAO;;AAGR,SAAgB,gBAAwB;CACvC,MAAM,MAAM,QAAQ,IAAI,2BAA2B,QAAQ,IAAI,sBAAsB;CACrF,MAAM,aAAa,IAAI,MAAM,CAAC,aAAa;AAC3C,KAAI,sBAAsB,IAAI,WAAW,CACxC,QAAO,aAAW,wBAAwB;AAE3C,QAAO,aAAW,IAAI,MAAM,CAAC;;;;;;;AAQ9B,SAAgB,eAAe,SAAuB;CACrD,MAAM,OAAO,eAAe;AAC5B,KAAI;AACH,YAAU,QAAQ,KAAK,EAAE,EAAE,WAAW,MAAM,CAAC;AAC7C,iBAAe,MAAM,oBAAG,IAAI,MAAM,EAAC,aAAa,CAAC,GAAG,QAAQ,KAAK,EAAE,UAAU,QAAQ,CAAC;SAC/E;;;;;;;;;;ACtBT,IAAM,qBAAqB;AAC3B,IAAM,uBAAuB;AAC7B,IAAM,wBAAwB;AAC9B,IAAM,0BAA0B;AAchC,IAAa,gBAAb,cAAmC,MAAM;CACxC,cAAc;AACb,QAAM,+BAA+B;AACrC,OAAK,OAAO;;;AAId,SAAS,aAAW,OAAuB;AAC1C,KAAI,UAAU,IAAK,QAAO,SAAS;AACnC,KAAI,MAAM,WAAW,KAAK,CAAE,QAAO,KAAK,SAAS,EAAE,MAAM,MAAM,EAAE,CAAC;AAClE,QAAO;;AAGR,SAAS,OAAO,MAAc,UAA0B;CACvD,MAAM,MAAM,QAAQ,IAAI;AACxB,KAAI,QAAQ,KAAA,EAAW,QAAO;CAC9B,MAAM,SAAS,OAAO,SAAS,KAAK,GAAG;AACvC,QAAO,OAAO,SAAS,OAAO,GAAG,SAAS;;AAG3C,SAAS,YAAU,MAAc,UAA4B;CAC5D,MAAM,MAAM,QAAQ,IAAI;AACxB,KAAI,QAAQ,KAAA,EAAW,QAAO;CAC9B,MAAM,aAAa,IAAI,MAAM,CAAC,aAAa;AAC3C,KAAI;EAAC;EAAK;EAAQ;EAAO;EAAK,CAAC,SAAS,WAAW,CAAE,QAAO;AAC5D,KAAI;EAAC;EAAK;EAAS;EAAM;EAAM,CAAC,SAAS,WAAW,CAAE,QAAO;AAC7D,QAAO;;AAGR,SAAS,aAAyB;AAIjC,QAAO;EACN,SAJe,aACf,QAAQ,IAAI,8BAA8B,MAAM,IAAI,qCACpD;EAGA,YAAY,KAAK,IAAI,GAAG,OAAO,kCAAkC,mBAAmB,CAAC;EACrF,cAAc,KAAK,IAAI,GAAG,OAAO,oCAAoC,qBAAqB,CAAC;EAC3F;;AAGF,SAAgB,WAAmB;AAClC,QAAO,aACN,QAAQ,IAAI,+BAA+B,MAAM,IAAI,+BACrD;;;;;;;;;;AAWF,SAAgB,oBAA6B;CAC5C,MAAM,MAAM,UAAU;CACtB,IAAI;AACJ,KAAI;AACH,YAAU,YAAY,IAAI;SACnB;AACP,SAAO;;AAER,MAAK,MAAM,QAAQ,SAAS;AAC3B,MAAI,CAAC,KAAK,SAAS,QAAQ,CAAE;AAC7B,MAAI,KAAK,WAAW,aAAa,IAAI,KAAK,WAAW,QAAQ,CAAE;AAC/D,SAAO;;AAER,QAAO;;AAGR,SAAS,uBAAuB,MAAsB;AACrD,KAAI;AACH,SAAO,aAAa,MAAM,OAAO,CAAC,MAAM;SACjC;AACP,SAAO;;;AAIT,SAAS,iBAAiB,SAA+B;CACxD,MAAM,MAAM,uBAAuB,KAAK,SAAS,MAAM,CAAC;CACxD,MAAM,QAAQ,uBAAuB,KAAK,SAAS,QAAQ,CAAC;CAC5D,MAAM,QAAQ,uBAAuB,KAAK,SAAS,KAAK,CAAC;CACzD,MAAM,KAAK,UAAU,KAAK,OAAO,OAAO,SAAS,OAAO,GAAG;AAC3D,QAAO;EACN;EACA,IAAI,OAAO,QAAQ,CAAC,OAAO,SAAS,GAAG,GAAG,OAAO;EACjD;EACA;;AAGF,SAAS,WAAW,SAA0B;CAC7C,MAAM,MAAM,OAAO,SAAS,SAAS,GAAG;AACxC,KAAI,CAAC,OAAO,SAAS,IAAI,IAAI,OAAO,EAAG,QAAO;AAC9C,KAAI;AAEH,UAAQ,KAAK,KAAK,EAAE;AACpB,SAAO;SACA;AACP,SAAO;;;AAIT,SAAS,YAAY,KAA6D;CACjF,MAAM,WAAW,iBAAiB,IAAI,QAAQ;CAC9C,MAAM,OAAO,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK;AAE1C,KAAI,SAAS,KAAK;AACjB,MAAI,WAAW,SAAS,IAAI,EAAE;AAC7B,OAAI,SAAS,OAAO,KAAM,QAAO;IAAE,OAAO;IAAO;IAAU;AAC3D,UAAO;IAAE,OAAO,OAAO,SAAS,KAAK,IAAI;IAAY;IAAU;;AAEhE,SAAO;GAAE,OAAO;GAAM;GAAU;;AAGjC,KAAI,SAAS,OAAO,KACnB,QAAO;EAAE,OAAO,OAAO,SAAS,KAAK,IAAI;EAAc;EAAU;CAGlE,IAAI;AACJ,KAAI;AACH,WAAS,KAAK,MAAM,SAAS,IAAI,QAAQ,CAAC,UAAU,IAAK;SAClD;AACP,SAAO;GAAE,OAAO;GAAM;GAAU;;AAEjC,QAAO;EAAE,OAAO,OAAO,SAAS,IAAI;EAAc;EAAU;;AAG7D,SAAS,eAAe,SAAuB;AAC9C,MAAK,MAAM,QAAQ;EAAC;EAAO;EAAM;EAAQ,CACxC,KAAI;AACH,aAAW,KAAK,SAAS,KAAK,CAAC;SACxB;AAIT,KAAI;AACH,YAAU,QAAQ;SACX;;AAKT,SAAS,eAAe,GAAiB,GAA0B;AAClE,QAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE;;AAG1D,SAAS,0BAA0B,SAAiB,UAA8B;AAEjF,KAAI,eADY,iBAAiB,QAAQ,EACb,SAAS,CACpC,gBAAe,QAAQ;;AAIzB,SAAS,iBAAiB,KAA4C;AACrE,QAAO,OAAO,QAAQ,YAAY,QAAQ,QAAQ,UAAU;;AAG7D,eAAe,MAAM,IAA2B;AAC/C,QAAO,IAAI,SAAS,YAAY,WAAW,SAAS,GAAG,CAAC;;;;;;;;;;;;AAazD,eAAsB,yBAA4B,IAAsC;CACvF,MAAM,MAAM,YAAY;AACxB,WAAU,QAAQ,IAAI,QAAQ,EAAE,EAAE,WAAW,MAAM,CAAC;CACpD,MAAM,aAAa,GAAG,QAAQ,IAAI,GAAG,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK,CAAC,GAAG,UAAU,KAAM,IAAM;CAE5F,IAAI,WAAW;AACf,MAAK,IAAI,UAAU,GAAG,UAAU,uBAAuB,WAAW;AACjE,MAAI;AACH,aAAU,IAAI,QAAQ;WACd,KAAK;AACb,OAAI,iBAAiB,IAAI,IAAI,IAAI,SAAS,UAAU;IACnD,MAAM,EAAE,OAAO,aAAa,YAAY,IAAI;AAC5C,QAAI,MACH,2BAA0B,IAAI,SAAS,SAAS;AAEjD,UAAM,MAAM,wBAAwB;AACpC;;AAED,SAAM,MAAM,wBAAwB;AACpC;;AAGD,MAAI;AACH,iBAAc,KAAK,IAAI,SAAS,KAAK,EAAE,OAAO,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK,CAAC,EAAE,EAC7E,UAAU,QACV,CAAC;AACF,iBAAc,KAAK,IAAI,SAAS,MAAM,EAAE,OAAO,QAAQ,IAAI,EAAE,EAAE,UAAU,QAAQ,CAAC;AAClF,iBAAc,KAAK,IAAI,SAAS,QAAQ,EAAE,YAAY,EAAE,UAAU,QAAQ,CAAC;AAC3E,cAAW;AACX;UACO;AACP,kBAAe,IAAI,QAAQ;AAC3B,SAAM,MAAM,wBAAwB;;;AAItC,KAAI,CAAC,SACJ,OAAM,IAAI,eAAe;AAG1B,KAAI;AACH,SAAO,MAAM,IAAI;WACR;AAET,MADqB,uBAAuB,KAAK,IAAI,SAAS,QAAQ,CAAC,KAClD,WACpB,gBAAe,IAAI,QAAQ;;;;;;;;AAU9B,SAAgB,aAAa,SAA2C;CACvE,MAAM,MAAM,UAAU;AACtB,KAAI;AACH,YAAU,KAAK,EAAE,WAAW,MAAM,CAAC;SAC5B;AACP,iBAAe,wDAAwD;AACvE,SAAO;;CAGR,MAAM,cAAc,KAAK,UAAU,QAAQ;CAE3C,MAAM,UAAU,KAAK,KADL,aAAa,QAAQ,IAAI,GAAG,KAAK,KAAK,CAAC,GAAG,UAAU,KAAM,IAAM,CAAC,OAC/C;AAClC,KAAI;AACH,gBAAc,SAAS,aAAa,EAAE,UAAU,QAAQ,CAAC;SAClD;AACP,iBAAe,gEAAgE;AAC/E,SAAO;;CAIR,MAAM,YAAY,KAAK,KADL,QAAQ,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK,CAAC,GAAG,QAAQ,IAAI,GAAG,UAAU,KAAM,IAAM,CAAC,OAC3D;AACtC,KAAI;AACH,aAAW,SAAS,UAAU;SACvB;AACP,MAAI;AACH,cAAW,QAAQ;UACZ;AAGR,iBAAe,qDAAqD;AACpE,SAAO;;AAER,gBAAe,+CAA+C,YAAY;AAC1E,QAAO;;;;;;;;;AAUR,SAAgB,qBAAqB,YAA0B;CAC9D,MAAM,MAAM,UAAU;AACtB,KAAI;AACH,YAAU,KAAK,EAAE,WAAW,MAAM,CAAC;SAC5B;AACP;;CAGD,IAAI;AACJ,KAAI;AACH,YAAU,YAAY,IAAI;SACnB;AACP;;CAGD,MAAM,OAAO,KAAK,KAAK,GAAG;AAC1B,MAAK,MAAM,QAAQ,SAAS;AAC3B,MAAI,CAAC,KAAK,WAAW,aAAa,IAAI,CAAC,KAAK,SAAS,QAAQ,CAAE;EAC/D,MAAM,UAAU,KAAK,KAAK,KAAK;EAC/B,IAAI;AACJ,MAAI;AACH,YAAS,SAAS,QAAQ,CAAC,UAAU;UAC9B;AACP;;AAED,MAAI,OAAO,UAAU,WAAY;EAGjC,MAAM,gBAAgB,KAAK,KADL,kBAAkB,KAAK,MAAM,KAAK,CAAC,GAAG,QAAQ,IAAI,GAAG,UAAU,KAAM,IAAM,CAAC,OACpD;AAC9C,MAAI;AACH,cAAW,SAAS,cAAc;AAClC,kBACC,kEAAkE,gBAClE;UACM;;;;;;;;;AAYV,SAAS,qBAAqB,KAAa,MAAc,QAAsB;CAC9E,MAAM,aAAa,KAAK,KAAK,KAAK;CAClC,MAAM,iBAAiB,QAAQ,OAAO,GAAG,KAAK,KAAK,CAAC,GAAG,UAAU,KAAM,IAAM,CAAC,GAAG;AACjF,KAAI;AACH,aAAW,YAAY,KAAK,KAAK,eAAe,CAAC;AACjD,iBACC,iEAAiE,OAAO,KAAK,iBAC7E;SACM;AAGP,MAAI;AACH,cAAW,WAAW;AACtB,kBACC,6DAA6D,OAAO,KAAK,OACzE;UACM;;;;;;;;;;;AAqBV,eAAsB,WAAW,SAAkD;CAClF,MAAM,MAAM,UAAU;AACtB,KAAI;AACH,YAAU,KAAK,EAAE,WAAW,MAAM,CAAC;SAC5B;AACP,SAAO;GAAE,WAAW;GAAG,QAAQ;GAAG;;CAGnC,IAAI;AACJ,KAAI;AACH,YAAU,YAAY,IAAI;SACnB;AACP,SAAO;GAAE,WAAW;GAAG,QAAQ;GAAG;;CAGnC,MAAM,SAAS,QACb,QACC,SACA,KAAK,SAAS,QAAQ,IAAI,CAAC,KAAK,WAAW,aAAa,IAAI,CAAC,KAAK,WAAW,QAAQ,CACtF,CACA,MAAM;CAER,MAAM,SAA2B;EAAE,WAAW;EAAG,QAAQ;EAAG;AAC5D,MAAK,MAAM,QAAQ,QAAQ;EAC1B,MAAM,OAAO,KAAK,KAAK,KAAK;EAC5B,IAAI;AACJ,MAAI;AACH,SAAM,aAAa,MAAM,OAAO;UACzB;AAGP,kBAAe,8DAA8D,OAAO;AACpF,UAAO;AACP;;EAED,IAAI;AACJ,MAAI;AACH,YAAS,KAAK,MAAM,IAAI;UACjB;AAIP,wBAAqB,KAAK,MAAM,cAAc;AAC9C,UAAO;AACP;;AAED,MAAI,UAAU,QAAQ,OAAO,WAAW,YAAY,MAAM,QAAQ,OAAO,EAAE;AAE1E,wBAAqB,KAAK,MAAM,cAAc;AAC9C;;EAGD,IAAI,KAAK;AACT,MAAI;AACH,QAAK,MAAM,QAAQ,OAAkC;UAC9C;AACP,QAAK;;AAGN,MAAI,GACH,KAAI;AACH,cAAW,KAAK;AAChB,UAAO;UACA;OAGF;AACN,kBAAe,iEAAiE,OAAO;AACvF,UAAO;;;AAGT,QAAO;;;;;;;;AASR,SAAgB,yBAAyB,SAA2C;CACnF,MAAM,YACL,OAAO,QAAQ,oBAAoB,WAAW,QAAQ,gBAAgB,MAAM,GAAG;AAChF,KAAI,cAAc,UAAU,cAAc,aAAc,QAAO;AAC/D,KAAI,cAAc,aACjB,QAAO,YAAU,6BAA6B,KAAK;AAEpD,KAAI,CAAC,YAAU,6BAA6B,MAAM,CAAE,QAAO;AAC3D,QAAO,YAAU,qCAAqC,MAAM;;;;;;;AAQ7D,SAAgB,iBAAyB;AACxC,QAAO,YAAY,CAAC;;;;;;;;;;;;ACndrB,IAAM,qBAAqB;AAC3B,IAAM,wBAAwB;AAC9B,IAAM,kBAAkB;AACxB,IAAM,2BAA2B;AAEjC,IAAM,sBAAsB,IAAI,IAAI;CAAC;CAAQ;CAAS;CAAa;CAAgB;CAAc,CAAC;AAElG,IAAM,4BAA4B;CAAC;CAAkB;CAAqB;CAAoB;AAE9F,SAAgB,sBAAoC;AACnD,QAAO;EACN,cAAc;EACd,aAAa;EACb,gBAAgB,EAAE;EAClB,YAAY;EACZ;;AAGF,SAAS,WAAW,OAAuB;AAC1C,KAAI,UAAU,IAAK,QAAO,SAAS;AACnC,KAAI,MAAM,WAAW,KAAK,CAAE,QAAO,KAAK,SAAS,EAAE,MAAM,MAAM,EAAE,CAAC;AAClE,QAAO;;AAGR,SAAgB,aAAqB;CACpC,MAAM,WAAW,QAAQ,IAAI;AAC7B,QAAO,WAAW,UAAU,MAAM,GAAG,WAAW,iCAAiC;;AAGlF,SAAgB,oBAAoB,WAA2B;CAC9D,MAAM,SAAS,WAAW,OAAO,CAAC,OAAO,UAAU,CAAC,OAAO,MAAM,CAAC,MAAM,GAAG,GAAG;AAC9E,QAAO,KAAK,YAAY,EAAE,GAAG,OAAO,OAAO;;;;;;;;AAS5C,SAAgB,oBAAoB,OAAwB;AAC3D,KAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAO,MAAM,MAAM,CAAC,QAAQ,OAAO,IAAI;;AAGxC,SAAS,oBAAoB,OAAgB,KAAuB;AACnE,KAAI,CAAC,MAAM,QAAQ,MAAM,CAAE,QAAO,EAAE;CACpC,MAAM,MAAgB,EAAE;AACxB,MAAK,MAAM,QAAQ,OAAO;AACzB,MAAI,OAAO,SAAS,SAAU;EAC9B,MAAM,UAAU,KAAK,MAAM;AAC3B,MAAI,QAAS,KAAI,KAAK,QAAQ;;AAE/B,QAAO,IAAI,MAAM,GAAG,IAAI;;AAGzB,SAAgB,iBAAiB,WAAiC;CACjE,MAAM,OAAO,oBAAoB,UAAU;AAC3C,KAAI,CAAC,WAAW,KAAK,CAAE,QAAO,qBAAqB;AACnD,KAAI;EACH,MAAM,MAAM,aAAa,MAAM,OAAO;EACtC,MAAM,SAAkB,KAAK,MAAM,IAAI;AACvC,MAAI,UAAU,QAAQ,OAAO,WAAW,YAAY,MAAM,QAAQ,OAAO,CACxE,QAAO,qBAAqB;EAE7B,MAAM,MAAM;AACZ,SAAO;GACN,cAAc,OAAO,IAAI,iBAAiB,WAAW,IAAI,aAAa,MAAM,GAAG;GAC/E,aAAa,OAAO,IAAI,gBAAgB,WAAW,IAAI,YAAY,MAAM,GAAG;GAC5E,gBAAgB,oBAAoB,IAAI,gBAAgB,mBAAmB;GAC3E,YAAY,OAAO,IAAI,eAAe,WAAW,IAAI,WAAW,MAAM,GAAG;GACzE;SACM;AACP,SAAO,qBAAqB;;;AAI9B,SAAS,SAAiB;AACzB,yBAAO,IAAI,MAAM,EAAC,aAAa;;AAGhC,SAAgB,iBAAiB,WAAmB,OAA2B;AAE9E,WADY,YAAY,EACT,EAAE,WAAW,MAAM,CAAC;CACnC,MAAM,OAAO,oBAAoB,UAAU;CAC3C,MAAM,UAAU,GAAG,KAAK;CACxB,MAAM,UAAU;EACf,cAAc,OAAO,MAAM,gBAAgB,GAAG;EAC9C,aAAa,OAAO,MAAM,eAAe,GAAG;EAC5C,gBAAgB,oBAAoB,MAAM,gBAAgB,mBAAmB;EAC7E,YAAY,OAAO,MAAM,cAAc,GAAG;EAC1C;AACD,eAAc,SAAS,KAAK,UAAU,QAAQ,EAAE,EAAE,UAAU,QAAQ,CAAC;AACrE,YAAW,SAAS,KAAK;;AAG1B,SAAgB,kBAAkB,WAAyB;CAC1D,MAAM,OAAO,oBAAoB,UAAU;AAC3C,KAAI;AACH,SAAO,MAAM,EAAE,OAAO,MAAM,CAAC;SACtB;;AAKT,SAAS,uBAAuB,WAA6B;CAC5D,MAAM,MAAgB,EAAE;AACxB,MAAK,MAAM,QAAQ,UAAU,MAAM,KAAK,CACvC,MAAK,MAAM,UAAU,0BACpB,KAAI,KAAK,WAAW,OAAO,EAAE;EAC5B,MAAM,OAAO,KAAK,MAAM,OAAO,OAAO,CAAC,MAAM;AAC7C,MAAI,KAAM,KAAI,KAAK,KAAK;;AAI3B,QAAO;;AAGR,SAAgB,6BAA6B,SAA4C;CACxF,MAAM,WAAW,OAAO,QAAQ,aAAa,GAAG,CAC9C,MAAM,CACN,aAAa;AACf,KAAI,CAAC,oBAAoB,IAAI,SAAS,CAAE,QAAO,EAAE;CAEjD,MAAM,YAAY,QAAQ;AAC1B,KAAI,aAAa,QAAQ,OAAO,cAAc,YAAY,MAAM,QAAQ,UAAU,CACjF,QAAO,EAAE;CAEV,MAAM,MAAM;CAEZ,MAAM,YAAsB,EAAE;AAC9B,MAAK,MAAM,OAAO;EAAC;EAAY;EAAa;EAAO,EAAE;EACpD,MAAM,QAAQ,IAAI;AAClB,MAAI,OAAO,UAAU,UAAU;GAC9B,MAAM,UAAU,MAAM,MAAM;AAC5B,OAAI,QAAS,WAAU,KAAK,QAAQ;;;AAGtC,KAAI,aAAa,eAAe;EAM/B,MAAM,aADL,OAAO,IAAI,cAAc,YAAY,IAAI,UAAU,MAAM,GAAG,IAAI,YAAY,UAC/C,OAAO,IAAI,UAAU,WAAW,IAAI,QAAQ;AAC1E,MAAI,WAAW,MAAM,CACpB,WAAU,KAAK,GAAG,uBAAuB,UAAU,CAAC;;CAItD,MAAM,uBAAO,IAAI,KAAa;CAC9B,MAAM,UAAoB,EAAE;AAC5B,MAAK,MAAM,QAAQ,WAAW;AAC7B,MAAI,KAAK,IAAI,KAAK,CAAE;AACpB,OAAK,IAAI,KAAK;AACd,UAAQ,KAAK,KAAK;;AAEnB,QAAO;;;;;;;;AASR,SAAgB,sBAAsB,SAAuD;CAC5F,MAAM,aAAa,QAAQ;AAC3B,KAAI,OAAO,eAAe,SAAU,QAAO;CAC3C,MAAM,YAAY,WAAW,MAAM;AACnC,KAAI,CAAC,UAAW,QAAO;CAEvB,MAAM,gBACL,OAAO,QAAQ,oBAAoB,WAAW,QAAQ,gBAAgB,MAAM,GAAG;AAEhF,KAAI,kBAAkB,cAAc;AACnC,oBAAkB,UAAU;AAC5B,SAAO;;CAGR,MAAM,QAAQ,iBAAiB,UAAU;CACzC,IAAI,UAAU;AAEd,KAAI,kBAAkB,oBAAoB;EACzC,MAAM,SAAS,oBAAoB,QAAQ,OAAO;AAClD,MAAI,QAAQ;AACX,OAAI,CAAC,MAAM,cAAc;AACxB,UAAM,eAAe;AACrB,cAAU;;AAEX,OAAI,MAAM,gBAAgB,QAAQ;AACjC,UAAM,cAAc;AACpB,cAAU;;;YAGF,kBAAkB,iBAAiB,kBAAkB,sBAAsB;EACrF,MAAM,WAAW,MAAM,eAAe,QAAQ,SAAS,KAAK,MAAM,CAAC,SAAS,EAAE;EAC9E,MAAM,OAAO,IAAI,IAAI,SAAS;AAC9B,OAAK,MAAM,QAAQ,6BAA6B,QAAQ,EAAE;AACzD,OAAI,KAAK,IAAI,KAAK,CAAE;AACpB,YAAS,KAAK,KAAK;AACnB,QAAK,IAAI,KAAK;AACd,aAAU;;AAEX,QAAM,iBAAiB,SAAS,MAAM,CAAC,mBAAmB;;AAG3D,KAAI,SAAS;AACZ,QAAM,aAAa,QAAQ;AAC3B,MAAI;AACH,oBAAiB,WAAW,MAAM;UAC3B;;AAIT,QAAO;;AAGR,SAAS,aAAa,OAAuB;CAC5C,MAAM,aAAa,MAAM,QAAQ,OAAO,IAAI,CAAC,QAAQ,QAAQ,GAAG;AAChE,KAAI,CAAC,WAAY,QAAO;CACxB,MAAM,QAAQ,WAAW,MAAM,IAAI;AACnC,QAAO,MAAM,MAAM,SAAS,MAAM;;;;;;;AAQnC,SAAgB,iBAAiB,MAItB;CACV,MAAM,QAAkB,EAAE;CAC1B,MAAM,cAAc,KAAK,QAAQ,oBAAoB,KAAK,MAAM,aAAa,GAAG;CAChF,MAAM,gBAAgB,KAAK,QACxB,KAAK,MAAM,eAAe,QAAQ,SAAS,KAAK,MAAM,CAAC,SAAS,EAAE,GAClE,EAAE;AAEL,KAAI,YAAa,OAAM,KAAK,YAAY;AACxC,KAAI,KAAK,UAAU,KAAK,WAAW,eAAe,KAAK,OAAO,SAAS,EACtE,OAAM,KAAK,KAAK,OAAO;AAExB,KAAI,KAAK,QAAS,OAAM,KAAK,KAAK,QAAQ;AAC1C,KAAI,cAAc,SAAS,GAAG;EAC7B,MAAM,QAAQ,cACZ,MAAM,CAAC,yBAAyB,CAChC,IAAI,aAAa,CACjB,QAAQ,SAAS,KAAK,SAAS,EAAE;AACnC,MAAI,MAAM,SAAS,EAAG,OAAM,KAAK,MAAM,KAAK,IAAI,CAAC;;AAGlD,KAAI,MAAM,WAAW,EAAG,QAAO;CAC/B,MAAM,QAAQ,MAAM,KAAK,IAAI;AAC7B,QAAO,MAAM,SAAS,kBAAkB,MAAM,MAAM,GAAG,gBAAgB,GAAG;;;AAI3E,SAAgB,yBAAyB,OAAsC;AAC9E,KAAI,CAAC,MAAO,QAAO,EAAE;AAErB,QADc,MAAM,eAAe,QAAQ,SAAS,KAAK,MAAM,CAAC,SAAS,EAAE,CAC9D,MAAM,CAAC,sBAAsB;;;;;;;;;;;;;;;;ACpO3C,SAAS,sBAAoB,WAAmB,SAAuB;AACtE,SAAQ,IAAI,KAAK,UAAU;EAAE,OAAO;EAAW;EAAS,CAAC,CAAC;AAC1D,SAAQ,WAAW;;;;;;;;;;AAWpB,eAAe,cACd,SACA,MACA,MAC8D;CAC9D,MAAM,MAAM,UAAU,KAAK,GAAG,KAAK;CACnC,MAAM,aAAa,IAAI,iBAAiB;CACxC,MAAM,UAAU,iBAAiB,WAAW,OAAO,EAAE,IAAK;AAC1D,KAAI;EACH,MAAM,MAAM,MAAM,MAAM,KAAK;GAC5B,QAAQ;GACR,SAAS,EAAE,gBAAgB,oBAAoB;GAC/C,MAAM,KAAK,UAAU,QAAQ;GAC7B,QAAQ,WAAW;GACnB,CAAC;AACF,MAAI,CAAC,IAAI,GAAI,QAAO;GAAE,IAAI;GAAO,UAAU;GAAG,SAAS;GAAG;EAE1D,IAAI;AACJ,MAAI;AACH,UAAO,MAAM,IAAI,MAAM;UAChB;AACP,kBAAe,sEAAsE;AACrF,UAAO;IAAE,IAAI;IAAO,UAAU;IAAG,SAAS;IAAG;;AAE9C,MAAI,QAAQ,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,KAAK,EAAE;AACpE,kBAAe,sEAAsE;AACrF,UAAO;IAAE,IAAI;IAAO,UAAU;IAAG,SAAS;IAAG;;EAE9C,MAAM,MAAM;AACZ,MAAI,OAAO,IAAI,aAAa,YAAY,OAAO,IAAI,YAAY,UAAU;AACxE,kBAAe,yEAAyE;AACxF,UAAO;IAAE,IAAI;IAAO,UAAU;IAAG,SAAS;IAAG;;AAE9C,MAAI,IAAI,UAAU,GAAG;AACpB,kBAAe,+DAA+D;AAC9E,UAAO;IAAE,IAAI;IAAO,UAAU,IAAI;IAAU,SAAS,IAAI;IAAS;;AAEnE,SAAO;GAAE,IAAI;GAAM,UAAU,IAAI;GAAU,SAAS,IAAI;GAAS;SAC1D;AACP,SAAO;GAAE,IAAI;GAAO,UAAU;GAAG,SAAS;GAAG;WACpC;AACT,eAAa,QAAQ;;;;AAKvB,SAAgB,cACf,SACA,QACwC;CACxC,MAAM,WAAW,8BAA8B,QAAQ;AACvD,KAAI,CAAC,SAAU,QAAO;EAAE,UAAU;EAAG,SAAS;EAAG;CAEjD,MAAM,KAAK,QAAQ,OAAO;AAC1B,KAAI;AACH,MAAI;AACH,iBAAc,GAAG;UACV;EAGR,MAAM,kBAAkB,gBAAgB,SAAS,QAAQ;AAMzD,MALiB,GACf,QACA,uFACA,CACA,IAAI,SAAS,QAAQ,SAAS,mBAAmB,SAAS,SAAS,CACvD,QAAO;GAAE,UAAU;GAAG,SAAS;GAAG;AAEhD,KAAG,QACF;;;;;;iCAOA,CAAC,IACD,SAAS,QACT,SAAS,mBACT,SAAS,qBACT,SAAS,UACT,SAAS,QACT,SAAS,mBACT,eACA,SAAS,YACT,KAAK,UAAU,gBAAgB,CAC/B;EAQD,MAAM,gBALY,GAChB,QACA,mGACA,CACA,IAAI,SAAS,QAAQ,SAAS,kBAAkB,CAClB;AAGhC,KAAG,QACF;;;;;;;;;;kCAWA,CAAC,IACD,SAAS,QACT,SAAS,mBACT,SAAS,qBACT,SAAS,KACT,SAAS,SACT,SAAS,YACT,SAAS,YACT,cACA;AAED,SAAO;GAAE,UAAU;GAAG,SAAS;GAAG;WACzB;AACT,KAAG,OAAO;;;;;;;;;;;;;;;AAgBZ,eAAe,uBACd,SACA,QACgB;CAChB,MAAM,WAAW,8BAA8B,QAAQ;AACvD,KAAI,CAAC,SAAU;CAEf,IAAI;AACJ,KAAI;AACH,aAAW,IAAI,gBAAgB;UACvB,KAAK;AACb,iBACC,mEAAmE,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GACnH;AACD;;CAGD,IAAI;AACJ,KAAI;AACH,UAAQ,IAAI,YAAY,OAAO;UACvB,KAAK;AACb,iBACC,gEAAgE,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GAChH;AACD;;AAGD,KAAI;AACH,QAAM,eACL,OACA,EAAE,UAAU,EACZ;GACC,mBAAmB,SAAS;GAC5B,QAAQ,SAAS;GACjB,KAAK,SAAS,OAAO;GACrB,SAAS,SAAS,WAAW;GAC7B,WAAW,SAAS,cAAc;GAClC,WAAW;GACX,CACD;UACO,KAAK;AACb,iBACC,gEAAgE,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GAChH;WACQ;AACT,QAAM,OAAO;;;;;;;;AASf,eAAsB,wBACrB,SACA,MACA,OAAmB,EAAE,EACG;CACxB,MAAM,aAAa,KAAK,cAAc;CACtC,MAAM,eAAe,KAAK,gBAAgB;CAC1C,MAAM,YAAY,KAAK,aAAa;CACpC,MAAM,gBAAgB,KAAK,iBAAiB;AAK5C,KAAI;AACH,wBAAsB,QAAQ;SACvB;CAIR,MAAM,OAAO,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO,OAAO,SAAS,KAAK,MAAM,GAAG;CAIvF,IAAI,eAA8B;CAClC,MAAM,kBAA0B;AAC/B,MAAI,iBAAiB,KAAM,gBAAe,UAAU,aAAa,KAAK,CAAC;AACvE,SAAO;;CAGR,MAAM,qBACL,WACiF;AACjF,MAAI;AACH,UAAO;IAAE,IAAI;IAAM,QAAQ,aAAa,QAAQ,WAAW,CAAC;IAAE;WACtD,KAAK;AACb,kBACC,sDAAsD,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GACtG;AACD,UAAO,EAAE,IAAI,OAAO;;;CAItB,MAAM,6BAA6B,YAA2B;AAC7D,MAAI,CAAC,yBAAyB,QAAQ,CAAE;AAMxC,MAAI;AACH,gBAAa,SAAS,WAAW,CAAC;WAC1B,KAAK;AACb,kBACC,kEAAkE,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GAClH;;AAEF,MAAI;AACH,SAAM,cAAc,SAAS,WAAW,CAAC;WACjC,KAAK;AACb,kBACC,qDAAqD,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GACrG;;;CAWH,MAAM,wBAAwB,YAA2B;AACxD,MAAI,CAAC,mBAAmB,CAAE;AAC1B,MAAI;AACH,SAAM,yBAAyB,YAAY;AAC1C,yBAAqB,gBAAgB,CAAC;AACtC,UAAM,WAAW,OAAO,kBAAkB;AAEzC,UADmB,MAAM,WAAW,eAAe,KAAK,MAAM,KAAK,EACpD,GAAI,QAAO;AAC1B,YAAO,kBAAkB,cAAc,CAAC;MACvC;KACD;WACM,KAAK;AACb,OAAI,eAAe,cAElB;AAED,kBACC,oDAAoD,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GACpG;;;CAKH,MAAM,aAAa,MAAM,WAAW,SAAS,KAAK,MAAM,KAAK;AAC7D,KAAI,WAAW,IAAI;AAClB,QAAM,4BAA4B;AAClC,QAAM,uBAAuB;AAC7B,SAAO;GAAE,UAAU,WAAW;GAAU,SAAS,WAAW;GAAS,KAAK;GAAQ;;AAKnF,KAAI;AACH,SAAO,MAAM,yBAAyB,YAAY;AACjD,wBAAqB,gBAAgB,CAAC;AAEtC,SAAM,WAAW,OAAO,kBAAkB;AAEzC,SADmB,MAAM,WAAW,eAAe,KAAK,MAAM,KAAK,EACpD,GAAI,QAAO;AAE1B,WADe,kBAAkB,cAAc,CACjC;KACb;GAEF,MAAM,aAAa,MAAM,WAAW,SAAS,KAAK,MAAM,KAAK;AAC7D,OAAI,WAAW,IAAI;AAClB,UAAM,4BAA4B;AAClC,WAAO;KACN,UAAU,WAAW;KACrB,SAAS,WAAW;KACpB,KAAK;KACL;;GAGF,MAAM,SAAS,kBAAkB,QAAQ;AACzC,OAAI,OAAO,IAAI;AACd,UAAM,4BAA4B;AAClC,WAAO;KAAE,GAAG,OAAO;KAAQ,KAAK;KAAmB;;AAGpD,OAAI,aAAa,QAAQ,CACxB,QAAO;IAAE,UAAU;IAAG,SAAS;IAAG,KAAK;IAAkB;AAG1D,kBAAe,+DAA+D;AAC9E,SAAM,IAAI,MAAM,qDAAqD;IACpE;UACM,KAAK;AACb,MAAI,EAAE,eAAe,eAAgB,OAAM;AAE3C,iBAAe,iEAAiE;EAChF,MAAM,SAAS,kBAAkB,QAAQ;AACzC,MAAI,OAAO,GACV,QAAO;GAAE,GAAG,OAAO;GAAQ,KAAK;GAAU;AAE3C,MAAI,aAAa,QAAQ,CACxB,QAAO;GAAE,UAAU;GAAG,SAAS;GAAG,KAAK;GAAmB;AAE3D,iBAAe,wEAAwE;AACvF,QAAM;;;AAIR,IAAM,gBAAgB,IAAI,QAAQ,qBAAqB,CACrD,cAAc,UAAU,CACxB,YAAY,6DAA6D;AAE3E,YAAY,cAAc;AAC1B,qBAAqB,cAAc;AAEnC,SAAS,eAAe,OAAoC;CAC3D,MAAM,aAAa,OAAO,SAAS,GAAG,CACpC,MAAM,CACN,aAAa;AACf,QAAO,eAAe,OAAO,eAAe,UAAU,eAAe,SAAS,eAAe;;AAG9F,IAAa,0BAA0B,cAAc,OACpD,OAAO,SAAkD;AAKxD,KAAI,eAAe,QAAQ,IAAI,sBAAsB,CACpD;CAID,IAAI;AACJ,KAAI;AACH,QAAM,aAAa,GAAG,OAAO,CAAC,MAAM;SAC7B;AACP,wBAAoB,cAAc,uBAAuB;AACzD;;AAED,KAAI,CAAC,KAAK;AACT,wBAAoB,cAAc,cAAc;AAChD;;CAGD,IAAI;AACJ,KAAI;EACH,MAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,MAAI,UAAU,QAAQ,OAAO,WAAW,YAAY,MAAM,QAAQ,OAAO,EAAE;AAC1E,yBAAoB,eAAe,gCAAgC;AACnE;;AAED,YAAU;SACH;AACP,wBAAoB,eAAe,eAAe;AAClD;;AAGD,KAAI;EACH,MAAM,SAAS,MAAM,wBAAwB,SAAS,KAAK;AAC3D,UAAQ,IAAI,KAAK,UAAU,OAAO,CAAC;UAC3B,KAAK;AACb,wBAAoB,gBAAgB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;;EAGvF;;;AC/bD,IAAM,kBAAkB;AAcxB,IAAM,sBAAsB;AAC5B,IAAM,sBAAsB;AAC5B,IAAM,oBAAoB;AAC1B,IAAM,0BAA0B;AAEhC,SAAS,SAAS,OAAgE;AACjF,SAAQ,IAAI,KAAK,UAAU,MAAM,CAAC;;AAGnC,SAAS,eAAe,OAAoC;CAC3D,MAAM,aAAa,OAAO,SAAS,GAAG,CACpC,MAAM,CACN,aAAa;AACf,QAAO,eAAe,OAAO,eAAe,WAAW,eAAe;;AAGvE,SAAS,UAAU,OAAoC;CACtD,MAAM,aAAa,OAAO,SAAS,GAAG,CACpC,MAAM,CACN,aAAa;AACf,QAAO,eAAe,OAAO,eAAe,UAAU,eAAe,SAAS,eAAe;;AAG9F,SAAS,mBAAiB,OAA2B,UAA0B;CAC9E,MAAM,SAAS,OAAO,SAAS,OAAO,SAAS,GAAG,EAAE,GAAG;AACvD,KAAI,CAAC,OAAO,SAAS,OAAO,IAAI,UAAU,EACzC,QAAO;AAER,QAAO;;AAGR,SAAS,eAAe,mBAA0C;AACjE,KAAI,CAAC,kBACJ,QAAO,EAAE,UAAU,MAAM;AAE1B,QAAO;EACN,UAAU;EACV,oBAAoB;GACnB,eAAe;GACf;GACA;EACD;;AAGF,SAAS,0BAA0B,MAAc,UAA0B;CAC1E,MAAM,aAAa,KAAK,MAAM;AAC9B,KAAI,CAAC,WACJ,QAAO;AAER,KAAI,CAAC,OAAO,SAAS,SAAS,IAAI,YAAY,KAAK,WAAW,UAAU,SACvE,QAAO;AAIR,QAAO,GAAG,WAAW,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC;;AAGnD,SAAS,qBAAqB,SAAiD;AAO9E,QADe,oBAAoB,QAAQ,OAAO,IACjC;;AAGlB,SAAS,qBAAqB,SAAiD;AAE9E,QAAO,mBADK,OAAO,QAAQ,QAAQ,WAAW,QAAQ,MAAM,MAC7B,QAAQ,QAAQ;;AAGhD,eAAe,eACd,SACA,SACA,QACA,kBAA4B,EAAE,EACZ;CAClB,MAAM,QAAQ,IAAI,YAAY,OAAO;AACrC,KAAI;EACH,MAAM,QAAQ,mBAAiB,QAAQ,IAAI,sBAAsB,EAAE;EACnE,MAAM,SAAS,mBAAiB,QAAQ,IAAI,6BAA6B,IAAI;EAC7E,MAAM,UAA8D,EAAE;AACtE,MAAI,QACH,SAAQ,UAAU;AAEnB,MAAI,gBAAgB,SAAS,EAC5B,SAAQ,oBAAoB;EAE7B,MAAM,OAAO,MAAM,MAAM,qBAAqB,SAAS,OAAO,QAAQ,QAAQ;AAC9E,SAAO,OAAO,KAAK,aAAa,GAAG,CAAC,MAAM;WACjC;AACT,QAAM,OAAO;;;AAIf,eAAe,YACd,SACA,SACA,YAAY,0BAA0B,KACpB;CAClB,MAAM,OAAO,QAAQ,IAAI,uBAAuB;CAChD,MAAM,OAAO,mBAAiB,QAAQ,IAAI,qBAAqB,oBAAoB;CACnF,MAAM,MAAM,IAAI,IAAI,UAAU,KAAK,GAAG,KAAK,WAAW;AACtD,KAAI,aAAa,IAAI,WAAW,QAAQ;AACxC,KAAI,aAAa,IAAI,SAAS,OAAO,mBAAiB,QAAQ,IAAI,sBAAsB,EAAE,CAAC,CAAC;AAC5F,KAAI,aAAa,IAChB,gBACA,OAAO,mBAAiB,QAAQ,IAAI,6BAA6B,IAAI,CAAC,CACtE;AACD,KAAI,QACH,KAAI,aAAa,IAAI,WAAW,QAAQ;CAGzC,MAAM,aAAa,IAAI,iBAAiB;CACxC,MAAM,UAAU,iBAAiB,WAAW,OAAO,EAAE,UAAU;AAC/D,KAAI;EACH,MAAM,MAAM,MAAM,MAAM,KAAK,EAAE,QAAQ,WAAW,QAAQ,CAAC;AAC3D,MAAI,CAAC,IAAI,GACR,QAAO;EAER,MAAM,OAAQ,MAAM,IAAI,MAAM;AAC9B,SAAO,OAAO,KAAK,aAAa,GAAG,CAAC,MAAM;SACnC;AACP,SAAO;WACE;AACT,eAAa,QAAQ;;;AAIvB,eAAsB,yBACrB,SACA,MACA,OAAmB,EAAE,EACG;AAIxB,KAAI,UAAU,QAAQ,IAAI,sBAAsB,CAC/C,QAAO,gBAAgB;AAExB,KAAI,CAAC,eAAe,QAAQ,IAAI,0BAA0B,IAAI,CAC7D,QAAO,gBAAgB;CAKxB,IAAI,QAA6B;AACjC,KAAI;AACH,UAAQ,sBAAsB,QAAQ;SAC/B;AACP,UAAQ;;CAGT,MAAM,aAAa,qBAAqB,QAAQ;AAChD,KAAI,CAAC,WACJ,QAAO,gBAAgB;CAGxB,MAAM,YAAY,KAAK,kBAAkB;CACzC,MAAM,WAAW,KAAK,YAAY;CAClC,MAAM,YAAY,KAAK,aAAa;CACpC,MAAM,UAAU,qBAAqB,QAAQ;CAC7C,MAAM,QAAQ,iBAAiB;EAAE,QAAQ;EAAY;EAAS;EAAO,CAAC;CACtE,MAAM,kBAAkB,yBAAyB,MAAM;CACvD,MAAM,WAAW,mBAAiB,QAAQ,IAAI,0BAA0B,kBAAkB;CAC1F,MAAM,gBACL,mBAAiB,QAAQ,IAAI,gCAAgC,wBAAwB,GAAG;CAEzF,IAAI,oBAAoB;AACxB,KAAI;AAEH,sBAAoB,MAAM,UAAU,OAAO,SAD5B,UAAU,aAAa,KAAK,CAAC,EACgB,gBAAgB;UACpE,KAAK;AACb,sBAAoB;AACpB,iBACC,iDAAiD,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GACjG;;AAGF,KAAI,CAAC,qBAAqB,eAAe,QAAQ,IAAI,gCAAgC,IAAI,CAKxF,qBAAoB,MAAM,SAAS,OAAO,SAAS,cAAc;AAGlE,QAAO,eAAe,0BAA0B,mBAAmB,SAAS,CAAC;;AAG9E,IAAM,sBAAsB,IAAI,QAAQ,qBAAqB,CAC3D,cAAc,UAAU,CACxB,YAAY,kEAAkE;AAEhF,YAAY,oBAAoB;AAEhC,IAAa,0BAA0B,oBAAoB,OAAO,OAAO,SAAqB;CAC7F,IAAI,MAAM;AACV,YAAW,MAAM,SAAS,QAAQ,MACjC,QAAO,OAAO,MAAM;CAErB,MAAM,UAAU,IAAI,MAAM;AAC1B,KAAI,CAAC,SAAS;AACb,WAAS,gBAAgB,CAAC;AAC1B;;CAGD,IAAI;AACJ,KAAI;EACH,MAAM,SAAS,KAAK,MAAM,QAAQ;AAClC,MAAI,UAAU,QAAQ,OAAO,WAAW,YAAY,MAAM,QAAQ,OAAO,EAAE;AAC1E,YAAS;IAAE,OAAO;IAAe,SAAS;IAAiC,CAAC;AAC5E,WAAQ,WAAW;AACnB;;AAED,YAAU;SACH;AACP,WAAS;GAAE,OAAO;GAAe,SAAS;GAAgB,CAAC;AAC3D,UAAQ,WAAW;AACnB;;AAID,UADe,MAAM,yBAAyB,SAAS,KAAK,CAC5C;EACf;;;ACrOF,SAAS,mBAAmB,OAA2B,UAAsC;AAC5F,KAAI,SAAS,KAAM,QAAO,KAAA;CAC1B,MAAM,UAAU,MAAM,MAAM;AAC5B,KAAI,CAAC,QAAQ,KAAK,QAAQ,CACzB,OAAM,IAAI,MAAM,WAAW,SAAS,IAAI,QAAQ;AAEjD,QAAO,OAAO,SAAS,SAAS,GAAG;;AAGpC,SAAS,0BAA0B,MAAuD;CACzF,MAAM,QAAiC,EAAE;AACzC,KAAI,KAAK,gBAAgB,KAAM,OAAM,eAAe;AACpD,KAAI,KAAK,gBAAgB,MAAO,OAAM,eAAe;AACrD,KAAI,KAAK,UAAU,MAAM,CAAE,OAAM,YAAY,KAAK,SAAS,MAAM;CACjE,MAAM,WAAW,mBAAmB,KAAK,UAAU,cAAc;AACjE,KAAI,YAAY,KAAM,OAAM,YAAY;CACxC,MAAM,eAAe,mBAAmB,KAAK,eAAe,oBAAoB;AAChF,KAAI,gBAAgB,KAAM,OAAM,kBAAkB;AAClD,KAAI,KAAK,gBAAgB,MAAM,CAAE,OAAM,uBAAuB,KAAK,eAAe,MAAM;AACxF,KAAI,KAAK,kBAAkB,MAAM,CAAE,OAAM,yBAAyB,KAAK,iBAAiB,MAAM;AAC9F,QAAO;;AAGR,SAAS,qBACR,gBACA,OAC0B;AAC1B,QAAO;EAAE,GAAG;EAAgB,GAAG;EAAO;;AAGvC,SAAS,0BACR,MACwB;AACxB,KAAI,KAAK,cAAc,KAAK,YAC3B,OAAM,IAAI,MAAM,kDAAkD;CAEnE,MAAM,cAAc,KAAK;AACzB,KAAI,CAAC,YACJ,OAAM,IAAI,MAAM,2BAA2B;CAE5C,MAAM,aAAa,8BAA8B,YAAY;CAG7D,MAAM,iBAAiB,WAAW,WAAW,GAC1C,4BAA4B,WAAW,GACvC,uBAAuB;CAC1B,MAAM,QAAQ,0BAA0B;EACvC;EACA,aAAa,KAAK,aAAa,OAAO,KAAK,cAAc,QAAQ,KAAA;EACjE,UAAU,KAAK;EACf,UAAU,KAAK;EACf,eAAe,KAAK;EACpB,gBAAgB,KAAK;EACrB,kBAAkB,KAAK;EACvB,MAAM,KAAK;EACX,CAAC;AACF,KAAI,OAAO,KAAK,MAAM,CAAC,WAAW,EACjC,OAAM,IAAI,MAAM,8CAA8C;CAE/D,MAAM,aAAa,qBAAqB,gBAAgB,MAAM;AAE9D,QAAO;EACN,cAAc;EACd,aAHiB,uBAAuB,YAAY,WAAW;EAI/D,cAAc,OAAO,KAAK,MAAM,CAAC,MAAM;EACvC,QAAQ;EACR;;AAGF,IAAa,gBAAgB,IAAI,QAAQ,SAAS,CAChD,cAAc,UAAU,CACxB,YAAY,+BAA+B;AAE7C,IAAM,eAAe,IAAI,QAAQ,YAAY,CAC3C,cAAc,UAAU,CACxB,YAAY,mDAAmD,CAC/D,SAAS,kBAAkB,uBAAuB,CAClD,OAAO,iBAAiB,wBAAwB,CAChD,OAAO,kBAAkB,yBAAyB,CAClD,OAAO,sBAAsB,gBAAgB,CAC7C,OAAO,sBAAsB,gBAAgB,CAC7C,OAAO,+BAA+B,sBAAsB,CAC5D,OAAO,2BAA2B,2BAA2B,CAC7D,OAAO,+BAA+B,6BAA6B;AAGrE,aAAa,UACZ,IAAI,OAAO,uBAAuB,gDAAgD,CAAC,UAAU,CAC7F;AAED,cAAc,aAAa;AAE3B,aAAa,QAEX,gBACA,SACI;AACJ,KAAI;EAEH,MAAM,cAAc,kBAAkB,KAAK;AAC3C,MAAI,CAAC,aAAa;AACjB,WAAQ,MAAM,kDAAkD;AAChE,WAAQ,WAAW;AACnB;;EAGD,MAAM,SAAS,0BAA0B;GAAE,GAAG;GAAM;GAAa,CAAC;AAElE,MAAI,KAAK,MAAM;AACd,WAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;AAGD,UAAQ,IAAI,6BAA6B,OAAO,cAAc;AAC9D,UAAQ,IAAI,iBAAiB,OAAO,aAAa,KAAK,KAAK,GAAG;UACtD,KAAK;AACb,MAAI,KAAK,KACR,SAAQ,IACP,KAAK,UAAU;GACd,OAAO;GACP,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;GACzD,CAAC,CACF;MAED,SAAQ,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAEhE,UAAQ,WAAW;;EAGrB;AAED,cAAc,WAAW,aAAa;AAQtC,SAAS,iBAAiB,QAAwC;CACjE,MAAM,QAAkB,EAAE;CAC1B,MAAM,aAAa,CAAC,OAAO,UAAU,GAAG,OAAO,cAAc;CAE7D,MAAM,cAAsC;EAC3C,YAAY;EACZ,sBAAsB;EACtB,oBAAoB;EACpB,oBAAoB;EACpB,iBAAiB;EACjB;AACD,YAAW,MAAM,GAAG,OAAO,YAAY,EAAE,WAAW,OAAO,YAAY,EAAE,WAAW,IAAI;AAExF,MAAK,MAAM,SAAS,YAAY;EAE/B,MAAM,SADa,UAAU,OAAO,WACR,QAAQ;EACpC,MAAM,cAAc,MAAM,SAAS,WAAW;AAC9C,QAAM,KAAK,GAAG,OAAO,IAAI,MAAM,OAAO,IAAI,MAAM,OAAO;AACvD,QAAM,KAAK,UAAU,MAAM,OAAO,IAAI,YAAY,GAAG;;AAEtD,QAAO,MAAM,KAAK,KAAK;;AAGxB,IAAM,WAAW,IAAI,QAAQ,QAAQ,CACnC,cAAc,UAAU,CACxB,YAAY,iCAAiC;AAE/C,gBAAgB,SAAS;AACzB,cAAc,SAAS;AAEvB,SAAS,QAAQ,SAAuB;AACvC,KAAI;EACH,MAAM,SAAS,yBAAyB,KAAK,QAAQ,OAAO;AAC5D,MAAI,KAAK,KACR,SAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;MAE5C,SAAQ,IAAI,iBAAiB,OAAO,CAAC;UAE9B,KAAK;AACb,MAAI,KAAK,KACR,SAAQ,IACP,KAAK,UAAU;GACd,OAAO;GACP,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;GACzD,CAAC,CACF;MAED,SAAQ,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAEhE,UAAQ,WAAW;;EAEnB;AAEF,cAAc,WAAW,SAAS;;;;;;;;;;;;;;;ACtLlC,SAAS,yBAAyB,MAA8D;CAC/F,MAAM,SAAS,OAAO,KAAK,aAAa,GAAG,CAAC,MAAM;CAClD,MAAM,WAAW,OAAO,KAAK,iBAAiB,GAAG,CAAC,MAAM;AACxD,KAAI,UAAU,SAAU,OAAM,IAAI,MAAM,oDAAoD;AAC5F,KAAI,UAAU;EACb,MAAM,OAAO,aAAa,UAAU,OAAO,CAAC,MAAM;AAClD,MAAI,CAAC,KAAM,OAAM,IAAI,MAAM,6BAA6B,WAAW;AACnE,SAAO;;AAER,KAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,4DAA4D;AACzF,QAAO;;;;;;AAOR,SAAgB,0BAAmC;CAClD,MAAM,MAAM,IAAI,QAAQ,cAAc,CACpC,cAAc,UAAU,CACxB,YAAY,8DAA8D;CAI5E,MAAM,iBAAiB,IAAI,QAAQ,eAAe,CAChD,cAAc,UAAU,CACxB,YAAY,gDAAgD,CAC5D,SAAS,WAAW,WAAW,CAC/B,OAAO,iBAAiB,wBAAwB;AAClD,aAAY,eAAe;AAC3B,eAAc,eAAe;AAC7B,gBAAe,OACd,OACC,SACA,SACI;AACJ,MAAI;GACH,MAAM,QAAQ,MAAM,6BAA6B;IAChD;IACA,aAAa,KAAK,MAAM,MAAM,IAAI;IAClC,QAAQ,aAAa,KAAK,IAAI;IAC9B,CAAC;AACF,OAAI,KAAK,MAAM;AACd,YAAQ,IAAI,KAAK,UAAU,OAAO,MAAM,EAAE,CAAC;AAC3C;;AAED,KAAE,MAAM,mCAAmC;AAC3C,KAAE,IAAI,QAAQ,gBAAgB,QAAQ,MAAM,GAAG;AAC/C,KAAE,MAAM,OAAO,MAAM,gBAAgB,MAAM,YAAY,QAAQ,MAAM,CAAC,CAAC;WAC/D,KAAK;AACb,OAAI,KAAK,MAAM;AACd,kBAAc,uBAAuB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AACtF;;AAED,KAAE,IAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAC7D,WAAQ,WAAW;;GAGrB;AACD,KAAI,WAAW,eAAe;CAI9B,MAAM,gBAAgB,IAAI,QAAQ,cAAc,CAC9C,cAAc,UAAU,CACxB,YAAY,+CAA+C;AAC7D,aAAY,cAAc;AAC1B,eAAc,cAAc;AAC5B,eAAc,OAAO,OAAO,SAA2D;AACtF,MAAI;GACH,MAAM,SAAS,MAAM,4BAA4B,EAAE,QAAQ,aAAa,KAAK,IAAI,MAAM,CAAC;AACxF,OAAI,KAAK,MAAM;AACd,YAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;AAED,KAAE,MAAM,kCAAkC;AAC1C,OAAI,OAAO,WAAW,GAAG;AACxB,MAAE,MAAM,8BAA8B;AACtC;;AAED,QAAK,MAAM,SAAS,OACnB,GAAE,IAAI,QACL,KAAK,OAAO,MAAM,YAAY,GAAG,GAAG,MAAM,eAAe,KAAK,OAAO,MAAM,aAAa,CAAC,KAAK,KAC9F;AAEF,KAAE,MAAM,GAAG,OAAO,OAAO,WAAW;WAC5B,KAAK;AACb,OAAI,KAAK,MAAM;AACd,kBAAc,sBAAsB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AACrF;;AAED,KAAE,IAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAC7D,WAAQ,WAAW;;GAEnB;AACF,KAAI,WAAW,cAAc;CAI7B,MAAM,kBAAkB,IAAI,QAAQ,gBAAgB,CAClD,cAAc,UAAU,CACxB,YAAY,+CAA+C,CAC3D,SAAS,WAAW,WAAW,CAC/B,SAAS,eAAe,YAAY,CACpC,OAAO,+BAA+B,qBAAqB,CAC3D,OAAO,sBAAsB,oBAAoB,CACjD,OAAO,4BAA4B,4BAA4B,CAC/D,OAAO,iBAAiB,eAAe;AACzC,aAAY,gBAAgB;AAC5B,eAAc,gBAAgB;AAC9B,iBAAgB,OACf,OACC,SACA,UACA,SASI;AACJ,MAAI;GACH,MAAM,YAAY,yBAAyB,KAAK;GAChD,MAAM,cAAc,OAAO,KAAK,eAAe,GAAG,CAAC,MAAM;AACzD,OAAI,CAAC,aAAa;AACjB,QAAI,KAAK,MAAM;AACd,mBAAc,eAAe,0CAA0C,EAAE;AACzE;;AAED,MAAE,IAAI,MAAM,yCAAyC;AACrD,YAAQ,WAAW;AACnB;;AAGD,OAD0B,qBAAqB,UAAU,KAC/B,aAAa;AACtC,QAAI,KAAK,MAAM;AACd,mBACC,wBACA,qDACA;AACD;;AAED,MAAE,IAAI,MAAM,qDAAqD;AACjE,YAAQ,WAAW;AACnB;;GAED,MAAM,aAAa,MAAM,8BAA8B;IACtD;IACA;IACA;IACA;IACA,aAAa,KAAK,MAAM,MAAM,IAAI;IAClC,QAAQ,aAAa,KAAK,IAAI;IAC9B,CAAC;AACF,OAAI,KAAK,MAAM;AACd,YAAQ,IAAI,KAAK,UAAU,YAAY,MAAM,EAAE,CAAC;AAChD;;AAED,KAAE,MAAM,oCAAoC;AAC5C,KAAE,IAAI,QAAQ,YAAY,SAAS,MAAM,CAAC,MAAM,QAAQ,MAAM,GAAG;AACjE,KAAE,MAAM,OAAO,WAAW,gBAAgB,WAAW,aAAa,SAAS,MAAM,CAAC,CAAC;WAC3E,KAAK;AACb,OAAI,KAAK,MAAM;AACd,kBAAc,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAChF;;AAED,KAAE,IAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAC7D,WAAQ,WAAW;;GAGrB;AACD,KAAI,WAAW,gBAAgB;CAI/B,MAAM,iBAAiB,IAAI,QAAQ,eAAe,CAChD,cAAc,UAAU,CACxB,YAAY,qDAAqD,CACjE,SAAS,WAAW,WAAW,CAC/B,OAAO,sBAAsB,2BAA2B;AAC1D,aAAY,eAAe;AAC3B,eAAc,eAAe;AAC7B,gBAAe,OACd,OACC,SACA,SACI;AACJ,MAAI;GACH,MAAM,OAAO,MAAM,6BAA6B;IAC/C;IACA,iBAAiB,KAAK,oBAAoB;IAC1C,QAAQ,aAAa,KAAK,IAAI;IAC9B,CAAC;AACF,OAAI,KAAK,MAAM;AACd,YAAQ,IAAI,KAAK,UAAU,MAAM,MAAM,EAAE,CAAC;AAC1C;;AAED,KAAE,MAAM,mCAAmC;AAC3C,OAAI,KAAK,WAAW,GAAG;AACtB,MAAE,MAAM,2BAA2B,QAAQ,MAAM,GAAG;AACpD;;AAED,QAAK,MAAM,OAAO,MAAM;IACvB,MAAM,QACL,OAAO,IAAI,gBAAgB,IAAI,aAAa,GAAG,CAAC,MAAM,IAAI,OAAO,IAAI,aAAa,GAAG;IACtF,MAAM,UAAU,OAAO,IAAI,WAAW,EAAE,KAAK,IAAI,YAAY;AAC7D,MAAE,IAAI,QAAQ,KAAK,MAAM,IAAI,OAAO,IAAI,aAAa,GAAG,CAAC,IAAI,UAAU;;AAExE,KAAE,MAAM,GAAG,KAAK,OAAO,YAAY;WAC3B,KAAK;AACb,OAAI,KAAK,MAAM;AACd,kBAAc,uBAAuB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AACtF;;AAED,KAAE,IAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAC7D,WAAQ,WAAW;;GAGrB;AACD,KAAI,WAAW,eAAe;CAI9B,MAAM,kBAAkB,IAAI,QAAQ,gBAAgB,CAClD,cAAc,UAAU,CACxB,YAAY,2DAA2D,CACvE,SAAS,WAAW,WAAW,CAC/B,SAAS,eAAe,YAAY,CACpC,eAAe,iBAAiB,eAAe;AACjD,aAAY,gBAAgB;AAC5B,eAAc,gBAAgB;AAC9B,iBAAgB,OACf,OACC,SACA,UACA,SACI;AACJ,MAAI;GACH,MAAM,SAAS,MAAM,8BAA8B;IAClD;IACA;IACA,aAAa,KAAK,KAAK,MAAM;IAC7B,QAAQ,aAAa,KAAK,IAAI;IAC9B,CAAC;AACF,OAAI,CAAC,QAAQ;AACZ,QAAI,KAAK,MAAM;AACd,mBAAc,oBAAoB,qBAAqB,SAAS,MAAM,GAAG;AACzE;;AAED,MAAE,IAAI,MAAM,qBAAqB,SAAS,MAAM,GAAG;AACnD,YAAQ,WAAW;AACnB;;AAED,OAAI,KAAK,MAAM;AACd,YAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;AAED,KAAE,MAAM,oCAAoC;AAC5C,KAAE,IAAI,QAAQ,WAAW,SAAS,MAAM,CAAC,MAAM,QAAQ,MAAM,GAAG;AAChE,KAAE,MAAM,OAAO,OAAO,gBAAgB,OAAO,aAAa,SAAS,MAAM,CAAC,CAAC;WACnE,KAAK;AACb,OAAI,KAAK,MAAM;AACd,kBAAc,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAChF;;AAED,KAAE,IAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAC7D,WAAQ,WAAW;;GAGrB;AACD,KAAI,WAAW,gBAAgB;CAI/B,MAAM,mBAAmB,IAAI,QAAQ,iBAAiB,CACpD,cAAc,UAAU,CACxB,YAAY,4DAA4D,CACxE,SAAS,WAAW,WAAW,CAC/B,SAAS,eAAe,YAAY;AACtC,aAAY,iBAAiB;AAC7B,eAAc,iBAAiB;AAC/B,kBAAiB,OAChB,OACC,SACA,UACA,SACI;AACJ,MAAI;AAMH,OAAI,CALO,MAAM,+BAA+B;IAC/C;IACA;IACA,QAAQ,aAAa,KAAK,IAAI;IAC9B,CAAC,EACO;AACR,QAAI,KAAK,MAAM;AACd,mBAAc,oBAAoB,qBAAqB,SAAS,MAAM,GAAG;AACzE;;AAED,MAAE,IAAI,MAAM,qBAAqB,SAAS,MAAM,GAAG;AACnD,YAAQ,WAAW;AACnB;;AAED,OAAI,KAAK,MAAM;AACd,YAAQ,IACP,KAAK,UACJ;KAAE,IAAI;KAAM,UAAU,QAAQ,MAAM;KAAE,WAAW,SAAS,MAAM;KAAE,EAClE,MACA,EACA,CACD;AACD;;AAED,KAAE,MAAM,qCAAqC;AAC7C,KAAE,IAAI,QAAQ,YAAY,SAAS,MAAM,CAAC,MAAM,QAAQ,MAAM,GAAG;AACjE,KAAE,MAAM,WAAW;WACX,KAAK;AACb,OAAI,KAAK,MAAM;AACd,kBAAc,kBAAkB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AACjF;;AAED,KAAE,IAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAC7D,WAAQ,WAAW;;GAGrB;AACD,KAAI,WAAW,iBAAiB;CAIhC,MAAM,kBAAkB,IAAI,QAAQ,gBAAgB,CAClD,cAAc,UAAU,CACxB,YAAY,6DAA6D,CACzE,SAAS,WAAW,WAAW,CAC/B,SAAS,eAAe,YAAY;AACtC,aAAY,gBAAgB;AAC5B,eAAc,gBAAgB;AAC9B,iBAAgB,OACf,OACC,SACA,UACA,SACI;AACJ,MAAI;AAMH,OAAI,CALO,MAAM,8BAA8B;IAC9C;IACA;IACA,QAAQ,aAAa,KAAK,IAAI;IAC9B,CAAC,EACO;AACR,QAAI,KAAK,MAAM;AACd,mBAAc,oBAAoB,qBAAqB,SAAS,MAAM,GAAG;AACzE;;AAED,MAAE,IAAI,MAAM,qBAAqB,SAAS,MAAM,GAAG;AACnD,YAAQ,WAAW;AACnB;;AAED,OAAI,KAAK,MAAM;AACd,YAAQ,IACP,KAAK,UACJ;KAAE,IAAI;KAAM,UAAU,QAAQ,MAAM;KAAE,WAAW,SAAS,MAAM;KAAE,EAClE,MACA,EACA,CACD;AACD;;AAED,KAAE,MAAM,oCAAoC;AAC5C,KAAE,IAAI,QAAQ,WAAW,SAAS,MAAM,CAAC,QAAQ,QAAQ,MAAM,GAAG;AAClE,KAAE,MAAM,UAAU;WACV,KAAK;AACb,OAAI,KAAK,MAAM;AACd,kBAAc,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAChF;;AAED,KAAE,IAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAC7D,WAAQ,WAAW;;GAGrB;AACD,KAAI,WAAW,gBAAgB;CAI/B,MAAM,gBAAgB,IAAI,QAAQ,QAAQ,CACxC,cAAc,UAAU,CACxB,YAAY,wCAAwC,CACpD,OAAO,6BAA6B,YAAY,CAChD,OAAO,6BAA6B,YAAY;AAElD,eAAc,UAAU,IAAI,OAAO,wBAAwB,4BAA4B,CAAC;AACxF,eAAc,UAAU,IAAI,OAAO,eAAe,4BAA4B,CAAC,UAAU,CAAC;AAE1F,eAAc,UAAU,IAAI,OAAO,iBAAiB,YAAY,CAAC,UAAU,CAAC;AAC5E,eAAc,UAAU,IAAI,OAAO,iBAAiB,YAAY,CAAC,UAAU,CAAC;AAC5E,eAAc,OACb,OAAO,SAOD;EAIL,MAAM,OAAO,OAAO,KAAK,mBAAmB,KAAK,QAAQ,YAAY,CAAC,MAAM,IAAI;EAChF,MAAM,OAAO,OAAO,SAAS,OAAO,KAAK,mBAAmB,KAAK,QAAQ,OAAO,EAAE,GAAG;EACrF,MAAM,SAAS,aAAa,KAAK,IAAI;EACrC,MAAM,MAAM,iCAAiC,EAAE,QAAQ,CAAC;AACxD,IAAE,MAAM,4BAA4B;AACpC,IAAE,IAAI,QAAQ,mCAAmC,KAAK,GAAG,OAAO;AAChE,IAAE,IAAI,KAAK,OAAO,SAAS;AAC3B,QAAU;GAAE,OAAO,IAAI;GAAO,UAAU;GAAM;GAAM,CAAC;GAEtD;AACD,KAAI,WAAW,cAAc;CAI7B,MAAM,yBAAyB,IAAI,QAAQ,wBAAwB,CACjE,cAAc,UAAU,CACxB,YAAY,gDAAgD,CAC5D,SAAS,WAAW,WAAW,CAC/B,OAAO,sBAAsB,kCAAkC,CAC/D,OAAO,2BAA2B,2CAA2C;AAC/E,aAAY,uBAAuB;AACnC,eAAc,uBAAuB;AACrC,wBAAuB,OACtB,OACC,SACA,SAOI;AACJ,MAAI;GACH,MAAM,OAAO,MAAM,qCAAqC;IACvD;IACA,QAAQ,aAAa,KAAK,IAAI;IAC9B,WAAW,KAAK,WAAW,MAAM,IAAI;IACrC,aAAa,KAAK,aAAa,MAAM,IAAI;IACzC,CAAC;AACF,OAAI,KAAK,MAAM;AACd,YAAQ,IAAI,KAAK,UAAU,MAAM,MAAM,EAAE,CAAC;AAC1C;;AAED,KAAE,MAAM,4CAA4C;AACpD,OAAI,KAAK,WAAW,GAAG;AACtB,MAAE,MAAM,2BAA2B,QAAQ,MAAM,GAAG;AACpD;;AAED,QAAK,MAAM,OAAO,KACjB,GAAE,IAAI,QACL,KAAK,IAAI,SAAS,QAAQ,IAAI,eAAe,UAAU,IAAI,iBAAiB,WAAW,IAAI,WAAW,WAAW,IAAI,cAAc,OACnI;AAEF,KAAE,MAAM,GAAG,KAAK,OAAO,qBAAqB;WACpC,KAAK;AACb,OAAI,KAAK,MAAM;AACd,kBACC,gCACA,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAChD;AACD;;AAED,KAAE,IAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAC7D,WAAQ,WAAW;;GAGrB;AACD,KAAI,WAAW,uBAAuB;CAItC,MAAM,0BAA0B,IAAI,QAAQ,yBAAyB,CACnE,cAAc,UAAU,CACxB,YAAY,2BAA2B,CACvC,SAAS,cAAc,qBAAqB,CAC5C,OAAO,sBAAsB,kCAAkC,CAC/D,OAAO,2BAA2B,2CAA2C;AAC/E,aAAY,wBAAwB;AACpC,eAAc,wBAAwB;AACtC,yBAAwB,OACvB,OACC,SACA,SAOI;AACJ,MAAI;AAOH,OAAI,CANO,MAAM,sCAAsC;IACtD;IACA,QAAQ,aAAa,KAAK,IAAI;IAC9B,WAAW,KAAK,WAAW,MAAM,IAAI;IACrC,aAAa,KAAK,aAAa,MAAM,IAAI;IACzC,CAAC,EACO;AACR,QAAI,KAAK,MAAM;AACd,mBAAc,mBAAmB,8BAA8B,QAAQ,MAAM,GAAG;AAChF;;AAED,MAAE,IAAI,MAAM,8BAA8B,QAAQ,MAAM,GAAG;AAC3D,YAAQ,WAAW;AACnB;;AAED,OAAI,KAAK,MAAM;AACd,YAAQ,IAAI,KAAK,UAAU;KAAE,IAAI;KAAM,UAAU,QAAQ,MAAM;KAAE,EAAE,MAAM,EAAE,CAAC;AAC5E;;AAED,KAAE,MAAM,6CAA6C;AACrD,KAAE,IAAI,QAAQ,WAAW,QAAQ,MAAM,GAAG;AAC1C,KAAE,MAAM,UAAU;WACV,KAAK;AACb,OAAI,KAAK,MAAM;AACd,kBAAc,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAChF;;AAED,KAAE,IAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAC7D,WAAQ,WAAW;;GAGrB;AACD,KAAI,WAAW,wBAAwB;CAIvC,MAAM,kBAAkB,IAAI,QAAQ,gBAAgB,CAClD,cAAc,UAAU,CACxB,YAAY,mCAAmC,CAC/C,SAAS,WAAW,WAAW,CAC/B,OAAO,mBAAmB,WAAW,CACrC,OAAO,2BAA2B,2BAA2B,CAC7D,OAAO,qBAAqB,iBAAiB,aAAa,CAC1D,OAAO,uBAAuB,oBAAoB,KAAK,CACvD,OAAO,sBAAsB,kCAAkC,CAC/D,OAAO,2BAA2B,2CAA2C;AAC/E,aAAY,gBAAgB;AAC5B,eAAc,gBAAgB;AAC9B,iBAAgB,OACf,OACC,UACA,SAWI;AACJ,MAAI;GACH,MAAM,WAAW,OAAO,SAAS,OAAO,KAAK,YAAY,KAAK,EAAE,GAAG;GACnE,MAAM,UAAU,OAAO,KAAK,SAAS,GAAG,CAAC,MAAM,IAAI,OAAO,YAAY,GAAG,CAAC,MAAM;GAChF,MAAM,SAAS,MAAM,8BAA8B;IAClD;IACA,gBAAgB,KAAK,gBAAgB,MAAM,IAAI;IAC/C,QAAQ,OAAO,KAAK,UAAU,aAAa,CAAC,MAAM;IAClD;IACA,WAAW;IACX,QAAQ,aAAa,KAAK,IAAI;IAC9B,WAAW,KAAK,WAAW,MAAM,IAAI;IACrC,aAAa,KAAK,aAAa,MAAM,IAAI;IACzC,CAAC;AACF,OAAI,KAAK,MAAM;AACd,YAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;AAED,KAAE,MAAM,oCAAoC;AAC5C,KAAE,IAAI,QAAQ,sBAAsB,UAAU;AAC9C,OAAI,OAAO,OAAO,SAAS,SAAU,GAAE,IAAI,QAAQ,WAAW,OAAO,OAAO;AAC5E,OAAI,OAAO,OAAO,YAAY,SAAU,GAAE,IAAI,QAAQ,aAAa,OAAO,UAAU;AACpF,QAAK,MAAM,WAAW,MAAM,QAAQ,OAAO,SAAS,GAAG,OAAO,WAAW,EAAE,CAC1E,GAAE,IAAI,KAAK,OAAO,QAAQ,CAAC;AAE5B,KAAE,MAAM,eAAe;WACf,KAAK;AACb,OAAI,KAAK,MAAM;AACd,kBAAc,wBAAwB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AACvF;;AAED,KAAE,IAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAC7D,WAAQ,WAAW;;GAGrB;AACD,KAAI,WAAW,gBAAgB;CAI/B,MAAM,kBAAkB,IAAI,QAAQ,gBAAgB,CAClD,cAAc,UAAU,CACxB,YAAY,8BAA8B,CAC1C,SAAS,YAAY,uBAAuB,CAC5C,OAAO,qBAAqB,iBAAiB;AAC/C,aAAY,gBAAgB;AAC5B,iBAAgB,gBAAgB;AAChC,eAAc,gBAAgB;AAC9B,iBAAgB,OACf,OACC,QACA,SAOI;AACJ,MAAI;GACH,MAAM,SAAS,MAAM,8BAA8B;IAClD,aAAa;IACb,QAAQ,aAAa,KAAK,IAAI;IAC9B,SAAS,KAAK,WAAW;IACzB,YAAY,KAAK,UAAU;IAC3B,CAAC;AACF,OAAI,KAAK,MAAM;AACd,YAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;AAED,KAAE,MAAM,oCAAoC;AAC5C,KAAE,IAAI,QAAQ,uBAAuB,OAAO,WAAW;AACvD,KAAE,IAAI,QAAQ,kBAAkB,OAAO,kBAAkB;AACzD,KAAE,IAAI,QAAQ,aAAa,OAAO,SAAS;AAC3C,KAAE,MAAM,6BAA6B;WAC7B,KAAK;AACb,OAAI,KAAK,MAAM;AACd,kBAAc,wBAAwB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AACvF;;AAED,KAAE,IAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAC7D,WAAQ,WAAW;;GAGrB;AACD,KAAI,WAAW,gBAAgB;CAI/B,MAAM,sBAAsB,IAAI,QAAQ,qBAAqB,CAC3D,cAAc,UAAU,CACxB,YAAY,yCAAyC,CACrD,SAAS,WAAW,WAAW,CAC/B,OAAO,mBAAmB,WAAW,CACrC,OAAO,sBAAsB,kCAAkC,CAC/D,OAAO,2BAA2B,2CAA2C;AAC/E,aAAY,oBAAoB;AAChC,eAAc,oBAAoB;AAClC,qBAAoB,OACnB,OACC,UACA,SAQI;AACJ,MAAI;GACH,MAAM,UAAU,OAAO,KAAK,SAAS,GAAG,CAAC,MAAM,IAAI,OAAO,YAAY,GAAG,CAAC,MAAM;GAChF,MAAM,OAAO,MAAM,kCAAkC;IACpD;IACA,QAAQ,aAAa,KAAK,IAAI;IAC9B,WAAW,KAAK,WAAW,MAAM,IAAI;IACrC,aAAa,KAAK,aAAa,MAAM,IAAI;IACzC,CAAC;AACF,OAAI,KAAK,MAAM;AACd,YAAQ,IAAI,KAAK,UAAU,MAAM,MAAM,EAAE,CAAC;AAC1C;;AAED,KAAE,MAAM,yCAAyC;AACjD,OAAI,KAAK,WAAW,GAAG;AACtB,MAAE,MAAM,gCAAgC,UAAU;AAClD;;AAED,QAAK,MAAM,OAAO,MAAM;IACvB,MAAM,cAAc,IAAI,gBAAgB,IAAI;AAC5C,MAAE,IAAI,QAAQ,KAAK,YAAY,IAAI,IAAI,UAAU,eAAe,IAAI,aAAa;;AAElF,KAAE,MAAM,GAAG,KAAK,OAAO,0BAA0B;WACzC,KAAK;AACb,OAAI,KAAK,MAAM;AACd,kBACC,6BACA,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAChD;AACD;;AAED,KAAE,IAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAC7D,WAAQ,WAAW;;GAGrB;AACD,KAAI,WAAW,oBAAoB;CAInC,SAAS,4BACR,MACA,SACC;EACD,MAAM,YAAY,IAAI,QAAQ,KAAK,CACjC,cAAc,UAAU,CACxB,YAAY,GAAG,UAAU,YAAY,OAAO,6BAA6B,CACzE,SAAS,gBAAgB,kBAAkB,CAC3C,OAAO,sBAAsB,kCAAkC,CAC/D,OAAO,2BAA2B,2CAA2C;AAC/E,cAAY,UAAU;AACtB,gBAAc,UAAU;AACxB,YAAU,OACT,OACC,WACA,SAOI;AACJ,OAAI;IACH,MAAM,UAAU,MAAM,mCAAmC;KACxD,WAAW,UAAU,MAAM;KAC3B;KACA,YAAY;KACZ,QAAQ,aAAa,KAAK,IAAI;KAC9B,WAAW,KAAK,WAAW,MAAM,IAAI;KACrC,aAAa,KAAK,aAAa,MAAM,IAAI;KACzC,CAAC;AACF,QAAI,CAAC,SAAS;AACb,SAAI,KAAK,MAAM;AACd,oBACC,0BACA,2BAA2B,UAAU,MAAM,GAC3C;AACD;;AAED,OAAE,IAAI,MAAM,2BAA2B,UAAU,MAAM,GAAG;AAC1D,aAAQ,WAAW;AACnB;;AAED,QAAI,KAAK,MAAM;AACd,aAAQ,IAAI,KAAK,UAAU,SAAS,MAAM,EAAE,CAAC;AAC7C;;AAED,MAAE,MAAM,uBAAuB,OAAO;AACtC,MAAE,IAAI,QAAQ,GAAG,UAAU,aAAa,SAAS,gBAAgB,UAAU,MAAM,GAAG;AACpF,MAAE,MAAM,OAAO,QAAQ,UAAU,UAAU,CAAC;YACpC,KAAK;AACb,QAAI,KAAK,MAAM;AACd,mBAAc,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAChF;;AAED,MAAE,IAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAC7D,YAAQ,WAAW;;IAGrB;AACD,MAAI,WAAW,UAAU;;AAG1B,6BAA4B,wBAAwB,KAAK;AACzD,6BAA4B,qBAAqB,MAAM;AAEvD,QAAO;;;AAIR,IAAa,qBAAqB,yBAAyB;;;AC7xB3D,SAAS,YAAY,OAAuB;AAC3C,KAAI,QAAQ,KAAM,QAAO,GAAG,MAAM;AAClC,KAAI,QAAQ,OAAO,KAAM,QAAO,IAAI,QAAQ,MAAM,QAAQ,EAAE,CAAC;AAC7D,QAAO,IAAI,SAAS,OAAO,OAAO,QAAQ,EAAE,CAAC;;AAG9C,SAAS,2BAAyB,OAA+C;AAChF,KAAI,CAAC,MAAO,QAAO,KAAA;CACnB,MAAM,SAAS,OAAO,SAAS,OAAO,GAAG;AACzC,KAAI,CAAC,OAAO,SAAS,OAAO,IAAI,UAAU,EACzC,OAAM,IAAI,MAAM,6BAA6B,QAAQ;AAEtD,QAAO;;AAGR,SAAS,cAAc,OAAiD;AACvE,KAAI,CAAC,MAAO,QAAO,KAAA;CACnB,MAAM,QAAQ,MACZ,MAAM,IAAI,CACV,KAAK,SAAS,KAAK,MAAM,CAAC,CAC1B,QAAQ,SAAS,KAAK,SAAS,EAAE;AACnC,QAAO,MAAM,SAAS,IAAI,QAAQ,KAAA;;AAGnC,SAAS,4BAA4B,IAAwC;AAC5E,KAAI;EACH,MAAM,MAAM,GACV,QACA;;;;2DAKA,CACA,KAAK;AACP,SAAO,OAAO,KAAK,eAAe,EAAE;SAC7B;AACP,SAAO;;;AAIT,IAAa,YAAY,IAAI,QAAQ,KAAK,CACxC,cAAc,UAAU,CACxB,YAAY,uBAAuB;AAGrC,IAAM,UAAU,IAAI,QAAQ,OAAO,CACjC,cAAc,UAAU,CACxB,YAAY,kDAAkD;AAChE,YAAY,QAAQ;AACpB,QAAQ,QAAQ,SAAiB;CAChC,MAAM,SAAS,aAAa,aAAa,KAAK,CAAC;AAC/C,GAAE,MAAM,kBAAkB;AAC1B,GAAE,IAAI,QAAQ,mBAAmB,OAAO,OAAO;AAC/C,GAAE,MAAM,SAAS,OAAO,UAAU,gBAAgB,CAAC,QAAQ;EAC1D;AACF,UAAU,WAAW,QAAQ;AAG7B,IAAM,YAAY,IAAI,QAAQ,SAAS,CACrC,cAAc,UAAU,CACxB,YAAY,oCAAoC;AAClD,YAAY,UAAU;AACtB,UAAU,QAAQ,SAAiB;CAClC,MAAM,SAAS,eAAe,aAAa,KAAK,CAAC;AACjD,GAAE,MAAM,oBAAoB;AAC5B,GAAE,IAAI,QAAQ,aAAa,OAAO,OAAO;AACzC,GAAE,MAAM,SAAS,OAAO,UAAU,gBAAgB,CAAC,QAAQ;EAC1D;AACF,UAAU,WAAW,UAAU;AAG/B,IAAM,eAAe,IAAI,QAAQ,wBAAwB,CACvD,cAAc,UAAU,CACxB,YACA,wGACA,CACA,OAAO,aAAa,6CAA6C,CACjE,OAAO,yBAAyB,mCAAmC,KAAK,CACxE,OAAO,sBAAsB,uCAAuC,MAAM,CAC1E,OAAO,mBAAmB,6BAA6B,OAAO,CAC9D,OAAO,2BAA2B,+BAA+B,OAAO,CACxE,OAAO,YAAY,8CAA8C;AACnE,YAAY,aAAa;AACzB,aAAa,QAEX,SAQI;CACJ,MAAM,SAAS,cAAc,aAAa,KAAK,CAAC;CAChD,MAAM,KAAK,QAAQ,OAAO;CAC1B,IAAI,SAAS;AACb,KAAI;EACH,MAAM,aAAa,OAAO,SAAS,KAAK,YAAY,GAAG,IAAI;EAC3D,MAAM,YAAY,OAAO,SAAS,KAAK,WAAW,GAAG,IAAI;EACzD,MAAM,WAAW,OAAO,SAAS,KAAK,UAAU,GAAG,IAAI;EACvD,MAAM,iBAAiB,OAAO,SAAS,KAAK,gBAAgB,GAAG,IAAI;EACnE,MAAM,cAAc,4BAA4B,GAAG;AACnD,IAAE,MAAM,mCAAmC;AAC3C,IAAE,IAAI,KAAK,yBAAyB,YAAY,YAAY,GAAG;AAC/D,IAAE,IAAI,KACL,sDAAsD,UAAU,wCAAwC,WAAW,mDACnH;EACD,MAAM,UAAU,2BAA2B,IAAI,YAAY,SAAS;AACpE,MAAI,QAAQ,gBAAgB,EAC3B,GAAE,IAAI,KACL,kBAAkB,QAAQ,cAAc,gBAAgB,CAAC,SAAS,YAAY,QAAQ,0BAA0B,CAAC,OAAO,QAAQ,kBAAkB,gBAAgB,CAAC,qBAAqB,QAAQ,gBAChM;MAED,GAAE,IAAI,KAAK,0CAA0C;AAGtD,MAAI,KAAK,QAAQ;AAChB,KAAE,MAAM,gCAAgC;AACxC;;EAGD,MAAM,aAAa,iCAAiC,IAAI;GACvD;GACA,cAAc,YAAY,OAAO;GACjC,cAAc;GACd,cAAc;GACd,SAAS,SAAS;AACjB,QAAI,KAAK,YAAY,KAAK,CAAC,KAAK,gBAAiB;IACjD,MAAM,SAAS,KAAK,kBAAkB,sBAAsB;AAC5D,MAAE,IAAI,KACL,QAAQ,KAAK,WAAW,YAAY,KAAK,QAAQ,gBAAgB,CAAC,wBAAwB,YAAY,KAAK,WAAW,GAAG,SACzH;;GAEF,CAAC;AAEF,IAAE,IAAI,KAAK,gBAAgB,WAAW,aAAa,gBAAgB,GAAG;AACtE,IAAE,IAAI,KACL,+CAA+C,YAAY,WAAW,WAAW,CAAC,gBAClF;AACD,MAAI,WAAW,UAAW,GAAE,IAAI,KAAK,mBAAmB,WAAW,YAAY;AAC/E,MAAI,WAAW,gBACd,GAAE,IAAI,KACL,6KACA;AAEF,MAAI,KAAK,QAAQ;AAChB,KAAE,IAAI,KAAK,iCAAiC;AAC5C,MAAG,OAAO;AACV,YAAS;GACT,MAAM,WAAW,eAAe,OAAO;AACvC,KAAE,MAAM,2CAA2C,YAAY,SAAS,UAAU,CAAC,GAAG;AACtF;;AAED,IAAE,MACD,4KACA;WACQ;AACT,MAAI,OAAQ,IAAG,OAAO;;EAGxB;AACD,UAAU,WAAW,aAAa;AAGlC,IAAM,qBAAqB,IAAI,QAAQ,oBAAoB,CACzD,cAAc,UAAU,CACxB,YAAY,kDAAkD,CAC9D,OAAO,mBAAmB,oBAAoB,KAAK;AACrD,YAAY,mBAAmB;AAC/B,cAAc,mBAAmB;AACjC,mBAAmB,QAAQ,SAAgD;CAC1E,MAAM,SAAS,kBAAkB,aAAa,KAAK,EAAE,OAAO,SAAS,KAAK,OAAO,GAAG,IAAI,GAAG;AAC3F,KAAI,KAAK,MAAM;AACd,UAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;AAED,GAAE,MAAM,+BAA+B;AACvC,GAAE,IAAI,KACL,WAAW,OAAO,OAAO,QAAQ,gBAAgB,CAAC,kBAAkB,OAAO,OAAO,SAAS,gBAAgB,CAAC,aAC5G;AACD,KAAI,OAAO,MAAM,WAAW,GAAG;AAC9B,IAAE,MAAM,wBAAwB;AAChC;;AAED,MAAK,MAAM,QAAQ,OAAO,MACzB,GAAE,IAAI,QACL,GAAG,KAAK,OAAO,GAAG,KAAK,UAAU,WAAW,KAAK,IAAI,GAAG,KAAK,0BAA0B,KAAK,uBAAuB,CAAC,YACvG,KAAK,wBAAwB,WAAW,KAAK,uBAAuB,WAAW,KAAK,WAAW,KAC5G;AAEF,GAAE,MAAM,OAAO;EACd;AACF,UAAU,WAAW,mBAAmB;AAGxC,IAAM,oBAAoB,IAAI,QAAQ,mBAAmB,CACvD,cAAc,UAAU,CACxB,YAAY,yCAAyC,CACrD,OAAO,mBAAmB,iCAAiC,KAAK;AAClE,YAAY,kBAAkB;AAC9B,kBAAkB,QAAQ,SAAqC;CAC9D,MAAM,SAAS,sBAAsB,aAAa,KAAK,EAAE,OAAO,SAAS,KAAK,OAAO,GAAG,IAAI,GAAG;AAC/F,GAAE,MAAM,8BAA8B;AACtC,GAAE,MAAM,YAAY,OAAO,QAAQ,gBAAgB,CAAC,mBAAmB;EACtE;AACF,UAAU,WAAW,kBAAkB;AAGvC,IAAM,mBAAmB,IAAI,QAAQ,kBAAkB,CACrD,cAAc,UAAU,CACxB,YAAY,uEAAuE,CACnF,OAAO,mCAAmC,8BAA8B,OAAO,CAC/E,OAAO,mCAAmC,8BAA8B,OAAO,CAC/E,OAAO,0CAA0C,qCAAqC,MAAM,CAC5F,OAAO,0BAA0B,4BAA4B,KAAK;AACpE,YAAY,iBAAiB;AAC7B,cAAc,iBAAiB;AAC/B,iBAAiB,QAEf,SAOI;CACJ,MAAM,SAAS,cAAc,aAAa,KAAK,EAAE;EAChD,qBAAqB,OAAO,WAAW,KAAK,oBAAoB;EAChE,qBAAqB,OAAO,WAAW,KAAK,oBAAoB;EAChE,4BAA4B,OAAO,WAAW,KAAK,2BAA2B;EAC9E,aAAa,OAAO,WAAW,KAAK,YAAY;EAChD,CAAC;AAEF,KAAI,KAAK,MAAM;AACd,UAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C,MAAI,CAAC,OAAO,OAAQ,SAAQ,WAAW;AACvC;;AAGD,GAAE,MAAM,6BAA6B;AACrC,GAAE,IAAI,KACL;EACC,gCAAgC,OAAO,QAAQ,MAAM,mBAAmB,QAAQ,EAAE;EAClF,gCAAgC,OAAO,QAAQ,MAAM,mBAAmB,QAAQ,EAAE;EAClF,gCAAgC,OAAO,QAAQ,MAAM,0BAA0B,QAAQ,EAAE;EACzF,gCAAgC,OAAO,QAAQ,gBAAgB;EAC/D,CAAC,KAAK,KAAK,CACZ;AAED,KAAI,OAAO,OACV,GAAE,MAAM,0BAA0B;MAC5B;AACN,OAAK,MAAM,KAAK,OAAO,SACtB,GAAE,IAAI,MAAM,EAAE;AAEf,IAAE,MAAM,0BAA0B;AAClC,UAAQ,WAAW;;EAGrB;AACD,UAAU,WAAW,iBAAiB;AAGtC,IAAM,mBAAmB,IAAI,QAAQ,iBAAiB,CACpD,cAAc,UAAU,CACxB,YAAY,sDAAsD,CAClE,SAAS,cAAc,uBAAuB,CAC9C,SAAS,cAAc,mBAAmB,CAC1C,OAAO,WAAW,qCAAqC;AACzD,YAAY,iBAAiB;AAC7B,iBAAiB,QAAQ,SAAiB,SAAiB,SAAuC;CACjG,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,KAAI;EACH,MAAM,SAAS,CAAC,KAAK;EAErB,MAAM,gBAAgB,KADH,QAAQ,QAAQ,MAAM,MAAM,CAAC,QAAQ,MAAM,MAAM;EAEpE,MAAM,SAAS,CAAC,YAAY,qBAAqB;EACjD,MAAM,SAAiC,EAAE;EACzC,MAAM,YAAY;AACjB,QAAK,MAAM,SAAS,QAAQ;IAC3B,MAAM,OAAO,MAAM,GACjB,QACA,+BAA+B,MAAM,kDACrC,CACA,IAAI,SAAS,cAAc;AAC7B,WAAO,SAAS,KAAK;AACrB,QAAI,CAAC,UAAU,KAAK,MAAM,GAAG;AAC5B,WAAM,GACJ,QAAQ,UAAU,MAAM,oCAAoC,CAC5D,IAAI,SAAS,QAAQ;AACvB,WAAM,GACJ,QACA,UAAU,MAAM,oEAChB,CACA,IAAI,SAAS,eAAe,QAAQ;;;;AAIzC,MAAI,OACH,MAAK;MAEL,OAAM,GAAG,YAAY,IAAI,EAAE;EAE5B,MAAM,SAAS,SAAS,gBAAgB;AACxC,IAAE,MAAM,4BAA4B;AACpC,IAAE,IAAI,KAAK,GAAG,OAAO,GAAG,QAAQ,KAAK,UAAU;AAC/C,IAAE,IAAI,KACL,CAAC,aAAa,OAAO,YAAY,uBAAuB,OAAO,qBAAqB,CAAC,KACpF,KACA,CACD;AACD,MAAI,OACH,GAAE,MAAM,0BAA0B;MAElC,GAAE,MAAM,OAAO;WAEP;AACT,QAAM,OAAO;;EAEb;AACF,UAAU,WAAW,iBAAiB;AAGtC,IAAM,uBAAuB,IAAI,QAAQ,qBAAqB,CAC5D,cAAc,UAAU,CACxB,YAAY,4DAA4D,CACxE,OAAO,WAAW,qCAAqC;AACzD,YAAY,qBAAqB;AACjC,qBAAqB,QAAQ,SAAuC;CACnE,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,KAAI;EACH,MAAM,SAAS,CAAC,KAAK;EACrB,MAAM,SAAS,CAAC,YAAY,qBAAqB;EACjD,MAAM,2BAAgC,IAAI,KAAK;EAC/C,MAAM,SAAiC,EAAE;EAEzC,MAAM,YAAY;AACjB,QAAK,MAAM,SAAS,QAAQ;IAC3B,MAAM,WAAW,MAAM,GACrB,QACA,gCAAgC,MAAM,mDACtC,CACA,KAAK;IACP,IAAI,UAAU;AACd,SAAK,MAAM,OAAO,UAAU;KAC3B,MAAM,WAAW,IAAI,QAAQ,MAAM,IAAI,CAAC,KAAK,IAAI,IAAI;AACrD,SAAI,aAAa,IAAI,SAAS;AAC7B,eAAS,IAAI,IAAI,SAAS,SAAS;AACnC,UAAI,CAAC,QAAQ;OACZ,MAAM,OAAO,MAAM,GACjB,QAAQ,UAAU,MAAM,oCAAoC,CAC5D,IAAI,UAAU,IAAI,QAAQ;AAC5B,kBAAW,KAAK;aACV;OACN,MAAM,MAAM,MAAM,GAChB,QAAQ,+BAA+B,MAAM,oBAAoB,CACjE,IAAI,IAAI,QAAQ;AAClB,kBAAW,IAAI;;;;AAIlB,WAAO,SAAS;;;AAGlB,MAAI,OACH,MAAK;MAEL,OAAM,GAAG,YAAY,IAAI,EAAE;AAG5B,IAAE,MAAM,gCAAgC;AACxC,IAAE,IAAI,KAAK,YAAY,SAAS;AAChC,IAAE,IAAI,KACL,CACC,uBAAuB,OAAO,YAC9B,iCAAiC,OAAO,qBACxC,CAAC,KAAK,KAAK,CACZ;AACD,MAAI,SAAS,OAAO,GAAG;AACtB,KAAE,IAAI,KAAK,mBAAmB;AAC9B,QAAK,MAAM,CAAC,MAAM,OAAO,CAAC,GAAG,SAAS,SAAS,CAAC,CAAC,MAAM,CACtD,GAAE,IAAI,QAAQ,KAAK,KAAK,KAAK,KAAK;;AAGpC,MAAI,OACH,GAAE,MAAM,0BAA0B;MAElC,GAAE,MAAM,OAAO;WAEP;AACT,QAAM,OAAO;;EAEb;AACF,UAAU,WAAW,qBAAqB;AAG1C,IAAM,gBAAgB,IAAI,QAAQ,cAAc,CAC9C,cAAc,UAAU,CACxB,YAAY,oDAAoD,CAChE,OAAO,eAAe,4CAA4C,KAAK;AACzE,YAAY,cAAc;AAC1B,cAAc,cAAc;AAC5B,cAAc,QAAQ,SAAgD;CACrE,MAAM,SAAS,cAAc,aAAa,KAAK,CAAC;CAChD,MAAM,KAAK,QAAQ,OAAO;AAC1B,KAAI;EACH,MAAM,QAAQ,KAAK,IAAI,GAAG,OAAO,SAAS,KAAK,OAAO,GAAG,IAAI,GAAG;EAChE,MAAM,gBAAgB,SAAS,OAAO,CAAC;EACvC,MAAM,WAAW,GACf,QAAQ,kFAAkF,CAC1F,KAAK;EACP,MAAM,YAAY,GAAG,QAAQ,mDAAmD,CAAC,KAAK;EAGtF,MAAM,WAAW,GAAG,QAAQ,mBAAmB,CAAC,KAAK;EACrD,MAAM,SAAS,GACb,QACA;;;;cAKA,CACA,IAAI,MAAM;AAEZ,MAAI,KAAK,MAAM;AACd,WAAQ,IACP,KAAK,UACJ;IACC,iBAAiB;IACjB,eAAe,UAAU,SAAS;IAClC,aAAa,WAAW,kBAAkB,MAAM,UAAU,aAAa;IACvE,QAAQ,OAAO,KAAK,OAAO;KAAE,MAAM,EAAE;KAAM,YAAY,EAAE;KAAY,EAAE;IACvE,EACD,MACA,EACA,CACD;AACD;;AAGD,IAAE,MAAM,yBAAyB;AACjC,IAAE,IAAI,KACL;GACC,kBAAkB,YAAY,cAAc;GAC5C,kBAAkB,YAAY,UAAU,SAAS,EAAE;GACnD,kBAAkB,aAAa,WAAW,kBAAkB,MAAM,UAAU,aAAa,MAAM;GAC/F,CAAC,KAAK,KAAK,CACZ;AACD,MAAI,OAAO,SAAS,GAAG;AACtB,KAAE,IAAI,KAAK,mBAAmB;AAC9B,QAAK,MAAM,KAAK,OACf,GAAE,IAAI,QAAQ,KAAK,EAAE,KAAK,OAAO,GAAG,CAAC,GAAG,YAAY,EAAE,WAAW,CAAC,SAAS,GAAG,GAAG;;AAGnF,IAAE,MAAM,OAAO;WACN;AACT,KAAG,OAAO;;EAEV;AACF,UAAU,WAAW,cAAc;AAGnC,IAAM,kBAAkB,IAAI,QAAQ,gBAAgB,CAClD,cAAc,UAAU,CACxB,YAAY,uDAAuD,CACnE,OAAO,eAAe,wBAAwB,CAC9C,OAAO,iBAAiB,oDAAoD,CAC5E,OAAO,uBAAuB,iDAAiD,CAC/E,OAAO,kBAAkB,+BAA+B,CACxD,OAAO,cAAc,4BAA4B,CACjD,OAAO,aAAa,kCAAkC;AACxD,YAAY,gBAAgB;AAC5B,cAAc,gBAAgB;AAC9B,gBAAgB,QAEd,SASI;CACJ,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,KAAI;EACH,MAAM,QAAQ,2BAAyB,KAAK,MAAM;EAClD,MAAM,UACL,KAAK,gBAAgB,OAClB,OACA,KAAK,SAAS,MAAM,IACrB,QAAQ,IAAI,iBAAiB,MAAM,IACnC,eAAe,QAAQ,KAAK,EAAE,KAAK;EACtC,MAAM,SAAS,iBAAiB,MAAM,IAAI;GACzC;GACA,OAAO,KAAK,SAAS;GACrB;GACA,YAAY,CAAC,KAAK;GAClB,QAAQ,KAAK,WAAW;GACxB,CAAC;AAEF,MAAI,KAAK,MAAM;AACd,WAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;EAGD,MAAM,SAAS,KAAK,SAAS,iBAAiB;AAC9C,IAAE,MAAM,2BAA2B;AACnC,IAAE,IAAI,QAAQ,GAAG,OAAO,GAAG,OAAO,QAAQ,qBAAqB,OAAO,QAAQ,GAAG;AACjF,IAAE,MAAM,WAAW,OAAO,QAAQ,WAAW;UACrC,OAAO;AACf,IAAE,IAAI,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;AACnE,UAAQ,WAAW;WACV;AACT,QAAM,OAAO;;EAGf;AACD,UAAU,WAAW,gBAAgB;AAGrC,IAAM,cAAc,IAAI,QAAQ,qBAAqB,CACnD,cAAc,UAAU,CACxB,YAAY,4DAA4D,CACxE,OAAO,eAAe,4BAA4B,CAClD,OAAO,aAAa,wCAAwC;AAC9D,YAAY,YAAY;AACxB,cAAc,YAAY;AAC1B,YAAY,QAEV,SAKI;CACJ,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,KAAI;EACH,MAAM,QAAQ,2BAAyB,KAAK,MAAM;EAClD,MAAM,SAAS,gCAAgC,MAAM,IAAI,SAAS,MAAM,KAAK,WAAW,KAAK;AAE7F,MAAI,KAAK,MAAM;AACd,WAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;EAGD,MAAM,SAAS,KAAK,SAAS,qBAAqB;AAClD,IAAE,MAAM,gCAAgC;AACxC,IAAE,MAAM,GAAG,OAAO,GAAG,OAAO,YAAY,MAAM,OAAO,QAAQ,eAAe;UACpE,OAAO;AACf,IAAE,IAAI,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;AACnE,UAAQ,WAAW;WACV;AACT,QAAM,OAAO;;EAGf;AACD,UAAU,WAAW,YAAY;AAGjC,IAAM,cAAc,IAAI,QAAQ,iBAAiB,CAC/C,cAAc,UAAU,CACxB,YAAY,uDAAuD,CACnE,OAAO,eAAe,wBAAwB,CAC9C,OAAO,iBAAiB,0DAA0D,CAClF,OAAO,aAAa,wCAAwC;AAC9D,YAAY,YAAY;AACxB,cAAc,YAAY;AAC1B,YAAY,QAEV,SAMI;CACJ,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,KAAI;EACH,MAAM,QAAQ,2BAAyB,KAAK,MAAM;EAClD,MAAM,QAAQ,cAAc,KAAK,MAAM;EACvC,MAAM,SAAS,4BAA4B,MAAM,IAAI;GACpD;GACA,OAAO,SAAS;GAChB,QAAQ,KAAK,WAAW;GACxB,CAAC;AAEF,MAAI,KAAK,MAAM;AACd,WAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;EAGD,MAAM,SAAS,KAAK,SAAS,qBAAqB;AAClD,IAAE,MAAM,4BAA4B;AACpC,IAAE,MAAM,GAAG,OAAO,GAAG,OAAO,YAAY,MAAM,OAAO,QAAQ,WAAW;UAChE,OAAO;AACf,IAAE,IAAI,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;AACnE,UAAQ,WAAW;WACV;AACT,QAAM,OAAO;;EAGf;AACD,UAAU,WAAW,YAAY;AAGjC,IAAM,WAAW,IAAI,QAAQ,iBAAiB,CAC5C,cAAc,UAAU,CACxB,YACA,+FACA,CACA,OAAO,iBAAiB,qEAAqE,CAC7F,OAAO,eAAe,qBAAqB,CAC3C,OAAO,aAAa,wCAAwC;AAC9D,YAAY,SAAS;AACrB,cAAc,SAAS;AACvB,SAAS,QAEP,SAMI;CACJ,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,KAAI;EACH,MAAM,WAAW,2BAAyB,KAAK,OAAO;EACtD,MAAM,QAAQ,2BAAyB,KAAK,MAAM;EAClD,MAAM,SAAS,2BAA2B,MAAM,IAAI;GACnD;GACA;GACA,QAAQ,KAAK,WAAW;GACxB,CAAC;AAEF,MAAI,KAAK,MAAM;AACd,WAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;EAGD,MAAM,SAAS,KAAK,SAAS,qBAAqB;AAClD,IAAE,MAAM,4BAA4B;AACpC,MAAI,OAAO,MAAM,SAAS,KAAK,OAAO,MAAM,UAAU,GACrD,MAAK,MAAM,QAAQ,OAAO,MACzB,GAAE,IAAI,KACL,GAAG,OAAO,IAAI,KAAK,eAAe,WAAW,KAAK,QAAQ,MAAM,KAAK,MAAM,MAAM,GAAG,GAAG,GACvF;AAGH,IAAE,MAAM,GAAG,OAAO,GAAG,OAAO,YAAY,mBAAmB,OAAO,QAAQ,QAAQ;UAC1E,OAAO;AACf,IAAE,IAAI,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;AACnE,UAAQ,WAAW;WACV;AACT,QAAM,OAAO;;EAGf;AACD,UAAU,WAAW,SAAS;AAE9B,IAAM,uBAAuB,IAAI,QAAQ,sBAAsB,CAC7D,cAAc,UAAU,CACxB,YAAY,iEAAiE,CAC7E,OAAO,eAAe,wBAAwB,CAC9C,OAAO,aAAa,kCAAkC;AACxD,YAAY,qBAAqB;AACjC,cAAc,qBAAqB;AACnC,qBAAqB,QAEnB,SAKI;CACJ,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,KAAI;EACH,MAAM,QAAQ,2BAAyB,KAAK,MAAM;EAClD,MAAM,SAAS,wBAAwB,MAAM,IAAI;GAChD;GACA,QAAQ,KAAK,WAAW;GACxB,CAAC;AAEF,MAAI,KAAK,MAAM;AACd,WAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;EAGD,MAAM,SAAS,KAAK,SAAS,iBAAiB;AAC9C,IAAE,MAAM,iCAAiC;AACzC,IAAE,IAAI,QAAQ,GAAG,OAAO,GAAG,OAAO,QAAQ,qBAAqB,OAAO,QAAQ,GAAG;AACjF,IAAE,MAAM,WAAW,OAAO,QAAQ,WAAW;UACrC,OAAO;AACf,IAAE,IAAI,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;AACnE,UAAQ,WAAW;WACV;AACT,QAAM,OAAO;;EAGf;AACD,UAAU,WAAW,qBAAqB;AAG1C,IAAM,uBAAuB,IAAI,QAAQ,qBAAqB,CAC5D,cAAc,UAAU,CACxB,YACA,wFACA,CACA,OAAO,eAAe,wBAAwB,CAC9C,OAAO,aAAa,kCAAkC;AACxD,YAAY,qBAAqB;AACjC,cAAc,qBAAqB;AACnC,qBAAqB,QAEnB,SAKI;CACJ,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,KAAI;EACH,MAAM,QAAQ,2BAAyB,KAAK,MAAM;EAClD,MAAM,SAAS,0BAA0B,MAAM,IAAI;GAClD;GACA,QAAQ,KAAK,WAAW;GACxB,CAAC;AAEF,MAAI,KAAK,MAAM;AACd,WAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;EAGD,MAAM,SAAS,KAAK,SAAS,iBAAiB;AAC9C,IAAE,MAAM,gCAAgC;AACxC,IAAE,IAAI,QAAQ,GAAG,OAAO,GAAG,OAAO,QAAQ,qBAAqB,OAAO,QAAQ,GAAG;AACjF,IAAE,MAAM,WAAW,OAAO,QAAQ,WAAW;UACrC,OAAO;AACf,IAAE,IAAI,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;AACnE,UAAQ,WAAW;WACV;AACT,QAAM,OAAO;;EAGf;AACD,UAAU,WAAW,qBAAqB;AAG1C,IAAM,0BAA0B,IAAI,QAAQ,yBAAyB,CACnE,cAAc,UAAU,CACxB,YACA,kGACA,CACA,OAAO,eAAe,wBAAwB,CAC9C,OAAO,iBAAiB,kCAAkC,CAC1D,OACA,eACA,4EACA,CACA,OAAO,aAAa,kCAAkC;AACxD,YAAY,wBAAwB;AACpC,cAAc,wBAAwB;AACtC,wBAAwB,OACvB,OACC,SAOI;CACJ,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,KAAI;EACH,MAAM,QAAQ,2BAAyB,KAAK,MAAM;EAClD,MAAM,QAAQ,cAAc,KAAK,MAAM;EACvC,MAAM,SAAS,MAAM,4BAA4B,MAAM,IAAI;GAC1D;GACA;GACA,WAAW,KAAK,cAAc;GAC9B,QAAQ,KAAK,WAAW;GACxB,CAAC;AAEF,MAAI,KAAK,MAAM;AACd,WAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;EAGD,MAAM,SAAS,KAAK,SAAS,iBAAiB;AAC9C,IAAE,MAAM,oCAAoC;AAC5C,IAAE,IAAI,QACL,GAAG,OAAO,GAAG,OAAO,QAAQ,qBAAqB,OAAO,QAAQ,WAAW,OAAO,OAAO,GACzF;AACD,IAAE,MAAM,WAAW,OAAO,QAAQ,WAAW;UACrC,OAAO;AACf,IAAE,IAAI,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;AACnE,UAAQ,WAAW;WACV;AACT,QAAM,OAAO;;EAGf;AACD,UAAU,WAAW,wBAAwB;;;AC3zB7C,SAAS,yBAAyB,OAA+C;AAChF,KAAI,CAAC,MAAO,QAAO,KAAA;CACnB,MAAM,SAAS,OAAO,SAAS,OAAO,GAAG;AACzC,KAAI,CAAC,OAAO,SAAS,OAAO,IAAI,UAAU,EACzC,OAAM,IAAI,MAAM,6BAA6B,QAAQ;AAEtD,QAAO;;AAGR,SAAgB,yBACf,KACA,YACA,aACgB;AAChB,KAAI,gBAAgB,KAAM,QAAO;CACjC,MAAM,WAAW,YAAY,MAAM;AACnC,KAAI,SAAU,QAAO;CACrB,MAAM,aAAa,QAAQ,IAAI,iBAAiB,MAAM;AACtD,KAAI,WAAY,QAAO;AACvB,QAAO,eAAe,KAAK,KAAK;;AAGjC,IAAM,WAAW,IAAI,QAAQ,QAAQ,CACnC,cAAc,UAAU,CACxB,YAAY,+BAA+B,CAC3C,OAAO,eAAe,wBAAwB,CAC9C,OAAO,iBAAiB,oDAAoD,CAC5E,OAAO,uBAAuB,iDAAiD,CAC/E,OAAO,kBAAkB,4BAA4B,CACrD,OAAO,cAAc,4BAA4B,CACjD,OAAO,aAAa,uCAAuC;AAE7D,YAAY,SAAS;AACrB,cAAc,SAAS;AAEvB,IAAa,eAAe,SAAS,OACpC,OACC,SASI;CACJ,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,KAAI;EACH,MAAM,QAAQ,yBAAyB,KAAK,MAAM;EAClD,MAAM,UAAU,yBAAyB,QAAQ,KAAK,EAAE,KAAK,SAAS,KAAK,YAAY;EAEvF,MAAM,SAAS,MAAM,gBAAgB,MAAM,IAAI;GAC9C;GACA,OAAO,KAAK,SAAS;GACrB;GACA,YAAY,CAAC,KAAK;GAClB,QAAQ,KAAK,WAAW;GACxB,CAAC;AAEF,MAAI,KAAK,MAAM;AACd,WAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;EAGD,MAAM,SAAS,KAAK,SAAS,gBAAgB;AAC7C,IAAE,MAAM,gBAAgB;AACxB,IAAE,IAAI,QACL,GAAG,OAAO,GAAG,OAAO,SAAS,YAAY,OAAO,SAAS,aAAa,OAAO,QAAQ,WACrF;AACD,IAAE,MAAM,WAAW,OAAO,QAAQ,WAAW;UACrC,OAAO;AACf,IAAE,IAAI,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;AACnE,UAAQ,WAAW;WACV;AACT,QAAM,OAAO;;EAGf;;;ACrFD,IAAM,kBAAkB;CACvB;CACA;CACA;CACA;CACA;AAED,SAAS,uBAAuB,SAAiD;CAChF,MAAM,yBAAS,IAAI,KAAqB;AACxC,MAAK,MAAM,OAAO,iBAAiB;EAClC,MAAM,QAAQ,QAAQ;AACtB,MAAI,OAAO,UAAU,SAAU;EAC/B,MAAM,OAAO,MAAM,MAAM;AACzB,MAAI,KAAM,QAAO,IAAI,KAAK,KAAK;;AAEhC,KAAI,OAAO,SAAS,EAAG,QAAO;AAE9B,KADe,IAAI,IAAI,OAAO,QAAQ,CAAC,CAC5B,OAAO,EAAG,QAAO;AAC5B,MAAK,MAAM,OAAO,iBAAiB;EAClC,MAAM,QAAQ,OAAO,IAAI,IAAI;AAC7B,MAAI,MAAO,QAAO;;AAEnB,QAAO;;AAGR,eAAe,gBAAkD;CAChE,MAAM,SAAmB,EAAE;AAC3B,YAAW,MAAM,SAAS,QAAQ,MACjC,QAAO,KAAK,OAAO,SAAS,MAAM,GAAG,QAAQ,OAAO,KAAK,OAAO,MAAM,CAAC,CAAC;CAEzE,MAAM,MAAM,OAAO,OAAO,OAAO,CAAC,SAAS,QAAQ,CAAC,MAAM;AAC1D,KAAI,CAAC,IAAK,OAAM,IAAI,MAAM,sBAAsB;CAChD,MAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,KAAI,UAAU,QAAQ,OAAO,WAAW,YAAY,MAAM,QAAQ,OAAO,CACxE,OAAM,IAAI,MAAM,4BAA4B;AAE7C,QAAO;;AAGR,SAAS,oBAAoB,WAAmB,SAAuB;AACtE,SAAQ,IAAI,KAAK,UAAU;EAAE,OAAO;EAAW;EAAS,CAAC,CAAC;AAC1D,SAAQ,WAAW;;AAGpB,IAAM,aAAa,IAAI,QAAQ,oBAAoB,CACjD,cAAc,UAAU,CACxB,YAAY,0DAA0D;AAExE,YAAY,WAAW;AAEvB,IAAa,yBAAyB,WAAW,OAAO,OAAO,SAAiB;AAC/E,KAAI;EACH,MAAM,UAAU,MAAM,eAAe;EACrC,MAAM,YAAY,uBAAuB,QAAQ;AACjD,MAAI,CAAC,WAAW;AACf,uBAAoB,oBAAoB,sBAAsB;AAC9D;;AAED,MAAI,UAAU,WAAW,OAAO,EAAE;AACjC,uBAAoB,oBAAoB,qBAAqB;AAC7D;;EAGD,MAAM,YAAY,OAAO,QAAQ,eAAe,WAAW,QAAQ,WAAW,MAAM,GAAG;AACvF,MAAI,CAAC,WAAW;AACf,uBAAoB,oBAAoB,sBAAsB;AAC9D;;EAGD,MAAM,MAAM,OAAO,QAAQ,QAAQ,WAAW,QAAQ,MAAM;EAC5D,MAAM,UAAU,OAAO,QAAQ,YAAY,WAAW,QAAQ,UAAU;EACxE,MAAM,YAAY,OAAO,QAAQ,eAAe,WAAW,QAAQ,aAAa;EAChF,MAAM,WAAW,OAAO,SAAS,OAAO,QAAQ,WAAW,CAAC,GACzD,KAAK,MAAM,OAAO,QAAQ,WAAW,CAAC,GACtC;EACH,MAAM,WAAW,OAAO,SAAS,OAAO,QAAQ,WAAW,CAAC,GACzD,OAAO,QAAQ,WAAW,GAC1B;EACH,MAAM,UAAU,OAAO,QAAQ,aAAa,WAAW,QAAQ,SAAS,MAAM,GAAG;EACjF,MAAM,eACL,QAAQ,WAAW,OAAO,QAAQ,YAAY,YAAY,CAAC,MAAM,QAAQ,QAAQ,QAAQ,GACrF,gBAAgB,QAAQ,QAAQ,GACjC,EAAE;EAEN,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,MAAI;AACH,SAAM,0BAA0B;IAC/B,mBAAmB;IACnB,QAAQ;IACR;IACA;IACA;IACA,kBAAkB;IAClB,CAAC;AACF,SAAM,qBAAqB,WAAW,CACrC;IACC,UAAU;IACV,YAAY;IACZ,SAAS;IACT,YAAY;IACZ,YAAY;IACZ,CACD,CAAC;YACO;AACT,SAAM,OAAO;;UAEN,KAAK;AACb,sBAAoB,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;;EAEtF;;;ACzGF,SAAS,eAAe,OAAuB;AAC9C,QAAO,MAAM,WAAW,KAAK,GAAG,KAAK,SAAS,EAAE,MAAM,MAAM,EAAE,CAAC,GAAG;;AAGnE,IAAM,QAAM,IAAI,QAAQ,kBAAkB,CACxC,cAAc,UAAU,CACxB,YAAY,uDAAuD,CACnE,SAAS,YAAY,wCAAwC,CAC7D,OAAO,uBAAuB,gDAAgD,CAC9E,OAAO,kBAAkB,sBAAsB,CAC/C,OAAO,sBAAsB,+BAA+B,CAC5D,OAAO,iBAAiB,wDAAwD;AAElF,YAAY,MAAI;AAEhB,MAAI,QAEF,QACA,SAMI;CACJ,MAAM,UAAU,eAAe;EAC9B,QAAQ,cAAc,aAAa,KAAK,CAAC;EACzC,SAAS,KAAK;EACd,aAAa,KAAK;EAClB,iBAAiB,KAAK;EACtB,OAAO,KAAK;EACZ,CAAC;CACF,MAAM,OAAO,GAAG,KAAK,UAAU,SAAS,MAAM,EAAE,CAAC;AACjD,KAAI,WAAW,KAAK;AACnB,UAAQ,OAAO,MAAM,KAAK;AAC1B;;CAED,MAAM,aAAa,eAAe,OAAO;AACzC,eAAc,YAAY,MAAM,OAAO;AACvC,GAAE,MAAM,0BAA0B;AAClC,GAAE,IAAI,QACL;EACC,cAAc;EACd,cAAc,QAAQ,SAAS,OAAO,gBAAgB;EACtD,cAAc,QAAQ,aAAa,OAAO,gBAAgB;EAC1D,cAAc,QAAQ,kBAAkB,OAAO,gBAAgB;EAC/D,cAAc,QAAQ,aAAa,OAAO,gBAAgB;EAC1D,CAAC,KAAK,KAAK,CACZ;AACD,GAAE,MAAM,OAAO;EAEhB;AAED,IAAa,wBAAwB;;;AChDrC,IAAM,QAAM,IAAI,QAAQ,kBAAkB,CACxC,cAAc,UAAU,CACxB,YAAY,6CAA6C,CACzD,SAAS,eAAe,sCAAsC,CAC9D,OAAO,0BAA0B,4CAA4C,CAC7E,OAAO,aAAa,iCAAiC;AAEvD,YAAY,MAAI;AAChB,cAAc,MAAI;AAElB,MAAI,QAEF,WACA,SAKI;CACJ,IAAI;AACJ,KAAI;AACH,YAAU,kBAAkB,UAAU;UAC9B,OAAO;EACf,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,MAAI,KAAK,KACR,eAAc,iBAAiB,QAAQ;OACjC;AACN,KAAE,IAAI,MAAM,QAAQ;AACpB,WAAQ,WAAW;;AAEpB;;AAGD,KAAI,CAAC,KAAK,MAAM;AACf,IAAE,MAAM,0BAA0B;AAClC,IAAE,IAAI,KACL;GACC,mBAAmB,QAAQ;GAC3B,mBAAmB,QAAQ;GAC3B,mBAAmB,QAAQ,SAAS,OAAO,gBAAgB;GAC3D,mBAAmB,QAAQ,aAAa,OAAO,gBAAgB;GAC/D,mBAAmB,QAAQ,kBAAkB,OAAO,gBAAgB;GACpE,mBAAmB,QAAQ,aAAa,OAAO,gBAAgB;GAC/D,CAAC,KAAK,KAAK,CACZ;;CAGF,MAAM,SAAS,eAAe,SAAS;EACtC,QAAQ,cAAc,aAAa,KAAK,CAAC;EACzC,cAAc,KAAK;EACnB,QAAQ,KAAK;EACb,CAAC;AAEF,KAAI,KAAK,MAAM;AACd,UAAQ,IACP,KAAK,UAAU;GACd,UAAU,OAAO;GACjB,cAAc,OAAO;GACrB,SAAS,OAAO;GAChB,CAAC,CACF;AACD;;AAGD,KAAI,OAAO,QAAQ;AAClB,IAAE,MAAM,mBAAmB;AAC3B;;AAED,GAAE,IAAI,QACL;EACC,uBAAuB,OAAO,SAAS,gBAAgB;EACvD,uBAAuB,OAAO,aAAa,gBAAgB;EAC3D,uBAAuB,OAAO,aAAa,gBAAgB;EAC3D,uBAAuB,OAAO,kBAAkB,gBAAgB;EAChE,CAAC,KAAK,KAAK,CACZ;AACD,GAAE,MAAM,OAAO;EAEhB;AAED,IAAa,wBAAwB;;;AC1FrC,IAAM,SAAS,IAAI,QAAQ,MAAM,CAC/B,cAAc,UAAU,CACxB,YAAY,6BAA6B;AAE3C,YAAY,OAAO;AAEnB,IAAa,aAAa,OAAO,OAAO,OAAO,SAAiB;CAC/D,MAAM,SAAS,aAAa,KAAK;AACjC,KAAI,OAAQ,SAAQ,IAAI,aAAa;AACrC,KAAI;AACH,QAAM,OAAO;UACL,KAAK;AACb,UAAQ,MACP,+BAA+B,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GAC/E;AACD,UAAQ,WAAW;;EAEnB;;;ACRF,IAAa,iBAAb,cAAoC,MAAM;CACzC,YAAY,SAAiB;AAC5B,QAAM,QAAQ;AACd,OAAK,OAAO;;;AAId,SAAgB,sBAAsB,OAAe,UAA8B;AAClF,QAAO,CAAC,GAAG,UAAU,MAAM;;AAG5B,SAAgB,sBAAsB,SAA2B;AAChE,QAAO,QACL,OAAO,mBAAmB,aAAa,KAAK,CAC5C,OAAO,qBAAqB,eAAe,CAC3C,OAAO,2BAA2B,eAAe,CACjD,OACA,6BACA,oDACA,uBACA,EAAE,CACF,CACA,OAAO,uBAAuB,iDAAiD,CAC/E,OAAO,kBAAkB,6BAA6B,CACtD,OAAO,aAAa,iEAAiE,CACrF,OAAO,wBAAwB,2DAA2D;;AAG7F,SAAgB,wBACf,MAUA,MAII,EAAE,EACe;CACrB,MAAM,QAAQ,iBAAiB,KAAK,SAAS,MAAM,QAAQ;CAC3D,MAAM,YAAY,KAAK,eAAe,KAAK;CAC3C,MAAM,SAAS,YAAY,oBAAoB,WAAW,eAAe,GAAG,KAAA;CAC5E,MAAM,UAAuB,EAAE;AAE/B,KAAI,CAAC,KAAK,aAAa;EACtB,MAAM,iBAAiB,IAAI,YAAY,MAAM,IAAI;EACjD,MAAM,mBAAmB,IAAI,oBAAoB;EACjD,MAAM,MAAM,IAAI,OAAO,QAAQ,KAAK;EACpC,MAAM,UAAU,kBAAkB,iBAAiB,KAAK,KAAK,WAAW,KAAK;AAC7E,MAAI,QACH,SAAQ,UAAU;;AAIpB,MAAK,KAAK,gBAAgB,UAAU,KAAK,EACxC,SAAQ,oBAAoB,KAAK;CAGlC,IAAI;AACJ,KAAI,KAAK,WAAW,KAAK,iBAAiB,MAAM;AAC/C,kBAAgB,EAAE,SAAS,MAAM;AACjC,MAAI,KAAK,iBAAiB,KACzB,eAAc,qBAAqB,oBAClC,KAAK,eACL,uBACA;;AAIH,QAAO;EAAE;EAAO;EAAQ;EAAS;EAAe;;AAGjD,SAAS,iBAAiB,OAAe,OAAuB;AAC/D,KAAI,CAAC,QAAQ,KAAK,MAAM,MAAM,CAAC,CAC9B,OAAM,IAAI,eAAe,GAAG,MAAM,6BAA6B;CAEhE,MAAM,SAAS,OAAO,SAAS,OAAO,GAAG;AACzC,KAAI,CAAC,OAAO,SAAS,OAAO,IAAI,SAAS,EACxC,OAAM,IAAI,eAAe,GAAG,MAAM,6BAA6B;AAEhE,QAAO;;AAGR,SAAS,oBAAoB,OAAe,OAAuB;AAClE,KAAI,CAAC,QAAQ,KAAK,MAAM,MAAM,CAAC,CAC9B,OAAM,IAAI,eAAe,GAAG,MAAM,iCAAiC;CAEpE,MAAM,SAAS,OAAO,SAAS,OAAO,GAAG;AACzC,KAAI,CAAC,OAAO,SAAS,OAAO,IAAI,SAAS,EACxC,OAAM,IAAI,eAAe,GAAG,MAAM,iCAAiC;AAEpE,QAAO;;;;;;;;;;;ACtER,SAAS,sBAAsB,OAA8B;AAC5D,KAAI,CAAC,QAAQ,KAAK,MAAM,MAAM,CAAC,CAAE,QAAO;CACxC,MAAM,IAAI,OAAO,MAAM,MAAM,CAAC;AAC9B,QAAO,OAAO,SAAS,EAAE,IAAI,KAAK,KAAK,OAAO,UAAU,EAAE,GAAG,IAAI;;AAGlE,SAAS,iBAAiB,OAAe,MAA+B;CACvE,MAAM,WAAW,sBAAsB,MAAM;AAC7C,KAAI,aAAa,MAAM;AACtB,MAAI,KAAK,KACR,eAAc,cAAc,sBAAsB,QAAQ;OACpD;AACN,KAAE,IAAI,MAAM,sBAAsB,QAAQ;AAC1C,WAAQ,WAAW;;AAEpB;;CAED,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,KAAI;EACH,MAAM,OAAO,MAAM,IAAI,SAAS;AAChC,MAAI,CAAC,MAAM;AACV,OAAI,KAAK,KACR,eAAc,aAAa,UAAU,SAAS,YAAY;QACpD;AACN,MAAE,IAAI,MAAM,UAAU,SAAS,YAAY;AAC3C,YAAQ,WAAW;;AAEpB;;AAED,MAAI,KAAK,KACR,SAAQ,IAAI,KAAK,UAAU,MAAM,MAAM,EAAE,CAAC;OACpC;AAEN,WAAQ,IAAI,IAAI,KAAK,GAAG,IAAI,KAAK,KAAK,IAAI,KAAK,QAAQ;AACvD,OAAI,KAAK,SAAU,SAAQ,IAAI,KAAK,KAAK,WAAW;AACpD,WAAQ,IAAI,cAAc,KAAK,WAAW,gBAAgB,KAAK,aAAa;AAC5E,OAAI,KAAK,UAAW,SAAQ,IAAI,WAAW,KAAK,YAAY;AAC5D,OAAI,KAAK,WAAW;IACnB,MAAM,UACL,KAAK,UAAU,SAAS,MAAM,GAAG,KAAK,UAAU,MAAM,GAAG,IAAI,CAAC,KAAK,KAAK;AACzE,YAAQ,IAAI,KAAK,UAAU;;;WAGpB;AACT,QAAM,OAAO;;;AAIf,SAAS,mBAAmB,OAAe,MAA+B;CACzE,MAAM,WAAW,sBAAsB,MAAM;AAC7C,KAAI,aAAa,MAAM;AACtB,MAAI,KAAK,KACR,eAAc,cAAc,sBAAsB,QAAQ;OACpD;AACN,KAAE,IAAI,MAAM,sBAAsB,QAAQ;AAC1C,WAAQ,WAAW;;AAEpB;;CAED,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,KAAI;AACH,QAAM,OAAO,SAAS;AACtB,MAAI,KAAK,KACR,SAAQ,IAAI,KAAK,UAAU;GAAE,IAAI;GAAU,QAAQ;GAAa,CAAC,CAAC;MAElE,GAAE,IAAI,QAAQ,UAAU,SAAS,kBAAkB;WAE3C;AACT,QAAM,OAAO;;;AAYf,eAAe,qBAAqB,MAA4C;CAC/E,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;CAChE,IAAI,YAA2B;AAC/B,KAAI;EACH,MAAM,UAAU,eAAe,QAAQ,KAAK,EAAE,KAAK,WAAW,KAAK;AACnE,cAAY,MAAM,aAAa;GAC9B,KAAK,QAAQ,KAAK;GAClB;GACA,MAAM,QAAQ,IAAI,QAAQ;GAC1B,aAAa;GACb,UAAU,EAAE,QAAQ,MAAM;GAC1B,CAAC;EACF,MAAM,QAAQ,MAAM,SAAS,WAAW,KAAK,MAAM,KAAK,OAAO,KAAK,MAAM,IAAK,KAAK,KAAK;AACzF,QAAM,MAAM,0BAA0B;AACtC,QAAM,WAAW,WAAW,EAAE,QAAQ,MAAM,CAAC;AAC7C,MAAI,KAAK,KACR,SAAQ,IAAI,KAAK,UAAU,EAAE,IAAI,OAAO,CAAC,CAAC;MAE1C,GAAE,IAAI,QAAQ,iBAAiB,QAAQ;UAEhC,KAAK;AACb,MAAI,cAAc,KACjB,KAAI;AACH,SAAM,WAAW,WAAW;IAAE,QAAQ;IAAM,OAAO;IAAM,CAAC;UACnD;EAIT,MAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAChE,MAAI,KAAK,KACR,eAAc,mBAAmB,QAAQ;OACnC;AACN,KAAE,IAAI,MAAM,2BAA2B,UAAU;AACjD,WAAQ,WAAW;;WAEX;AACT,QAAM,OAAO;;;AAIf,SAAS,0BAAmC;CAC3C,MAAM,MAAM,IAAI,QAAQ,OAAO,CAC7B,cAAc,UAAU,CACxB,YAAY,qBAAqB,CACjC,SAAS,QAAQ,YAAY;AAC/B,aAAY,IAAI;AAChB,eAAc,IAAI;AAClB,KAAI,OAAO,iBAAiB;AAC5B,QAAO;;AAGR,SAAS,4BAAqC;CAC7C,MAAM,MAAM,IAAI,QAAQ,SAAS,CAC/B,cAAc,UAAU,CACxB,YAAY,2BAA2B,CACvC,SAAS,QAAQ,YAAY;AAC/B,aAAY,IAAI;AAChB,eAAc,IAAI;AAClB,KAAI,OAAO,mBAAmB;AAC9B,QAAO;;AAGR,SAAS,8BAAuC;CAC/C,MAAM,MAAM,IAAI,QAAQ,WAAW,CACjC,cAAc,UAAU,CACxB,YAAY,6BAA6B,CACzC,eAAe,qBAAqB,2DAA2D,CAC/F,eAAe,uBAAuB,eAAe,CACrD,eAAe,qBAAqB,mBAAmB,CACvD,OAAO,oBAAoB,yBAAyB,CACpD,OAAO,uBAAuB,2CAA2C;AAC3E,aAAY,IAAI;AAChB,eAAc,IAAI;AAClB,KAAI,OAAO,qBAAqB;AAChC,QAAO;;AAGR,SAAS,4BAAqC;CAC7C,MAAM,MAAM,IAAI,QAAQ,SAAS,CAC/B,cAAc,UAAU,CACxB,YAAY,4DAA4D,CACxE,SAAS,aAAa,+BAA+B,CACrD,OAAO,mBAAmB,aAAa,KAAK,CAC5C,OAAO,qBAAqB,eAAe,CAC3C,OAAO,2BAA2B,eAAe,CACjD,OACA,6BACA,oDACA,uBACA,EAAE,CACF,CACA,OAAO,uBAAuB,iDAAiD,CAC/E,OAAO,kBAAkB,6BAA6B,CACtD,mBAAmB,KAAK,CACxB,qBAAqB,KAAK;AAC5B,aAAY,IAAI;AAChB,KAAI,OACH,OACC,SACA,SAQI;AACJ,yBAAuB,yBAAyB,eAAe;EAC/D,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,MAAI;GACH,MAAM,EAAE,OAAO,QAAQ,YAAY,wBAAwB,MAAM,EAChE,YAAY,QAAQ,IAAI,iBACxB,CAAC;GACF,MAAM,OAAO,MAAM,MAAM,qBAAqB,SAAS,OAAO,QAAQ,QAAQ;AAC9E,WAAQ,IAAI,KAAK,aAAa,GAAG;YACxB;AACT,SAAM,OAAO;;GAGf;AACD,QAAO;;AAGR,SAAS,gCAAyC;CACjD,MAAM,MAAM,IAAI,QAAQ,cAAc,CACpC,cAAc,UAAU,CACxB,YAAY,iDAAiD,CAC7D,OAAO,uBAAuB,iDAAiD,CAC/E,OAAO,kBAAkB,8BAA8B,CACvD,OACA,mBACA,qDACC,OAAO,SAAmB,CAAC,GAAG,MAAM,MAAM,EAC3C,EAAE,CACF,CACA,OACA,mBACA,qEACC,OAAO,SAAmB,CAAC,GAAG,MAAM,MAAM,EAC3C,EAAE,CACF,CACA,OAAO,cAAc,4BAA4B;AACnD,aAAY,IAAI;AAChB,eAAc,IAAI;AAClB,KAAI,QAEF,SAQI;EACJ,MAAM,UACL,KAAK,gBAAgB,OAClB,OACA,KAAK,SAAS,MAAM,IACrB,QAAQ,IAAI,iBAAiB,MAAM,IACnC,eAAe,QAAQ,KAAK,EAAE,KAAK;EACtC,MAAM,mBAAmB,KAAK,YAAY,EAAE,EAAE,MAC5C,OAAO,6BAA6B,GAAG,IAAI,KAC5C;AACD,MAAI,gBACH,OAAM,IAAI,MAAM,+BAA+B,kBAAkB;EAElE,MAAM,SAAS,CACd,GAAI,KAAK,SAAS,EAAE,EACpB,GAAG,gCAAgC,KAAK,YAAY,EAAE,CAAC,CACvD;EACD,MAAM,SAAS,oBAAoB,aAAa,KAAK,EAAE;GACtD;GACA,aAAa,KAAK,gBAAgB;GAClC,iBAAiB,KAAK,aAAa;GACnC;GACA,CAAC;AAEF,MAAI,KAAK,MAAM;AACd,WAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;AAGD,IAAE,MAAM,6BAA6B;AACrC,IAAE,IAAI,KACL;GACC,aAAa,OAAO,OAAO;GAC3B,WAAW,OAAO,OAAO;GACzB,aAAa,OAAO,OAAO;GAC3B,CAAC,KAAK,KAAK,CACZ;AACD,IAAE,IAAI,KAAK,kBAAkB;AAC7B,OAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,OAAO,eAAe,CAChE,GAAE,IAAI,QAAQ,KAAK,KAAK,OAAO,GAAG,CAAC,GAAG,OAAO,MAAM,GAAG;AAEvD,IAAE,IAAI,KAAK,qBAAqB;AAChC,IAAE,IAAI,QAAQ,iBAAiB,OAAO,kBAAkB,SAAS;AACjE,IAAE,IAAI,QAAQ,iBAAiB,OAAO,kBAAkB,WAAW;AACnE,IAAE,IAAI,KAAK,oBAAoB;AAC/B,IAAE,IAAI,QAAQ,6BAA6B,OAAO,iBAAiB,kBAAkB;AACrF,IAAE,IAAI,QAAQ,6BAA6B,OAAO,iBAAiB,0BAA0B;AAC7F,IAAE,IAAI,QAAQ,6BAA6B,OAAO,gBAAgB,SAAS;AAC3E,IAAE,IAAI,QAAQ,6BAA6B,OAAO,gBAAgB,WAAW;AAC7E,IAAE,IAAI,KAAK,mBAAmB;AAC9B,OAAK,MAAM,CAAC,QAAQ,UAAU,OAAO,QAAQ,OAAO,gBAAgB,CACnE,GAAE,IAAI,QAAQ,KAAK,OAAO,OAAO,GAAG,CAAC,GAAG,OAAO,MAAM,GAAG;AAEzD,IAAE,IAAI,KAAK,mBAAmB;AAC9B,OAAK,MAAM,CAAC,QAAQ,UAAU,OAAO,QAAQ,OAAO,sBAAsB,CACzE,GAAE,IAAI,QAAQ,KAAK,OAAO,OAAO,GAAG,CAAC,GAAG,OAAO,MAAM,GAAG;AAEzD,IAAE,IAAI,KAAK,wBAAwB;AACnC,OAAK,MAAM,CAAC,QAAQ,UAAU,OAAO,QAAQ,OAAO,4BAA4B,CAC/E,GAAE,IAAI,QAAQ,KAAK,OAAO,OAAO,GAAG,CAAC,GAAG,OAAO,MAAM,GAAG;AAEzD,MAAI,OAAO,cAAc,SAAS,GAAG;AACpC,KAAE,IAAI,KAAK,iBAAiB;AAC5B,QAAK,MAAM,SAAS,OAAO,eAAe;AACzC,MAAE,IAAI,QAAQ,YAAY,MAAM,QAAQ;AACxC,QAAI,MAAM,YACT,GAAE,IAAI,QACL,iBAAiB,MAAM,YAAY,IAAI,MAAM,qBAAqB,UAAU,GAAG,MAAM,iBAAiB,MAAM,MAAM,mBAAmB,KACrI;AAEF,MAAE,IAAI,QAAQ,aAAa,MAAM,OAAO;AACxC,MAAE,IAAI,QACL,0BAA0B,MAAM,gBAAgB,QAAQ,SAAS,MAAM,gBAAgB,MAAM,aAAa,MAAM,gBAAgB,UAAU,WAAW,MAAM,gBAAgB,UAC3K;AACD,MAAE,IAAI,QACL,2BAA2B,MAAM,mBAAmB,OAAO,YAAY,MAAM,mBAAmB,WAChG;AACD,MAAE,IAAI,QACL,2BAA2B,MAAM,WAAW,YAAY,QAAQ,EAAE,CAAC,kBAAkB,MAAM,WAAW,eAAe,QAAQ,EAAE,CAAC,wBAAwB,MAAM,WAAW,qBAAqB,QAAQ,EAAE,GACxM;AACD,QAAI,MAAM,iCACT,GAAE,IAAI,QACL,2DAA2D,MAAM,iCAAiC,WAAW,YAAY,QAAQ,EAAE,CAAC,kBAAkB,MAAM,iCAAiC,WAAW,eAAe,QAAQ,EAAE,CAAC,wBAAwB,MAAM,iCAAiC,WAAW,qBAAqB,QAAQ,EAAE,GAC3U;AAEF,QAAI,MAAM,+CACT,GAAE,IAAI,QACL,qEAAqE,MAAM,+CAA+C,WAAW,YAAY,QAAQ,EAAE,CAAC,kBAAkB,MAAM,+CAA+C,WAAW,eAAe,QAAQ,EAAE,CAAC,wBAAwB,MAAM,+CAA+C,WAAW,qBAAqB,QAAQ,EAAE,GAC/X;AAEF,QAAI,MAAM,eACT,GAAE,IAAI,QACL,kCAAkC,MAAM,eAAe,aAAa,QAAQ,KAAK,gBAAgB,MAAM,eAAe,kBAAkB,QAAQ,KAAK,gBAAgB,MAAM,eAAe,sBAAsB,aAAa,MAAM,eAAe,sBAAsB,QAAQ,KAAK,WAAW,MAAM,eAAe,oBAAoB,QAAQ,MAAM,eAAe,kBAAkB,SAAS,MAAM,eAAe,YAAY,kBAAkB,MAAM,eAAe,qBAAqB,WAAW,MAAM,eAAe,6BAA6B,OAAO,MAAM,eAAe,QACvjB;AAEF,SAAK,MAAM,QAAQ,MAAM,MAAM,MAAM,GAAG,EAAE,CACzC,GAAE,IAAI,QACL,QAAQ,KAAK,GAAG,KAAK,KAAK,KAAK,GAAG,KAAK,KAAK,GAAG,KAAK,QAAQ,GAAG,KAAK,cAAc,GAAG,KAAK,oBAAoB,IAAI,KAAK,MAAM,KAAK,KAAK,cACvI;;;AAIJ,IAAE,MAAM,OAAO;GAEhB;AACD,QAAO;;AAGR,SAAS,iCAA0C;CAClD,MAAM,MAAM,IAAI,QAAQ,eAAe,CACrC,cAAc,UAAU,CACxB,YAAY,yEAAyE,CACrF,SAAS,iBAAiB,gCAAgC,CAC1D,SAAS,kBAAkB,iCAAiC,CAC5D,OAAO,uBAAuB,iDAAiD,CAC/E,OAAO,kBAAkB,8BAA8B,CACvD,OACA,mBACA,uDACC,OAAO,SAAmB,CAAC,GAAG,MAAM,MAAM,EAC3C,EAAE,CACF,CACA,OACA,mBACA,qEACC,OAAO,SAAmB,CAAC,GAAG,MAAM,MAAM,EAC3C,EAAE,CACF,CACA,OAAO,cAAc,4BAA4B;AACnD,eAAc,IAAI;AAClB,KAAI,QAEF,YACA,aACA,SAOI;EACJ,MAAM,UACL,KAAK,gBAAgB,OAClB,OACA,KAAK,SAAS,MAAM,IACrB,QAAQ,IAAI,iBAAiB,MAAM,IACnC,eAAe,QAAQ,KAAK,EAAE,KAAK;EACtC,MAAM,mBAAmB,KAAK,YAAY,EAAE,EAAE,MAC5C,OAAO,6BAA6B,GAAG,IAAI,KAC5C;AACD,MAAI,gBACH,OAAM,IAAI,MAAM,+BAA+B,kBAAkB;EAElE,MAAM,SAAS,CACd,GAAI,KAAK,SAAS,EAAE,EACpB,GAAG,gCAAgC,KAAK,YAAY,EAAE,CAAC,CACvD;EACD,MAAM,SAAS,yBAAyB,YAAY,aAAa;GAChE;GACA,aAAa,KAAK,gBAAgB;GAClC,iBAAiB,KAAK,aAAa;GACnC;GACA,CAAC;AAEF,MAAI,KAAK,MAAM;AACd,WAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;AAGD,IAAE,MAAM,8BAA8B;AACtC,IAAE,IAAI,KACL;GACC,sBAAsB,OAAO,SAAS,OAAO;GAC7C,uBAAuB,OAAO,UAAU,OAAO;GAC/C,mBAAmB,OAAO,MAAM,OAAO;GACvC,iBAAiB,OAAO,MAAM,kBAAkB;GAChD,mBAAmB,OAAO,MAAM,kBAAkB;GAClD,yBAAyB,OAAO,MAAM,gBAAgB;GACtD,2BAA2B,OAAO,MAAM,gBAAgB;GACxD,CAAC,KAAK,KAAK,CACZ;AACD,IAAE,IAAI,KAAK,eAAe;AAC1B,OAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,OAAO,MAAM,eAAe,CACtE,GAAE,IAAI,QAAQ,KAAK,KAAK,OAAO,GAAG,CAAC,GAAG,OAAO,MAAM,GAAG;AAEvD,IAAE,IAAI,KAAK,wBAAwB;AACnC,OAAK,MAAM,CAAC,QAAQ,UAAU,OAAO,QAAQ,OAAO,MAAM,sBAAsB,CAC/E,GAAE,IAAI,QAAQ,KAAK,OAAO,OAAO,GAAG,CAAC,GAAG,OAAO,MAAM,GAAG;AAEzD,IAAE,IAAI,KAAK,8BAA8B;AACzC,OAAK,MAAM,CAAC,QAAQ,UAAU,OAAO,QAAQ,OAAO,MAAM,4BAA4B,CACrF,GAAE,IAAI,QAAQ,KAAK,OAAO,OAAO,GAAG,CAAC,GAAG,OAAO,MAAM,GAAG;AAEzD,MAAI,OAAO,kBAAkB,SAAS,GAAG;AACxC,KAAE,IAAI,KAAK,qBAAqB;AAChC,QAAK,MAAM,SAAS,OAAO,mBAAmB;AAC7C,MAAE,IAAI,QAAQ,YAAY,MAAM,QAAQ;AACxC,MAAE,IAAI,QACL,uBAAuB,MAAM,iBAAiB,IAAI,aAAa,MAAM,kBAAkB,MACvF;AACD,MAAE,IAAI,QACL,gCAAgC,MAAM,iBAAiB,OAAO,gBAAgB,MAAM,kBAAkB,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI,IAAI,IAAI,iBAAiB,MAAM,mBAAmB,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI,IAAI,MACtM;AACD,QAAI,MAAM,iBACT,GAAE,IAAI,QACL,iCAAiC,MAAM,iBAAiB,YAAY,QAAQ,EAAE,CAAC,kBAAkB,MAAM,iBAAiB,eAAe,QAAQ,EAAE,CAAC,wBAAwB,MAAM,iBAAiB,qBAAqB,QAAQ,EAAE,GAChO;AAEF,QAAI,MAAM,yBACT,GAAE,IAAI,QACL,6BAA6B,MAAM,yBAAyB,OAAO,YAAY,MAAM,yBAAyB,WAC9G;AAEF,QAAI,MAAM,2BAA2B,MAAM,yBAC1C,GAAE,IAAI,QACL,iCAAiC,MAAM,yBAAyB,SAAS,IAAI,aAAa,MAAM,0BAA0B,SAAS,MACnI;AAEF,QAAI,MAAM,qBACT,GAAE,IAAI,QACL,kCAAkC,MAAM,qBAAqB,cAAc,IAAI,gBAAgB,MAAM,qBAAqB,mBAAmB,IAAI,gBAAgB,MAAM,qBAAqB,yBAAyB,IAAI,aAAa,MAAM,qBAAqB,uBAAuB,IAAI,WAAW,MAAM,qBAAqB,uBAAuB,IAAI,QAAQ,MAAM,qBAAqB,qBAAqB,IAAI,SAAS,MAAM,qBAAqB,eAAe,IAAI,kBAAkB,MAAM,qBAAqB,wBAAwB,IAAI,WAAW,MAAM,qBAAqB,gCAAgC,IAAI,OAAO,MAAM,qBAAqB,SAAS,MAC9oB;;;AAIJ,IAAE,MAAM,OAAO;GAEhB;AACD,QAAO;;AAGR,SAAS,sCAA+C;CACvD,MAAM,MAAM,IAAI,QAAQ,oBAAoB,CAC1C,cAAc,UAAU,CACxB,YAAY,mFAAmF,CAC/F,OAAO,qBAAqB,yBAAyB,CACrD,OAAO,mBAAmB,uCAAuC,CACjE,eAAe,mBAAmB,uCAAuC,CACzE,OAAO,cAAc,4BAA4B;AACnD,aAAY,IAAI;AAChB,eAAc,IAAI;AAClB,KAAI,QAEF,SAOI;EACJ,MAAM,iBAAiB,KAAK,WAAW,MAAM,IAAI;EACjD,MAAM,eAAe,KAAK,SAAS,MAAM,IAAI;EAC7C,MAAM,eAAe,eAAe,SAAS;EAC7C,MAAM,aAAa,aAAa,SAAS;AACzC,MAAI,iBAAiB,WACpB,OAAM,IAAI,MAAM,oDAAoD;EAErE,MAAM,YAAY,eAAe,sBAAsB,eAAe,GAAG;AACzE,MAAI,gBAAgB,cAAc,KACjC,OAAM,IAAI,MAAM,uBAAuB,kBAAkB,KAAK,YAAY;EAE3E,MAAM,UAAU,aAAa,sBAAsB,aAAa,GAAG;AACnE,MAAI,cAAc,YAAY,KAC7B,OAAM,IAAI,MAAM,qBAAqB,gBAAgB,KAAK,UAAU;EAErE,MAAM,aAAa,KAAK,UAAU,MAAM,IAAI;EAC5C,MAAM,WAAW,iCAAiC,WAAW;AAC7D,MAAI,CAAC,SACJ,OAAM,IAAI,MAAM,qCAAqC,cAAc,KAAK,WAAW;EAEpF,MAAM,SACL,WAAW,OACR,yBAAyB,aAAa,KAAK,EAAE;GAC7C;GACA,YAAY,SAAS;GACrB,iBAAiB,KAAK,aAAa;GACnC,CAAC,GACD,yBAAyB,aAAa,KAAK,EAAE;GAClC;GACX,YAAY,SAAS;GACrB,iBAAiB,KAAK,aAAa;GACnC,CAAC;AAEL,MAAI,KAAK,MAAM;AACd,WAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;AAGD,IAAE,MAAM,mCAAmC;AAC3C,IAAE,IAAI,KACL;GACC,aAAa,OAAO,SAAS,GAAG,KAAK,OAAO,SAAS;GACrD,WAAW,OAAO,OAAO,OAAO,OAAO,OAAO,WAAW,OAAO,KAAK,OAAO,OAAO,YAAY;GAC/F,YAAY,OAAO,QAAQ,GAAG,IAAI,OAAO,QAAQ,WAAW,aAAa;GACzE,kBAAkB,OAAO,QAAQ;GACjC,wBAAwB,OAAO,QAAQ;GACvC,CAAC,KAAK,KAAK,CACZ;AACD,IAAE,IAAI,KACL;GACC,SAAS,OAAO,OAAO,QAAQ;GAC/B,kBAAkB,OAAO,OAAO;GAChC,sBAAsB,OAAO,OAAO;GACpC,4BAA4B,OAAO,SAAS;GAC5C,gCAAgC,OAAO,SAAS;GAChD,0BAA0B,OAAO,SAAS;GAC1C,kCAAkC,OAAO,SAAS;GAClD,CAAC,KAAK,KAAK,CACZ;AACD,MAAI,OAAO,eAAe,SAAS,GAAG;AACrC,KAAE,IAAI,KAAK,mBAAmB;AAC9B,QAAK,MAAM,UAAU,OAAO,eAC3B,GAAE,IAAI,QAAQ,OAAO,SAAS;;AAGhC,IAAE,IAAI,KAAK,mBAAmB;AAC9B,OAAK,MAAM,UAAU,OAAO,QAC3B,GAAE,IAAI,QACL,KAAK,OAAO,GAAG,OAAO,GAAG,CAAC,WAAW,OAAO,eAAe,QAAQ,KAAK,gBAAgB,OAAO,mBAAmB,QAAQ,OAC1H;AAEF,IAAE,MAAM,OAAO;GAEhB;AACD,QAAO;;AAGR,SAAS,sCAA+C;CACvD,MAAM,MAAM,IAAI,QAAQ,oBAAoB,CAC1C,cAAc,UAAU,CACxB,YACA,kGACA,CACA,eAAe,mBAAmB,qCAAqC,CACvE,OACA,+BACA,gEACA,CACA,OAAO,2BAA2B,yDAAyD,CAC3F,OAAO,kCAAkC,gDAAgD,CACzF,OAAO,sBAAsB,2CAA2C,CACxE,OACA,8BACA,+DACA,CACA,OACA,8BACA,gEACA,CACA,OACA,2BACA,qEACA,CACA,eAAe,mBAAmB,uCAAuC;AAC3E,aAAY,IAAI;AAChB,eAAc,IAAI;AAClB,KAAI,OACH,OACC,SAYI;EACJ,MAAM,eAAe,KAAK,SAAS,MAAM,IAAI;EAC7C,MAAM,UAAU,sBAAsB,aAAa;AACnD,MAAI,YAAY,KACf,OAAM,IAAI,MAAM,qBAAqB,gBAAgB,KAAK,UAAU;EAErE,MAAM,aAAa,KAAK,UAAU,MAAM,IAAI;EAC5C,MAAM,WAAW,iCAAiC,WAAW;AAC7D,MAAI,CAAC,SACJ,OAAM,IAAI,MAAM,qCAAqC,cAAc,KAAK,WAAW;EAEpF,MAAM,wBAAwB,KAAK,kBAAkB,MAAM,IAAI;EAC/D,MAAM,mBACL,sBAAsB,SAAS,IAAI,sBAAsB,sBAAsB,GAAG;AACnF,MAAI,sBAAsB,SAAS,KAAK,qBAAqB,KAC5D,OAAM,IAAI,MACT,8BAA8B,yBAAyB,KAAK,mBAC5D;EAEF,MAAM,2BAA2B,KAAK,qBAAqB,MAAM,IAAI;EACrE,IAAI;AACJ,MAAI,yBAAyB,SAAS,GAAG;GACxC,MAAM,SAAS,OAAO,yBAAyB;AAC/C,OAAI,CAAC,OAAO,SAAS,OAAO,CAC3B,OAAM,IAAI,MACT,iCAAiC,4BAA4B,KAAK,sBAClE;AAEF,yBAAsB;;EAEvB,MAAM,uBAAuB,KAAK,iBAAiB,MAAM,IAAI;EAC7D,MAAM,kBACL,qBAAqB,SAAS,IAAI,sBAAsB,qBAAqB,GAAG;AACjF,MAAI,qBAAqB,SAAS,KAAK,oBAAoB,KAC1D,OAAM,IAAI,MACT,8BAA8B,wBAAwB,KAAK,kBAC3D;EAEF,MAAM,iBAAiB,oBAAoB;EAC3C,MAAM,8BAA8B;GACnC,GAAG;GACH,qBAAqB,uBAAuB,eAAe;GAC3D,4BAA4B,KAAK,oBAAoB;GACrD,yBAAyB,KAAK,iBAAiB,MAAM,IAAI;GACzD,0BAA0B,KAAK,kBAAkB,MAAM,IAAI;GAC3D,yBAAyB,mBAAmB,eAAe;GAC3D;EACD,MAAM,WAAW,IAAI,eAAe,4BAA4B;EAChE,MAAM,SACL,KAAK,wBAAwB,OAC1B,MAAM,qCACN,aAAa,KAAK,EAClB,6BACA;GACC;GACA,YAAY,SAAS;GACrB,kBAAkB,oBAAoB,KAAA;GACtC,CACD,GACA,MAAM,sBAAsB,aAAa,KAAK,EAAE,UAAU;GAC1D;GACA,YAAY,SAAS;GACrB,kBAAkB,oBAAoB,KAAA;GACtC,CAAC;AAEL,MAAI,KAAK,MAAM;AACd,WAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;AAGD,IAAE,MAAM,mCAAmC;AAC3C,IAAE,IAAI,KACL;GACC,aAAa,OAAO,SAAS,GAAG,KAAK,OAAO,SAAS;GACrD,UAAU,OAAO,OAAO;GACxB,YAAY,OAAO,OAAO;GAC1B,aAAa,OAAO,SAAS,SAAS,GAAG,OAAO,SAAS;GACzD,SAAS,OAAO,SAAS,QAAQ;GACjC,qBAAqB,OAAO,SAAS,qBAAqB,QAAQ;GAClE,qBAAqB,OAAO,SAAS,mBAAmB;GACxD,mBAAmB,OAAO,eAAe;GACzC,SAAS,OAAO,WAAW,OAAO,QAAQ;GAC1C,CAAC,KAAK,KAAK,CACZ;AACD,MAAI,OAAO,eAAe,OACzB,GAAE,IAAI,QAAQ,0BAA0B,OAAO,eAAe,SAAS;AAExE,MAAI,OAAO,WAAW,eAAe,SAAS,GAAG;AAChD,KAAE,IAAI,KAAK,mBAAmB;AAC9B,QAAK,MAAM,UAAU,OAAO,WAAW,eACtC,GAAE,IAAI,QAAQ,OAAO,SAAS;;AAGhC,IAAE,IAAI,KACL;GACC,oBAAoB,OAAO,WAAW,OAAO;GAC7C,uBAAuB,OAAO,WAAW,OAAO;GAChD,4BAA4B,OAAO,WAAW,SAAS;GACvD,gCAAgC,OAAO,WAAW,SAAS;GAC3D,0BAA0B,OAAO,WAAW,SAAS;GACrD,CAAC,KAAK,KAAK,CACZ;AACD,IAAE,MAAM,OAAO;GAEhB;AACD,QAAO;;AAGR,SAAS,yCAAkD;CAC1D,MAAM,MAAM,IAAI,QAAQ,uBAAuB,CAC7C,cAAc,UAAU,CACxB,YACA,qFACA,CACA,eAAe,oBAAoB,uBAAuB,CAC1D,OAAO,kCAAkC,oDAAoD,CAC7F,OAAO,4BAA4B,iDAAiD,CACpF,OAAO,2BAA2B,yDAAyD,CAC3F,OAAO,sBAAsB,kDAAkD,CAC/E,OACA,8BACA,sEACA,CACA,OACA,8BACA,uEACA,CACA,OACA,2BACA,4EACA,CACA,OACA,kCACA,uDACA,CACA,OACA,+BACA,yEACA;AACF,aAAY,IAAI;AAChB,eAAc,IAAI;AAClB,KAAI,OACH,OACC,SAaI;EACJ,MAAM,cAAc,KAAK,WAAW,MAAM,IAAI;EAC9C,MAAM,YAAY,8BAA8B,YAAY;AAC5D,MAAI,CAAC,UACJ,OAAM,IAAI,MAAM,iCAAiC,eAAe,KAAK,YAAY;EAElF,MAAM,wBAAwB,KAAK,kBAAkB,MAAM,IAAI;EAC/D,MAAM,mBACL,sBAAsB,SAAS,IAAI,sBAAsB,sBAAsB,GAAG;AACnF,MAAI,sBAAsB,SAAS,KAAK,qBAAqB,KAC5D,OAAM,IAAI,MACT,8BAA8B,yBAAyB,KAAK,mBAC5D;EAEF,MAAM,2BAA2B,KAAK,qBAAqB,MAAM,IAAI;EACrE,IAAI;AACJ,MAAI,yBAAyB,SAAS,GAAG;GACxC,MAAM,SAAS,OAAO,yBAAyB;AAC/C,OAAI,CAAC,OAAO,SAAS,OAAO,CAC3B,OAAM,IAAI,MACT,iCAAiC,4BAA4B,KAAK,sBAClE;AAEF,yBAAsB;;EAEvB,MAAM,uBAAuB,KAAK,iBAAiB,MAAM,IAAI;EAC7D,MAAM,kBACL,qBAAqB,SAAS,IAAI,sBAAsB,qBAAqB,GAAG;AACjF,MAAI,qBAAqB,SAAS,KAAK,oBAAoB,KAC1D,OAAM,IAAI,MACT,8BAA8B,wBAAwB,KAAK,kBAC3D;EAEF,MAAM,iBAAiB,oBAAoB;EAC3C,MAAM,8BAA8B;GACnC,GAAG;GACH,kBAAkB,KAAK,kBAAkB,MAAM,IAAI,eAAe;GAClE,eAAe,KAAK,eAAe,MAAM,IAAI,eAAe;GAC5D,qBAAqB,uBAAuB,eAAe;GAC3D,4BAA4B,KAAK,oBAAoB;GACrD,yBAAyB,KAAK,iBAAiB,MAAM,IAAI;GACzD,0BAA0B,KAAK,kBAAkB,MAAM,IAAI;GAC3D,yBAAyB,mBAAmB,eAAe;GAC3D;EACD,MAAM,WAAW,IAAI,eAAe,4BAA4B;EAChE,MAAM,OAAO,EAAE;AA4Bf,OAAK,MAAM,SAAS,UAAU,SAAS;GACtC,MAAM,aAAa,MAAM,cAAc,UAAU;GACjD,MAAM,SACL,KAAK,wBAAwB,OAC1B,MAAM,qCACN,aAAa,KAAK,EAClB,6BACA;IACC,SAAS,MAAM;IACf;IACA,kBAAkB,oBAAoB,KAAA;IACtC,CACD,GACA,MAAM,sBAAsB,aAAa,KAAK,EAAE,UAAU;IAC1D,SAAS,MAAM;IACf;IACA,kBAAkB,oBAAoB,KAAA;IACtC,CAAC;AACL,QAAK,KAAK;IACT,SAAS,MAAM;IACf,WAAW,MAAM;IACjB,OAAO,MAAM;IACb,SAAS,MAAM;IACf,YAAY,MAAM;IAClB;IACA,cAAc,MAAM,gBAAgB;IACpC,UAAU;KACT,WAAW,OAAO,SAAS;KAC3B,aAAa,OAAO,SAAS;KAC7B,WAAW,OAAO,SAAS;KAC3B,kBAAkB,OAAO,SAAS;KAClC;IACD,QAAQ,OAAO,eAAe;IAC9B,QAAQ,OAAO,eAAe;IAC9B,MAAM,OAAO,SAAS,QAAQ;IAC9B,UAAU,OAAO,SAAS;IAC1B,OAAO,OAAO,SAAS;IACvB,oBAAoB,OAAO,SAAS;IACpC,iBAAiB,OAAO,SAAS;IACjC,kBAAkB,OAAO,SAAS;IAClC,iBAAiB,OAAO,SAAS;IACjC,aAAa,OAAO,SAAS;IAC7B,WAAW,OAAO,WAAW,OAAO;IACpC,cAAc,OAAO,WAAW,OAAO;IACvC,eAAe,OAAO,SAAS;IAC/B,CAAC;;EAEH,MAAM,UAAU;GACf,OAAO,KAAK;GACZ,mBAAmB,KAAK,QAAQ,QAAQ,IAAI,YAAY,gBAAgB,CAAC;GACzE,oBAAoB,KAAK,QACvB,QAAQ,IAAI,YAAY,mBAAmB,IAAI,WAAW,OAC3D,CAAC;GACF,mBAAmB,KAAK,QACtB,QAAQ,IAAI,YAAY,mBAAmB,IAAI,WAAW,aAC3D,CAAC;GACF,mBAAmB,KAAK,QAAQ,QAAQ,IAAI,gBAAgB,KAAK,CAAC;GAClE,qBAAqB,KAAK,QACxB,QAAQ,IAAI,gBAAgB,QAAQ,IAAI,iBAAiB,IAAI,KAC9D,CAAC;GACF,oBAAoB,KAAK,QAAQ,QAAQ,IAAI,WAAW,qBAAqB,CAAC;GAC9E;EACD,MAAM,qBAAqB,MAAM,KAChC,IAAI,IACH,KAAK,KACH,QACA,GAAG,IAAI,SAAS,IAAI,IAAI,MAAM,IAAI,IAAI,qBAAqB,cAAc,SAC1E,CACD,CACD;EACD,MAAM,kBACL,KAAK,wBAAwB,OAC1B;GACA,UACC,mBAAmB,WAAW,IAC1B,KAAK,IAAI,YAAY,SAAS,WAC/B;GACJ,OAAO,mBAAmB,WAAW,IAAK,KAAK,IAAI,SAAS,SAAS,QAAS;GAC9E,aAAa;GACb,oBACC,mBAAmB,WAAW,IAC1B,KAAK,IAAI,sBAAsB,SAAS,qBACzC;GACJ,iBACC,mBAAmB,WAAW,IAC1B,KAAK,IAAI,mBAAmB,SAAS,kBACtC;GACJ,kBACC,mBAAmB,WAAW,IAC1B,KAAK,IAAI,oBAAoB,SAAS,mBACvC;GACJ,iBACC,mBAAmB,WAAW,IAC1B,KAAK,IAAI,mBAAmB,SAAS,kBACtC;GACJ,aACC,mBAAmB,WAAW,IAC1B,KAAK,IAAI,eAAe,SAAS,cAClC;GACJ,kBAAkB,oBAAoB;GACtC,mBAAmB;GACnB,GACA;GACA,UAAU,SAAS;GACnB,OAAO,SAAS;GAChB,aAAa;GACb,oBAAoB,SAAS;GAC7B,iBAAiB,SAAS;GAC1B,kBAAkB,SAAS;GAC3B,iBAAiB,SAAS;GAC1B,aAAa,SAAS;GACtB,kBAAkB,oBAAoB;GACtC,mBAAmB;GACnB;EACJ,MAAM,SAAS;GACd,WAAW;IACV,IAAI,UAAU;IACd,OAAO,UAAU;IACjB,YAAY,UAAU;IACtB;GACD,UAAU;GACV;GACA;GACA;AAED,MAAI,KAAK,MAAM;AACd,WAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;AAGD,IAAE,MAAM,sCAAsC;AAC9C,IAAE,IAAI,KACL;GACC,cAAc,UAAU,GAAG,KAAK,UAAU;GAC1C,aAAa,gBAAgB,SAAS,GAAG,gBAAgB;GACzD,iBAAiB,KAAK,wBAAwB,OAAO,QAAQ;GAC7D,qBAAqB,gBAAgB,uBAAuB,OAAO,UAAU,gBAAgB,qBAAqB,QAAQ;GAC1H,qBAAqB,gBAAgB,mBAAmB;GACxD,sBAAsB,gBAAgB,oBAAoB;GAC1D,sBAAsB,gBAAgB,mBAAmB;GACzD,gBAAgB,gBAAgB,eAAe;GAC/C,+BAA+B,oBAAoB;GACnD,yBAAyB,QAAQ,mBAAmB,GAAG,QAAQ;GAC/D,wBAAwB,QAAQ;GAChC,0BAA0B,QAAQ,oBAAoB,GAAG,QAAQ;GACjE,6BAA6B,QAAQ;GACrC,CAAC,KAAK,KAAK,CACZ;AACD,OAAK,MAAM,OAAO,KACjB,GAAE,IAAI,QACL,MAAM,IAAI,QAAQ,IAAI,IAAI,OAAO,OAAO,GAAG,CAAC,GAAG,IAAI,WAAW,OAAO,GAAG,CAAC,QAAQ,IAAI,KAAK,OAAO,EAAE,CAAC,aAAa,IAAI,gBAAgB,OAAO,OAAO,EAAE,CAAC,QAAQ,OAAO,IAAI,SAAS,UAAU,CAAC,OAAO,EAAE,CAAC,WAAW,IAAI,SAAS,YAAY,SAAS,OAAO,IAAI,SAAS,UAAU,CAAC,OAAO,EAAE,CAAC,cAAc,IAAI,SAAS,iBAAiB,GAAG,IAAI,SAAS,GAAG,IAAI,QAAQ,IAAI,qBAAqB,iBAAiB,GAAG,aAAa,IAAI,UAAU,gBAAgB,IAAI,aAAa,UAAU,IAAI,gBAAgB,QAAQ,KAAK,KAAK,IAAI,QACrgB;AAEF,IAAE,MAAM,OAAO;GAEhB;AACD,QAAO;;AAGR,SAAS,kCAA2C;CACnD,MAAM,MAAM,IAAI,QAAQ,gBAAgB,CACtC,cAAc,UAAU,CACxB,YAAY,2EAA2E,CACvF,OAAO,uBAAuB,iDAAiD,CAC/E,OAAO,kBAAkB,8BAA8B,CACvD,OAAO,eAAe,uBAAuB,KAAK;AACpD,aAAY,IAAI;AAChB,eAAc,IAAI;AAClB,KAAI,QAEF,SAMI;EACJ,MAAM,UACL,KAAK,gBAAgB,OAClB,OACA,KAAK,SAAS,MAAM,IACrB,QAAQ,IAAI,iBAAiB,MAAM,IACnC,eAAe,QAAQ,KAAK,EAAE,KAAK;EACtC,MAAM,QAAQ,OAAO,SAAS,KAAK,SAAS,MAAM,GAAG,IAAI;EACzD,MAAM,SAAS,wBAAwB,aAAa,KAAK,EAAE;GAC1D;GACA,aAAa,KAAK,gBAAgB;GAClC;GACA,CAAC;AAEF,MAAI,KAAK,MAAM;AACd,WAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;AAGD,IAAE,MAAM,+BAA+B;AACvC,IAAE,IAAI,KACL;GACC,yBAAyB,OAAO,OAAO;GACvC,wBAAwB,OAAO,OAAO;GACtC,kCAAkC,OAAO,OAAO;GAChD,+BAA+B,OAAO,OAAO;GAC7C,kCAAkC,OAAO,OAAO;GAChD,8BAA8B,OAAO,OAAO;GAC5C,gCAAgC,OAAO,OAAO;GAC9C,CAAC,KAAK,KAAK,CACZ;AACD,IAAE,IAAI,KAAK,qBAAqB;AAChC,OAAK,MAAM,SAAS,OAAO,OAC1B,GAAE,IAAI,QACL,KAAK,MAAM,UAAU,gBAAgB,MAAM,qBAAqB,WAAW,MAAM,eAAe,UAAU,MAAM,gBAAgB,YAAY,MAAM,kBAAkB,UAAU,MAAM,gBAAgB,eAAe,MAAM,8BACzN;AAEF,IAAE,MAAM,OAAO;GAEhB;AACD,QAAO;;AAGR,SAAS,gCAAyC;CACjD,MAAM,MAAM,IAAI,QAAQ,cAAc,CACpC,cAAc,UAAU,CACxB,YAAY,oDAAoD,CAChE,OAAO,uBAAuB,iDAAiD,CAC/E,OAAO,kBAAkB,8BAA8B,CACvD,OAAO,eAAe,yBAAyB,KAAK;AACtD,aAAY,IAAI;AAChB,eAAc,IAAI;AAClB,KAAI,QAEF,SAMI;EACJ,MAAM,UACL,KAAK,gBAAgB,OAClB,OACA,KAAK,SAAS,MAAM,IACrB,QAAQ,IAAI,iBAAiB,MAAM,IACnC,eAAe,QAAQ,KAAK,EAAE,KAAK;EACtC,MAAM,QAAQ,OAAO,SAAS,KAAK,SAAS,MAAM,GAAG,IAAI;EACzD,MAAM,SAAS,sBAAsB,aAAa,KAAK,EAAE;GACxD;GACA,aAAa,KAAK,gBAAgB;GAClC;GACA,CAAC;AAEF,MAAI,KAAK,MAAM;AACd,WAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;AAGD,IAAE,MAAM,6BAA6B;AACrC,IAAE,IAAI,KACL;GACC,WAAW,OAAO,OAAO;GACzB,oBAAoB,OAAO,OAAO;GAClC,mBAAmB,OAAO,OAAO;GACjC,YAAY,OAAO,OAAO;GAC1B,qBAAqB,OAAO,OAAO;GACnC,oBAAoB,OAAO,OAAO;GAClC,wBAAwB,OAAO,OAAO;GACtC,CAAC,KAAK,KAAK,CACZ;AACD,IAAE,IAAI,KAAK,mBAAmB;AAC9B,OAAK,MAAM,UAAU,OAAO,QAAQ,MAAM,GAAG,GAAG,CAC/C,GAAE,IAAI,QACL,KAAK,OAAO,OAAO,GAAG,OAAO,UAAU,gBAAgB,OAAO,qBAAqB,cAAc,OAAO,YAAY,KAAK,IAAI,IAAI,IAAI,YAAY,OAAO,aAAa,UAAU,OAAO,SACtL;AAEF,MAAI,OAAO,eAAe,SAAS,GAAG;AACrC,KAAE,IAAI,KAAK,kBAAkB;AAC7B,QAAK,MAAM,SAAS,OAAO,eAAe,MAAM,GAAG,GAAG,CACrD,GAAE,IAAI,QAAQ,KAAK,MAAM,UAAU,cAAc,MAAM,SAAS,KAAK,IAAI,GAAG;;AAG9E,IAAE,MAAM,OAAO;GAEhB;AACD,QAAO;;AAGR,IAAa,oBAAoB,yBAAyB;AAC1D,IAAa,sBAAsB,2BAA2B;AAC9D,IAAa,wBAAwB,6BAA6B;AAElE,IAAa,gBAAgB,IAAI,QAAQ,SAAS,CAChD,cAAc,UAAU,CACxB,YAAY,yBAAyB;AAEvC,cAAc,WAAW,yBAAyB,CAAC;AACnD,cAAc,WAAW,2BAA2B,CAAC;AACrD,cAAc,WAAW,6BAA6B,CAAC;AACvD,cAAc,WAAW,2BAA2B,CAAC;AACrD,cAAc,WAAW,+BAA+B,CAAC;AACzD,cAAc,WAAW,gCAAgC,CAAC;AAC1D,cAAc,WAAW,qCAAqC,CAAC;AAC/D,cAAc,WAAW,qCAAqC,CAAC;AAC/D,cAAc,WAAW,wCAAwC,CAAC;AAClE,cAAc,WAAW,iCAAiC,CAAC;AAC3D,cAAc,WAAW,+BAA+B,CAAC;;;AChoCzD,SAAS,kBAAkB,WAAmE;CAC7F,MAAM,aAAa;EAClB,UAAU,OAAO,kBAAkB,OAChC,YAAY,UAAU,OAAO,eAAe,QAAQ,EAAE,KACtD;EACH,UAAU,OAAO,cAAc,OAAO,QAAQ,UAAU,OAAO,WAAW,QAAQ,EAAE,KAAK;EACzF,UAAU,OAAO,eAAe,IAAI,QAAQ,UAAU,OAAO,iBAAiB;EAC9E,UAAU,OAAO,cAAc,IAAI,OAAO,UAAU,OAAO,gBAAgB;EAC3E,UAAU,OAAO,sBAAsB,IACpC,eAAe,UAAU,OAAO,oBAAoB,QAAQ,EAAE,KAC9D;EACH,CACC,OAAO,QAAQ,CACf,KAAK,IAAI;CAEX,MAAM,QAAQ,CAAC,GAAG,UAAU,KAAK,KAAK,UAAU,GAAG,KAAK,UAAU,KAAK,IAAI,UAAU,QAAQ;AAC7F,KAAI,UAAU,QAAS,OAAM,KAAK,iBAAiB,UAAU,UAAU;AACvE,KAAI,UAAU,QAAQ,SAAS,EAAG,OAAM,KAAK,iBAAiB,UAAU,QAAQ,KAAK,KAAK,GAAG;AAC7F,KAAI,WAAY,OAAM,KAAK,gBAAgB,aAAa;AACxD,KAAI,UAAU,QAAS,OAAM,KAAK,iBAAiB,UAAU,UAAU;AACvE,QAAO;;AAGR,SAAgB,gBAAgB,OAA0B;CACzD,MAAM,aACL,MAAM,OAAO,kBAAkB,SAAS,IACrC,MAAM,OAAO,kBAAkB,KAAK,KAAK,GACzC;CACJ,MAAM,QAAQ;EACb;EACA,YAAY,MAAM,OAAO;EACzB,cAAc,MAAM,OAAO,WAAW;EACtC,kBAAkB;EAClB,WAAW,MAAM,KAAK;EACtB,mBAAmB,MAAM,KAAK,QAAQ,KAAK,KAAK,IAAI;EACpD,mBAAmB,MAAM,OAAO,gBAAgB;EAChD;EACA;AAED,MAAK,MAAM,eAAe;EAAC;EAAY;EAAW;EAAW;EAAU,EAAW;EACjF,MAAM,QAAQ,MAAM,UAAU,WAAW,QACvC,cAAc,UAAU,gBAAgB,YACzC;AACD,MAAI,MAAM,WAAW,EAAG;AACxB,QAAM,KAAK,YAAY,OAAO,EAAE,CAAC,aAAa,GAAG,YAAY,MAAM,EAAE,CAAC;AACtE,OAAK,MAAM,aAAa,MACvB,OAAM,KAAK,GAAG,kBAAkB,UAAU,CAAC;AAE5C,QAAM,KAAK,GAAG;;AAGf,OAAM,KAAK,WAAW;AACtB,OAAM,KAAK,kBAAkB,MAAM,SAAS,YAAY,KAAK,KAAK,IAAI,WAAW;AACjF,OAAM,KAAK,kBAAkB,MAAM,SAAS,YAAY,KAAK,KAAK,IAAI,WAAW;AACjF,OAAM,KAAK,mBAAmB,MAAM,SAAS,aAAa,KAAK,KAAK,IAAI,WAAW;AACnF,OAAM,KACL,6BAA6B,MAAM,OAAO,eAAe,QAAQ,YAAY,MAAM,OAAO,eAAe,SAAS,gBAAgB,MAAM,OAAO,eAAe,eAC9J;AACD,OAAM,KAAK,uBAAuB,MAAM,OAAO,mBAAmB;AAClE,OAAM,KAAK,gBAAgB,MAAM,OAAO,YAAY,QAAQ,OAAO;AACnE,OAAM,KAAK,GAAG;AACd,OAAM,KAAK,aAAa;AACxB,OAAM,KAAK,MAAM,OAAO,UAAU;AAClC,QAAO,MAAM,KAAK,KAAK;;AAGxB,eAAe,UACd,MACA,WACA,KACgB;CAChB,IAAI,QAA4B;AAChC,KAAI;AACH,UAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAC1D,QAAM,IAAI,MAAM;UACR,OAAO;EACf,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;EACtE,MAAM,aAAa,iBAAiB;AACpC,MAAI,KAAK,MAAM;AACd,iBAAc,aAAa,gBAAgB,WAAW,SAAS,aAAa,IAAI,EAAE;AAClF;;AAED,IAAE,IAAI,MAAM,QAAQ;AACpB,UAAQ,WAAW,aAAa,IAAI;WAC3B;AACT,SAAO,OAAO;;;AAIhB,eAAe,WAAW,SAAiB,MAAyC;AACnF,OAAM,UAAU,MAAM,eAAe,OAAO,UAAU;EACrD,MAAM,EAAE,OAAO,QAAQ,SAAS,kBAAkB,wBAAwB,MAAM,EAC/E,YAAY,QAAQ,IAAI,iBACxB,CAAC;EACF,MAAM,SAAS,MAAM,MAAM,qBAAqB,SAAS,OAAO,QAAQ,SAAS,cAAc;AAE/F,MAAI,KAAK,MAAM;AACd,WAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;AAGD,IAAE,MAAM,oBAAoB,QAAQ,GAAG;AAEvC,MAAI,OAAO,MAAM,WAAW,GAAG;AAC9B,KAAE,IAAI,KAAK,8BAA8B;AACzC,KAAE,MAAM,OAAO;AACf;;EAGD,MAAM,UAAU,OAAO;AACvB,IAAE,IAAI,KACL,GAAG,QAAQ,YAAY,WAAW,QAAQ,YAAY,YACpD,QAAQ,gBAAgB,gBAAgB,MACzC,UAAU,QAAQ,QAAQ,IAAI,OAAO,QAAQ,QAAQ,SAAS,SAAS,QAAQ,QAAQ,MAAM,GAC9F;AAED,OAAK,MAAM,QAAQ,OAAO,MACzB,GAAE,IAAI,KAAK,IAAI,KAAK,GAAG,IAAI,KAAK,KAAK,IAAI,KAAK,QAAQ;AAGvD,IAAE,KAAK,OAAO,WAAW,YAAY;AACrC,IAAE,MAAM,OAAO;GACd;;AAGH,eAAe,YAAY,SAAiB,MAAyC;AACpF,OAAM,UAAU,MAAM,qBAAqB,OAAO,UAAU;EAC3D,MAAM,EAAE,OAAO,QAAQ,SAAS,kBAAkB,wBAAwB,MAAM,EAC/E,YAAY,QAAQ,IAAI,iBACxB,CAAC;EACF,MAAM,QAAQ,MAAM,MAAM,0BACzB,SACA,OACA,QACA,SACA,cACA;AAED,MAAI,KAAK,MAAM;AACd,WAAQ,IAAI,KAAK,UAAU,OAAO,MAAM,EAAE,CAAC;AAC3C;;AAGD,UAAQ,IAAI,gBAAgB,MAAM,CAAC;GAClC;;AAGH,IAAM,UAAU,sBACf,IAAI,QAAQ,OAAO,CACjB,yBAAyB,CACzB,cAAc,UAAU,CACxB,YAAY,oCAAoC,CAChD,SAAS,aAAa,+BAA+B,CACvD;AAED,YAAY,QAAQ;AACpB,cAAc,QAAQ;AACtB,QAAQ,OAAO,WAAW;AAE1B,IAAM,WAAW,sBAChB,IAAI,QAAQ,QAAQ,CAClB,cAAc,UAAU,CACxB,YAAY,iDAAiD,CAC7D,SAAS,aAAa,0BAA0B,CAClD;AAED,YAAY,SAAS;AACrB,cAAc,SAAS;AACvB,SAAS,OAAO,YAAY;AAC5B,QAAQ,WAAW,SAAS;AAE5B,IAAa,cAAc;;;AC3L3B,IAAM,MAAM,IAAI,QAAQ,SAAS,CAC/B,cAAc,UAAU,CACxB,YAAY,uBAAuB,CACnC,OAAO,eAAe,eAAe,IAAI,CACzC,OAAO,uBAAuB,iDAAiD,CAC/E,OAAO,kBAAkB,6BAA6B,CACtD,OAAO,iBAAiB,wBAAwB;AAElD,YAAY,IAAI;AAChB,cAAc,IAAI;AAElB,IAAI,QAEF,SAOI;CACJ,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,KAAI;EACH,MAAM,QAAQ,KAAK,IAAI,GAAG,OAAO,SAAS,KAAK,OAAO,GAAG,IAAI,EAAE;EAC/D,MAAM,UAA+C,EAAE;AACvD,MAAI,KAAK,KAAM,SAAQ,OAAO,KAAK;AACnC,MAAI,CAAC,KAAK,aAAa;GAEtB,MAAM,UADiB,QAAQ,IAAI,iBAAiB,MAAM,IACxB,eAAe,QAAQ,KAAK,EAAE,KAAK,WAAW,KAAK;AACrF,OAAI,QAAS,SAAQ,UAAU;;EAEhC,MAAM,QAAQ,MAAM,OAAO,OAAO,QAAQ;AAC1C,MAAI,KAAK,KACR,SAAQ,IAAI,KAAK,UAAU,MAAM,CAAC;MAElC,MAAK,MAAM,QAAQ,MAClB,SAAQ,IAAI,IAAI,KAAK,GAAG,IAAI,KAAK,KAAK,IAAI,KAAK,QAAQ;WAGhD;AACT,QAAM,OAAO;;EAGf;AAED,IAAa,gBAAgB;;;AC5C7B,IAAM,YAAY,IAAI,QAAQ,SAAS,CACrC,cAAc,UAAU,CACxB,YAAY,2BAA2B,CACvC,SAAS,WAAW,eAAe,CACnC,OAAO,mBAAmB,eAAe,IAAI,CAC7C,OAAO,uBAAuB,iDAAiD,CAC/E,OAAO,kBAAkB,6BAA6B,CACtD,OAAO,iBAAiB,wBAAwB;AAElD,YAAY,UAAU;AACtB,cAAc,UAAU;AAExB,IAAa,gBAAgB,UAAU,QAErC,OACA,SAOI;CACJ,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,KAAI;EACH,MAAM,QAAQ,KAAK,IAAI,GAAG,OAAO,SAAS,KAAK,OAAO,GAAG,IAAI,EAAE;EAC/D,MAAM,UAA+C,EAAE;AACvD,MAAI,KAAK,KAAM,SAAQ,OAAO,KAAK;AACnC,MAAI,CAAC,KAAK,aAAa;GAEtB,MAAM,UADiB,QAAQ,IAAI,iBAAiB,MAAM,IACxB,eAAe,QAAQ,KAAK,EAAE,KAAK,WAAW,KAAK;AACrF,OAAI,QAAS,SAAQ,UAAU;;EAEhC,MAAM,UAAU,MAAM,OAAO,OAAO,OAAO,QAAQ;AAEnD,MAAI,KAAK,MAAM;AACd,WAAQ,IAAI,KAAK,UAAU,SAAS,MAAM,EAAE,CAAC;AAC7C;;AAGD,MAAI,QAAQ,WAAW,GAAG;AACzB,KAAE,IAAI,KAAK,oBAAoB;AAC/B;;AAGD,IAAE,MAAM,GAAG,QAAQ,OAAO,kBAAkB,MAAM,GAAG;AAErD,OAAK,MAAM,QAAQ,SAAS;GAC3B,MAAM,QAAQ,KAAK,MAAM,QAAQ,EAAE;GACnC,MAAM,MAAM,UAAU,KAAK,WAAW;GACtC,MAAM,UACL,KAAK,UAAU,SAAS,MAAM,GAAG,KAAK,UAAU,MAAM,GAAG,IAAI,CAAC,KAAK,KAAK;AAEzE,KAAE,IAAI,QACL;IAAC,IAAI,KAAK,GAAG,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,MAAM;IAAI,KAAK;IAAO;IAAQ,CAAC,KAAK,KAAK,CACjF;;AAGF,IAAE,MAAM,OAAO;WACN;AACT,QAAM,OAAO;;EAGf;AAED,SAAS,UAAU,SAAyB;CAC3C,MAAM,KAAK,KAAK,KAAK,GAAG,IAAI,KAAK,QAAQ,CAAC,SAAS;CACnD,MAAM,OAAO,KAAK,MAAM,KAAK,MAAW;AACxC,KAAI,SAAS,EAAG,QAAO;AACvB,KAAI,SAAS,EAAG,QAAO;AACvB,KAAI,OAAO,GAAI,QAAO,GAAG,KAAK;AAE9B,QAAO,GADQ,KAAK,MAAM,OAAO,GAAG,CACnB;;;;;;;;AC1ClB,SAAgB,UAAU,SAAyB;CAClD,MAAM,OAAO,OAAO,SAAS,SAAS,GAAG;AACzC,KAAI,CAAC,OAAO,SAAS,KAAK,IAAI,OAAO,KAAK,OAAO,MAChD,OAAM,IAAI,MAAM,iBAAiB,UAAU;AAE5C,QAAO;;AAGR,SAAgB,6BAA6B,MAAmD;AAC/F,KAAI,KAAK,QAAQ,KAAK,QACrB,OAAM,IAAI,MAAM,sCAAsC;AAEvD,KAAI,KAAK,cAAc,KAAK,WAC3B,OAAM,IAAI,MAAM,+CAA+C;CAEhE,MAAM,SAAS,aAAa,KAAK,IAAI;AACrC,QAAO;EACN,MAAM,KAAK,OAAO,SAAS,KAAK,UAAU,YAAY;EACtD;EACA,YAAY,KAAK,UAAU;EAC3B,MAAM,KAAK;EACX,MAAM,UAAU,KAAK,KAAK;EAC1B,YAAY,KAAK,UAAU,OAAO,KAAK,aAAa,OAAO;EAC3D;;AAGF,SAAgB,uBACf,QACA,MAC0B;AAC1B,KAAI,WAAW,KAAA,EACd,QAAO,6BAA6B,KAAK;AAE1C,KAAI,KAAK,QAAQ,KAAK,QACrB,OAAM,IAAI,MAAM,qDAAqD;AAEtE,KAAI,WAAW,QACd,QAAO,4BAA4B,KAAK;AAEzC,QAAO,6BAA6B,QAAQ,KAAK;;AAGlD,SAAgB,4BAA4B,MAAkD;AAE7F,QAAO;EACN,MAAM;EACN,QAHc,aAAa,KAAK,IAAI;EAIpC,YAAY,KAAK,UAAU;EAC3B,MAAM,KAAK;EACX,MAAM,UAAU,KAAK,KAAK;EAC1B,YAAY,CAAC,KAAK;EAClB;;AAGF,SAAgB,6BACf,MACA,MAC0B;AAE1B,QAAO;EACN;EACA,QAHc,aAAa,KAAK,IAAI;EAIpC,YAAY,KAAK,UAAU;EAC3B,MAAM,KAAK;EACX,MAAM,UAAU,KAAK,KAAK;EAC1B,YAAY,SAAS;EACrB;;;;AClEF,SAAgB,iBAAiB,SAAiC;AACjE,KAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;CACpD,MAAM,SAAU,QAAqC;AACrD,KAAI,OAAO,WAAW,YAAY,CAAC,OAAO,SAAS,OAAO,IAAI,UAAU,EAAG,QAAO;AAClF,QAAO,KAAK,MAAM,OAAO;;AAG1B,SAAgB,YAAY,MAAuB;CAClD,MAAM,aAAa,KAAK,MAAM,CAAC,aAAa;AAC5C,QACC,eAAe,eACf,eAAe,eACf,eAAe,SACf,eAAe,aACf,eAAe;;AAIjB,SAAgB,mBAAmB,MAAuB;CACzD,MAAM,aAAa,KAAK,MAAM,CAAC,aAAa;AAC5C,QACC,eAAe,eACf,0BAA0B,KAAK,WAAW,IAC1C,eAAe,SACf,eAAe;;AAIjB,SAAS,oBAAoB,MAAc,MAAoB;AAC9D,KAAI,mBAAmB,KAAK,CAAE;AAC9B,GAAE,IAAI,KACL,mBAAmB,KAAK,GAAG,KAAK,oKAChC;;AAGF,SAAgB,sBAAsB,SAA0B;CAC/D,MAAM,UAAU,QAAQ,aAAa;AACrC,KAAI,CAAC,oBAAoB,KAAK,QAAQ,CAAE,QAAO;AAC/C,QACC,QAAQ,SAAS,UAAU,IAC3B,QAAQ,SAAS,6BAA6B,IAC9C,QAAQ,SAAS,qBAAqB;;AAIxC,SAAgB,sBAAsB,QAAgC;AACrE,QAAO,aAAa,UAAU,KAAA,EAAU,CAAC;;AAG1C,SAAgB,uBACf,UACA,aACgB;AAChB,KAAI,YAAY,eAAe,aAAa,YAAa,QAAO;AAChE,QAAO,YAAY,eAAe;;AAGnC,SAAS,mBAAmB,MAAc,MAA6B;AACtE,KAAI,CAAC,YAAY,KAAK,CAAE,QAAO;CAC/B,MAAM,SAAS,UAAU,QAAQ;EAAC;EAAO,SAAS;EAAQ;EAAgB;EAAK,EAAE;EAChF,UAAU;EACV,SAAS;EACT,CAAC;AACF,KAAI,OAAO,WAAW,EAAG,QAAO;CAChC,MAAM,SAAS,OAAO,UAAU,IAC9B,MAAM,QAAQ,CACd,KAAK,SAAS,KAAK,MAAM,CAAC,CAC1B,MAAM,SAAS,KAAK,SAAS,EAAE;AACjC,KAAI,CAAC,MAAO,QAAO;CACnB,MAAM,SAAS,OAAO,SAAS,OAAO,GAAG;AACzC,QAAO,OAAO,SAAS,OAAO,IAAI,SAAS,IAAI,SAAS;;AAGzD,SAAS,mBAAmB,KAA4B;CACvD,MAAM,SAAS,UAAU,MAAM;EAAC;EAAM,OAAO,IAAI;EAAE;EAAM;EAAW,EAAE;EACrE,UAAU;EACV,SAAS;EACT,CAAC;AACF,KAAI,OAAO,WAAW,EAAG,QAAO;CAChC,MAAM,OAAO,OAAO,UAAU,IAAI,MAAM;AACxC,QAAO,IAAI,SAAS,IAAI,MAAM;;AAG/B,SAAS,mBACR,KACA,QACA,aACU;AACV,KAAI,CAAC,YAAY,OAAO,KAAK,CAAE,QAAO;AACtC,KAAI,eAAe,gBAAgB,IAAK,QAAO;CAC/C,MAAM,UAAU,mBAAmB,IAAI;AACvC,KAAI,CAAC,QAAS,QAAO;AACrB,QAAO,sBAAsB,QAAQ;;AAGtC,SAAS,YAAY,QAAwB;AAC5C,QAAO,KAAK,QAAQ,OAAO,EAAE,aAAa;;AAG3C,SAAS,oBAAoB,QAAwC;CACpE,MAAM,UAAU,YAAY,OAAO;AACnC,KAAI,CAAC,WAAW,QAAQ,CAAE,QAAO;CACjC,MAAM,MAAM,aAAa,SAAS,QAAQ,CAAC,MAAM;AACjD,KAAI;EACH,MAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,MACC,OAAO,OAAO,QAAQ,YACtB,OAAO,OAAO,SAAS,YACvB,OAAO,OAAO,SAAS,SAEvB,QAAO;GAAE,KAAK,OAAO;GAAK,MAAM,OAAO;GAAM,MAAM,OAAO;GAAM;SAE1D;EACP,MAAM,MAAM,OAAO,SAAS,KAAK,GAAG;AACpC,MAAI,OAAO,SAAS,IAAI,IAAI,MAAM,EACjC,QAAO;GAAE;GAAK,MAAM;GAAa,MAAM;GAAO;;AAGhD,QAAO;;AAGR,SAAS,iBAAiB,KAAsB;AAC/C,KAAI;AACH,UAAQ,KAAK,KAAK,EAAE;AACpB,SAAO;SACA;AACP,SAAO;;;AAIT,eAAe,0BAA0B,QAA2C;AACnF,KAAI;EACH,MAAM,aAAa,IAAI,iBAAiB;EACxC,MAAM,QAAQ,iBAAiB,WAAW,OAAO,EAAE,IAAK;EACxD,MAAM,MAAM,MAAM,MAAM,UAAU,OAAO,KAAK,GAAG,OAAO,KAAK,aAAa,EACzE,QAAQ,WAAW,QACnB,CAAC;AACF,eAAa,MAAM;AACnB,SAAO,IAAI;SACJ;AACP,SAAO;;;AAIT,eAAe,yBAAyB,MAAc,MAAsC;AAC3F,KAAI;EACH,MAAM,aAAa,IAAI,iBAAiB;EACxC,MAAM,QAAQ,iBAAiB,WAAW,OAAO,EAAE,IAAK;EACxD,MAAM,MAAM,MAAM,MAAM,UAAU,KAAK,GAAG,KAAK,aAAa,EAC3D,QAAQ,WAAW,QACnB,CAAC;AACF,eAAa,MAAM;AACnB,MAAI,CAAC,IAAI,GAAI,QAAO;AAEpB,SAAO,iBADS,MAAM,IAAI,MAAM,CACA;SACzB;AACP,SAAO;;;AAIT,eAAe,WAAW,MAAc,MAAgC;AACvE,QAAO,IAAI,SAAS,YAAY;EAC/B,MAAM,SAAS,IAAI,iBAAiB;GAAE;GAAM;GAAM,CAAC;EACnD,MAAM,QAAQ,SAAkB;AAC/B,UAAO,oBAAoB;AAC3B,UAAO,SAAS;AAChB,WAAQ,KAAK;;AAEd,SAAO,WAAW,IAAI;AACtB,SAAO,KAAK,iBAAiB,KAAK,KAAK,CAAC;AACxC,SAAO,KAAK,iBAAiB,KAAK,MAAM,CAAC;AACzC,SAAO,KAAK,eAAe,KAAK,MAAM,CAAC;GACtC;;AAGH,eAAe,mBAAmB,KAAa,YAAY,KAAyB;CACnF,MAAM,WAAW,KAAK,KAAK,GAAG;AAC9B,QAAO,KAAK,KAAK,GAAG,UAAU;AAC7B,MAAI,CAAC,iBAAiB,IAAI,CAAE,QAAO;AACnC,QAAM,IAAI,SAAS,YAAY,WAAW,SAAS,IAAI,CAAC;;AAEzD,QAAO,CAAC,iBAAiB,IAAI;;AAG9B,eAAe,mBAAmB,MAAc,MAAc,YAAY,KAAyB;CAClG,MAAM,WAAW,KAAK,KAAK,GAAG;AAC9B,QAAO,KAAK,KAAK,GAAG,UAAU;AAC7B,MAAI,CAAE,MAAM,WAAW,MAAM,KAAK,CAAG,QAAO;AAC5C,QAAM,IAAI,SAAS,YAAY,WAAW,SAAS,IAAI,CAAC;;AAEzD,QAAO;;AAGR,eAAe,mBACd,QACA,QACoD;CACpD,MAAM,eAAe,OAAO,QAAkC;AAC7D,MAAI;AACH,WAAQ,KAAK,KAAK,UAAU;AAC5B,UAAO,MAAM,mBAAmB,IAAI;UAC7B;AACP,UAAO;;;CAIT,MAAM,UAAU,YAAY,OAAO;CACnC,MAAM,SAAS,oBAAoB,OAAO;CAC1C,MAAM,qBAAqB,MAAM,yBAAyB,OAAO,MAAM,OAAO,KAAK;CACnF,MAAM,cAAc,mBAAmB,OAAO,MAAM,OAAO,KAAK;CAChE,MAAM,YAAY,uBAAuB,oBAAoB,YAAY;AACzE,KAAI,aAAa,mBAAmB,WAAW,QAAQ,YAAY,EAAE;AAEpE,MAAI,CADY,MAAM,aAAa,UAAU,CAC/B,QAAO;GAAE,SAAS;GAAO,KAAK;GAAW;AACvD,MAAI;AACH,UAAO,QAAQ;UACR;AAGR,SAAO;GAAE,SAAS;GAAM,KAAK;GAAW;;AAGzC,KAAI,CAAC,OAAQ,QAAO;EAAE,SAAS;EAAO,KAAK;EAAM;AAEjD,KAAI,MAAM,0BAA0B,OAAO;MAEtC,CADY,MAAM,aAAa,OAAO,IAAI,CAChC,QAAO;GAAE,SAAS;GAAO,KAAK,OAAO;GAAK;;AAEzD,KAAI;AACH,SAAO,QAAQ;SACR;AAGR,QAAO;EAAE,SAAS;EAAM,KAAK,OAAO;EAAK;;AAG1C,SAAgB,0BACf,YACA,YACA,WAAqB,QAAQ,UAClB;CACX,MAAM,OAAO;EACZ,GAAG;EACH;EACA;EACA;EACA;EACA;EACA,WAAW;EACX;EACA,OAAO,WAAW,KAAK;EACvB;AACD,KAAI,WAAW,OACd,MAAK,KAAK,aAAa,WAAW,OAAO;AAE1C,QAAO;;AAGR,SAAgB,uBAAuB,OAAyB;AAC/D,KAAI,EAAE,iBAAiB,OAAQ,QAAO;CACtC,MAAM,OAAO,MAAM,QAAQ,aAAa;AACxC,QACC,KAAK,SAAS,aAAa,IAC3B,KAAK,SAAS,cAAc,IAC5B,KAAK,SAAS,OAAO,IACpB,KAAK,SAAS,SAAS,IAAI,KAAK,SAAS,MAAM;;AAIlD,SAAgB,4BAA4B,OAAgB,QAA0B;CACrF,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AACtE,QAAO;EACN,MAAM;EACN,QAAQ,QAAQ;EAChB,QAAQ,QAAQ;EAChB,OAAO,QAAQ,KAAK;EACpB,sBAAsB,QAAQ,IAAI,8BAA8B;EAChE,SAAS;EACT;;AAGF,eAAe,sBAAsB,YAAoD;AACxF,qBAAoB,WAAW,MAAM,WAAW,KAAK;AACrD,KAAI,MAAM,WAAW,WAAW,MAAM,WAAW,KAAK,EAAE;AACvD,IAAE,IAAI,KAAK,oCAAoC,WAAW,KAAK,GAAG,WAAW,OAAO;AACpF;;CAED,MAAM,aAAa,QAAQ,KAAK;AAChC,KAAI,CAAC,YAAY;AAChB,IAAE,IAAI,MAAM,yDAAyD;AACrE,UAAQ,WAAW;AACnB;;CAED,MAAM,QAAQ,MAAM,QAAQ,UAAU,0BAA0B,YAAY,WAAW,EAAE;EACxF,KAAK,QAAQ,KAAK;EAClB,UAAU;EACV,OAAO;EACP,KAAK;GACJ,GAAG,QAAQ;GACX,GAAI,WAAW,SAAS,EAAE,YAAY,WAAW,QAAQ,GAAG,EAAE;GAC9D,GAAI,WAAW,aAAa,EAAE,gBAAgB,WAAW,YAAY,GAAG,EAAE;GAC1E;EACD,CAAC;AACF,OAAM,OAAO;AACb,KAAI,WAAW,OACd,eACC,YAAY,WAAW,OAAO,EAC9B,KAAK,UAAU;EAAE,KAAK,MAAM;EAAK,MAAM,WAAW;EAAM,MAAM,WAAW;EAAM,CAAC,EAChF,QACA;AAEF,GAAE,MAAM,iBAAiB;AACzB,GAAE,MACD,qCAAqC,MAAM,IAAI,cAAc,WAAW,KAAK,GAAG,WAAW,OAC3F;;AAGF,eAAe,sBAAsB,YAAoD;CACxF,MAAM,EAAE,WAAW,eAAe,YAAY,aAAa,MAAM,OAAO;CACxE,MAAM,EAAE,UAAU,MAAM,OAAO;AAE/B,KAAI,WAAW,OAAQ,SAAQ,IAAI,aAAa,WAAW;AAC3D,KAAI,WAAW,WAAY,SAAQ,IAAI,iBAAiB,WAAW;AACnE,qBAAoB,WAAW,MAAM,WAAW,KAAK;AACrD,KAAI,MAAM,WAAW,WAAW,MAAM,WAAW,KAAK,EAAE;AACvD,IAAE,IAAI,KAAK,oCAAoC,WAAW,KAAK,GAAG,WAAW,OAAO;AACpF,UAAQ,WAAW;AACnB;;CAED,MAAM,aAAa,sBAAsB,WAAW,OAAO;CAE3D,MAAM,WAAW,IAAI,gBAAgB;CACrC,IAAI;AACJ,KAAI;AACH,UAAQ,UAAU;UACV,KAAK;AACb,MAAI,qBAAqB,IAAI,CAAC,uBAAuB,IAAI,CACxD,OAAM;AAGP,IAAE,IAAI,KAAK,8EAA8E;AACzF,OAAK,MAAM,QAAQ,4BAClB,KACA,cAAc,WAAW,UAAU,KAAA,EAAU,CAC7C,CACA,GAAE,IAAI,KAAK,0BAA0B,OAAO;AAE7C,UAAQ,IAAI,6BAA6B;AACzC,cAAY;AACZ,UAAQ,UAAU;AAClB,IAAE,IAAI,KAAK,mFAAmF;;CAG/F,MAAM,UAAU,IAAI,gBAAgB,OAAO,EAAE,UAAU,CAAC;AACxD,SAAQ,OAAO;CAEf,MAAM,YAAY,IAAI,iBAAiB;CACvC,MAAM,iBAAiB,IAAI,iBAAiB;CAI5C,MAAM,aAAa,0BAHJ,WAAW,aACvB,4BAA4B,WAAW,WAAW,GAClD,uBAAuB,CAC0B;CACpD,MAAM,cAAc,WAAW;CAC/B,MAAM,kBAAkB,IAAI,oBAAoB;EAC/C,QAAQ,cAAc,WAAW,UAAU,KAAA,EAAU;EACrD,QAAQ,eAAe;EACvB,CAAC;CACF,MAAM,wBAAwB,IAAI,2BAA2B,EAC5D,QAAQ,cAAc,WAAW,UAAU,KAAA,EAAU,EACrD,CAAC;CACF,MAAM,yBAAyB,IAAI,uBAAuB,EACzD,QAAQ,cAAc,WAAW,UAAU,KAAA,EAAU,EACrD,CAAC;CACF,MAAM,oBAGF;EACH,OAAO,cAAc,aAAa;EAClC,QAAQ,cAAc,yCAAyC;EAC/D;CAED,MAAM,UAAU;EACf,oBAAoB;EACpB;EACA;EACA,4BAA4B;EAC5B;CACD,MAAM,MAAM,UAAU,QAAQ;CAE9B,MAAM,UAAU,YADD,cAAc,WAAW,UAAU,KAAA,EAAU,CACzB;CAInC,IAAI,aAA8C;CAClD,IAAI,oBAAoB;AACxB,KAAI,aAAa;AAEhB,eAAa,MACZ;GAAE,OAFa,cAAc,QAAQ,CAEpB;GAAO,UAAU,WAAW;GAAU,MAAM,WAAW;GAAU,GACjF,SAAS;AACT,uBAAoB;AACpB,KAAE,IAAI,KAAK,qCAAqC,KAAK,QAAQ,GAAG,KAAK,OAAO;IAE7E;AACD,aAAW,GAAG,UAAU,QAA+B;AACtD,OAAI,CAAC,qBAAqB,IAAI,SAAS,aACtC,GAAE,IAAI,KACL,aAAa,WAAW,SAAS,iDACjC;OAED,GAAE,IAAI,KAAK,wBAAwB,IAAI,UAAU;IAGjD;;CAGH,MAAM,SAAS,MACd;EAAE,OAAO,IAAI;EAAO,UAAU,WAAW;EAAM,MAAM,WAAW;EAAM,GACrE,SAAS;AACT,gBACC,SACA,KAAK,UAAU;GAAE,KAAK,QAAQ;GAAK,MAAM,WAAW;GAAM,MAAM,WAAW;GAAM,CAAC,EAClF,QACA;AACD,IAAE,MAAM,iBAAiB;AACzB,IAAE,IAAI,QAAQ,uBAAuB,KAAK,QAAQ,GAAG,KAAK,OAAO;AACjE,IAAE,IAAI,KAAK,aAAa,aAAa;AACrC,IAAE,IAAI,KAAK,4BAA4B;AACvC,MAAI,CAAC,qBAAqB,EAAE;AAC3B,yBAAsB,OAAO;AAC7B,KAAE,IAAI,KAAK,oCAAoC;;AAEhD,MAAI,2BAA2B,MAAM,GAAG,EAAE;AACzC,0BAAuB,OAAO;AAC9B,KAAE,IAAI,KAAK,uCAAuC;;AAEnD,MAAI,WAAW,sBAAsB;AACpC,mBAAgB,OAAO;AACvB,KAAE,IAAI,KAAK,uCAAuC;;AAEnD,MAAI,aAAa;GAChB,MAAM,mBAAmB;AACzB,KAAE,IAAI,KAAK,yCAAyC,mBAAmB,IAAK,UAAU;AACtF,oBAAiB;AAChB,sBAAkB,QAAQ;AAC1B,sBAAkB,SAAS;AACtB,kBAAc;KAClB,QAAQ,cAAc,WAAW,UAAU,KAAA,EAAU;KACrD,WAAW,WAAW;KACtB,MAAM,WAAW;KACjB,MAAM,WAAW;KACjB,QAAQ,UAAU;KAClB,gBAAgB,UAAU;AACzB,UAAI,UAAU,WAAW;AACxB,yBAAkB,QAAQ;AAC1B,yBAAkB,SAAS;aACrB;AACN,yBAAkB,QAAQ;AAC1B,yBAAkB,SACjB,UAAU,aACP,uCACA;;;KAGN,CAAC,CACA,OAAO,QAAiB;KACxB,MAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAC5D,uBAAkB,QAAQ;AAC1B,uBAAkB,SAAS;AAC3B,OAAE,IAAI,MAAM,uBAAuB,MAAM;MACxC,CACD,cAAc;AACd,SAAI,kBAAkB,UAAU,SAAS;AACxC,wBAAkB,QAAQ,UAAU,OAAO,UAAU,aAAa;AAClE,wBAAkB,SAAS,UAAU,OAAO,UAAU,iBAAiB;;MAEvE;MACD,iBAAiB,CAAC,OAAO;;GAG9B;AAED,QAAO,GAAG,UAAU,QAA+B;AAClD,MAAI,IAAI,SAAS,aAChB,GAAE,IAAI,KAAK,oCAAoC,WAAW,KAAK,GAAG,WAAW,OAAO;MAEpF,GAAE,IAAI,MAAM,IAAI,QAAQ;AAEzB,UAAQ,KAAK,EAAE;GACd;CAMF,MAAM,qBAAqB,kBAAkB;AAC5C,MAAI;AACH,SAAM,GAAG,OAAO,2BAA2B;WACnC,KAAK;AACb,KAAE,IAAI,KAAK,0BAA0B,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GAAG;;IALvD,MAAS,IAOd;AAC9B,oBAAmB,OAAO;CAE1B,MAAM,WAAW,YAAY;AAC5B,IAAE,MAAM,gBAAgB;AACxB,gBAAc,mBAAmB;AACjC,YAAU,OAAO;AACjB,iBAAe,OAAO;AACtB,QAAM,QAAQ,MAAM;AACpB,QAAM,uBAAuB,MAAM;AACnC,QAAM,sBAAsB,MAAM;AAClC,QAAM,gBAAgB,MAAM;AAG5B,QAAM,IAAI,SAAe,YAAY;GACpC,IAAI,YAAY,aAAa,IAAI;GACjC,MAAM,aAAa;AAClB,QAAI,EAAE,cAAc,EAAG,UAAS;;AAEjC,eAAY,MAAM,KAAK;AACvB,UAAO,MAAM,KAAK;IACjB,CAAC,YAAY,GAEb;AAEF,MAAI;AACH,UAAO,QAAQ;UACR;AAGR,cAAY;AACZ,UAAQ,KAAK,EAAE;;CAIhB,MAAM,sBAAsB;AAC3B,mBAAiB;AAChB,OAAI;AACH,WAAO,QAAQ;WACR;AAGR,eAAY;AACZ,WAAQ,KAAK,EAAE;KACb,IAAM,CAAC,OAAO;;AAElB,SAAQ,GAAG,gBAAgB;AAC1B,iBAAe;AACV,YAAU;GACd;AACF,SAAQ,GAAG,iBAAiB;AAC3B,iBAAe;AACV,YAAU;GACd;;AAGH,eAAe,mBAAmB,YAAoD;CACrF,MAAM,SAAS,cAAc,WAAW,UAAU,KAAA,EAAU;AAC5D,KAAI,WAAW,SAAS,UAAU,WAAW,SAAS,WAAW;EAChE,MAAM,SAAS,MAAM,mBAAmB,QAAQ;GAC/C,MAAM,WAAW;GACjB,MAAM,WAAW;GACjB,CAAC;AACF,MAAI,OAAO,SAAS;AACnB,KAAE,MAAM,iBAAiB;AACzB,KAAE,IAAI,QAAQ,iBAAiB,OAAO,MAAM,SAAS,OAAO,IAAI,KAAK,KAAK;AAC1E,OAAI,WAAW,SAAS,QAAQ;AAC/B,MAAE,MAAM,OAAO;AACf;;AAID,OAAI,CADa,MAAM,mBAAmB,WAAW,MAAM,WAAW,KAAK,CAE1E,GAAE,IAAI,KAAK,QAAQ,WAAW,KAAK,6CAA6C;aAEvE,OAAO,KAAK;AACtB,KAAE,MAAM,iBAAiB;AACzB,KAAE,IAAI,MAAM,sCAAsC,OAAO,IAAI,GAAG;AAChE,WAAQ,WAAW;AACnB;aACU,WAAW,SAAS,QAAQ;AACtC,KAAE,MAAM,iBAAiB;AACzB,KAAE,MAAM,6BAA6B;AACrC;;;AAIF,KAAI,WAAW,SAAS,WAAW,WAAW,SAAS,WAAW;AACjE,MAAI,WAAW,YAAY;AAC1B,SAAM,sBAAsB;IAAE,GAAG;IAAY;IAAQ,CAAC;AACtD;;AAED,QAAM,sBAAsB;GAAE,GAAG;GAAY;GAAQ,CAAC;;;AAIxD,IAAM,WAAW,IAAI,QAAQ,QAAQ,CACnC,cAAc,UAAU,CACxB,YAAY,2BAA2B,CACvC,SAAS,YAAY,wCAAwC;AAE/D,YAAY,SAAS;AACrB,gBAAgB,SAAS;AACzB,qBAAqB,SAAS;AAG9B,SAAS,UAAU,IAAI,OAAO,gBAAgB,2BAA2B,CAAC,UAAU,CAAC;AACrF,SAAS,UAAU,IAAI,OAAO,gBAAgB,2BAA2B,CAAC,UAAU,CAAC;AACrF,SAAS,UAAU,IAAI,OAAO,UAAU,yBAAyB,CAAC,UAAU,CAAC;AAC7E,SAAS,UAAU,IAAI,OAAO,aAAa,4BAA4B,CAAC,UAAU,CAAC;AAEnF,IAAa,eAAe,SAAS,OACpC,OAAO,QAA4B,SAA6B;AAC/D,KAAI;AAEH,MAAI,KAAK,KAAM,wBAAuB,UAAU,qBAAqB;AACrE,MAAI,KAAK,QAAS,wBAAuB,aAAa,wBAAwB;AAC9E,MAAI,KAAK,WAAY,wBAAuB,gBAAgB,sBAAsB;AAClF,MAAI,KAAK,WACR,wBAAuB,gBAAgB,mCAAmC;EAE3E,MAAM,mBACL,WAAW,KAAA,IACR,KAAA,IACA,WAAW,WAAW,WAAW,UAAU,WAAW,YACpD,SACD;AACL,MAAI,qBAAqB,MAAM;AAC9B,KAAE,IAAI,MAAM,yBAAyB,SAAS;AAC9C,WAAQ,WAAW;AACnB;;AAED,QAAM,mBAAmB,uBAAuB,kBAAkB,KAAK,CAAC;UAChE,KAAK;AACb,IAAE,IAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AAC7D,UAAQ,WAAW;;EAGrB;;;ACrqBD,SAAgB,0BAA0B,WAA2B;CACpE,MAAM,WAAW,KAAK,WAAW,gBAAgB;AACjD,KAAI,WAAW,SAAS,CAAE,QAAO;CACjC,MAAM,YAAY,KAAK,WAAW,iBAAiB;AACnD,KAAI,WAAW,UAAU,CAAE,QAAO;AAClC,QAAO;;AAGR,SAAgB,gBAAgB,MAAuC;AACtE,KAAI,CAAC,WAAW,KAAK,CAAE,QAAO,EAAE;CAChC,MAAM,MAAM,aAAa,MAAM,QAAQ;AACvC,KAAI;AACH,SAAO,KAAK,MAAM,IAAI;SACf;EACP,MAAM,UAAU,oBAAoB,kBAAkB,IAAI,CAAC;AAC3D,SAAO,KAAK,MAAM,QAAQ;;;AAI5B,SAAgB,gBAAgB,MAAc,MAAqC;AAClF,WAAU,QAAQ,KAAK,EAAE,EAAE,WAAW,MAAM,CAAC;AAC7C,eAAc,MAAM,GAAG,KAAK,UAAU,MAAM,MAAM,EAAE,CAAC,KAAK,QAAQ;;;;;;;;;;;;;;;;ACHnE,SAAS,oBAA4B;AACpC,QAAO,KAAK,SAAS,EAAE,WAAW,WAAW;;AAG9C,SAAS,kBAA0B;AAClC,QAAO,KAAK,SAAS,EAAE,UAAU;;;AAIlC,IAAM,uBAAuB;AAC7B,IAAM,+BAA+B,CAAC,WAAW,qBAAqB;;AAOtE,SAAS,8BAAoC;CAC5C,MAAM,eAAe,KAAK,mBAAmB,EAAE,WAAW,aAAa;CACvE,MAAM,eAAe,KAAK,mBAAmB,EAAE,OAAO,YAAY;AAClE,KAAI,WAAW,aAAa,CAC3B,KAAI;AACH,SAAO,aAAa;AACpB,IAAE,IAAI,KAAK,sEAAsE;SAC1E;AACP,IAAE,IAAI,KAAK,kEAAkE;;AAG/E,KAAI,WAAW,aAAa,CAC3B,KAAI;AACH,SAAO,aAAa;AACpB,IAAE,IAAI,KAAK,8DAA8D;SAClE;;;AAOV,SAAS,yBAAyB,QAA0C;CAC3E,MAAM,YAAY,OAAO;AACzB,KAAI,CAAC,aAAa,OAAO,cAAc,SAAU,QAAO;CACxD,MAAM,QAAQ,UAAU;AACxB,KAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;CAEhD,MAAM,UAAU,MAAM;AAMtB,KAJE,MAAM,QAAQ,QAAQ,IACtB,QAAQ,MAAM,QAAQ,OAAO,QAAQ,aAAa,QAAQ,SAAS,QAAQ,MAAM,IACjF,OAAO,YAAY,aAAa,YAAY,SAAS,YAAY,OAErD;AACb,IAAE,IAAI,KAAK,wCAAwC;AACnD,YAAU,UAAU;GACnB,MAAM;GACN,SAAS;IAAC;IAAO;IAAW;IAAM;GAClC,SAAS;GACT;AACD,SAAO;;AAER,QAAO;;;AAIR,SAAS,uBAAuB,UAA4C;CAC3E,MAAM,aAAa,SAAS;AAC5B,KAAI,CAAC,cAAc,OAAO,eAAe,SAAU,QAAO;CAC1D,MAAM,QAAQ,WAAW;AACzB,KAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;CAEhD,MAAM,UAAU,MAAM;CACtB,MAAM,OAAO,MAAM;AAQnB,KANE,OAAO,YAAY,aAAa,YAAY,SAAS,YAAY,SACjE,MAAM,QAAQ,KAAK,IACnB,KAAK,MACH,QAAQ,OAAO,QAAQ,aAAa,IAAI,WAAW,YAAY,IAAI,QAAQ,OAC5E,EAEW;AACb,IAAE,IAAI,KAAK,+CAA+C;AAC1D,aAAW,UAAU;GACpB,SAAS;GACT,MAAM;IAAC;IAAM;IAAW;IAAM;GAC9B;AACD,SAAO;;AAER,QAAO;;AAOR,SAAS,cAAc,OAAyB;AAE/C,8BAA6B;CAE7B,MAAM,aAAa,0BAA0B,mBAAmB,CAAC;CACjE,IAAI;AACJ,KAAI;AACH,WAAS,gBAAgB,WAAW;UAC5B,KAAK;AACb,IAAE,IAAI,MACL,mBAAmB,WAAW,IAAI,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GAClF;AACD,SAAO;;CAGR,IAAI,UAAU,OAAO;AACrB,KAAI,CAAC,MAAM,QAAQ,QAAQ,CAC1B,WAAU,EAAE;CAGb,MAAM,uBAAuB,UAC5B,OAAO,UAAU,YACjB,CAAC,sBAAsB,GAAG,6BAA6B,CAAC,MACtD,SAAS,UAAU,QAAQ,MAAM,WAAW,GAAG,KAAK,GAAG,CACxD;CAEF,MAAM,mBAAoB,QAAqB,MAC7C,UACA,OAAO,UAAU,aAChB,UAAU,wBAAwB,MAAM,WAAW,GAAG,qBAAqB,GAAG,EAChF;CACD,MAAM,gBAAiB,QAAqB,MAC1C,UACA,OAAO,UAAU,YACjB,6BAA6B,MAAM,SAAS,UAAU,QAAQ,MAAM,WAAW,GAAG,KAAK,GAAG,CAAC,CAC5F;AAED,KAAI,oBAAoB,CAAC,iBAAiB,CAAC,OAAO;AACjD,IAAE,IAAI,KAAK,WAAW,qBAAqB,2BAA2B;AACtE,SAAO;;AAGR,WAAW,QAAqB,QAAQ,UAAU,CAAC,oBAAoB,MAAM,CAAC;AAC9E,KAAI,cACH,GAAE,IAAI,KAAK,uEAAuE;AAGlF,SAAqB,KAAK,qBAAqB;AAChD,QAAO,SAAS;AAEhB,KAAI;AACH,kBAAgB,YAAY,OAAO;AACnC,IAAE,IAAI,QAAQ,WAAW,qBAAqB,aAAa,aAAa;UAChE,KAAK;AACb,IAAE,IAAI,MACL,mBAAmB,WAAW,IAAI,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GAClF;AACD,SAAO;;AAGR,QAAO;;AAGR,SAAS,WAAW,OAAyB;CAC5C,MAAM,aAAa,0BAA0B,mBAAmB,CAAC;CACjE,IAAI;AACJ,KAAI;AACH,WAAS,gBAAgB,WAAW;UAC5B,KAAK;AACb,IAAE,IAAI,MACL,mBAAmB,WAAW,IAAI,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GAClF;AACD,SAAO;;CAGR,IAAI,YAAY,OAAO;AACvB,KAAI,aAAa,QAAQ,OAAO,cAAc,YAAY,MAAM,QAAQ,UAAU,CACjF,aAAY,EAAE;CAIf,MAAM,WAAW,yBAAyB,OAAO;AAEjD,KAAI,aAAa,aAAa,CAAC,SAAS,CAAC,UAAU;AAClD,IAAE,IAAI,KAAK,+BAA+B,aAAa;AACvD,SAAO;;AAGR,KAAI,CAAC,UAAU;AACd,YAAU,UAAU;GACnB,MAAM;GACN,SAAS;IAAC;IAAO;IAAW;IAAM;GAClC,SAAS;GACT;AACD,SAAO,MAAM;;AAGd,KAAI;AACH,kBAAgB,YAAY,OAAO;AACnC,IAAE,IAAI,QAAQ,wBAAwB,aAAa;UAC3C,KAAK;AACb,IAAE,IAAI,MACL,mBAAmB,WAAW,IAAI,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GAClF;AACD,SAAO;;AAGR,QAAO;;AAGR,SAAS,+BAAwC;CAGhD,MAAM,YAAY,KAAK,iBAAiB,EAAE,WAAW,UAAU;AAC/D,KAAI,WAAW,UAAU,CAAE,QAAO;AAGlC,KAAI,WADc,KAAK,WAAW,SAAS,aAAa,CAC/B,CAAE,QAAO;AAClC,QAAO;;AAGR,SAAS,iBAAiB,OAAyB;CAClD,MAAM,eAAe,KAAK,iBAAiB,EAAE,gBAAgB;CAC7D,IAAI;AACJ,KAAI;AACH,aAAW,gBAAgB,aAAa;SACjC;AACP,aAAW,EAAE;;CAGd,IAAI,aAAa,SAAS;AAC1B,KAAI,cAAc,QAAQ,OAAO,eAAe,YAAY,MAAM,QAAQ,WAAW,CACpF,cAAa,EAAE;CAIhB,MAAM,WAAW,uBAAuB,SAAS;AAEjD,KAAI,aAAa,cAAc,CAAC,SAAS,CAAC,SACzC,GAAE,IAAI,KAAK,sCAAsC,eAAe;MAC1D;AACN,MAAI,CAAC,UAAU;AACd,cAAW,UAAU;IACpB,SAAS;IACT,MAAM;KAAC;KAAM;KAAW;KAAM;IAC9B;AACD,YAAS,aAAa;;AAGvB,MAAI;AACH,mBAAgB,cAAc,SAAS;AACvC,KAAE,IAAI,QAAQ,+BAA+B,eAAe;WACpD,KAAK;AACb,KAAE,IAAI,MACL,mBAAmB,aAAa,IAAI,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GACpF;AACD,UAAO;;;AAKT,KAAI,CAAC,8BAA8B,IAAI,OAAO;AAC7C,IAAE,IAAI,KAAK,+DAA+D;AAC1E,IAAE,IAAI,KAAK,8CAA8C;AACzD,IAAE,IAAI,KAAK,4BAA4B;AACvC,IAAE,IAAI,KAAK,GAAG;AACd,IAAE,IAAI,KAAK,iCAAiC;AAC5C,IAAE,IAAI,KAAK,mDAAmD;OAE9D,GAAE,IAAI,KAAK,mDAAmD;AAG/D,QAAO;;AAGR,IAAa,eAAe,IAAI,QAAQ,QAAQ,CAC9C,cAAc,UAAU,CACxB,YAAY,mEAAmE,CAC/E,OAAO,WAAW,mCAAmC,CACrD,OAAO,mBAAmB,4BAA4B,CACtD,OAAO,iBAAiB,+BAA+B,CACvD,QAAQ,SAA4E;AACpF,GAAE,MAAM,kBAAkB,UAAU;CACpC,MAAM,QAAQ,KAAK,SAAS;CAC5B,IAAI,KAAK;AAET,KAAI,CAAC,KAAK,YAAY;AACrB,IAAE,IAAI,KAAK,gCAAgC;AAC3C,OAAK,cAAc,MAAM,IAAI;AAC7B,IAAE,IAAI,KAAK,oCAAoC;AAC/C,OAAK,WAAW,MAAM,IAAI;;AAG3B,KAAI,CAAC,KAAK,cAAc;AACvB,IAAE,IAAI,KAAK,uCAAuC;AAClD,OAAK,iBAAiB,MAAM,IAAI;;AAGjC,KAAI,GACH,GAAE,MAAM,0DAA0D;MAC5D;AACN,IAAE,MAAM,gCAAgC;AACxC,UAAQ,WAAW;;EAEnB;;;ACpTH,SAAS,OAAO,GAAmB;AAClC,QAAO,GAAG,KAAK,MAAM,IAAI,IAAI,CAAC;;AAG/B,SAAS,UAAU,GAAmB;AACrC,KAAI,KAAK,IAAe,QAAO,KAAK,IAAI,KAAe,QAAQ,EAAE,CAAC;AAClE,KAAI,KAAK,IAAW,QAAO,KAAK,IAAI,KAAW,QAAQ,EAAE,CAAC;AAC1D,KAAI,KAAK,IAAO,QAAO,KAAK,IAAI,KAAO,QAAQ,EAAE,CAAC;AAClD,QAAO,GAAG;;AAGX,IAAM,WAAW,IAAI,QAAQ,QAAQ,CACnC,cAAc,UAAU,CACxB,YAAY,2BAA2B;AAEzC,YAAY,SAAS;AACrB,cAAc,SAAS;AAEvB,IAAa,eAAe,SAAS,QAAQ,SAA4B;CACxE,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,KAAI;EACH,MAAM,SAAS,MAAM,OAAO;AAC5B,MAAI,KAAK,MAAM;AACd,WAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;EAGD,MAAM,KAAK,OAAO;EAClB,MAAM,UAAU,GAAG,aAAa,SAAW,QAAQ,EAAE;AAErD,IAAE,MAAM,gBAAgB;AAExB,IAAE,IAAI,KAAK,CAAC,gBAAgB,GAAG,QAAQ,gBAAgB,OAAO,KAAK,CAAC,KAAK,KAAK,CAAC;AAE/E,IAAE,IAAI,QACL;GACC,gBAAgB,GAAG,SAAS,gBAAgB;GAC5C,gBAAgB,GAAG,oBAAoB,gBAAgB,CAAC,YAAY,GAAG,aAAa,gBAAgB,CAAC;GACrG,gBAAgB,GAAG,YAAY,gBAAgB,CAAC,WAAW,OAAO,GAAG,cAAc,CAAC;GACpF,gBAAgB,GAAG,UAAU,gBAAgB;GAC7C,gBAAgB,GAAG,YAAY,gBAAgB,CAAC,IAAI,OAAO,GAAG,gBAAgB,CAAC;GAC/E,gBAAgB,GAAG,WAAW,gBAAgB;GAC9C,CAAC,KAAK,KAAK,CACZ;AAED,MAAI,OAAO,MAAM,OAAO,SAAS,GAAG;GACnC,MAAM,QAAQ,OAAO,MAAM,OAAO,KAAK,MAA4C;IAClF,MAAM,QAAQ,CAAC,GAAG,EAAE,MAAM,IAAI,EAAE,MAAM,gBAAgB,GAAG;AACzD,QAAI,EAAE,cAAc,EAAG,OAAM,KAAK,QAAQ,UAAU,EAAE,YAAY,CAAC,SAAS;AAC5E,QAAI,EAAE,eAAe,EAAG,OAAM,KAAK,cAAc,UAAU,EAAE,aAAa,CAAC,SAAS;AACpF,WAAO,KAAK,MAAM,KAAK,KAAK;KAC3B;GAEF,MAAM,IAAI,OAAO,MAAM;AACvB,SAAM,KAAK,GAAG;AACd,SAAM,KACL,YAAY,EAAE,OAAO,gBAAgB,CAAC,gBAAgB,UAAU,EAAE,YAAY,CAAC,sBAAsB,UAAU,EAAE,aAAa,CAAC,SAC/H;AAED,KAAE,IAAI,KAAK,UAAU,MAAM,KAAK,KAAK,GAAG;;AAGzC,IAAE,MAAM,OAAO;WACN;AACT,QAAM,OAAO;;EAEb;;;ACnEF,SAAgB,kBAAkB,KAA6B;CAC9D,MAAM,SAAS,IAAI,KAAK,OAAO;CAC/B,MAAM,QAAQ,OAAO,IAAI,SAAS,GAAG;CACrC,MAAM,SAAS,QAAQ,MAAM,UAAU;AACvC,QAAO,GAAG,IAAI,eAAe,GAAG,OAAO,MAAM,IAAI,OAAO,OAAO,IAAI,QAAQ,GAAG,IAAI,eAAe,KAAK;;AAavG,SAAgB,wBACf,QACA,MACA,YACA,WAAqB,EAAE,EACZ;AACX,KAAI,CAAC,WAAY,OAAM,IAAI,MAAM,8DAA8D;CAC/F,MAAM,OAAO;EAAC,GAAG;EAAU;EAAY;EAAQ;AAC/C,KAAI,WAAW,QACd,MAAK,KAAK,YAAY;UACZ,WAAW,OACrB,MAAK,KAAK,SAAS;KAEnB,MAAK,KAAK,YAAY;CAEvB,MAAM,aAAa,aAAa,KAAK;AACrC,KAAI,WAAY,MAAK,KAAK,aAAa,WAAW;AAClD,KAAI,KAAK,OAAQ,MAAK,KAAK,YAAY,KAAK,OAAO;AACnD,KAAI,KAAK,KAAM,MAAK,KAAK,UAAU,KAAK,KAAK;AAC7C,KAAI,KAAK,KAAM,MAAK,KAAK,UAAU,KAAK,KAAK;AAC7C,QAAO;;AAGR,SAAgB,qBACf,cACA,QACS;AACT,KAAI,OAAO,GAAI,QAAO,KAAK,aAAa;AAExC,QAAO,KAAK,aAAa,SADV,OAAO,QAAQ,KAAK,OAAO,UAAU;;AAIrD,SAAgB,iBAAiB,OAAqC;AACrE,KAAI,CAAC,MAAO,QAAO,EAAE;AACrB,QAAO,MACL,MAAM,IAAI,CACV,KAAK,SAAS,KAAK,MAAM,CAAC,CAC1B,OAAO,QAAQ;;AAQlB,SAAgB,0BACf,iBACA,gBACA,MACA,YACW;AACX,KAAI,mBAAmB,CAAC,CAAC,QAAQ,UAAU,CAAC,SAAS,gBAAgB,aAAa,CAAC,CAClF,QAAO,CAAC,gBAAgB;AAEzB,KAAI,kBAAkB,mBAAmB,UACxC,QAAO,CAAC,GAAG,eAAe,GAAG,OAAO;CAErC,MAAM,YAAY,OAAO,OAAO,WAAW,CACzC,SAAS,YAAY,WAAW,EAAE,CAAC,CACnC,QAAQ,UAAU,CAAC,MAAM,SAAS,CAClC,KAAK,UAAU,MAAM,QAAQ,CAC7B,QAAQ,YAAY,WAAW,YAAY,eAAe,YAAY,MAAM,CAC5E,KAAK,YAAY,GAAG,QAAQ,GAAG,OAAO;AACxC,QAAO,CAAC,GAAG,IAAI,IAAI,UAAU,CAAC;;;;;;;AClC/B,SAAS,cAAc,YAA8C;AACpE,QAAO,aAAa,4BAA4B,WAAW,GAAG,uBAAuB;;AAGtF,SAAS,eAAe,QAAiC,YAA6B;AACrF,QAAO,uBAAuB,QAAQ,cAAc,KAAA,EAAU;;AAG/D,SAAS,mBAAmB,OAAuB;AAClD,KAAI,CAAC,QAAQ,KAAK,MAAM,MAAM,CAAC,CAC9B,OAAM,IAAI,MAAM,oBAAoB,QAAQ;AAE7C,QAAO,OAAO,SAAS,OAAO,GAAG;;AAGlC,SAAS,2BACR,OACA,UACqB;AACrB,KAAI,SAAS,KAAM,QAAO,KAAA;CAC1B,MAAM,UAAU,MAAM,MAAM;AAC5B,KAAI,CAAC,QAAQ,KAAK,QAAQ,CACzB,OAAM,IAAI,MAAM,WAAW,SAAS,IAAI,QAAQ;AAEjD,QAAO,OAAO,SAAS,SAAS,GAAG;;AAmBpC,SAAS,iBACR,IACA,SACuE;CACvE,MAAM,UAAU,QAAQ,MAAM;AAC9B,KAAI,CAAC,QAAS,QAAO;CACrB,MAAM,OAAO,GACX,OAAO;EAAE,gBAAgB,OAAO,UAAU;EAAgB,MAAM,OAAO,UAAU;EAAM,CAAC,CACxF,KAAK,OAAO,UAAU,CACtB,MAAM,GAAG,OAAO,UAAU,gBAAgB,QAAQ,CAAC,CACnD,KAAK;AACP,KAAI,KAAM,QAAO;CACjB,MAAM,SAAS,GACb,OAAO;EAAE,gBAAgB,OAAO,UAAU;EAAgB,MAAM,OAAO,UAAU;EAAM,CAAC,CACxF,KAAK,OAAO,UAAU,CACtB,MAAM,GAAG,OAAO,UAAU,MAAM,QAAQ,CAAC,CACzC,KAAK;AACP,KAAI,OAAO,SAAS,EAAG,QAAO;AAC9B,QAAO,OAAO,MAAM;;AAGrB,eAAe,SAAS,MAAc,MAAgC;AACrE,QAAO,IAAI,SAAS,YAAY;EAC/B,MAAM,SAAS,IAAI,iBAAiB;GAAE;GAAM;GAAM,CAAC;EACnD,MAAM,QAAQ,OAAgB;AAC7B,UAAO,oBAAoB;AAC3B,UAAO,SAAS;AAChB,WAAQ,GAAG;;AAEZ,SAAO,WAAW,IAAI;AACtB,SAAO,KAAK,iBAAiB,KAAK,KAAK,CAAC;AACxC,SAAO,KAAK,iBAAiB,KAAK,MAAM,CAAC;AACzC,SAAO,KAAK,eAAe,KAAK,MAAM,CAAC;GACtC;;AAGH,SAAS,kBAAkB,QAAuD;AACjF,KAAI;EACH,MAAM,MAAM,aAAa,KAAK,QAAQ,OAAO,EAAE,aAAa,EAAE,OAAO;EACrE,MAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,MAAI,OAAO,OAAO,SAAS,YAAY,OAAO,OAAO,SAAS,SAC7D,QAAO;GAAE,MAAM,OAAO;GAAM,MAAM,OAAO;GAAM;SAEzC;AAGR,QAAO;;AAGR,SAAS,2BAA2B,OAAsD;AACzF,KAAI;EACH,MAAM,aAAa,MAAM,SAAS,MAAM,GAAG,QAAQ,UAAU;EAC7D,MAAM,MAAM,IAAI,IAAI,WAAW;EAC/B,MAAM,OAAO,IAAI,OAAO,OAAO,SAAS,IAAI,MAAM,GAAG,GAAG,IAAI,aAAa,WAAW,MAAM;AAC1F,MAAI,CAAC,IAAI,YAAY,CAAC,OAAO,SAAS,KAAK,CAAE,QAAO;AACpD,SAAO;GAAE,MAAM,IAAI;GAAU;GAAM;SAC5B;AACP,SAAO;;;AAIT,eAAe,kBACd,QACA,MACgB;AAChB,KAAI,KAAK,SAAS,SAAS,KAAK,WAAW,KAC1C,GAAE,IAAI,KACL,mGACA;AAEF,KAAI,WAAW;MACC,0BAA0B,cAAc,KAAK,OAAO,CAAC,CACzD,gBAAgB,MAAM;AAChC,KAAE,IAAI,MAAM,qDAAqD;AACjE,WAAQ,WAAW;AACnB;;;CAOF,MAAM,aAAa,aAAa,KAAK;CACrC,MAAM,OAAO,wBAAwB,QAAQ,MAAM,QAAQ,KAAK,MAAM,IAAI,QAAQ,SAAS;AAC3F,OAAM,IAAI,SAAe,SAAS,WAAW;EAC5C,MAAM,QAAQ,MAAM,QAAQ,UAAU,MAAM;GAC3C,KAAK,QAAQ,KAAK;GAClB,OAAO;GACP,KAAK;IACJ,GAAG,QAAQ;IACX,GAAI,aAAa,EAAE,YAAY,YAAY,GAAG,EAAE;IAChD,GAAI,KAAK,SAAS,EAAE,gBAAgB,KAAK,QAAQ,GAAG,EAAE;IACtD;GACD,CAAC;AACF,QAAM,KAAK,SAAS,OAAO;AAC3B,QAAM,KAAK,SAAS,SAAwB;AAC3C,OAAI,QAAQ,SAAS,EACpB,SAAQ,WAAW;AAEpB,YAAS;IACR;GACD;;AAGH,IAAa,cAAc,IAAI,QAAQ,OAAO,CAC5C,cAAc,UAAU,CACxB,YAAY,yCAAyC;AAIvD,IAAM,cAAc,IAAI,QAAQ,WAAW,CACzC,cAAc,UAAU,CACxB,YAAY,4BAA4B,CACxC,OAAO,eAAe,gBAAgB,KAAK;AAC7C,YAAY,YAAY;AACxB,cAAc,YAAY;AAC1B,YAAY,QAAQ,SAA0E;CAC7F,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,KAAI;EACH,MAAM,IAAI,QAAQ,MAAM,IAAI,EAAE,QAAQ,CAAC;EACvC,MAAM,QAAQ,mBAAmB,KAAK,MAAM;EAC5C,MAAM,OAAO,EACX,OAAO;GACP,gBAAgB,OAAO,aAAa;GACpC,IAAI,OAAO,aAAa;GACxB,QAAQ,OAAO,aAAa;GAC5B,SAAS,OAAO,aAAa;GAC7B,OAAO,OAAO,aAAa;GAC3B,aAAa,OAAO,aAAa;GACjC,CAAC,CACD,KAAK,OAAO,aAAa,CACzB,QAAQ,KAAK,OAAO,aAAa,YAAY,CAAC,CAC9C,MAAM,MAAM,CACZ,KAAK;AAEP,MAAI,KAAK,MAAM;AACd,WAAQ,IAAI,KAAK,UAAU,MAAM,MAAM,EAAE,CAAC;AAC1C;;AAGD,OAAK,MAAM,OAAO,KACjB,SAAQ,IAAI,kBAAkB,IAAI,CAAC;WAE3B;AACT,QAAM,OAAO;;EAEb;AACF,YAAY,WAAW,YAAY;AAInC,SAAS,8BAA8B,QAAsC;CAC5E,MAAM,MAAM,IAAI,QAAQ,OAAO,CAC7B,cAAc,UAAU,CACxB,YAAY,gBAAgB,OAAO,oCAAoC,OAAO,GAAG;AACnF,aAAY,IAAI;AAChB,iBAAgB,IAAI;AACpB,sBAAqB,IAAI;AACzB,uBAAsB,IAAI;AAC1B,KAAI,OAAO,OAAO,SAA+B;AAChD,yBAAuB,gBAAgB,UAAU,iBAAiB,SAAS;AAC3E,QAAM,kBAAkB,QAAQ,KAAK;GACpC;AACF,aAAY,WAAW,KAAK,EAAE,QAAQ,MAAM,CAAC;;AAG9C,8BAA8B,QAAQ;AACtC,8BAA8B,OAAO;AACrC,8BAA8B,UAAU;AAIxC,IAAM,UAAU,IAAI,QAAQ,OAAO,CACjC,cAAc,UAAU,CACxB,YAAY,yBAAyB,CACrC,OAAO,iBAAiB,yBAAyB;AACnD,YAAY,QAAQ;AACpB,cAAc,QAAQ;AACtB,QAAQ,OAAO,OAAO,SAA0E;CAC/F,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,KAAI;EACH,MAAM,UAAU,QAAQ,IAAI,kBAAkB,MAAM,IAAI,KAAA;AACxD,oBAAkB,MAAM,GAAG;EAC3B,MAAM,IAAI,QAAQ,MAAM,IAAI,EAAE,QAAQ,CAAC;EACvC,MAAM,OAAO,KAAK,cACR;GACP,MAAM,gBAAgB,EACpB,OAAO,EAAE,gBAAgB,OAAO,UAAU,gBAAgB,CAAC,CAC3D,KAAK,OAAO,UAAU,CACtB,MAAM,GAAG,OAAO,UAAU,gBAAgB,KAAK,KAAK,CAAC,CACrD,KAAK;AACP,OAAI,cAAc,SAAS,EAAG,QAAO;GACrC,MAAM,cAAc,EAClB,OAAO,EAAE,gBAAgB,OAAO,UAAU,gBAAgB,CAAC,CAC3D,KAAK,OAAO,UAAU,CACtB,MAAM,GAAG,OAAO,UAAU,MAAM,KAAK,KAAK,CAAC,CAC3C,KAAK;AACP,OAAI,YAAY,SAAS,GAAG;AAC3B,QAAI,KAAK,MAAM;AACd,mBAAc,kBAAkB,2BAA2B,KAAK,OAAO;AACvE,YAAO,EAAE;;AAEV,MAAE,IAAI,MAAM,2BAA2B,KAAK,OAAO;AACnD,YAAQ,WAAW;AACnB,WAAO,EAAE;;AAEV,UAAO;MACJ,GACH,EAAE,OAAO,EAAE,gBAAgB,OAAO,UAAU,gBAAgB,CAAC,CAAC,KAAK,OAAO,UAAU,CAAC,KAAK;AAE7F,MAAI,KAAK,WAAW,GAAG;AACtB,OAAI,QAAQ,SAAU;AACtB,OAAI,KAAK,MAAM;AACd,kBAAc,YAAY,8BAA8B;AACxD;;AAED,KAAE,IAAI,KAAK,8BAA8B;AACzC,WAAQ,WAAW;AACnB;;EAGD,IAAI,aAAa;EACjB,MAAM,UAID,EAAE;AACP,OAAK,MAAM,OAAO,MAAM;GACvB,MAAM,SAAS,MAAM,YAAY,MAAM,IAAI,IAAI,gBAAgB,EAAE,SAAS,CAAC;AAC3E,OAAI,CAAC,OAAO,GAAI,cAAa;AAC7B,WAAQ,KAAK;IACZ,gBAAgB,IAAI;IACpB,IAAI,OAAO;IACX,GAAI,OAAO,QAAQ,EAAE,OAAO,OAAO,OAAO,GAAG,EAAE;IAC/C,CAAC;AACF,OAAI,CAAC,KAAK,KACT,SAAQ,IAAI,qBAAqB,IAAI,gBAAgB,OAAO,CAAC;;AAG/D,MAAI,KAAK,KACR,SAAQ,IAAI,KAAK,UAAU;GAAE,IAAI,CAAC;GAAY;GAAS,EAAE,MAAM,EAAE,CAAC;AAEnE,MAAI,WACH,SAAQ,WAAW;WAEX;AACT,QAAM,OAAO;;EAEb;AACF,YAAY,WAAW,QAAQ;AAI/B,IAAM,UAAU,IAAI,QAAQ,OAAO,CACjC,cAAc,UAAU,CACxB,YAAY,iDAAiD,CAC7D,OAAO,mBAAmB,kDAAkD,CAC5E,OAAO,wBAAwB,0DAA0D,CACzF,OAAO,kBAAkB,mDAAmD,CAC5E,OAAO,iBAAiB,qBAAqB,CAC7C,OAAO,yBAAyB,oCAAoC,CACpE,OAAO,wBAAwB,4CAA4C,CAC3E,OAAO,wBAAwB,4CAA4C,CAC3E,OAAO,SAAS,gDAAgD,CAChE,OAAO,aAAa,iDAAiD;AACvE,YAAY,QAAQ;AACpB,gBAAgB,QAAQ;AACxB,cAAc,QAAQ;AACtB,QAAQ,OAAO,OAAO,SAA0B;CAC/C,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,KAAI;EACH,MAAM,sBAAsB,KAAK,UAAU,QAAQ,KAAK,cAAc;AACtE,MAAI,KAAK,eAAe,qBAAqB;AAC5C,OAAI,KAAK,MAAM;AACd,kBACC,eACA,oEACA,EACA;AACD;;AAED,KAAE,IAAI,MAAM,mEAAmE;AAC/E,WAAQ,WAAW;AACnB;;AAED,MAAI,KAAK,UAAU,KAAK,YAAY;AACnC,OAAI,KAAK,MAAM;AACd,kBAAc,eAAe,6CAA6C,EAAE;AAC5E;;AAED,KAAE,IAAI,MAAM,4CAA4C;AACxD,WAAQ,WAAW;AACnB;;EAGD,IAAI,aAAa,KAAK;AACtB,MAAI,KAAK,WACR,KAAI;AACH,gBACC,KAAK,eAAe,MACjB,MAAM,IAAI,SAAiB,SAAS,WAAW;IAC/C,IAAI,OAAO;AACX,YAAQ,MAAM,YAAY,OAAO;AACjC,YAAQ,MAAM,GAAG,SAAS,UAAU;AACnC,aAAQ;MACP;AACF,YAAQ,MAAM,GAAG,aAAa,QAAQ,KAAK,CAAC;AAC5C,YAAQ,MAAM,GAAG,SAAS,OAAO;KAChC,GACD,aAAa,KAAK,YAAY,OAAO;WACjC,OAAO;GACf,MAAM,MACL,iBAAiB,QACd,uCAAuC,KAAK,WAAW,IAAI,MAAM,YACjE,uCAAuC,KAAK;AAChD,OAAI,KAAK,MAAM;AACd,kBAAc,cAAc,IAAI;AAChC;;AAED,KAAE,IAAI,MAAM,IAAI;AAChB,WAAQ,WAAW;AACnB;;AAIF,MAAI,uBAAuB,EAAE,cAAc,IAAI,MAAM,EAAE;AACtD,OAAI,KAAK,MAAM;AACd,kBACC,eACA,qEACA,EACA;AACD;;AAED,KAAE,IAAI,MAAM,oEAAoE;AAChF,WAAQ,WAAW;AACnB;;AAGD,MAAI,CAAC,eAAe,KAAK,WAAW,KAAK,WAAW,KAAK,OAAO,KAAK,UAAU;AAC9E,OAAI,KAAK,MAAM;AACd,kBACC,eACA,oFACA,EACA;AACD;;AAED,KAAE,IAAI,MACL,mFACA;AACD,WAAQ,WAAW;AACnB;;AAGD,MAAI,YAAY,MAAM,EAAE;AACvB,OAAI,KAAK,OAAO,KAAK,SAAS;AAC7B,QAAI,KAAK,MAAM;AACd,mBAAc,eAAe,sCAAsC,EAAE;AACrE;;AAED,MAAE,IAAI,MAAM,qCAAqC;AACjD,YAAQ,WAAW;AACnB;;AAED,QAAK,KAAK,OAAO,KAAK,aAAa,KAAK,WAAW,KAAK,UAAU;AACjE,QAAI,KAAK,MAAM;AACd,mBACC,eACA,+DACA,EACA;AACD;;AAED,MAAE,IAAI,MAAM,8DAA8D;AAC1E,YAAQ,WAAW;AACnB;;GAGD,IAAI;AACJ,OAAI;AACH,cAAU,KAAK,MAAM,WAAW;YACxB,OAAO;IACf,MAAM,MACL,iBAAiB,QACd,4BAA4B,MAAM,YAClC;AACJ,QAAI,KAAK,MAAM;AACd,mBAAc,mBAAmB,IAAI;AACrC;;AAED,MAAE,IAAI,MAAM,IAAI;AAChB,YAAQ,WAAW;AACnB;;GAGD,MAAM,WAAW,OAAO,QAAQ,aAAa,GAAG,CAAC,MAAM;GACvD,MAAM,cAAc,OAAO,QAAQ,eAAe,GAAG,CAAC,MAAM;GAC5D,MAAM,YAAY,OAAO,QAAQ,cAAc,GAAG,CAAC,MAAM;GACzD,MAAM,oBAAoB,KAAK,SAAS,MAAM,GAC3C,CAAC,KAAK,QAAQ,MAAM,CAAC,GACrB,MAAM,QAAQ,QAAQ,UAAU,GAC9B,QAAQ,UACR,QAAQ,SAAyB,OAAO,SAAS,YAAY,KAAK,MAAM,CAAC,SAAS,EAAE,CACpF,KAAK,SAAS,KAAK,MAAM,CAAC,GAC3B,EAAE;AACN,OAAI,CAAC,YAAY,CAAC,eAAe,CAAC,aAAa,kBAAkB,WAAW,GAAG;IAC9E,MAAM,MAAM;AACZ,QAAI,KAAK,MAAM;AACd,mBAAc,mBAAmB,IAAI;AACrC;;AAED,MAAE,IAAI,MAAM,IAAI;AAChB,YAAQ,WAAW;AACnB;;AAED,OAAI,qBAAqB,UAAU,KAAK,aAAa;AACpD,QAAI,KAAK,MAAM;AACd,mBAAc,wBAAwB,uCAAuC;AAC7E;;AAED,MAAE,IAAI,MAAM,uCAAuC;AACnD,YAAQ,WAAW;AACnB;;AAGD,uBAAoB,MAAM,IAAI,UAAU,mBAAmB;IAC1D,MAAM,KAAK;IACX,mBAAmB;IACnB;IACA,CAAC;AAEF,OAAI,KAAK,QACR,sBAAqB,MAAM,IAAI,UAAU;IAAE,SAAS;IAAM,SAAS;IAAM,CAAC;YAChE,KAAK,OAAO,KAAK,WAAW,KAAK,QAC3C,sBAAqB,MAAM,IAAI,UAAU;IACxC,SAAS,KAAK,MAAM,EAAE,GAAG,iBAAiB,KAAK,QAAQ;IACvD,SAAS,KAAK,MAAM,EAAE,GAAG,iBAAiB,KAAK,QAAQ;IACvD,CAAC;AAGH,OAAI,KAAK,MAAM;AACd,YAAQ,IAAI,KAAK,UAAU;KAAE,IAAI;KAAM,gBAAgB;KAAU,CAAC,CAAC;AACnE;;AAED,KAAE,IAAI,QAAQ,eAAe,WAAW;AACxC;;EAGD,MAAM,UAAU,QAAQ,IAAI,kBAAkB,MAAM,IAAI,KAAA;EACxD,MAAM,CAAC,UAAU,eAAe,qBAAqB,MAAM,IAAI,EAAE,SAAS,CAAC;EAC3E,MAAM,YAAY,cAAc,QAAQ;AACxC,MAAI,CAAC,WAAW;AACf,OAAI,KAAK,MAAM;AACd,kBAAc,eAAe,qBAAqB;AAClD;;AAED,KAAE,IAAI,MAAM,qBAAqB;AACjC,WAAQ,WAAW;AACnB;;EAGD,MAAM,SAAS,cAAc,KAAK,OAAO;EACzC,MAAM,kBAAkB,KAAK,SAAS,MAAM;EAC5C,MAAM,iBAAiB,OAAO,OAAO,cAAc,WAAW,OAAO,YAAY;EACjF,MAAM,iBAAiB,OAAO,OAAO,cAAc,WAAW,OAAO,YAAY;EACjF,MAAM,YAAY,0BACjB,mBAAmB,MACnB,gBACA,gBACA,mBAAmB,CACnB;EACD,MAAM,aAAa;GAClB,WAAW;GACX;GACA,YAAY;GACZ,SAAS,UAAU,MAAM;GACzB;GACA;EACD,MAAM,cAAc,KAAK,UAAU,WAAW;AAE9C,MAAI,KAAK,eAAe,KAAK,MAAM;AAClC,WAAQ,OAAO,MAAM,GAAG,YAAY,IAAI;AACxC;;EAGD,MAAM,UAAU,YAAY,WAAW,KAAK,QAAQ;AACpD,UAAQ,IAAI,kBAAkB;AAC9B,UAAQ,IAAI,YAAY;AACxB,UAAQ,IAAI,iEAAiE;AAC7E,UAAQ,IAAI,iDAAiD;AAC7D,UAAQ,IAAI,kCAAkC;AAC9C,UAAQ,IAAI,iCAAiC,QAAQ,GAAG;AACxD,UAAQ,IAAI,8CAA8C;AAC1D,UAAQ,IAAI,qCAAqC;AACjD,UAAQ,IACP,8GACA;WACQ;AACT,QAAM,OAAO;;EAEb;AACF,YAAY,WAAW,QAAQ;AAI/B,IAAM,YAAY,IAAI,QAAQ,SAAS,CACrC,cAAc,UAAU,CACxB,YAAY,qDAAqD;AACnE,YAAY,UAAU;AACtB,gBAAgB,UAAU;AAC1B,cAAc,UAAU;AACxB,UAAU,OACT,OAAO,SAA4E;CAClF,MAAM,SAAS,cAAc,KAAK,OAAO;CACzC,MAAM,SAAS,cAAc,aAAa,KAAK,CAAC;CAChD,MAAM,QAAQ,IAAI,YAAY,OAAO;AACrC,KAAI;EACH,MAAM,IAAI,QAAQ,MAAM,IAAI,EAAE,QAAQ,CAAC;EACvC,MAAM,SAAS,EACb,OAAO,EAAE,WAAW,OAAO,WAAW,WAAW,CAAC,CAClD,KAAK,OAAO,WAAW,CACvB,MAAM,EAAE,CACR,KAAK;EACP,MAAM,cAAc,EAClB,QAAQ,CACR,KAAK,OAAO,gBAAgB,CAC5B,MAAM,GAAG,OAAO,gBAAgB,IAAI,EAAE,CAAC,CACvC,KAAK;EACP,MAAM,QAAQ,EACZ,OAAO;GACP,gBAAgB,OAAO,UAAU;GACjC,gBAAgB,OAAO,UAAU;GACjC,oBAAoB,OAAO,UAAU;GACrC,YAAY,OAAO,UAAU;GAC7B,CAAC,CACD,KAAK,OAAO,UAAU,CACtB,KAAK;EAEP,MAAM,SAAmB,EAAE;EAC3B,MAAM,WAAW,OAAO,OAAO,cAAc,WAAW,OAAO,YAAY;EAC3E,MAAM,WAAW,OAAO,OAAO,cAAc,WAAW,OAAO,YAAY;EAC3E,MAAM,gBAAgB,kBAAkB,OAAO;EAE/C,MAAM,YAAY,gBACf,MAAM,SAAS,cAAc,MAAM,cAAc,KAAK,GACtD;AAEH,MAAI,CAAC,UAAW,QAAO,KAAK,qBAAqB;AACjD,MAAI,CAAC,OAAQ,QAAO,KAAK,mBAAmB;AAC5C,MACC,aAAa,eACZ,CAAC,YAAY,cAAc,YAAY,cAAc,YAAY,iBAAiB,KAEnF,QAAO,KAAK,eAAe;AAE5B,MAAI,MAAM,WAAW,EAAG,QAAO,KAAK,WAAW;AAC/C,MAAI,CAAC,OAAO,aAAc,QAAO,KAAK,mBAAmB;EAEzD,MAAM,cAMD,EAAE;AAEP,OAAK,MAAM,QAAQ,OAAO;GACzB,MAAM,YAAY,KAAK,iBAAkB,KAAK,MAAM,KAAK,eAAe,GAAgB,EAAE;GAC1F,MAAM,WAAW,2BAA2B,UAAU,MAAM,GAAG;GAC/D,MAAM,QAAQ,WACV,MAAM,SAAS,SAAS,MAAM,SAAS,KAAK,GAC5C,OACA,gBACD;GACH,MAAM,SAAS,QAAQ,KAAK,mBAAmB;GAC/C,MAAM,SAAS,QAAQ,KAAK,WAAW;AACvC,eAAY,KAAK;IAChB,gBAAgB,KAAK;IACrB,WAAW,UAAU;IACrB,WAAW;IACX;IACA,gBAAgB;IAChB,CAAC;AACF,OAAI,UAAU,KAAM,QAAO,KAAK,QAAQ,KAAK,eAAe,cAAc;AAC1E,OAAI,CAAC,UAAU,CAAC,OAAQ,QAAO,KAAK,QAAQ,KAAK,eAAe,aAAa;;AAG9E,MAAI,KAAK,MAAM;AACd,WAAQ,IACP,KAAK,UAAU;IACd,SAAS,OAAO,iBAAiB;IACjC,QAAQ,GAAG,SAAS,GAAG;IACvB,MAAM,QAAQ,IAAI,oBAAoB,mBAAmB;IACzD,QAAQ,YAAY,YAAY;IAChC,UAAU,QAAQ,aAAa;IAC/B,cAAc,aAAa,cAAc;IACzC,OAAO;IACP,QAAQ,CAAC,GAAG,IAAI,IAAI,OAAO,CAAC;IAC5B,IAAI,OAAO,WAAW;IACtB,CAAC,CACF;AACD;;AAGD,UAAQ,IAAI,cAAc;AAC1B,UAAQ,IAAI,cAAc,OAAO,iBAAiB,OAAO;AACzD,UAAQ,IAAI,aAAa,SAAS,GAAG,WAAW;AAChD,UAAQ,IAAI,WAAW,QAAQ,IAAI,oBAAoB,mBAAmB,gBAAgB;AAC1F,UAAQ,IAAI,aAAa,YAAY,YAAY,gBAAgB;AAEjE,MAAI,CAAC,OACJ,SAAQ,IAAI,kDAAkD;MAE9D,SAAQ,IAAI,eAAe,OAAO,YAAY;AAG/C,MACC,aAAa,eACZ,CAAC,YAAY,cAAc,YAAY,cAAc,YAAY,iBAAiB,KAEnF,SAAQ,IACP,mBAAmB,YAAY,WAAW,OAAO,YAAY,iBAAiB,UAAU,GACxF;AAGF,MAAI,MAAM,WAAW,EACpB,SAAQ,IAAI,sCAAsC;OAC5C;AACN,WAAQ,IAAI,YAAY,MAAM,SAAS;AACvC,QAAK,MAAM,UAAU,YACpB,SAAQ,IACP,OAAO,OAAO,eAAe,cAAc,OAAO,UAAU,SAAS,OAAO,UAAU,UAAU,OAAO,OAAO,cAAc,OAAO,iBACnI;;AAIH,MAAI,OAAO,SAAS,EACnB,SAAQ,IAAI,SAAS,CAAC,GAAG,IAAI,IAAI,OAAO,CAAC,CAAC,MAAM,GAAG,EAAE,CAAC,KAAK,KAAK,GAAG;MAEnE,SAAQ,IAAI,yBAAyB;WAE7B;AACT,QAAM,OAAO;;EAGf;AACD,YAAY,WAAW,UAAU;AAIjC,IAAM,YAAY,IAAI,QAAQ,SAAS,CACrC,cAAc,UAAU,CACxB,YAAY,2CAA2C;AACzD,YAAY,UAAU;AACtB,gBAAgB,UAAU;AAC1B,cAAc,UAAU;AACxB,UAAU,QAAQ,SAA4E;CAC7F,MAAM,SAAS,cAAc,KAAK,OAAO;CACzC,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,KAAI;EACH,MAAM,IAAI,QAAQ,MAAM,IAAI,EAAE,QAAQ,CAAC;EACvC,MAAM,YAAY,EAChB,OAAO;GACP,WAAW,OAAO,WAAW;GAC7B,aAAa,OAAO,WAAW;GAC/B,CAAC,CACD,KAAK,OAAO,WAAW,CACvB,MAAM,EAAE,CACR,KAAK;EACP,MAAM,QAAQ,EACZ,OAAO;GACP,gBAAgB,OAAO,UAAU;GACjC,MAAM,OAAO,UAAU;GACvB,cAAc,OAAO,UAAU;GAC/B,YAAY,OAAO,UAAU;GAC7B,CAAC,CACD,KAAK,OAAO,UAAU,CACtB,KAAK;AAEP,MAAI,KAAK,MAAM;AACd,WAAQ,IACP,KAAK,UACJ;IACC,SAAS,OAAO,iBAAiB;IACjC,MAAM,OAAO,aAAa;IAC1B,MAAM,OAAO,aAAa;IAC1B,YAAY,OAAO,mBAAmB;IACtC,WAAW,WAAW,aAAa;IACnC,aAAa,WAAW,eAAe;IACvC,iBAAiB,OAAO,wBAAwB;IAChD,OAAO,MAAM,KAAK,UAAU;KAC3B,WAAW,KAAK;KAChB,MAAM,KAAK;KACX,WAAW,KAAK;KAChB,QAAQ,KAAK,cAAc;KAC3B,EAAE;IACH,EACD,MACA,EACA,CACD;AACD;;AAGD,IAAE,MAAM,sBAAsB;AAC9B,IAAE,IAAI,KACL;GACC,eAAe,OAAO,iBAAiB,OAAO,QAAQ;GACtD,eAAe,OAAO,aAAa;GACnC,eAAe,OAAO,aAAa;GACnC,eAAe,OAAO,mBAAmB,IAAI;GAC7C,gBAAgB,OAAO,wBAAwB;GAC/C,CAAC,KAAK,KAAK,CACZ;AACD,MAAI,UACH,GAAE,IAAI,KAAK,gBAAgB,UAAU,UAAU,iBAAiB,UAAU,cAAc;MAExF,GAAE,IAAI,KAAK,8DAA8D;AAE1E,MAAI,MAAM,WAAW,EACpB,GAAE,IAAI,KAAK,cAAc;MAEzB,MAAK,MAAM,QAAQ,OAAO;GACzB,MAAM,QAAQ,KAAK,QAAQ,KAAK;AAChC,KAAE,IAAI,QACL,KAAK,MAAM,cAAc,KAAK,gBAAgB,QAAQ,WAAW,KAAK,cAAc,OACpF;;AAGH,IAAE,MAAM,GAAG,MAAM,OAAO,UAAU;WACzB;AACT,QAAM,OAAO;;EAEb;AACF,YAAY,WAAW,UAAU;AAIjC,IAAM,YAAY,IAAI,QAAQ,SAAS,CACrC,cAAc,UAAU,CACxB,YAAY,6CAA6C,CACzD,OAAO,sBAAsB,mBAAmB,CAChD,OAAO,sBAAsB,mBAAmB,CAChD,OAAO,wBAAwB,2BAA2B;AAC5D,YAAY,UAAU;AACtB,gBAAgB,UAAU;AAC1B,cAAc,UAAU;AAExB,UAAU,UAAU,IAAI,OAAO,iBAAiB,mBAAmB,CAAC,UAAU,CAAC;AAC/E,UAAU,UAAU,IAAI,OAAO,iBAAiB,mBAAmB,CAAC,UAAU,CAAC;AAC/E,UAAU,QACR,SAUK;AAEL,KAAI,KAAK,QAAQ,CAAC,KAAK,SACtB,wBAAuB,yBAAyB,cAAc;AAE/D,KAAI,KAAK,QAAQ,CAAC,KAAK,SACtB,wBAAuB,yBAAyB,cAAc;CAE/D,MAAM,gBAAgB,KAAK,YAAY,KAAK;CAC5C,MAAM,gBAAgB,KAAK,YAAY,KAAK;CAE5C,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,KAAI;EACH,MAAM,CAAC,UAAU,eAAe,qBAAqB,MAAM,GAAG;EAC9D,MAAM,SAAS,cAAc,KAAK,OAAO;AACzC,SAAO,eAAe;AACtB,MAAI,cAAe,QAAO,YAAY;EACtC,MAAM,WAAW,2BAA2B,eAAe,cAAc;EACzE,MAAM,eAAe,2BAA2B,KAAK,UAAU,aAAa;AAC5E,MAAI,YAAY,KAAM,QAAO,YAAY;AACzC,MAAI,gBAAgB,KAAM,QAAO,kBAAkB;AACnD,iBAAe,QAAQ,KAAK,OAAO;AAEnC,MAAI,KAAK,MAAM;AACd,WAAQ,IACP,KAAK,UAAU;IACd,IAAI;IACJ,WAAW;IACX;IACA,MAAM,OAAO,aAAa;IAC1B,MAAM,OAAO,aAAa;IAC1B,YAAY,OAAO,mBAAmB;IACtC,CAAC,CACF;AACD;;AAGD,IAAE,MAAM,sBAAsB;AAC9B,IAAE,IAAI,QACL;GACC,gBAAgB;GAChB,gBAAgB;GAChB,gBAAgB,OAAO,aAAa;GACpC,gBAAgB,OAAO,aAAa;GACpC,gBAAgB,OAAO,mBAAmB,IAAI;GAC9C,CAAC,KAAK,KAAK,CACZ;AACD,IAAE,MAAM,qDAAqD;WACpD;AACT,QAAM,OAAO;;EAGf;AACD,YAAY,WAAW,UAAU;AAIjC,IAAM,aAAa,IAAI,QAAQ,UAAU,CACvC,cAAc,UAAU,CACxB,YAAY,8CAA8C;AAC5D,gBAAgB,WAAW;AAC3B,WAAW,QAAQ,SAA8B;CAChD,MAAM,SAAS,cAAc,KAAK,OAAO;AACzC,QAAO,eAAe;AACtB,gBAAe,QAAQ,KAAK,OAAO;AACnC,GAAE,MAAM,uBAAuB;AAC/B,GAAE,MAAM,yDAAyD;EAChE;AACF,YAAY,WAAW,WAAW;AAIlC,IAAM,eAAe,IAAI,QAAQ,QAAQ,CACvC,cAAc,UAAU,CACxB,YAAY,wBAAwB;AACtC,YAAY,aAAa;AACzB,cAAc,aAAa;AAC3B,aAAa,QAAQ,SAA2D;CAC/E,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,KAAI;EAEH,MAAM,QADI,QAAQ,MAAM,IAAI,EAAE,QAAQ,CAAC,CAErC,OAAO;GACP,gBAAgB,OAAO,UAAU;GACjC,MAAM,OAAO,UAAU;GACvB,WAAW,OAAO,UAAU;GAC5B,cAAc,OAAO,UAAU;GAC/B,YAAY,OAAO,UAAU;GAC7B,CAAC,CACD,KAAK,OAAO,UAAU,CACtB,QAAQ,KAAK,OAAO,UAAU,aAAa,CAAC,CAC5C,KAAK;AAEP,MAAI,KAAK,MAAM;AACd,WAAQ,IAAI,KAAK,UAAU,OAAO,MAAM,EAAE,CAAC;AAC3C;;AAGD,IAAE,MAAM,qBAAqB;AAC7B,MAAI,MAAM,WAAW,GAAG;AACvB,KAAE,MAAM,sBAAsB;AAC9B;;AAED,OAAK,MAAM,QAAQ,OAAO;GACzB,MAAM,QAAQ,KAAK,QAAQ,KAAK;GAChC,MAAM,QAAQ,KAAK,aAAa;AAChC,KAAE,IAAI,QACL,GAAG,MAAM,iBAAiB,MAAM,iBAAiB,KAAK,gBAAgB,QAAQ,cAAc,KAAK,cAAc,OAC/G;;AAEF,IAAE,MAAM,GAAG,MAAM,OAAO,UAAU;WACzB;AACT,QAAM,OAAO;;EAEb;AAEF,IAAM,iBAAiB,IAAI,QAAQ,SAAS,CAC1C,cAAc,UAAU,CACxB,YAAY,gDAAgD,CAC5D,SAAS,UAAU,+BAA+B;AACpD,YAAY,eAAe;AAC3B,cAAc,eAAe;AAC7B,eAAe,QAAQ,SAAiB,SAA2D;CAClG,MAAM,QAAQ,IAAI,YAAY,cAAc,aAAa,KAAK,CAAC,CAAC;AAChE,KAAI;EACH,MAAM,IAAI,QAAQ,MAAM,IAAI,EAAE,QAAQ,CAAC;EACvC,MAAM,QAAQ,iBAAiB,GAAG,QAAQ;AAC1C,MAAI,UAAU,aAAa;AAC1B,OAAI,KAAK,MAAM;AACd,kBAAc,kBAAkB,2BAA2B,QAAQ,MAAM,GAAG;AAC5E;;AAED,KAAE,IAAI,MAAM,2BAA2B,QAAQ,MAAM,GAAG;AACxD,WAAQ,WAAW;AACnB;;AAED,MAAI,CAAC,OAAO;AACX,OAAI,KAAK,MAAM;AACd,kBAAc,kBAAkB,mBAAmB,QAAQ,MAAM,GAAG;AACpE;;AAED,KAAE,IAAI,MAAM,mBAAmB,QAAQ,MAAM,GAAG;AAChD,WAAQ,WAAW;AACnB;;AAED,IAAE,OAAO,OAAO,mBAAmB,CACjC,MAAM,GAAG,OAAO,mBAAmB,gBAAgB,MAAM,eAAe,CAAC,CACzE,KAAK;AACP,IAAE,OAAO,OAAO,UAAU,CACxB,MAAM,GAAG,OAAO,UAAU,gBAAgB,MAAM,eAAe,CAAC,CAChE,KAAK;EACP,MAAM,UAAU;GACf,IAAI;GACJ,gBAAgB,MAAM;GACtB,MAAM,MAAM;GACZ;AACD,MAAI,KAAK,MAAM;AACd,WAAQ,IAAI,KAAK,UAAU,SAAS,MAAM,EAAE,CAAC;AAC7C;;AAED,IAAE,MAAM,4BAA4B;AACpC,IAAE,IAAI,QAAQ,gBAAgB,MAAM,QAAQ,MAAM,iBAAiB;AACnE,IAAE,MAAM,MAAM,eAAe;WACpB;AACT,QAAM,OAAO;;EAEb;AACF,aAAa,WAAW,eAAe;AACvC,YAAY,WAAW,aAAa;AAIpC,IAAM,eAAe,IAAI,QAAQ,YAAY,CAC3C,cAAc,UAAU,CACxB,YAAY,+DAA+D,CAC3E,SAAS,oBAAoB,mCAAmC,CAChE,OAAO,gCAAgC,mDAAmD,CAC1F,OAAO,mBAAmB,2CAA2C,OAAO,CAC5E,OAAO,qBAAqB,iBAAiB,CAC7C,OAAO,WAAW,sCAAsC;AAC1D,YAAY,aAAa;AACzB,cAAc,aAAa;AAE3B,aAAa,UAAU,IAAI,OAAO,sBAAsB,iBAAiB,CAAC,UAAU,CAAC;AACrF,aAAa,OACZ,OACC,SACA,SAUI;CAEJ,MAAM,gBAAgB,WAAW,KAAK,QAAQ,IAAI,MAAM;AACxD,KAAI,CAAC,cAAc;AAClB,MAAI,KAAK,MAAM;AACd,iBAAc,eAAe,+CAA+C,EAAE;AAC9E;;AAED,IAAE,IAAI,MAAM,8CAA8C;AAC1D,UAAQ,WAAW;AACnB;;CAID,MAAM,QAAQ,IAAI,YADH,cAAc,aAAa,KAAK,CAAC,CACX;AACrC,KAAI;EACH,MAAM,WAAW,KAAK,IAAI,GAAG,OAAO,SAAS,KAAK,UAAU,GAAG,IAAI,IAAK;EACxE,MAAM,UAAU,KAAK,WAAW,KAAA;EAIhC,MAAM,OAHI,QAAQ,MAAM,IAAI,EAAE,QAAQ,CAAC,CAIrC,QAAQ,CACR,KAAK,OAAO,UAAU,CACtB,MAAM,GAAG,OAAO,UAAU,gBAAgB,aAAa,CAAC,CACxD,KAAK;AACP,MAAI,CAAC,MAAM;AACV,OAAI,KAAK,KACR,eAAc,kBAAkB,QAAQ,aAAa,2BAA2B;OAEhF,GAAE,IAAI,MAAM,QAAQ,aAAa,2BAA2B;AAE7D,WAAQ,WAAW;AACnB;;AAED,MAAI,CAAC,KAAK,oBAAoB;AAC7B,OAAI,KAAK,KACR,eACC,mBACA,QAAQ,aAAa,8CACrB;OAED,GAAE,IAAI,MAAM,QAAQ,aAAa,8CAA8C;AAEhF,WAAQ,WAAW;AACnB;;AAID,MAAI,CAAC,KAAK,OAAO;GAChB,MAAM,QAAQ,+BAA+B,MAAM,GAAG;AACtD,OAAI,MAAM,OAAO;AAChB,QAAI,KAAK,KACR,eACC,0BACA,GAAG,MAAM,MAAM,2EACf;QAED,GAAE,IAAI,MACL,GAAG,MAAM,MAAM,2EACf;AAEF,YAAQ,WAAW;AACnB;;;EAKF,MAAM,CAAC,YAAY,qBAAqB,MAAM,IAAI,EAAE,SAAS,CAAC;EAG9D,MAAM,YAAY,KAAK,MAAM,OAAO,KAAK,kBAAkB,KAAK,CAAC;AACjE,MAAI,CAAC,UAAU,QAAQ;AACtB,OAAI,KAAK,KACR,eACC,qBACA,kEACA;OAED,GAAE,IAAI,MAAM,kEAAkE;AAE/E,WAAQ,WAAW;AACnB;;EAGD,IAAI,WAIO;EACX,IAAI,UAAU;EACd,MAAM,iBAA6D,EAAE;AAErE,OAAK,MAAM,WAAW,WAAW;GAChC,MAAM,YAAY,aAAa,QAAQ;AACvC,OAAI,CAAC,UAAW;GAChB,MAAM,YAAY,GAAG,UAAU;GAC/B,MAAM,UAAU,iBAAiB;IAChC;IACA,QAAQ;IACR,KAAK;IACL,WAAW,OAAO,MAAM,EAAE;IAC1B,kBAAkB,KAAK;IACvB;IACA,CAAC;AACF,OAAI;IACH,MAAM,CAAC,MAAM,WAAW,MAAM,YAAY,OAAO,WAAW,EAAE,SAAS,CAAC;AACxE,QAAI,SAAS,OAAO,CAAC,SAAS;AAC7B,oBAAe,KAAK;MAAE,SAAS;MAAW,QAAQ,UAAU;MAAQ,CAAC;AACrE;;AAED,QAAI,QAAQ,gBAAgB,KAAK,oBAAoB;AACpD,oBAAe,KAAK;MAAE,SAAS;MAAW,QAAQ;MAAwB,CAAC;AAC3E;;IAED,MAAM,QAAQ,QAAQ;AACtB,QACC,SACA,OAAO,MAAM,eAAe,YAC5B,OAAO,MAAM,gBAAgB,UAC5B;AACD,gBAAW;MACV,YAAY,MAAM;MAClB,aAAa,MAAM;MACnB,iBACC,OAAO,MAAM,oBAAoB,WAAW,MAAM,kBAAkB;MACrE;AACD,eAAU;AACV,oBAAe,KAAK;MAAE,SAAS;MAAW,QAAQ;MAAM,CAAC;AACzD;;AAED,mBAAe,KAAK;KAAE,SAAS;KAAW,QAAQ;KAA+B,CAAC;YAC1E,KAAK;AACb,mBAAe,KAAK;KACnB,SAAS;KACT,QAAQ,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;KACxD,CAAC;;;AAIJ,MAAI,CAAC,YAAY,CAAC,SAAS;GAC1B,MAAM,UAAU,eAAe,KAAK,MAAM,GAAG,EAAE,QAAQ,IAAI,EAAE,SAAS,CAAC,KAAK,KAAK;GACjF,MAAM,SAAS,UACZ,uDAAuD,YACvD;AACH,OAAI,KAAK,KACR,SAAQ,IAAI,KAAK,UAAU;IAAE,IAAI;IAAO,OAAO;IAAQ,WAAW;IAAgB,CAAC,CAAC;OAEpF,GAAE,IAAI,MAAM,OAAO;AAEpB,WAAQ,WAAW;AACnB;;AAGD,MAAI,CAAC,KAAK,MAAM;AACf,KAAE,MAAM,yBAAyB;AACjC,KAAE,IAAI,KAAK,sBAAsB,KAAK,QAAQ,aAAa,KAAK;;EAGjE,MAAM,YAAY;GACjB,YAAY,SAAS;GACrB,aAAa,SAAS;GACtB,iBAAiB,SAAS;GAC1B,uBAAuB;GACvB,gBAAgB;GAChB,QAAQ;GACR;EAED,MAAM,EAAE,UAAU,MAAM,sBAAsB,SAAS,WAAW,UAAU;GAC3E;GACA,kBAAkB,KAAK;GACvB;GACA,CAAC;EAEF,MAAM,SAAS,uBAAuB,MAAM,IAAI,cAAc,OAAO,UAAU;AAE/E,MAAI,KAAK,KACR,SAAQ,IACP,KAAK,UAAU;GACd,IAAI,OAAO;GACX,SAAS,OAAO;GAChB,SAAS,OAAO;GAChB,OAAO,OAAO,SAAS;GACvB,CAAC,CACF;OACK;AACN,OAAI,OAAO,GACV,GAAE,IAAI,QAAQ,WAAW,OAAO,QAAQ,qBAAqB,OAAO,QAAQ,UAAU;OAEtF,GAAE,IAAI,MAAM,OAAO,SAAS,0BAA0B;AAEvD,KAAE,MAAM,OAAO,KAAK,uBAAuB,mBAAmB;;AAE/D,MAAI,CAAC,OAAO,GAAI,SAAQ,WAAW;WAC1B;AACT,QAAM,OAAO;;EAGf;AACD,YAAY,WAAW,aAAa;AAIpC,IAAM,aAAa,IAAI,QAAQ,UAAU,CACvC,cAAc,UAAU,CACxB,YAAY,2CAA2C,CACvD,SAAS,SAAS,yDAAyD,CAC3E,OAAO,mBAAmB,gBAAgB;AAC5C,gBAAgB,WAAW;AAC3B,WAAW,QAAQ,KAAa,SAA8C;CAC7E,MAAM,SAAS,cAAc,KAAK,OAAO;AACzC,QAAO,uBAAuB,IAAI,MAAM;AACxC,KAAI,KAAK,MAAO,QAAO,yBAAyB,KAAK,MAAM,MAAM;AACjE,gBAAe,QAAQ,KAAK,OAAO;AACnC,GAAE,MAAM,uBAAuB;AAC/B,GAAE,IAAI,QAAQ,gBAAgB,IAAI,MAAM,GAAG;AAC3C,KAAI,KAAK,MAAO,GAAE,IAAI,KAAK,UAAU,KAAK,MAAM,MAAM,GAAG;AACzD,GAAE,MAAM,uDAAuD;EAC9D;AACF,YAAY,WAAW,WAAW;AAQlC,IAAM,uBAAuB,yBAAyB;AAEtD,qBAAqB,KAAK,cAAc,UAAmB,cAAuB;CACjF,MAAM,UAAU,UAAU,MAAM;AAChC,wBAAuB,4BAA4B,WAAW,uBAAuB,UAAU;EAC9F;AAEF,YAAY,WAAW,qBAAqB;;;ACzwC5C,IAAa,iBAAiB,IAAI,QAAQ,UAAU,CAClD,cAAc,UAAU,CACxB,YAAY,wBAAwB,CACpC,aAAa;AACb,SAAQ,IAAI,QAAQ;EACnB;;;;;;;;;;;;;ACuCH,IAAM,aAAa,SAAS,oBAAoB;AAChD,WAAW,GAAG,YAAY,EAAE,YAAY;AACvC,OAAM;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,CAAC;EACD;AACF,WAAW,MAAM;AAEjB,SAAS,YAAY,MAAuB;AAC3C,MAAK,MAAM,OAAO,QAAQ,KAAK,MAAM,EAAE,EAAE;AACxC,MAAI,QAAQ,KAAM,QAAO;AACzB,MAAI,QAAQ,KAAM,QAAO;AACzB,MAAI,CAAC,IAAI,WAAW,IAAI,CAAE,QAAO;;AAElC,QAAO;;AAGR,SAAS,2BAAmC;AAE3C,MADkB,QAAQ,IAAI,SAAS,IACzB,SAAS,OAAO,CAC7B,QAAO,WAAW,4BAA4B;AAE/C,QAAO,WAAW,wBAAwB;;AAG3C,IAAM,UAAU,IAAI,SAAS;AAE7B,QACE,KAAK,UAAU,CACf,YAAY,mDAAmD,CAC/D,yBAAyB,CACzB,OAAO,wBAAwB,2BAA2B,CAC1D,OAAO,qBAAqB,yCAAyC,CACrE,QAAQ,QAAQ,CAChB,cAAc,UAAU;AAE1B,IAAI,YAAY,qBAAqB,IAAI,YAAY,uBAAuB,EAAE;AAC7E,YAAW,oBAAoB;AAC/B,SAAQ,KAAK,EAAE;;AAGhB,IAAI,YAAY,oBAAoB,EAAE;AACrC,SAAQ,IAAI,0BAA0B,CAAC;AACvC,SAAQ,KAAK,EAAE;;AAGhB,IAAI,YAAY,uBAAuB,EAAE;AACxC,YAAW,sBAAsB;AACjC,SAAQ,KAAK,EAAE;;AAWhB;CACC,MAAM,YAAY,IAAI,QAAQ,SAAS,CACrC,YAAY,uDAAuD,CACnE,SAAS,YAAY,wCAAwC,CAC7D,OAAO,eAAe,gBAAgB,CACtC,OAAO,oBAAoB,gBAAgB,CAC3C,OAAO,uBAAuB,oBAAoB,CAClD,OAAO,kBAAkB,sBAAsB,CAC/C,OAAO,sBAAsB,+BAA+B,CAC5D,OAAO,iBAAiB,wDAAwD,CAChF,cAAc,UAAU,CACxB,mBAAmB,KAAK,CACxB,qBAAqB,KAAK,CAC1B,OAAO,YAAY;EAGnB,MAAM,MAAM,QAAQ,KAAK,QAAQ,SAAS;EAC1C,MAAM,OAAO,OAAO,IAAI,QAAQ,KAAK,MAAM,MAAM,EAAE,GAAG,EAAE;AACxD,QAAM,sBAAsB,WAAW;GAAC;GAAQ;GAAmB,GAAG;GAAK,CAAC;GAC3E;CAEH,MAAM,YAAY,IAAI,QAAQ,SAAS,CACrC,YAAY,6CAA6C,CACzD,SAAS,eAAe,sCAAsC,CAC9D,OAAO,eAAe,gBAAgB,CACtC,OAAO,oBAAoB,gBAAgB,CAC3C,OAAO,0BAA0B,4CAA4C,CAC7E,OAAO,aAAa,iCAAiC,CACrD,cAAc,UAAU,CACxB,mBAAmB,KAAK,CACxB,qBAAqB,KAAK,CAC1B,OAAO,YAAY;EACnB,MAAM,MAAM,QAAQ,KAAK,QAAQ,SAAS;EAC1C,MAAM,OAAO,OAAO,IAAI,QAAQ,KAAK,MAAM,MAAM,EAAE,GAAG,EAAE;AACxD,QAAM,sBAAsB,WAAW;GAAC;GAAQ;GAAmB,GAAG;GAAK,CAAC;GAC3E;AAEH,eAAc,WAAW,UAAU;AACnC,eAAc,WAAW,UAAU;;AAGpC,QAAQ,WAAW,aAAa;AAChC,QAAQ,WAAW,cAAc;AACjC,QAAQ,WAAW,mBAAmB;AACtC,QAAQ,WAAW,WAAW;AAC9B,QAAQ,WAAW,wBAAwB;AAC3C,QAAQ,WAAW,wBAAwB;AAC3C,QAAQ,WAAW,UAAU;AAC7B,QAAQ,WAAW,sBAAsB;AACzC,QAAQ,WAAW,sBAAsB;AACzC,QAAQ,WAAW,aAAa;AAChC,QAAQ,WAAW,aAAa;AAChC,QAAQ,WAAW,cAAc;AACjC,QAAQ,WAAW,cAAc;AACjC,QAAQ,WAAW,YAAY;AAG/B,QAAQ,WAAW,mBAAmB,EAAE,QAAQ,MAAM,CAAC;AACvD,QAAQ,WAAW,qBAAqB,EAAE,QAAQ,MAAM,CAAC;AACzD,QAAQ,WAAW,uBAAuB,EAAE,QAAQ,MAAM,CAAC;AAC3D,QAAQ,WAAW,cAAc;AACjC,QAAQ,WAAW,YAAY;AAC/B,QAAQ,WAAW,aAAa;AAChC,QAAQ,WAAW,uBAAuB;AAC1C,QAAQ,WAAW,eAAe;AAElC,QAAQ,OAAO"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/help-style.ts","../src/shared-options.ts","../src/commands/claude-hook-plugin-log.ts","../src/commands/claude-hook-ingest-spool.ts","../src/commands/claude-hook-session-state.ts","../src/commands/claude-hook-ingest.ts","../src/commands/claude-hook-inject.ts","../src/commands/config.ts","../src/commands/coordinator.ts","../src/commands/db.ts","../src/commands/embed.ts","../src/commands/enqueue-raw-event.ts","../src/commands/export-memories.ts","../src/commands/import-memories.ts","../src/commands/mcp.ts","../src/commands/pack-shared.ts","../src/commands/memory.ts","../src/commands/pack.ts","../src/commands/recent.ts","../src/commands/search.ts","../src/commands/serve-invocation.ts","../src/commands/serve.ts","../src/commands/setup-config.ts","../src/commands/setup.ts","../src/commands/stats.ts","../src/commands/sync-helpers.ts","../src/commands/sync.ts","../src/commands/version.ts","../src/index.ts"],"sourcesContent":["/**\n * Shared Commander help style configuration.\n *\n * Applied to every Command instance so subcommand --help\n * output gets the same colors as the root.\n */\n\nimport { styleText } from \"node:util\";\nimport type { HelpConfiguration } from \"commander\";\n\nexport const helpStyle: HelpConfiguration = {\n\tstyleTitle: (str) => styleText(\"bold\", str),\n\tstyleCommandText: (str) => styleText(\"cyan\", str),\n\tstyleCommandDescription: (str) => str,\n\tstyleDescriptionText: (str) => styleText(\"dim\", str),\n\tstyleOptionText: (str) => styleText(\"green\", str),\n\tstyleOptionTerm: (str) => styleText(\"green\", str),\n\tstyleSubcommandText: (str) => styleText(\"cyan\", str),\n\tstyleArgumentText: (str) => styleText(\"yellow\", str),\n};\n","/**\n * Shared CLI option builders.\n *\n * Defines standard flags once with consistent short forms, descriptions,\n * and hidden legacy aliases. Every command module should use these instead\n * of ad-hoc .option() calls.\n *\n * See docs/cli-design-conventions.md for the full spec.\n */\n\nimport type { Command } from \"commander\";\nimport { Option } from \"commander\";\n\n// ---------------------------------------------------------------------------\n// --db-path / -d (with hidden --db alias)\n// ---------------------------------------------------------------------------\n\n/** Add -d/--db-path and hidden --db alias to a command. */\nexport function addDbOption(cmd: Command): Command {\n\tcmd.addOption(new Option(\"-d, --db-path <path>\", \"database path (overrides $CODEMEM_DB)\"));\n\t// Hidden legacy alias\n\tcmd.addOption(new Option(\"--db <path>\", \"database path\").hideHelp());\n\treturn cmd;\n}\n\n/** Resolve the db path from parsed opts that may have --db or --db-path. */\nexport function resolveDbOpt(opts: { db?: string; dbPath?: string }): string | undefined {\n\treturn opts.dbPath ?? opts.db;\n}\n\n// ---------------------------------------------------------------------------\n// --config / -c\n// ---------------------------------------------------------------------------\n\n/** Add -c/--config to a command. */\nexport function addConfigOption(cmd: Command): Command {\n\tcmd.addOption(new Option(\"-c, --config <path>\", \"config file path (overrides $CODEMEM_CONFIG)\"));\n\treturn cmd;\n}\n\n// ---------------------------------------------------------------------------\n// --json / -j\n// ---------------------------------------------------------------------------\n\n/** Add -j/--json to a command. */\nexport function addJsonOption(cmd: Command): Command {\n\tcmd.addOption(new Option(\"-j, --json\", \"output as JSON\"));\n\treturn cmd;\n}\n\n// ---------------------------------------------------------------------------\n// Host / port (viewer — the default service)\n// ---------------------------------------------------------------------------\n\n/** Add --host and --port for the viewer/serve service. */\nexport function addViewerHostOptions(\n\tcmd: Command,\n\tdefaults: { host?: string; port?: string } = {},\n): Command {\n\tcmd.option(\"--host <host>\", \"viewer host\", defaults.host ?? \"127.0.0.1\");\n\tcmd.option(\"--port <port>\", \"viewer port\", defaults.port ?? \"38888\");\n\treturn cmd;\n}\n\n// ---------------------------------------------------------------------------\n// Hidden legacy aliases (accept silently, ignore)\n// ---------------------------------------------------------------------------\n\n/** Add hidden --user/--system Typer-era compatibility flags. */\nexport function addLegacyServiceFlags(cmd: Command): Command {\n\tcmd.addOption(new Option(\"--user\", \"accepted for compatibility\").default(true).hideHelp());\n\tcmd.addOption(new Option(\"--system\", \"accepted for compatibility\").hideHelp());\n\treturn cmd;\n}\n\n// ---------------------------------------------------------------------------\n// Deprecation warning helper\n// ---------------------------------------------------------------------------\n\n/** Emit a deprecation warning to stderr. */\nexport function emitDeprecationWarning(oldForm: string, newForm: string): void {\n\tconsole.error(`Warning: '${oldForm}' is deprecated, use '${newForm}' instead.`);\n}\n\n// ---------------------------------------------------------------------------\n// Structured JSON error helper\n// ---------------------------------------------------------------------------\n\n/** Print a structured JSON error to stdout and set the exit code. */\nexport function emitJsonError(errorCode: string, message: string, exitCode = 1): void {\n\tconsole.log(JSON.stringify({ error: errorCode, message }));\n\tprocess.exitCode = exitCode;\n}\n\n// ---------------------------------------------------------------------------\n// Common option type for action handlers\n// ---------------------------------------------------------------------------\n\nexport interface DbOpts {\n\tdb?: string;\n\tdbPath?: string;\n}\n\nexport interface ConfigOpts {\n\tconfig?: string;\n}\n\nexport interface JsonOpts {\n\tjson?: boolean;\n}\n\nexport interface ViewerHostOpts {\n\thost: string;\n\tport: string;\n}\n","/**\n * Append-only plugin failure log used by both `claude-hook-inject` and\n * `claude-hook-ingest` to record errors that don't justify crashing the\n * hook command itself.\n *\n * Behavior:\n * - Default log path is `~/.codemem/plugin.log`.\n * - `CODEMEM_PLUGIN_LOG_PATH` (preferred) or `CODEMEM_PLUGIN_LOG` may\n * override the path. Boolean-shaped values (`0/1/true/false/yes/no/on/off`\n * and empty) are treated as toggles, not paths, so the default is used.\n * - All I/O is best-effort: failures are swallowed.\n */\n\nimport { appendFileSync, mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nconst BOOLEAN_TOGGLE_VALUES = new Set([\"\", \"0\", \"false\", \"off\", \"1\", \"true\", \"yes\", \"on\", \"no\"]);\n\nfunction expandHome(value: string): string {\n\tif (value === \"~\") return homedir();\n\tif (value.startsWith(\"~/\")) return join(homedir(), value.slice(2));\n\treturn value;\n}\n\nexport function pluginLogPath(): string {\n\tconst raw = process.env.CODEMEM_PLUGIN_LOG_PATH ?? process.env.CODEMEM_PLUGIN_LOG ?? \"\";\n\tconst normalized = raw.trim().toLowerCase();\n\tif (BOOLEAN_TOGGLE_VALUES.has(normalized)) {\n\t\treturn expandHome(\"~/.codemem/plugin.log\");\n\t}\n\treturn expandHome(raw.trim());\n}\n\n/**\n * Append a single timestamped line to the plugin log. Best-effort: any\n * filesystem error is swallowed so a logging failure can never bubble up\n * into a Claude hook crash.\n */\nexport function logHookFailure(message: string): void {\n\tconst path = pluginLogPath();\n\ttry {\n\t\tmkdirSync(dirname(path), { recursive: true });\n\t\tappendFileSync(path, `${new Date().toISOString()} ${message}\\n`, { encoding: \"utf8\" });\n\t} catch {\n\t\t// best-effort\n\t}\n}\n","/**\n * Durability layer for `claude-hook-ingest`: file-based mutex to\n * serialize concurrent invocations, on-disk spool that captures\n * payloads when both HTTP and direct ingestion paths fail, and a\n * recovery routine that promotes stale temp files back into the queue.\n */\n\nimport { randomInt } from \"node:crypto\";\nimport {\n\tmkdirSync,\n\treaddirSync,\n\treadFileSync,\n\trenameSync,\n\trmdirSync,\n\tstatSync,\n\tunlinkSync,\n\twriteFileSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { logHookFailure } from \"./claude-hook-plugin-log.js\";\n\nconst DEFAULT_LOCK_TTL_S = 300;\nconst DEFAULT_LOCK_GRACE_S = 2;\nconst LOCK_ACQUIRE_ATTEMPTS = 100;\nconst LOCK_ACQUIRE_BACKOFF_MS = 50;\n\ntype LockSnapshot = {\n\tpid: string;\n\tts: number | null;\n\towner: string;\n};\n\ntype LockConfig = {\n\tlockDir: string;\n\tttlSeconds: number;\n\tgraceSeconds: number;\n};\n\nexport class LockBusyError extends Error {\n\tconstructor() {\n\t\tsuper(\"claude-hook-ingest lock busy\");\n\t\tthis.name = \"LockBusyError\";\n\t}\n}\n\nfunction expandHome(value: string): string {\n\tif (value === \"~\") return homedir();\n\tif (value.startsWith(\"~/\")) return join(homedir(), value.slice(2));\n\treturn value;\n}\n\nfunction envInt(name: string, fallback: number): number {\n\tconst raw = process.env[name];\n\tif (raw === undefined) return fallback;\n\tconst parsed = Number.parseInt(raw, 10);\n\treturn Number.isFinite(parsed) ? parsed : fallback;\n}\n\nfunction envTruthy(name: string, fallback: boolean): boolean {\n\tconst raw = process.env[name];\n\tif (raw === undefined) return fallback;\n\tconst normalized = raw.trim().toLowerCase();\n\tif ([\"1\", \"true\", \"yes\", \"on\"].includes(normalized)) return true;\n\tif ([\"0\", \"false\", \"no\", \"off\"].includes(normalized)) return false;\n\treturn fallback;\n}\n\nfunction lockConfig(): LockConfig {\n\tconst lockDir = expandHome(\n\t\tprocess.env.CODEMEM_CLAUDE_HOOK_LOCK_DIR?.trim() || \"~/.codemem/claude-hook-ingest.lock\",\n\t);\n\treturn {\n\t\tlockDir,\n\t\tttlSeconds: Math.max(1, envInt(\"CODEMEM_CLAUDE_HOOK_LOCK_TTL_S\", DEFAULT_LOCK_TTL_S)),\n\t\tgraceSeconds: Math.max(1, envInt(\"CODEMEM_CLAUDE_HOOK_LOCK_GRACE_S\", DEFAULT_LOCK_GRACE_S)),\n\t};\n}\n\nexport function spoolDir(): string {\n\treturn expandHome(\n\t\tprocess.env.CODEMEM_CLAUDE_HOOK_SPOOL_DIR?.trim() || \"~/.codemem/claude-hook-spool\",\n\t);\n}\n\n/**\n * Cheap pre-check used by the unlocked HTTP-success path to decide\n * whether it needs to acquire the ingest lock and drain queued\n * payloads. Returns true when the spool directory contains at least\n * one active entry (a `*.json` file that is neither an in-flight\n * `.hook-tmp-*` nor a quarantined `.bad-*` file). Any I/O failure\n * is treated as \"no entries\" so callers stay on the fast path.\n */\nexport function hasSpooledEntries(): boolean {\n\tconst dir = spoolDir();\n\tlet entries: string[];\n\ttry {\n\t\tentries = readdirSync(dir);\n\t} catch {\n\t\treturn false;\n\t}\n\tfor (const name of entries) {\n\t\tif (!name.endsWith(\".json\")) continue;\n\t\tif (name.startsWith(\".hook-tmp-\") || name.startsWith(\".bad-\")) continue;\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nfunction readFileTrimmedOrEmpty(path: string): string {\n\ttry {\n\t\treturn readFileSync(path, \"utf8\").trim();\n\t} catch {\n\t\treturn \"\";\n\t}\n}\n\nfunction readLockMetadata(lockDir: string): LockSnapshot {\n\tconst pid = readFileTrimmedOrEmpty(join(lockDir, \"pid\"));\n\tconst owner = readFileTrimmedOrEmpty(join(lockDir, \"owner\"));\n\tconst tsRaw = readFileTrimmedOrEmpty(join(lockDir, \"ts\"));\n\tconst ts = tsRaw === \"\" ? null : Number.parseInt(tsRaw, 10);\n\treturn {\n\t\tpid,\n\t\tts: ts === null || !Number.isFinite(ts) ? null : ts,\n\t\towner,\n\t};\n}\n\nfunction isPidAlive(pidText: string): boolean {\n\tconst pid = Number.parseInt(pidText, 10);\n\tif (!Number.isFinite(pid) || pid <= 0) return false;\n\ttry {\n\t\t// Signal 0 performs the existence check without delivering a signal.\n\t\tprocess.kill(pid, 0);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction lockIsStale(cfg: LockConfig): { stale: boolean; snapshot: LockSnapshot } {\n\tconst snapshot = readLockMetadata(cfg.lockDir);\n\tconst nowS = Math.floor(Date.now() / 1000);\n\n\tif (snapshot.pid) {\n\t\tif (isPidAlive(snapshot.pid)) {\n\t\t\tif (snapshot.ts === null) return { stale: false, snapshot };\n\t\t\treturn { stale: nowS - snapshot.ts > cfg.ttlSeconds, snapshot };\n\t\t}\n\t\treturn { stale: true, snapshot };\n\t}\n\n\tif (snapshot.ts !== null) {\n\t\treturn { stale: nowS - snapshot.ts > cfg.graceSeconds, snapshot };\n\t}\n\n\tlet mtimeS: number;\n\ttry {\n\t\tmtimeS = Math.floor(statSync(cfg.lockDir).mtimeMs / 1000);\n\t} catch {\n\t\treturn { stale: true, snapshot };\n\t}\n\treturn { stale: nowS - mtimeS > cfg.graceSeconds, snapshot };\n}\n\nfunction cleanupLockDir(lockDir: string): void {\n\tfor (const name of [\"pid\", \"ts\", \"owner\"]) {\n\t\ttry {\n\t\t\tunlinkSync(join(lockDir, name));\n\t\t} catch {\n\t\t\t// best-effort\n\t\t}\n\t}\n\ttry {\n\t\trmdirSync(lockDir);\n\t} catch {\n\t\t// best-effort\n\t}\n}\n\nfunction snapshotsEqual(a: LockSnapshot, b: LockSnapshot): boolean {\n\treturn a.pid === b.pid && a.ts === b.ts && a.owner === b.owner;\n}\n\nfunction cleanupLockDirIfUnchanged(lockDir: string, snapshot: LockSnapshot): void {\n\tconst current = readLockMetadata(lockDir);\n\tif (snapshotsEqual(current, snapshot)) {\n\t\tcleanupLockDir(lockDir);\n\t}\n}\n\nfunction isErrnoException(err: unknown): err is NodeJS.ErrnoException {\n\treturn typeof err === \"object\" && err !== null && \"code\" in err;\n}\n\nasync function sleep(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Run `fn` while holding the claude-hook-ingest lock. Throws\n * `LockBusyError` when the lock cannot be acquired within\n * `LOCK_ACQUIRE_ATTEMPTS` attempts.\n *\n * The lock is a directory at `lockDir`, with three sentinel files\n * (`pid`, `ts`, `owner`) recording who currently holds it. Stale locks\n * are detected via PID liveness, TTL, and a grace window for the\n * race between mkdir and writing pid/ts.\n */\nexport async function withClaudeHookIngestLock<T>(fn: () => Promise<T> | T): Promise<T> {\n\tconst cfg = lockConfig();\n\tmkdirSync(dirname(cfg.lockDir), { recursive: true });\n\tconst ownerToken = `${process.pid}-${Math.floor(Date.now() / 1000)}-${randomInt(1000, 10000)}`;\n\n\tlet acquired = false;\n\tfor (let attempt = 0; attempt < LOCK_ACQUIRE_ATTEMPTS; attempt++) {\n\t\ttry {\n\t\t\tmkdirSync(cfg.lockDir);\n\t\t} catch (err) {\n\t\t\tif (isErrnoException(err) && err.code === \"EEXIST\") {\n\t\t\t\tconst { stale, snapshot } = lockIsStale(cfg);\n\t\t\t\tif (stale) {\n\t\t\t\t\tcleanupLockDirIfUnchanged(cfg.lockDir, snapshot);\n\t\t\t\t}\n\t\t\t\tawait sleep(LOCK_ACQUIRE_BACKOFF_MS);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tawait sleep(LOCK_ACQUIRE_BACKOFF_MS);\n\t\t\tcontinue;\n\t\t}\n\n\t\ttry {\n\t\t\twriteFileSync(join(cfg.lockDir, \"ts\"), String(Math.floor(Date.now() / 1000)), {\n\t\t\t\tencoding: \"utf8\",\n\t\t\t});\n\t\t\twriteFileSync(join(cfg.lockDir, \"pid\"), String(process.pid), { encoding: \"utf8\" });\n\t\t\twriteFileSync(join(cfg.lockDir, \"owner\"), ownerToken, { encoding: \"utf8\" });\n\t\t\tacquired = true;\n\t\t\tbreak;\n\t\t} catch {\n\t\t\tcleanupLockDir(cfg.lockDir);\n\t\t\tawait sleep(LOCK_ACQUIRE_BACKOFF_MS);\n\t\t}\n\t}\n\n\tif (!acquired) {\n\t\tthrow new LockBusyError();\n\t}\n\n\ttry {\n\t\treturn await fn();\n\t} finally {\n\t\tconst currentOwner = readFileTrimmedOrEmpty(join(cfg.lockDir, \"owner\"));\n\t\tif (currentOwner === ownerToken) {\n\t\t\tcleanupLockDir(cfg.lockDir);\n\t\t}\n\t}\n}\n\n/**\n * Persist a payload to the spool directory using a tmp+rename so that\n * a partially-written file is never visible to the drainer. Returns\n * true on success, false on any I/O failure.\n */\nexport function spoolPayload(payload: Record<string, unknown>): boolean {\n\tconst dir = spoolDir();\n\ttry {\n\t\tmkdirSync(dir, { recursive: true });\n\t} catch {\n\t\tlogHookFailure(\"codemem claude-hook-ingest failed to create spool dir\");\n\t\treturn false;\n\t}\n\n\tconst payloadText = JSON.stringify(payload);\n\tconst tmpName = `.hook-tmp-${process.pid}-${Date.now()}-${randomInt(1000, 10000)}.json`;\n\tconst tmpPath = join(dir, tmpName);\n\ttry {\n\t\twriteFileSync(tmpPath, payloadText, { encoding: \"utf8\" });\n\t} catch {\n\t\tlogHookFailure(\"codemem claude-hook-ingest failed to allocate spool temp file\");\n\t\treturn false;\n\t}\n\n\tconst finalName = `hook-${Math.floor(Date.now() / 1000)}-${process.pid}-${randomInt(1000, 10000)}.json`;\n\tconst finalPath = join(dir, finalName);\n\ttry {\n\t\trenameSync(tmpPath, finalPath);\n\t} catch {\n\t\ttry {\n\t\t\tunlinkSync(tmpPath);\n\t\t} catch {\n\t\t\t// best-effort\n\t\t}\n\t\tlogHookFailure(\"codemem claude-hook-ingest failed to spool payload\");\n\t\treturn false;\n\t}\n\tlogHookFailure(`codemem claude-hook-ingest spooled payload: ${finalPath}`);\n\treturn true;\n}\n\n/**\n * Promote any `.hook-tmp-*.json` files older than `ttlSeconds` to a\n * recovered name so they are picked up by the next drain. Caller is\n * responsible for passing the same TTL used by lock acquisition so\n * that an in-flight write inside an active locked region is never\n * mistaken for a crashed-writer leftover.\n */\nexport function recoverStaleTmpSpool(ttlSeconds: number): void {\n\tconst dir = spoolDir();\n\ttry {\n\t\tmkdirSync(dir, { recursive: true });\n\t} catch {\n\t\treturn;\n\t}\n\n\tlet entries: string[];\n\ttry {\n\t\tentries = readdirSync(dir);\n\t} catch {\n\t\treturn;\n\t}\n\n\tconst nowS = Date.now() / 1000;\n\tfor (const name of entries) {\n\t\tif (!name.startsWith(\".hook-tmp-\") || !name.endsWith(\".json\")) continue;\n\t\tconst tmpPath = join(dir, name);\n\t\tlet mtimeS: number;\n\t\ttry {\n\t\t\tmtimeS = statSync(tmpPath).mtimeMs / 1000;\n\t\t} catch {\n\t\t\tcontinue;\n\t\t}\n\t\tif (nowS - mtimeS <= ttlSeconds) continue;\n\n\t\tconst recoveredName = `hook-recovered-${Math.floor(nowS)}-${process.pid}-${randomInt(1000, 10000)}.json`;\n\t\tconst recoveredPath = join(dir, recoveredName);\n\t\ttry {\n\t\t\trenameSync(tmpPath, recoveredPath);\n\t\t\tlogHookFailure(\n\t\t\t\t`codemem claude-hook-ingest recovered stale temp spool payload: ${recoveredPath}`,\n\t\t\t);\n\t\t} catch {\n\t\t\t// best-effort\n\t\t}\n\t}\n}\n\n/**\n * Move a permanently-broken spool entry out of the queue so that it\n * stops being picked up by future drains. The entry is renamed in\n * place with a `.bad-<reason>-` prefix so an operator can inspect or\n * delete it manually.\n */\nfunction quarantineSpoolEntry(dir: string, name: string, reason: string): void {\n\tconst sourcePath = join(dir, name);\n\tconst quarantineName = `.bad-${reason}-${Date.now()}-${randomInt(1000, 10000)}-${name}`;\n\ttry {\n\t\trenameSync(sourcePath, join(dir, quarantineName));\n\t\tlogHookFailure(\n\t\t\t`codemem claude-hook-ingest quarantined corrupt spool payload (${reason}): ${quarantineName}`,\n\t\t);\n\t} catch {\n\t\t// If rename fails, fall back to delete; either way the broken\n\t\t// entry must not stay in the active queue.\n\t\ttry {\n\t\t\tunlinkSync(sourcePath);\n\t\t\tlogHookFailure(\n\t\t\t\t`codemem claude-hook-ingest dropped corrupt spool payload (${reason}): ${name}`,\n\t\t\t);\n\t\t} catch {\n\t\t\t// best-effort\n\t\t}\n\t}\n}\n\nexport type SpoolHandler = (payload: Record<string, unknown>) => Promise<boolean> | boolean;\n\nexport type SpoolDrainResult = {\n\tprocessed: number;\n\tfailed: number;\n};\n\n/**\n * Process every queued payload in the spool directory in lexicographic\n * order (which approximates oldest-first because filenames embed the\n * second-precision creation timestamp). The handler returns true to\n * indicate the payload has been durably accepted; only then is the\n * spool entry deleted. Failed entries are left on disk for the next\n * drain attempt.\n */\nexport async function drainSpool(handler: SpoolHandler): Promise<SpoolDrainResult> {\n\tconst dir = spoolDir();\n\ttry {\n\t\tmkdirSync(dir, { recursive: true });\n\t} catch {\n\t\treturn { processed: 0, failed: 0 };\n\t}\n\n\tlet entries: string[];\n\ttry {\n\t\tentries = readdirSync(dir);\n\t} catch {\n\t\treturn { processed: 0, failed: 0 };\n\t}\n\n\tconst queued = entries\n\t\t.filter(\n\t\t\t(name) =>\n\t\t\t\tname.endsWith(\".json\") && !name.startsWith(\".hook-tmp-\") && !name.startsWith(\".bad-\"),\n\t\t)\n\t\t.sort();\n\n\tconst result: SpoolDrainResult = { processed: 0, failed: 0 };\n\tfor (const name of queued) {\n\t\tconst path = join(dir, name);\n\t\tlet raw: string;\n\t\ttry {\n\t\t\traw = readFileSync(path, \"utf8\");\n\t\t} catch {\n\t\t\t// Genuine I/O failure — leave the file alone so the next drain\n\t\t\t// can retry, and surface the failure to the plugin log.\n\t\t\tlogHookFailure(`codemem claude-hook-ingest failed to read spooled payload: ${path}`);\n\t\t\tresult.failed++;\n\t\t\tcontinue;\n\t\t}\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(raw);\n\t\t} catch {\n\t\t\t// Permanently corrupt content — keeping the file around would\n\t\t\t// loop forever every drain. Quarantine it under a `.bad-` prefix\n\t\t\t// so an operator can inspect it without it being picked up again.\n\t\t\tquarantineSpoolEntry(dir, name, \"parse-error\");\n\t\t\tresult.failed++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (parsed == null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\t\t// Parseable but wrong shape — same problem, same fix.\n\t\t\tquarantineSpoolEntry(dir, name, \"wrong-shape\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tlet ok = false;\n\t\ttry {\n\t\t\tok = await handler(parsed as Record<string, unknown>);\n\t\t} catch {\n\t\t\tok = false;\n\t\t}\n\n\t\tif (ok) {\n\t\t\ttry {\n\t\t\t\tunlinkSync(path);\n\t\t\t\tresult.processed++;\n\t\t\t} catch {\n\t\t\t\t// best-effort\n\t\t\t}\n\t\t} else {\n\t\t\tlogHookFailure(`codemem claude-hook-ingest failed processing spooled payload: ${path}`);\n\t\t\tresult.failed++;\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Whether the boundary-flush write-through should run for this hook\n * payload. SessionEnd defaults to forcing a flush; Stop only flushes\n * when both CODEMEM_CLAUDE_HOOK_FLUSH and CODEMEM_CLAUDE_HOOK_FLUSH_ON_STOP\n * are truthy.\n */\nexport function shouldForceBoundaryFlush(payload: Record<string, unknown>): boolean {\n\tconst eventName =\n\t\ttypeof payload.hook_event_name === \"string\" ? payload.hook_event_name.trim() : \"\";\n\tif (eventName !== \"Stop\" && eventName !== \"SessionEnd\") return false;\n\tif (eventName === \"SessionEnd\") {\n\t\treturn envTruthy(\"CODEMEM_CLAUDE_HOOK_FLUSH\", true);\n\t}\n\tif (!envTruthy(\"CODEMEM_CLAUDE_HOOK_FLUSH\", false)) return false;\n\treturn envTruthy(\"CODEMEM_CLAUDE_HOOK_FLUSH_ON_STOP\", false);\n}\n\n/**\n * Returns the configured lock TTL so callers (`claude-hook-ingest`)\n * can pass the same value to `recoverStaleTmpSpool` without re-reading\n * the env.\n */\nexport function lockTtlSeconds(): number {\n\treturn lockConfig().ttlSeconds;\n}\n","/**\n * Session-state tracking for Claude Code hook commands.\n *\n * Persists per-session signal (first prompt, latest prompt, recently\n * modified files) to disk so that retrieval inside `claude-hook-inject`\n * can build a query richer than the bare current prompt and so that\n * file-locality boosts can target files the user just edited.\n */\n\nimport { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport type SessionState = {\n\tfirst_prompt: string;\n\tlast_prompt: string;\n\tfiles_modified: string[];\n\tupdated_at: string;\n};\n\nconst MAX_FILES_MODIFIED = 64;\nconst MAX_WORKING_SET_PATHS = 8;\nconst MAX_QUERY_CHARS = 500;\nconst MAX_QUERY_FILE_BASENAMES = 5;\n\nconst MUTATING_TOOL_NAMES = new Set([\"edit\", \"write\", \"multiedit\", \"notebookedit\", \"apply_patch\"]);\n\nconst APPLY_PATCH_PATH_PREFIXES = [\"*** Add File: \", \"*** Update File: \", \"*** Delete File: \"];\n\nexport function defaultSessionState(): SessionState {\n\treturn {\n\t\tfirst_prompt: \"\",\n\t\tlast_prompt: \"\",\n\t\tfiles_modified: [],\n\t\tupdated_at: \"\",\n\t};\n}\n\nfunction expandHome(value: string): string {\n\tif (value === \"~\") return homedir();\n\tif (value.startsWith(\"~/\")) return join(homedir(), value.slice(2));\n\treturn value;\n}\n\nexport function contextDir(): string {\n\tconst override = process.env.CODEMEM_CLAUDE_HOOK_CONTEXT_DIR;\n\treturn expandHome(override?.trim() ? override : \"~/.codemem/claude-hook-context\");\n}\n\nexport function statePathForSession(sessionId: string): string {\n\tconst digest = createHash(\"sha1\").update(sessionId).digest(\"hex\").slice(0, 16);\n\treturn join(contextDir(), `${digest}.json`);\n}\n\n/**\n * Normalize a prompt-shaped payload field: drop non-strings, trim\n * leading/trailing whitespace, and collapse newlines to spaces so that\n * prompts compared across the inject + ingest paths and across turns\n * within a session use the same canonical form.\n */\nexport function normalizePromptText(value: unknown): string {\n\tif (typeof value !== \"string\") return \"\";\n\treturn value.trim().replace(/\\n/g, \" \");\n}\n\nfunction normalizeStringList(value: unknown, cap: number): string[] {\n\tif (!Array.isArray(value)) return [];\n\tconst out: string[] = [];\n\tfor (const item of value) {\n\t\tif (typeof item !== \"string\") continue;\n\t\tconst trimmed = item.trim();\n\t\tif (trimmed) out.push(trimmed);\n\t}\n\treturn out.slice(0, cap);\n}\n\nexport function loadSessionState(sessionId: string): SessionState {\n\tconst path = statePathForSession(sessionId);\n\tif (!existsSync(path)) return defaultSessionState();\n\ttry {\n\t\tconst raw = readFileSync(path, \"utf8\");\n\t\tconst parsed: unknown = JSON.parse(raw);\n\t\tif (parsed == null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\t\treturn defaultSessionState();\n\t\t}\n\t\tconst obj = parsed as Record<string, unknown>;\n\t\treturn {\n\t\t\tfirst_prompt: typeof obj.first_prompt === \"string\" ? obj.first_prompt.trim() : \"\",\n\t\t\tlast_prompt: typeof obj.last_prompt === \"string\" ? obj.last_prompt.trim() : \"\",\n\t\t\tfiles_modified: normalizeStringList(obj.files_modified, MAX_FILES_MODIFIED),\n\t\t\tupdated_at: typeof obj.updated_at === \"string\" ? obj.updated_at.trim() : \"\",\n\t\t};\n\t} catch {\n\t\treturn defaultSessionState();\n\t}\n}\n\nfunction nowIso(): string {\n\treturn new Date().toISOString();\n}\n\nexport function saveSessionState(sessionId: string, state: SessionState): void {\n\tconst dir = contextDir();\n\tmkdirSync(dir, { recursive: true });\n\tconst path = statePathForSession(sessionId);\n\tconst tmpPath = `${path}.tmp`;\n\tconst payload = {\n\t\tfirst_prompt: String(state.first_prompt ?? \"\"),\n\t\tlast_prompt: String(state.last_prompt ?? \"\"),\n\t\tfiles_modified: normalizeStringList(state.files_modified, MAX_FILES_MODIFIED),\n\t\tupdated_at: String(state.updated_at ?? \"\"),\n\t};\n\twriteFileSync(tmpPath, JSON.stringify(payload), { encoding: \"utf8\" });\n\trenameSync(tmpPath, path);\n}\n\nexport function clearSessionState(sessionId: string): void {\n\tconst path = statePathForSession(sessionId);\n\ttry {\n\t\trmSync(path, { force: true });\n\t} catch {\n\t\t// best-effort: failure to clear an unreachable file is non-fatal\n\t}\n}\n\nfunction extractApplyPatchPaths(patchText: string): string[] {\n\tconst out: string[] = [];\n\tfor (const line of patchText.split(\"\\n\")) {\n\t\tfor (const prefix of APPLY_PATCH_PATH_PREFIXES) {\n\t\t\tif (line.startsWith(prefix)) {\n\t\t\t\tconst path = line.slice(prefix.length).trim();\n\t\t\t\tif (path) out.push(path);\n\t\t\t}\n\t\t}\n\t}\n\treturn out;\n}\n\nexport function extractModifiedPathsFromHook(payload: Record<string, unknown>): string[] {\n\tconst toolName = String(payload.tool_name ?? \"\")\n\t\t.trim()\n\t\t.toLowerCase();\n\tif (!MUTATING_TOOL_NAMES.has(toolName)) return [];\n\n\tconst toolInput = payload.tool_input;\n\tif (toolInput == null || typeof toolInput !== \"object\" || Array.isArray(toolInput)) {\n\t\treturn [];\n\t}\n\tconst obj = toolInput as Record<string, unknown>;\n\n\tconst collected: string[] = [];\n\tfor (const key of [\"filePath\", \"file_path\", \"path\"]) {\n\t\tconst value = obj[key];\n\t\tif (typeof value === \"string\") {\n\t\t\tconst trimmed = value.trim();\n\t\t\tif (trimmed) collected.push(trimmed);\n\t\t}\n\t}\n\tif (toolName === \"apply_patch\") {\n\t\t// `patchText` is the canonical key, but some agents send an empty\n\t\t// `patchText` alongside the real patch in `patch`. Use a falsy\n\t\t// fallback (not `??`) so an empty `patchText` doesn't shadow it.\n\t\tconst primary =\n\t\t\ttypeof obj.patchText === \"string\" && obj.patchText.trim() ? obj.patchText : null;\n\t\tconst patchText = primary ?? (typeof obj.patch === \"string\" ? obj.patch : null);\n\t\tif (patchText?.trim()) {\n\t\t\tcollected.push(...extractApplyPatchPaths(patchText));\n\t\t}\n\t}\n\n\tconst seen = new Set<string>();\n\tconst ordered: string[] = [];\n\tfor (const path of collected) {\n\t\tif (seen.has(path)) continue;\n\t\tseen.add(path);\n\t\tordered.push(path);\n\t}\n\treturn ordered;\n}\n\n/**\n * Update the on-disk session state for a hook payload and return the\n * resulting state. Returns null when the payload has no usable session_id\n * or when SessionEnd just cleared the state. Failures are swallowed —\n * hook commands must never crash on state I/O errors.\n */\nexport function trackHookSessionState(payload: Record<string, unknown>): SessionState | null {\n\tconst sessionRaw = payload.session_id;\n\tif (typeof sessionRaw !== \"string\") return null;\n\tconst sessionId = sessionRaw.trim();\n\tif (!sessionId) return null;\n\n\tconst hookEventName =\n\t\ttypeof payload.hook_event_name === \"string\" ? payload.hook_event_name.trim() : \"\";\n\n\tif (hookEventName === \"SessionEnd\") {\n\t\tclearSessionState(sessionId);\n\t\treturn null;\n\t}\n\n\tconst state = loadSessionState(sessionId);\n\tlet changed = false;\n\n\tif (hookEventName === \"UserPromptSubmit\") {\n\t\tconst prompt = normalizePromptText(payload.prompt);\n\t\tif (prompt) {\n\t\t\tif (!state.first_prompt) {\n\t\t\t\tstate.first_prompt = prompt;\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t\tif (state.last_prompt !== prompt) {\n\t\t\t\tstate.last_prompt = prompt;\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t}\n\t} else if (hookEventName === \"PostToolUse\" || hookEventName === \"PostToolUseFailure\") {\n\t\tconst existing = state.files_modified.filter((path) => path.trim().length > 0);\n\t\tconst seen = new Set(existing);\n\t\tfor (const path of extractModifiedPathsFromHook(payload)) {\n\t\t\tif (seen.has(path)) continue;\n\t\t\texisting.push(path);\n\t\t\tseen.add(path);\n\t\t\tchanged = true;\n\t\t}\n\t\tstate.files_modified = existing.slice(-MAX_FILES_MODIFIED);\n\t}\n\n\tif (changed) {\n\t\tstate.updated_at = nowIso();\n\t\ttry {\n\t\t\tsaveSessionState(sessionId, state);\n\t\t} catch {\n\t\t\t// best-effort: dropping a state update is preferable to crashing the hook\n\t\t}\n\t}\n\treturn state;\n}\n\nfunction pathBasename(value: string): string {\n\tconst normalized = value.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n\tif (!normalized) return \"\";\n\tconst parts = normalized.split(\"/\");\n\treturn parts[parts.length - 1] ?? \"\";\n}\n\n/**\n * Compose a retrieval query that combines the original session intent,\n * the current prompt, the project, and recent modified file basenames.\n * Caps the result at 500 characters.\n */\nexport function buildInjectQuery(args: {\n\tprompt: string;\n\tproject: string | null;\n\tstate: SessionState | null;\n}): string {\n\tconst parts: string[] = [];\n\tconst firstPrompt = args.state ? normalizePromptText(args.state.first_prompt) : \"\";\n\tconst filesModified = args.state\n\t\t? args.state.files_modified.filter((item) => item.trim().length > 0)\n\t\t: [];\n\n\tif (firstPrompt) parts.push(firstPrompt);\n\tif (args.prompt && args.prompt !== firstPrompt && args.prompt.length > 5) {\n\t\tparts.push(args.prompt);\n\t}\n\tif (args.project) parts.push(args.project);\n\tif (filesModified.length > 0) {\n\t\tconst names = filesModified\n\t\t\t.slice(-MAX_QUERY_FILE_BASENAMES)\n\t\t\t.map(pathBasename)\n\t\t\t.filter((name) => name.length > 0);\n\t\tif (names.length > 0) parts.push(names.join(\" \"));\n\t}\n\n\tif (parts.length === 0) return \"recent work\";\n\tconst query = parts.join(\" \");\n\treturn query.length > MAX_QUERY_CHARS ? query.slice(0, MAX_QUERY_CHARS) : query;\n}\n\n/** Return the working set paths (last N modified files) for pack filters. */\nexport function workingSetPathsFromState(state: SessionState | null): string[] {\n\tif (!state) return [];\n\tconst files = state.files_modified.filter((path) => path.trim().length > 0);\n\treturn files.slice(-MAX_WORKING_SET_PATHS);\n}\n","/**\n * codemem claude-hook-ingest — read a single Claude Code hook payload\n * from stdin and enqueue it for processing.\n *\n * HTTP-first strategy: POST to the running viewer's /api/claude-hooks\n * endpoint, then fall back to direct raw-event enqueue via the local\n * store when the viewer is unreachable.\n *\n * Usage (from Claude hooks config):\n * echo '{\"hook_event_name\":\"Stop\",\"session_id\":\"...\",\"last_assistant_message\":\"...\"}' \\\n * | codemem claude-hook-ingest\n */\n\nimport { readFileSync } from \"node:fs\";\nimport {\n\tbuildRawEventEnvelopeFromHook,\n\tconnect,\n\tensureSchemaBootstrapped,\n\tflushRawEvents,\n\tloadSqliteVec,\n\tMemoryStore,\n\tObserverClient,\n\tresolveDbPath,\n\tstripPrivateObj,\n} from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport { addDbOption, addViewerHostOptions, type DbOpts, resolveDbOpt } from \"../shared-options.js\";\nimport {\n\tdrainSpool,\n\thasSpooledEntries,\n\tLockBusyError,\n\tlockTtlSeconds,\n\trecoverStaleTmpSpool,\n\tshouldForceBoundaryFlush,\n\tspoolPayload,\n\twithClaudeHookIngestLock,\n} from \"./claude-hook-ingest-spool.js\";\nimport { logHookFailure } from \"./claude-hook-plugin-log.js\";\nimport { trackHookSessionState } from \"./claude-hook-session-state.js\";\n\ntype IngestVia = \"http\" | \"direct\" | \"spool\" | \"spool_lock_busy\";\n\ntype IngestResult = { inserted: number; skipped: number; via: IngestVia };\n\ntype IngestOpts = {\n\thost: string;\n\tport: string | number;\n} & DbOpts;\n\ntype IngestDeps = {\n\thttpIngest?: typeof tryHttpIngest;\n\tdirectIngest?: typeof directEnqueue;\n\tresolveDb?: typeof resolveDbPath;\n\tboundaryFlush?: (payload: Record<string, unknown>, dbPath: string) => Promise<void> | void;\n};\n\nfunction emitStructuredError(errorCode: string, message: string): void {\n\tconsole.log(JSON.stringify({ error: errorCode, message }));\n\tprocess.exitCode = 1;\n}\n\n/** Try to POST the hook payload to the running viewer server.\n *\n * Returns `ok: true` whenever the viewer accepts the request and\n * returns a well-shaped JSON body with numeric `inserted` / `skipped`\n * fields. That includes the `{inserted: 0, skipped: 1}` response the\n * viewer emits when the payload maps to a null envelope (Stop with no\n * assistant text, UserPromptSubmit with empty prompt, etc.) — that\n * determination is deterministic, so retrying via the direct fallback\n * would produce the exact same null envelope and the same skip. We\n * accept those as benign no-ops instead of triggering the durability\n * dance pointlessly.\n *\n * If a future server change adds a new `skipped` reason that IS\n * transient, we'll need a reason field in the response and updated\n * client handling — not an unconditional fail-over.\n */\nasync function tryHttpIngest(\n\tpayload: Record<string, unknown>,\n\thost: string,\n\tport: number,\n): Promise<{ ok: boolean; inserted: number; skipped: number }> {\n\tconst url = `http://${host}:${port}/api/claude-hooks`;\n\tconst controller = new AbortController();\n\tconst timeout = setTimeout(() => controller.abort(), 5000);\n\ttry {\n\t\tconst res = await fetch(url, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify(payload),\n\t\t\tsignal: controller.signal,\n\t\t});\n\t\tif (!res.ok) return { ok: false, inserted: 0, skipped: 0 };\n\n\t\tlet body: unknown;\n\t\ttry {\n\t\t\tbody = await res.json();\n\t\t} catch {\n\t\t\tlogHookFailure(\"codemem claude-hook-ingest HTTP accepted with invalid response body\");\n\t\t\treturn { ok: false, inserted: 0, skipped: 0 };\n\t\t}\n\t\tif (body == null || typeof body !== \"object\" || Array.isArray(body)) {\n\t\t\tlogHookFailure(\"codemem claude-hook-ingest HTTP accepted with invalid response type\");\n\t\t\treturn { ok: false, inserted: 0, skipped: 0 };\n\t\t}\n\t\tconst obj = body as Record<string, unknown>;\n\t\tif (typeof obj.inserted !== \"number\" || typeof obj.skipped !== \"number\") {\n\t\t\tlogHookFailure(\"codemem claude-hook-ingest HTTP accepted with unexpected response body\");\n\t\t\treturn { ok: false, inserted: 0, skipped: 0 };\n\t\t}\n\t\treturn { ok: true, inserted: obj.inserted, skipped: obj.skipped };\n\t} catch {\n\t\treturn { ok: false, inserted: 0, skipped: 0 };\n\t} finally {\n\t\tclearTimeout(timeout);\n\t}\n}\n\n/** Fall back to direct raw-event enqueue via the local SQLite store. */\nexport function directEnqueue(\n\tpayload: Record<string, unknown>,\n\tdbPath: string,\n): { inserted: number; skipped: number } {\n\tconst envelope = buildRawEventEnvelopeFromHook(payload);\n\tif (!envelope) return { inserted: 0, skipped: 1 };\n\n\tconst db = connect(dbPath);\n\ttry {\n\t\ttry {\n\t\t\tloadSqliteVec(db);\n\t\t} catch {\n\t\t\t// sqlite-vec not available — non-fatal for raw event enqueue\n\t\t}\n\t\t// Auto-bootstrap fresh databases before touching raw_events. The MCP\n\t\t// server's MemoryStore constructor normally bootstraps first, but\n\t\t// hooks can race its startup (claude-hook-ingest is a separate CLI\n\t\t// process) so we can't rely on that ordering.\n\t\tensureSchemaBootstrapped(db);\n\t\tconst strippedPayload = stripPrivateObj(envelope.payload) as Record<string, unknown>;\n\t\tconst existing = db\n\t\t\t.prepare(\n\t\t\t\t\"SELECT 1 FROM raw_events WHERE source = ? AND stream_id = ? AND event_id = ? LIMIT 1\",\n\t\t\t)\n\t\t\t.get(envelope.source, envelope.session_stream_id, envelope.event_id);\n\t\tif (existing) return { inserted: 0, skipped: 0 };\n\n\t\tdb.prepare(\n\t\t\t`INSERT INTO raw_events(\n\t\t\t\tsource, stream_id, opencode_session_id, event_id, event_seq,\n\t\t\t\tevent_type, ts_wall_ms, payload_json, created_at\n\t\t\t) VALUES (?, ?, ?, ?, (\n\t\t\t\tSELECT COALESCE(MAX(event_seq), 0) + 1\n\t\t\t\tFROM raw_events WHERE source = ? AND stream_id = ?\n\t\t\t), ?, ?, ?, datetime('now'))`,\n\t\t).run(\n\t\t\tenvelope.source,\n\t\t\tenvelope.session_stream_id,\n\t\t\tenvelope.opencode_session_id,\n\t\t\tenvelope.event_id,\n\t\t\tenvelope.source,\n\t\t\tenvelope.session_stream_id,\n\t\t\t\"claude.hook\",\n\t\t\tenvelope.ts_wall_ms,\n\t\t\tJSON.stringify(strippedPayload),\n\t\t);\n\n\t\t// Query actual max event_seq for this stream to keep session metadata in sync\n\t\tconst maxSeqRow = db\n\t\t\t.prepare(\n\t\t\t\t\"SELECT COALESCE(MAX(event_seq), 0) AS max_seq FROM raw_events WHERE source = ? AND stream_id = ?\",\n\t\t\t)\n\t\t\t.get(envelope.source, envelope.session_stream_id) as { max_seq: number };\n\t\tconst currentMaxSeq = maxSeqRow.max_seq;\n\n\t\t// Upsert session metadata with accurate sequence tracking\n\t\tdb.prepare(\n\t\t\t`INSERT INTO raw_event_sessions(\n\t\t\t\tsource, stream_id, opencode_session_id, cwd, project, started_at,\n\t\t\t\tlast_seen_ts_wall_ms, last_received_event_seq, last_flushed_event_seq, updated_at\n\t\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, -1, datetime('now'))\n\t\t\tON CONFLICT(source, stream_id) DO UPDATE SET\n\t\t\t\tcwd = COALESCE(excluded.cwd, cwd),\n\t\t\t\tproject = COALESCE(excluded.project, project),\n\t\t\t\tstarted_at = COALESCE(excluded.started_at, started_at),\n\t\t\t\tlast_seen_ts_wall_ms = MAX(COALESCE(excluded.last_seen_ts_wall_ms, 0), COALESCE(last_seen_ts_wall_ms, 0)),\n\t\t\t\tlast_received_event_seq = MAX(excluded.last_received_event_seq, last_received_event_seq),\n\t\t\t\tupdated_at = datetime('now')`,\n\t\t).run(\n\t\t\tenvelope.source,\n\t\t\tenvelope.session_stream_id,\n\t\t\tenvelope.opencode_session_id,\n\t\t\tenvelope.cwd,\n\t\t\tenvelope.project,\n\t\t\tenvelope.started_at,\n\t\t\tenvelope.ts_wall_ms,\n\t\t\tcurrentMaxSeq,\n\t\t);\n\n\t\treturn { inserted: 1, skipped: 0 };\n\t} finally {\n\t\tdb.close();\n\t}\n}\n\n/**\n * Best-effort boundary flush: write the payload through to the local\n * store (so the just-fired SessionEnd / Stop event is durable in\n * raw_events) and then run a synchronous flushRawEvents pass so that\n * the latest memories are extracted before the hook process exits and\n * the user closes their terminal.\n *\n * Any failure here \\u2014 observer construction, store I/O, flush errors,\n * or simply running without observer credentials \\u2014 is logged to\n * `~/.codemem/plugin.log` and swallowed. The hook command must never\n * crash on a boundary flush failure.\n */\nasync function flushBoundaryRawEvents(\n\tpayload: Record<string, unknown>,\n\tdbPath: string,\n): Promise<void> {\n\tconst envelope = buildRawEventEnvelopeFromHook(payload);\n\tif (!envelope) return;\n\n\tlet observer: ObserverClient;\n\ttry {\n\t\tobserver = new ObserverClient();\n\t} catch (err) {\n\t\tlogHookFailure(\n\t\t\t`codemem claude-hook-ingest boundary flush observer init failed: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t\treturn;\n\t}\n\n\tlet store: MemoryStore;\n\ttry {\n\t\tstore = new MemoryStore(dbPath);\n\t} catch (err) {\n\t\tlogHookFailure(\n\t\t\t`codemem claude-hook-ingest boundary flush store init failed: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t\treturn;\n\t}\n\n\ttry {\n\t\tawait flushRawEvents(\n\t\t\tstore,\n\t\t\t{ observer },\n\t\t\t{\n\t\t\t\topencodeSessionId: envelope.session_stream_id,\n\t\t\t\tsource: envelope.source,\n\t\t\t\tcwd: envelope.cwd ?? null,\n\t\t\t\tproject: envelope.project ?? null,\n\t\t\t\tstartedAt: envelope.started_at ?? null,\n\t\t\t\tmaxEvents: null,\n\t\t\t},\n\t\t);\n\t} catch (err) {\n\t\tlogHookFailure(\n\t\t\t`codemem claude-hook-ingest boundary flush raw events failed: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t} finally {\n\t\tstore.close();\n\t}\n}\n\n/**\n * Ingest one Claude hook payload using the TS contract:\n * HTTP enqueue first, then locked drain + retry + direct fallback +\n * disk spool durability.\n */\nexport async function ingestClaudeHookPayload(\n\tpayload: Record<string, unknown>,\n\topts: IngestOpts,\n\tdeps: IngestDeps = {},\n): Promise<IngestResult> {\n\tconst httpIngest = deps.httpIngest ?? tryHttpIngest;\n\tconst directIngest = deps.directIngest ?? directEnqueue;\n\tconst resolveDb = deps.resolveDb ?? resolveDbPath;\n\tconst boundaryFlush = deps.boundaryFlush ?? flushBoundaryRawEvents;\n\n\t// Update per-session state alongside ingestion so claude-hook-inject's\n\t// retrieval query can draw on prompts/files seen on the ingest path.\n\t// Failures must never crash the hook command.\n\ttry {\n\t\ttrackHookSessionState(payload);\n\t} catch {\n\t\t// best-effort\n\t}\n\n\tconst port = typeof opts.port === \"number\" ? opts.port : Number.parseInt(opts.port, 10);\n\n\t// Resolve DB path lazily so the unlocked HTTP-success path doesn't\n\t// touch the filesystem when the viewer is up.\n\tlet cachedDbPath: string | null = null;\n\tconst getDbPath = (): string => {\n\t\tif (cachedDbPath === null) cachedDbPath = resolveDb(resolveDbOpt(opts));\n\t\treturn cachedDbPath;\n\t};\n\n\tconst tryDirectFallback = (\n\t\tqueued: Record<string, unknown>,\n\t): { ok: true; result: { inserted: number; skipped: number } } | { ok: false } => {\n\t\ttry {\n\t\t\treturn { ok: true, result: directIngest(queued, getDbPath()) };\n\t\t} catch (err) {\n\t\t\tlogHookFailure(\n\t\t\t\t`codemem claude-hook-ingest direct fallback failed: ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t);\n\t\t\treturn { ok: false };\n\t\t}\n\t};\n\n\tconst flushOnBoundaryIfRequested = async (): Promise<void> => {\n\t\tif (!shouldForceBoundaryFlush(payload)) return;\n\t\t// Best-effort write-through of the boundary payload to the local\n\t\t// store, then a synchronous flushRawEvents pass so memory state\n\t\t// is durable even when the viewer process is the one being shut\n\t\t// down. Both halves are logged with a boundary-specific message\n\t\t// so operators can distinguish them from regular fallback errors.\n\t\ttry {\n\t\t\tdirectIngest(payload, getDbPath());\n\t\t} catch (err) {\n\t\t\tlogHookFailure(\n\t\t\t\t`codemem claude-hook-ingest boundary flush direct write failed: ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t);\n\t\t}\n\t\ttry {\n\t\t\tawait boundaryFlush(payload, getDbPath());\n\t\t} catch (err) {\n\t\t\tlogHookFailure(\n\t\t\t\t`codemem claude-hook-ingest boundary flush failed: ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t);\n\t\t}\n\t};\n\n\t// Drain any backlog spooled by previous failed invocations. Runs on\n\t// every successful HTTP path so the queue is recovered as soon as\n\t// the viewer comes back up; if a previous run had to spool because\n\t// both HTTP and direct ingest failed, those payloads must not sit\n\t// stranded just because the next call happens to hit a healthy\n\t// viewer. Cheap pre-check avoids the lock acquisition cost on the\n\t// fast path when the spool is empty (the common case).\n\tconst drainBacklogIfPresent = async (): Promise<void> => {\n\t\tif (!hasSpooledEntries()) return;\n\t\ttry {\n\t\t\tawait withClaudeHookIngestLock(async () => {\n\t\t\t\trecoverStaleTmpSpool(lockTtlSeconds());\n\t\t\t\tawait drainSpool(async (queuedPayload) => {\n\t\t\t\t\tconst queuedHttp = await httpIngest(queuedPayload, opts.host, port);\n\t\t\t\t\tif (queuedHttp.ok) return true;\n\t\t\t\t\treturn tryDirectFallback(queuedPayload).ok;\n\t\t\t\t});\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tif (err instanceof LockBusyError) {\n\t\t\t\t// Another invocation is already draining; nothing to do.\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlogHookFailure(\n\t\t\t\t`codemem claude-hook-ingest backlog drain failed: ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t);\n\t\t}\n\t};\n\n\t// 1. Unlocked HTTP attempt — fast path when the viewer is up.\n\tconst httpResult = await httpIngest(payload, opts.host, port);\n\tif (httpResult.ok) {\n\t\tawait flushOnBoundaryIfRequested();\n\t\tawait drainBacklogIfPresent();\n\t\treturn { inserted: httpResult.inserted, skipped: httpResult.skipped, via: \"http\" };\n\t}\n\n\t// 2. Locked failure path: drain spool, retry HTTP, fall back to\n\t// direct, spool the payload as last resort.\n\ttry {\n\t\treturn await withClaudeHookIngestLock(async () => {\n\t\t\trecoverStaleTmpSpool(lockTtlSeconds());\n\n\t\t\tawait drainSpool(async (queuedPayload) => {\n\t\t\t\tconst queuedHttp = await httpIngest(queuedPayload, opts.host, port);\n\t\t\t\tif (queuedHttp.ok) return true;\n\t\t\t\tconst direct = tryDirectFallback(queuedPayload);\n\t\t\t\treturn direct.ok;\n\t\t\t});\n\n\t\t\tconst secondHttp = await httpIngest(payload, opts.host, port);\n\t\t\tif (secondHttp.ok) {\n\t\t\t\tawait flushOnBoundaryIfRequested();\n\t\t\t\treturn {\n\t\t\t\t\tinserted: secondHttp.inserted,\n\t\t\t\t\tskipped: secondHttp.skipped,\n\t\t\t\t\tvia: \"http\" as const,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst direct = tryDirectFallback(payload);\n\t\t\tif (direct.ok) {\n\t\t\t\tawait flushOnBoundaryIfRequested();\n\t\t\t\treturn { ...direct.result, via: \"direct\" as const };\n\t\t\t}\n\n\t\t\tif (spoolPayload(payload)) {\n\t\t\t\treturn { inserted: 0, skipped: 0, via: \"spool\" as const };\n\t\t\t}\n\n\t\t\tlogHookFailure(\"codemem claude-hook-ingest failed: fallback and spool failed\");\n\t\t\tthrow new Error(\"claude-hook-ingest: fallback and spool both failed\");\n\t\t});\n\t} catch (err) {\n\t\tif (!(err instanceof LockBusyError)) throw err;\n\n\t\tlogHookFailure(\"codemem claude-hook-ingest lock busy; trying unlocked fallback\");\n\t\tconst direct = tryDirectFallback(payload);\n\t\tif (direct.ok) {\n\t\t\treturn { ...direct.result, via: \"direct\" };\n\t\t}\n\t\tif (spoolPayload(payload)) {\n\t\t\treturn { inserted: 0, skipped: 0, via: \"spool_lock_busy\" };\n\t\t}\n\t\tlogHookFailure(\"codemem claude-hook-ingest failed: unlocked fallback and spool failed\");\n\t\tthrow err;\n\t}\n}\n\nconst claudeHookCmd = new Command(\"claude-hook-ingest\")\n\t.configureHelp(helpStyle)\n\t.description(\"Ingest Claude hook payload: HTTP first, direct DB fallback\");\n\naddDbOption(claudeHookCmd);\naddViewerHostOptions(claudeHookCmd);\n\nfunction envTruthyValue(value: string | undefined): boolean {\n\tconst normalized = String(value ?? \"\")\n\t\t.trim()\n\t\t.toLowerCase();\n\treturn normalized === \"1\" || normalized === \"true\" || normalized === \"yes\" || normalized === \"on\";\n}\n\nexport const claudeHookIngestCommand = claudeHookCmd.action(\n\tasync (opts: DbOpts & { host: string; port: string }) => {\n\t\t// Honor the global plugin-ignore kill switch first so users can\n\t\t// disable every codemem hook side effect by exporting\n\t\t// CODEMEM_PLUGIN_IGNORE=1 without having to know which subcommand\n\t\t// is wired to which hook. Mirrors the inject command.\n\t\tif (envTruthyValue(process.env.CODEMEM_PLUGIN_IGNORE)) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Read payload from stdin\n\t\tlet raw: string;\n\t\ttry {\n\t\t\traw = readFileSync(0, \"utf8\").trim();\n\t\t} catch {\n\t\t\temitStructuredError(\"read_error\", \"failed to read stdin\");\n\t\t\treturn;\n\t\t}\n\t\tif (!raw) {\n\t\t\temitStructuredError(\"read_error\", \"empty stdin\");\n\t\t\treturn;\n\t\t}\n\n\t\tlet payload: Record<string, unknown>;\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(raw) as unknown;\n\t\t\tif (parsed == null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\t\t\temitStructuredError(\"parse_error\", \"payload must be a JSON object\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpayload = parsed as Record<string, unknown>;\n\t\t} catch {\n\t\t\temitStructuredError(\"parse_error\", \"invalid JSON\");\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst result = await ingestClaudeHookPayload(payload, opts);\n\t\t\tconsole.log(JSON.stringify(result));\n\t\t} catch (err) {\n\t\t\temitStructuredError(\"ingest_error\", err instanceof Error ? err.message : String(err));\n\t\t}\n\t},\n);\n","import { MemoryStore, resolveDbPath, resolveHookProject } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport { addDbOption, type DbOpts, resolveDbOpt } from \"../shared-options.js\";\nimport { logHookFailure } from \"./claude-hook-plugin-log.js\";\nimport {\n\tbuildInjectQuery,\n\tnormalizePromptText,\n\ttype SessionState,\n\ttrackHookSessionState,\n\tworkingSetPathsFromState,\n} from \"./claude-hook-session-state.js\";\n\ntype InjectResult = {\n\tcontinue: true;\n\thookSpecificOutput?: {\n\t\thookEventName: \"UserPromptSubmit\";\n\t\tadditionalContext: string;\n\t};\n};\n\n// claude-hook-inject is wired exclusively to UserPromptSubmit. The\n// hookSpecificOutput schema is event-specific (additionalContext is a\n// UserPromptSubmit-only field), so emitting any other event name would\n// produce invalid output regardless of what the payload claims.\nconst HOOK_EVENT_NAME = \"UserPromptSubmit\" as const;\n\ntype InjectOpts = DbOpts;\n\ntype HttpPackResponse = {\n\tpack_text?: string;\n};\n\ntype InjectDeps = {\n\tbuildLocalPack?: typeof buildLocalPack;\n\thttpPack?: typeof tryHttpPack;\n\tresolveDb?: typeof resolveDbPath;\n};\n\nconst DEFAULT_VIEWER_HOST = \"127.0.0.1\";\nconst DEFAULT_VIEWER_PORT = 38888;\nconst DEFAULT_MAX_CHARS = 16000;\nconst DEFAULT_HTTP_MAX_TIME_S = 2;\n\nfunction emitJson(value: InjectResult | { error: string; message: string }): void {\n\tconsole.log(JSON.stringify(value));\n}\n\nfunction envNotDisabled(value: string | undefined): boolean {\n\tconst normalized = String(value ?? \"\")\n\t\t.trim()\n\t\t.toLowerCase();\n\treturn normalized !== \"0\" && normalized !== \"false\" && normalized !== \"off\";\n}\n\nfunction envTruthy(value: string | undefined): boolean {\n\tconst normalized = String(value ?? \"\")\n\t\t.trim()\n\t\t.toLowerCase();\n\treturn normalized === \"1\" || normalized === \"true\" || normalized === \"yes\" || normalized === \"on\";\n}\n\nfunction parsePositiveInt(value: string | undefined, fallback: number): number {\n\tconst parsed = Number.parseInt(String(value ?? \"\"), 10);\n\tif (!Number.isFinite(parsed) || parsed <= 0) {\n\t\treturn fallback;\n\t}\n\treturn parsed;\n}\n\nfunction continueResult(additionalContext?: string): InjectResult {\n\tif (!additionalContext) {\n\t\treturn { continue: true };\n\t}\n\treturn {\n\t\tcontinue: true,\n\t\thookSpecificOutput: {\n\t\t\thookEventName: HOOK_EVENT_NAME,\n\t\t\tadditionalContext,\n\t\t},\n\t};\n}\n\nfunction truncateAdditionalContext(text: string, maxChars: number): string {\n\tconst normalized = text.trim();\n\tif (!normalized) {\n\t\treturn \"\";\n\t}\n\tif (!Number.isFinite(maxChars) || maxChars <= 0 || normalized.length <= maxChars) {\n\t\treturn normalized;\n\t}\n\t// Strip trailing whitespace from the slice before appending the marker\n\t// so the boundary stays readable in chat output.\n\treturn `${normalized.slice(0, maxChars).trimEnd()}\\n\\n[pack truncated]`;\n}\n\nfunction extractInjectContext(payload: Record<string, unknown>): string | null {\n\t// Reuse the same normalization the session-state tracker applies so the\n\t// `prompt !== first_prompt` comparison in buildInjectQuery is robust to\n\t// multi-line prompts (otherwise a \"fix\\nauth\" current prompt would never\n\t// match a stored \"fix auth\" first_prompt and would be appended on every\n\t// turn).\n\tconst prompt = normalizePromptText(payload.prompt);\n\treturn prompt || null;\n}\n\nfunction resolveInjectProject(payload: Record<string, unknown>): string | null {\n\tconst cwd = typeof payload.cwd === \"string\" ? payload.cwd : null;\n\treturn resolveHookProject(cwd, payload.project);\n}\n\nasync function buildLocalPack(\n\tcontext: string,\n\tproject: string | null,\n\tdbPath: string,\n\tworkingSetPaths: string[] = [],\n): Promise<string> {\n\tconst store = new MemoryStore(dbPath);\n\ttry {\n\t\tconst limit = parsePositiveInt(process.env.CODEMEM_INJECT_LIMIT, 8);\n\t\tconst budget = parsePositiveInt(process.env.CODEMEM_INJECT_TOKEN_BUDGET, 800);\n\t\tconst filters: { project?: string; working_set_paths?: string[] } = {};\n\t\tif (project) {\n\t\t\tfilters.project = project;\n\t\t}\n\t\tif (workingSetPaths.length > 0) {\n\t\t\tfilters.working_set_paths = workingSetPaths;\n\t\t}\n\t\tconst pack = await store.buildMemoryPackAsync(context, limit, budget, filters);\n\t\treturn String(pack.pack_text ?? \"\").trim();\n\t} finally {\n\t\tstore.close();\n\t}\n}\n\nasync function tryHttpPack(\n\tcontext: string,\n\tproject: string | null,\n\tmaxTimeMs = DEFAULT_HTTP_MAX_TIME_S * 1000,\n): Promise<string> {\n\tconst host = process.env.CODEMEM_VIEWER_HOST || DEFAULT_VIEWER_HOST;\n\tconst port = parsePositiveInt(process.env.CODEMEM_VIEWER_PORT, DEFAULT_VIEWER_PORT);\n\tconst url = new URL(`http://${host}:${port}/api/pack`);\n\turl.searchParams.set(\"context\", context);\n\turl.searchParams.set(\"limit\", String(parsePositiveInt(process.env.CODEMEM_INJECT_LIMIT, 8)));\n\turl.searchParams.set(\n\t\t\"token_budget\",\n\t\tString(parsePositiveInt(process.env.CODEMEM_INJECT_TOKEN_BUDGET, 800)),\n\t);\n\tif (project) {\n\t\turl.searchParams.set(\"project\", project);\n\t}\n\n\tconst controller = new AbortController();\n\tconst timeout = setTimeout(() => controller.abort(), maxTimeMs);\n\ttry {\n\t\tconst res = await fetch(url, { signal: controller.signal });\n\t\tif (!res.ok) {\n\t\t\treturn \"\";\n\t\t}\n\t\tconst body = (await res.json()) as HttpPackResponse;\n\t\treturn String(body.pack_text ?? \"\").trim();\n\t} catch {\n\t\treturn \"\";\n\t} finally {\n\t\tclearTimeout(timeout);\n\t}\n}\n\nexport async function buildClaudeHookInjection(\n\tpayload: Record<string, unknown>,\n\topts: InjectOpts,\n\tdeps: InjectDeps = {},\n): Promise<InjectResult> {\n\t// Honor the global plugin-ignore kill switch first so users can disable\n\t// every codemem hook side effect by exporting CODEMEM_PLUGIN_IGNORE=1\n\t// without having to know which subcommand is wired to which hook.\n\tif (envTruthy(process.env.CODEMEM_PLUGIN_IGNORE)) {\n\t\treturn continueResult();\n\t}\n\tif (!envNotDisabled(process.env.CODEMEM_INJECT_CONTEXT || \"1\")) {\n\t\treturn continueResult();\n\t}\n\n\t// Track session state before the prompt-presence check so SessionEnd /\n\t// PostToolUse / SessionStart events still update the per-session store.\n\tlet state: SessionState | null = null;\n\ttry {\n\t\tstate = trackHookSessionState(payload);\n\t} catch {\n\t\tstate = null;\n\t}\n\n\tconst promptText = extractInjectContext(payload);\n\tif (!promptText) {\n\t\treturn continueResult();\n\t}\n\n\tconst buildPack = deps.buildLocalPack ?? buildLocalPack;\n\tconst httpPack = deps.httpPack ?? tryHttpPack;\n\tconst resolveDb = deps.resolveDb ?? resolveDbPath;\n\tconst project = resolveInjectProject(payload);\n\tconst query = buildInjectQuery({ prompt: promptText, project, state });\n\tconst workingSetPaths = workingSetPathsFromState(state);\n\tconst maxChars = parsePositiveInt(process.env.CODEMEM_INJECT_MAX_CHARS, DEFAULT_MAX_CHARS);\n\tconst httpMaxTimeMs =\n\t\tparsePositiveInt(process.env.CODEMEM_INJECT_HTTP_MAX_TIME_S, DEFAULT_HTTP_MAX_TIME_S) * 1000;\n\n\tlet additionalContext = \"\";\n\ttry {\n\t\tconst dbPath = resolveDb(resolveDbOpt(opts));\n\t\tadditionalContext = await buildPack(query, project, dbPath, workingSetPaths);\n\t} catch (err) {\n\t\tadditionalContext = \"\";\n\t\tlogHookFailure(\n\t\t\t`codemem claude-hook-inject local pack failed: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t}\n\n\tif (!additionalContext && envNotDisabled(process.env.CODEMEM_INJECT_HTTP_FALLBACK || \"1\")) {\n\t\t// tryHttpPack swallows its own network errors and returns \"\" on\n\t\t// failure; don't wrap it here so tests that throw from a stub mock\n\t\t// still surface as failures (the existing\n\t\t// \"should not run\" assertions rely on this).\n\t\tadditionalContext = await httpPack(query, project, httpMaxTimeMs);\n\t}\n\n\treturn continueResult(truncateAdditionalContext(additionalContext, maxChars));\n}\n\nconst claudeHookInjectCmd = new Command(\"claude-hook-inject\")\n\t.configureHelp(helpStyle)\n\t.description(\"Return Claude hook additionalContext from local pack generation\");\n\naddDbOption(claudeHookInjectCmd);\n\nexport const claudeHookInjectCommand = claudeHookInjectCmd.action(async (opts: InjectOpts) => {\n\tlet raw = \"\";\n\tfor await (const chunk of process.stdin) {\n\t\traw += String(chunk);\n\t}\n\tconst trimmed = raw.trim();\n\tif (!trimmed) {\n\t\temitJson(continueResult());\n\t\treturn;\n\t}\n\n\tlet payload: Record<string, unknown>;\n\ttry {\n\t\tconst parsed = JSON.parse(trimmed) as unknown;\n\t\tif (parsed == null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\t\temitJson({ error: \"parse_error\", message: \"payload must be a JSON object\" });\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\t\tpayload = parsed as Record<string, unknown>;\n\t} catch {\n\t\temitJson({ error: \"parse_error\", message: \"invalid JSON\" });\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\n\tconst result = await buildClaudeHookInjection(payload, opts);\n\temitJson(result);\n});\n","import { existsSync } from \"node:fs\";\nimport {\n\ttype ConfigResolutionResult,\n\tgetWorkspaceCodememConfigPath,\n\treadCodememConfigFile,\n\treadCodememConfigFileAtPath,\n\tresolveCodememConfigPath,\n\twriteCodememConfigFile,\n} from \"@codemem/core\";\nimport { Command, Option } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddConfigOption,\n\taddJsonOption,\n\ttype ConfigOpts,\n\ttype JsonOpts,\n} from \"../shared-options.js\";\n\ntype WorkspaceConfigOptions = JsonOpts & {\n\tworkspaceId?: string;\n\tsyncEnabled?: boolean;\n\tsyncHost?: string;\n\tsyncPort?: string;\n\tsyncIntervalS?: string;\n\tcoordinatorUrl?: string;\n\tcoordinatorGroup?: string;\n};\n\ntype WorkspaceConfigResult = {\n\tworkspace_id: string;\n\tconfig_path: string;\n\tupdated_keys: string[];\n\tconfig: Record<string, unknown>;\n};\n\nfunction parseIntegerOption(value: string | undefined, flagName: string): number | undefined {\n\tif (value == null) return undefined;\n\tconst trimmed = value.trim();\n\tif (!/^\\d+$/.test(trimmed)) {\n\t\tthrow new Error(`Invalid ${flagName}: ${value}`);\n\t}\n\treturn Number.parseInt(trimmed, 10);\n}\n\nfunction buildWorkspaceConfigPatch(opts: WorkspaceConfigOptions): Record<string, unknown> {\n\tconst patch: Record<string, unknown> = {};\n\tif (opts.syncEnabled === true) patch.sync_enabled = true;\n\tif (opts.syncEnabled === false) patch.sync_enabled = false;\n\tif (opts.syncHost?.trim()) patch.sync_host = opts.syncHost.trim();\n\tconst syncPort = parseIntegerOption(opts.syncPort, \"--sync-port\");\n\tif (syncPort != null) patch.sync_port = syncPort;\n\tconst syncInterval = parseIntegerOption(opts.syncIntervalS, \"--sync-interval-s\");\n\tif (syncInterval != null) patch.sync_interval_s = syncInterval;\n\tif (opts.coordinatorUrl?.trim()) patch.sync_coordinator_url = opts.coordinatorUrl.trim();\n\tif (opts.coordinatorGroup?.trim()) patch.sync_coordinator_group = opts.coordinatorGroup.trim();\n\treturn patch;\n}\n\nfunction mergeWorkspaceConfig(\n\texistingConfig: Record<string, unknown>,\n\tpatch: Record<string, unknown>,\n): Record<string, unknown> {\n\treturn { ...existingConfig, ...patch };\n}\n\nfunction runWorkspaceConfigCommand(\n\topts: WorkspaceConfigOptions & { enableSync?: boolean; disableSync?: boolean },\n): WorkspaceConfigResult {\n\tif (opts.enableSync && opts.disableSync) {\n\t\tthrow new Error(\"Use only one of --enable-sync or --disable-sync\");\n\t}\n\tconst workspaceId = opts.workspaceId;\n\tif (!workspaceId) {\n\t\tthrow new Error(\"workspace-id is required\");\n\t}\n\tconst configPath = getWorkspaceCodememConfigPath(workspaceId);\n\t// Seeds new workspace config from legacy global config on first write,\n\t// so existing settings are inherited.\n\tconst existingConfig = existsSync(configPath)\n\t\t? readCodememConfigFileAtPath(configPath)\n\t\t: readCodememConfigFile();\n\tconst patch = buildWorkspaceConfigPatch({\n\t\tworkspaceId,\n\t\tsyncEnabled: opts.enableSync ? true : opts.disableSync ? false : undefined,\n\t\tsyncHost: opts.syncHost,\n\t\tsyncPort: opts.syncPort,\n\t\tsyncIntervalS: opts.syncIntervalS,\n\t\tcoordinatorUrl: opts.coordinatorUrl,\n\t\tcoordinatorGroup: opts.coordinatorGroup,\n\t\tjson: opts.json,\n\t});\n\tif (Object.keys(patch).length === 0) {\n\t\tthrow new Error(\"Provide at least one config field to update\");\n\t}\n\tconst nextConfig = mergeWorkspaceConfig(existingConfig, patch);\n\tconst savedPath = writeCodememConfigFile(nextConfig, configPath);\n\treturn {\n\t\tworkspace_id: workspaceId,\n\t\tconfig_path: savedPath,\n\t\tupdated_keys: Object.keys(patch).sort(),\n\t\tconfig: nextConfig,\n\t};\n}\n\nexport const configCommand = new Command(\"config\")\n\t.configureHelp(helpStyle)\n\t.description(\"Manage codemem configuration\");\n\nconst workspaceCmd = new Command(\"workspace\")\n\t.configureHelp(helpStyle)\n\t.description(\"Create or update workspace-scoped codemem config\")\n\t.argument(\"[workspace-id]\", \"workspace identifier\")\n\t.option(\"--enable-sync\", \"set sync_enabled=true\")\n\t.option(\"--disable-sync\", \"set sync_enabled=false\")\n\t.option(\"--sync-host <host>\", \"set sync_host\")\n\t.option(\"--sync-port <port>\", \"set sync_port\")\n\t.option(\"--sync-interval-s <seconds>\", \"set sync_interval_s\")\n\t.option(\"--coordinator-url <url>\", \"set sync_coordinator_url\")\n\t.option(\"--coordinator-group <group>\", \"set sync_coordinator_group\");\n\n// Hidden backwards-compat alias for --workspace-id <id>\nworkspaceCmd.addOption(\n\tnew Option(\"--workspace-id <id>\", \"workspace identifier (use positional instead)\").hideHelp(),\n);\n\naddJsonOption(workspaceCmd);\n\nworkspaceCmd.action(\n\t(\n\t\tworkspaceIdArg: string | undefined,\n\t\topts: WorkspaceConfigOptions & { enableSync?: boolean; disableSync?: boolean },\n\t) => {\n\t\ttry {\n\t\t\t// Positional takes precedence over hidden flag alias\n\t\t\tconst workspaceId = workspaceIdArg || opts.workspaceId;\n\t\t\tif (!workspaceId) {\n\t\t\t\tconsole.error(\"Error: missing required argument 'workspace-id'\");\n\t\t\t\tprocess.exitCode = 2;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst result = runWorkspaceConfigCommand({ ...opts, workspaceId });\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconsole.log(`Updated workspace config: ${result.config_path}`);\n\t\t\tconsole.log(`Updated keys: ${result.updated_keys.join(\", \")}`);\n\t\t} catch (err) {\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(\n\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\terror: \"config_error\",\n\t\t\t\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tconsole.error(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t},\n);\n\nconfigCommand.addCommand(workspaceCmd);\n\n// ---------------------------------------------------------------------------\n// config where — show resolved config path with full traceability\n// ---------------------------------------------------------------------------\n\ntype WhereOptions = ConfigOpts & JsonOpts;\n\nfunction formatWhereHuman(result: ConfigResolutionResult): string {\n\tconst lines: string[] = [];\n\tconst allEntries = [result.resolved, ...result.fallbackChain];\n\t// Sort by original precedence order for display\n\tconst sourceOrder: Record<string, number> = {\n\t\t\"cli-flag\": 0,\n\t\t\"env-codemem-config\": 1,\n\t\t\"env-runtime-root\": 2,\n\t\t\"env-workspace-id\": 3,\n\t\t\"legacy-global\": 4,\n\t};\n\tallEntries.sort((a, b) => (sourceOrder[a.source] ?? 99) - (sourceOrder[b.source] ?? 99));\n\n\tfor (const entry of allEntries) {\n\t\tconst isSelected = entry === result.resolved;\n\t\tconst marker = isSelected ? \">>>\" : \" \";\n\t\tconst existsLabel = entry.exists ? \"exists\" : \"missing\";\n\t\tlines.push(`${marker} [${entry.source}] ${entry.path}`);\n\t\tlines.push(` ${entry.reason} (${existsLabel})`);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nconst whereCmd = new Command(\"where\")\n\t.configureHelp(helpStyle)\n\t.description(\"show resolved config file path\");\n\naddConfigOption(whereCmd);\naddJsonOption(whereCmd);\n\nwhereCmd.action((opts: WhereOptions) => {\n\ttry {\n\t\tconst result = resolveCodememConfigPath(opts.config, \"read\");\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t} else {\n\t\t\tconsole.log(formatWhereHuman(result));\n\t\t}\n\t} catch (err) {\n\t\tif (opts.json) {\n\t\t\tconsole.log(\n\t\t\t\tJSON.stringify({\n\t\t\t\t\terror: \"config_error\",\n\t\t\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t\t\t}),\n\t\t\t);\n\t\t} else {\n\t\t\tconsole.error(err instanceof Error ? err.message : String(err));\n\t\t}\n\t\tprocess.exitCode = 1;\n\t}\n});\n\nconfigCommand.addCommand(whereCmd);\n\nexport { buildWorkspaceConfigPatch, mergeWorkspaceConfig, runWorkspaceConfigCommand };\n","/**\n * Coordinator CLI commands — manage coordinator invites, join requests, and relay server.\n *\n * Extracted from sync.ts to give coordinator admin its own top-level group\n * per cli-design-conventions.md (operator/admin surfaces belong in their own group).\n *\n * buildCoordinatorCommand() is a factory that creates a fresh command tree.\n * This allows both the canonical top-level `coordinator` and the deprecated\n * `sync coordinator` alias to have independent Commander instances (Commander\n * re-parents commands on addCommand, so sharing instances between two parents\n * is not possible).\n */\n\nimport { readFileSync } from \"node:fs\";\n\nimport * as p from \"@clack/prompts\";\nimport {\n\tcoordinatorCreateGroupAction,\n\tcoordinatorCreateInviteAction,\n\tcoordinatorDisableDeviceAction,\n\tcoordinatorEnrollDeviceAction,\n\tcoordinatorImportInviteAction,\n\tcoordinatorListBootstrapGrantsAction,\n\tcoordinatorListDevicesAction,\n\tcoordinatorListGroupsAction,\n\tcoordinatorListJoinRequestsAction,\n\tcoordinatorRemoveDeviceAction,\n\tcoordinatorRenameDeviceAction,\n\tcoordinatorReviewJoinRequestAction,\n\tcoordinatorRevokeBootstrapGrantAction,\n\tcreateBetterSqliteCoordinatorApp,\n\tDEFAULT_COORDINATOR_DB_PATH,\n\tfingerprintPublicKey,\n} from \"@codemem/core\";\nimport { serve as honoServe } from \"@hono/node-server\";\nimport { Command, Option } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddConfigOption,\n\taddDbOption,\n\taddJsonOption,\n\temitJsonError,\n\tresolveDbOpt,\n} from \"../shared-options.js\";\n\nfunction readCoordinatorPublicKey(opts: { publicKey?: string; publicKeyFile?: string }): string {\n\tconst inline = String(opts.publicKey ?? \"\").trim();\n\tconst filePath = String(opts.publicKeyFile ?? \"\").trim();\n\tif (inline && filePath) throw new Error(\"Use only one of --public-key or --public-key-file\");\n\tif (filePath) {\n\t\tconst text = readFileSync(filePath, \"utf8\").trim();\n\t\tif (!text) throw new Error(`Public key file is empty: ${filePath}`);\n\t\treturn text;\n\t}\n\tif (!inline) throw new Error(\"Public key required via --public-key or --public-key-file\");\n\treturn inline;\n}\n\n/**\n * Build a fresh coordinator command tree. Each call returns independent\n * Commander instances so the tree can be mounted under multiple parents.\n */\nexport function buildCoordinatorCommand(): Command {\n\tconst cmd = new Command(\"coordinator\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Manage coordinator invites, join requests, and relay server\");\n\n\t// ---- group-create ----\n\n\tconst groupCreateCmd = new Command(\"group-create\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Create a coordinator group in the local store\")\n\t\t.argument(\"<group>\", \"group id\")\n\t\t.option(\"--name <name>\", \"display name override\");\n\taddDbOption(groupCreateCmd);\n\taddJsonOption(groupCreateCmd);\n\tgroupCreateCmd.action(\n\t\tasync (\n\t\t\tgroupId: string,\n\t\t\topts: { name?: string; db?: string; dbPath?: string; json?: boolean },\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst group = await coordinatorCreateGroupAction({\n\t\t\t\t\tgroupId,\n\t\t\t\t\tdisplayName: opts.name?.trim() || null,\n\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t});\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(group, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem coordinator group-create\");\n\t\t\t\tp.log.success(`Group ready: ${groupId.trim()}`);\n\t\t\t\tp.outro(String(group.display_name ?? group.group_id ?? groupId.trim()));\n\t\t\t} catch (err) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"group_create_failed\", err instanceof Error ? err.message : String(err));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t},\n\t);\n\tcmd.addCommand(groupCreateCmd);\n\n\t// ---- list-groups ----\n\n\tconst listGroupsCmd = new Command(\"list-groups\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"List coordinator groups from the local store\");\n\taddDbOption(listGroupsCmd);\n\taddJsonOption(listGroupsCmd);\n\tlistGroupsCmd.action(async (opts: { db?: string; dbPath?: string; json?: boolean }) => {\n\t\ttry {\n\t\t\tconst groups = await coordinatorListGroupsAction({ dbPath: resolveDbOpt(opts) ?? null });\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(groups, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.intro(\"codemem coordinator list-groups\");\n\t\t\tif (groups.length === 0) {\n\t\t\t\tp.outro(\"No coordinator groups found\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (const group of groups) {\n\t\t\t\tp.log.message(\n\t\t\t\t\t`- ${String(group.group_id ?? \"\")}${group.display_name ? ` (${String(group.display_name)})` : \"\"}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tp.outro(`${groups.length} group(s)`);\n\t\t} catch (err) {\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\"list_groups_failed\", err instanceof Error ? err.message : String(err));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t});\n\tcmd.addCommand(listGroupsCmd);\n\n\t// ---- enroll-device ----\n\n\tconst enrollDeviceCmd = new Command(\"enroll-device\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Enroll a device in a local coordinator group\")\n\t\t.argument(\"<group>\", \"group id\")\n\t\t.argument(\"<device-id>\", \"device id\")\n\t\t.option(\"--fingerprint <fingerprint>\", \"device fingerprint\")\n\t\t.option(\"--public-key <key>\", \"device public key\")\n\t\t.option(\"--public-key-file <path>\", \"path to device public key\")\n\t\t.option(\"--name <name>\", \"display name\");\n\taddDbOption(enrollDeviceCmd);\n\taddJsonOption(enrollDeviceCmd);\n\tenrollDeviceCmd.action(\n\t\tasync (\n\t\t\tgroupId: string,\n\t\t\tdeviceId: string,\n\t\t\topts: {\n\t\t\t\tfingerprint?: string;\n\t\t\t\tpublicKey?: string;\n\t\t\t\tpublicKeyFile?: string;\n\t\t\t\tname?: string;\n\t\t\t\tdb?: string;\n\t\t\t\tdbPath?: string;\n\t\t\t\tjson?: boolean;\n\t\t\t},\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst publicKey = readCoordinatorPublicKey(opts);\n\t\t\t\tconst fingerprint = String(opts.fingerprint ?? \"\").trim();\n\t\t\t\tif (!fingerprint) {\n\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\temitJsonError(\"usage_error\", \"Fingerprint required via --fingerprint\", 2);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tp.log.error(\"Fingerprint required via --fingerprint\");\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst actualFingerprint = fingerprintPublicKey(publicKey);\n\t\t\t\tif (actualFingerprint !== fingerprint) {\n\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\temitJsonError(\n\t\t\t\t\t\t\t\"fingerprint_mismatch\",\n\t\t\t\t\t\t\t\"Fingerprint does not match the provided public key\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tp.log.error(\"Fingerprint does not match the provided public key\");\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst enrollment = await coordinatorEnrollDeviceAction({\n\t\t\t\t\tgroupId,\n\t\t\t\t\tdeviceId,\n\t\t\t\t\tfingerprint,\n\t\t\t\t\tpublicKey,\n\t\t\t\t\tdisplayName: opts.name?.trim() || null,\n\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t});\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(enrollment, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem coordinator enroll-device\");\n\t\t\t\tp.log.success(`Enrolled ${deviceId.trim()} in ${groupId.trim()}`);\n\t\t\t\tp.outro(String(enrollment.display_name ?? enrollment.device_id ?? deviceId.trim()));\n\t\t\t} catch (err) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"enroll_failed\", err instanceof Error ? err.message : String(err));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t},\n\t);\n\tcmd.addCommand(enrollDeviceCmd);\n\n\t// ---- list-devices ----\n\n\tconst listDevicesCmd = new Command(\"list-devices\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"List enrolled devices in a local coordinator group\")\n\t\t.argument(\"<group>\", \"group id\")\n\t\t.option(\"--include-disabled\", \"include disabled devices\");\n\taddDbOption(listDevicesCmd);\n\taddJsonOption(listDevicesCmd);\n\tlistDevicesCmd.action(\n\t\tasync (\n\t\t\tgroupId: string,\n\t\t\topts: { includeDisabled?: boolean; db?: string; dbPath?: string; json?: boolean },\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst rows = await coordinatorListDevicesAction({\n\t\t\t\t\tgroupId,\n\t\t\t\t\tincludeDisabled: opts.includeDisabled === true,\n\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t});\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(rows, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem coordinator list-devices\");\n\t\t\t\tif (rows.length === 0) {\n\t\t\t\t\tp.outro(`No enrolled devices for ${groupId.trim()}`);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (const row of rows) {\n\t\t\t\t\tconst label =\n\t\t\t\t\t\tString(row.display_name ?? row.device_id ?? \"\").trim() || String(row.device_id ?? \"\");\n\t\t\t\t\tconst enabled = Number(row.enabled ?? 1) === 1 ? \"enabled\" : \"disabled\";\n\t\t\t\t\tp.log.message(`- ${label} (${String(row.device_id ?? \"\")}) ${enabled}`);\n\t\t\t\t}\n\t\t\t\tp.outro(`${rows.length} device(s)`);\n\t\t\t} catch (err) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"list_devices_failed\", err instanceof Error ? err.message : String(err));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t},\n\t);\n\tcmd.addCommand(listDevicesCmd);\n\n\t// ---- rename-device ----\n\n\tconst renameDeviceCmd = new Command(\"rename-device\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Rename an enrolled device in the local coordinator store\")\n\t\t.argument(\"<group>\", \"group id\")\n\t\t.argument(\"<device-id>\", \"device id\")\n\t\t.requiredOption(\"--name <name>\", \"display name\");\n\taddDbOption(renameDeviceCmd);\n\taddJsonOption(renameDeviceCmd);\n\trenameDeviceCmd.action(\n\t\tasync (\n\t\t\tgroupId: string,\n\t\t\tdeviceId: string,\n\t\t\topts: { name: string; db?: string; dbPath?: string; json?: boolean },\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst result = await coordinatorRenameDeviceAction({\n\t\t\t\t\tgroupId,\n\t\t\t\t\tdeviceId,\n\t\t\t\t\tdisplayName: opts.name.trim(),\n\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t});\n\t\t\t\tif (!result) {\n\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\temitJsonError(\"device_not_found\", `Device not found: ${deviceId.trim()}`);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tp.log.error(`Device not found: ${deviceId.trim()}`);\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem coordinator rename-device\");\n\t\t\t\tp.log.success(`Renamed ${deviceId.trim()} in ${groupId.trim()}`);\n\t\t\t\tp.outro(String(result.display_name ?? result.device_id ?? deviceId.trim()));\n\t\t\t} catch (err) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"rename_failed\", err instanceof Error ? err.message : String(err));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t},\n\t);\n\tcmd.addCommand(renameDeviceCmd);\n\n\t// ---- disable-device ----\n\n\tconst disableDeviceCmd = new Command(\"disable-device\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Disable an enrolled device in the local coordinator store\")\n\t\t.argument(\"<group>\", \"group id\")\n\t\t.argument(\"<device-id>\", \"device id\");\n\taddDbOption(disableDeviceCmd);\n\taddJsonOption(disableDeviceCmd);\n\tdisableDeviceCmd.action(\n\t\tasync (\n\t\t\tgroupId: string,\n\t\t\tdeviceId: string,\n\t\t\topts: { db?: string; dbPath?: string; json?: boolean },\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst ok = await coordinatorDisableDeviceAction({\n\t\t\t\t\tgroupId,\n\t\t\t\t\tdeviceId,\n\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t});\n\t\t\t\tif (!ok) {\n\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\temitJsonError(\"device_not_found\", `Device not found: ${deviceId.trim()}`);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tp.log.error(`Device not found: ${deviceId.trim()}`);\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\tJSON.stringify(\n\t\t\t\t\t\t\t{ ok: true, group_id: groupId.trim(), device_id: deviceId.trim() },\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t2,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem coordinator disable-device\");\n\t\t\t\tp.log.success(`Disabled ${deviceId.trim()} in ${groupId.trim()}`);\n\t\t\t\tp.outro(\"disabled\");\n\t\t\t} catch (err) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"disable_failed\", err instanceof Error ? err.message : String(err));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t},\n\t);\n\tcmd.addCommand(disableDeviceCmd);\n\n\t// ---- remove-device ----\n\n\tconst removeDeviceCmd = new Command(\"remove-device\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Remove an enrolled device from the local coordinator store\")\n\t\t.argument(\"<group>\", \"group id\")\n\t\t.argument(\"<device-id>\", \"device id\");\n\taddDbOption(removeDeviceCmd);\n\taddJsonOption(removeDeviceCmd);\n\tremoveDeviceCmd.action(\n\t\tasync (\n\t\t\tgroupId: string,\n\t\t\tdeviceId: string,\n\t\t\topts: { db?: string; dbPath?: string; json?: boolean },\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst ok = await coordinatorRemoveDeviceAction({\n\t\t\t\t\tgroupId,\n\t\t\t\t\tdeviceId,\n\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t});\n\t\t\t\tif (!ok) {\n\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\temitJsonError(\"device_not_found\", `Device not found: ${deviceId.trim()}`);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tp.log.error(`Device not found: ${deviceId.trim()}`);\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\tJSON.stringify(\n\t\t\t\t\t\t\t{ ok: true, group_id: groupId.trim(), device_id: deviceId.trim() },\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t2,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem coordinator remove-device\");\n\t\t\t\tp.log.success(`Removed ${deviceId.trim()} from ${groupId.trim()}`);\n\t\t\t\tp.outro(\"removed\");\n\t\t\t} catch (err) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"remove_failed\", err instanceof Error ? err.message : String(err));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t},\n\t);\n\tcmd.addCommand(removeDeviceCmd);\n\n\t// ---- serve (coordinator relay) ----\n\n\tconst coordServeCmd = new Command(\"serve\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Run the coordinator relay HTTP server\")\n\t\t.option(\"--coordinator-host <host>\", \"bind host\")\n\t\t.option(\"--coordinator-port <port>\", \"bind port\");\n\t// Coordinator serve uses its own DB, not the main codemem DB\n\tcoordServeCmd.addOption(new Option(\"-d, --db-path <path>\", \"coordinator database path\"));\n\tcoordServeCmd.addOption(new Option(\"--db <path>\", \"coordinator database path\").hideHelp());\n\t// Hidden host/port aliases for backwards compat\n\tcoordServeCmd.addOption(new Option(\"--host <host>\", \"bind host\").hideHelp());\n\tcoordServeCmd.addOption(new Option(\"--port <port>\", \"bind port\").hideHelp());\n\tcoordServeCmd.action(\n\t\tasync (opts: {\n\t\t\tdb?: string;\n\t\t\tdbPath?: string;\n\t\t\tcoordinatorHost?: string;\n\t\t\tcoordinatorPort?: string;\n\t\t\thost?: string;\n\t\t\tport?: string;\n\t\t}) => {\n\t\t\t// Prefer canonical flags; fall back to hidden aliases; then defaults.\n\t\t\t// Defaults must NOT be set on the Option definitions, otherwise Commander\n\t\t\t// populates them and ?? cannot distinguish \"explicitly passed\" from \"default\".\n\t\t\tconst host = String(opts.coordinatorHost ?? opts.host ?? \"127.0.0.1\").trim() || \"127.0.0.1\";\n\t\t\tconst port = Number.parseInt(String(opts.coordinatorPort ?? opts.port ?? \"7347\"), 10);\n\t\t\tconst dbPath = resolveDbOpt(opts) ?? DEFAULT_COORDINATOR_DB_PATH;\n\t\t\tconst app = createBetterSqliteCoordinatorApp({ dbPath });\n\t\t\tp.intro(\"codemem coordinator serve\");\n\t\t\tp.log.success(`Coordinator listening at http://${host}:${port}`);\n\t\t\tp.log.info(`DB: ${dbPath}`);\n\t\t\thonoServe({ fetch: app.fetch, hostname: host, port });\n\t\t},\n\t);\n\tcmd.addCommand(coordServeCmd);\n\n\t// ---- list-bootstrap-grants ----\n\n\tconst listBootstrapGrantsCmd = new Command(\"list-bootstrap-grants\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"List bootstrap grants for a coordinator group\")\n\t\t.argument(\"<group>\", \"group id\")\n\t\t.option(\"--remote-url <url>\", \"remote coordinator URL override\")\n\t\t.option(\"--admin-secret <secret>\", \"remote coordinator admin secret override\");\n\taddDbOption(listBootstrapGrantsCmd);\n\taddJsonOption(listBootstrapGrantsCmd);\n\tlistBootstrapGrantsCmd.action(\n\t\tasync (\n\t\t\tgroupId: string,\n\t\t\topts: {\n\t\t\t\tdb?: string;\n\t\t\t\tdbPath?: string;\n\t\t\t\tremoteUrl?: string;\n\t\t\t\tadminSecret?: string;\n\t\t\t\tjson?: boolean;\n\t\t\t},\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst rows = await coordinatorListBootstrapGrantsAction({\n\t\t\t\t\tgroupId,\n\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t\tremoteUrl: opts.remoteUrl?.trim() || null,\n\t\t\t\t\tadminSecret: opts.adminSecret?.trim() || null,\n\t\t\t\t});\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(rows, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem coordinator list-bootstrap-grants\");\n\t\t\t\tif (rows.length === 0) {\n\t\t\t\t\tp.outro(`No bootstrap grants for ${groupId.trim()}`);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (const row of rows) {\n\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t`- ${row.grant_id} seed=${row.seed_device_id} worker=${row.worker_device_id} expires=${row.expires_at} revoked=${row.revoked_at ?? \"no\"}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tp.outro(`${rows.length} bootstrap grant(s)`);\n\t\t\t} catch (err) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\n\t\t\t\t\t\t\"list_bootstrap_grants_failed\",\n\t\t\t\t\t\terr instanceof Error ? err.message : String(err),\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t},\n\t);\n\tcmd.addCommand(listBootstrapGrantsCmd);\n\n\t// ---- revoke-bootstrap-grant ----\n\n\tconst revokeBootstrapGrantCmd = new Command(\"revoke-bootstrap-grant\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Revoke a bootstrap grant\")\n\t\t.argument(\"<grant-id>\", \"bootstrap grant id\")\n\t\t.option(\"--remote-url <url>\", \"remote coordinator URL override\")\n\t\t.option(\"--admin-secret <secret>\", \"remote coordinator admin secret override\");\n\taddDbOption(revokeBootstrapGrantCmd);\n\taddJsonOption(revokeBootstrapGrantCmd);\n\trevokeBootstrapGrantCmd.action(\n\t\tasync (\n\t\t\tgrantId: string,\n\t\t\topts: {\n\t\t\t\tdb?: string;\n\t\t\t\tdbPath?: string;\n\t\t\t\tremoteUrl?: string;\n\t\t\t\tadminSecret?: string;\n\t\t\t\tjson?: boolean;\n\t\t\t},\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst ok = await coordinatorRevokeBootstrapGrantAction({\n\t\t\t\t\tgrantId,\n\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t\tremoteUrl: opts.remoteUrl?.trim() || null,\n\t\t\t\t\tadminSecret: opts.adminSecret?.trim() || null,\n\t\t\t\t});\n\t\t\t\tif (!ok) {\n\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\temitJsonError(\"grant_not_found\", `Bootstrap grant not found: ${grantId.trim()}`);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tp.log.error(`Bootstrap grant not found: ${grantId.trim()}`);\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify({ ok: true, grant_id: grantId.trim() }, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem coordinator revoke-bootstrap-grant\");\n\t\t\t\tp.log.success(`Revoked ${grantId.trim()}`);\n\t\t\t\tp.outro(\"revoked\");\n\t\t\t} catch (err) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"revoke_failed\", err instanceof Error ? err.message : String(err));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t},\n\t);\n\tcmd.addCommand(revokeBootstrapGrantCmd);\n\n\t// ---- create-invite ----\n\n\tconst createInviteCmd = new Command(\"create-invite\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Create a coordinator team invite\")\n\t\t.argument(\"[group]\", \"group id\")\n\t\t.option(\"--group <group>\", \"group id\")\n\t\t.option(\"--coordinator-url <url>\", \"coordinator URL override\")\n\t\t.option(\"--policy <policy>\", \"invite policy\", \"auto_admit\")\n\t\t.option(\"--ttl-hours <hours>\", \"invite TTL hours\", \"24\")\n\t\t.option(\"--remote-url <url>\", \"remote coordinator URL override\")\n\t\t.option(\"--admin-secret <secret>\", \"remote coordinator admin secret override\");\n\taddDbOption(createInviteCmd);\n\taddJsonOption(createInviteCmd);\n\tcreateInviteCmd.action(\n\t\tasync (\n\t\t\tgroupArg: string | undefined,\n\t\t\topts: {\n\t\t\t\tgroup?: string;\n\t\t\t\tcoordinatorUrl?: string;\n\t\t\t\tpolicy?: string;\n\t\t\t\tttlHours?: string;\n\t\t\t\tdb?: string;\n\t\t\t\tdbPath?: string;\n\t\t\t\tremoteUrl?: string;\n\t\t\t\tadminSecret?: string;\n\t\t\t\tjson?: boolean;\n\t\t\t},\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst ttlHours = Number.parseInt(String(opts.ttlHours ?? \"24\"), 10);\n\t\t\t\tconst groupId = String(opts.group ?? \"\").trim() || String(groupArg ?? \"\").trim();\n\t\t\t\tconst result = await coordinatorCreateInviteAction({\n\t\t\t\t\tgroupId,\n\t\t\t\t\tcoordinatorUrl: opts.coordinatorUrl?.trim() || null,\n\t\t\t\t\tpolicy: String(opts.policy ?? \"auto_admit\").trim(),\n\t\t\t\t\tttlHours,\n\t\t\t\t\tcreatedBy: null,\n\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t\tremoteUrl: opts.remoteUrl?.trim() || null,\n\t\t\t\t\tadminSecret: opts.adminSecret?.trim() || null,\n\t\t\t\t});\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem coordinator create-invite\");\n\t\t\t\tp.log.success(`Invite created for ${groupId}`);\n\t\t\t\tif (typeof result.link === \"string\") p.log.message(`- link: ${result.link}`);\n\t\t\t\tif (typeof result.encoded === \"string\") p.log.message(`- invite: ${result.encoded}`);\n\t\t\t\tfor (const warning of Array.isArray(result.warnings) ? result.warnings : []) {\n\t\t\t\t\tp.log.warn(String(warning));\n\t\t\t\t}\n\t\t\t\tp.outro(\"Invite ready\");\n\t\t\t} catch (err) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"create_invite_failed\", err instanceof Error ? err.message : String(err));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t},\n\t);\n\tcmd.addCommand(createInviteCmd);\n\n\t// ---- import-invite ----\n\n\tconst importInviteCmd = new Command(\"import-invite\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Import a coordinator invite\")\n\t\t.argument(\"<invite>\", \"invite value or link\")\n\t\t.option(\"--keys-dir <path>\", \"keys directory\");\n\taddDbOption(importInviteCmd);\n\taddConfigOption(importInviteCmd);\n\taddJsonOption(importInviteCmd);\n\timportInviteCmd.action(\n\t\tasync (\n\t\t\tinvite: string,\n\t\t\topts: {\n\t\t\t\tdb?: string;\n\t\t\t\tdbPath?: string;\n\t\t\t\tkeysDir?: string;\n\t\t\t\tconfig?: string;\n\t\t\t\tjson?: boolean;\n\t\t\t},\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst result = await coordinatorImportInviteAction({\n\t\t\t\t\tinviteValue: invite,\n\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t\tkeysDir: opts.keysDir ?? null,\n\t\t\t\t\tconfigPath: opts.config ?? null,\n\t\t\t\t});\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem coordinator import-invite\");\n\t\t\t\tp.log.success(`Invite imported for ${result.group_id}`);\n\t\t\t\tp.log.message(`- coordinator: ${result.coordinator_url}`);\n\t\t\t\tp.log.message(`- status: ${result.status}`);\n\t\t\t\tp.outro(\"Coordinator config updated\");\n\t\t\t} catch (err) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"import_invite_failed\", err instanceof Error ? err.message : String(err));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t},\n\t);\n\tcmd.addCommand(importInviteCmd);\n\n\t// ---- list-join-requests ----\n\n\tconst listJoinRequestsCmd = new Command(\"list-join-requests\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"List pending coordinator join requests\")\n\t\t.argument(\"[group]\", \"group id\")\n\t\t.option(\"--group <group>\", \"group id\")\n\t\t.option(\"--remote-url <url>\", \"remote coordinator URL override\")\n\t\t.option(\"--admin-secret <secret>\", \"remote coordinator admin secret override\");\n\taddDbOption(listJoinRequestsCmd);\n\taddJsonOption(listJoinRequestsCmd);\n\tlistJoinRequestsCmd.action(\n\t\tasync (\n\t\t\tgroupArg: string | undefined,\n\t\t\topts: {\n\t\t\t\tgroup?: string;\n\t\t\t\tdb?: string;\n\t\t\t\tdbPath?: string;\n\t\t\t\tremoteUrl?: string;\n\t\t\t\tadminSecret?: string;\n\t\t\t\tjson?: boolean;\n\t\t\t},\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst groupId = String(opts.group ?? \"\").trim() || String(groupArg ?? \"\").trim();\n\t\t\t\tconst rows = await coordinatorListJoinRequestsAction({\n\t\t\t\t\tgroupId,\n\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t\tremoteUrl: opts.remoteUrl?.trim() || null,\n\t\t\t\t\tadminSecret: opts.adminSecret?.trim() || null,\n\t\t\t\t});\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify(rows, null, 2));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.intro(\"codemem coordinator list-join-requests\");\n\t\t\t\tif (rows.length === 0) {\n\t\t\t\t\tp.outro(`No pending join requests for ${groupId}`);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (const row of rows) {\n\t\t\t\t\tconst displayName = row.display_name || row.device_id;\n\t\t\t\t\tp.log.message(`- ${displayName} (${row.device_id}) request_id=${row.request_id}`);\n\t\t\t\t}\n\t\t\t\tp.outro(`${rows.length} pending join request(s)`);\n\t\t\t} catch (err) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\n\t\t\t\t\t\t\"list_join_requests_failed\",\n\t\t\t\t\t\terr instanceof Error ? err.message : String(err),\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t},\n\t);\n\tcmd.addCommand(listJoinRequestsCmd);\n\n\t// ---- approve-join-request / deny-join-request ----\n\n\tfunction addReviewJoinRequestCommand(\n\t\tname: \"approve-join-request\" | \"deny-join-request\",\n\t\tapprove: boolean,\n\t) {\n\t\tconst reviewCmd = new Command(name)\n\t\t\t.configureHelp(helpStyle)\n\t\t\t.description(`${approve ? \"Approve\" : \"Deny\"} a coordinator join request`)\n\t\t\t.argument(\"<request-id>\", \"join request id\")\n\t\t\t.option(\"--remote-url <url>\", \"remote coordinator URL override\")\n\t\t\t.option(\"--admin-secret <secret>\", \"remote coordinator admin secret override\");\n\t\taddDbOption(reviewCmd);\n\t\taddJsonOption(reviewCmd);\n\t\treviewCmd.action(\n\t\t\tasync (\n\t\t\t\trequestId: string,\n\t\t\t\topts: {\n\t\t\t\t\tdb?: string;\n\t\t\t\t\tdbPath?: string;\n\t\t\t\t\tremoteUrl?: string;\n\t\t\t\t\tadminSecret?: string;\n\t\t\t\t\tjson?: boolean;\n\t\t\t\t},\n\t\t\t) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst request = await coordinatorReviewJoinRequestAction({\n\t\t\t\t\t\trequestId: requestId.trim(),\n\t\t\t\t\t\tapprove,\n\t\t\t\t\t\treviewedBy: null,\n\t\t\t\t\t\tdbPath: resolveDbOpt(opts) ?? null,\n\t\t\t\t\t\tremoteUrl: opts.remoteUrl?.trim() || null,\n\t\t\t\t\t\tadminSecret: opts.adminSecret?.trim() || null,\n\t\t\t\t\t});\n\t\t\t\t\tif (!request) {\n\t\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\t\temitJsonError(\n\t\t\t\t\t\t\t\t\"join_request_not_found\",\n\t\t\t\t\t\t\t\t`Join request not found: ${requestId.trim()}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tp.log.error(`Join request not found: ${requestId.trim()}`);\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\tconsole.log(JSON.stringify(request, null, 2));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tp.intro(`codemem coordinator ${name}`);\n\t\t\t\t\tp.log.success(`${approve ? \"Approved\" : \"Denied\"} join request ${requestId.trim()}`);\n\t\t\t\t\tp.outro(String(request.status ?? \"updated\"));\n\t\t\t\t} catch (err) {\n\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\temitJsonError(\"review_failed\", err instanceof Error ? err.message : String(err));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\t\tcmd.addCommand(reviewCmd);\n\t}\n\n\taddReviewJoinRequestCommand(\"approve-join-request\", true);\n\taddReviewJoinRequestCommand(\"deny-join-request\", false);\n\n\treturn cmd;\n}\n\n/** Canonical top-level coordinator command for registration in index.ts. */\nexport const coordinatorCommand = buildCoordinatorCommand();\n","import { statSync } from \"node:fs\";\nimport * as p from \"@clack/prompts\";\nimport {\n\taiBackfillStructuredContent,\n\tbackfillMemoryDedupKeys,\n\tbackfillNarrativeFromBody,\n\tbackfillTagsText,\n\tconnect,\n\tdeactivateLowSignalMemories,\n\tdeactivateLowSignalObservations,\n\tdedupNearDuplicateMemories,\n\tgetRawEventStatus,\n\tinitDatabase,\n\tMemoryStore,\n\tplanReplicationOpsAgePrune,\n\tpruneReplicationOpsUntilCaughtUp,\n\trawEventsGate,\n\tresolveDbPath,\n\tresolveProject,\n\tretryRawEventFailures,\n\tvacuumDatabase,\n} from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddDbOption,\n\taddJsonOption,\n\ttype DbOpts,\n\ttype JsonOpts,\n\tresolveDbOpt,\n} from \"../shared-options.js\";\n\nfunction formatBytes(bytes: number): string {\n\tif (bytes < 1024) return `${bytes} B`;\n\tif (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction parseOptionalPositiveInt(value: string | undefined): number | undefined {\n\tif (!value) return undefined;\n\tconst parsed = Number.parseInt(value, 10);\n\tif (!Number.isFinite(parsed) || parsed <= 0) {\n\t\tthrow new Error(`invalid positive integer: ${value}`);\n\t}\n\treturn parsed;\n}\n\nfunction parseKindsCsv(value: string | undefined): string[] | undefined {\n\tif (!value) return undefined;\n\tconst kinds = value\n\t\t.split(\",\")\n\t\t.map((kind) => kind.trim())\n\t\t.filter((kind) => kind.length > 0);\n\treturn kinds.length > 0 ? kinds : undefined;\n}\n\nfunction estimateReplicationOpsBytes(db: ReturnType<typeof connect>): number {\n\ttry {\n\t\tconst row = db\n\t\t\t.prepare(\n\t\t\t\t`SELECT COALESCE(SUM(pgsize), 0) AS total_bytes\n\t\t\t\t FROM dbstat\n\t\t\t\t WHERE name = 'replication_ops'\n\t\t\t\t OR name LIKE 'idx_replication_ops_%'\n\t\t\t\t OR name LIKE 'sqlite_autoindex_replication_ops_%'`,\n\t\t\t)\n\t\t\t.get() as { total_bytes?: number } | undefined;\n\t\treturn Number(row?.total_bytes ?? 0);\n\t} catch {\n\t\treturn 0;\n\t}\n}\n\nexport const dbCommand = new Command(\"db\")\n\t.configureHelp(helpStyle)\n\t.description(\"Database maintenance\");\n\n// --- db init ---\nconst initCmd = new Command(\"init\")\n\t.configureHelp(helpStyle)\n\t.description(\"Create or verify the SQLite database and schema\");\naddDbOption(initCmd);\ninitCmd.action((opts: DbOpts) => {\n\tconst result = initDatabase(resolveDbOpt(opts));\n\tp.intro(\"codemem db init\");\n\tp.log.success(`Database ready: ${result.path}`);\n\tp.outro(`Size: ${result.sizeBytes.toLocaleString()} bytes`);\n});\ndbCommand.addCommand(initCmd);\n\n// --- db vacuum ---\nconst vacuumCmd = new Command(\"vacuum\")\n\t.configureHelp(helpStyle)\n\t.description(\"Run VACUUM on the SQLite database\");\naddDbOption(vacuumCmd);\nvacuumCmd.action((opts: DbOpts) => {\n\tconst result = vacuumDatabase(resolveDbOpt(opts));\n\tp.intro(\"codemem db vacuum\");\n\tp.log.success(`Vacuumed: ${result.path}`);\n\tp.outro(`Size: ${result.sizeBytes.toLocaleString()} bytes`);\n});\ndbCommand.addCommand(vacuumCmd);\n\n// --- db prune-replication-ops ---\nconst pruneReplCmd = new Command(\"prune-replication-ops\")\n\t.configureHelp(helpStyle)\n\t.description(\n\t\t\"Prune replication op history with approximate oldest-first retention, dry-run, and progress reporting\",\n\t)\n\t.option(\"--dry-run\", \"show current size/targets without deleting\")\n\t.option(\"--max-age-days <days>\", \"retention age threshold in days\", \"30\")\n\t.option(\"--max-size-mb <mb>\", \"target replication log budget in MB\", \"512\")\n\t.option(\"--batch-ops <n>\", \"max ops deleted per batch\", \"5000\")\n\t.option(\"--batch-runtime-ms <ms>\", \"max runtime per batch in ms\", \"2000\")\n\t.option(\"--vacuum\", \"run VACUUM explicitly after prune completes\");\naddDbOption(pruneReplCmd);\npruneReplCmd.action(\n\t(\n\t\topts: DbOpts & {\n\t\t\tdryRun?: boolean;\n\t\t\tmaxAgeDays: string;\n\t\t\tmaxSizeMb: string;\n\t\t\tbatchOps: string;\n\t\t\tbatchRuntimeMs: string;\n\t\t\tvacuum?: boolean;\n\t\t},\n\t) => {\n\t\tconst dbPath = resolveDbPath(resolveDbOpt(opts));\n\t\tconst db = connect(dbPath);\n\t\tlet dbOpen = true;\n\t\ttry {\n\t\t\tconst maxAgeDays = Number.parseInt(opts.maxAgeDays, 10) || 30;\n\t\t\tconst maxSizeMb = Number.parseInt(opts.maxSizeMb, 10) || 512;\n\t\t\tconst batchOps = Number.parseInt(opts.batchOps, 10) || 5000;\n\t\t\tconst batchRuntimeMs = Number.parseInt(opts.batchRuntimeMs, 10) || 2000;\n\t\t\tconst beforeBytes = estimateReplicationOpsBytes(db);\n\t\t\tp.intro(\"codemem db prune-replication-ops\");\n\t\t\tp.log.info(`Replication ops size: ${formatBytes(beforeBytes)}`);\n\t\t\tp.log.info(\n\t\t\t\t`Policy: approximately prune oldest-first toward <= ${maxSizeMb} MB while removing history older than ${maxAgeDays} day(s), subject to per-pass batch/runtime limits`,\n\t\t\t);\n\t\t\tconst agePlan = planReplicationOpsAgePrune(db, maxAgeDays, batchOps);\n\t\t\tif (agePlan.candidate_ops > 0) {\n\t\t\t\tp.log.info(\n\t\t\t\t\t`Age pass plan: ${agePlan.candidate_ops.toLocaleString()} ops, ~${formatBytes(agePlan.estimated_candidate_bytes)} in ~${agePlan.estimated_batches.toLocaleString()} batch(es), cutoff ${agePlan.cutoff_cursor}`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tp.log.info(\"Age pass plan: no ops older than cutoff\");\n\t\t\t}\n\n\t\t\tif (opts.dryRun) {\n\t\t\t\tp.outro(\"Dry run only; no changes made\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst loopResult = pruneReplicationOpsUntilCaughtUp(db, {\n\t\t\t\tmaxAgeDays,\n\t\t\t\tmaxSizeBytes: maxSizeMb * 1024 * 1024,\n\t\t\t\tmaxDeleteOps: batchOps,\n\t\t\t\tmaxRuntimeMs: batchRuntimeMs,\n\t\t\t\tonPass: (pass) => {\n\t\t\t\t\tif (pass.deleted === 0 && !pass.stoppedByBudget) return;\n\t\t\t\t\tconst suffix = pass.stoppedByBudget ? \" (budget-limited)\" : \"\";\n\t\t\t\t\tp.log.step(\n\t\t\t\t\t\t`Pass ${pass.passNumber}: deleted ${pass.deleted.toLocaleString()} ops, remaining size ~${formatBytes(pass.afterBytes)}${suffix}`,\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tp.log.info(`Deleted ops: ${loopResult.totalDeleted.toLocaleString()}`);\n\t\t\tp.log.info(\n\t\t\t\t`Estimated replication ops size after prune: ${formatBytes(loopResult.afterBytes)} (approximate)`,\n\t\t\t);\n\t\t\tif (loopResult.lastFloor) p.log.info(`Retained floor: ${loopResult.lastFloor}`);\n\t\t\tif (loopResult.stoppedByBudget) {\n\t\t\t\tp.log.warn(\n\t\t\t\t\t\"Prune stopped because the current batch/runtime budget was exhausted before retention caught up. Re-run with higher --batch-ops or --batch-runtime-ms for faster catch-up.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (opts.vacuum) {\n\t\t\t\tp.log.step(\"Running VACUUM as requested...\");\n\t\t\t\tdb.close();\n\t\t\t\tdbOpen = false;\n\t\t\t\tconst vacuumed = vacuumDatabase(dbPath);\n\t\t\t\tp.outro(`Done. VACUUM complete. File size is now ${formatBytes(vacuumed.sizeBytes)}.`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.outro(\n\t\t\t\t\"Done. Retention is approximate oldest-first pruning. SQLite file size may not shrink until you run `codemem db vacuum` explicitly (or re-run this command with --vacuum).\",\n\t\t\t);\n\t\t} finally {\n\t\t\tif (dbOpen) db.close();\n\t\t}\n\t},\n);\ndbCommand.addCommand(pruneReplCmd);\n\n// --- db raw-events-status ---\nconst rawEventsStatusCmd = new Command(\"raw-events-status\")\n\t.configureHelp(helpStyle)\n\t.description(\"Show pending raw-event backlog by source stream\")\n\t.option(\"-n, --limit <n>\", \"max rows to show\", \"25\");\naddDbOption(rawEventsStatusCmd);\naddJsonOption(rawEventsStatusCmd);\nrawEventsStatusCmd.action((opts: DbOpts & JsonOpts & { limit: string }) => {\n\tconst result = getRawEventStatus(resolveDbOpt(opts), Number.parseInt(opts.limit, 10) || 25);\n\tif (opts.json) {\n\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\treturn;\n\t}\n\tp.intro(\"codemem db raw-events-status\");\n\tp.log.info(\n\t\t`Totals: ${result.totals.pending.toLocaleString()} pending across ${result.totals.sessions.toLocaleString()} session(s)`,\n\t);\n\tif (result.items.length === 0) {\n\t\tp.outro(\"No pending raw events\");\n\t\treturn;\n\t}\n\tfor (const item of result.items) {\n\t\tp.log.message(\n\t\t\t`${item.source}:${item.stream_id} pending=${Math.max(0, item.last_received_event_seq - item.last_flushed_event_seq)} ` +\n\t\t\t\t`received=${item.last_received_event_seq} flushed=${item.last_flushed_event_seq} project=${item.project ?? \"\"}`,\n\t\t);\n\t}\n\tp.outro(\"done\");\n});\ndbCommand.addCommand(rawEventsStatusCmd);\n\n// --- db raw-events-retry ---\nconst rawEventsRetryCmd = new Command(\"raw-events-retry\")\n\t.configureHelp(helpStyle)\n\t.description(\"Requeue failed raw-event flush batches\")\n\t.option(\"-n, --limit <n>\", \"max failed batches to requeue\", \"25\");\naddDbOption(rawEventsRetryCmd);\nrawEventsRetryCmd.action((opts: DbOpts & { limit: string }) => {\n\tconst result = retryRawEventFailures(resolveDbOpt(opts), Number.parseInt(opts.limit, 10) || 25);\n\tp.intro(\"codemem db raw-events-retry\");\n\tp.outro(`Requeued ${result.retried.toLocaleString()} failed batch(es)`);\n});\ndbCommand.addCommand(rawEventsRetryCmd);\n\n// --- db raw-events-gate ---\nconst rawEventsGateCmd = new Command(\"raw-events-gate\")\n\t.configureHelp(helpStyle)\n\t.description(\"Validate raw-event reliability thresholds (non-zero exit on failure)\")\n\t.option(\"--min-flush-success-rate <rate>\", \"minimum flush success rate\", \"0.95\")\n\t.option(\"--max-dropped-event-rate <rate>\", \"maximum dropped event rate\", \"0.05\")\n\t.option(\"--min-session-boundary-accuracy <rate>\", \"minimum session boundary accuracy\", \"0.9\")\n\t.option(\"--window-hours <hours>\", \"lookback window in hours\", \"24\");\naddDbOption(rawEventsGateCmd);\naddJsonOption(rawEventsGateCmd);\nrawEventsGateCmd.action(\n\t(\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\tminFlushSuccessRate: string;\n\t\t\t\tmaxDroppedEventRate: string;\n\t\t\t\tminSessionBoundaryAccuracy: string;\n\t\t\t\twindowHours: string;\n\t\t\t},\n\t) => {\n\t\tconst result = rawEventsGate(resolveDbOpt(opts), {\n\t\t\tminFlushSuccessRate: Number.parseFloat(opts.minFlushSuccessRate),\n\t\t\tmaxDroppedEventRate: Number.parseFloat(opts.maxDroppedEventRate),\n\t\t\tminSessionBoundaryAccuracy: Number.parseFloat(opts.minSessionBoundaryAccuracy),\n\t\t\twindowHours: Number.parseFloat(opts.windowHours),\n\t\t});\n\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\tif (!result.passed) process.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\n\t\tp.intro(\"codemem db raw-events-gate\");\n\t\tp.log.info(\n\t\t\t[\n\t\t\t\t`flush_success_rate: ${result.metrics.rates.flush_success_rate.toFixed(4)}`,\n\t\t\t\t`dropped_event_rate: ${result.metrics.rates.dropped_event_rate.toFixed(4)}`,\n\t\t\t\t`session_boundary_accuracy: ${result.metrics.rates.session_boundary_accuracy.toFixed(4)}`,\n\t\t\t\t`window_hours: ${result.metrics.window_hours ?? \"all\"}`,\n\t\t\t].join(\"\\n\"),\n\t\t);\n\n\t\tif (result.passed) {\n\t\t\tp.outro(\"reliability gate passed\");\n\t\t} else {\n\t\t\tfor (const f of result.failures) {\n\t\t\t\tp.log.error(f);\n\t\t\t}\n\t\t\tp.outro(\"reliability gate FAILED\");\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t},\n);\ndbCommand.addCommand(rawEventsGateCmd);\n\n// --- db rename-project ---\nconst renameProjectCmd = new Command(\"rename-project\")\n\t.configureHelp(helpStyle)\n\t.description(\"Rename a project across sessions and related tables\")\n\t.argument(\"<old-name>\", \"current project name\")\n\t.argument(\"<new-name>\", \"new project name\")\n\t.option(\"--apply\", \"apply changes (default is dry-run)\");\naddDbOption(renameProjectCmd);\nrenameProjectCmd.action((oldName: string, newName: string, opts: DbOpts & { apply?: boolean }) => {\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\ttry {\n\t\tconst dryRun = !opts.apply;\n\t\tconst escapedOld = oldName.replace(/%/g, \"\\\\%\").replace(/_/g, \"\\\\_\");\n\t\tconst suffixPattern = `%/${escapedOld}`;\n\t\tconst tables = [\"sessions\", \"raw_event_sessions\"] as const;\n\t\tconst counts: Record<string, number> = {};\n\t\tconst run = () => {\n\t\t\tfor (const table of tables) {\n\t\t\t\tconst rows = store.db\n\t\t\t\t\t.prepare(\n\t\t\t\t\t\t`SELECT COUNT(*) as cnt FROM ${table} WHERE project = ? OR project LIKE ? ESCAPE '\\\\'`,\n\t\t\t\t\t)\n\t\t\t\t\t.get(oldName, suffixPattern) as { cnt: number };\n\t\t\t\tcounts[table] = rows.cnt;\n\t\t\t\tif (!dryRun && rows.cnt > 0) {\n\t\t\t\t\tstore.db\n\t\t\t\t\t\t.prepare(`UPDATE ${table} SET project = ? WHERE project = ?`)\n\t\t\t\t\t\t.run(newName, oldName);\n\t\t\t\t\tstore.db\n\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t`UPDATE ${table} SET project = ? WHERE project LIKE ? ESCAPE '\\\\' AND project != ?`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.run(newName, suffixPattern, newName);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tif (dryRun) {\n\t\t\trun();\n\t\t} else {\n\t\t\tstore.db.transaction(run)();\n\t\t}\n\t\tconst action = dryRun ? \"Will rename\" : \"Renamed\";\n\t\tp.intro(\"codemem db rename-project\");\n\t\tp.log.info(`${action} ${oldName} → ${newName}`);\n\t\tp.log.info(\n\t\t\t[`Sessions: ${counts.sessions}`, `Raw event sessions: ${counts.raw_event_sessions}`].join(\n\t\t\t\t\"\\n\",\n\t\t\t),\n\t\t);\n\t\tif (dryRun) {\n\t\t\tp.outro(\"Pass --apply to execute\");\n\t\t} else {\n\t\t\tp.outro(\"done\");\n\t\t}\n\t} finally {\n\t\tstore.close();\n\t}\n});\ndbCommand.addCommand(renameProjectCmd);\n\n// --- db normalize-projects ---\nconst normalizeProjectsCmd = new Command(\"normalize-projects\")\n\t.configureHelp(helpStyle)\n\t.description(\"Normalize path-like project identifiers to their basename\")\n\t.option(\"--apply\", \"apply changes (default is dry-run)\");\naddDbOption(normalizeProjectsCmd);\nnormalizeProjectsCmd.action((opts: DbOpts & { apply?: boolean }) => {\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\ttry {\n\t\tconst dryRun = !opts.apply;\n\t\tconst tables = [\"sessions\", \"raw_event_sessions\"] as const;\n\t\tconst rewrites: Map<string, string> = new Map();\n\t\tconst counts: Record<string, number> = {};\n\n\t\tconst run = () => {\n\t\t\tfor (const table of tables) {\n\t\t\t\tconst projects = store.db\n\t\t\t\t\t.prepare(\n\t\t\t\t\t\t`SELECT DISTINCT project FROM ${table} WHERE project IS NOT NULL AND project LIKE '%/%'`,\n\t\t\t\t\t)\n\t\t\t\t\t.all() as Array<{ project: string }>;\n\t\t\t\tlet updated = 0;\n\t\t\t\tfor (const row of projects) {\n\t\t\t\t\tconst basename = row.project.split(\"/\").pop() ?? row.project;\n\t\t\t\t\tif (basename !== row.project) {\n\t\t\t\t\t\trewrites.set(row.project, basename);\n\t\t\t\t\t\tif (!dryRun) {\n\t\t\t\t\t\t\tconst info = store.db\n\t\t\t\t\t\t\t\t.prepare(`UPDATE ${table} SET project = ? WHERE project = ?`)\n\t\t\t\t\t\t\t\t.run(basename, row.project);\n\t\t\t\t\t\t\tupdated += info.changes;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst cnt = store.db\n\t\t\t\t\t\t\t\t.prepare(`SELECT COUNT(*) as cnt FROM ${table} WHERE project = ?`)\n\t\t\t\t\t\t\t\t.get(row.project) as { cnt: number };\n\t\t\t\t\t\t\tupdated += cnt.cnt;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcounts[table] = updated;\n\t\t\t}\n\t\t};\n\t\tif (dryRun) {\n\t\t\trun();\n\t\t} else {\n\t\t\tstore.db.transaction(run)();\n\t\t}\n\n\t\tp.intro(\"codemem db normalize-projects\");\n\t\tp.log.info(`Dry run: ${dryRun}`);\n\t\tp.log.info(\n\t\t\t[\n\t\t\t\t`Sessions to update: ${counts.sessions}`,\n\t\t\t\t`Raw event sessions to update: ${counts.raw_event_sessions}`,\n\t\t\t].join(\"\\n\"),\n\t\t);\n\t\tif (rewrites.size > 0) {\n\t\t\tp.log.info(\"Rewritten paths:\");\n\t\t\tfor (const [from, to] of [...rewrites.entries()].sort()) {\n\t\t\t\tp.log.message(` ${from} → ${to}`);\n\t\t\t}\n\t\t}\n\t\tif (dryRun) {\n\t\t\tp.outro(\"Pass --apply to execute\");\n\t\t} else {\n\t\t\tp.outro(\"done\");\n\t\t}\n\t} finally {\n\t\tstore.close();\n\t}\n});\ndbCommand.addCommand(normalizeProjectsCmd);\n\n// --- db size-report ---\nconst sizeReportCmd = new Command(\"size-report\")\n\t.configureHelp(helpStyle)\n\t.description(\"Show SQLite file size and major storage consumers\")\n\t.option(\"--limit <n>\", \"number of largest tables/indexes to show\", \"12\");\naddDbOption(sizeReportCmd);\naddJsonOption(sizeReportCmd);\nsizeReportCmd.action((opts: DbOpts & JsonOpts & { limit: string }) => {\n\tconst dbPath = resolveDbPath(resolveDbOpt(opts));\n\tconst db = connect(dbPath);\n\ttry {\n\t\tconst limit = Math.max(1, Number.parseInt(opts.limit, 10) || 12);\n\t\tconst fileSizeBytes = statSync(dbPath).size;\n\t\tconst pageInfo = db\n\t\t\t.prepare(\"SELECT page_count * page_size as total FROM pragma_page_count, pragma_page_size\")\n\t\t\t.get() as { total: number } | undefined;\n\t\tconst freePages = db.prepare(\"SELECT freelist_count FROM pragma_freelist_count\").get() as\n\t\t\t| { freelist_count: number }\n\t\t\t| undefined;\n\t\tconst pageSize = db.prepare(\"PRAGMA page_size\").get() as { page_size: number } | undefined;\n\t\tconst tables = db\n\t\t\t.prepare(\n\t\t\t\t`SELECT name, SUM(pgsize) as size_bytes\n\t\t\t\t FROM dbstat\n\t\t\t\t GROUP BY name\n\t\t\t\t ORDER BY size_bytes DESC\n\t\t\t\t LIMIT ?`,\n\t\t\t)\n\t\t\t.all(limit) as Array<{ name: string; size_bytes: number }>;\n\n\t\tif (opts.json) {\n\t\t\tconsole.log(\n\t\t\t\tJSON.stringify(\n\t\t\t\t\t{\n\t\t\t\t\t\tfile_size_bytes: fileSizeBytes,\n\t\t\t\t\t\tdb_size_bytes: pageInfo?.total ?? 0,\n\t\t\t\t\t\tfree_bytes: (freePages?.freelist_count ?? 0) * (pageSize?.page_size ?? 4096),\n\t\t\t\t\t\ttables: tables.map((t) => ({ name: t.name, size_bytes: t.size_bytes })),\n\t\t\t\t\t},\n\t\t\t\t\tnull,\n\t\t\t\t\t2,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tp.intro(\"codemem db size-report\");\n\t\tp.log.info(\n\t\t\t[\n\t\t\t\t`File size: ${formatBytes(fileSizeBytes)}`,\n\t\t\t\t`DB size: ${formatBytes(pageInfo?.total ?? 0)}`,\n\t\t\t\t`Free space: ${formatBytes((freePages?.freelist_count ?? 0) * (pageSize?.page_size ?? 4096))}`,\n\t\t\t].join(\"\\n\"),\n\t\t);\n\t\tif (tables.length > 0) {\n\t\t\tp.log.info(\"Largest objects:\");\n\t\t\tfor (const t of tables) {\n\t\t\t\tp.log.message(` ${t.name.padEnd(40)} ${formatBytes(t.size_bytes).padStart(10)}`);\n\t\t\t}\n\t\t}\n\t\tp.outro(\"done\");\n\t} finally {\n\t\tdb.close();\n\t}\n});\ndbCommand.addCommand(sizeReportCmd);\n\n// --- db backfill-tags ---\nconst backfillTagsCmd = new Command(\"backfill-tags\")\n\t.configureHelp(helpStyle)\n\t.description(\"Populate tags_text for memories where tags are empty\")\n\t.option(\"--limit <n>\", \"max memories to check\")\n\t.option(\"--since <iso>\", \"only memories created at/after this ISO timestamp\")\n\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t.option(\"--all-projects\", \"backfill across all projects\")\n\t.option(\"--inactive\", \"include inactive memories\")\n\t.option(\"--dry-run\", \"preview updates without writing\");\naddDbOption(backfillTagsCmd);\naddJsonOption(backfillTagsCmd);\nbackfillTagsCmd.action(\n\t(\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\tlimit?: string;\n\t\t\t\tsince?: string;\n\t\t\t\tproject?: string;\n\t\t\t\tallProjects?: boolean;\n\t\t\t\tinactive?: boolean;\n\t\t\t\tdryRun?: boolean;\n\t\t\t},\n\t) => {\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tconst limit = parseOptionalPositiveInt(opts.limit);\n\t\t\tconst project =\n\t\t\t\topts.allProjects === true\n\t\t\t\t\t? null\n\t\t\t\t\t: opts.project?.trim() ||\n\t\t\t\t\t\tprocess.env.CODEMEM_PROJECT?.trim() ||\n\t\t\t\t\t\tresolveProject(process.cwd(), null);\n\t\t\tconst result = backfillTagsText(store.db, {\n\t\t\t\tlimit,\n\t\t\t\tsince: opts.since ?? null,\n\t\t\t\tproject,\n\t\t\t\tactiveOnly: !opts.inactive,\n\t\t\t\tdryRun: opts.dryRun === true,\n\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst action = opts.dryRun ? \"Would update\" : \"Updated\";\n\t\t\tp.intro(\"codemem db backfill-tags\");\n\t\t\tp.log.success(`${action} ${result.updated} memories (skipped ${result.skipped})`);\n\t\t\tp.outro(`Checked ${result.checked} memories`);\n\t\t} catch (error) {\n\t\t\tp.log.error(error instanceof Error ? error.message : String(error));\n\t\t\tprocess.exitCode = 1;\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\ndbCommand.addCommand(backfillTagsCmd);\n\n// --- db prune-observations ---\nconst pruneObsCmd = new Command(\"prune-observations\")\n\t.configureHelp(helpStyle)\n\t.description(\"Deactivate low-signal observations (does not delete rows)\")\n\t.option(\"--limit <n>\", \"max observations to check\")\n\t.option(\"--dry-run\", \"preview deactivations without writing\");\naddDbOption(pruneObsCmd);\naddJsonOption(pruneObsCmd);\npruneObsCmd.action(\n\t(\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\tlimit?: string;\n\t\t\t\tdryRun?: boolean;\n\t\t\t},\n\t) => {\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tconst limit = parseOptionalPositiveInt(opts.limit);\n\t\t\tconst result = deactivateLowSignalObservations(store.db, limit ?? null, opts.dryRun === true);\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst action = opts.dryRun ? \"Would deactivate\" : \"Deactivated\";\n\t\t\tp.intro(\"codemem db prune-observations\");\n\t\t\tp.outro(`${action} ${result.deactivated} of ${result.checked} observations`);\n\t\t} catch (error) {\n\t\t\tp.log.error(error instanceof Error ? error.message : String(error));\n\t\t\tprocess.exitCode = 1;\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\ndbCommand.addCommand(pruneObsCmd);\n\n// --- db prune-memories ---\nconst pruneMemCmd = new Command(\"prune-memories\")\n\t.configureHelp(helpStyle)\n\t.description(\"Deactivate low-signal memories across selected kinds\")\n\t.option(\"--limit <n>\", \"max memories to check\")\n\t.option(\"--kinds <csv>\", \"comma-separated memory kinds (default set when omitted)\")\n\t.option(\"--dry-run\", \"preview deactivations without writing\");\naddDbOption(pruneMemCmd);\naddJsonOption(pruneMemCmd);\npruneMemCmd.action(\n\t(\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\tlimit?: string;\n\t\t\t\tkinds?: string;\n\t\t\t\tdryRun?: boolean;\n\t\t\t},\n\t) => {\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tconst limit = parseOptionalPositiveInt(opts.limit);\n\t\t\tconst kinds = parseKindsCsv(opts.kinds);\n\t\t\tconst result = deactivateLowSignalMemories(store.db, {\n\t\t\t\tkinds,\n\t\t\t\tlimit: limit ?? null,\n\t\t\t\tdryRun: opts.dryRun === true,\n\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst action = opts.dryRun ? \"Would deactivate\" : \"Deactivated\";\n\t\t\tp.intro(\"codemem db prune-memories\");\n\t\t\tp.outro(`${action} ${result.deactivated} of ${result.checked} memories`);\n\t\t} catch (error) {\n\t\t\tp.log.error(error instanceof Error ? error.message : String(error));\n\t\t\tprocess.exitCode = 1;\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\ndbCommand.addCommand(pruneMemCmd);\n\n// --- db dedup-memories ---\nconst dedupCmd = new Command(\"dedup-memories\")\n\t.configureHelp(helpStyle)\n\t.description(\n\t\t\"Deactivate near-duplicate memories (cross-session, same normalized title within time window)\",\n\t)\n\t.option(\"--window <ms>\", \"max time gap in milliseconds between duplicates (default: 3600000)\")\n\t.option(\"--limit <n>\", \"max pairs to check\")\n\t.option(\"--dry-run\", \"preview deactivations without writing\");\naddDbOption(dedupCmd);\naddJsonOption(dedupCmd);\ndedupCmd.action(\n\t(\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\twindow?: string;\n\t\t\t\tlimit?: string;\n\t\t\t\tdryRun?: boolean;\n\t\t\t},\n\t) => {\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tconst windowMs = parseOptionalPositiveInt(opts.window);\n\t\t\tconst limit = parseOptionalPositiveInt(opts.limit);\n\t\t\tconst result = dedupNearDuplicateMemories(store.db, {\n\t\t\t\twindowMs,\n\t\t\t\tlimit,\n\t\t\t\tdryRun: opts.dryRun === true,\n\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst action = opts.dryRun ? \"Would deactivate\" : \"Deactivated\";\n\t\t\tp.intro(\"codemem db dedup-memories\");\n\t\t\tif (result.pairs.length > 0 && result.pairs.length <= 20) {\n\t\t\t\tfor (const pair of result.pairs) {\n\t\t\t\t\tp.log.info(\n\t\t\t\t\t\t`${action} [${pair.deactivated_id}] (kept [${pair.kept_id}]): ${pair.title.slice(0, 80)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tp.outro(`${action} ${result.deactivated} duplicates from ${result.checked} pairs`);\n\t\t} catch (error) {\n\t\t\tp.log.error(error instanceof Error ? error.message : String(error));\n\t\t\tprocess.exitCode = 1;\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\ndbCommand.addCommand(dedupCmd);\n\nconst backfillDedupKeysCmd = new Command(\"backfill-dedup-keys\")\n\t.configureHelp(helpStyle)\n\t.description(\"Populate missing memory_items.dedup_key values for legacy rows\")\n\t.option(\"--limit <n>\", \"max memories to check\")\n\t.option(\"--dry-run\", \"preview updates without writing\");\naddDbOption(backfillDedupKeysCmd);\naddJsonOption(backfillDedupKeysCmd);\nbackfillDedupKeysCmd.action(\n\t(\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\tlimit?: string;\n\t\t\t\tdryRun?: boolean;\n\t\t\t},\n\t) => {\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tconst limit = parseOptionalPositiveInt(opts.limit);\n\t\t\tconst result = backfillMemoryDedupKeys(store.db, {\n\t\t\t\tlimit,\n\t\t\t\tdryRun: opts.dryRun === true,\n\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst action = opts.dryRun ? \"Would update\" : \"Updated\";\n\t\t\tp.intro(\"codemem db backfill-dedup-keys\");\n\t\t\tp.log.success(`${action} ${result.updated} memories (skipped ${result.skipped})`);\n\t\t\tp.outro(`Checked ${result.checked} memories`);\n\t\t} catch (error) {\n\t\t\tp.log.error(error instanceof Error ? error.message : String(error));\n\t\t\tprocess.exitCode = 1;\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\ndbCommand.addCommand(backfillDedupKeysCmd);\n\n// --- db backfill-narrative ---\nconst backfillNarrativeCmd = new Command(\"backfill-narrative\")\n\t.configureHelp(helpStyle)\n\t.description(\n\t\t\"Extract narrative from session_summary body_text (## Completed / ## Learned sections)\",\n\t)\n\t.option(\"--limit <n>\", \"max memories to check\")\n\t.option(\"--dry-run\", \"preview updates without writing\");\naddDbOption(backfillNarrativeCmd);\naddJsonOption(backfillNarrativeCmd);\nbackfillNarrativeCmd.action(\n\t(\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\tlimit?: string;\n\t\t\t\tdryRun?: boolean;\n\t\t\t},\n\t) => {\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tconst limit = parseOptionalPositiveInt(opts.limit);\n\t\t\tconst result = backfillNarrativeFromBody(store.db, {\n\t\t\t\tlimit,\n\t\t\t\tdryRun: opts.dryRun === true,\n\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst action = opts.dryRun ? \"Would update\" : \"Updated\";\n\t\t\tp.intro(\"codemem db backfill-narrative\");\n\t\t\tp.log.success(`${action} ${result.updated} memories (skipped ${result.skipped})`);\n\t\t\tp.outro(`Checked ${result.checked} memories`);\n\t\t} catch (error) {\n\t\t\tp.log.error(error instanceof Error ? error.message : String(error));\n\t\t\tprocess.exitCode = 1;\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\ndbCommand.addCommand(backfillNarrativeCmd);\n\n// --- db ai-backfill-structured ---\nconst aiBackfillStructuredCmd = new Command(\"ai-backfill-structured\")\n\t.configureHelp(helpStyle)\n\t.description(\n\t\t\"Use GPT-5.4 to populate missing narrative/facts/concepts for older non-session-summary memories\",\n\t)\n\t.option(\"--limit <n>\", \"max memories to check\")\n\t.option(\"--kinds <csv>\", \"comma-separated kinds to target\")\n\t.option(\n\t\t\"--overwrite\",\n\t\t\"overwrite existing structured fields instead of only filling missing ones\",\n\t)\n\t.option(\"--dry-run\", \"preview updates without writing\");\naddDbOption(aiBackfillStructuredCmd);\naddJsonOption(aiBackfillStructuredCmd);\naiBackfillStructuredCmd.action(\n\tasync (\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\tlimit?: string;\n\t\t\t\tkinds?: string;\n\t\t\t\toverwrite?: boolean;\n\t\t\t\tdryRun?: boolean;\n\t\t\t},\n\t) => {\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tconst limit = parseOptionalPositiveInt(opts.limit);\n\t\t\tconst kinds = parseKindsCsv(opts.kinds);\n\t\t\tconst result = await aiBackfillStructuredContent(store.db, {\n\t\t\t\tlimit,\n\t\t\t\tkinds,\n\t\t\t\toverwrite: opts.overwrite === true,\n\t\t\t\tdryRun: opts.dryRun === true,\n\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst action = opts.dryRun ? \"Would update\" : \"Updated\";\n\t\t\tp.intro(\"codemem db ai-backfill-structured\");\n\t\t\tp.log.success(\n\t\t\t\t`${action} ${result.updated} memories (skipped ${result.skipped}, failed ${result.failed})`,\n\t\t\t);\n\t\t\tp.outro(`Checked ${result.checked} memories`);\n\t\t} catch (error) {\n\t\t\tp.log.error(error instanceof Error ? error.message : String(error));\n\t\t\tprocess.exitCode = 1;\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\ndbCommand.addCommand(aiBackfillStructuredCmd);\n","import * as p from \"@clack/prompts\";\nimport { backfillVectors, MemoryStore, resolveDbPath, resolveProject } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddDbOption,\n\taddJsonOption,\n\ttype DbOpts,\n\ttype JsonOpts,\n\tresolveDbOpt,\n} from \"../shared-options.js\";\n\nfunction parseOptionalPositiveInt(value: string | undefined): number | undefined {\n\tif (!value) return undefined;\n\tconst parsed = Number.parseInt(value, 10);\n\tif (!Number.isFinite(parsed) || parsed <= 0) {\n\t\tthrow new Error(`invalid positive integer: ${value}`);\n\t}\n\treturn parsed;\n}\n\nexport function resolveEmbedProjectScope(\n\tcwd: string,\n\tprojectOpt: string | undefined,\n\tallProjects: boolean | undefined,\n): string | null {\n\tif (allProjects === true) return null;\n\tconst explicit = projectOpt?.trim();\n\tif (explicit) return explicit;\n\tconst envProject = process.env.CODEMEM_PROJECT?.trim();\n\tif (envProject) return envProject;\n\treturn resolveProject(cwd, null);\n}\n\nconst embedCmd = new Command(\"embed\")\n\t.configureHelp(helpStyle)\n\t.description(\"Backfill semantic embeddings\")\n\t.option(\"--limit <n>\", \"max memories to check\")\n\t.option(\"--since <iso>\", \"only memories created at/after this ISO timestamp\")\n\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t.option(\"--all-projects\", \"embed across all projects\")\n\t.option(\"--inactive\", \"include inactive memories\")\n\t.option(\"--dry-run\", \"preview work without writing vectors\");\n\naddDbOption(embedCmd);\naddJsonOption(embedCmd);\n\nexport const embedCommand = embedCmd.action(\n\tasync (\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\tlimit?: string;\n\t\t\t\tsince?: string;\n\t\t\t\tproject?: string;\n\t\t\t\tallProjects?: boolean;\n\t\t\t\tinactive?: boolean;\n\t\t\t\tdryRun?: boolean;\n\t\t\t},\n\t) => {\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tconst limit = parseOptionalPositiveInt(opts.limit);\n\t\t\tconst project = resolveEmbedProjectScope(process.cwd(), opts.project, opts.allProjects);\n\n\t\t\tconst result = await backfillVectors(store.db, {\n\t\t\t\tlimit,\n\t\t\t\tsince: opts.since ?? null,\n\t\t\t\tproject,\n\t\t\t\tactiveOnly: !opts.inactive,\n\t\t\t\tdryRun: opts.dryRun === true,\n\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst action = opts.dryRun ? \"Would embed\" : \"Embedded\";\n\t\t\tp.intro(\"codemem embed\");\n\t\t\tp.log.success(\n\t\t\t\t`${action} ${result.embedded} vectors (${result.inserted} inserted, ${result.skipped} skipped)`,\n\t\t\t);\n\t\t\tp.outro(`Checked ${result.checked} memories`);\n\t\t} catch (error) {\n\t\t\tp.log.error(error instanceof Error ? error.message : String(error));\n\t\t\tprocess.exitCode = 1;\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\n","import { MemoryStore, resolveDbPath, stripPrivateObj } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport { addDbOption, type DbOpts, resolveDbOpt } from \"../shared-options.js\";\n\nconst SESSION_ID_KEYS = [\n\t\"session_stream_id\",\n\t\"session_id\",\n\t\"stream_id\",\n\t\"opencode_session_id\",\n] as const;\n\nfunction resolveSessionStreamId(payload: Record<string, unknown>): string | null {\n\tconst values = new Map<string, string>();\n\tfor (const key of SESSION_ID_KEYS) {\n\t\tconst value = payload[key];\n\t\tif (typeof value !== \"string\") continue;\n\t\tconst text = value.trim();\n\t\tif (text) values.set(key, text);\n\t}\n\tif (values.size === 0) return null;\n\tconst unique = new Set(values.values());\n\tif (unique.size > 1) return null;\n\tfor (const key of SESSION_ID_KEYS) {\n\t\tconst value = values.get(key);\n\t\tif (value) return value;\n\t}\n\treturn null;\n}\n\nasync function readStdinJson(): Promise<Record<string, unknown>> {\n\tconst chunks: Buffer[] = [];\n\tfor await (const chunk of process.stdin) {\n\t\tchunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));\n\t}\n\tconst raw = Buffer.concat(chunks).toString(\"utf-8\").trim();\n\tif (!raw) throw new Error(\"stdin JSON required\");\n\tconst parsed = JSON.parse(raw) as unknown;\n\tif (parsed == null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(\"payload must be an object\");\n\t}\n\treturn parsed as Record<string, unknown>;\n}\n\nfunction emitStructuredError(errorCode: string, message: string): void {\n\tconsole.log(JSON.stringify({ error: errorCode, message }));\n\tprocess.exitCode = 1;\n}\n\nconst enqueueCmd = new Command(\"enqueue-raw-event\")\n\t.configureHelp(helpStyle)\n\t.description(\"Enqueue one raw event from stdin into the durable queue\");\n\naddDbOption(enqueueCmd);\n\nexport const enqueueRawEventCommand = enqueueCmd.action(async (opts: DbOpts) => {\n\ttry {\n\t\tconst payload = await readStdinJson();\n\t\tconst sessionId = resolveSessionStreamId(payload);\n\t\tif (!sessionId) {\n\t\t\temitStructuredError(\"validation_error\", \"session id required\");\n\t\t\treturn;\n\t\t}\n\t\tif (sessionId.startsWith(\"msg_\")) {\n\t\t\temitStructuredError(\"validation_error\", \"invalid session id\");\n\t\t\treturn;\n\t\t}\n\n\t\tconst eventType = typeof payload.event_type === \"string\" ? payload.event_type.trim() : \"\";\n\t\tif (!eventType) {\n\t\t\temitStructuredError(\"validation_error\", \"event_type required\");\n\t\t\treturn;\n\t\t}\n\n\t\tconst cwd = typeof payload.cwd === \"string\" ? payload.cwd : null;\n\t\tconst project = typeof payload.project === \"string\" ? payload.project : null;\n\t\tconst startedAt = typeof payload.started_at === \"string\" ? payload.started_at : null;\n\t\tconst tsWallMs = Number.isFinite(Number(payload.ts_wall_ms))\n\t\t\t? Math.floor(Number(payload.ts_wall_ms))\n\t\t\t: null;\n\t\tconst tsMonoMs = Number.isFinite(Number(payload.ts_mono_ms))\n\t\t\t? Number(payload.ts_mono_ms)\n\t\t\t: null;\n\t\tconst eventId = typeof payload.event_id === \"string\" ? payload.event_id.trim() : \"\";\n\t\tconst eventPayload =\n\t\t\tpayload.payload && typeof payload.payload === \"object\" && !Array.isArray(payload.payload)\n\t\t\t\t? (stripPrivateObj(payload.payload) as Record<string, unknown>)\n\t\t\t\t: {};\n\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tstore.updateRawEventSessionMeta({\n\t\t\t\topencodeSessionId: sessionId,\n\t\t\t\tsource: \"opencode\",\n\t\t\t\tcwd,\n\t\t\t\tproject,\n\t\t\t\tstartedAt,\n\t\t\t\tlastSeenTsWallMs: tsWallMs,\n\t\t\t});\n\t\t\tstore.recordRawEventsBatch(sessionId, [\n\t\t\t\t{\n\t\t\t\t\tevent_id: eventId,\n\t\t\t\t\tevent_type: eventType,\n\t\t\t\t\tpayload: eventPayload,\n\t\t\t\t\tts_wall_ms: tsWallMs,\n\t\t\t\t\tts_mono_ms: tsMonoMs,\n\t\t\t\t},\n\t\t\t]);\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t} catch (err) {\n\t\temitStructuredError(\"enqueue_error\", err instanceof Error ? err.message : String(err));\n\t}\n});\n","import { writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { exportMemories, resolveDbPath } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport { addDbOption, type DbOpts, resolveDbOpt } from \"../shared-options.js\";\n\nfunction expandUserPath(value: string): string {\n\treturn value.startsWith(\"~/\") ? join(homedir(), value.slice(2)) : value;\n}\n\nconst cmd = new Command(\"export-memories\")\n\t.configureHelp(helpStyle)\n\t.description(\"Export memories to a JSON file for sharing or backup\")\n\t.argument(\"<output>\", \"output file path (use '-' for stdout)\")\n\t.option(\"--project <project>\", \"filter by project (defaults to git repo root)\")\n\t.option(\"--all-projects\", \"export all projects\")\n\t.option(\"--include-inactive\", \"include deactivated memories\")\n\t.option(\"--since <iso>\", \"only export memories created after this ISO timestamp\");\n\naddDbOption(cmd);\n\ncmd.action(\n\t(\n\t\toutput: string,\n\t\topts: DbOpts & {\n\t\t\tproject?: string;\n\t\t\tallProjects?: boolean;\n\t\t\tincludeInactive?: boolean;\n\t\t\tsince?: string;\n\t\t},\n\t) => {\n\t\tconst payload = exportMemories({\n\t\t\tdbPath: resolveDbPath(resolveDbOpt(opts)),\n\t\t\tproject: opts.project,\n\t\t\tallProjects: opts.allProjects,\n\t\t\tincludeInactive: opts.includeInactive,\n\t\t\tsince: opts.since,\n\t\t});\n\t\tconst text = `${JSON.stringify(payload, null, 2)}\\n`;\n\t\tif (output === \"-\") {\n\t\t\tprocess.stdout.write(text);\n\t\t\treturn;\n\t\t}\n\t\tconst outputPath = expandUserPath(output);\n\t\twriteFileSync(outputPath, text, \"utf8\");\n\t\tp.intro(\"codemem export-memories\");\n\t\tp.log.success(\n\t\t\t[\n\t\t\t\t`Output: ${outputPath}`,\n\t\t\t\t`Sessions: ${payload.sessions.length.toLocaleString()}`,\n\t\t\t\t`Memories: ${payload.memory_items.length.toLocaleString()}`,\n\t\t\t\t`Summaries: ${payload.session_summaries.length.toLocaleString()}`,\n\t\t\t\t`Prompts: ${payload.user_prompts.length.toLocaleString()}`,\n\t\t\t].join(\"\\n\"),\n\t\t);\n\t\tp.outro(\"done\");\n\t},\n);\n\nexport const exportMemoriesCommand = cmd;\n","import * as p from \"@clack/prompts\";\nimport type { ExportPayload } from \"@codemem/core\";\nimport { importMemories, readImportPayload, resolveDbPath } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddDbOption,\n\taddJsonOption,\n\ttype DbOpts,\n\temitJsonError,\n\ttype JsonOpts,\n\tresolveDbOpt,\n} from \"../shared-options.js\";\n\nconst cmd = new Command(\"import-memories\")\n\t.configureHelp(helpStyle)\n\t.description(\"Import memories from an exported JSON file\")\n\t.argument(\"<inputFile>\", \"input JSON file (use '-' for stdin)\")\n\t.option(\"--remap-project <path>\", \"remap all projects to this path on import\")\n\t.option(\"--dry-run\", \"preview import without writing\");\n\naddDbOption(cmd);\naddJsonOption(cmd);\n\ncmd.action(\n\t(\n\t\tinputFile: string,\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\tremapProject?: string;\n\t\t\t\tdryRun?: boolean;\n\t\t\t},\n\t) => {\n\t\tlet payload: ExportPayload;\n\t\ttry {\n\t\t\tpayload = readImportPayload(inputFile);\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : \"Invalid import file\";\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\"invalid_input\", message);\n\t\t\t} else {\n\t\t\t\tp.log.error(message);\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (!opts.json) {\n\t\t\tp.intro(\"codemem import-memories\");\n\t\t\tp.log.info(\n\t\t\t\t[\n\t\t\t\t\t`Export version: ${payload.version}`,\n\t\t\t\t\t`Exported at: ${payload.exported_at}`,\n\t\t\t\t\t`Sessions: ${payload.sessions.length.toLocaleString()}`,\n\t\t\t\t\t`Memories: ${payload.memory_items.length.toLocaleString()}`,\n\t\t\t\t\t`Summaries: ${payload.session_summaries.length.toLocaleString()}`,\n\t\t\t\t\t`Prompts: ${payload.user_prompts.length.toLocaleString()}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t}\n\n\t\tconst result = importMemories(payload, {\n\t\t\tdbPath: resolveDbPath(resolveDbOpt(opts)),\n\t\t\tremapProject: opts.remapProject,\n\t\t\tdryRun: opts.dryRun,\n\t\t});\n\n\t\tif (opts.json) {\n\t\t\tconsole.log(\n\t\t\t\tJSON.stringify({\n\t\t\t\t\tsessions: result.sessions,\n\t\t\t\t\tmemory_items: result.memory_items,\n\t\t\t\t\tskipped: result.dryRun,\n\t\t\t\t}),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (result.dryRun) {\n\t\t\tp.outro(\"dry run complete\");\n\t\t\treturn;\n\t\t}\n\t\tp.log.success(\n\t\t\t[\n\t\t\t\t`Imported sessions: ${result.sessions.toLocaleString()}`,\n\t\t\t\t`Imported prompts: ${result.user_prompts.toLocaleString()}`,\n\t\t\t\t`Imported memories: ${result.memory_items.toLocaleString()}`,\n\t\t\t\t`Imported summaries: ${result.session_summaries.toLocaleString()}`,\n\t\t\t].join(\"\\n\"),\n\t\t);\n\t\tp.outro(\"done\");\n\t},\n);\n\nexport const importMemoriesCommand = cmd;\n","import { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport { addDbOption, type DbOpts, resolveDbOpt } from \"../shared-options.js\";\n\nconst mcpCmd = new Command(\"mcp\")\n\t.configureHelp(helpStyle)\n\t.description(\"Start the MCP stdio server\");\n\naddDbOption(mcpCmd);\n\nexport const mcpCommand = mcpCmd.action(async (opts: DbOpts) => {\n\tconst dbPath = resolveDbOpt(opts);\n\tif (dbPath) process.env.CODEMEM_DB = dbPath;\n\ttry {\n\t\tawait import(\"@codemem/mcp\");\n\t} catch (err) {\n\t\tconsole.error(\n\t\t\t`Failed to start MCP server: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t\tprocess.exitCode = 1;\n\t}\n});\n","import type { PackRenderOptions } from \"@codemem/core\";\nimport { resolveProject } from \"@codemem/core\";\nimport type { Command } from \"commander\";\n\nexport type PackFilters = { project?: string; working_set_paths?: string[] };\n\nexport type PackRequestOptions = {\n\tlimit: number;\n\tbudget: number | undefined;\n\tfilters: PackFilters;\n\trenderOptions?: PackRenderOptions;\n};\n\nexport class PackUsageError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"PackUsageError\";\n\t}\n}\n\nexport function collectWorkingSetFile(value: string, previous: string[]): string[] {\n\treturn [...previous, value];\n}\n\nexport function addPackRequestOptions(command: Command): Command {\n\treturn command\n\t\t.option(\"-n, --limit <n>\", \"max items\", \"10\")\n\t\t.option(\"--budget <tokens>\", \"token budget\")\n\t\t.option(\"--token-budget <tokens>\", \"token budget\")\n\t\t.option(\n\t\t\t\"--working-set-file <path>\",\n\t\t\t\"recently modified file path used as ranking hint\",\n\t\t\tcollectWorkingSetFile,\n\t\t\t[],\n\t\t)\n\t\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t\t.option(\"--all-projects\", \"search across all projects\")\n\t\t.option(\"--compact\", \"render a scannable index with full detail only for top N items\")\n\t\t.option(\"--compact-detail <n>\", \"items to show in full detail in compact mode (default 3)\");\n}\n\nexport function buildPackRequestOptions(\n\topts: {\n\t\tlimit?: string;\n\t\tbudget?: string;\n\t\ttokenBudget?: string;\n\t\tworkingSetFile?: string[];\n\t\tproject?: string;\n\t\tallProjects?: boolean;\n\t\tcompact?: boolean;\n\t\tcompactDetail?: string;\n\t},\n\tctx: {\n\t\tcwd?: string;\n\t\tenvProject?: string | null;\n\t\tresolveProjectFn?: typeof resolveProject;\n\t} = {},\n): PackRequestOptions {\n\tconst limit = parsePositiveInt(opts.limit ?? \"10\", \"limit\");\n\tconst budgetRaw = opts.tokenBudget ?? opts.budget;\n\tconst budget = budgetRaw ? parseNonNegativeInt(budgetRaw, \"token budget\") : undefined;\n\tconst filters: PackFilters = {};\n\n\tif (!opts.allProjects) {\n\t\tconst defaultProject = ctx.envProject?.trim() || null;\n\t\tconst resolveProjectFn = ctx.resolveProjectFn ?? resolveProject;\n\t\tconst cwd = ctx.cwd ?? process.cwd();\n\t\tconst project = defaultProject || resolveProjectFn(cwd, opts.project ?? null);\n\t\tif (project) {\n\t\t\tfilters.project = project;\n\t\t}\n\t}\n\n\tif ((opts.workingSetFile?.length ?? 0) > 0) {\n\t\tfilters.working_set_paths = opts.workingSetFile;\n\t}\n\n\tlet renderOptions: PackRenderOptions | undefined;\n\tif (opts.compact || opts.compactDetail != null) {\n\t\trenderOptions = { compact: true };\n\t\tif (opts.compactDetail != null) {\n\t\t\trenderOptions.compactDetailCount = parseNonNegativeInt(\n\t\t\t\topts.compactDetail,\n\t\t\t\t\"compact detail count\",\n\t\t\t);\n\t\t}\n\t}\n\n\treturn { limit, budget, filters, renderOptions };\n}\n\nfunction parsePositiveInt(value: string, label: string): number {\n\tif (!/^\\d+$/.test(value.trim())) {\n\t\tthrow new PackUsageError(`${label} must be a positive integer`);\n\t}\n\tconst parsed = Number.parseInt(value, 10);\n\tif (!Number.isFinite(parsed) || parsed < 1) {\n\t\tthrow new PackUsageError(`${label} must be a positive integer`);\n\t}\n\treturn parsed;\n}\n\nfunction parseNonNegativeInt(value: string, label: string): number {\n\tif (!/^\\d+$/.test(value.trim())) {\n\t\tthrow new PackUsageError(`${label} must be a non-negative integer`);\n\t}\n\tconst parsed = Number.parseInt(value, 10);\n\tif (!Number.isFinite(parsed) || parsed < 0) {\n\t\tthrow new PackUsageError(`${label} must be a non-negative integer`);\n\t}\n\treturn parsed;\n}\n","/**\n * Memory management CLI commands — show, forget, remember, inject.\n *\n * Ports codemem/commands/memory_cmds.py (show_cmd, forget_cmd, remember_cmd).\n * Inject is deprecated in favor of `codemem pack`.\n */\n\nimport * as p from \"@clack/prompts\";\nimport {\n\tcompareMemoryRoleReports,\n\tgetExtractionBenchmarkProfile,\n\tgetInjectionEvalScenarioPack,\n\tgetInjectionEvalScenarioPrompts,\n\tgetMemoryRoleReport,\n\tgetRawEventRelinkPlan,\n\tgetRawEventRelinkReport,\n\tgetSessionExtractionEval,\n\tgetSessionExtractionEvalScenario,\n\tloadObserverConfig,\n\tMemoryStore,\n\tObserverClient,\n\treplayBatchExtraction,\n\treplayBatchExtractionWithTierRouting,\n\tresolveDbPath,\n\tresolveProject,\n} from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddDbOption,\n\taddJsonOption,\n\ttype DbOpts,\n\temitDeprecationWarning,\n\temitJsonError,\n\ttype JsonOpts,\n\tresolveDbOpt,\n} from \"../shared-options.js\";\nimport { buildPackRequestOptions, collectWorkingSetFile } from \"./pack-shared.js\";\n\n/** Parse a strict positive integer, rejecting prefixes like \"12abc\". */\nfunction parseStrictPositiveId(value: string): number | null {\n\tif (!/^\\d+$/.test(value.trim())) return null;\n\tconst n = Number(value.trim());\n\treturn Number.isFinite(n) && n >= 1 && Number.isInteger(n) ? n : null;\n}\n\nfunction showMemoryAction(idStr: string, opts: DbOpts & JsonOpts): void {\n\tconst memoryId = parseStrictPositiveId(idStr);\n\tif (memoryId === null) {\n\t\tif (opts.json) {\n\t\t\temitJsonError(\"invalid_id\", `Invalid memory ID: ${idStr}`);\n\t\t} else {\n\t\t\tp.log.error(`Invalid memory ID: ${idStr}`);\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t\treturn;\n\t}\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\ttry {\n\t\tconst item = store.get(memoryId);\n\t\tif (!item) {\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\"not_found\", `Memory ${memoryId} not found`);\n\t\t\t} else {\n\t\t\t\tp.log.error(`Memory ${memoryId} not found`);\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify(item, null, 2));\n\t\t} else {\n\t\t\t// Human-readable format\n\t\t\tconsole.log(`#${item.id} [${item.kind}] ${item.title}`);\n\t\t\tif (item.subtitle) console.log(` ${item.subtitle}`);\n\t\t\tconsole.log(` created: ${item.created_at} confidence: ${item.confidence}`);\n\t\t\tif (item.tags_text) console.log(` tags: ${item.tags_text}`);\n\t\t\tif (item.body_text) {\n\t\t\t\tconst preview =\n\t\t\t\t\titem.body_text.length > 300 ? `${item.body_text.slice(0, 300)}…` : item.body_text;\n\t\t\t\tconsole.log(`\\n${preview}`);\n\t\t\t}\n\t\t}\n\t} finally {\n\t\tstore.close();\n\t}\n}\n\nfunction forgetMemoryAction(idStr: string, opts: DbOpts & JsonOpts): void {\n\tconst memoryId = parseStrictPositiveId(idStr);\n\tif (memoryId === null) {\n\t\tif (opts.json) {\n\t\t\temitJsonError(\"invalid_id\", `Invalid memory ID: ${idStr}`);\n\t\t} else {\n\t\t\tp.log.error(`Invalid memory ID: ${idStr}`);\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t\treturn;\n\t}\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\ttry {\n\t\tstore.forget(memoryId);\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify({ id: memoryId, status: \"forgotten\" }));\n\t\t} else {\n\t\t\tp.log.success(`Memory ${memoryId} marked inactive`);\n\t\t}\n\t} finally {\n\t\tstore.close();\n\t}\n}\n\ninterface RememberMemoryOptions extends DbOpts, JsonOpts {\n\tkind: string;\n\ttitle: string;\n\tbody: string;\n\ttags?: string[];\n\tproject?: string;\n}\n\nasync function rememberMemoryAction(opts: RememberMemoryOptions): Promise<void> {\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\tlet sessionId: number | null = null;\n\ttry {\n\t\tconst project = resolveProject(process.cwd(), opts.project ?? null);\n\t\tsessionId = store.startSession({\n\t\t\tcwd: process.cwd(),\n\t\t\tproject,\n\t\t\tuser: process.env.USER ?? \"unknown\",\n\t\t\ttoolVersion: \"manual\",\n\t\t\tmetadata: { manual: true },\n\t\t});\n\t\tconst memId = store.remember(sessionId, opts.kind, opts.title, opts.body, 0.5, opts.tags);\n\t\tawait store.flushPendingVectorWrites();\n\t\tstore.endSession(sessionId, { manual: true });\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify({ id: memId }));\n\t\t} else {\n\t\t\tp.log.success(`Stored memory ${memId}`);\n\t\t}\n\t} catch (err) {\n\t\tif (sessionId !== null) {\n\t\t\ttry {\n\t\t\t\tstore.endSession(sessionId, { manual: true, error: true });\n\t\t\t} catch {\n\t\t\t\t// ignore — already in error path\n\t\t\t}\n\t\t}\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tif (opts.json) {\n\t\t\temitJsonError(\"remember_failed\", message);\n\t\t} else {\n\t\t\tp.log.error(`Failed to store memory: ${message}`);\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t} finally {\n\t\tstore.close();\n\t}\n}\n\nfunction createShowMemoryCommand(): Command {\n\tconst cmd = new Command(\"show\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Show a memory item\")\n\t\t.argument(\"<id>\", \"memory ID\");\n\taddDbOption(cmd);\n\taddJsonOption(cmd);\n\tcmd.action(showMemoryAction);\n\treturn cmd;\n}\n\nfunction createForgetMemoryCommand(): Command {\n\tconst cmd = new Command(\"forget\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Deactivate a memory item\")\n\t\t.argument(\"<id>\", \"memory ID\");\n\taddDbOption(cmd);\n\taddJsonOption(cmd);\n\tcmd.action(forgetMemoryAction);\n\treturn cmd;\n}\n\nfunction createRememberMemoryCommand(): Command {\n\tconst cmd = new Command(\"remember\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Manually add a memory item\")\n\t\t.requiredOption(\"-k, --kind <kind>\", \"memory kind (discovery, decision, feature, bugfix, etc.)\")\n\t\t.requiredOption(\"-t, --title <title>\", \"memory title\")\n\t\t.requiredOption(\"-b, --body <body>\", \"memory body text\")\n\t\t.option(\"--tags <tags...>\", \"tags (space-separated)\")\n\t\t.option(\"--project <project>\", \"project name (defaults to git repo root)\");\n\taddDbOption(cmd);\n\taddJsonOption(cmd);\n\tcmd.action(rememberMemoryAction);\n\treturn cmd;\n}\n\nfunction createInjectMemoryCommand(): Command {\n\tconst cmd = new Command(\"inject\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Build raw memory context text for manual prompt injection\")\n\t\t.argument(\"<context>\", \"context string to search for\")\n\t\t.option(\"-n, --limit <n>\", \"max items\", \"10\")\n\t\t.option(\"--budget <tokens>\", \"token budget\")\n\t\t.option(\"--token-budget <tokens>\", \"token budget\")\n\t\t.option(\n\t\t\t\"--working-set-file <path>\",\n\t\t\t\"recently modified file path used as ranking hint\",\n\t\t\tcollectWorkingSetFile,\n\t\t\t[],\n\t\t)\n\t\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t\t.option(\"--all-projects\", \"search across all projects\")\n\t\t.allowUnknownOption(true)\n\t\t.allowExcessArguments(true);\n\taddDbOption(cmd);\n\tcmd.action(\n\t\tasync (\n\t\t\tcontext: string,\n\t\t\topts: DbOpts & {\n\t\t\t\tlimit?: string;\n\t\t\t\tbudget?: string;\n\t\t\t\ttokenBudget?: string;\n\t\t\t\tworkingSetFile?: string[];\n\t\t\t\tproject?: string;\n\t\t\t\tallProjects?: boolean;\n\t\t\t},\n\t\t) => {\n\t\t\temitDeprecationWarning(\"codemem memory inject\", \"codemem pack\");\n\t\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\t\ttry {\n\t\t\t\tconst { limit, budget, filters } = buildPackRequestOptions(opts, {\n\t\t\t\t\tenvProject: process.env.CODEMEM_PROJECT,\n\t\t\t\t});\n\t\t\t\tconst pack = await store.buildMemoryPackAsync(context, limit, budget, filters);\n\t\t\t\tconsole.log(pack.pack_text ?? \"\");\n\t\t\t} finally {\n\t\t\t\tstore.close();\n\t\t\t}\n\t\t},\n\t);\n\treturn cmd;\n}\n\nfunction createMemoryRoleReportCommand(): Command {\n\tconst cmd = new Command(\"role-report\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Analyze inferred memory roles in a DB snapshot\")\n\t\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t\t.option(\"--all-projects\", \"analyze across all projects\")\n\t\t.option(\n\t\t\t\"--probe <query>\",\n\t\t\t\"run a retrieval probe query against the snapshot\",\n\t\t\t(value, prev: string[]) => [...prev, value],\n\t\t\t[],\n\t\t)\n\t\t.option(\n\t\t\t\"--scenario <id>\",\n\t\t\t\"run a named injection-first eval scenario pack (can be repeated)\",\n\t\t\t(value, prev: string[]) => [...prev, value],\n\t\t\t[],\n\t\t)\n\t\t.option(\"--inactive\", \"include inactive memories\");\n\taddDbOption(cmd);\n\taddJsonOption(cmd);\n\tcmd.action(\n\t\t(\n\t\t\topts: DbOpts &\n\t\t\t\tJsonOpts & {\n\t\t\t\t\tproject?: string;\n\t\t\t\t\tallProjects?: boolean;\n\t\t\t\t\tprobe?: string[];\n\t\t\t\t\tscenario?: string[];\n\t\t\t\t\tinactive?: boolean;\n\t\t\t\t},\n\t\t) => {\n\t\t\tconst project =\n\t\t\t\topts.allProjects === true\n\t\t\t\t\t? null\n\t\t\t\t\t: opts.project?.trim() ||\n\t\t\t\t\t\tprocess.env.CODEMEM_PROJECT?.trim() ||\n\t\t\t\t\t\tresolveProject(process.cwd(), null);\n\t\t\tconst invalidScenario = (opts.scenario ?? []).find(\n\t\t\t\t(id) => getInjectionEvalScenarioPack(id) == null,\n\t\t\t);\n\t\t\tif (invalidScenario) {\n\t\t\t\tthrow new Error(`Unknown eval scenario pack: ${invalidScenario}`);\n\t\t\t}\n\t\t\tconst probes = [\n\t\t\t\t...(opts.probe ?? []),\n\t\t\t\t...getInjectionEvalScenarioPrompts(opts.scenario ?? []),\n\t\t\t];\n\t\t\tconst result = getMemoryRoleReport(resolveDbOpt(opts), {\n\t\t\t\tproject,\n\t\t\t\tallProjects: opts.allProjects === true,\n\t\t\t\tincludeInactive: opts.inactive === true,\n\t\t\t\tprobes,\n\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tp.intro(\"codemem memory role-report\");\n\t\t\tp.log.info(\n\t\t\t\t[\n\t\t\t\t\t`Memories: ${result.totals.memories}`,\n\t\t\t\t\t`Active: ${result.totals.active}`,\n\t\t\t\t\t`Sessions: ${result.totals.sessions}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t\tp.log.info(\"Counts by role:\");\n\t\t\tfor (const [role, count] of Object.entries(result.counts_by_role)) {\n\t\t\t\tp.log.message(` ${role.padEnd(10)} ${String(count)}`);\n\t\t\t}\n\t\t\tp.log.info(\"Counts by mapping:\");\n\t\t\tp.log.message(` mapped ${result.counts_by_mapping.mapped}`);\n\t\t\tp.log.message(` unmapped ${result.counts_by_mapping.unmapped}`);\n\t\t\tp.log.info(\"Summary lineages:\");\n\t\t\tp.log.message(` session_summary ${result.summary_lineages.session_summary}`);\n\t\t\tp.log.message(` legacy_metadata_summary ${result.summary_lineages.legacy_metadata_summary}`);\n\t\t\tp.log.message(` summary_mapped ${result.summary_mapping.mapped}`);\n\t\t\tp.log.message(` summary_unmapped ${result.summary_mapping.unmapped}`);\n\t\t\tp.log.info(\"Project quality:\");\n\t\t\tfor (const [bucket, count] of Object.entries(result.project_quality)) {\n\t\t\t\tp.log.message(` ${bucket.padEnd(12)} ${String(count)}`);\n\t\t\t}\n\t\t\tp.log.info(\"Session classes:\");\n\t\t\tfor (const [bucket, count] of Object.entries(result.session_class_buckets)) {\n\t\t\t\tp.log.message(` ${bucket.padEnd(20)} ${String(count)}`);\n\t\t\t}\n\t\t\tp.log.info(\"Summary dispositions:\");\n\t\t\tfor (const [bucket, count] of Object.entries(result.summary_disposition_buckets)) {\n\t\t\t\tp.log.message(` ${bucket.padEnd(20)} ${String(count)}`);\n\t\t\t}\n\t\t\tif (result.probe_results.length > 0) {\n\t\t\t\tp.log.info(\"Probe results:\");\n\t\t\t\tfor (const probe of result.probe_results) {\n\t\t\t\t\tp.log.message(` query: ${probe.query}`);\n\t\t\t\t\tif (probe.scenario_id) {\n\t\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t\t` scenario: ${probe.scenario_id} (${probe.scenario_category ?? \"unknown\"})${probe.scenario_title ? ` — ${probe.scenario_title}` : \"\"}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tp.log.message(` mode: ${probe.mode}`);\n\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t` top roles: durable=${probe.top_role_counts.durable} recap=${probe.top_role_counts.recap} ephemeral=${probe.top_role_counts.ephemeral} general=${probe.top_role_counts.general}`,\n\t\t\t\t\t);\n\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t` top mapping: mapped=${probe.top_mapping_counts.mapped} unmapped=${probe.top_mapping_counts.unmapped}`,\n\t\t\t\t\t);\n\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t` burden: recap_share=${probe.top_burden.recap_share.toFixed(2)} unmapped_share=${probe.top_burden.unmapped_share.toFixed(2)} recap_unmapped_share=${probe.top_burden.recap_unmapped_share.toFixed(2)}`,\n\t\t\t\t\t);\n\t\t\t\t\tif (probe.simulated_demoted_unmapped_recap) {\n\t\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t\t` simulated demote-unmapped-recap burden: recap_share=${probe.simulated_demoted_unmapped_recap.top_burden.recap_share.toFixed(2)} unmapped_share=${probe.simulated_demoted_unmapped_recap.top_burden.unmapped_share.toFixed(2)} recap_unmapped_share=${probe.simulated_demoted_unmapped_recap.top_burden.recap_unmapped_share.toFixed(2)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (probe.simulated_demoted_unmapped_recap_and_ephemeral) {\n\t\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t\t` simulated demote-unmapped-recap+ephemeral burden: recap_share=${probe.simulated_demoted_unmapped_recap_and_ephemeral.top_burden.recap_share.toFixed(2)} unmapped_share=${probe.simulated_demoted_unmapped_recap_and_ephemeral.top_burden.unmapped_share.toFixed(2)} recap_unmapped_share=${probe.simulated_demoted_unmapped_recap_and_ephemeral.top_burden.recap_unmapped_share.toFixed(2)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (probe.scenario_score) {\n\t\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t\t` scenario score: mode_match=${probe.scenario_score.mode_match ? \"yes\" : \"no\"} top1_primary=${probe.scenario_score.primary_in_top1 ? \"yes\" : \"no\"} top3_primary=${probe.scenario_score.primary_in_top3_count} top1_anti=${probe.scenario_score.anti_signal_in_top1 ? \"yes\" : \"no\"} primary=${probe.scenario_score.primary_match_count} anti=${probe.scenario_score.anti_signal_count} recap=${probe.scenario_score.recap_count} unmapped_recap=${probe.scenario_score.unmapped_recap_count} chatter=${probe.scenario_score.administrative_chatter_count} net=${probe.scenario_score.score}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tfor (const item of probe.items.slice(0, 5)) {\n\t\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t\t` [${item.id}] (${item.kind}/${item.role}/${item.mapping}/${item.session_class}/${item.summary_disposition}) ${item.title} — ${item.role_reason}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tp.outro(\"done\");\n\t\t},\n\t);\n\treturn cmd;\n}\n\nfunction createMemoryRoleCompareCommand(): Command {\n\tconst cmd = new Command(\"role-compare\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Compare inferred memory-role and probe metrics across two DB snapshots\")\n\t\t.argument(\"<baseline_db>\", \"baseline sqlite database path\")\n\t\t.argument(\"<candidate_db>\", \"candidate sqlite database path\")\n\t\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t\t.option(\"--all-projects\", \"analyze across all projects\")\n\t\t.option(\n\t\t\t\"--probe <query>\",\n\t\t\t\"run a retrieval probe query against both snapshots\",\n\t\t\t(value, prev: string[]) => [...prev, value],\n\t\t\t[],\n\t\t)\n\t\t.option(\n\t\t\t\"--scenario <id>\",\n\t\t\t\"run a named injection-first eval scenario pack (can be repeated)\",\n\t\t\t(value, prev: string[]) => [...prev, value],\n\t\t\t[],\n\t\t)\n\t\t.option(\"--inactive\", \"include inactive memories\");\n\taddJsonOption(cmd);\n\tcmd.action(\n\t\t(\n\t\t\tbaselineDb: string,\n\t\t\tcandidateDb: string,\n\t\t\topts: JsonOpts & {\n\t\t\t\tproject?: string;\n\t\t\t\tallProjects?: boolean;\n\t\t\t\tprobe?: string[];\n\t\t\t\tscenario?: string[];\n\t\t\t\tinactive?: boolean;\n\t\t\t},\n\t\t) => {\n\t\t\tconst project =\n\t\t\t\topts.allProjects === true\n\t\t\t\t\t? null\n\t\t\t\t\t: opts.project?.trim() ||\n\t\t\t\t\t\tprocess.env.CODEMEM_PROJECT?.trim() ||\n\t\t\t\t\t\tresolveProject(process.cwd(), null);\n\t\t\tconst invalidScenario = (opts.scenario ?? []).find(\n\t\t\t\t(id) => getInjectionEvalScenarioPack(id) == null,\n\t\t\t);\n\t\t\tif (invalidScenario) {\n\t\t\t\tthrow new Error(`Unknown eval scenario pack: ${invalidScenario}`);\n\t\t\t}\n\t\t\tconst probes = [\n\t\t\t\t...(opts.probe ?? []),\n\t\t\t\t...getInjectionEvalScenarioPrompts(opts.scenario ?? []),\n\t\t\t];\n\t\t\tconst result = compareMemoryRoleReports(baselineDb, candidateDb, {\n\t\t\t\tproject,\n\t\t\t\tallProjects: opts.allProjects === true,\n\t\t\t\tincludeInactive: opts.inactive === true,\n\t\t\t\tprobes,\n\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tp.intro(\"codemem memory role-compare\");\n\t\t\tp.log.info(\n\t\t\t\t[\n\t\t\t\t\t`Baseline sessions: ${result.baseline.totals.sessions}`,\n\t\t\t\t\t`Candidate sessions: ${result.candidate.totals.sessions}`,\n\t\t\t\t\t`Delta sessions: ${result.delta.totals.sessions}`,\n\t\t\t\t\t`Mapped delta: ${result.delta.counts_by_mapping.mapped}`,\n\t\t\t\t\t`Unmapped delta: ${result.delta.counts_by_mapping.unmapped}`,\n\t\t\t\t\t`Summary mapped delta: ${result.delta.summary_mapping.mapped}`,\n\t\t\t\t\t`Summary unmapped delta: ${result.delta.summary_mapping.unmapped}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t\tp.log.info(\"Role deltas:\");\n\t\t\tfor (const [role, count] of Object.entries(result.delta.counts_by_role)) {\n\t\t\t\tp.log.message(` ${role.padEnd(10)} ${String(count)}`);\n\t\t\t}\n\t\t\tp.log.info(\"Session class deltas:\");\n\t\t\tfor (const [bucket, count] of Object.entries(result.delta.session_class_buckets)) {\n\t\t\t\tp.log.message(` ${bucket.padEnd(20)} ${String(count)}`);\n\t\t\t}\n\t\t\tp.log.info(\"Summary disposition deltas:\");\n\t\t\tfor (const [bucket, count] of Object.entries(result.delta.summary_disposition_buckets)) {\n\t\t\t\tp.log.message(` ${bucket.padEnd(20)} ${String(count)}`);\n\t\t\t}\n\t\t\tif (result.probe_comparisons.length > 0) {\n\t\t\t\tp.log.info(\"Probe comparisons:\");\n\t\t\t\tfor (const probe of result.probe_comparisons) {\n\t\t\t\t\tp.log.message(` query: ${probe.query}`);\n\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t` modes: baseline=${probe.baseline_mode ?? \"-\"} candidate=${probe.candidate_mode ?? \"-\"}`,\n\t\t\t\t\t);\n\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t` overlap: shared_top_keys=${probe.shared_item_keys.length} baseline_top=${probe.baseline_item_ids.slice(0, 5).join(\",\") || \"-\"} candidate_top=${probe.candidate_item_ids.slice(0, 5).join(\",\") || \"-\"}`,\n\t\t\t\t\t);\n\t\t\t\t\tif (probe.delta_top_burden) {\n\t\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t\t` burden delta: recap_share=${probe.delta_top_burden.recap_share.toFixed(2)} unmapped_share=${probe.delta_top_burden.unmapped_share.toFixed(2)} recap_unmapped_share=${probe.delta_top_burden.recap_unmapped_share.toFixed(2)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (probe.delta_top_mapping_counts) {\n\t\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t\t` mapping delta: mapped=${probe.delta_top_mapping_counts.mapped} unmapped=${probe.delta_top_mapping_counts.unmapped}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (probe.baseline_scenario_score || probe.candidate_scenario_score) {\n\t\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t\t` scenario scores: baseline=${probe.baseline_scenario_score?.score ?? \"-\"} candidate=${probe.candidate_scenario_score?.score ?? \"-\"}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (probe.delta_scenario_score) {\n\t\t\t\t\t\tp.log.message(\n\t\t\t\t\t\t\t` scenario delta: mode_match=${probe.delta_scenario_score.mode_match ?? \"-\"} top1_primary=${probe.delta_scenario_score.primary_in_top1 ?? \"-\"} top3_primary=${probe.delta_scenario_score.primary_in_top3_count ?? \"-\"} top1_anti=${probe.delta_scenario_score.anti_signal_in_top1 ?? \"-\"} primary=${probe.delta_scenario_score.primary_match_count ?? \"-\"} anti=${probe.delta_scenario_score.anti_signal_count ?? \"-\"} recap=${probe.delta_scenario_score.recap_count ?? \"-\"} unmapped_recap=${probe.delta_scenario_score.unmapped_recap_count ?? \"-\"} chatter=${probe.delta_scenario_score.administrative_chatter_count ?? \"-\"} net=${probe.delta_scenario_score.score ?? \"-\"}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tp.outro(\"done\");\n\t\t},\n\t);\n\treturn cmd;\n}\n\nfunction createMemoryExtractionReportCommand(): Command {\n\tconst cmd = new Command(\"extraction-report\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Score extracted memories for a session against a built-in extraction eval rubric\")\n\t\t.option(\"--session-id <id>\", \"session ID to evaluate\")\n\t\t.option(\"--batch-id <id>\", \"raw-event flush batch ID to evaluate\")\n\t\t.requiredOption(\"--scenario <id>\", \"built-in extraction eval scenario ID\")\n\t\t.option(\"--inactive\", \"include inactive memories\");\n\taddDbOption(cmd);\n\taddJsonOption(cmd);\n\tcmd.action(\n\t\t(\n\t\t\topts: DbOpts &\n\t\t\t\tJsonOpts & {\n\t\t\t\t\tsessionId: string;\n\t\t\t\t\tbatchId?: string;\n\t\t\t\t\tscenario: string;\n\t\t\t\t\tinactive?: boolean;\n\t\t\t\t},\n\t\t) => {\n\t\t\tconst sessionIdInput = opts.sessionId?.trim() ?? \"\";\n\t\t\tconst batchIdInput = opts.batchId?.trim() ?? \"\";\n\t\t\tconst hasSessionId = sessionIdInput.length > 0;\n\t\t\tconst hasBatchId = batchIdInput.length > 0;\n\t\t\tif (hasSessionId === hasBatchId) {\n\t\t\t\tthrow new Error(\"Provide exactly one of --session-id or --batch-id\");\n\t\t\t}\n\t\t\tconst sessionId = hasSessionId ? parseStrictPositiveId(sessionIdInput) : null;\n\t\t\tif (hasSessionId && sessionId === null) {\n\t\t\t\tthrow new Error(`Invalid session ID: ${sessionIdInput || opts.sessionId}`);\n\t\t\t}\n\t\t\tconst batchId = hasBatchId ? parseStrictPositiveId(batchIdInput) : null;\n\t\t\tif (hasBatchId && batchId === null) {\n\t\t\t\tthrow new Error(`Invalid batch ID: ${batchIdInput || opts.batchId}`);\n\t\t\t}\n\t\t\tconst scenarioId = opts.scenario?.trim() ?? \"\";\n\t\t\tconst scenario = getSessionExtractionEvalScenario(scenarioId);\n\t\t\tif (!scenario) {\n\t\t\t\tthrow new Error(`Unknown extraction eval scenario: ${scenarioId || opts.scenario}`);\n\t\t\t}\n\t\t\tconst result =\n\t\t\t\tbatchId != null\n\t\t\t\t\t? getSessionExtractionEval(resolveDbOpt(opts), {\n\t\t\t\t\t\t\tbatchId,\n\t\t\t\t\t\t\tscenarioId: scenario.id,\n\t\t\t\t\t\t\tincludeInactive: opts.inactive === true,\n\t\t\t\t\t\t})\n\t\t\t\t\t: getSessionExtractionEval(resolveDbOpt(opts), {\n\t\t\t\t\t\t\tsessionId: sessionId as number,\n\t\t\t\t\t\t\tscenarioId: scenario.id,\n\t\t\t\t\t\t\tincludeInactive: opts.inactive === true,\n\t\t\t\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tp.intro(\"codemem memory extraction-report\");\n\t\t\tp.log.info(\n\t\t\t\t[\n\t\t\t\t\t`Scenario: ${result.scenario.id} — ${result.scenario.title}`,\n\t\t\t\t\t`Target: ${result.target.type}${result.target.batchId != null ? ` #${result.target.batchId}` : \"\"}`,\n\t\t\t\t\t`Session: ${result.session.id} (${result.session.project ?? \"no-project\"})`,\n\t\t\t\t\t`Session class: ${result.session.sessionClass}`,\n\t\t\t\t\t`Summary disposition: ${result.session.summaryDisposition}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t\tp.log.info(\n\t\t\t\t[\n\t\t\t\t\t`Pass: ${result.pass ? \"yes\" : \"no\"}`,\n\t\t\t\t\t`Summary count: ${result.counts.summaries}`,\n\t\t\t\t\t`Observation count: ${result.counts.observations}`,\n\t\t\t\t\t`Summary thread coverage: ${result.coverage.summaryThreadCoverage}`,\n\t\t\t\t\t`Observation thread coverage: ${result.coverage.observationThreadCoverage}`,\n\t\t\t\t\t`Total thread coverage: ${result.coverage.totalThreadCoverage}`,\n\t\t\t\t\t`Duplicate observation threads: ${result.coverage.duplicateObservationThreads}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t\tif (result.failureReasons.length > 0) {\n\t\t\t\tp.log.warn(\"Failure reasons:\");\n\t\t\t\tfor (const reason of result.failureReasons) {\n\t\t\t\t\tp.log.message(` - ${reason}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tp.log.info(\"Thread coverage:\");\n\t\t\tfor (const thread of result.threads) {\n\t\t\t\tp.log.message(\n\t\t\t\t\t` ${thread.id.padEnd(22)} summary=${thread.summaryMatch ? \"yes\" : \"no\"} observations=${thread.observationMatch ? \"yes\" : \"no\"}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tp.outro(\"done\");\n\t\t},\n\t);\n\treturn cmd;\n}\n\nfunction createMemoryExtractionReplayCommand(): Command {\n\tconst cmd = new Command(\"extraction-replay\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\n\t\t\t\"Re-run the observer on a historical flush batch without persisting, then score the fresh output\",\n\t\t)\n\t\t.requiredOption(\"--batch-id <id>\", \"raw-event flush batch ID to replay\")\n\t\t.option(\n\t\t\t\"--transcript-budget <chars>\",\n\t\t\t\"override replay transcript budget in characters (replay only)\",\n\t\t)\n\t\t.option(\"--observer-tier-routing\", \"use replay-only benchmark-backed observer tier routing\")\n\t\t.option(\"--observer-temperature <value>\", \"override observer temperature for replay only\")\n\t\t.option(\"--openai-responses\", \"use OpenAI Responses API for replay only\")\n\t\t.option(\n\t\t\t\"--reasoning-effort <level>\",\n\t\t\t\"set OpenAI reasoning.effort for replay only (responses path)\",\n\t\t)\n\t\t.option(\n\t\t\t\"--reasoning-summary <mode>\",\n\t\t\t\"set OpenAI reasoning.summary for replay only (responses path)\",\n\t\t)\n\t\t.option(\n\t\t\t\"--max-output-tokens <n>\",\n\t\t\t\"override OpenAI max_output_tokens for replay only (responses path)\",\n\t\t)\n\t\t.requiredOption(\"--scenario <id>\", \"built-in extraction eval scenario ID\");\n\taddDbOption(cmd);\n\taddJsonOption(cmd);\n\tcmd.action(\n\t\tasync (\n\t\t\topts: DbOpts &\n\t\t\t\tJsonOpts & {\n\t\t\t\t\tbatchId: string;\n\t\t\t\t\tobserverTierRouting?: boolean;\n\t\t\t\t\topenaiResponses?: boolean;\n\t\t\t\t\treasoningEffort?: string;\n\t\t\t\t\treasoningSummary?: string;\n\t\t\t\t\tmaxOutputTokens?: string;\n\t\t\t\t\tobserverTemperature?: string;\n\t\t\t\t\ttranscriptBudget?: string;\n\t\t\t\t\tscenario: string;\n\t\t\t\t},\n\t\t) => {\n\t\t\tconst batchIdInput = opts.batchId?.trim() ?? \"\";\n\t\t\tconst batchId = parseStrictPositiveId(batchIdInput);\n\t\t\tif (batchId === null) {\n\t\t\t\tthrow new Error(`Invalid batch ID: ${batchIdInput || opts.batchId}`);\n\t\t\t}\n\t\t\tconst scenarioId = opts.scenario?.trim() ?? \"\";\n\t\t\tconst scenario = getSessionExtractionEvalScenario(scenarioId);\n\t\t\tif (!scenario) {\n\t\t\t\tthrow new Error(`Unknown extraction eval scenario: ${scenarioId || opts.scenario}`);\n\t\t\t}\n\t\t\tconst transcriptBudgetInput = opts.transcriptBudget?.trim() ?? \"\";\n\t\t\tconst transcriptBudget =\n\t\t\t\ttranscriptBudgetInput.length > 0 ? parseStrictPositiveId(transcriptBudgetInput) : null;\n\t\t\tif (transcriptBudgetInput.length > 0 && transcriptBudget === null) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid transcript budget: ${transcriptBudgetInput || opts.transcriptBudget}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst observerTemperatureInput = opts.observerTemperature?.trim() ?? \"\";\n\t\t\tlet observerTemperature: number | undefined;\n\t\t\tif (observerTemperatureInput.length > 0) {\n\t\t\t\tconst parsed = Number(observerTemperatureInput);\n\t\t\t\tif (!Number.isFinite(parsed)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Invalid observer temperature: ${observerTemperatureInput || opts.observerTemperature}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tobserverTemperature = parsed;\n\t\t\t}\n\t\t\tconst maxOutputTokensInput = opts.maxOutputTokens?.trim() ?? \"\";\n\t\t\tconst maxOutputTokens =\n\t\t\t\tmaxOutputTokensInput.length > 0 ? parseStrictPositiveId(maxOutputTokensInput) : null;\n\t\t\tif (maxOutputTokensInput.length > 0 && maxOutputTokens === null) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid max output tokens: ${maxOutputTokensInput || opts.maxOutputTokens}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst observerConfig = loadObserverConfig();\n\t\t\tconst observerConfigWithOverrides = {\n\t\t\t\t...observerConfig,\n\t\t\t\tobserverTemperature: observerTemperature ?? observerConfig.observerTemperature,\n\t\t\t\tobserverOpenAIUseResponses: opts.openaiResponses === true,\n\t\t\t\tobserverReasoningEffort: opts.reasoningEffort?.trim() || null,\n\t\t\t\tobserverReasoningSummary: opts.reasoningSummary?.trim() || null,\n\t\t\t\tobserverMaxOutputTokens: maxOutputTokens ?? observerConfig.observerMaxTokens,\n\t\t\t};\n\t\t\tconst observer = new ObserverClient(observerConfigWithOverrides);\n\t\t\tconst result =\n\t\t\t\topts.observerTierRouting === true\n\t\t\t\t\t? await replayBatchExtractionWithTierRouting(\n\t\t\t\t\t\t\tresolveDbOpt(opts),\n\t\t\t\t\t\t\tobserverConfigWithOverrides,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbatchId,\n\t\t\t\t\t\t\t\tscenarioId: scenario.id,\n\t\t\t\t\t\t\t\ttranscriptBudget: transcriptBudget ?? undefined,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t)\n\t\t\t\t\t: await replayBatchExtraction(resolveDbOpt(opts), observer, {\n\t\t\t\t\t\t\tbatchId,\n\t\t\t\t\t\t\tscenarioId: scenario.id,\n\t\t\t\t\t\t\ttranscriptBudget: transcriptBudget ?? undefined,\n\t\t\t\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tp.intro(\"codemem memory extraction-replay\");\n\t\t\tp.log.info(\n\t\t\t\t[\n\t\t\t\t\t`Scenario: ${result.scenario.id} — ${result.scenario.title}`,\n\t\t\t\t\t`Batch: ${result.target.batchId}`,\n\t\t\t\t\t`Session: ${result.target.sessionId}`,\n\t\t\t\t\t`Observer: ${result.observer.provider}/${result.observer.model}`,\n\t\t\t\t\t`Tier: ${result.observer.tier ?? \"manual\"}`,\n\t\t\t\t\t`OpenAI Responses: ${result.observer.openaiUseResponses ? \"yes\" : \"no\"}`,\n\t\t\t\t\t`Reasoning effort: ${result.observer.reasoningEffort ?? \"none\"}`,\n\t\t\t\t\t`Classification: ${result.classification.status}`,\n\t\t\t\t\t`Pass: ${result.evaluation.pass ? \"yes\" : \"no\"}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t\tif (result.classification.reason) {\n\t\t\t\tp.log.message(`Classification reason: ${result.classification.reason}`);\n\t\t\t}\n\t\t\tif (result.evaluation.failureReasons.length > 0) {\n\t\t\t\tp.log.warn(\"Failure reasons:\");\n\t\t\t\tfor (const reason of result.evaluation.failureReasons) {\n\t\t\t\t\tp.log.message(` - ${reason}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tp.log.info(\n\t\t\t\t[\n\t\t\t\t\t`Fresh summaries: ${result.evaluation.counts.summaries}`,\n\t\t\t\t\t`Fresh observations: ${result.evaluation.counts.observations}`,\n\t\t\t\t\t`Summary thread coverage: ${result.evaluation.coverage.summaryThreadCoverage}`,\n\t\t\t\t\t`Observation thread coverage: ${result.evaluation.coverage.observationThreadCoverage}`,\n\t\t\t\t\t`Total thread coverage: ${result.evaluation.coverage.totalThreadCoverage}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t\tp.outro(\"done\");\n\t\t},\n\t);\n\treturn cmd;\n}\n\nfunction createMemoryExtractionBenchmarkCommand(): Command {\n\tconst cmd = new Command(\"extraction-benchmark\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\n\t\t\t\"Run the formal extraction replay benchmark set and print a cost/quality scoreboard\",\n\t\t)\n\t\t.requiredOption(\"--benchmark <id>\", \"benchmark profile id\")\n\t\t.option(\"--observer-provider <provider>\", \"override observer provider for this benchmark run\")\n\t\t.option(\"--observer-model <model>\", \"override observer model for this benchmark run\")\n\t\t.option(\"--observer-tier-routing\", \"use replay-only benchmark-backed observer tier routing\")\n\t\t.option(\"--openai-responses\", \"use OpenAI Responses API for this benchmark run\")\n\t\t.option(\n\t\t\t\"--reasoning-effort <level>\",\n\t\t\t\"set OpenAI reasoning.effort for this benchmark run (responses path)\",\n\t\t)\n\t\t.option(\n\t\t\t\"--reasoning-summary <mode>\",\n\t\t\t\"set OpenAI reasoning.summary for this benchmark run (responses path)\",\n\t\t)\n\t\t.option(\n\t\t\t\"--max-output-tokens <n>\",\n\t\t\t\"override OpenAI max_output_tokens for this benchmark run (responses path)\",\n\t\t)\n\t\t.option(\n\t\t\t\"--observer-temperature <value>\",\n\t\t\t\"override observer temperature for this benchmark run\",\n\t\t)\n\t\t.option(\n\t\t\t\"--transcript-budget <chars>\",\n\t\t\t\"override replay transcript budget in characters for this benchmark run\",\n\t\t);\n\taddDbOption(cmd);\n\taddJsonOption(cmd);\n\tcmd.action(\n\t\tasync (\n\t\t\topts: DbOpts &\n\t\t\t\tJsonOpts & {\n\t\t\t\t\tbenchmark: string;\n\t\t\t\t\tobserverProvider?: string;\n\t\t\t\t\tobserverModel?: string;\n\t\t\t\t\tobserverTierRouting?: boolean;\n\t\t\t\t\topenaiResponses?: boolean;\n\t\t\t\t\treasoningEffort?: string;\n\t\t\t\t\treasoningSummary?: string;\n\t\t\t\t\tmaxOutputTokens?: string;\n\t\t\t\t\tobserverTemperature?: string;\n\t\t\t\t\ttranscriptBudget?: string;\n\t\t\t\t},\n\t\t) => {\n\t\t\tconst benchmarkId = opts.benchmark?.trim() ?? \"\";\n\t\t\tconst benchmark = getExtractionBenchmarkProfile(benchmarkId);\n\t\t\tif (!benchmark) {\n\t\t\t\tthrow new Error(`Unknown extraction benchmark: ${benchmarkId || opts.benchmark}`);\n\t\t\t}\n\t\t\tconst transcriptBudgetInput = opts.transcriptBudget?.trim() ?? \"\";\n\t\t\tconst transcriptBudget =\n\t\t\t\ttranscriptBudgetInput.length > 0 ? parseStrictPositiveId(transcriptBudgetInput) : null;\n\t\t\tif (transcriptBudgetInput.length > 0 && transcriptBudget === null) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid transcript budget: ${transcriptBudgetInput || opts.transcriptBudget}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst observerTemperatureInput = opts.observerTemperature?.trim() ?? \"\";\n\t\t\tlet observerTemperature: number | undefined;\n\t\t\tif (observerTemperatureInput.length > 0) {\n\t\t\t\tconst parsed = Number(observerTemperatureInput);\n\t\t\t\tif (!Number.isFinite(parsed)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Invalid observer temperature: ${observerTemperatureInput || opts.observerTemperature}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tobserverTemperature = parsed;\n\t\t\t}\n\t\t\tconst maxOutputTokensInput = opts.maxOutputTokens?.trim() ?? \"\";\n\t\t\tconst maxOutputTokens =\n\t\t\t\tmaxOutputTokensInput.length > 0 ? parseStrictPositiveId(maxOutputTokensInput) : null;\n\t\t\tif (maxOutputTokensInput.length > 0 && maxOutputTokens === null) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid max output tokens: ${maxOutputTokensInput || opts.maxOutputTokens}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst observerConfig = loadObserverConfig();\n\t\t\tconst observerConfigWithOverrides = {\n\t\t\t\t...observerConfig,\n\t\t\t\tobserverProvider: opts.observerProvider?.trim() || observerConfig.observerProvider,\n\t\t\t\tobserverModel: opts.observerModel?.trim() || observerConfig.observerModel,\n\t\t\t\tobserverTemperature: observerTemperature ?? observerConfig.observerTemperature,\n\t\t\t\tobserverOpenAIUseResponses: opts.openaiResponses === true,\n\t\t\t\tobserverReasoningEffort: opts.reasoningEffort?.trim() || null,\n\t\t\t\tobserverReasoningSummary: opts.reasoningSummary?.trim() || null,\n\t\t\t\tobserverMaxOutputTokens: maxOutputTokens ?? observerConfig.observerMaxTokens,\n\t\t\t};\n\t\t\tconst observer = new ObserverClient(observerConfigWithOverrides);\n\t\t\tconst runs = [] as Array<{\n\t\t\t\tbatchId: number;\n\t\t\t\tsessionId: number;\n\t\t\t\tlabel: string;\n\t\t\t\tpurpose: \"shape_quality\" | \"replay_robustness\";\n\t\t\t\tcomplexity: string;\n\t\t\t\tscenarioId: string;\n\t\t\t\texpectedTier: string | null;\n\t\t\t\tanalysis: {\n\t\t\t\t\teventSpan: number;\n\t\t\t\t\tpromptCount: number;\n\t\t\t\t\ttoolCount: number;\n\t\t\t\t\ttranscriptLength: number;\n\t\t\t\t};\n\t\t\t\tstatus: \"pass\" | \"shape_fail\" | \"observer_no_output\";\n\t\t\t\treason: string;\n\t\t\t\ttier: string;\n\t\t\t\tprovider: string;\n\t\t\t\tmodel: string;\n\t\t\t\topenaiUseResponses: boolean;\n\t\t\t\treasoningEffort: string | null;\n\t\t\t\treasoningSummary: string | null;\n\t\t\t\tmaxOutputTokens: number;\n\t\t\t\ttemperature: number | null;\n\t\t\t\tsummaries: number;\n\t\t\t\tobservations: number;\n\t\t\t\trepairApplied: boolean;\n\t\t\t}>;\n\t\t\tfor (const batch of benchmark.batches) {\n\t\t\t\tconst scenarioId = batch.scenarioId ?? benchmark.scenarioId;\n\t\t\t\tconst result =\n\t\t\t\t\topts.observerTierRouting === true\n\t\t\t\t\t\t? await replayBatchExtractionWithTierRouting(\n\t\t\t\t\t\t\t\tresolveDbOpt(opts),\n\t\t\t\t\t\t\t\tobserverConfigWithOverrides,\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tbatchId: batch.batchId,\n\t\t\t\t\t\t\t\t\tscenarioId,\n\t\t\t\t\t\t\t\t\ttranscriptBudget: transcriptBudget ?? undefined,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: await replayBatchExtraction(resolveDbOpt(opts), observer, {\n\t\t\t\t\t\t\t\tbatchId: batch.batchId,\n\t\t\t\t\t\t\t\tscenarioId,\n\t\t\t\t\t\t\t\ttranscriptBudget: transcriptBudget ?? undefined,\n\t\t\t\t\t\t\t});\n\t\t\t\truns.push({\n\t\t\t\t\tbatchId: batch.batchId,\n\t\t\t\t\tsessionId: batch.sessionId,\n\t\t\t\t\tlabel: batch.label,\n\t\t\t\t\tpurpose: batch.purpose,\n\t\t\t\t\tcomplexity: batch.complexity,\n\t\t\t\t\tscenarioId,\n\t\t\t\t\texpectedTier: batch.expectedTier ?? null,\n\t\t\t\t\tanalysis: {\n\t\t\t\t\t\teventSpan: result.analysis.eventSpan,\n\t\t\t\t\t\tpromptCount: result.analysis.promptCount,\n\t\t\t\t\t\ttoolCount: result.analysis.toolCount,\n\t\t\t\t\t\ttranscriptLength: result.analysis.transcriptLength,\n\t\t\t\t\t},\n\t\t\t\t\tstatus: result.classification.status,\n\t\t\t\t\treason: result.classification.reason,\n\t\t\t\t\ttier: result.observer.tier ?? \"manual\",\n\t\t\t\t\tprovider: result.observer.provider,\n\t\t\t\t\tmodel: result.observer.model,\n\t\t\t\t\topenaiUseResponses: result.observer.openaiUseResponses,\n\t\t\t\t\treasoningEffort: result.observer.reasoningEffort,\n\t\t\t\t\treasoningSummary: result.observer.reasoningSummary,\n\t\t\t\t\tmaxOutputTokens: result.observer.maxOutputTokens,\n\t\t\t\t\ttemperature: result.observer.temperature,\n\t\t\t\t\tsummaries: result.evaluation.counts.summaries,\n\t\t\t\t\tobservations: result.evaluation.counts.observations,\n\t\t\t\t\trepairApplied: result.observer.repairApplied,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst summary = {\n\t\t\t\ttotal: runs.length,\n\t\t\t\tshapeQualityTotal: runs.filter((run) => run.purpose === \"shape_quality\").length,\n\t\t\t\tshapeQualityPasses: runs.filter(\n\t\t\t\t\t(run) => run.purpose === \"shape_quality\" && run.status === \"pass\",\n\t\t\t\t).length,\n\t\t\t\tshapeQualityFails: runs.filter(\n\t\t\t\t\t(run) => run.purpose === \"shape_quality\" && run.status === \"shape_fail\",\n\t\t\t\t).length,\n\t\t\t\texpectedTierTotal: runs.filter((run) => run.expectedTier != null).length,\n\t\t\t\texpectedTierMatches: runs.filter(\n\t\t\t\t\t(run) => run.expectedTier != null && run.expectedTier === run.tier,\n\t\t\t\t).length,\n\t\t\t\trobustnessNoOutput: runs.filter((run) => run.status === \"observer_no_output\").length,\n\t\t\t};\n\t\t\tconst uniqueObserverKeys = Array.from(\n\t\t\t\tnew Set(\n\t\t\t\t\truns.map(\n\t\t\t\t\t\t(run) =>\n\t\t\t\t\t\t\t`${run.provider}::${run.model}::${run.openaiUseResponses ? \"responses\" : \"chat\"}`,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t);\n\t\t\tconst observerSummary =\n\t\t\t\topts.observerTierRouting === true\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tprovider:\n\t\t\t\t\t\t\t\tuniqueObserverKeys.length === 1\n\t\t\t\t\t\t\t\t\t? (runs[0]?.provider ?? observer.provider)\n\t\t\t\t\t\t\t\t\t: \"mixed\",\n\t\t\t\t\t\t\tmodel: uniqueObserverKeys.length === 1 ? (runs[0]?.model ?? observer.model) : \"mixed\",\n\t\t\t\t\t\t\ttierRouting: true,\n\t\t\t\t\t\t\topenaiUseResponses:\n\t\t\t\t\t\t\t\tuniqueObserverKeys.length === 1\n\t\t\t\t\t\t\t\t\t? (runs[0]?.openaiUseResponses ?? observer.openaiUseResponses)\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\treasoningEffort:\n\t\t\t\t\t\t\t\tuniqueObserverKeys.length === 1\n\t\t\t\t\t\t\t\t\t? (runs[0]?.reasoningEffort ?? observer.reasoningEffort)\n\t\t\t\t\t\t\t\t\t: \"mixed\",\n\t\t\t\t\t\t\treasoningSummary:\n\t\t\t\t\t\t\t\tuniqueObserverKeys.length === 1\n\t\t\t\t\t\t\t\t\t? (runs[0]?.reasoningSummary ?? observer.reasoningSummary)\n\t\t\t\t\t\t\t\t\t: \"mixed\",\n\t\t\t\t\t\t\tmaxOutputTokens:\n\t\t\t\t\t\t\t\tuniqueObserverKeys.length === 1\n\t\t\t\t\t\t\t\t\t? (runs[0]?.maxOutputTokens ?? observer.maxOutputTokens)\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\ttemperature:\n\t\t\t\t\t\t\t\tuniqueObserverKeys.length === 1\n\t\t\t\t\t\t\t\t\t? (runs[0]?.temperature ?? observer.temperature)\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\ttranscriptBudget: transcriptBudget ?? null,\n\t\t\t\t\t\t\tselectedObservers: uniqueObserverKeys,\n\t\t\t\t\t\t}\n\t\t\t\t\t: {\n\t\t\t\t\t\t\tprovider: observer.provider,\n\t\t\t\t\t\t\tmodel: observer.model,\n\t\t\t\t\t\t\ttierRouting: false,\n\t\t\t\t\t\t\topenaiUseResponses: observer.openaiUseResponses,\n\t\t\t\t\t\t\treasoningEffort: observer.reasoningEffort,\n\t\t\t\t\t\t\treasoningSummary: observer.reasoningSummary,\n\t\t\t\t\t\t\tmaxOutputTokens: observer.maxOutputTokens,\n\t\t\t\t\t\t\ttemperature: observer.temperature,\n\t\t\t\t\t\t\ttranscriptBudget: transcriptBudget ?? null,\n\t\t\t\t\t\t\tselectedObservers: uniqueObserverKeys,\n\t\t\t\t\t\t};\n\t\t\tconst output = {\n\t\t\t\tbenchmark: {\n\t\t\t\t\tid: benchmark.id,\n\t\t\t\t\ttitle: benchmark.title,\n\t\t\t\t\tscenarioId: benchmark.scenarioId,\n\t\t\t\t},\n\t\t\t\tobserver: observerSummary,\n\t\t\t\tsummary,\n\t\t\t\truns,\n\t\t\t};\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(output, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tp.intro(\"codemem memory extraction-benchmark\");\n\t\t\tp.log.info(\n\t\t\t\t[\n\t\t\t\t\t`Benchmark: ${benchmark.id} — ${benchmark.title}`,\n\t\t\t\t\t`Observer: ${observerSummary.provider}/${observerSummary.model}`,\n\t\t\t\t\t`Tier routing: ${opts.observerTierRouting === true ? \"yes\" : \"no\"}`,\n\t\t\t\t\t`OpenAI Responses: ${observerSummary.openaiUseResponses === null ? \"mixed\" : observerSummary.openaiUseResponses ? \"yes\" : \"no\"}`,\n\t\t\t\t\t`Reasoning effort: ${observerSummary.reasoningEffort ?? \"none\"}`,\n\t\t\t\t\t`Reasoning summary: ${observerSummary.reasoningSummary ?? \"none\"}`,\n\t\t\t\t\t`Max output tokens: ${observerSummary.maxOutputTokens ?? \"mixed\"}`,\n\t\t\t\t\t`Temperature: ${observerSummary.temperature ?? \"mixed\"}`,\n\t\t\t\t\t`Transcript budget override: ${transcriptBudget ?? \"default\"}`,\n\t\t\t\t\t`Shape-quality passes: ${summary.shapeQualityPasses}/${summary.shapeQualityTotal}`,\n\t\t\t\t\t`Shape-quality fails: ${summary.shapeQualityFails}`,\n\t\t\t\t\t`Expected-tier matches: ${summary.expectedTierMatches}/${summary.expectedTierTotal}`,\n\t\t\t\t\t`Observer no-output cases: ${summary.robustnessNoOutput}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t\tfor (const run of runs) {\n\t\t\t\tp.log.message(\n\t\t\t\t\t` [${run.batchId}] ${run.status.padEnd(18)} ${run.complexity.padEnd(10)} tier=${run.tier.padEnd(6)} expected=${(run.expectedTier ?? \"n/a\").padEnd(6)} span=${String(run.analysis.eventSpan).padEnd(3)} prompts=${run.analysis.promptCount} tools=${String(run.analysis.toolCount).padEnd(2)} transcript=${run.analysis.transcriptLength} ${run.provider}/${run.model}${run.openaiUseResponses ? \" [responses]\" : \"\"} summaries=${run.summaries} observations=${run.observations} repair=${run.repairApplied ? \"yes\" : \"no\"} — ${run.label}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tp.outro(\"done\");\n\t\t},\n\t);\n\treturn cmd;\n}\n\nfunction createMemoryRelinkReportCommand(): Command {\n\tconst cmd = new Command(\"relink-report\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Analyze dry-run raw-event session relinking and compaction opportunities\")\n\t\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t\t.option(\"--all-projects\", \"analyze across all projects\")\n\t\t.option(\"--limit <n>\", \"max groups to print\", \"25\");\n\taddDbOption(cmd);\n\taddJsonOption(cmd);\n\tcmd.action(\n\t\t(\n\t\t\topts: DbOpts &\n\t\t\t\tJsonOpts & {\n\t\t\t\t\tproject?: string;\n\t\t\t\t\tallProjects?: boolean;\n\t\t\t\t\tlimit?: string;\n\t\t\t\t},\n\t\t) => {\n\t\t\tconst project =\n\t\t\t\topts.allProjects === true\n\t\t\t\t\t? null\n\t\t\t\t\t: opts.project?.trim() ||\n\t\t\t\t\t\tprocess.env.CODEMEM_PROJECT?.trim() ||\n\t\t\t\t\t\tresolveProject(process.cwd(), null);\n\t\t\tconst limit = Number.parseInt(opts.limit ?? \"25\", 10) || 25;\n\t\t\tconst result = getRawEventRelinkReport(resolveDbOpt(opts), {\n\t\t\t\tproject,\n\t\t\t\tallProjects: opts.allProjects === true,\n\t\t\t\tlimit,\n\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tp.intro(\"codemem memory relink-report\");\n\t\t\tp.log.info(\n\t\t\t\t[\n\t\t\t\t\t`Recoverable sessions: ${result.totals.recoverable_sessions}`,\n\t\t\t\t\t`Distinct stable ids: ${result.totals.distinct_stable_ids}`,\n\t\t\t\t\t`Groups with multiple sessions: ${result.totals.groups_with_multiple_sessions}`,\n\t\t\t\t\t`Groups with mapped session: ${result.totals.groups_with_mapped_session}`,\n\t\t\t\t\t`Groups without mapped session: ${result.totals.groups_without_mapped_session}`,\n\t\t\t\t\t`Active memories in groups: ${result.totals.active_memories}`,\n\t\t\t\t\t`Repointable active memories: ${result.totals.repointable_active_memories}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t\tp.log.info(\"Top relink groups:\");\n\t\t\tfor (const group of result.groups) {\n\t\t\t\tp.log.message(\n\t\t\t\t\t` ${group.stable_id} -> canonical ${group.canonical_session_id} | local=${group.local_sessions} mapped=${group.mapped_sessions} unmapped=${group.unmapped_sessions} active=${group.active_memories} repointable=${group.repointable_active_memories}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tp.outro(\"done\");\n\t\t},\n\t);\n\treturn cmd;\n}\n\nfunction createMemoryRelinkPlanCommand(): Command {\n\tconst cmd = new Command(\"relink-plan\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Emit dry-run raw-event relink remediation actions\")\n\t\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t\t.option(\"--all-projects\", \"analyze across all projects\")\n\t\t.option(\"--limit <n>\", \"max groups to include\", \"25\");\n\taddDbOption(cmd);\n\taddJsonOption(cmd);\n\tcmd.action(\n\t\t(\n\t\t\topts: DbOpts &\n\t\t\t\tJsonOpts & {\n\t\t\t\t\tproject?: string;\n\t\t\t\t\tallProjects?: boolean;\n\t\t\t\t\tlimit?: string;\n\t\t\t\t},\n\t\t) => {\n\t\t\tconst project =\n\t\t\t\topts.allProjects === true\n\t\t\t\t\t? null\n\t\t\t\t\t: opts.project?.trim() ||\n\t\t\t\t\t\tprocess.env.CODEMEM_PROJECT?.trim() ||\n\t\t\t\t\t\tresolveProject(process.cwd(), null);\n\t\t\tconst limit = Number.parseInt(opts.limit ?? \"25\", 10) || 25;\n\t\t\tconst result = getRawEventRelinkPlan(resolveDbOpt(opts), {\n\t\t\t\tproject,\n\t\t\t\tallProjects: opts.allProjects === true,\n\t\t\t\tlimit,\n\t\t\t});\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tp.intro(\"codemem memory relink-plan\");\n\t\t\tp.log.info(\n\t\t\t\t[\n\t\t\t\t\t`Groups: ${result.totals.groups}`,\n\t\t\t\t\t`Eligible groups: ${result.totals.eligible_groups}`,\n\t\t\t\t\t`Skipped groups: ${result.totals.skipped_groups}`,\n\t\t\t\t\t`Actions: ${result.totals.actions}`,\n\t\t\t\t\t`Bridge creations: ${result.totals.bridge_creations}`,\n\t\t\t\t\t`Memory repoints: ${result.totals.memory_repoints}`,\n\t\t\t\t\t`Session compactions: ${result.totals.session_compactions}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t\tp.log.info(\"Planned actions:\");\n\t\t\tfor (const action of result.actions.slice(0, 15)) {\n\t\t\t\tp.log.message(\n\t\t\t\t\t` ${action.action} ${action.stable_id} -> canonical ${action.canonical_session_id} | sessions=${action.session_ids.join(\",\") || \"-\"} memories=${action.memory_count} reason=${action.reason}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (result.skipped_groups.length > 0) {\n\t\t\t\tp.log.info(\"Skipped groups:\");\n\t\t\t\tfor (const group of result.skipped_groups.slice(0, 10)) {\n\t\t\t\t\tp.log.message(` ${group.stable_id} | blockers=${group.blockers.join(\",\")}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tp.outro(\"done\");\n\t\t},\n\t);\n\treturn cmd;\n}\n\nexport const showMemoryCommand = createShowMemoryCommand();\nexport const forgetMemoryCommand = createForgetMemoryCommand();\nexport const rememberMemoryCommand = createRememberMemoryCommand();\n\nexport const memoryCommand = new Command(\"memory\")\n\t.configureHelp(helpStyle)\n\t.description(\"Memory item management\");\n\nmemoryCommand.addCommand(createShowMemoryCommand());\nmemoryCommand.addCommand(createForgetMemoryCommand());\nmemoryCommand.addCommand(createRememberMemoryCommand());\nmemoryCommand.addCommand(createInjectMemoryCommand());\nmemoryCommand.addCommand(createMemoryRoleReportCommand());\nmemoryCommand.addCommand(createMemoryRoleCompareCommand());\nmemoryCommand.addCommand(createMemoryExtractionReportCommand());\nmemoryCommand.addCommand(createMemoryExtractionReplayCommand());\nmemoryCommand.addCommand(createMemoryExtractionBenchmarkCommand());\nmemoryCommand.addCommand(createMemoryRelinkReportCommand());\nmemoryCommand.addCommand(createMemoryRelinkPlanCommand());\n","import * as p from \"@clack/prompts\";\nimport type { PackTrace } from \"@codemem/core\";\nimport { MemoryStore, resolveDbPath } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddDbOption,\n\taddJsonOption,\n\ttype DbOpts,\n\temitJsonError,\n\ttype JsonOpts,\n\tresolveDbOpt,\n} from \"../shared-options.js\";\nimport { addPackRequestOptions, buildPackRequestOptions, PackUsageError } from \"./pack-shared.js\";\n\ntype PackCommandOptions = DbOpts &\n\tJsonOpts & {\n\t\tlimit: string;\n\t\tbudget?: string;\n\t\ttokenBudget?: string;\n\t\tworkingSetFile?: string[];\n\t\tproject?: string;\n\t\tallProjects?: boolean;\n\t\tcompact?: boolean;\n\t\tcompactDetail?: string;\n\t};\n\nfunction describeCandidate(candidate: PackTrace[\"retrieval\"][\"candidates\"][number]): string[] {\n\tconst scoreParts = [\n\t\tcandidate.scores.combined_score != null\n\t\t\t? `combined=${candidate.scores.combined_score.toFixed(2)}`\n\t\t\t: null,\n\t\tcandidate.scores.base_score != null ? `base=${candidate.scores.base_score.toFixed(2)}` : null,\n\t\tcandidate.scores.text_overlap > 0 ? `text=${candidate.scores.text_overlap}` : null,\n\t\tcandidate.scores.tag_overlap > 0 ? `tag=${candidate.scores.tag_overlap}` : null,\n\t\tcandidate.scores.working_set_overlap > 0\n\t\t\t? `working_set=${candidate.scores.working_set_overlap.toFixed(2)}`\n\t\t\t: null,\n\t]\n\t\t.filter(Boolean)\n\t\t.join(\" \");\n\n\tconst lines = [`${candidate.rank}. [${candidate.id}] (${candidate.kind}) ${candidate.title}`];\n\tif (candidate.section) lines.push(` - section: ${candidate.section}`);\n\tif (candidate.reasons.length > 0) lines.push(` - reasons: ${candidate.reasons.join(\", \")}`);\n\tif (scoreParts) lines.push(` - scores: ${scoreParts}`);\n\tif (candidate.preview) lines.push(` - preview: ${candidate.preview}`);\n\treturn lines;\n}\n\nexport function renderPackTrace(trace: PackTrace): string {\n\tconst workingSet =\n\t\ttrace.inputs.working_set_files.length > 0\n\t\t\t? trace.inputs.working_set_files.join(\", \")\n\t\t\t: \"(none)\";\n\tconst lines = [\n\t\t\"Pack trace\",\n\t\t`- Query: ${trace.inputs.query}`,\n\t\t`- Project: ${trace.inputs.project ?? \"(default)\"}`,\n\t\t`- Working set: ${workingSet}`,\n\t\t`- Mode: ${trace.mode.selected}`,\n\t\t`- Mode reasons: ${trace.mode.reasons.join(\", \") || \"(none)\"}`,\n\t\t`- Token budget: ${trace.inputs.token_budget ?? \"(none)\"}`,\n\t\t\"\",\n\t];\n\n\tfor (const disposition of [\"selected\", \"dropped\", \"deduped\", \"trimmed\"] as const) {\n\t\tconst group = trace.retrieval.candidates.filter(\n\t\t\t(candidate) => candidate.disposition === disposition,\n\t\t);\n\t\tif (group.length === 0) continue;\n\t\tlines.push(disposition.charAt(0).toUpperCase() + disposition.slice(1));\n\t\tfor (const candidate of group) {\n\t\t\tlines.push(...describeCandidate(candidate));\n\t\t}\n\t\tlines.push(\"\");\n\t}\n\n\tlines.push(\"Assembly\");\n\tlines.push(`- deduped ids: ${trace.assembly.deduped_ids.join(\", \") || \"(none)\"}`);\n\tlines.push(`- trimmed ids: ${trace.assembly.trimmed_ids.join(\", \") || \"(none)\"}`);\n\tlines.push(`- trim reasons: ${trace.assembly.trim_reasons.join(\", \") || \"(none)\"}`);\n\tlines.push(\n\t\t`- section counts: summary=${trace.output.section_counts.summary} timeline=${trace.output.section_counts.timeline} observations=${trace.output.section_counts.observations}`,\n\t);\n\tlines.push(`- estimated tokens: ${trace.output.estimated_tokens}`);\n\tlines.push(`- truncated: ${trace.output.truncated ? \"yes\" : \"no\"}`);\n\tlines.push(\"\");\n\tlines.push(\"Final pack\");\n\tlines.push(trace.output.pack_text);\n\treturn lines.join(\"\\n\");\n}\n\nasync function withStore(\n\topts: PackCommandOptions,\n\terrorCode: string,\n\trun: (store: MemoryStore) => Promise<void>,\n): Promise<void> {\n\tlet store: MemoryStore | null = null;\n\ttry {\n\t\tstore = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\tawait run(store);\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tconst usageError = error instanceof PackUsageError;\n\t\tif (opts.json) {\n\t\t\temitJsonError(usageError ? \"usage_error\" : errorCode, message, usageError ? 2 : 1);\n\t\t\treturn;\n\t\t}\n\t\tp.log.error(message);\n\t\tprocess.exitCode = usageError ? 2 : 1;\n\t} finally {\n\t\tstore?.close();\n\t}\n}\n\nasync function packAction(context: string, opts: PackCommandOptions): Promise<void> {\n\tawait withStore(opts, \"pack_failed\", async (store) => {\n\t\tconst { limit, budget, filters, renderOptions } = buildPackRequestOptions(opts, {\n\t\t\tenvProject: process.env.CODEMEM_PROJECT,\n\t\t});\n\t\tconst result = await store.buildMemoryPackAsync(context, limit, budget, filters, renderOptions);\n\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\treturn;\n\t\t}\n\n\t\tp.intro(`Memory pack for \"${context}\"`);\n\n\t\tif (result.items.length === 0) {\n\t\t\tp.log.warn(\"No relevant memories found.\");\n\t\t\tp.outro(\"done\");\n\t\t\treturn;\n\t\t}\n\n\t\tconst metrics = result.metrics;\n\t\tp.log.info(\n\t\t\t`${metrics.total_items} items, ~${metrics.pack_tokens} tokens` +\n\t\t\t\t(metrics.fallback_used ? \" (fallback)\" : \"\") +\n\t\t\t\t` [fts:${metrics.sources.fts} sem:${metrics.sources.semantic} fuzzy:${metrics.sources.fuzzy}]`,\n\t\t);\n\n\t\tfor (const item of result.items) {\n\t\t\tp.log.step(`#${item.id} ${item.kind} ${item.title}`);\n\t\t}\n\n\t\tp.note(result.pack_text, \"pack_text\");\n\t\tp.outro(\"done\");\n\t});\n}\n\nasync function traceAction(context: string, opts: PackCommandOptions): Promise<void> {\n\tawait withStore(opts, \"pack_trace_failed\", async (store) => {\n\t\tconst { limit, budget, filters, renderOptions } = buildPackRequestOptions(opts, {\n\t\t\tenvProject: process.env.CODEMEM_PROJECT,\n\t\t});\n\t\tconst trace = await store.buildMemoryPackTraceAsync(\n\t\t\tcontext,\n\t\t\tlimit,\n\t\t\tbudget,\n\t\t\tfilters,\n\t\t\trenderOptions,\n\t\t);\n\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify(trace, null, 2));\n\t\t\treturn;\n\t\t}\n\n\t\tconsole.log(renderPackTrace(trace));\n\t});\n}\n\nconst packCmd = addPackRequestOptions(\n\tnew Command(\"pack\")\n\t\t.enablePositionalOptions()\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Build a context-aware memory pack\")\n\t\t.argument(\"<context>\", \"context string to search for\"),\n);\n\naddDbOption(packCmd);\naddJsonOption(packCmd);\npackCmd.action(packAction);\n\nconst traceCmd = addPackRequestOptions(\n\tnew Command(\"trace\")\n\t\t.configureHelp(helpStyle)\n\t\t.description(\"Trace retrieval and assembly for a memory pack\")\n\t\t.argument(\"<context>\", \"context string to trace\"),\n);\n\naddDbOption(traceCmd);\naddJsonOption(traceCmd);\ntraceCmd.action(traceAction);\npackCmd.addCommand(traceCmd);\n\nexport const packCommand = packCmd;\n","import { MemoryStore, resolveDbPath, resolveProject } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddDbOption,\n\taddJsonOption,\n\ttype DbOpts,\n\ttype JsonOpts,\n\tresolveDbOpt,\n} from \"../shared-options.js\";\n\nconst cmd = new Command(\"recent\")\n\t.configureHelp(helpStyle)\n\t.description(\"Show recent memories\")\n\t.option(\"--limit <n>\", \"max results\", \"5\")\n\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t.option(\"--all-projects\", \"search across all projects\")\n\t.option(\"--kind <kind>\", \"filter by memory kind\");\n\naddDbOption(cmd);\naddJsonOption(cmd);\n\ncmd.action(\n\t(\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\tlimit: string;\n\t\t\t\tproject?: string;\n\t\t\t\tallProjects?: boolean;\n\t\t\t\tkind?: string;\n\t\t\t},\n\t) => {\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tconst limit = Math.max(1, Number.parseInt(opts.limit, 10) || 5);\n\t\t\tconst filters: { kind?: string; project?: string } = {};\n\t\t\tif (opts.kind) filters.kind = opts.kind;\n\t\t\tif (!opts.allProjects) {\n\t\t\t\tconst defaultProject = process.env.CODEMEM_PROJECT?.trim() || null;\n\t\t\t\tconst project = defaultProject || resolveProject(process.cwd(), opts.project ?? null);\n\t\t\t\tif (project) filters.project = project;\n\t\t\t}\n\t\t\tconst items = store.recent(limit, filters);\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(items));\n\t\t\t} else {\n\t\t\t\tfor (const item of items) {\n\t\t\t\t\tconsole.log(`#${item.id} [${item.kind}] ${item.title}`);\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\n\nexport const recentCommand = cmd;\n","import * as p from \"@clack/prompts\";\nimport { MemoryStore, resolveDbPath, resolveProject } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddDbOption,\n\taddJsonOption,\n\ttype DbOpts,\n\ttype JsonOpts,\n\tresolveDbOpt,\n} from \"../shared-options.js\";\n\nconst searchCmd = new Command(\"search\")\n\t.configureHelp(helpStyle)\n\t.description(\"Search memories by query\")\n\t.argument(\"<query>\", \"search query\")\n\t.option(\"-n, --limit <n>\", \"max results\", \"5\")\n\t.option(\"--project <project>\", \"project identifier (defaults to git repo root)\")\n\t.option(\"--all-projects\", \"search across all projects\")\n\t.option(\"--kind <kind>\", \"filter by memory kind\");\n\naddDbOption(searchCmd);\naddJsonOption(searchCmd);\n\nexport const searchCommand = searchCmd.action(\n\t(\n\t\tquery: string,\n\t\topts: DbOpts &\n\t\t\tJsonOpts & {\n\t\t\t\tlimit: string;\n\t\t\t\tproject?: string;\n\t\t\t\tallProjects?: boolean;\n\t\t\t\tkind?: string;\n\t\t\t},\n\t) => {\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tconst limit = Math.max(1, Number.parseInt(opts.limit, 10) || 5);\n\t\t\tconst filters: { kind?: string; project?: string } = {};\n\t\t\tif (opts.kind) filters.kind = opts.kind;\n\t\t\tif (!opts.allProjects) {\n\t\t\t\tconst defaultProject = process.env.CODEMEM_PROJECT?.trim() || null;\n\t\t\t\tconst project = defaultProject || resolveProject(process.cwd(), opts.project ?? null);\n\t\t\t\tif (project) filters.project = project;\n\t\t\t}\n\t\t\tconst results = store.search(query, limit, filters);\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify(results, null, 2));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (results.length === 0) {\n\t\t\t\tp.log.warn(\"No results found.\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tp.intro(`${results.length} result(s) for \"${query}\"`);\n\n\t\t\tfor (const item of results) {\n\t\t\t\tconst score = item.score.toFixed(3);\n\t\t\t\tconst age = timeSince(item.created_at);\n\t\t\t\tconst preview =\n\t\t\t\t\titem.body_text.length > 120 ? `${item.body_text.slice(0, 120)}…` : item.body_text;\n\n\t\t\t\tp.log.message(\n\t\t\t\t\t[`#${item.id} ${item.kind} ${age} [${score}]`, item.title, preview].join(\"\\n\"),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tp.outro(\"done\");\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\n\nfunction timeSince(isoDate: string): string {\n\tconst ms = Date.now() - new Date(isoDate).getTime();\n\tconst days = Math.floor(ms / 86_400_000);\n\tif (days === 0) return \"today\";\n\tif (days === 1) return \"1d ago\";\n\tif (days < 30) return `${days}d ago`;\n\tconst months = Math.floor(days / 30);\n\treturn `${months}mo ago`;\n}\n","import { type DbOpts, resolveDbOpt } from \"../shared-options.js\";\n\nexport type ServeMode = \"start\" | \"stop\" | \"restart\";\n\nexport type ServeAction = ServeMode | undefined;\n\nexport interface LegacyServeOptions extends DbOpts {\n\tconfig?: string;\n\thost: string;\n\tport: string;\n\tbackground?: boolean;\n\tforeground?: boolean;\n\tstop?: boolean;\n\trestart?: boolean;\n}\n\nexport interface StartServeOptions extends DbOpts {\n\tconfig?: string;\n\thost: string;\n\tport: string;\n\tforeground?: boolean;\n}\n\nexport interface StopRestartServeOptions extends DbOpts {\n\tconfig?: string;\n\thost: string;\n\tport: string;\n}\n\nexport interface ResolvedServeInvocation {\n\tmode: ServeMode;\n\tdbPath: string | null;\n\tconfigPath: string | null;\n\thost: string;\n\tport: number;\n\tbackground: boolean;\n}\n\n/**\n * Parse and validate a port string. Throws a user-friendly message (no stack trace)\n * that callers in serve.ts catch at the action boundary.\n */\nexport function parsePort(rawPort: string): number {\n\tconst port = Number.parseInt(rawPort, 10);\n\tif (!Number.isFinite(port) || port < 1 || port > 65535) {\n\t\tthrow new Error(`Invalid port: ${rawPort}`);\n\t}\n\treturn port;\n}\n\nexport function resolveLegacyServeInvocation(opts: LegacyServeOptions): ResolvedServeInvocation {\n\tif (opts.stop && opts.restart) {\n\t\tthrow new Error(\"Use only one of --stop or --restart\");\n\t}\n\tif (opts.foreground && opts.background) {\n\t\tthrow new Error(\"Use only one of --background or --foreground\");\n\t}\n\tconst dbPath = resolveDbOpt(opts) ?? null;\n\treturn {\n\t\tmode: opts.stop ? \"stop\" : opts.restart ? \"restart\" : \"start\",\n\t\tdbPath,\n\t\tconfigPath: opts.config ?? null,\n\t\thost: opts.host,\n\t\tport: parsePort(opts.port),\n\t\tbackground: Boolean(opts.restart || opts.background),\n\t};\n}\n\nexport function resolveServeInvocation(\n\taction: ServeAction,\n\topts: LegacyServeOptions,\n): ResolvedServeInvocation {\n\tif (action === undefined) {\n\t\treturn resolveLegacyServeInvocation(opts);\n\t}\n\tif (opts.stop || opts.restart) {\n\t\tthrow new Error(\"Do not combine lifecycle flags with a serve action\");\n\t}\n\tif (action === \"start\") {\n\t\treturn resolveStartServeInvocation(opts);\n\t}\n\treturn resolveStopRestartInvocation(action, opts);\n}\n\nexport function resolveStartServeInvocation(opts: StartServeOptions): ResolvedServeInvocation {\n\tconst dbPath = resolveDbOpt(opts) ?? null;\n\treturn {\n\t\tmode: \"start\",\n\t\tdbPath,\n\t\tconfigPath: opts.config ?? null,\n\t\thost: opts.host,\n\t\tport: parsePort(opts.port),\n\t\tbackground: !opts.foreground,\n\t};\n}\n\nexport function resolveStopRestartInvocation(\n\tmode: \"stop\" | \"restart\",\n\topts: StopRestartServeOptions,\n): ResolvedServeInvocation {\n\tconst dbPath = resolveDbOpt(opts) ?? null;\n\treturn {\n\t\tmode,\n\t\tdbPath,\n\t\tconfigPath: opts.config ?? null,\n\t\thost: opts.host,\n\t\tport: parsePort(opts.port),\n\t\tbackground: mode === \"restart\",\n\t};\n}\n","import { spawn, spawnSync } from \"node:child_process\";\nimport { existsSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport net from \"node:net\";\nimport { dirname, join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport {\n\tDedupKeyBackfillRunner,\n\thasPendingDedupKeyBackfill,\n\tinitDatabase,\n\tisEmbeddingDisabled,\n\ttype MemoryStore,\n\tObserverClient,\n\tRawEventSweeper,\n\treadCodememConfigFile,\n\treadCodememConfigFileAtPath,\n\treadCoordinatorSyncConfig,\n\tresolveDbPath,\n\trunSyncDaemon,\n\tSyncRetentionRunner,\n\tVectorModelMigrationRunner,\n} from \"@codemem/core\";\nimport { Command, Option } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddConfigOption,\n\taddDbOption,\n\taddViewerHostOptions,\n\temitDeprecationWarning,\n} from \"../shared-options.js\";\nimport {\n\ttype LegacyServeOptions,\n\ttype ResolvedServeInvocation,\n\tresolveServeInvocation,\n\ttype ServeAction,\n} from \"./serve-invocation.js\";\n\ninterface ViewerPidRecord {\n\tpid: number;\n\thost: string;\n\tport: number;\n}\n\nexport function extractViewerPid(payload: unknown): number | null {\n\tif (!payload || typeof payload !== \"object\") return null;\n\tconst rawPid = (payload as { viewer_pid?: unknown }).viewer_pid;\n\tif (typeof rawPid !== \"number\" || !Number.isFinite(rawPid) || rawPid <= 0) return null;\n\treturn Math.trunc(rawPid);\n}\n\nexport function isLocalHost(host: string): boolean {\n\tconst normalized = host.trim().toLowerCase();\n\treturn (\n\t\tnormalized === \"127.0.0.1\" ||\n\t\tnormalized === \"localhost\" ||\n\t\tnormalized === \"::1\" ||\n\t\tnormalized === \"0.0.0.0\" ||\n\t\tnormalized === \"::\"\n\t);\n}\n\nexport function isLoopbackOnlyHost(host: string): boolean {\n\tconst normalized = host.trim().toLowerCase();\n\treturn (\n\t\tnormalized === \"localhost\" ||\n\t\t/^127(?:\\.\\d{1,3}){0,3}$/.test(normalized) ||\n\t\tnormalized === \"::1\" ||\n\t\tnormalized === \"0:0:0:0:0:0:0:1\"\n\t);\n}\n\nfunction warnIfViewerExposed(host: string, port: number): void {\n\tif (isLoopbackOnlyHost(host)) return;\n\tp.log.warn(\n\t\t`Viewer bound to ${host}:${port}. codemem's viewer trust model assumes localhost-only access; do not expose it through a reverse proxy, tunnel, or public bind without adding your own auth layer.`,\n\t);\n}\n\nexport function isLikelyViewerCommand(command: string): boolean {\n\tconst lowered = command.toLowerCase();\n\tif (!/\\bserve\\s+start\\b/.test(lowered)) return false;\n\treturn (\n\t\tlowered.includes(\"codemem\") ||\n\t\tlowered.includes(\"packages/cli/dist/index.js\") ||\n\t\tlowered.includes(\"/cli/dist/index.js\")\n\t);\n}\n\nexport function prepareViewerDatabase(dbPath?: string | null): string {\n\treturn initDatabase(dbPath ?? undefined).path;\n}\n\nexport function pickViewerPidCandidate(\n\tstatsPid: number | null,\n\tlistenerPid: number | null,\n): number | null {\n\tif (statsPid && listenerPid && statsPid !== listenerPid) return null;\n\treturn statsPid ?? listenerPid ?? null;\n}\n\nfunction lookupListeningPid(host: string, port: number): number | null {\n\tif (!isLocalHost(host)) return null;\n\tconst result = spawnSync(\"lsof\", [\"-nP\", `-iTCP:${port}`, \"-sTCP:LISTEN\", \"-t\"], {\n\t\tencoding: \"utf-8\",\n\t\ttimeout: 1000,\n\t});\n\tif (result.status !== 0) return null;\n\tconst first = (result.stdout || \"\")\n\t\t.split(/\\r?\\n/)\n\t\t.map((line) => line.trim())\n\t\t.find((line) => line.length > 0);\n\tif (!first) return null;\n\tconst parsed = Number.parseInt(first, 10);\n\treturn Number.isFinite(parsed) && parsed > 0 ? parsed : null;\n}\n\nfunction readProcessCommand(pid: number): string | null {\n\tconst result = spawnSync(\"ps\", [\"-p\", String(pid), \"-o\", \"command=\"], {\n\t\tencoding: \"utf-8\",\n\t\ttimeout: 1000,\n\t});\n\tif (result.status !== 0) return null;\n\tconst cmd = (result.stdout || \"\").trim();\n\treturn cmd.length > 0 ? cmd : null;\n}\n\nfunction isTrustedViewerPid(\n\tpid: number,\n\ttarget: { host: string; port: number },\n\tlistenerPid: number | null,\n): boolean {\n\tif (!isLocalHost(target.host)) return false;\n\tif (listenerPid && listenerPid !== pid) return false;\n\tconst command = readProcessCommand(pid);\n\tif (!command) return false;\n\treturn isLikelyViewerCommand(command);\n}\n\nfunction pidFilePath(dbPath: string): string {\n\treturn join(dirname(dbPath), \"viewer.pid\");\n}\n\nfunction readViewerPidRecord(dbPath: string): ViewerPidRecord | null {\n\tconst pidPath = pidFilePath(dbPath);\n\tif (!existsSync(pidPath)) return null;\n\tconst raw = readFileSync(pidPath, \"utf-8\").trim();\n\ttry {\n\t\tconst parsed = JSON.parse(raw) as Partial<ViewerPidRecord>;\n\t\tif (\n\t\t\ttypeof parsed.pid === \"number\" &&\n\t\t\ttypeof parsed.host === \"string\" &&\n\t\t\ttypeof parsed.port === \"number\"\n\t\t) {\n\t\t\treturn { pid: parsed.pid, host: parsed.host, port: parsed.port };\n\t\t}\n\t} catch {\n\t\tconst pid = Number.parseInt(raw, 10);\n\t\tif (Number.isFinite(pid) && pid > 0) {\n\t\t\treturn { pid, host: \"127.0.0.1\", port: 38888 };\n\t\t}\n\t}\n\treturn null;\n}\n\nfunction isProcessRunning(pid: number): boolean {\n\ttry {\n\t\tprocess.kill(pid, 0);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function respondsLikeCodememViewer(record: ViewerPidRecord): Promise<boolean> {\n\ttry {\n\t\tconst controller = new AbortController();\n\t\tconst timer = setTimeout(() => controller.abort(), 1000);\n\t\tconst res = await fetch(`http://${record.host}:${record.port}/api/stats`, {\n\t\t\tsignal: controller.signal,\n\t\t});\n\t\tclearTimeout(timer);\n\t\treturn res.ok;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function lookupViewerPidFromStats(host: string, port: number): Promise<number | null> {\n\ttry {\n\t\tconst controller = new AbortController();\n\t\tconst timer = setTimeout(() => controller.abort(), 1000);\n\t\tconst res = await fetch(`http://${host}:${port}/api/stats`, {\n\t\t\tsignal: controller.signal,\n\t\t});\n\t\tclearTimeout(timer);\n\t\tif (!res.ok) return null;\n\t\tconst payload = await res.json();\n\t\treturn extractViewerPid(payload);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function isPortOpen(host: string, port: number): Promise<boolean> {\n\treturn new Promise((resolve) => {\n\t\tconst socket = net.createConnection({ host, port });\n\t\tconst done = (open: boolean) => {\n\t\t\tsocket.removeAllListeners();\n\t\t\tsocket.destroy();\n\t\t\tresolve(open);\n\t\t};\n\t\tsocket.setTimeout(300);\n\t\tsocket.once(\"connect\", () => done(true));\n\t\tsocket.once(\"timeout\", () => done(false));\n\t\tsocket.once(\"error\", () => done(false));\n\t});\n}\n\nasync function waitForProcessExit(pid: number, timeoutMs = 30000): Promise<boolean> {\n\tconst deadline = Date.now() + timeoutMs;\n\twhile (Date.now() < deadline) {\n\t\tif (!isProcessRunning(pid)) return true;\n\t\tawait new Promise((resolve) => setTimeout(resolve, 100));\n\t}\n\treturn !isProcessRunning(pid);\n}\n\nasync function waitForPortRelease(host: string, port: number, timeoutMs = 10000): Promise<boolean> {\n\tconst deadline = Date.now() + timeoutMs;\n\twhile (Date.now() < deadline) {\n\t\tif (!(await isPortOpen(host, port))) return true;\n\t\tawait new Promise((resolve) => setTimeout(resolve, 200));\n\t}\n\treturn false;\n}\n\nasync function stopExistingViewer(\n\tdbPath: string,\n\ttarget: { host: string; port: number },\n): Promise<{ stopped: boolean; pid: number | null }> {\n\tconst terminatePid = async (pid: number): Promise<boolean> => {\n\t\ttry {\n\t\t\tprocess.kill(pid, \"SIGTERM\");\n\t\t\treturn await waitForProcessExit(pid);\n\t\t} catch {\n\t\t\treturn true;\n\t\t}\n\t};\n\n\tconst pidPath = pidFilePath(dbPath);\n\tconst record = readViewerPidRecord(dbPath);\n\tconst viewerPidFromStats = await lookupViewerPidFromStats(target.host, target.port);\n\tconst listenerPid = lookupListeningPid(target.host, target.port);\n\tconst viewerPid = pickViewerPidCandidate(viewerPidFromStats, listenerPid);\n\tif (viewerPid && isTrustedViewerPid(viewerPid, target, listenerPid)) {\n\t\tconst stopped = await terminatePid(viewerPid);\n\t\tif (!stopped) return { stopped: false, pid: viewerPid };\n\t\ttry {\n\t\t\trmSync(pidPath);\n\t\t} catch {\n\t\t\t// ignore\n\t\t}\n\t\treturn { stopped: true, pid: viewerPid };\n\t}\n\n\tif (!record) return { stopped: false, pid: null };\n\n\tif (await respondsLikeCodememViewer(record)) {\n\t\tconst stopped = await terminatePid(record.pid);\n\t\tif (!stopped) return { stopped: false, pid: record.pid };\n\t}\n\ttry {\n\t\trmSync(pidPath);\n\t} catch {\n\t\t// ignore\n\t}\n\treturn { stopped: true, pid: record.pid };\n}\n\nexport function buildForegroundRunnerArgs(\n\tscriptPath: string,\n\tinvocation: ResolvedServeInvocation,\n\texecArgv: string[] = process.execArgv,\n): string[] {\n\tconst args = [\n\t\t...execArgv,\n\t\tscriptPath,\n\t\t\"serve\",\n\t\t\"start\",\n\t\t\"--foreground\",\n\t\t\"--host\",\n\t\tinvocation.host,\n\t\t\"--port\",\n\t\tString(invocation.port),\n\t];\n\tif (invocation.dbPath) {\n\t\targs.push(\"--db-path\", invocation.dbPath);\n\t}\n\treturn args;\n}\n\nexport function isSqliteVecLoadFailure(error: unknown): boolean {\n\tif (!(error instanceof Error)) return false;\n\tconst text = error.message.toLowerCase();\n\treturn (\n\t\ttext.includes(\"sqlite-vec\") ||\n\t\ttext.includes(\"vec_version\") ||\n\t\ttext.includes(\"vec0\") ||\n\t\t(text.includes(\"sqlite\") && text.includes(\"vec\"))\n\t);\n}\n\nexport function sqliteVecFailureDiagnostics(error: unknown, dbPath: string): string[] {\n\tconst message = error instanceof Error ? error.message : String(error);\n\treturn [\n\t\t`db=${dbPath}`,\n\t\t`node=${process.version}`,\n\t\t`exec=${process.execPath}`,\n\t\t`cwd=${process.cwd()}`,\n\t\t`embedding_disabled=${process.env.CODEMEM_EMBEDDING_DISABLED ?? \"\"}`,\n\t\t`error=${message}`,\n\t];\n}\n\nasync function startBackgroundViewer(invocation: ResolvedServeInvocation): Promise<void> {\n\twarnIfViewerExposed(invocation.host, invocation.port);\n\tif (await isPortOpen(invocation.host, invocation.port)) {\n\t\tp.log.warn(`Viewer already running at http://${invocation.host}:${invocation.port}`);\n\t\treturn;\n\t}\n\tconst scriptPath = process.argv[1];\n\tif (!scriptPath) {\n\t\tp.log.error(\"Unable to resolve CLI entrypoint for background launch\");\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\tconst child = spawn(process.execPath, buildForegroundRunnerArgs(scriptPath, invocation), {\n\t\tcwd: process.cwd(),\n\t\tdetached: true,\n\t\tstdio: \"ignore\",\n\t\tenv: {\n\t\t\t...process.env,\n\t\t\t...(invocation.dbPath ? { CODEMEM_DB: invocation.dbPath } : {}),\n\t\t\t...(invocation.configPath ? { CODEMEM_CONFIG: invocation.configPath } : {}),\n\t\t},\n\t});\n\tchild.unref();\n\tif (invocation.dbPath) {\n\t\twriteFileSync(\n\t\t\tpidFilePath(invocation.dbPath),\n\t\t\tJSON.stringify({ pid: child.pid, host: invocation.host, port: invocation.port }),\n\t\t\t\"utf-8\",\n\t\t);\n\t}\n\tp.intro(\"codemem viewer\");\n\tp.outro(\n\t\t`Viewer started in background (pid ${child.pid}) at http://${invocation.host}:${invocation.port}`,\n\t);\n}\n\nasync function startForegroundViewer(invocation: ResolvedServeInvocation): Promise<void> {\n\tconst { createApp, createSyncApp, closeStore, getStore } = await import(\"@codemem/server\");\n\tconst { serve } = await import(\"@hono/node-server\");\n\n\tif (invocation.dbPath) process.env.CODEMEM_DB = invocation.dbPath;\n\tif (invocation.configPath) process.env.CODEMEM_CONFIG = invocation.configPath;\n\twarnIfViewerExposed(invocation.host, invocation.port);\n\tif (await isPortOpen(invocation.host, invocation.port)) {\n\t\tp.log.warn(`Viewer already running at http://${invocation.host}:${invocation.port}`);\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\tconst preparedDb = prepareViewerDatabase(invocation.dbPath);\n\n\tconst observer = new ObserverClient();\n\tlet store: MemoryStore;\n\ttry {\n\t\tstore = getStore();\n\t} catch (err) {\n\t\tif (isEmbeddingDisabled() || !isSqliteVecLoadFailure(err)) {\n\t\t\tthrow err;\n\t\t}\n\n\t\tp.log.warn(\"sqlite-vec failed to load; retrying viewer startup with embeddings disabled\");\n\t\tfor (const line of sqliteVecFailureDiagnostics(\n\t\t\terr,\n\t\t\tresolveDbPath(invocation.dbPath ?? undefined),\n\t\t)) {\n\t\t\tp.log.warn(`sqlite-vec diagnostic: ${line}`);\n\t\t}\n\t\tprocess.env.CODEMEM_EMBEDDING_DISABLED = \"1\";\n\t\tcloseStore();\n\t\tstore = getStore();\n\t\tp.log.warn(\"Embeddings disabled for this viewer process; raw-event ingestion remains active.\");\n\t}\n\n\tconst sweeper = new RawEventSweeper(store, { observer });\n\tsweeper.start();\n\n\tconst syncAbort = new AbortController();\n\tconst retentionAbort = new AbortController();\n\tconst config = invocation.configPath\n\t\t? readCodememConfigFileAtPath(invocation.configPath)\n\t\t: readCodememConfigFile();\n\tconst syncConfig = readCoordinatorSyncConfig(config);\n\tconst syncEnabled = syncConfig.syncEnabled;\n\tconst retentionRunner = new SyncRetentionRunner({\n\t\tdbPath: resolveDbPath(invocation.dbPath ?? undefined),\n\t\tsignal: retentionAbort.signal,\n\t});\n\tconst vectorMigrationRunner = new VectorModelMigrationRunner({\n\t\tdbPath: resolveDbPath(invocation.dbPath ?? undefined),\n\t});\n\tconst dedupKeyBackfillRunner = new DedupKeyBackfillRunner({\n\t\tdbPath: resolveDbPath(invocation.dbPath ?? undefined),\n\t});\n\tconst syncRuntimeStatus: {\n\t\tphase: \"starting\" | \"running\" | \"stopping\" | \"error\" | \"disabled\" | null;\n\t\tdetail: string | null;\n\t} = {\n\t\tphase: syncEnabled ? \"starting\" : \"disabled\",\n\t\tdetail: syncEnabled ? \"Waiting for viewer startup to finish\" : \"Sync is disabled\",\n\t};\n\n\tconst appOpts = {\n\t\tstoreFactory: () => store,\n\t\tsweeper,\n\t\tobserver,\n\t\tgetSyncRuntimeStatus: () => syncRuntimeStatus,\n\t};\n\tconst app = createApp(appOpts);\n\tconst dbPath = resolveDbPath(invocation.dbPath ?? undefined);\n\tconst pidPath = pidFilePath(dbPath);\n\n\t// Sync protocol listener — separate port, network-accessible for peers.\n\t// syncServerRef is never nulled after creation so shutdown always drains it.\n\tlet syncServer: ReturnType<typeof serve> | null = null;\n\tlet syncListenerReady = false;\n\tif (syncEnabled) {\n\t\tconst syncApp = createSyncApp(appOpts);\n\t\tsyncServer = serve(\n\t\t\t{ fetch: syncApp.fetch, hostname: syncConfig.syncHost, port: syncConfig.syncPort },\n\t\t\t(info) => {\n\t\t\t\tsyncListenerReady = true;\n\t\t\t\tp.log.step(`Sync protocol listening on http://${info.address}:${info.port}`);\n\t\t\t},\n\t\t);\n\t\tsyncServer.on(\"error\", (err: NodeJS.ErrnoException) => {\n\t\t\tif (!syncListenerReady && err.code === \"EADDRINUSE\") {\n\t\t\t\tp.log.warn(\n\t\t\t\t\t`Sync port ${syncConfig.syncPort} already in use; peer sync protocol unavailable`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tp.log.warn(`Sync listener error: ${err.message}`);\n\t\t\t}\n\t\t\t// Non-fatal — viewer continues. syncServer ref is kept for shutdown drain.\n\t\t});\n\t}\n\n\tconst server = serve(\n\t\t{ fetch: app.fetch, hostname: invocation.host, port: invocation.port },\n\t\t(info) => {\n\t\t\twriteFileSync(\n\t\t\t\tpidPath,\n\t\t\t\tJSON.stringify({ pid: process.pid, host: invocation.host, port: invocation.port }),\n\t\t\t\t\"utf-8\",\n\t\t\t);\n\t\t\tp.intro(\"codemem viewer\");\n\t\t\tp.log.success(`Listening on http://${info.address}:${info.port}`);\n\t\t\tp.log.info(`Database: ${preparedDb}`);\n\t\t\tp.log.step(\"Raw event sweeper started\");\n\t\t\tif (!isEmbeddingDisabled()) {\n\t\t\t\tvectorMigrationRunner.start();\n\t\t\t\tp.log.step(\"Vector maintenance runner started\");\n\t\t\t}\n\t\t\tif (hasPendingDedupKeyBackfill(store.db)) {\n\t\t\t\tdedupKeyBackfillRunner.start();\n\t\t\t\tp.log.step(\"Dedup-key maintenance runner started\");\n\t\t\t}\n\t\t\tif (syncConfig.syncRetentionEnabled) {\n\t\t\t\tretentionRunner.start();\n\t\t\t\tp.log.step(\"Retention maintenance runner started\");\n\t\t\t}\n\t\t\tif (syncEnabled) {\n\t\t\t\tconst syncStartDelayMs = 3000;\n\t\t\t\tp.log.step(`Sync daemon will start in background (${syncStartDelayMs / 1000}s delay)`);\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tsyncRuntimeStatus.phase = \"starting\";\n\t\t\t\t\tsyncRuntimeStatus.detail = \"Starting sync in background\";\n\t\t\t\t\tvoid runSyncDaemon({\n\t\t\t\t\t\tdbPath: resolveDbPath(invocation.dbPath ?? undefined),\n\t\t\t\t\t\tintervalS: syncConfig.syncIntervalS,\n\t\t\t\t\t\thost: syncConfig.syncHost,\n\t\t\t\t\t\tport: syncConfig.syncPort,\n\t\t\t\t\t\tsignal: syncAbort.signal,\n\t\t\t\t\t\tonPhaseChange: (phase) => {\n\t\t\t\t\t\t\tif (phase === \"running\") {\n\t\t\t\t\t\t\t\tsyncRuntimeStatus.phase = null;\n\t\t\t\t\t\t\t\tsyncRuntimeStatus.detail = null;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tsyncRuntimeStatus.phase = phase;\n\t\t\t\t\t\t\t\tsyncRuntimeStatus.detail =\n\t\t\t\t\t\t\t\t\tphase === \"starting\"\n\t\t\t\t\t\t\t\t\t\t? \"Running initial sync in background\"\n\t\t\t\t\t\t\t\t\t\t: \"Stopping sync daemon\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\t\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\t\t\t\t\t\tsyncRuntimeStatus.phase = \"error\";\n\t\t\t\t\t\t\tsyncRuntimeStatus.detail = msg;\n\t\t\t\t\t\t\tp.log.error(`Sync daemon failed: ${msg}`);\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.finally(() => {\n\t\t\t\t\t\t\tif (syncRuntimeStatus.phase !== \"error\") {\n\t\t\t\t\t\t\t\tsyncRuntimeStatus.phase = syncAbort.signal.aborted ? \"stopping\" : null;\n\t\t\t\t\t\t\t\tsyncRuntimeStatus.detail = syncAbort.signal.aborted ? \"Sync stopped\" : null;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t}, syncStartDelayMs).unref();\n\t\t\t}\n\t\t},\n\t);\n\n\tserver.on(\"error\", (err: NodeJS.ErrnoException) => {\n\t\tif (err.code === \"EADDRINUSE\") {\n\t\t\tp.log.warn(`Viewer already running at http://${invocation.host}:${invocation.port}`);\n\t\t} else {\n\t\t\tp.log.error(err.message);\n\t\t}\n\t\tprocess.exit(1);\n\t});\n\n\t// Periodic WAL checkpoint — keeps the WAL file bounded.\n\t// Without this, long-running viewer processes accumulate a WAL that can\n\t// grow to match the main DB size when concurrent readers hold it open.\n\tconst WAL_CHECKPOINT_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes\n\tconst walCheckpointTimer = setInterval(() => {\n\t\ttry {\n\t\t\tstore.db.pragma(\"wal_checkpoint(TRUNCATE)\");\n\t\t} catch (err) {\n\t\t\tp.log.warn(`WAL checkpoint failed: ${err instanceof Error ? err.message : String(err)}`);\n\t\t}\n\t}, WAL_CHECKPOINT_INTERVAL_MS);\n\twalCheckpointTimer.unref();\n\n\tconst shutdown = async () => {\n\t\tp.outro(\"shutting down\");\n\t\tclearInterval(walCheckpointTimer);\n\t\tsyncAbort.abort();\n\t\tretentionAbort.abort();\n\t\tawait sweeper.stop();\n\t\tawait dedupKeyBackfillRunner.stop();\n\t\tawait vectorMigrationRunner.stop();\n\t\tawait retentionRunner.stop();\n\n\t\t// Drain both listeners before closing the shared store.\n\t\tawait new Promise<void>((resolve) => {\n\t\t\tlet remaining = syncServer ? 2 : 1;\n\t\t\tconst done = () => {\n\t\t\t\tif (--remaining === 0) resolve();\n\t\t\t};\n\t\t\tsyncServer?.close(done);\n\t\t\tserver.close(done);\n\t\t}).catch(() => {\n\t\t\t// Best-effort drain — proceed to cleanup.\n\t\t});\n\n\t\ttry {\n\t\t\trmSync(pidPath);\n\t\t} catch {\n\t\t\t// ignore\n\t\t}\n\t\tcloseStore();\n\t\tprocess.exit(0);\n\t};\n\n\t// Force-exit safety net if graceful shutdown stalls for an unusually long time.\n\tconst forceShutdown = () => {\n\t\tsetTimeout(() => {\n\t\t\ttry {\n\t\t\t\trmSync(pidPath);\n\t\t\t} catch {\n\t\t\t\t// ignore\n\t\t\t}\n\t\t\tcloseStore();\n\t\t\tprocess.exit(1);\n\t\t}, 30000).unref();\n\t};\n\tprocess.on(\"SIGINT\", () => {\n\t\tforceShutdown();\n\t\tvoid shutdown();\n\t});\n\tprocess.on(\"SIGTERM\", () => {\n\t\tforceShutdown();\n\t\tvoid shutdown();\n\t});\n}\n\nasync function runServeInvocation(invocation: ResolvedServeInvocation): Promise<void> {\n\tconst dbPath = resolveDbPath(invocation.dbPath ?? undefined);\n\tif (invocation.mode === \"stop\" || invocation.mode === \"restart\") {\n\t\tconst result = await stopExistingViewer(dbPath, {\n\t\t\thost: invocation.host,\n\t\t\tport: invocation.port,\n\t\t});\n\t\tif (result.stopped) {\n\t\t\tp.intro(\"codemem viewer\");\n\t\t\tp.log.success(`Stopped viewer${result.pid ? ` (pid ${result.pid})` : \"\"}`);\n\t\t\tif (invocation.mode === \"stop\") {\n\t\t\t\tp.outro(\"done\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Wait for port to be fully released before restarting.\n\t\t\tconst released = await waitForPortRelease(invocation.host, invocation.port);\n\t\t\tif (!released) {\n\t\t\t\tp.log.warn(`Port ${invocation.port} still in use after stop — restart may fail`);\n\t\t\t}\n\t\t} else if (result.pid) {\n\t\t\tp.intro(\"codemem viewer\");\n\t\t\tp.log.error(`Viewer is still shutting down (pid ${result.pid})`);\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t} else if (invocation.mode === \"stop\") {\n\t\t\tp.intro(\"codemem viewer\");\n\t\t\tp.outro(\"No background viewer found\");\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif (invocation.mode === \"start\" || invocation.mode === \"restart\") {\n\t\tif (invocation.background) {\n\t\t\tawait startBackgroundViewer({ ...invocation, dbPath });\n\t\t\treturn;\n\t\t}\n\t\tawait startForegroundViewer({ ...invocation, dbPath });\n\t}\n}\n\nconst serveCmd = new Command(\"serve\")\n\t.configureHelp(helpStyle)\n\t.description(\"Run or manage the viewer\")\n\t.argument(\"[action]\", \"lifecycle action (start|stop|restart)\");\n\naddDbOption(serveCmd);\naddConfigOption(serveCmd);\naddViewerHostOptions(serveCmd);\n\n// Legacy lifecycle flags — hidden from --help, emit deprecation warnings when used.\nserveCmd.addOption(new Option(\"--background\", \"run viewer in background\").hideHelp());\nserveCmd.addOption(new Option(\"--foreground\", \"run viewer in foreground\").hideHelp());\nserveCmd.addOption(new Option(\"--stop\", \"stop background viewer\").hideHelp());\nserveCmd.addOption(new Option(\"--restart\", \"restart background viewer\").hideHelp());\n\nexport const serveCommand = serveCmd.action(\n\tasync (action: string | undefined, opts: LegacyServeOptions) => {\n\t\ttry {\n\t\t\t// Emit deprecation warnings for legacy flags\n\t\t\tif (opts.stop) emitDeprecationWarning(\"--stop\", \"codemem serve stop\");\n\t\t\tif (opts.restart) emitDeprecationWarning(\"--restart\", \"codemem serve restart\");\n\t\t\tif (opts.background) emitDeprecationWarning(\"--background\", \"codemem serve start\");\n\t\t\tif (opts.foreground)\n\t\t\t\temitDeprecationWarning(\"--foreground\", \"codemem serve start --foreground\");\n\n\t\t\tconst normalizedAction =\n\t\t\t\taction === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: action === \"start\" || action === \"stop\" || action === \"restart\"\n\t\t\t\t\t\t? (action as ServeAction)\n\t\t\t\t\t\t: null;\n\t\t\tif (normalizedAction === null) {\n\t\t\t\tp.log.error(`Unknown serve action: ${action}`);\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait runServeInvocation(resolveServeInvocation(normalizedAction, opts));\n\t\t} catch (err) {\n\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t},\n);\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { stripJsonComments, stripTrailingCommas } from \"@codemem/core\";\n\nexport function resolveOpencodeConfigPath(configDir: string): string {\n\tconst jsonPath = join(configDir, \"opencode.json\");\n\tif (existsSync(jsonPath)) return jsonPath;\n\tconst jsoncPath = join(configDir, \"opencode.jsonc\");\n\tif (existsSync(jsoncPath)) return jsoncPath;\n\treturn jsoncPath;\n}\n\nexport function loadJsoncConfig(path: string): Record<string, unknown> {\n\tif (!existsSync(path)) return {};\n\tconst raw = readFileSync(path, \"utf-8\");\n\ttry {\n\t\treturn JSON.parse(raw) as Record<string, unknown>;\n\t} catch {\n\t\tconst cleaned = stripTrailingCommas(stripJsonComments(raw));\n\t\treturn JSON.parse(cleaned) as Record<string, unknown>;\n\t}\n}\n\nexport function writeJsonConfig(path: string, data: Record<string, unknown>): void {\n\tmkdirSync(dirname(path), { recursive: true });\n\twriteFileSync(path, `${JSON.stringify(data, null, 2)}\\n`, \"utf-8\");\n}\n","/**\n * codemem setup — one-command installation for OpenCode plugin + MCP config.\n *\n * Replaces Python's install_plugin_cmd + install_mcp_cmd.\n *\n * What it does:\n * 1. Adds \"@codemem/opencode-plugin\" to the plugin array in ~/.config/opencode/opencode.jsonc\n * 2. Adds/updates the MCP entry in ~/.config/opencode/opencode.jsonc\n * 3. For Claude Code: installs MCP config and guides marketplace plugin install\n *\n * Designed to be safe to run repeatedly (idempotent unless --force).\n */\n\nimport { existsSync, rmSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { VERSION } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport { loadJsoncConfig, resolveOpencodeConfigPath, writeJsonConfig } from \"./setup-config.js\";\n\nfunction opencodeConfigDir(): string {\n\treturn join(homedir(), \".config\", \"opencode\");\n}\n\nfunction claudeConfigDir(): string {\n\treturn join(homedir(), \".claude\");\n}\n\n/** The npm package name used in the OpenCode plugin array. */\nconst OPENCODE_PLUGIN_SPEC = \"@codemem/opencode-plugin\";\nconst LEGACY_OPENCODE_PLUGIN_SPECS = [\"codemem\", \"@kunickiaj/codemem\"];\n\n// ---------------------------------------------------------------------------\n// Legacy migration helpers\n// ---------------------------------------------------------------------------\n\n/** Remove legacy copied plugin JS file from ~/.config/opencode/plugins/codemem.js */\nfunction migrateLegacyOpencodePlugin(): void {\n\tconst legacyPlugin = join(opencodeConfigDir(), \"plugins\", \"codemem.js\");\n\tconst legacyCompat = join(opencodeConfigDir(), \"lib\", \"compat.js\");\n\tif (existsSync(legacyPlugin)) {\n\t\ttry {\n\t\t\trmSync(legacyPlugin);\n\t\t\tp.log.step(\"Removed legacy copied plugin: ~/.config/opencode/plugins/codemem.js\");\n\t\t} catch {\n\t\t\tp.log.warn(\"Could not remove legacy plugin file — remove manually if needed\");\n\t\t}\n\t}\n\tif (existsSync(legacyCompat)) {\n\t\ttry {\n\t\t\trmSync(legacyCompat);\n\t\t\tp.log.step(\"Removed legacy compat lib: ~/.config/opencode/lib/compat.js\");\n\t\t} catch {\n\t\t\t// Non-fatal.\n\t\t}\n\t}\n}\n\n/** Detect and upgrade legacy uvx/uv-based MCP entries in OpenCode config. */\nfunction migrateLegacyOpencodeMcp(config: Record<string, unknown>): boolean {\n\tconst mcpConfig = config.mcp as Record<string, unknown> | undefined;\n\tif (!mcpConfig || typeof mcpConfig !== \"object\") return false;\n\tconst entry = mcpConfig.codemem as Record<string, unknown> | undefined;\n\tif (!entry || typeof entry !== \"object\") return false;\n\n\tconst command = entry.command;\n\tconst isLegacy =\n\t\t(Array.isArray(command) &&\n\t\t\tcommand.some((arg) => typeof arg === \"string\" && (arg === \"uvx\" || arg === \"uv\"))) ||\n\t\t(typeof command === \"string\" && (command === \"uvx\" || command === \"uv\"));\n\n\tif (isLegacy) {\n\t\tp.log.step(\"Upgrading legacy uvx MCP entry to npx\");\n\t\tmcpConfig.codemem = {\n\t\t\ttype: \"local\",\n\t\t\tcommand: [\"npx\", \"codemem\", \"mcp\"],\n\t\t\tenabled: true,\n\t\t};\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/** Detect and upgrade legacy uvx-based MCP entries in Claude settings. */\nfunction migrateLegacyClaudeMcp(settings: Record<string, unknown>): boolean {\n\tconst mcpServers = settings.mcpServers as Record<string, unknown> | undefined;\n\tif (!mcpServers || typeof mcpServers !== \"object\") return false;\n\tconst entry = mcpServers.codemem as Record<string, unknown> | undefined;\n\tif (!entry || typeof entry !== \"object\") return false;\n\n\tconst command = entry.command;\n\tconst args = entry.args;\n\tconst isLegacy =\n\t\t(typeof command === \"string\" && (command === \"uvx\" || command === \"uv\")) ||\n\t\t(Array.isArray(args) &&\n\t\t\targs.some(\n\t\t\t\t(arg) => typeof arg === \"string\" && (arg.startsWith(\"codemem==\") || arg === \"uvx\"),\n\t\t\t));\n\n\tif (isLegacy) {\n\t\tp.log.step(\"Upgrading legacy uvx Claude MCP entry to npx\");\n\t\tmcpServers.codemem = {\n\t\t\tcommand: \"npx\",\n\t\t\targs: [\"-y\", \"codemem\", \"mcp\"],\n\t\t};\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n// ---------------------------------------------------------------------------\n// Install functions\n// ---------------------------------------------------------------------------\n\nfunction installPlugin(force: boolean): boolean {\n\t// Clean up legacy copied plugin files first.\n\tmigrateLegacyOpencodePlugin();\n\n\tconst configPath = resolveOpencodeConfigPath(opencodeConfigDir());\n\tlet config: Record<string, unknown>;\n\ttry {\n\t\tconfig = loadJsoncConfig(configPath);\n\t} catch (err) {\n\t\tp.log.error(\n\t\t\t`Failed to parse ${configPath}: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t\treturn false;\n\t}\n\n\tlet plugins = config.plugin as unknown;\n\tif (!Array.isArray(plugins)) {\n\t\tplugins = [];\n\t}\n\n\tconst isManagedPluginSpec = (entry: unknown): entry is string =>\n\t\ttypeof entry === \"string\" &&\n\t\t[OPENCODE_PLUGIN_SPEC, ...LEGACY_OPENCODE_PLUGIN_SPECS].some(\n\t\t\t(spec) => entry === spec || entry.startsWith(`${spec}@`),\n\t\t);\n\n\tconst hasCanonicalSpec = (plugins as string[]).some(\n\t\t(entry) =>\n\t\t\ttypeof entry === \"string\" &&\n\t\t\t(entry === OPENCODE_PLUGIN_SPEC || entry.startsWith(`${OPENCODE_PLUGIN_SPEC}@`)),\n\t);\n\tconst hasLegacySpec = (plugins as string[]).some(\n\t\t(entry) =>\n\t\t\ttypeof entry === \"string\" &&\n\t\t\tLEGACY_OPENCODE_PLUGIN_SPECS.some((spec) => entry === spec || entry.startsWith(`${spec}@`)),\n\t);\n\n\tif (hasCanonicalSpec && !hasLegacySpec && !force) {\n\t\tp.log.info(`Plugin \"${OPENCODE_PLUGIN_SPEC}\" already in plugin array`);\n\t\treturn true;\n\t}\n\n\tplugins = (plugins as string[]).filter((entry) => !isManagedPluginSpec(entry));\n\tif (hasLegacySpec) {\n\t\tp.log.step(\"Removed legacy OpenCode plugin spec(s): codemem / @kunickiaj/codemem\");\n\t}\n\n\t(plugins as string[]).push(OPENCODE_PLUGIN_SPEC);\n\tconfig.plugin = plugins;\n\n\ttry {\n\t\twriteJsonConfig(configPath, config);\n\t\tp.log.success(`Plugin \"${OPENCODE_PLUGIN_SPEC}\" added to ${configPath}`);\n\t} catch (err) {\n\t\tp.log.error(\n\t\t\t`Failed to write ${configPath}: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nfunction installMcp(force: boolean): boolean {\n\tconst configPath = resolveOpencodeConfigPath(opencodeConfigDir());\n\tlet config: Record<string, unknown>;\n\ttry {\n\t\tconfig = loadJsoncConfig(configPath);\n\t} catch (err) {\n\t\tp.log.error(\n\t\t\t`Failed to parse ${configPath}: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t\treturn false;\n\t}\n\n\tlet mcpConfig = config.mcp as Record<string, unknown> | undefined;\n\tif (mcpConfig == null || typeof mcpConfig !== \"object\" || Array.isArray(mcpConfig)) {\n\t\tmcpConfig = {};\n\t}\n\n\t// Auto-upgrade legacy uvx-based MCP entries.\n\tconst migrated = migrateLegacyOpencodeMcp(config);\n\n\tif (\"codemem\" in mcpConfig && !force && !migrated) {\n\t\tp.log.info(`MCP entry already exists in ${configPath}`);\n\t\treturn true;\n\t}\n\n\tif (!migrated) {\n\t\tmcpConfig.codemem = {\n\t\t\ttype: \"local\",\n\t\t\tcommand: [\"npx\", \"codemem\", \"mcp\"],\n\t\t\tenabled: true,\n\t\t};\n\t\tconfig.mcp = mcpConfig;\n\t}\n\n\ttry {\n\t\twriteJsonConfig(configPath, config);\n\t\tp.log.success(`MCP entry installed: ${configPath}`);\n\t} catch (err) {\n\t\tp.log.error(\n\t\t\t`Failed to write ${configPath}: ${err instanceof Error ? err.message : String(err)}`,\n\t\t);\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nfunction isClaudeHooksPluginInstalled(): boolean {\n\t// Check if the marketplace hooks plugin is installed by looking for\n\t// the hooks directory — NOT for MCP config (which we write ourselves).\n\tconst pluginDir = join(claudeConfigDir(), \"plugins\", \"codemem\");\n\tif (existsSync(pluginDir)) return true;\n\t// Also check for hook scripts installed by the marketplace plugin.\n\tconst hooksJson = join(pluginDir, \"hooks\", \"hooks.json\");\n\tif (existsSync(hooksJson)) return true;\n\treturn false;\n}\n\nfunction installClaudeMcp(force: boolean): boolean {\n\tconst settingsPath = join(claudeConfigDir(), \"settings.json\");\n\tlet settings: Record<string, unknown>;\n\ttry {\n\t\tsettings = loadJsoncConfig(settingsPath);\n\t} catch {\n\t\tsettings = {};\n\t}\n\n\tlet mcpServers = settings.mcpServers as Record<string, unknown> | undefined;\n\tif (mcpServers == null || typeof mcpServers !== \"object\" || Array.isArray(mcpServers)) {\n\t\tmcpServers = {};\n\t}\n\n\t// Auto-upgrade legacy uvx-based Claude MCP entries.\n\tconst migrated = migrateLegacyClaudeMcp(settings);\n\n\tif (\"codemem\" in mcpServers && !force && !migrated) {\n\t\tp.log.info(`Claude MCP entry already exists in ${settingsPath}`);\n\t} else {\n\t\tif (!migrated) {\n\t\t\tmcpServers.codemem = {\n\t\t\t\tcommand: \"npx\",\n\t\t\t\targs: [\"-y\", \"codemem\", \"mcp\"],\n\t\t\t};\n\t\t\tsettings.mcpServers = mcpServers;\n\t\t}\n\n\t\ttry {\n\t\t\twriteJsonConfig(settingsPath, settings);\n\t\t\tp.log.success(`Claude MCP entry installed: ${settingsPath}`);\n\t\t} catch (err) {\n\t\t\tp.log.error(\n\t\t\t\t`Failed to write ${settingsPath}: ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// Guide marketplace plugin install for hooks integration.\n\tif (!isClaudeHooksPluginInstalled() || force) {\n\t\tp.log.info(\"To install the Claude Code hooks plugin, run in Claude Code:\");\n\t\tp.log.info(\" /plugin marketplace add kunickiaj/codemem\");\n\t\tp.log.info(\" /plugin install codemem\");\n\t\tp.log.info(\"\");\n\t\tp.log.info(\"To update an existing install:\");\n\t\tp.log.info(\" /plugin marketplace update codemem-marketplace\");\n\t} else {\n\t\tp.log.info(\"Claude Code hooks plugin appears to be installed\");\n\t}\n\n\treturn true;\n}\n\nexport const setupCommand = new Command(\"setup\")\n\t.configureHelp(helpStyle)\n\t.description(\"Install codemem plugin + MCP config for OpenCode and Claude Code\")\n\t.option(\"--force\", \"overwrite existing installations\")\n\t.option(\"--opencode-only\", \"only install for OpenCode\")\n\t.option(\"--claude-only\", \"only install for Claude Code\")\n\t.action((opts: { force?: boolean; opencodeOnly?: boolean; claudeOnly?: boolean }) => {\n\t\tp.intro(`codemem setup v${VERSION}`);\n\t\tconst force = opts.force ?? false;\n\t\tlet ok = true;\n\n\t\tif (!opts.claudeOnly) {\n\t\t\tp.log.step(\"Installing OpenCode plugin...\");\n\t\t\tok = installPlugin(force) && ok;\n\t\t\tp.log.step(\"Installing OpenCode MCP config...\");\n\t\t\tok = installMcp(force) && ok;\n\t\t}\n\n\t\tif (!opts.opencodeOnly) {\n\t\t\tp.log.step(\"Installing Claude Code MCP config...\");\n\t\t\tok = installClaudeMcp(force) && ok;\n\t\t}\n\n\t\tif (ok) {\n\t\t\tp.outro(\"Setup complete — restart your editor to load the plugin\");\n\t\t} else {\n\t\t\tp.outro(\"Setup completed with warnings\");\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t});\n","import * as p from \"@clack/prompts\";\nimport { MemoryStore, resolveDbPath } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddDbOption,\n\taddJsonOption,\n\ttype DbOpts,\n\ttype JsonOpts,\n\tresolveDbOpt,\n} from \"../shared-options.js\";\n\nfunction fmtPct(n: number): string {\n\treturn `${Math.round(n * 100)}%`;\n}\n\nfunction fmtTokens(n: number): string {\n\tif (n >= 1_000_000_000) return `~${(n / 1_000_000_000).toFixed(1)}B`;\n\tif (n >= 1_000_000) return `~${(n / 1_000_000).toFixed(1)}M`;\n\tif (n >= 1_000) return `~${(n / 1_000).toFixed(0)}K`;\n\treturn `${n}`;\n}\n\nconst statsCmd = new Command(\"stats\")\n\t.configureHelp(helpStyle)\n\t.description(\"Show database statistics\");\n\naddDbOption(statsCmd);\naddJsonOption(statsCmd);\n\nexport const statsCommand = statsCmd.action((opts: DbOpts & JsonOpts) => {\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\ttry {\n\t\tconst result = store.stats();\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\t\treturn;\n\t\t}\n\n\t\tconst db = result.database;\n\t\tconst sizeMb = (db.size_bytes / 1_048_576).toFixed(1);\n\n\t\tp.intro(\"codemem stats\");\n\n\t\tp.log.info([`Path: ${db.path}`, `Size: ${sizeMb} MB`].join(\"\\n\"));\n\n\t\tp.log.success(\n\t\t\t[\n\t\t\t\t`Sessions: ${db.sessions.toLocaleString()}`,\n\t\t\t\t`Memories: ${db.active_memory_items.toLocaleString()} active / ${db.memory_items.toLocaleString()} total`,\n\t\t\t\t`Tags: ${db.tags_filled.toLocaleString()} filled (${fmtPct(db.tags_coverage)} of active)`,\n\t\t\t\t`Artifacts: ${db.artifacts.toLocaleString()}`,\n\t\t\t\t`Vectors: ${db.vector_rows.toLocaleString()} (${fmtPct(db.vector_coverage)} coverage)`,\n\t\t\t\t`Raw events: ${db.raw_events.toLocaleString()}`,\n\t\t\t].join(\"\\n\"),\n\t\t);\n\n\t\tif (result.usage.events.length > 0) {\n\t\t\tconst lines = result.usage.events.map((e: (typeof result.usage.events)[number]) => {\n\t\t\t\tconst parts = [`${e.event}: ${e.count.toLocaleString()}`];\n\t\t\t\tif (e.tokens_read > 0) parts.push(`read ${fmtTokens(e.tokens_read)} tokens`);\n\t\t\t\tif (e.tokens_saved > 0) parts.push(`est. saved ${fmtTokens(e.tokens_saved)} tokens`);\n\t\t\t\treturn ` ${parts.join(\", \")}`;\n\t\t\t});\n\n\t\t\tconst t = result.usage.totals;\n\t\t\tlines.push(\"\");\n\t\t\tlines.push(\n\t\t\t\t` Total: ${t.events.toLocaleString()} events, read ${fmtTokens(t.tokens_read)} tokens, est. saved ${fmtTokens(t.tokens_saved)} tokens`,\n\t\t\t);\n\n\t\t\tp.log.step(`Usage\\n${lines.join(\"\\n\")}`);\n\t\t}\n\n\t\tp.outro(\"done\");\n\t} finally {\n\t\tstore.close();\n\t}\n});\n","import { resolveDbOpt } from \"../shared-options.js\";\n\nexport interface SyncAttemptRow {\n\tpeer_device_id: string;\n\tok: number;\n\tops_in: number;\n\tops_out: number;\n\terror: string | null;\n\tfinished_at: string | null;\n}\n\nexport function formatSyncAttempt(row: SyncAttemptRow): string {\n\tconst status = row.ok ? \"ok\" : \"error\";\n\tconst error = String(row.error || \"\");\n\tconst suffix = error ? ` | ${error}` : \"\";\n\treturn `${row.peer_device_id}|${status}|in=${row.ops_in}|out=${row.ops_out}|${row.finished_at ?? \"\"}${suffix}`;\n}\n\nexport interface SyncLifecycleOptions {\n\tdb?: string;\n\tdbPath?: string;\n\tconfig?: string;\n\thost?: string;\n\tport?: string;\n\tuser?: boolean;\n\tsystem?: boolean;\n}\n\nexport function buildServeLifecycleArgs(\n\taction: \"start\" | \"stop\" | \"restart\",\n\topts: SyncLifecycleOptions,\n\tscriptPath: string,\n\texecArgv: string[] = [],\n): string[] {\n\tif (!scriptPath) throw new Error(\"Unable to resolve CLI entrypoint for sync lifecycle command\");\n\tconst args = [...execArgv, scriptPath, \"serve\"];\n\tif (action === \"start\") {\n\t\targs.push(\"--restart\");\n\t} else if (action === \"stop\") {\n\t\targs.push(\"--stop\");\n\t} else {\n\t\targs.push(\"--restart\");\n\t}\n\tconst dbResolved = resolveDbOpt(opts);\n\tif (dbResolved) args.push(\"--db-path\", dbResolved);\n\tif (opts.config) args.push(\"--config\", opts.config);\n\tif (opts.host) args.push(\"--host\", opts.host);\n\tif (opts.port) args.push(\"--port\", opts.port);\n\treturn args;\n}\n\nexport function formatSyncOnceResult(\n\tpeerDeviceId: string,\n\tresult: { ok: boolean; error?: string },\n): string {\n\tif (result.ok) return `- ${peerDeviceId}: ok`;\n\tconst suffix = result.error ? `: ${result.error}` : \"\";\n\treturn `- ${peerDeviceId}: error${suffix}`;\n}\n\nexport function parseProjectList(value: string | undefined): string[] {\n\tif (!value) return [];\n\treturn value\n\t\t.split(\",\")\n\t\t.map((item) => item.trim())\n\t\t.filter(Boolean);\n}\n\ntype InterfaceMap = Record<\n\tstring,\n\tArray<{ address: string; family?: string | number; internal?: boolean }> | undefined\n>;\n\nexport function collectAdvertiseAddresses(\n\texplicitAddress: string | null,\n\tconfiguredHost: string | null,\n\tport: number,\n\tinterfaces: InterfaceMap,\n): string[] {\n\tif (explicitAddress && ![\"auto\", \"default\"].includes(explicitAddress.toLowerCase())) {\n\t\treturn [explicitAddress];\n\t}\n\tif (configuredHost && configuredHost !== \"0.0.0.0\") {\n\t\treturn [`${configuredHost}:${port}`];\n\t}\n\tconst addresses = Object.values(interfaces)\n\t\t.flatMap((entries) => entries ?? [])\n\t\t.filter((entry) => !entry.internal)\n\t\t.map((entry) => entry.address)\n\t\t.filter((address) => address && address !== \"127.0.0.1\" && address !== \"::1\")\n\t\t.map((address) => `${address}:${port}`);\n\treturn [...new Set(addresses)];\n}\n","/**\n * Sync CLI commands — enable/disable/status/peers/connect.\n */\n\nimport { spawn } from \"node:child_process\";\nimport { readFileSync } from \"node:fs\";\nimport net from \"node:net\";\nimport { networkInterfaces } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport * as p from \"@clack/prompts\";\nimport {\n\tapplyBootstrapSnapshot,\n\tbuildAuthHeaders,\n\tbuildBaseUrl,\n\tensureDeviceIdentity,\n\tfetchAllSnapshotPages,\n\tfingerprintPublicKey,\n\thasUnsyncedSharedMemoryChanges,\n\tloadPublicKey,\n\tMemoryStore,\n\treadCodememConfigFile,\n\treadCodememConfigFileAtPath,\n\treadCoordinatorSyncConfig,\n\trequestJson,\n\tresolveDbPath,\n\trunSyncPass,\n\tschema,\n\tsetPeerProjectFilter,\n\tsyncPassPreflight,\n\tupdatePeerAddresses,\n\twriteCodememConfigFile,\n} from \"@codemem/core\";\nimport { Command, Option } from \"commander\";\nimport { desc, eq } from \"drizzle-orm\";\nimport { drizzle } from \"drizzle-orm/better-sqlite3\";\nimport { helpStyle } from \"../help-style.js\";\nimport {\n\taddConfigOption,\n\taddDbOption,\n\taddJsonOption,\n\taddLegacyServiceFlags,\n\taddViewerHostOptions,\n\temitDeprecationWarning,\n\temitJsonError,\n\tresolveDbOpt,\n} from \"../shared-options.js\";\nimport { buildCoordinatorCommand } from \"./coordinator.js\";\nimport {\n\tbuildServeLifecycleArgs,\n\tcollectAdvertiseAddresses,\n\tformatSyncAttempt,\n\tformatSyncOnceResult,\n\tparseProjectList,\n\ttype SyncLifecycleOptions,\n} from \"./sync-helpers.js\";\n\nfunction readCliConfig(configPath?: string): Record<string, unknown> {\n\treturn configPath ? readCodememConfigFileAtPath(configPath) : readCodememConfigFile();\n}\n\nfunction writeCliConfig(config: Record<string, unknown>, configPath?: string): string {\n\treturn writeCodememConfigFile(config, configPath || undefined);\n}\n\nfunction parseAttemptsLimit(value: string): number {\n\tif (!/^\\d+$/.test(value.trim())) {\n\t\tthrow new Error(`Invalid --limit: ${value}`);\n\t}\n\treturn Number.parseInt(value, 10);\n}\n\nfunction parsePositiveIntegerOption(\n\tvalue: string | undefined,\n\tflagName: string,\n): number | undefined {\n\tif (value == null) return undefined;\n\tconst trimmed = value.trim();\n\tif (!/^\\d+$/.test(trimmed)) {\n\t\tthrow new Error(`Invalid ${flagName}: ${value}`);\n\t}\n\treturn Number.parseInt(trimmed, 10);\n}\n\ninterface SyncPairOptions {\n\taccept?: string;\n\tacceptFile?: string;\n\tpayloadOnly?: boolean;\n\tname?: string;\n\taddress?: string;\n\tinclude?: string;\n\texclude?: string;\n\tall?: boolean;\n\tdefault?: boolean;\n\tconfig?: string;\n\tdb?: string;\n\tdbPath?: string;\n\tjson?: boolean;\n}\n\nfunction resolvePeerMatch(\n\tdb: ReturnType<typeof drizzle>,\n\tpeerRef: string,\n): { peer_device_id: string; name: string | null } | null | \"ambiguous\" {\n\tconst trimmed = peerRef.trim();\n\tif (!trimmed) return null;\n\tconst byId = db\n\t\t.select({ peer_device_id: schema.syncPeers.peer_device_id, name: schema.syncPeers.name })\n\t\t.from(schema.syncPeers)\n\t\t.where(eq(schema.syncPeers.peer_device_id, trimmed))\n\t\t.get();\n\tif (byId) return byId;\n\tconst byName = db\n\t\t.select({ peer_device_id: schema.syncPeers.peer_device_id, name: schema.syncPeers.name })\n\t\t.from(schema.syncPeers)\n\t\t.where(eq(schema.syncPeers.name, trimmed))\n\t\t.all();\n\tif (byName.length > 1) return \"ambiguous\";\n\treturn byName[0] ?? null;\n}\n\nasync function portOpen(host: string, port: number): Promise<boolean> {\n\treturn new Promise((resolve) => {\n\t\tconst socket = net.createConnection({ host, port });\n\t\tconst done = (ok: boolean) => {\n\t\t\tsocket.removeAllListeners();\n\t\t\tsocket.destroy();\n\t\t\tresolve(ok);\n\t\t};\n\t\tsocket.setTimeout(300);\n\t\tsocket.once(\"connect\", () => done(true));\n\t\tsocket.once(\"timeout\", () => done(false));\n\t\tsocket.once(\"error\", () => done(false));\n\t});\n}\n\nfunction readViewerBinding(dbPath: string): { host: string; port: number } | null {\n\ttry {\n\t\tconst raw = readFileSync(join(dirname(dbPath), \"viewer.pid\"), \"utf8\");\n\t\tconst parsed = JSON.parse(raw) as Partial<{ host: string; port: number }>;\n\t\tif (typeof parsed.host === \"string\" && typeof parsed.port === \"number\") {\n\t\t\treturn { host: parsed.host, port: parsed.port };\n\t\t}\n\t} catch {\n\t\t// ignore malformed or missing pidfile\n\t}\n\treturn null;\n}\n\nfunction parseStoredAddressEndpoint(value: string): { host: string; port: number } | null {\n\ttry {\n\t\tconst normalized = value.includes(\"://\") ? value : `http://${value}`;\n\t\tconst url = new URL(normalized);\n\t\tconst port = url.port ? Number.parseInt(url.port, 10) : url.protocol === \"https:\" ? 443 : 80;\n\t\tif (!url.hostname || !Number.isFinite(port)) return null;\n\t\treturn { host: url.hostname, port };\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function runServeLifecycle(\n\taction: \"start\" | \"stop\" | \"restart\",\n\topts: SyncLifecycleOptions,\n): Promise<void> {\n\tif (opts.user === false || opts.system === true) {\n\t\tp.log.warn(\n\t\t\t\"TS sync lifecycle currently manages the local viewer process, not separate user/system services.\",\n\t\t);\n\t}\n\tif (action === \"start\") {\n\t\tconst config = readCoordinatorSyncConfig(readCliConfig(opts.config));\n\t\tif (config.syncEnabled !== true) {\n\t\t\tp.log.error(\"Sync is disabled. Run `codemem sync enable` first.\");\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\t\t// Don't pass sync_host/sync_port as viewer bind values.\n\t\t// The viewer binds its own host/port (default 127.0.0.1:38888)\n\t\t// and the sync protocol listener reads sync_host/sync_port\n\t\t// internally from readCoordinatorSyncConfig().\n\t}\n\tconst dbResolved = resolveDbOpt(opts);\n\tconst args = buildServeLifecycleArgs(action, opts, process.argv[1] ?? \"\", process.execArgv);\n\tawait new Promise<void>((resolve, reject) => {\n\t\tconst child = spawn(process.execPath, args, {\n\t\t\tcwd: process.cwd(),\n\t\t\tstdio: \"inherit\",\n\t\t\tenv: {\n\t\t\t\t...process.env,\n\t\t\t\t...(dbResolved ? { CODEMEM_DB: dbResolved } : {}),\n\t\t\t\t...(opts.config ? { CODEMEM_CONFIG: opts.config } : {}),\n\t\t\t},\n\t\t});\n\t\tchild.once(\"error\", reject);\n\t\tchild.once(\"exit\", (code: number | null) => {\n\t\t\tif (code && code !== 0) {\n\t\t\t\tprocess.exitCode = code;\n\t\t\t}\n\t\t\tresolve();\n\t\t});\n\t});\n}\n\nexport const syncCommand = new Command(\"sync\")\n\t.configureHelp(helpStyle)\n\t.description(\"Sync configuration and peer management\");\n\n// ---- sync attempts ----\n\nconst attemptsCmd = new Command(\"attempts\")\n\t.configureHelp(helpStyle)\n\t.description(\"Show recent sync attempts\")\n\t.option(\"--limit <n>\", \"max attempts\", \"10\");\naddDbOption(attemptsCmd);\naddJsonOption(attemptsCmd);\nattemptsCmd.action((opts: { db?: string; dbPath?: string; limit: string; json?: boolean }) => {\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\ttry {\n\t\tconst d = drizzle(store.db, { schema });\n\t\tconst limit = parseAttemptsLimit(opts.limit);\n\t\tconst rows = d\n\t\t\t.select({\n\t\t\t\tpeer_device_id: schema.syncAttempts.peer_device_id,\n\t\t\t\tok: schema.syncAttempts.ok,\n\t\t\t\tops_in: schema.syncAttempts.ops_in,\n\t\t\t\tops_out: schema.syncAttempts.ops_out,\n\t\t\t\terror: schema.syncAttempts.error,\n\t\t\t\tfinished_at: schema.syncAttempts.finished_at,\n\t\t\t})\n\t\t\t.from(schema.syncAttempts)\n\t\t\t.orderBy(desc(schema.syncAttempts.finished_at))\n\t\t\t.limit(limit)\n\t\t\t.all();\n\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify(rows, null, 2));\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const row of rows) {\n\t\t\tconsole.log(formatSyncAttempt(row));\n\t\t}\n\t} finally {\n\t\tstore.close();\n\t}\n});\nsyncCommand.addCommand(attemptsCmd);\n\n// ---- sync start/stop/restart [deprecated] ----\n\nfunction addDeprecatedLifecycleCommand(action: \"start\" | \"stop\" | \"restart\") {\n\tconst cmd = new Command(action)\n\t\t.configureHelp(helpStyle)\n\t\t.description(`[deprecated] ${action} sync daemon — use 'codemem serve ${action}'`);\n\taddDbOption(cmd);\n\taddConfigOption(cmd);\n\taddViewerHostOptions(cmd);\n\taddLegacyServiceFlags(cmd);\n\tcmd.action(async (opts: SyncLifecycleOptions) => {\n\t\temitDeprecationWarning(`codemem sync ${action}`, `codemem serve ${action}`);\n\t\tawait runServeLifecycle(action, opts);\n\t});\n\tsyncCommand.addCommand(cmd, { hidden: true });\n}\n\naddDeprecatedLifecycleCommand(\"start\");\naddDeprecatedLifecycleCommand(\"stop\");\naddDeprecatedLifecycleCommand(\"restart\");\n\n// ---- sync once ----\n\nconst onceCmd = new Command(\"once\")\n\t.configureHelp(helpStyle)\n\t.description(\"Run a single sync pass\")\n\t.option(\"--peer <peer>\", \"peer device id or name\");\naddDbOption(onceCmd);\naddJsonOption(onceCmd);\nonceCmd.action(async (opts: { db?: string; dbPath?: string; peer?: string; json?: boolean }) => {\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\ttry {\n\t\tconst keysDir = process.env.CODEMEM_KEYS_DIR?.trim() || undefined;\n\t\tsyncPassPreflight(store.db);\n\t\tconst d = drizzle(store.db, { schema });\n\t\tconst rows = opts.peer\n\t\t\t? (() => {\n\t\t\t\t\tconst deviceMatches = d\n\t\t\t\t\t\t.select({ peer_device_id: schema.syncPeers.peer_device_id })\n\t\t\t\t\t\t.from(schema.syncPeers)\n\t\t\t\t\t\t.where(eq(schema.syncPeers.peer_device_id, opts.peer))\n\t\t\t\t\t\t.all();\n\t\t\t\t\tif (deviceMatches.length > 0) return deviceMatches;\n\t\t\t\t\tconst nameMatches = d\n\t\t\t\t\t\t.select({ peer_device_id: schema.syncPeers.peer_device_id })\n\t\t\t\t\t\t.from(schema.syncPeers)\n\t\t\t\t\t\t.where(eq(schema.syncPeers.name, opts.peer))\n\t\t\t\t\t\t.all();\n\t\t\t\t\tif (nameMatches.length > 1) {\n\t\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\t\temitJsonError(\"ambiguous_peer\", `Peer name is ambiguous: ${opts.peer}`);\n\t\t\t\t\t\t\treturn [];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tp.log.error(`Peer name is ambiguous: ${opts.peer}`);\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\t\t\t\t\treturn nameMatches;\n\t\t\t\t})()\n\t\t\t: d.select({ peer_device_id: schema.syncPeers.peer_device_id }).from(schema.syncPeers).all();\n\n\t\tif (rows.length === 0) {\n\t\t\tif (process.exitCode) return; // already set by ambiguous peer\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\"no_peers\", \"No peers available for sync\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.warn(\"No peers available for sync\");\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\n\t\tlet hadFailure = false;\n\t\tconst results: Array<{\n\t\t\tpeer_device_id: string;\n\t\t\tok: boolean;\n\t\t\terror?: string;\n\t\t}> = [];\n\t\tfor (const row of rows) {\n\t\t\tconst result = await runSyncPass(store.db, row.peer_device_id, { keysDir });\n\t\t\tif (!result.ok) hadFailure = true;\n\t\t\tresults.push({\n\t\t\t\tpeer_device_id: row.peer_device_id,\n\t\t\t\tok: result.ok,\n\t\t\t\t...(result.error ? { error: result.error } : {}),\n\t\t\t});\n\t\t\tif (!opts.json) {\n\t\t\t\tconsole.log(formatSyncOnceResult(row.peer_device_id, result));\n\t\t\t}\n\t\t}\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify({ ok: !hadFailure, results }, null, 2));\n\t\t}\n\t\tif (hadFailure) {\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t} finally {\n\t\tstore.close();\n\t}\n});\nsyncCommand.addCommand(onceCmd);\n\n// ---- sync pair ----\n\nconst pairCmd = new Command(\"pair\")\n\t.configureHelp(helpStyle)\n\t.description(\"Print pairing payload or accept a peer payload\")\n\t.option(\"--accept <json>\", \"accept pairing payload JSON from another device\")\n\t.option(\"--accept-file <path>\", \"accept pairing payload from file path, or '-' for stdin\")\n\t.option(\"--payload-only\", \"when generating pairing payload, print JSON only\")\n\t.option(\"--name <name>\", \"label for the peer\")\n\t.option(\"--address <host:port>\", \"override peer address (host:port)\")\n\t.option(\"--include <projects>\", \"outbound-only allowlist for accepted peer\")\n\t.option(\"--exclude <projects>\", \"outbound-only blocklist for accepted peer\")\n\t.option(\"--all\", \"with --accept, push all projects to that peer\")\n\t.option(\"--default\", \"with --accept, use default/global push filters\");\naddDbOption(pairCmd);\naddConfigOption(pairCmd);\naddJsonOption(pairCmd);\npairCmd.action(async (opts: SyncPairOptions) => {\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\ttry {\n\t\tconst acceptModeRequested = opts.accept != null || opts.acceptFile != null;\n\t\tif (opts.payloadOnly && acceptModeRequested) {\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\n\t\t\t\t\t\"usage_error\",\n\t\t\t\t\t\"--payload-only cannot be combined with --accept or --accept-file\",\n\t\t\t\t\t2,\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.error(\"--payload-only cannot be combined with --accept or --accept-file\");\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\t\tif (opts.accept && opts.acceptFile) {\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\"usage_error\", \"Use only one of --accept or --accept-file\", 2);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.error(\"Use only one of --accept or --accept-file\");\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\n\t\tlet acceptText = opts.accept;\n\t\tif (opts.acceptFile) {\n\t\t\ttry {\n\t\t\t\tacceptText =\n\t\t\t\t\topts.acceptFile === \"-\"\n\t\t\t\t\t\t? await new Promise<string>((resolve, reject) => {\n\t\t\t\t\t\t\t\tlet text = \"\";\n\t\t\t\t\t\t\t\tprocess.stdin.setEncoding(\"utf8\");\n\t\t\t\t\t\t\t\tprocess.stdin.on(\"data\", (chunk) => {\n\t\t\t\t\t\t\t\t\ttext += chunk;\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tprocess.stdin.on(\"end\", () => resolve(text));\n\t\t\t\t\t\t\t\tprocess.stdin.on(\"error\", reject);\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t: readFileSync(opts.acceptFile, \"utf8\");\n\t\t\t} catch (error) {\n\t\t\t\tconst msg =\n\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t? `Failed to read pairing payload from ${opts.acceptFile}: ${error.message}`\n\t\t\t\t\t\t: `Failed to read pairing payload from ${opts.acceptFile}`;\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"read_error\", msg);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(msg);\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (acceptModeRequested && !(acceptText ?? \"\").trim()) {\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\n\t\t\t\t\t\"usage_error\",\n\t\t\t\t\t\"Empty pairing payload; provide JSON via --accept or --accept-file\",\n\t\t\t\t\t2,\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.error(\"Empty pairing payload; provide JSON via --accept or --accept-file\");\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\n\t\tif (!acceptText && (opts.include || opts.exclude || opts.all || opts.default)) {\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\n\t\t\t\t\t\"usage_error\",\n\t\t\t\t\t\"Project filters are outbound-only and must be set on the device running --accept\",\n\t\t\t\t\t2,\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.error(\n\t\t\t\t\"Project filters are outbound-only and must be set on the device running --accept\",\n\t\t\t);\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\n\t\tif (acceptText?.trim()) {\n\t\t\tif (opts.all && opts.default) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"usage_error\", \"Use only one of --all or --default\", 2);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(\"Use only one of --all or --default\");\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ((opts.all || opts.default) && (opts.include || opts.exclude)) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\n\t\t\t\t\t\t\"usage_error\",\n\t\t\t\t\t\t\"--include/--exclude cannot be combined with --all/--default\",\n\t\t\t\t\t\t2,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(\"--include/--exclude cannot be combined with --all/--default\");\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet payload: Record<string, unknown>;\n\t\t\ttry {\n\t\t\t\tpayload = JSON.parse(acceptText) as Record<string, unknown>;\n\t\t\t} catch (error) {\n\t\t\t\tconst msg =\n\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t? `Invalid pairing payload: ${error.message}`\n\t\t\t\t\t\t: \"Invalid pairing payload\";\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"invalid_payload\", msg);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(msg);\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst deviceId = String(payload.device_id || \"\").trim();\n\t\t\tconst fingerprint = String(payload.fingerprint || \"\").trim();\n\t\t\tconst publicKey = String(payload.public_key || \"\").trim();\n\t\t\tconst resolvedAddresses = opts.address?.trim()\n\t\t\t\t? [opts.address.trim()]\n\t\t\t\t: Array.isArray(payload.addresses)\n\t\t\t\t\t? (payload.addresses as unknown[])\n\t\t\t\t\t\t\t.filter((item): item is string => typeof item === \"string\" && item.trim().length > 0)\n\t\t\t\t\t\t\t.map((item) => item.trim())\n\t\t\t\t\t: [];\n\t\t\tif (!deviceId || !fingerprint || !publicKey || resolvedAddresses.length === 0) {\n\t\t\t\tconst msg = \"Pairing payload missing device_id, fingerprint, public_key, or addresses\";\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"invalid_payload\", msg);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(msg);\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (fingerprintPublicKey(publicKey) !== fingerprint) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"fingerprint_mismatch\", \"Pairing payload fingerprint mismatch\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tp.log.error(\"Pairing payload fingerprint mismatch\");\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tupdatePeerAddresses(store.db, deviceId, resolvedAddresses, {\n\t\t\t\tname: opts.name,\n\t\t\t\tpinnedFingerprint: fingerprint,\n\t\t\t\tpublicKey,\n\t\t\t});\n\n\t\t\tif (opts.default) {\n\t\t\t\tsetPeerProjectFilter(store.db, deviceId, { include: null, exclude: null });\n\t\t\t} else if (opts.all || opts.include || opts.exclude) {\n\t\t\t\tsetPeerProjectFilter(store.db, deviceId, {\n\t\t\t\t\tinclude: opts.all ? [] : parseProjectList(opts.include),\n\t\t\t\t\texclude: opts.all ? [] : parseProjectList(opts.exclude),\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(JSON.stringify({ ok: true, peer_device_id: deviceId }));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.success(`Paired with ${deviceId}`);\n\t\t\treturn;\n\t\t}\n\n\t\tconst keysDir = process.env.CODEMEM_KEYS_DIR?.trim() || undefined;\n\t\tconst [deviceId, fingerprint] = ensureDeviceIdentity(store.db, { keysDir });\n\t\tconst publicKey = loadPublicKey(keysDir);\n\t\tif (!publicKey) {\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\"missing_key\", \"Public key missing\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.error(\"Public key missing\");\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\n\t\tconst config = readCliConfig(opts.config);\n\t\tconst explicitAddress = opts.address?.trim();\n\t\tconst configuredHost = typeof config.sync_host === \"string\" ? config.sync_host : null;\n\t\tconst configuredPort = typeof config.sync_port === \"number\" ? config.sync_port : 7337;\n\t\tconst addresses = collectAdvertiseAddresses(\n\t\t\texplicitAddress ?? null,\n\t\t\tconfiguredHost,\n\t\t\tconfiguredPort,\n\t\t\tnetworkInterfaces(),\n\t\t);\n\t\tconst payloadObj = {\n\t\t\tdevice_id: deviceId,\n\t\t\tfingerprint,\n\t\t\tpublic_key: publicKey,\n\t\t\taddress: addresses[0] ?? \"\",\n\t\t\taddresses,\n\t\t};\n\t\tconst payloadText = JSON.stringify(payloadObj);\n\n\t\tif (opts.payloadOnly || opts.json) {\n\t\t\tprocess.stdout.write(`${payloadText}\\n`);\n\t\t\treturn;\n\t\t}\n\n\t\tconst escaped = payloadText.replaceAll(\"'\", \"'\\\\''\");\n\t\tconsole.log(\"Pairing payload\");\n\t\tconsole.log(payloadText);\n\t\tconsole.log(\"On the other device, save this JSON to pairing.json, then run:\");\n\t\tconsole.log(\" codemem sync pair --accept-file pairing.json\");\n\t\tconsole.log(\"If you prefer inline JSON, run:\");\n\t\tconsole.log(` codemem sync pair --accept '${escaped}'`);\n\t\tconsole.log(\"For machine-friendly output next time, run:\");\n\t\tconsole.log(\" codemem sync pair --payload-only\");\n\t\tconsole.log(\n\t\t\t\"On the accepting device, --include/--exclude control both what it sends and what it accepts from that peer.\",\n\t\t);\n\t} finally {\n\t\tstore.close();\n\t}\n});\nsyncCommand.addCommand(pairCmd);\n\n// ---- sync doctor ----\n\nconst doctorCmd = new Command(\"doctor\")\n\t.configureHelp(helpStyle)\n\t.description(\"Diagnose common sync setup and connectivity issues\");\naddDbOption(doctorCmd);\naddConfigOption(doctorCmd);\naddJsonOption(doctorCmd);\ndoctorCmd.action(\n\tasync (opts: { db?: string; dbPath?: string; config?: string; json?: boolean }) => {\n\t\tconst config = readCliConfig(opts.config);\n\t\tconst dbPath = resolveDbPath(resolveDbOpt(opts));\n\t\tconst store = new MemoryStore(dbPath);\n\t\ttry {\n\t\t\tconst d = drizzle(store.db, { schema });\n\t\t\tconst device = d\n\t\t\t\t.select({ device_id: schema.syncDevice.device_id })\n\t\t\t\t.from(schema.syncDevice)\n\t\t\t\t.limit(1)\n\t\t\t\t.get();\n\t\t\tconst daemonState = d\n\t\t\t\t.select()\n\t\t\t\t.from(schema.syncDaemonState)\n\t\t\t\t.where(eq(schema.syncDaemonState.id, 1))\n\t\t\t\t.get();\n\t\t\tconst peers = d\n\t\t\t\t.select({\n\t\t\t\t\tpeer_device_id: schema.syncPeers.peer_device_id,\n\t\t\t\t\taddresses_json: schema.syncPeers.addresses_json,\n\t\t\t\t\tpinned_fingerprint: schema.syncPeers.pinned_fingerprint,\n\t\t\t\t\tpublic_key: schema.syncPeers.public_key,\n\t\t\t\t})\n\t\t\t\t.from(schema.syncPeers)\n\t\t\t\t.all();\n\n\t\t\tconst issues: string[] = [];\n\t\t\tconst syncHost = typeof config.sync_host === \"string\" ? config.sync_host : \"0.0.0.0\";\n\t\t\tconst syncPort = typeof config.sync_port === \"number\" ? config.sync_port : 7337;\n\t\t\tconst viewerBinding = readViewerBinding(dbPath);\n\n\t\t\tconst reachable = viewerBinding\n\t\t\t\t? await portOpen(viewerBinding.host, viewerBinding.port)\n\t\t\t\t: false;\n\n\t\t\tif (!reachable) issues.push(\"daemon not running\");\n\t\t\tif (!device) issues.push(\"identity missing\");\n\t\t\tif (\n\t\t\t\tdaemonState?.last_error &&\n\t\t\t\t(!daemonState.last_ok_at || daemonState.last_ok_at < (daemonState.last_error_at ?? \"\"))\n\t\t\t) {\n\t\t\t\tissues.push(\"daemon error\");\n\t\t\t}\n\t\t\tif (peers.length === 0) issues.push(\"no peers\");\n\t\t\tif (!config.sync_enabled) issues.push(\"sync is disabled\");\n\n\t\t\tconst peerDetails: Array<{\n\t\t\t\tpeer_device_id: string;\n\t\t\t\taddresses: number;\n\t\t\t\treachable: string;\n\t\t\t\tpinned: boolean;\n\t\t\t\thas_public_key: boolean;\n\t\t\t}> = [];\n\n\t\t\tfor (const peer of peers) {\n\t\t\t\tconst addresses = peer.addresses_json ? (JSON.parse(peer.addresses_json) as string[]) : [];\n\t\t\t\tconst endpoint = parseStoredAddressEndpoint(addresses[0] ?? \"\");\n\t\t\t\tconst reach = endpoint\n\t\t\t\t\t? (await portOpen(endpoint.host, endpoint.port))\n\t\t\t\t\t\t? \"ok\"\n\t\t\t\t\t\t: \"unreachable\"\n\t\t\t\t\t: \"unknown\";\n\t\t\t\tconst pinned = Boolean(peer.pinned_fingerprint);\n\t\t\t\tconst hasKey = Boolean(peer.public_key);\n\t\t\t\tpeerDetails.push({\n\t\t\t\t\tpeer_device_id: peer.peer_device_id,\n\t\t\t\t\taddresses: addresses.length,\n\t\t\t\t\treachable: reach,\n\t\t\t\t\tpinned,\n\t\t\t\t\thas_public_key: hasKey,\n\t\t\t\t});\n\t\t\t\tif (reach !== \"ok\") issues.push(`peer ${peer.peer_device_id} unreachable`);\n\t\t\t\tif (!pinned || !hasKey) issues.push(`peer ${peer.peer_device_id} not pinned`);\n\t\t\t}\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(\n\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\tenabled: config.sync_enabled === true,\n\t\t\t\t\t\tlisten: `${syncHost}:${syncPort}`,\n\t\t\t\t\t\tmdns: process.env.CODEMEM_SYNC_MDNS ? \"env-configured\" : \"default/off\",\n\t\t\t\t\t\tdaemon: reachable ? \"running\" : \"not running\",\n\t\t\t\t\t\tidentity: device?.device_id ?? null,\n\t\t\t\t\t\tdaemon_error: daemonState?.last_error ?? null,\n\t\t\t\t\t\tpeers: peerDetails,\n\t\t\t\t\t\tissues: [...new Set(issues)],\n\t\t\t\t\t\tok: issues.length === 0,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconsole.log(\"Sync doctor\");\n\t\t\tconsole.log(`- Enabled: ${config.sync_enabled === true}`);\n\t\t\tconsole.log(`- Listen: ${syncHost}:${syncPort}`);\n\t\t\tconsole.log(`- mDNS: ${process.env.CODEMEM_SYNC_MDNS ? \"env-configured\" : \"default/off\"}`);\n\t\t\tconsole.log(`- Daemon: ${reachable ? \"running\" : \"not running\"}`);\n\n\t\t\tif (!device) {\n\t\t\t\tconsole.log(\"- Identity: missing (run `codemem sync enable`)\");\n\t\t\t} else {\n\t\t\t\tconsole.log(`- Identity: ${device.device_id}`);\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tdaemonState?.last_error &&\n\t\t\t\t(!daemonState.last_ok_at || daemonState.last_ok_at < (daemonState.last_error_at ?? \"\"))\n\t\t\t) {\n\t\t\t\tconsole.log(\n\t\t\t\t\t`- Daemon error: ${daemonState.last_error} (at ${daemonState.last_error_at ?? \"unknown\"})`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (peers.length === 0) {\n\t\t\t\tconsole.log(\"- Peers: none (pair a device first)\");\n\t\t\t} else {\n\t\t\t\tconsole.log(`- Peers: ${peers.length}`);\n\t\t\t\tfor (const detail of peerDetails) {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t` - ${detail.peer_device_id}: addresses=${detail.addresses} reach=${detail.reachable} pinned=${detail.pinned} public_key=${detail.has_public_key}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (issues.length > 0) {\n\t\t\t\tconsole.log(`WARN: ${[...new Set(issues)].slice(0, 3).join(\", \")}`);\n\t\t\t} else {\n\t\t\t\tconsole.log(\"OK: sync looks healthy\");\n\t\t\t}\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\nsyncCommand.addCommand(doctorCmd);\n\n// ---- sync status ----\n\nconst statusCmd = new Command(\"status\")\n\t.configureHelp(helpStyle)\n\t.description(\"Show sync configuration and peer summary\");\naddDbOption(statusCmd);\naddConfigOption(statusCmd);\naddJsonOption(statusCmd);\nstatusCmd.action((opts: { db?: string; dbPath?: string; config?: string; json?: boolean }) => {\n\tconst config = readCliConfig(opts.config);\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\ttry {\n\t\tconst d = drizzle(store.db, { schema });\n\t\tconst deviceRow = d\n\t\t\t.select({\n\t\t\t\tdevice_id: schema.syncDevice.device_id,\n\t\t\t\tfingerprint: schema.syncDevice.fingerprint,\n\t\t\t})\n\t\t\t.from(schema.syncDevice)\n\t\t\t.limit(1)\n\t\t\t.get();\n\t\tconst peers = d\n\t\t\t.select({\n\t\t\t\tpeer_device_id: schema.syncPeers.peer_device_id,\n\t\t\t\tname: schema.syncPeers.name,\n\t\t\t\tlast_sync_at: schema.syncPeers.last_sync_at,\n\t\t\t\tlast_error: schema.syncPeers.last_error,\n\t\t\t})\n\t\t\t.from(schema.syncPeers)\n\t\t\t.all();\n\n\t\tif (opts.json) {\n\t\t\tconsole.log(\n\t\t\t\tJSON.stringify(\n\t\t\t\t\t{\n\t\t\t\t\t\tenabled: config.sync_enabled === true,\n\t\t\t\t\t\thost: config.sync_host ?? \"0.0.0.0\",\n\t\t\t\t\t\tport: config.sync_port ?? 7337,\n\t\t\t\t\t\tinterval_s: config.sync_interval_s ?? 120,\n\t\t\t\t\t\tdevice_id: deviceRow?.device_id ?? null,\n\t\t\t\t\t\tfingerprint: deviceRow?.fingerprint ?? null,\n\t\t\t\t\t\tcoordinator_url: config.sync_coordinator_url ?? null,\n\t\t\t\t\t\tpeers: peers.map((peer) => ({\n\t\t\t\t\t\t\tdevice_id: peer.peer_device_id,\n\t\t\t\t\t\t\tname: peer.name,\n\t\t\t\t\t\t\tlast_sync: peer.last_sync_at,\n\t\t\t\t\t\t\tstatus: peer.last_error ?? \"ok\",\n\t\t\t\t\t\t})),\n\t\t\t\t\t},\n\t\t\t\t\tnull,\n\t\t\t\t\t2,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tp.intro(\"codemem sync status\");\n\t\tp.log.info(\n\t\t\t[\n\t\t\t\t`Enabled: ${config.sync_enabled === true ? \"yes\" : \"no\"}`,\n\t\t\t\t`Host: ${config.sync_host ?? \"0.0.0.0\"}`,\n\t\t\t\t`Port: ${config.sync_port ?? 7337}`,\n\t\t\t\t`Interval: ${config.sync_interval_s ?? 120}s`,\n\t\t\t\t`Coordinator: ${config.sync_coordinator_url ?? \"(not configured)\"}`,\n\t\t\t].join(\"\\n\"),\n\t\t);\n\t\tif (deviceRow) {\n\t\t\tp.log.info(`Device ID: ${deviceRow.device_id}\\nFingerprint: ${deviceRow.fingerprint}`);\n\t\t} else {\n\t\t\tp.log.warn(\"Device identity not initialized (run `codemem sync enable`)\");\n\t\t}\n\t\tif (peers.length === 0) {\n\t\t\tp.log.info(\"Peers: none\");\n\t\t} else {\n\t\t\tfor (const peer of peers) {\n\t\t\t\tconst label = peer.name || peer.peer_device_id;\n\t\t\t\tp.log.message(\n\t\t\t\t\t` ${label}: last_sync=${peer.last_sync_at ?? \"never\"}, status=${peer.last_error ?? \"ok\"}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tp.outro(`${peers.length} peer(s)`);\n\t} finally {\n\t\tstore.close();\n\t}\n});\nsyncCommand.addCommand(statusCmd);\n\n// ---- sync enable ----\n\nconst enableCmd = new Command(\"enable\")\n\t.configureHelp(helpStyle)\n\t.description(\"Enable sync and initialize device identity\")\n\t.option(\"--sync-host <host>\", \"sync listen host\")\n\t.option(\"--sync-port <port>\", \"sync listen port\")\n\t.option(\"--interval <seconds>\", \"sync interval in seconds\");\naddDbOption(enableCmd);\naddConfigOption(enableCmd);\naddJsonOption(enableCmd);\n// Hidden aliases for backwards compat\nenableCmd.addOption(new Option(\"--host <host>\", \"sync listen host\").hideHelp());\nenableCmd.addOption(new Option(\"--port <port>\", \"sync listen port\").hideHelp());\nenableCmd.action(\n\t(opts: {\n\t\tdb?: string;\n\t\tdbPath?: string;\n\t\tconfig?: string;\n\t\tsyncHost?: string;\n\t\tsyncPort?: string;\n\t\thost?: string;\n\t\tport?: string;\n\t\tinterval?: string;\n\t\tjson?: boolean;\n\t}) => {\n\t\t// Emit deprecation warnings for legacy --host/--port\n\t\tif (opts.host && !opts.syncHost) {\n\t\t\temitDeprecationWarning(\"--host on sync enable\", \"--sync-host\");\n\t\t}\n\t\tif (opts.port && !opts.syncPort) {\n\t\t\temitDeprecationWarning(\"--port on sync enable\", \"--sync-port\");\n\t\t}\n\t\tconst effectiveHost = opts.syncHost ?? opts.host;\n\t\tconst effectivePort = opts.syncPort ?? opts.port;\n\n\t\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\t\ttry {\n\t\t\tconst [deviceId, fingerprint] = ensureDeviceIdentity(store.db);\n\t\t\tconst config = readCliConfig(opts.config);\n\t\t\tconfig.sync_enabled = true;\n\t\t\tif (effectiveHost) config.sync_host = effectiveHost;\n\t\t\tconst syncPort = parsePositiveIntegerOption(effectivePort, \"--sync-port\");\n\t\t\tconst syncInterval = parsePositiveIntegerOption(opts.interval, \"--interval\");\n\t\t\tif (syncPort != null) config.sync_port = syncPort;\n\t\t\tif (syncInterval != null) config.sync_interval_s = syncInterval;\n\t\t\twriteCliConfig(config, opts.config);\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(\n\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\tok: true,\n\t\t\t\t\t\tdevice_id: deviceId,\n\t\t\t\t\t\tfingerprint,\n\t\t\t\t\t\thost: config.sync_host ?? \"0.0.0.0\",\n\t\t\t\t\t\tport: config.sync_port ?? 7337,\n\t\t\t\t\t\tinterval_s: config.sync_interval_s ?? 120,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tp.intro(\"codemem sync enable\");\n\t\t\tp.log.success(\n\t\t\t\t[\n\t\t\t\t\t`Device ID: ${deviceId}`,\n\t\t\t\t\t`Fingerprint: ${fingerprint}`,\n\t\t\t\t\t`Host: ${config.sync_host ?? \"0.0.0.0\"}`,\n\t\t\t\t\t`Port: ${config.sync_port ?? 7337}`,\n\t\t\t\t\t`Interval: ${config.sync_interval_s ?? 120}s`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t);\n\t\t\tp.outro(\"Sync enabled — restart `codemem serve` to activate\");\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\nsyncCommand.addCommand(enableCmd);\n\n// ---- sync disable ----\n\nconst disableCmd = new Command(\"disable\")\n\t.configureHelp(helpStyle)\n\t.description(\"Disable sync without deleting keys or peers\");\naddConfigOption(disableCmd);\ndisableCmd.action((opts: { config?: string }) => {\n\tconst config = readCliConfig(opts.config);\n\tconfig.sync_enabled = false;\n\twriteCliConfig(config, opts.config);\n\tp.intro(\"codemem sync disable\");\n\tp.outro(\"Sync disabled — restart `codemem serve` to take effect\");\n});\nsyncCommand.addCommand(disableCmd);\n\n// ---- sync peers ----\n\nconst peersCommand = new Command(\"peers\")\n\t.configureHelp(helpStyle)\n\t.description(\"List known sync peers\");\naddDbOption(peersCommand);\naddJsonOption(peersCommand);\npeersCommand.action((opts: { db?: string; dbPath?: string; json?: boolean }) => {\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\ttry {\n\t\tconst d = drizzle(store.db, { schema });\n\t\tconst peers = d\n\t\t\t.select({\n\t\t\t\tpeer_device_id: schema.syncPeers.peer_device_id,\n\t\t\t\tname: schema.syncPeers.name,\n\t\t\t\taddresses: schema.syncPeers.addresses_json,\n\t\t\t\tlast_sync_at: schema.syncPeers.last_sync_at,\n\t\t\t\tlast_error: schema.syncPeers.last_error,\n\t\t\t})\n\t\t\t.from(schema.syncPeers)\n\t\t\t.orderBy(desc(schema.syncPeers.last_sync_at))\n\t\t\t.all();\n\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify(peers, null, 2));\n\t\t\treturn;\n\t\t}\n\n\t\tp.intro(\"codemem sync peers\");\n\t\tif (peers.length === 0) {\n\t\t\tp.outro(\"No peers configured\");\n\t\t\treturn;\n\t\t}\n\t\tfor (const peer of peers) {\n\t\t\tconst label = peer.name || peer.peer_device_id;\n\t\t\tconst addrs = peer.addresses || \"(no addresses)\";\n\t\t\tp.log.message(\n\t\t\t\t`${label}\\n addresses: ${addrs}\\n last_sync: ${peer.last_sync_at ?? \"never\"}\\n status: ${peer.last_error ?? \"ok\"}`,\n\t\t\t);\n\t\t}\n\t\tp.outro(`${peers.length} peer(s)`);\n\t} finally {\n\t\tstore.close();\n\t}\n});\n\nconst peersRemoveCmd = new Command(\"remove\")\n\t.configureHelp(helpStyle)\n\t.description(\"Remove a sync peer by device id or exact name\")\n\t.argument(\"<peer>\", \"peer device id or exact name\");\naddDbOption(peersRemoveCmd);\naddJsonOption(peersRemoveCmd);\npeersRemoveCmd.action((peerRef: string, opts: { db?: string; dbPath?: string; json?: boolean }) => {\n\tconst store = new MemoryStore(resolveDbPath(resolveDbOpt(opts)));\n\ttry {\n\t\tconst d = drizzle(store.db, { schema });\n\t\tconst match = resolvePeerMatch(d, peerRef);\n\t\tif (match === \"ambiguous\") {\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\"ambiguous_peer\", `Peer name is ambiguous: ${peerRef.trim()}`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.error(`Peer name is ambiguous: ${peerRef.trim()}`);\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\t\tif (!match) {\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\"peer_not_found\", `Peer not found: ${peerRef.trim()}`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.error(`Peer not found: ${peerRef.trim()}`);\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\t\td.delete(schema.replicationCursors)\n\t\t\t.where(eq(schema.replicationCursors.peer_device_id, match.peer_device_id))\n\t\t\t.run();\n\t\td.delete(schema.syncPeers)\n\t\t\t.where(eq(schema.syncPeers.peer_device_id, match.peer_device_id))\n\t\t\t.run();\n\t\tconst payload = {\n\t\t\tok: true,\n\t\t\tpeer_device_id: match.peer_device_id,\n\t\t\tname: match.name,\n\t\t};\n\t\tif (opts.json) {\n\t\t\tconsole.log(JSON.stringify(payload, null, 2));\n\t\t\treturn;\n\t\t}\n\t\tp.intro(\"codemem sync peers remove\");\n\t\tp.log.success(`Removed peer ${match.name || match.peer_device_id}`);\n\t\tp.outro(match.peer_device_id);\n\t} finally {\n\t\tstore.close();\n\t}\n});\npeersCommand.addCommand(peersRemoveCmd);\nsyncCommand.addCommand(peersCommand);\n\n// ---- sync bootstrap <peer-device-id> ----\n\nconst bootstrapCmd = new Command(\"bootstrap\")\n\t.configureHelp(helpStyle)\n\t.description(\"Fast-bootstrap memories from a peer (full snapshot transfer)\")\n\t.argument(\"[peer-device-id]\", \"peer device ID to bootstrap from\")\n\t.option(\"--bootstrap-grant <grant-id>\", \"bootstrap grant id for seed-authorized bootstrap\")\n\t.option(\"--page-size <n>\", \"items per snapshot page (default: 2000)\", \"2000\")\n\t.option(\"--keys-dir <path>\", \"keys directory\")\n\t.option(\"--force\", \"skip dirty-local-state safety check\");\naddDbOption(bootstrapCmd);\naddJsonOption(bootstrapCmd);\n// Hidden alias for backwards compat\nbootstrapCmd.addOption(new Option(\"--peer <device-id>\", \"peer device ID\").hideHelp());\nbootstrapCmd.action(\n\tasync (\n\t\tpeerArg: string | undefined,\n\t\topts: {\n\t\t\tpeer?: string;\n\t\t\tbootstrapGrant?: string;\n\t\t\tpageSize: string;\n\t\t\tdb?: string;\n\t\t\tdbPath?: string;\n\t\t\tkeysDir?: string;\n\t\t\tforce?: boolean;\n\t\t\tjson?: boolean;\n\t\t},\n\t) => {\n\t\t// Resolve peer from positional or hidden --peer alias\n\t\tconst peerDeviceId = (peerArg || opts.peer || \"\").trim();\n\t\tif (!peerDeviceId) {\n\t\t\tif (opts.json) {\n\t\t\t\temitJsonError(\"usage_error\", \"missing required argument: <peer-device-id>\", 2);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tp.log.error(\"missing required argument: <peer-device-id>\");\n\t\t\tprocess.exitCode = 2;\n\t\t\treturn;\n\t\t}\n\n\t\tconst dbPath = resolveDbPath(resolveDbOpt(opts));\n\t\tconst store = new MemoryStore(dbPath);\n\t\ttry {\n\t\t\tconst pageSize = Math.max(1, Number.parseInt(opts.pageSize, 10) || 2000);\n\t\t\tconst keysDir = opts.keysDir ?? undefined;\n\t\t\tconst d = drizzle(store.db, { schema });\n\n\t\t\t// Look up peer\n\t\t\tconst peer = d\n\t\t\t\t.select()\n\t\t\t\t.from(schema.syncPeers)\n\t\t\t\t.where(eq(schema.syncPeers.peer_device_id, peerDeviceId))\n\t\t\t\t.get();\n\t\t\tif (!peer) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\"peer_not_found\", `Peer ${peerDeviceId} not found in sync_peers.`);\n\t\t\t\t} else {\n\t\t\t\t\tp.log.error(`Peer ${peerDeviceId} not found in sync_peers.`);\n\t\t\t\t}\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!peer.pinned_fingerprint) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\n\t\t\t\t\t\t\"peer_not_pinned\",\n\t\t\t\t\t\t`Peer ${peerDeviceId} has no pinned fingerprint. Accept it first.`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tp.log.error(`Peer ${peerDeviceId} has no pinned fingerprint. Accept it first.`);\n\t\t\t\t}\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Safety check\n\t\t\tif (!opts.force) {\n\t\t\t\tconst dirty = hasUnsyncedSharedMemoryChanges(store.db);\n\t\t\t\tif (dirty.dirty) {\n\t\t\t\t\tif (opts.json) {\n\t\t\t\t\t\temitJsonError(\n\t\t\t\t\t\t\t\"local_unsynced_changes\",\n\t\t\t\t\t\t\t`${dirty.count} unsynced shared memory change(s) would be lost. Use --force to override.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tp.log.error(\n\t\t\t\t\t\t\t`${dirty.count} unsynced shared memory change(s) would be lost. Use --force to override.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Resolve device identity\n\t\t\tconst [deviceId] = ensureDeviceIdentity(store.db, { keysDir });\n\n\t\t\t// Get peer status to obtain reset boundary\n\t\t\tconst addresses = JSON.parse(String(peer.addresses_json ?? \"[]\")) as string[];\n\t\t\tif (!addresses.length) {\n\t\t\t\tif (opts.json) {\n\t\t\t\t\temitJsonError(\n\t\t\t\t\t\t\"no_peer_addresses\",\n\t\t\t\t\t\t\"Peer has no known addresses. Run a sync first or add addresses.\",\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tp.log.error(\"Peer has no known addresses. Run a sync first or add addresses.\");\n\t\t\t\t}\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet boundary: {\n\t\t\t\tgeneration: number;\n\t\t\t\tsnapshot_id: string;\n\t\t\t\tbaseline_cursor: string | null;\n\t\t\t} | null = null;\n\t\t\tlet baseUrl = \"\";\n\t\t\tconst addressResults: Array<{ address: string; result: string }> = [];\n\n\t\t\tfor (const address of addresses) {\n\t\t\t\tconst candidate = buildBaseUrl(address);\n\t\t\t\tif (!candidate) continue;\n\t\t\t\tconst statusUrl = `${candidate}/v1/status`;\n\t\t\t\tconst headers = buildAuthHeaders({\n\t\t\t\t\tdeviceId,\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\turl: statusUrl,\n\t\t\t\t\tbodyBytes: Buffer.alloc(0),\n\t\t\t\t\tbootstrapGrantId: opts.bootstrapGrant,\n\t\t\t\t\tkeysDir,\n\t\t\t\t});\n\t\t\t\ttry {\n\t\t\t\t\tconst [code, payload] = await requestJson(\"GET\", statusUrl, { headers });\n\t\t\t\t\tif (code !== 200 || !payload) {\n\t\t\t\t\t\taddressResults.push({ address: candidate, result: `status ${code}` });\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (payload.fingerprint !== peer.pinned_fingerprint) {\n\t\t\t\t\t\taddressResults.push({ address: candidate, result: \"fingerprint mismatch\" });\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst reset = payload.sync_reset as Record<string, unknown> | undefined;\n\t\t\t\t\tif (\n\t\t\t\t\t\treset &&\n\t\t\t\t\t\ttypeof reset.generation === \"number\" &&\n\t\t\t\t\t\ttypeof reset.snapshot_id === \"string\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tboundary = {\n\t\t\t\t\t\t\tgeneration: reset.generation,\n\t\t\t\t\t\t\tsnapshot_id: reset.snapshot_id,\n\t\t\t\t\t\t\tbaseline_cursor:\n\t\t\t\t\t\t\t\ttypeof reset.baseline_cursor === \"string\" ? reset.baseline_cursor : null,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tbaseUrl = candidate;\n\t\t\t\t\t\taddressResults.push({ address: candidate, result: \"ok\" });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\taddressResults.push({ address: candidate, result: \"missing sync_reset boundary\" });\n\t\t\t\t} catch (err) {\n\t\t\t\t\taddressResults.push({\n\t\t\t\t\t\taddress: candidate,\n\t\t\t\t\t\tresult: err instanceof Error ? err.message : String(err),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!boundary || !baseUrl) {\n\t\t\t\tconst summary = addressResults.map((r) => `${r.address}: ${r.result}`).join(\"; \");\n\t\t\t\tconst detail = summary\n\t\t\t\t\t? `no reachable peer with valid reset boundary. Tried: ${summary}`\n\t\t\t\t\t: \"peer unreachable or missing reset boundary\";\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tconsole.log(JSON.stringify({ ok: false, error: detail, addresses: addressResults }));\n\t\t\t\t} else {\n\t\t\t\t\tp.log.error(detail);\n\t\t\t\t}\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!opts.json) {\n\t\t\t\tp.intro(\"codemem sync bootstrap\");\n\t\t\t\tp.log.step(`Bootstrapping from ${peer.name || peerDeviceId}...`);\n\t\t\t}\n\n\t\t\tconst resetInfo = {\n\t\t\t\tgeneration: boundary.generation,\n\t\t\t\tsnapshot_id: boundary.snapshot_id,\n\t\t\t\tbaseline_cursor: boundary.baseline_cursor,\n\t\t\t\tretained_floor_cursor: null,\n\t\t\t\treset_required: true as const,\n\t\t\t\treason: \"initial_bootstrap\" as const,\n\t\t\t};\n\n\t\t\tconst { items } = await fetchAllSnapshotPages(baseUrl, resetInfo, deviceId, {\n\t\t\t\tkeysDir,\n\t\t\t\tbootstrapGrantId: opts.bootstrapGrant,\n\t\t\t\tpageSize,\n\t\t\t});\n\n\t\t\tconst result = applyBootstrapSnapshot(store.db, peerDeviceId, items, resetInfo);\n\n\t\t\tif (opts.json) {\n\t\t\t\tconsole.log(\n\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\tok: result.ok,\n\t\t\t\t\t\tapplied: result.applied,\n\t\t\t\t\t\tdeleted: result.deleted,\n\t\t\t\t\t\terror: result.error ?? null,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tp.log.success(`Applied ${result.applied} memories (removed ${result.deleted} stale).`);\n\t\t\t\t} else {\n\t\t\t\t\tp.log.error(result.error || \"Bootstrap apply failed.\");\n\t\t\t\t}\n\t\t\t\tp.outro(result.ok ? \"Bootstrap complete\" : \"Bootstrap failed\");\n\t\t\t}\n\t\t\tif (!result.ok) process.exitCode = 1;\n\t\t} finally {\n\t\t\tstore.close();\n\t\t}\n\t},\n);\nsyncCommand.addCommand(bootstrapCmd);\n\n// ---- sync connect <coordinator-url> ----\n\nconst connectCmd = new Command(\"connect\")\n\t.configureHelp(helpStyle)\n\t.description(\"Configure coordinator URL for cloud sync\")\n\t.argument(\"<url>\", \"coordinator URL (e.g. https://coordinator.example.com)\")\n\t.option(\"--group <group>\", \"sync group ID\");\naddConfigOption(connectCmd);\nconnectCmd.action((url: string, opts: { group?: string; config?: string }) => {\n\tconst config = readCliConfig(opts.config);\n\tconfig.sync_coordinator_url = url.trim();\n\tif (opts.group) config.sync_coordinator_group = opts.group.trim();\n\twriteCliConfig(config, opts.config);\n\tp.intro(\"codemem sync connect\");\n\tp.log.success(`Coordinator: ${url.trim()}`);\n\tif (opts.group) p.log.info(`Group: ${opts.group.trim()}`);\n\tp.outro(\"Restart `codemem serve` to activate coordinator sync\");\n});\nsyncCommand.addCommand(connectCmd);\n\n// ---- Deprecation alias: sync coordinator → coordinator ----\n// Build a separate coordinator command tree for the sync alias (Commander\n// re-parents commands on addCommand, so sharing instances is not possible).\n// The canonical coordinatorCommand lives in coordinator.ts and is registered\n// at the top level by index.ts.\n\nconst syncCoordinatorAlias = buildCoordinatorCommand();\n\nsyncCoordinatorAlias.hook(\"preAction\", (_thisCmd: Command, actionCmd: Command) => {\n\tconst subName = actionCmd.name();\n\temitDeprecationWarning(`codemem sync coordinator ${subName}`, `codemem coordinator ${subName}`);\n});\n\nsyncCommand.addCommand(syncCoordinatorAlias);\n","import { VERSION } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport { helpStyle } from \"../help-style.js\";\n\nexport const versionCommand = new Command(\"version\")\n\t.configureHelp(helpStyle)\n\t.description(\"Print codemem version\")\n\t.action(() => {\n\t\tconsole.log(VERSION);\n\t});\n","#!/usr/bin/env node\n\n/**\n * @codemem/cli — CLI entry point.\n *\n * Commands:\n * codemem stats → database statistics\n * codemem search → FTS5 memory search\n * codemem pack → context-aware memory pack\n * codemem serve → viewer server\n * codemem mcp → MCP stdio server\n */\n\nimport { VERSION } from \"@codemem/core\";\nimport { Command } from \"commander\";\nimport omelette from \"omelette\";\nimport { claudeHookIngestCommand } from \"./commands/claude-hook-ingest.js\";\nimport { claudeHookInjectCommand } from \"./commands/claude-hook-inject.js\";\nimport { configCommand } from \"./commands/config.js\";\nimport { coordinatorCommand } from \"./commands/coordinator.js\";\nimport { dbCommand } from \"./commands/db.js\";\nimport { embedCommand } from \"./commands/embed.js\";\nimport { enqueueRawEventCommand } from \"./commands/enqueue-raw-event.js\";\nimport { exportMemoriesCommand } from \"./commands/export-memories.js\";\nimport { importMemoriesCommand } from \"./commands/import-memories.js\";\nimport { mcpCommand } from \"./commands/mcp.js\";\nimport {\n\tforgetMemoryCommand,\n\tmemoryCommand,\n\trememberMemoryCommand,\n\tshowMemoryCommand,\n} from \"./commands/memory.js\";\nimport { packCommand } from \"./commands/pack.js\";\nimport { recentCommand } from \"./commands/recent.js\";\nimport { searchCommand } from \"./commands/search.js\";\nimport { serveCommand } from \"./commands/serve.js\";\nimport { setupCommand } from \"./commands/setup.js\";\nimport { statsCommand } from \"./commands/stats.js\";\nimport { syncCommand } from \"./commands/sync.js\";\nimport { versionCommand } from \"./commands/version.js\";\nimport { helpStyle } from \"./help-style.js\";\n\ntype CompletionWithScriptGenerators = ReturnType<typeof omelette> & {\n\tgenerateCompletionCode: () => string;\n\tgenerateCompletionCodeFish: () => string;\n};\n\n// Shell completion (bash/zsh/fish)\nconst completion = omelette(\"codemem <command>\") as CompletionWithScriptGenerators;\ncompletion.on(\"command\", ({ reply }) => {\n\treply([\n\t\t\"claude-hook-inject\",\n\t\t\"claude-hook-ingest\",\n\t\t\"config\",\n\t\t\"coordinator\",\n\t\t\"db\",\n\t\t\"embed\",\n\t\t\"enqueue-raw-event\",\n\t\t\"export-memories\",\n\t\t\"import-memories\",\n\t\t\"mcp\",\n\t\t\"memory\",\n\t\t\"pack\",\n\t\t\"recent\",\n\t\t\"search\",\n\t\t\"serve\",\n\t\t\"setup\",\n\t\t\"stats\",\n\t\t\"sync\",\n\t\t\"version\",\n\t\t\"help\",\n\t\t\"--help\",\n\t\t\"--version\",\n\t]);\n});\ncompletion.init();\n\nfunction hasRootFlag(flag: string): boolean {\n\tfor (const arg of process.argv.slice(2)) {\n\t\tif (arg === \"--\") return false;\n\t\tif (arg === flag) return true;\n\t\tif (!arg.startsWith(\"-\")) return false;\n\t}\n\treturn false;\n}\n\nfunction getShellCompletionScript(): string {\n\tconst shellPath = process.env.SHELL ?? \"\";\n\tif (shellPath.includes(\"fish\")) {\n\t\treturn completion.generateCompletionCodeFish();\n\t}\n\treturn completion.generateCompletionCode();\n}\n\nconst program = new Command();\n\nprogram\n\t.name(\"codemem\")\n\t.description(\"codemem — persistent memory for AI coding agents\")\n\t.enablePositionalOptions()\n\t.option(\"--install-completion\", \"install shell completion\")\n\t.option(\"--show-completion\", \"show shell completion install guidance\")\n\t.version(VERSION)\n\t.configureHelp(helpStyle);\n\nif (hasRootFlag(\"--setup-completion\") || hasRootFlag(\"--install-completion\")) {\n\tcompletion.setupShellInitFile();\n\tprocess.exit(0);\n}\n\nif (hasRootFlag(\"--show-completion\")) {\n\tconsole.log(getShellCompletionScript());\n\tprocess.exit(0);\n}\n\nif (hasRootFlag(\"--cleanup-completion\")) {\n\tcompletion.cleanupShellInitFile();\n\tprocess.exit(0);\n}\n\n// --- Memory subcommands: export/import registered under `memory` group ---\n// Per cli-design-conventions.md, export/import belong under their noun group.\n// The top-level export-memories/import-memories remain as compatibility aliases.\n//\n// We create thin wrapper commands that replicate the same argument/option shape\n// and delegate to the original command's parseAsync with synthetic argv.\n// This avoids accessing Commander internals while keeping a single source of\n// truth for the action logic in the original command modules.\n{\n\tconst memExport = new Command(\"export\")\n\t\t.description(\"Export memories to a JSON file for sharing or backup\")\n\t\t.argument(\"<output>\", \"output file path (use '-' for stdout)\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.option(\"--db-path <path>\", \"database path\")\n\t\t.option(\"--project <project>\", \"filter by project\")\n\t\t.option(\"--all-projects\", \"export all projects\")\n\t\t.option(\"--include-inactive\", \"include deactivated memories\")\n\t\t.option(\"--since <iso>\", \"only export memories created after this ISO timestamp\")\n\t\t.configureHelp(helpStyle)\n\t\t.allowUnknownOption(true)\n\t\t.allowExcessArguments(true)\n\t\t.action(async () => {\n\t\t\t// Forward to the original command by re-parsing the raw argv tail.\n\t\t\t// `memory export <args>` → `export-memories <args>`\n\t\t\tconst idx = process.argv.indexOf(\"export\");\n\t\t\tconst tail = idx >= 0 ? process.argv.slice(idx + 1) : [];\n\t\t\tawait exportMemoriesCommand.parseAsync([\"node\", \"export-memories\", ...tail]);\n\t\t});\n\n\tconst memImport = new Command(\"import\")\n\t\t.description(\"Import memories from an exported JSON file\")\n\t\t.argument(\"<inputFile>\", \"input JSON file (use '-' for stdin)\")\n\t\t.option(\"--db <path>\", \"database path\")\n\t\t.option(\"--db-path <path>\", \"database path\")\n\t\t.option(\"--remap-project <path>\", \"remap all projects to this path on import\")\n\t\t.option(\"--dry-run\", \"preview import without writing\")\n\t\t.configureHelp(helpStyle)\n\t\t.allowUnknownOption(true)\n\t\t.allowExcessArguments(true)\n\t\t.action(async () => {\n\t\t\tconst idx = process.argv.indexOf(\"import\");\n\t\t\tconst tail = idx >= 0 ? process.argv.slice(idx + 1) : [];\n\t\t\tawait importMemoriesCommand.parseAsync([\"node\", \"import-memories\", ...tail]);\n\t\t});\n\n\tmemoryCommand.addCommand(memExport);\n\tmemoryCommand.addCommand(memImport);\n}\n\nprogram.addCommand(serveCommand);\nprogram.addCommand(configCommand);\nprogram.addCommand(coordinatorCommand);\nprogram.addCommand(mcpCommand);\nprogram.addCommand(claudeHookInjectCommand);\nprogram.addCommand(claudeHookIngestCommand);\nprogram.addCommand(dbCommand);\nprogram.addCommand(exportMemoriesCommand);\nprogram.addCommand(importMemoriesCommand);\nprogram.addCommand(statsCommand);\nprogram.addCommand(embedCommand);\nprogram.addCommand(recentCommand);\nprogram.addCommand(searchCommand);\nprogram.addCommand(packCommand);\n// Deprecated top-level aliases — use `memory show`, `memory forget`, `memory remember` instead.\n// These are hidden from --help and shell completion but still functional for backwards compat.\nprogram.addCommand(showMemoryCommand, { hidden: true });\nprogram.addCommand(forgetMemoryCommand, { hidden: true });\nprogram.addCommand(rememberMemoryCommand, { hidden: true });\nprogram.addCommand(memoryCommand);\nprogram.addCommand(syncCommand);\nprogram.addCommand(setupCommand);\nprogram.addCommand(enqueueRawEventCommand);\nprogram.addCommand(versionCommand);\n\nprogram.parse();\n"],"mappings":"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"}