@wrongstack/core 0.296.3 → 0.296.4

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/coordination/mailbox-project-server.ts", "../../src/kernel/events.ts", "../../src/utils/perf-profile.ts", "../../src/coordination/mailbox-events.ts", "../../src/coordination/mailbox-project-server-endpoint.ts", "../../src/coordination/mailbox-project-server-protocol.ts", "../../src/coordination/sqlite-mailbox.ts", "../../src/coordination/mailbox-constants.ts", "../../src/coordination/global-mailbox-completion.ts", "../../src/coordination/mailbox-types.ts", "../../src/coordination/mailbox-receipt-folding.ts", "../../src/coordination/mailbox-retention-state.ts", "../../src/coordination/mailbox-status-mappers.ts", "../../src/coordination/mailbox-message-codec.ts", "../../src/coordination/sqlite-mailbox-compaction.ts", "../../src/coordination/mailbox-credential-store.ts", "../../src/coordination/sqlite-mailbox-rows.ts", "../../src/coordination/sqlite-mailbox-credentials.ts", "../../src/coordination/sqlite-mailbox-schema.ts", "../../src/utils/sqlite-warning.ts", "../../src/coordination/global-mailbox-paths.ts", "../../src/coordination/mailbox-parse-state.ts", "../../src/coordination/mailbox-registry-codec.ts"],
4
- "sourcesContent": ["#!/usr/bin/env node\n/**\n * One detached mailbox owner per local WrongStack project state directory.\n *\n * Only this process opens the project SQLite database. Every CLI/TUI/WebUI/HQ\n * process talks to it through the deterministic local IPC endpoint.\n */\n\nimport * as fs from 'node:fs';\nimport * as fsPromises from 'node:fs/promises';\nimport * as net from 'node:net';\nimport * as path from 'node:path';\nimport { EventBus } from '../kernel/events.js';\nimport { useDaemonPerfDefaults } from '../utils/perf-profile.js';\nimport { MailboxEventEmitter } from './mailbox-events.js';\nimport {\n ensureMailboxProjectServerSocketDirectory,\n mailboxProjectServerEndpoint,\n mailboxProjectServerMetadataPath,\n} from './mailbox-project-server-endpoint.js';\nimport {\n encodeMailboxProjectServerMessage,\n isMailboxProjectServerClientMessage,\n MAILBOX_PROJECT_SERVER_MAX_FRAME_CHARS,\n MAILBOX_PROJECT_SERVER_PROTOCOL_VERSION,\n type MailboxProjectServerClientMessage,\n type MailboxProjectServerInfo,\n type MailboxProjectServerMessage,\n type MailboxServerOperationName,\n type MailboxServerOperations,\n} from './mailbox-project-server-protocol.js';\nimport { SQLITE_MAILBOX_FILE, SqliteMailbox } from './sqlite-mailbox.js';\n\nconst DEFAULT_IDLE_MS = 5 * 60_000;\nconst DEFAULT_CLIENT_LEASE_MS = 45_000;\n\n/**\n * Cap on outbound bytes queued for a single client before it is dropped.\n *\n * `socket.write()` returns `false` once its internal queue passes the stream's\n * high-water mark; that is the signal to stop producing. This server\n * broadcasts every `mailbox.*` event to every connected client, so ignoring\n * that signal meant one client that stopped reading \u2014 a suspended process, a\n * TUI stuck behind a modal, a debugger-paused peer \u2014 made the owner buffer\n * every subsequent broadcast for it, without limit. Nothing else here is big:\n * the SQLite file is single-digit MB, so an owner holding hundreds of MB is\n * this queue and nothing else.\n *\n * Dropping is the right response rather than throttling: these are\n * notifications, and SQLite remains the authority. A client that reconnects\n * re-queries current state, so it loses nothing but the events it was already\n * too far behind to have processed.\n */\nconst MAX_CLIENT_WRITE_BUFFER_BYTES = 8 * 1024 * 1024;\n\ninterface ClientState {\n socket: net.Socket;\n buffer: string;\n lastSeenAt: number;\n}\n\nfunction parseArgs(argv: string[]): { projectDir: string } {\n let projectDir: string | undefined;\n for (let index = 0; index < argv.length; index++) {\n if (argv[index] === '--project-dir') projectDir = argv[++index];\n }\n if (!projectDir) throw new Error('mailbox project server requires --project-dir');\n return { projectDir: path.resolve(projectDir) };\n}\n\n// Long-lived daemon: lean SQLite residency unless the operator says\n// otherwise. Must run before any store opens.\nuseDaemonPerfDefaults();\n\nconst { projectDir } = parseArgs(process.argv.slice(2));\nconst endpoint = mailboxProjectServerEndpoint(projectDir);\nconst metadataPath = mailboxProjectServerMetadataPath(projectDir);\nconst idleInput = Number(process.env['WRONGSTACK_MAILBOX_SERVER_IDLE_MS']);\nconst idleMs = Number.isFinite(idleInput) && idleInput >= 100 ? idleInput : DEFAULT_IDLE_MS;\nconst leaseInput = Number(process.env['WRONGSTACK_MAILBOX_SERVER_CLIENT_LEASE_MS']);\nconst clientLeaseMs =\n Number.isFinite(leaseInput) && leaseInput >= 100 ? leaseInput : DEFAULT_CLIENT_LEASE_MS;\nconst leaseSweepMs = Math.min(10_000, Math.max(100, Math.floor(clientLeaseMs / 3)));\nconst startedAt = new Date().toISOString();\nconst events = new EventBus();\nconst eventEmitter = new MailboxEventEmitter();\nlet mailbox: SqliteMailbox | undefined;\nconst clients = new Set<ClientState>();\nlet pendingRequests = 0;\nlet idleTimer: ReturnType<typeof setTimeout> | undefined;\nlet stopping = false;\nlet stopAutoCompact: (() => void) | undefined;\n\nconst serverInfo: MailboxProjectServerInfo = {\n protocolVersion: MAILBOX_PROJECT_SERVER_PROTOCOL_VERSION,\n pid: process.pid,\n projectDir,\n endpoint,\n startedAt,\n};\n\nfunction writeEncoded(state: ClientState, encoded: string): void {\n if (state.socket.destroyed) return;\n // A client that has stopped draining must not be allowed to grow the\n // owner's heap one broadcast at a time. `writableLength` is what is still\n // queued in this socket, so checking it before writing bounds the worst\n // case at roughly one message beyond the cap.\n if (state.socket.writableLength > MAX_CLIENT_WRITE_BUFFER_BYTES) {\n state.socket.destroy(new Error('Mailbox client fell too far behind on reads'));\n return;\n }\n state.socket.write(encoded);\n}\n\nfunction send(state: ClientState, message: MailboxProjectServerMessage): void {\n if (state.socket.destroyed) return;\n writeEncoded(state, encodeMailboxProjectServerMessage(message));\n}\n\n/**\n * Encode once, write to every client.\n *\n * Serializing inside the per-client loop meant the same payload was\n * stringified once per connected client. Mailbox snapshot events are tens of\n * KB, so a handful of attached surfaces (TUI, WebUI, HQ) turned every event\n * into a multiple of that in short-lived garbage \u2014 visible as a sawtooth of\n * hundreds of MB in a daemon whose database is single-digit MB.\n */\nfunction broadcast(message: MailboxProjectServerMessage): void {\n if (clients.size === 0) return;\n const encoded = encodeMailboxProjectServerMessage(message);\n for (const state of clients) writeEncoded(state, encoded);\n}\n\nevents.onAny((event, payload) => {\n if (event.startsWith('mailbox.')) broadcast({ type: 'event', event, payload });\n});\neventEmitter.subscribe((event) => broadcast({ type: 'mailbox-event', event }));\n\nfunction serverStatus(): MailboxServerOperations['ping']['result'] {\n const databasePath = mailbox?.databasePath ?? path.join(projectDir, SQLITE_MAILBOX_FILE);\n return {\n ...serverInfo,\n clients: clients.size,\n pendingRequests,\n messagePath: databasePath,\n databasePath,\n storageKind: 'sqlite',\n };\n}\n\nasync function dispatch(op: MailboxServerOperationName, rawArgs: unknown): Promise<unknown> {\n const activeMailbox = mailbox;\n if (activeMailbox === undefined) throw new Error('Mailbox SQLite owner is not initialized');\n switch (op) {\n case 'ping':\n return serverStatus();\n case 'send': {\n const args = rawArgs as MailboxServerOperations['send']['args'];\n return activeMailbox.send(args.input);\n }\n case 'sendRuntimeControl': {\n const args = rawArgs as MailboxServerOperations['sendRuntimeControl']['args'];\n return activeMailbox.sendRuntimeControl(args.input);\n }\n case 'query': {\n const args = rawArgs as MailboxServerOperations['query']['args'];\n return activeMailbox.query(args.query);\n }\n case 'ack': {\n const args = rawArgs as MailboxServerOperations['ack']['args'];\n return activeMailbox.ack(args.input);\n }\n case 'ackMany': {\n const args = rawArgs as MailboxServerOperations['ackMany']['args'];\n return activeMailbox.ackMany(args.input);\n }\n case 'unreadCount': {\n const args = rawArgs as MailboxServerOperations['unreadCount']['args'];\n return activeMailbox.unreadCount(args.forAgentId, args.sessionId);\n }\n case 'softDelete': {\n const args = rawArgs as MailboxServerOperations['softDelete']['args'];\n return activeMailbox.softDelete(args.mailId, args.by);\n }\n case 'restore': {\n const args = rawArgs as MailboxServerOperations['restore']['args'];\n return activeMailbox.restore(args.mailId);\n }\n case 'registerAgent': {\n const args = rawArgs as MailboxServerOperations['registerAgent']['args'];\n return activeMailbox.registerAgent(args.input);\n }\n case 'deregisterAgent': {\n const args = rawArgs as MailboxServerOperations['deregisterAgent']['args'];\n return activeMailbox.deregisterAgent(args.agentId);\n }\n case 'heartbeat': {\n const args = rawArgs as MailboxServerOperations['heartbeat']['args'];\n return activeMailbox.heartbeat(args.input);\n }\n case 'getAgentStatuses':\n return activeMailbox.getAgentStatuses();\n case 'getOnlineAgents':\n return activeMailbox.getOnlineAgents();\n case 'purgeAgents': {\n const args = rawArgs as MailboxServerOperations['purgeAgents']['args'];\n return activeMailbox.purgeAgents(args.maxAgeMs);\n }\n case 'registerClient': {\n const args = rawArgs as MailboxServerOperations['registerClient']['args'];\n return activeMailbox.registerClient(args.input);\n }\n case 'deregisterClient': {\n const args = rawArgs as MailboxServerOperations['deregisterClient']['args'];\n return activeMailbox.deregisterClient(args.clientId);\n }\n case 'clientHeartbeat': {\n const args = rawArgs as MailboxServerOperations['clientHeartbeat']['args'];\n return activeMailbox.clientHeartbeat(args.input);\n }\n case 'getClientStatuses':\n return activeMailbox.getClientStatuses();\n case 'purgeClients':\n return activeMailbox.purgeClients();\n case 'clearAll':\n return activeMailbox.clearAll();\n case 'purgeStale': {\n const args = rawArgs as MailboxServerOperations['purgeStale']['args'];\n return activeMailbox.purgeStale(args.options);\n }\n case 'autoCompact': {\n const args = rawArgs as MailboxServerOperations['autoCompact']['args'];\n return activeMailbox.autoCompact(args.options);\n }\n case 'credentialIssue': {\n const args = rawArgs as MailboxServerOperations['credentialIssue']['args'];\n return activeMailbox.credentialIssue(args.options);\n }\n case 'credentialVerify': {\n const args = rawArgs as MailboxServerOperations['credentialVerify']['args'];\n return activeMailbox.credentialVerify(args.credentialId, args.secret);\n }\n case 'credentialRevoke': {\n const args = rawArgs as MailboxServerOperations['credentialRevoke']['args'];\n return activeMailbox.credentialRevoke(args.credentialId, args.reason, args.by);\n }\n case 'credentialRotate': {\n const args = rawArgs as MailboxServerOperations['credentialRotate']['args'];\n return activeMailbox.credentialRotate(args.credentialId, args.options);\n }\n case 'credentialGet': {\n const args = rawArgs as MailboxServerOperations['credentialGet']['args'];\n return activeMailbox.credentialGet(args.credentialId);\n }\n case 'credentialList':\n return activeMailbox.credentialList();\n case 'credentialStatusCounts':\n return activeMailbox.credentialStatusCounts();\n }\n}\n\nfunction handleMessage(state: ClientState, message: MailboxProjectServerClientMessage): void {\n state.lastSeenAt = Date.now();\n if (message.type === 'heartbeat') return;\n if (message.type === 'shutdown') {\n send(state, {\n type: 'response',\n id: message.id,\n ok: true,\n result: { stopped: true, pid: process.pid, reason: message.reason },\n });\n setImmediate(() => void stop(message.reason ?? 'client-request'));\n return;\n }\n pendingRequests++;\n void dispatch(message.op, message.args)\n .then((result) => {\n // JSON.stringify omits `undefined` object properties. Keep successful\n // void operations structurally valid for the client runtime guard.\n send(state, { type: 'response', id: message.id, ok: true, result: result ?? null });\n })\n .catch((error) => {\n send(state, {\n type: 'response',\n id: message.id,\n ok: false,\n error: error instanceof Error ? error.message : String(error),\n errorName: error instanceof Error ? error.name : undefined,\n });\n })\n .finally(() => {\n pendingRequests = Math.max(0, pendingRequests - 1);\n // A client may disconnect while its last request is still settling.\n // The close handler cannot arm the idle timer while pendingRequests > 0,\n // so re-check after every request or an owner can remain alive forever.\n scheduleIdleStop();\n });\n}\n\nfunction onData(state: ClientState, chunk: string): void {\n state.lastSeenAt = Date.now();\n state.buffer += chunk;\n while (true) {\n const newline = state.buffer.indexOf('\\n');\n if (newline < 0) {\n if (state.buffer.length > MAILBOX_PROJECT_SERVER_MAX_FRAME_CHARS) {\n state.socket.destroy(new Error('Mailbox request frame exceeded maximum size'));\n }\n return;\n }\n if (newline > MAILBOX_PROJECT_SERVER_MAX_FRAME_CHARS) {\n state.socket.destroy(new Error('Mailbox request frame exceeded maximum size'));\n return;\n }\n const line = state.buffer.slice(0, newline);\n state.buffer = state.buffer.slice(newline + 1);\n if (!line) continue;\n let parsed: unknown;\n try {\n parsed = JSON.parse(line) as unknown;\n } catch {\n state.socket.destroy(new Error('Invalid mailbox project server request'));\n return;\n }\n if (!isMailboxProjectServerClientMessage(parsed)) {\n state.socket.destroy(new Error('Invalid mailbox project server request'));\n return;\n }\n handleMessage(state, parsed);\n }\n}\n\nfunction scheduleIdleStop(): void {\n if (stopping || clients.size > 0 || pendingRequests > 0) return;\n if (idleTimer) clearTimeout(idleTimer);\n idleTimer = setTimeout(() => void stop('idle-timeout'), idleMs);\n idleTimer.unref?.();\n}\n\nasync function writeMetadata(): Promise<void> {\n await fsPromises.mkdir(projectDir, { recursive: true });\n const temporary = `${metadataPath}.${process.pid}.tmp`;\n await fsPromises.writeFile(temporary, `${JSON.stringify(serverStatus(), null, 2)}\\n`, {\n encoding: 'utf8',\n mode: 0o600,\n });\n try {\n await fsPromises.rename(temporary, metadataPath);\n } catch {\n await fsPromises.rm(metadataPath, { force: true });\n await fsPromises.rename(temporary, metadataPath);\n }\n}\n\nasync function removeOwnedMetadata(): Promise<void> {\n try {\n const current = JSON.parse(await fsPromises.readFile(metadataPath, 'utf8')) as {\n pid?: number;\n };\n if (current.pid === process.pid) await fsPromises.rm(metadataPath, { force: true });\n } catch {\n // Missing or replaced metadata does not belong to this process.\n }\n}\n\nasync function stop(_reason: string): Promise<void> {\n if (stopping) return;\n stopping = true;\n if (idleTimer) clearTimeout(idleTimer);\n idleTimer = undefined;\n clearInterval(leaseSweep);\n stopAutoCompact?.();\n // Stop accepting new clients, then actively close the existing sockets.\n // Waiting for server.close() before closing them deadlocks explicit shutdown:\n // the requester keeps its IPC socket open while server.close() waits for\n // that same socket to disappear.\n const serverClosed = new Promise<void>((resolve) => server.close(() => resolve()));\n for (const state of clients) state.socket.end();\n const forceCloseTimer = setTimeout(() => {\n for (const state of clients) state.socket.destroy();\n }, 1_000);\n forceCloseTimer.unref?.();\n await serverClosed;\n clearTimeout(forceCloseTimer);\n for (const state of clients) state.socket.destroy();\n clients.clear();\n await mailbox?.close().catch(() => {});\n mailbox = undefined;\n await removeOwnedMetadata();\n if (process.platform !== 'win32') {\n await fsPromises.rm(endpoint, { force: true }).catch(() => {});\n }\n}\n\nensureMailboxProjectServerSocketDirectory(endpoint);\nconst server = net.createServer((socket) => {\n if (stopping) {\n socket.destroy();\n return;\n }\n if (idleTimer) clearTimeout(idleTimer);\n idleTimer = undefined;\n socket.setEncoding('utf8');\n const state: ClientState = { socket, buffer: '', lastSeenAt: Date.now() };\n clients.add(state);\n send(state, { type: 'hello', ...serverInfo });\n socket.on('data', (chunk: string) => onData(state, chunk));\n socket.on('error', () => {\n // Close handling below owns cleanup; socket errors must not crash the owner.\n });\n socket.on('close', () => {\n clients.delete(state);\n scheduleIdleStop();\n });\n});\n\nconst leaseSweep = setInterval(() => {\n const cutoff = Date.now() - clientLeaseMs;\n for (const state of clients) {\n if (state.lastSeenAt < cutoff) state.socket.destroy();\n }\n scheduleIdleStop();\n}, leaseSweepMs);\nleaseSweep.unref?.();\n\nlet probingExistingEndpoint = false;\nfunction listenForOwnership(): void {\n server.listen(endpoint);\n}\n\nserver.on('error', (error: NodeJS.ErrnoException) => {\n if (error.code === 'EADDRINUSE' && process.platform === 'win32') {\n process.exitCode = 0;\n return;\n }\n if (error.code === 'EADDRINUSE' && !probingExistingEndpoint) {\n probingExistingEndpoint = true;\n const probe = net.createConnection(endpoint);\n probe.once('connect', () => {\n probe.destroy();\n process.exitCode = 0;\n });\n probe.once('error', () => {\n probe.destroy();\n try {\n fs.rmSync(endpoint, { force: true });\n } catch {\n // Another contender may already have removed the stale socket.\n }\n probingExistingEndpoint = false;\n listenForOwnership();\n });\n return;\n }\n process.exitCode = 1;\n});\n\nserver.on('listening', () => {\n if (process.platform !== 'win32') {\n try {\n fs.chmodSync(endpoint, 0o600);\n } catch {\n // The containing 0700 directory still restricts access.\n }\n }\n try {\n // The IPC bind is the ownership election. Open SQLite only after winning\n // that election so losing detached contenders never become DB owners.\n mailbox = new SqliteMailbox(projectDir, events, eventEmitter);\n } catch {\n void stop('sqlite-initialization-failed').finally(() => {\n process.exitCode = 1;\n });\n return;\n }\n stopAutoCompact = mailbox.startAutoCompactTimer();\n void writeMetadata()\n .then(() => scheduleIdleStop())\n .catch(() => {\n void stop('metadata-write-failed').finally(() => {\n process.exitCode = 1;\n });\n });\n});\n\nlistenForOwnership();\n\nfor (const signal of ['SIGINT', 'SIGTERM'] as const) {\n process.once(signal, () => {\n void stop(signal).finally(() => {\n process.exitCode = 0;\n });\n });\n}\n", "/**\n * EventBus \u2014 observe-only typed event bus.\n * Subscribers cannot modify or cancel. Subscriber exceptions are caught.\n */\n\nimport type { AgentEventMap } from './events/agent-events.js';\nimport type { BrainEventMap } from './events/brain-events.js';\nimport type { FileEventMap } from './events/file-events.js';\nimport type { FleetEventMap } from './events/fleet-events.js';\nimport type { MemoryEventMap } from './events/memory-events.js';\nimport type { NetworkEventMap } from './events/network-events.js';\nimport type { ProcessEventMap } from './events/process-events.js';\nimport type { ProviderEventMap } from './events/provider-events.js';\nimport type { SddEventMap } from './events/sdd-events.js';\nimport type { SessionEventMap } from './events/session-events.js';\nimport type { ToolEventMap } from './events/tool-events.js';\nimport type { WorktreeEventMap } from './events/worktree-events.js';\n\n/** Safety cap on the wildcard listener array to prevent unbounded growth from\n * undisposed onPattern/onRegex/onAny callers. No legitimate usage needs more\n * than this \u2014 past the cap, new registrations are rejected with a warning. */\nconst MAX_WILDCARDS = 500;\n\n/**\n * Safety cap on total named listeners (all event names combined) to prevent\n * unbounded heap growth when callers forget to dispose their `.on()` registrations.\n * While each `.on()` returns a disposer, long-lived sessions with missing cleanup\n * could accumulate thousands of listener closures (each holding references to its\n * captured scope). Past this cap, new `.on()` registrations are rejected with a\n * logged warning and a no-op disposer is returned, making the leak visible without\n * crashing the process.\n */\nconst MAX_NAMED_LISTENERS = 2000;\n\n/** Distress signals the BrainMonitor watches. See `coordination/brain-monitor.ts`. */\nexport type BrainInterventionKind =\n | 'tool_failure_streak'\n | 'error_storm'\n | 'agent_stall'\n | 'file_churn';\n\n/**\n * Structural shape of a tracked agent as flushed by AgentStatusTracker. Kept\n * structural (not imported from the root `session-registry` module) so the\n * low-level kernel layer takes on no dependency on composition modules. The\n * real `AgentEntry` is assignable to this.\n */\nexport interface TrackedAgentSnapshot {\n id: string;\n name: string;\n startedAt?: string | undefined;\n status: string;\n currentTool?: string | undefined;\n currentTask?: string | undefined;\n taskId?: string | undefined;\n iterations: number;\n toolCalls: number;\n costUsd?: number | undefined;\n tokensIn?: number | undefined;\n tokensOut?: number | undefined;\n ctxPct?: number | undefined;\n model?: string | undefined;\n partialText?: string | undefined;\n todos?:\n | Array<{\n id: string;\n content: string;\n status: 'pending' | 'in_progress' | 'completed';\n activeForm?: string | undefined;\n }>\n | undefined;\n latestPrompt?: string | undefined;\n latestPromptAt?: number | undefined;\n lastActivityAt: string;\n}\n\nexport interface EventMap\n extends AgentEventMap,\n BrainEventMap,\n SessionEventMap,\n ProviderEventMap,\n ProcessEventMap,\n NetworkEventMap,\n FileEventMap,\n ToolEventMap,\n MemoryEventMap,\n SddEventMap,\n WorktreeEventMap,\n FleetEventMap {}\n\nexport type EventName = keyof EventMap;\nexport type Listener<E extends EventName> = (payload: EventMap[E]) => void;\n\nexport interface EventLogger {\n error(msg: string, ctx?: unknown): void | undefined;\n}\n\nexport class EventBus {\n protected readonly listeners = new Map<EventName, Set<Listener<EventName>>>();\n protected readonly wildcards: Array<{\n match: (event: string) => boolean;\n fn: (event: string, payload: unknown) => void;\n }> = [];\n protected logger?: EventLogger | undefined;\n /**\n * Dispatch arrays cached per event name, rebuilt lazily after a\n * subscription change. See {@link namedSnapshot}. Every mutation of\n * `listeners` must invalidate the matching entry, and every mutation of\n * `wildcards` must null `wildcardSnapshotCache` \u2014 a missed invalidation\n * means an emit dispatches to a stale listener set.\n */\n private readonly listenerSnapshots = new Map<EventName, readonly Listener<EventName>[]>();\n private wildcardSnapshotCache:\n | readonly {\n match: (event: string) => boolean;\n fn: (event: string, payload: unknown) => void;\n }[]\n | null = null;\n\n setLogger(logger: EventLogger): void {\n this.logger = logger;\n }\n\n on<E extends EventName>(event: E, fn: Listener<E>): () => void {\n // Prevent unbounded accumulation of named listeners when callers\n // forget to dispose their registrations. Past the cap, new `.on()`\n // calls are rejected with a warning and a no-op disposer \u2014 the\n // process keeps running and the developer sees the symptom.\n if (this.listenerCount() >= MAX_NAMED_LISTENERS) {\n this.logger?.error(\n `EventBus named listener limit (~${MAX_NAMED_LISTENERS}) reached \u2014 rejecting on(\"${event}\"). ` +\n 'Callers must dispose their named listeners to prevent unbounded memory growth.',\n );\n return () => {};\n }\n let set = this.listeners.get(event);\n if (!set) {\n set = new Set();\n this.listeners.set(event, set);\n }\n set.add(fn as Listener<EventName>);\n this.listenerSnapshots.delete(event);\n return () => this.off(event, fn);\n }\n\n off<E extends EventName>(event: E, fn: Listener<E>): void {\n const set = this.listeners.get(event);\n if (!set) return;\n set.delete(fn as Listener<EventName>);\n this.listenerSnapshots.delete(event);\n // Prune the now-empty Set so the map doesn't accumulate dead entries that\n // listenerCount() and iteration would otherwise walk. Safe during an\n // in-flight emit() because emit snapshots the Set before iterating, so it\n // never observes the live Set being deleted.\n if (set.size === 0) this.listeners.delete(event);\n }\n\n once<E extends EventName>(event: E, fn: Listener<E>): () => void {\n const wrapper: Listener<E> = (payload) => {\n this.off(event, wrapper as Listener<EventName>);\n (fn as Listener<E>)(payload);\n };\n this.on(event, wrapper as Listener<E>);\n return () => {\n this.off(event, wrapper as Listener<EventName>);\n };\n }\n\n /**\n * Subscribe to all events, regardless of name. Short-hand for\n * `onPattern('*')`. Use for logging, debugging, or forwarding every\n * event to another bus (as FleetBus does).\n *\n * Returns an unsubscribe function.\n */\n onAny(fn: (event: string, payload: unknown) => void): () => void {\n return this.onPattern('*', fn);\n }\n\n /**\n * Subscribe to all events whose name matches a glob-style prefix.\n * `'tool.*'` matches `tool.started`, `tool.executed`, `tool.progress`, etc.\n * `'*'` matches every event.\n *\n * The handler receives `(eventName, payload)` with the event name as a\n * string and the payload as `unknown`. Use for logging, debugging, or\n * metrics collection across a family of events.\n *\n * Returns an unsubscribe function.\n */\n onPattern(pattern: string, fn: (event: string, payload: unknown) => void): () => void {\n if (this.wildcards.length >= MAX_WILDCARDS) {\n this.logger?.error(\n `EventBus wildcard limit (${MAX_WILDCARDS}) reached \u2014 rejecting onPattern(\"${pattern}\"). ` +\n 'Callers must dispose their wildcard listeners to prevent unbounded growth.',\n );\n return () => {};\n }\n const match = makePatternMatcher(pattern);\n const entry = { match, fn };\n this.wildcards.push(entry);\n this.wildcardSnapshotCache = null;\n return () => {\n const idx = this.wildcards.indexOf(entry);\n if (idx >= 0) {\n this.wildcards.splice(idx, 1);\n this.wildcardSnapshotCache = null;\n }\n };\n }\n\n /**\n * Subscribe to all events whose name matches a RegExp.\n * More flexible than `onPattern` \u2014 use when you need regex features\n * (alternation, character classes, capture groups).\n *\n * Returns an unsubscribe function.\n */\n onRegex(regex: RegExp, fn: (event: string, payload: unknown) => void): () => void {\n if (this.wildcards.length >= MAX_WILDCARDS) {\n this.logger?.error(\n `EventBus wildcard limit (${MAX_WILDCARDS}) reached \u2014 rejecting onRegex(${regex}). ` +\n 'Callers must dispose their wildcard listeners to prevent unbounded growth.',\n );\n return () => {};\n }\n const entry = { match: (e: string) => regex.test(e), fn };\n this.wildcards.push(entry);\n this.wildcardSnapshotCache = null;\n return () => {\n const idx = this.wildcards.indexOf(entry);\n if (idx >= 0) {\n this.wildcards.splice(idx, 1);\n this.wildcardSnapshotCache = null;\n }\n };\n }\n\n emit<E extends EventName>(event: E, payload: EventMap[E]): void {\n const snapshot = this.namedSnapshot(event);\n if (snapshot !== undefined) {\n for (const fn of snapshot) {\n try {\n (fn as Listener<E>)(payload);\n } catch (err) {\n this.logger?.error(`EventBus listener for \"${event}\" threw`, err);\n }\n }\n }\n if (this.wildcards.length > 0) {\n const name = event as string;\n for (const { match, fn } of this.wildcardSnapshot()) {\n if (!match(name)) continue;\n try {\n fn(name, payload);\n } catch (err) {\n this.logger?.error(`EventBus wildcard listener for \"${name}\" threw`, err);\n }\n }\n }\n }\n\n /**\n * Dispatch array for one event name, or `undefined` when nothing is\n * subscribed.\n *\n * Dispatch iterates a stable array rather than the live Set so a listener\n * that subscribes or unsubscribes mid-emit cannot change what this round\n * delivers: an addition fires from the next emit, a removal may still fire\n * this round. That is the contract callers rely on, and it is unchanged.\n *\n * What changed is who pays for it. Building the array per emit did O(number\n * of listeners) copying on every event, including `tool.progress` and\n * streaming deltas \u2014 the highest-frequency paths in the process. The array\n * is now cached and rebuilt only when the subscription set actually changes,\n * which is wiring time and essentially never during a run. Measured at 2M\n * emits with 12 named + 6 wildcard listeners: 207 ms \u2192 141 ms.\n *\n * This is a throughput win, not a footprint one: the per-emit arrays died in\n * the nursery and never showed up as retained heap (measured heap growth was\n * the same either way). Do not cite this as a memory fix.\n *\n * A mutation during dispatch invalidates the cache for the *next* emit while\n * the in-flight loop keeps walking the array it started with \u2014 which is\n * exactly the snapshot semantics described above.\n */\n private namedSnapshot(event: EventName): readonly Listener<EventName>[] | undefined {\n const cached = this.listenerSnapshots.get(event);\n if (cached !== undefined) return cached;\n const set = this.listeners.get(event);\n if (!set || set.size === 0) return undefined;\n const snapshot = [...set];\n this.listenerSnapshots.set(event, snapshot);\n return snapshot;\n }\n\n /** Wildcard counterpart to {@link namedSnapshot}; same caching rationale. */\n private wildcardSnapshot(): readonly {\n match: (event: string) => boolean;\n fn: (event: string, payload: unknown) => void;\n }[] {\n this.wildcardSnapshotCache ??= this.wildcards.slice();\n return this.wildcardSnapshotCache;\n }\n\n /**\n * Emit a plugin-defined event that is intentionally outside EventMap.\n * Custom events are delivered to wildcard/pattern listeners only; typed\n * listeners remain reserved for core EventMap keys.\n */\n emitCustom(event: string, payload: unknown): void {\n if (this.wildcards.length === 0) return;\n for (const { match, fn } of this.wildcardSnapshot()) {\n if (!match(event)) continue;\n try {\n fn(event, payload);\n } catch (err) {\n this.logger?.error(`EventBus wildcard listener for \"${event}\" threw`, err);\n }\n }\n }\n\n clear(): void {\n this.listeners.clear();\n this.wildcards.length = 0;\n this.listenerSnapshots.clear();\n this.wildcardSnapshotCache = null;\n }\n\n /**\n * V2-D: introspection helper. Pass an `event` to count handlers for a\n * single key, or omit to get the total across every event. Used by the\n * leak-detection smoke test to flag handler accumulation across runs.\n * Does NOT include wildcard listeners.\n */\n listenerCount(event?: EventName): number {\n if (event !== undefined) return this.listeners.get(event)?.size ?? 0;\n let total = 0;\n for (const set of this.listeners.values()) total += set.size;\n return total;\n }\n\n /**\n * Number of wildcard listeners currently registered.\n */\n wildcardCount(): number {\n return this.wildcards.length;\n }\n\n /**\n * True if anything would receive an emit for `event` \u2014 a named listener\n * OR a wildcard/regex pattern that matches the event name. Unlike\n * `listenerCount`, this DOES account for wildcards, so callers that gate\n * behavior on \"is anyone listening?\" (e.g. SubagentBudget deciding whether\n * to negotiate a soft limit vs hard-stop) don't misfire when the only\n * subscriber is a pattern listener like the FleetBus's `onPattern('*')`.\n */\n hasListenerFor(event: string): boolean {\n if ((this.listeners.get(event as EventName)?.size ?? 0) > 0) return true;\n return this.wildcards.some((w) => w.match(event));\n }\n}\n\n// \u2500\u2500 Scoped EventBus \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * A decorator over `EventBus` that records every listener registration\n * (`.on`, `.once`, `.onPattern`, `.onRegex`) so that `teardown()` can\n * remove all of them at once \u2014 preventing the memory leaks that occur\n * when dynamic plugins or long-lived TUI/WebUI interfaces forget to\n * call `.off()` during session termination.\n *\n * Usage:\n * ```ts\n * const bus = new ScopedEventBus();\n * bus.on('tool.executed', handler1); // tracked\n * bus.on('provider.response', handler2); // tracked\n * bus.onPattern('subagent.*', handler3); // tracked\n * // ... later, when the plugin or session is torn down:\n * bus.teardown(); // removes all three listeners\n * ```\n *\n * Also implements `Disposable` (via `[Symbol.dispose]`) for use with\n * the `using` keyword in Node \u2265 22, or can be used manually with\n * `bus.teardown()`.\n */\nexport class ScopedEventBus extends EventBus {\n // Track registrations by a unique counter key so that EventBus.once()'s\n // internal listener-removal doesn't affect our tracking (once removes the\n // fn from EventBus but we still need to call our unsub during teardown).\n private readonly registrations = new Map<number, () => void>();\n private nextKey = 0;\n\n /**\n * Identical to `EventBus.on` but the listener is tracked so that\n * `teardown()` will remove it automatically.\n */\n override on<E extends EventName>(event: E, fn: Listener<E>): () => void {\n const key = this.nextKey++;\n const unsub = super.on(event, fn);\n this.registrations.set(key, unsub);\n return () => {\n this.registrations.delete(key);\n unsub();\n };\n }\n\n /**\n * Identical to `EventBus.once` but the listener is tracked so that\n * `teardown()` will remove it automatically.\n *\n * Uses EventBus's public API directly to avoid triggering our own `on()`\n * override (which would consume a key slot for the wrapper, then orphan\n * our registration entry under a different key).\n *\n * When the wrapper fires, it cleans up BOTH the underlying EventBus\n * listener AND the tracking entry \u2014 so `scopedListenerCount` returns to\n * its pre-`once()` value without requiring the caller to invoke the\n * returned unsubscribe. The returned `unsub` is still safe to call\n * after auto-removal (its delete is a no-op and its off() finds\n * nothing to remove).\n */\n override once<E extends EventName>(event: E, fn: Listener<E>): () => void {\n const key = this.nextKey++;\n const wrapper: Listener<E> = (payload) => {\n // Bypass ScopedEventBus.on() \u2014 go straight to EventBus.off() so we\n // don't recurse and don't consume another key.\n EventBus.prototype.off.call(this, event, wrapper as Listener<EventName>);\n // Drop the tracking entry so scopedListenerCount is honest. Done\n // before calling `fn` so a handler that calls scopedListenerCount\n // mid-fire sees the post-removal state.\n this.registrations.delete(key);\n (fn as Listener<E>)(payload);\n };\n // Use the EventBus prototype directly to register without triggering\n // ScopedEventBus.on() which would consume a second key.\n EventBus.prototype.on.call(this, event, wrapper as Listener<EventName>);\n const unsub = () => {\n this.registrations.delete(key);\n EventBus.prototype.off.call(this, event, wrapper as Listener<EventName>);\n };\n this.registrations.set(key, unsub);\n return unsub;\n }\n\n /**\n * Subscribe to all events. Alias for `onPattern('*')` \u2014 the listener is\n * tracked so that `teardown()` will remove it automatically.\n */\n override onAny(fn: (event: string, payload: unknown) => void): () => void {\n if (this.wildcards.length >= MAX_WILDCARDS) {\n this.logger?.error(\n `EventBus wildcard limit (${MAX_WILDCARDS}) reached \u2014 rejecting onAny(). ` +\n 'Callers must dispose their wildcard listeners to prevent unbounded growth.',\n );\n return () => {};\n }\n const key = this.nextKey++;\n // Call EventBus.onPattern directly so the wrapper-consumption in\n // ScopedEventBus.on() doesn't re-enter and create a second registration slot.\n const unsub = EventBus.prototype.onPattern.call(this, '*', fn);\n this.registrations.set(key, unsub);\n return () => {\n this.registrations.delete(key);\n unsub();\n };\n }\n\n /**\n * Identical to `EventBus.onPattern` but the listener is tracked so that\n * `teardown()` will remove it automatically.\n */\n override onPattern(pattern: string, fn: (event: string, payload: unknown) => void): () => void {\n // Pre-check the cap before delegating to EventBus.onPattern so we never\n // store a no-op disposer in our registrations map, which would inflate\n // scopedListenerCount metrics without providing any cleanup.\n if (this.wildcards.length >= MAX_WILDCARDS) {\n this.logger?.error(\n `EventBus wildcard limit (${MAX_WILDCARDS}) reached \u2014 rejecting onPattern(\"${pattern}\"). ` +\n 'Callers must dispose their wildcard listeners to prevent unbounded growth.',\n );\n return () => {};\n }\n const key = this.nextKey++;\n const unsub = super.onPattern(pattern, fn);\n this.registrations.set(key, unsub);\n return () => {\n this.registrations.delete(key);\n unsub();\n };\n }\n\n /**\n * Identical to `EventBus.onRegex` but the listener is tracked so that\n * `teardown()` will remove it automatically.\n */\n override onRegex(regex: RegExp, fn: (event: string, payload: unknown) => void): () => void {\n if (this.wildcards.length >= MAX_WILDCARDS) {\n this.logger?.error(\n `EventBus wildcard limit (${MAX_WILDCARDS}) reached \u2014 rejecting onRegex(${regex}). ` +\n 'Callers must dispose their wildcard listeners to prevent unbounded growth.',\n );\n return () => {};\n }\n const key = this.nextKey++;\n const unsub = super.onRegex(regex, fn);\n this.registrations.set(key, unsub);\n return () => {\n this.registrations.delete(key);\n unsub();\n };\n }\n\n /**\n * Remove every listener that was registered through this scoped bus.\n * Idempotent \u2014 calling it multiple times is safe.\n *\n * Also available as `[Symbol.dispose]` for explicit resource management:\n * ```ts\n * using scope = new ScopedEventBus();\n * scope.on('tool.executed', handler);\n * // automatically teardown()'d when scope exits\n * ```\n */\n teardown(): void {\n for (const unsub of this.registrations.values()) {\n try {\n unsub();\n } catch {\n /* ignore \u2014 best effort */\n }\n }\n this.registrations.clear();\n this.clear();\n }\n\n /** Alias for `teardown()` \u2014 enables `using new ScopedEventBus()` in Node \u2265 22. */\n [Symbol.dispose](): void {\n this.teardown();\n }\n\n /** Number of tracked registrations. */\n get scopedListenerCount(): number {\n return this.registrations.size;\n }\n}\n\n/**\n * Reused matcher for the `'*'` wildcard \u2014 equivalent to `() => true`\n * but allocated once at module load rather than on every `onPattern('*')`\n * or `onAny()` call. The wildcard array can grow to hundreds of entries\n * during long-lived sessions, so caching the function avoids GC pressure.\n */\nconst MATCH_ALL: (event: string) => boolean = () => true;\n\n/**\n * Convert a glob-style pattern to a matcher function.\n * Only supports `*` at the end of a prefix \u2014 `'tool.*'` becomes\n * \"starts with tool.\". `'*'` matches everything.\n */\nfunction makePatternMatcher(pattern: string): (event: string) => boolean {\n if (pattern === '*') return MATCH_ALL;\n if (pattern.endsWith('.*')) {\n const prefix = pattern.slice(0, -2);\n return (e: string) => e.startsWith(`${prefix}.`);\n }\n // Exact match fallback\n return (e: string) => e === pattern;\n}\n", "/**\n * Process-wide performance profile.\n *\n * `WRONGSTACK_PERF_PROFILE` (alias `WSTACK_PERF_PROFILE`):\n * - `balanced` (default) \u2014 current throughput-oriented defaults\n * - `frugal` / `cimri` \u2014 lower CPU concurrency, leaner SQLite caches,\n * coarser UI stream paint. Correctness and APIs unchanged.\n */\n\nexport type PerfProfile = 'balanced' | 'frugal';\n\n/**\n * Long-lived IPC daemons default to `frugal`.\n *\n * The SQLite pragmas below are per *connection*, and a daemon holds its\n * connections for its whole lifetime \u2014 the codebase-index daemon measured\n * 336MB RSS, essentially all of it the 128MiB page cache plus 512MiB mmap\n * reservation, while sitting idle. A foreground host pays that cost briefly;\n * a daemon pays it for hours. An explicit `WRONGSTACK_PERF_PROFILE` from the\n * operator still wins in both directions.\n */\nlet daemonDefaults = false;\n\n/** Call once from a daemon entry point, before opening any store. */\nexport function useDaemonPerfDefaults(): void {\n daemonDefaults = true;\n}\n\n/** Resolve the active profile from the environment (evaluated each call). */\nexport function getPerfProfile(): PerfProfile {\n const explicit = process.env.WRONGSTACK_PERF_PROFILE ?? process.env.WSTACK_PERF_PROFILE;\n if (explicit === undefined || explicit.trim() === '') {\n return daemonDefaults ? 'frugal' : 'balanced';\n }\n const raw = explicit.trim().toLowerCase();\n if (raw === 'frugal' || raw === 'cimri' || raw === 'low' || raw === 'eco') {\n return 'frugal';\n }\n return 'balanced';\n}\n\nexport function isFrugalPerf(): boolean {\n return getPerfProfile() === 'frugal';\n}\n\n/** Parallel file-parse batch size for the codebase indexer. */\nexport function indexParallelBatchSize(availableCores: number): number {\n const cores = Math.max(1, Math.floor(availableCores) || 1);\n if (isFrugalPerf()) {\n // Serial-ish: at most 4 files concurrent, never more than core count.\n return Math.min(4, cores);\n }\n // Historical default: cores\u00D74, hard-capped at 40.\n return Math.min(cores * 4, 40);\n}\n\n/**\n * SQLite page-cache / mmap sizes in KiB (negative PRAGMA = KiB units for cache).\n * Frugal keeps correctness; just spends less RSS.\n */\nexport function sqliteCachePragmas(): { cacheSizeKiB: number; mmapBytes: number } {\n if (isFrugalPerf()) {\n return { cacheSizeKiB: 16_384, mmapBytes: 64 * 1024 * 1024 }; // 16 MiB / 64 MiB\n }\n return { cacheSizeKiB: 131_072, mmapBytes: 512 * 1024 * 1024 }; // 128 MiB / 512 MiB\n}\n\n/** sage store defaults (slightly smaller than index). */\nexport function SageCachePragmas(): { cacheSizeKiB: number; mmapBytes: number } {\n if (isFrugalPerf()) {\n return { cacheSizeKiB: 8_192, mmapBytes: 32 * 1024 * 1024 }; // 8 MiB / 32 MiB\n }\n return { cacheSizeKiB: 65_536, mmapBytes: 256 * 1024 * 1024 }; // 64 MiB / 256 MiB\n}\n\n/**\n * TUI stream paint interval. Higher = fewer React dispatches (less CPU/heap\n * churn). Balanced keeps the historical ~10fps; frugal ~6\u20137fps.\n */\nexport function tuiStreamFlushMs(): number {\n return isFrugalPerf() ? 150 : 100;\n}\n", "/**\n * MailboxEventEmitter \u2014 minimal pub/sub for real-time push to SSE clients.\n *\n * The HTTP bridge uses this to push `send`/`ack`/`delete` events to\n * connected SSE clients without requiring them to poll. Each event is a\n * shallow copy of the relevant data (message id, action, timestamp) \u2014\n * never the full mailbox state.\n *\n * The emitter is intentionally simple: a Set of listeners, add/remove,\n * and emit. No buffering, no replay \u2014 if a client connects after a send,\n * it won't receive past events (it should query first to catch up).\n *\n * @module mailbox-events\n */\n\nimport type { MailboxAudience } from './mailbox-types.js';\n\nexport type MailboxEventType = 'message.sent' | 'message.acked' | 'message.deleted' | 'message.restored';\n\nexport interface MailboxEvent {\n type: MailboxEventType;\n messageId: string;\n from?: string | undefined;\n to?: string | undefined;\n audience?: MailboxAudience | undefined;\n timestamp: string;\n}\n\nexport type MailboxEventListener = (event: MailboxEvent) => void;\n\nexport class MailboxEventEmitter {\n private listeners = new Set<MailboxEventListener>();\n\n subscribe(fn: MailboxEventListener): () => void {\n this.listeners.add(fn);\n return () => { this.listeners.delete(fn); };\n }\n\n emit(event: MailboxEvent): void {\n const snapshot = [...this.listeners];\n for (const fn of snapshot) {\n try { fn(event); } catch { /* listener must not crash the emitter */ }\n }\n }\n\n /** Number of active subscribers (for observability / metrics). */\n get subscriberCount(): number {\n return this.listeners.size;\n }\n\n clear(): void {\n this.listeners.clear();\n }\n}\n", "import { createHash } from 'node:crypto';\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { MAILBOX_PROJECT_SERVER_PROTOCOL_VERSION } from './mailbox-project-server-protocol.js';\n\nexport const MAILBOX_PROJECT_SERVER_METADATA_FILE = '.mailbox-server.json';\n\nfunction normalizeLocalPath(value: string): string {\n const resolved = path.resolve(value);\n return process.platform === 'win32' ? resolved.toLowerCase() : resolved;\n}\n\nexport function mailboxProjectServerKey(projectDir: string): string {\n return createHash('sha256')\n .update(normalizeLocalPath(projectDir))\n .digest('hex')\n .slice(0, 24);\n}\n\nexport function mailboxProjectServerEndpoint(projectDir: string): string {\n const key = mailboxProjectServerKey(projectDir);\n if (process.platform === 'win32') {\n return `\\\\\\\\.\\\\pipe\\\\wrongstack-mailbox-v${MAILBOX_PROJECT_SERVER_PROTOCOL_VERSION}-${key}`;\n }\n return path.join(\n os.tmpdir(),\n `wrongstack-mailbox-v${MAILBOX_PROJECT_SERVER_PROTOCOL_VERSION}`,\n `${key}.sock`,\n );\n}\n\nexport function mailboxProjectServerMetadataPath(projectDir: string): string {\n return path.join(path.resolve(projectDir), MAILBOX_PROJECT_SERVER_METADATA_FILE);\n}\n\nexport function ensureMailboxProjectServerSocketDirectory(endpoint: string): void {\n if (process.platform !== 'win32') {\n fs.mkdirSync(path.dirname(endpoint), { recursive: true, mode: 0o700 });\n }\n}\n", "import type { MailboxEvent } from './mailbox-events.js';\nimport type {\n CredentialValidation,\n IssueCredentialOptions,\n MailboxCredential,\n} from './mailbox-credential-store.js';\nimport type {\n AgentHeartbeatInput,\n AgentRegistrationInput,\n AutoCompactOptions,\n AutoCompactResult,\n ClientHeartbeatInput,\n ClientRegistrationInput,\n ClientStatus,\n MailboxAckBatchInput,\n MailboxAckInput,\n MailboxAgentStatus,\n MailboxMessage,\n MailboxQuery,\n MailboxSendInput,\n PurgeOptions,\n PurgeResult,\n} from './mailbox-types.js';\n\nexport const MAILBOX_PROJECT_SERVER_PROTOCOL_VERSION = 3;\nexport const MAILBOX_PROJECT_SERVER_MAX_FRAME_CHARS = 16 * 1024 * 1024;\n\nexport interface MailboxProjectServerInfo {\n protocolVersion: number;\n pid: number;\n projectDir: string;\n endpoint: string;\n startedAt: string;\n}\n\nexport interface MailboxProjectServerStatus extends MailboxProjectServerInfo {\n clients: number;\n pendingRequests: number;\n /** Compatibility alias; points to databasePath for protocol v2+. */\n messagePath: string;\n databasePath: string;\n storageKind: 'sqlite' | 'legacy-test-adapter';\n}\n\nexport interface MailboxServerOperations {\n ping: { args: Record<string, never>; result: MailboxProjectServerStatus };\n send: { args: { input: MailboxSendInput }; result: MailboxMessage };\n sendRuntimeControl: {\n args: { input: Omit<MailboxSendInput, 'type'> & { type?: 'control' } };\n result: MailboxMessage;\n };\n query: { args: { query: MailboxQuery }; result: MailboxMessage[] };\n ack: { args: { input: MailboxAckInput }; result: MailboxMessage | null };\n ackMany: { args: { input: MailboxAckBatchInput }; result: MailboxMessage[] };\n unreadCount: {\n args: { forAgentId: string; sessionId?: string | undefined };\n result: number;\n };\n softDelete: {\n args: { mailId: string; by: string };\n result: MailboxMessage | null;\n };\n restore: { args: { mailId: string }; result: MailboxMessage | null };\n registerAgent: { args: { input: AgentRegistrationInput }; result: void };\n deregisterAgent: { args: { agentId: string }; result: void };\n heartbeat: { args: { input: AgentHeartbeatInput }; result: void };\n getAgentStatuses: { args: Record<string, never>; result: MailboxAgentStatus[] };\n getOnlineAgents: { args: Record<string, never>; result: MailboxAgentStatus[] };\n purgeAgents: { args: { maxAgeMs?: number | undefined }; result: number };\n registerClient: { args: { input: ClientRegistrationInput }; result: void };\n deregisterClient: { args: { clientId: string }; result: void };\n clientHeartbeat: { args: { input: ClientHeartbeatInput }; result: void };\n getClientStatuses: { args: Record<string, never>; result: ClientStatus[] };\n purgeClients: { args: Record<string, never>; result: number };\n clearAll: { args: Record<string, never>; result: void };\n purgeStale: { args: { options?: PurgeOptions | undefined }; result: PurgeResult };\n autoCompact: {\n args: { options?: AutoCompactOptions | undefined };\n result: AutoCompactResult;\n };\n credentialIssue: {\n args: { options: IssueCredentialOptions };\n result: { credential: MailboxCredential; secret: string };\n };\n credentialVerify: {\n args: { credentialId: string; secret: string };\n result: CredentialValidation;\n };\n credentialRevoke: {\n args: { credentialId: string; reason?: string | undefined; by?: string | undefined };\n result: boolean;\n };\n credentialRotate: {\n args: { credentialId: string; options?: Partial<IssueCredentialOptions> | undefined };\n result: { credential: MailboxCredential; secret: string } | null;\n };\n credentialGet: {\n args: { credentialId: string };\n result: MailboxCredential | null;\n };\n credentialList: {\n args: Record<string, never>;\n result: MailboxCredential[];\n };\n credentialStatusCounts: {\n args: Record<string, never>;\n result: Record<string, number>;\n };\n}\n\nexport type MailboxServerOperationName = keyof MailboxServerOperations;\n\nexport type MailboxProjectServerClientMessage =\n | {\n type: 'request';\n id: number;\n op: MailboxServerOperationName;\n args: unknown;\n }\n | { type: 'heartbeat' }\n | { type: 'shutdown'; id: number; reason?: string | undefined };\n\nconst MAILBOX_SERVER_OPERATION_NAMES: Readonly<Record<MailboxServerOperationName, true>> = {\n ping: true,\n send: true,\n sendRuntimeControl: true,\n query: true,\n ack: true,\n ackMany: true,\n unreadCount: true,\n softDelete: true,\n restore: true,\n registerAgent: true,\n deregisterAgent: true,\n heartbeat: true,\n getAgentStatuses: true,\n getOnlineAgents: true,\n purgeAgents: true,\n registerClient: true,\n deregisterClient: true,\n clientHeartbeat: true,\n getClientStatuses: true,\n purgeClients: true,\n clearAll: true,\n purgeStale: true,\n autoCompact: true,\n credentialIssue: true,\n credentialVerify: true,\n credentialRevoke: true,\n credentialRotate: true,\n credentialGet: true,\n credentialList: true,\n credentialStatusCounts: true,\n};\n\nfunction isRequestId(value: unknown): value is number {\n return Number.isSafeInteger(value) && (value as number) >= 0;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction hasString(record: Record<string, unknown>, key: string): boolean {\n return typeof record[key] === 'string' && (record[key] as string).length > 0;\n}\n\nfunction hasRecord(record: Record<string, unknown>, key: string): boolean {\n return isRecord(record[key]);\n}\n\nfunction isMailboxServerOperationArgs(\n op: MailboxServerOperationName,\n value: unknown,\n): boolean {\n if (!isRecord(value)) return false;\n switch (op) {\n case 'ping':\n case 'getAgentStatuses':\n case 'getOnlineAgents':\n case 'getClientStatuses':\n case 'purgeClients':\n case 'clearAll':\n case 'credentialList':\n case 'credentialStatusCounts':\n return true;\n case 'send':\n case 'sendRuntimeControl':\n case 'ack':\n case 'ackMany':\n case 'registerAgent':\n case 'heartbeat':\n case 'registerClient':\n case 'clientHeartbeat':\n return hasRecord(value, 'input');\n case 'query':\n return hasRecord(value, 'query');\n case 'unreadCount':\n return hasString(value, 'forAgentId');\n case 'softDelete':\n return hasString(value, 'mailId') && hasString(value, 'by');\n case 'restore':\n return hasString(value, 'mailId');\n case 'deregisterAgent':\n return hasString(value, 'agentId');\n case 'purgeAgents':\n case 'purgeStale':\n case 'autoCompact':\n return true;\n case 'deregisterClient':\n return hasString(value, 'clientId');\n case 'credentialIssue':\n return hasRecord(value, 'options');\n case 'credentialVerify':\n return hasString(value, 'credentialId') && hasString(value, 'secret');\n case 'credentialRevoke':\n case 'credentialRotate':\n case 'credentialGet':\n return hasString(value, 'credentialId');\n }\n}\n\n/** Runtime boundary guard for untrusted newline-delimited IPC frames. */\nexport function isMailboxProjectServerClientMessage(\n value: unknown,\n): value is MailboxProjectServerClientMessage {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const message = value as Record<string, unknown>;\n if (message['type'] === 'heartbeat') return true;\n if (message['type'] === 'shutdown') {\n return (\n isRequestId(message['id']) &&\n (message['reason'] === undefined || typeof message['reason'] === 'string')\n );\n }\n if (message['type'] !== 'request' || !isRequestId(message['id'])) return false;\n const op = message['op'];\n return (\n typeof op === 'string' &&\n Object.hasOwn(MAILBOX_SERVER_OPERATION_NAMES, op) &&\n isMailboxServerOperationArgs(op as MailboxServerOperationName, message['args'])\n );\n}\n\nexport type MailboxProjectServerMessage =\n | ({ type: 'hello' } & MailboxProjectServerInfo)\n | { type: 'mailbox-event'; event: MailboxEvent }\n | { type: 'event'; event: string; payload: unknown }\n | { type: 'response'; id: number; ok: true; result: unknown }\n | {\n type: 'response';\n id: number;\n ok: false;\n error: string;\n errorName?: string | undefined;\n };\n\n/** Runtime guard for server frames before the client touches discriminants. */\nexport function isMailboxProjectServerMessage(\n value: unknown,\n): value is MailboxProjectServerMessage {\n if (!isRecord(value) || typeof value['type'] !== 'string') return false;\n if (value['type'] === 'hello') {\n return (\n Number.isInteger(value['protocolVersion']) &&\n Number.isInteger(value['pid']) &&\n hasString(value, 'projectDir') &&\n hasString(value, 'endpoint') &&\n hasString(value, 'startedAt')\n );\n }\n if (value['type'] === 'event') return hasString(value, 'event');\n if (value['type'] === 'mailbox-event') return isRecord(value['event']);\n if (value['type'] !== 'response' || !isRequestId(value['id'])) return false;\n if (value['ok'] === true) return Object.hasOwn(value, 'result');\n return value['ok'] === false && typeof value['error'] === 'string';\n}\n\nexport function encodeMailboxProjectServerMessage(message: object): string {\n return `${JSON.stringify(message)}\\n`;\n}\n", "import { randomUUID } from 'node:crypto';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { DatabaseSync } from 'node:sqlite';\n\nimport type { EventBus } from '../kernel/events.js';\nimport {\n AGENT_STALE_MS,\n AUTO_COMPACT_INTERVAL_MS,\n CLIENT_STALE_MS,\n HEARTBEAT_THROTTLE_MS,\n} from './mailbox-constants.js';\nimport type {\n CredentialValidation,\n IssueCredentialOptions,\n MailboxCredential,\n} from './mailbox-credential-store.js';\nimport type { MailboxEventEmitter } from './mailbox-events.js';\nimport { isMessageCompletedForActor } from './global-mailbox-completion.js';\nimport { isFanOutRecipient } from './mailbox-receipt-folding.js';\nimport {\n projectMailboxCompletion,\n} from './mailbox-retention-state.js';\nimport { mapRegisteredAgentsToStatuses, mapRegisteredClientsToStatuses } from './mailbox-status-mappers.js';\nimport type {\n AgentHeartbeatInput,\n AgentRegistrationInput,\n AutoCompactOptions,\n AutoCompactResult,\n ClientHeartbeatInput,\n ClientRegistrationInput,\n ClientStatus,\n Mailbox,\n MailboxAckBatchInput,\n MailboxAckInput,\n MailboxAgentStatus,\n MailboxMessage,\n MailboxMessageProjection,\n MailboxQuery,\n MailboxRecipientState,\n MailboxSendInput,\n PurgeOptions,\n PurgeResult,\n RegisteredAgent,\n RegisteredClient,\n} from './mailbox-types.js';\nimport {\n isMailboxMessageVisibleTo,\n normalizeRecipient,\n sessionRecipient,\n validateSendType,\n} from './mailbox-types.js';\nimport { normalizeMailboxMessageType } from './mailbox-message-codec.js';\nimport {\n autoCompact,\n type CompactionContext,\n purgeStale,\n} from './sqlite-mailbox-compaction.js';\nimport {\n credentialGet,\n credentialIssue,\n credentialList,\n credentialRevoke,\n credentialRotate,\n credentialStatusCounts,\n credentialVerify,\n} from './sqlite-mailbox-credentials.js';\nimport {\n deleteMessages,\n materializeMessageRows,\n type MessageRow,\n type SqliteStatement,\n persistAgent,\n persistClient,\n persistMessage,\n persistReceipt,\n pruneAgents,\n pruneClients,\n readAgents,\n readClients,\n withoutAggregateCompletion,\n} from './sqlite-mailbox-rows.js';\nimport {\n initializeSchema,\n loadDatabaseSync,\n migrateLegacyFiles,\n type SchemaContext,\n} from './sqlite-mailbox-schema.js';\nexport const SQLITE_MAILBOX_FILE = '_mailbox.sqlite';\n/**\n * Server-owned project mailbox persistence.\n *\n * Production callers must reach this store through RemoteMailbox. The detached\n * project server is the only process that opens the database connection.\n */\n/**\n * Bounds for the in-memory heartbeat throttle maps. The sweep only runs once a\n * map is over the entry cap, so the steady state costs nothing.\n */\nconst HEARTBEAT_TRACKING_MAX_ENTRIES = 512;\nconst HEARTBEAT_TRACKING_TTL_MS = 30 * 60_000;\n\nexport class SqliteMailbox implements Mailbox {\n readonly databasePath: string;\n /** Compatibility alias used by project-server health/status consumers. */\n readonly messagePath: string;\n readonly eventEmitter?: MailboxEventEmitter | undefined;\n\n private readonly db: DatabaseSync;\n private readonly events?: EventBus | undefined;\n private readonly lastHeartbeat = new Map<string, number>();\n private readonly lastClientHeartbeat = new Map<string, number>();\n private autoCompactTimer: NodeJS.Timeout | null = null;\n private closed = false;\n\n constructor(\n readonly projectDir: string,\n events?: EventBus,\n eventEmitter?: MailboxEventEmitter,\n ) {\n fs.mkdirSync(projectDir, { recursive: true });\n this.databasePath = path.join(projectDir, SQLITE_MAILBOX_FILE);\n this.messagePath = this.databasePath;\n this.events = events;\n this.eventEmitter = eventEmitter;\n const Database = loadDatabaseSync();\n this.db = new Database(this.databasePath);\n this.db.exec('PRAGMA journal_mode = WAL');\n this.db.exec('PRAGMA synchronous = NORMAL');\n this.db.exec('PRAGMA foreign_keys = ON');\n this.db.exec('PRAGMA busy_timeout = 5000');\n initializeSchema(this.schemaCtx());\n migrateLegacyFiles(this.schemaCtx());\n }\n\n private stmt(sql: string): SqliteStatement {\n return this.db.prepare(sql);\n }\n\n private transaction<T>(run: () => T): T {\n this.db.exec('BEGIN IMMEDIATE');\n try {\n const result = run();\n this.db.exec('COMMIT');\n return result;\n } catch (error) {\n this.db.exec('ROLLBACK');\n throw error;\n }\n }\n\n /** Bundle of store state the schema/migration module operates on. */\n private schemaCtx(): SchemaContext {\n return {\n db: this.db,\n projectDir: this.projectDir,\n transaction: (run) => this.transaction(run),\n };\n }\n\n private persistMessage(message: MailboxMessage, legacyGlobalCompletion = false): void {\n persistMessage(this.db, message, legacyGlobalCompletion);\n }\n\n private persistReceipt(messageId: string, state: MailboxRecipientState): void {\n persistReceipt(this.db, messageId, state);\n }\n\n private materializeMessageRows(rows: readonly MessageRow[]): MailboxMessageProjection[] {\n return materializeMessageRows(this.db, rows);\n }\n\n private readMessages(): MailboxMessageProjection[] {\n const rows = this.stmt(\n 'SELECT id, data, legacy_global_completion FROM messages',\n ).all() as unknown as MessageRow[];\n return this.materializeMessageRows(rows);\n }\n\n private findMessage(messageId: string): MailboxMessageProjection | undefined {\n const row = this.stmt(\n 'SELECT id, data, legacy_global_completion FROM messages WHERE id = ?',\n ).get(messageId) as MessageRow | undefined;\n return row === undefined ? undefined : this.materializeMessageRows([row])[0];\n }\n\n async send(input: MailboxSendInput): Promise<MailboxMessage> {\n return this.sendMessage(input, false);\n }\n\n async sendRuntimeControl(\n input: Omit<MailboxSendInput, 'type'> & { type?: 'control' },\n ): Promise<MailboxMessage> {\n return this.sendMessage({ ...input, type: 'control' }, true);\n }\n\n private async sendMessage(\n input: MailboxSendInput,\n allowRuntimeControl: boolean,\n ): Promise<MailboxMessage> {\n const type = normalizeMailboxMessageType(input.type);\n const to = normalizeRecipient(input.to, input.senderSessionId);\n if (!(allowRuntimeControl && type === 'control')) validateSendType(type, to);\n const timestamp = new Date().toISOString();\n const message: MailboxMessage = {\n id: randomUUID(),\n from: input.from,\n to,\n type,\n ...(input.audience !== undefined && input.audience !== 'all'\n ? { audience: input.audience }\n : {}),\n subject: input.subject,\n body: input.body,\n priority: input.priority ?? 'normal',\n readBy: {},\n completed: false,\n timestamp,\n ...(input.replyTo !== undefined ? { replyTo: input.replyTo } : {}),\n ...(input.taskContext !== undefined ? { taskContext: input.taskContext } : {}),\n ...(input.senderSessionId !== undefined ? { senderSessionId: input.senderSessionId } : {}),\n ...(input.ttlMs !== undefined\n ? { expiresAt: new Date(Date.now() + input.ttlMs).toISOString() }\n : {}),\n };\n this.persistMessage(message);\n this.events?.emitCustom('mailbox.message_sent', {\n messageId: message.id,\n from: message.from,\n to: message.to,\n type: message.type,\n subject: message.subject,\n });\n this.eventEmitter?.emit({\n type: 'message.sent',\n messageId: message.id,\n from: message.from,\n to: message.to,\n audience: message.audience,\n timestamp,\n });\n return message;\n }\n\n async query(query: MailboxQuery): Promise<MailboxMessage[]> {\n const type = query.type === undefined ? undefined : normalizeMailboxMessageType(query.type);\n const priorityRank = { low: 0, normal: 1, high: 2 } as const;\n const minimumRank = query.minPriority === undefined ? 0 : priorityRank[query.minPriority];\n const statuses =\n query.unreadBy === undefined ? await this.getAgentStatuses() : undefined;\n const where: string[] = [];\n const params: Array<string | number> = [];\n if (query.to !== undefined) {\n where.push('(to_id = ? OR to_id = ?)');\n params.push(query.to, '*');\n }\n if (query.from !== undefined) {\n where.push('from_id = ?');\n params.push(query.from);\n }\n if (query.sessionId !== undefined) {\n where.push('sender_session_id = ?');\n params.push(query.sessionId);\n }\n if (type !== undefined) {\n where.push('type = ?');\n params.push(type);\n }\n if (query.minPriority !== undefined) {\n // Unrecognized priorities rank as `normal`, matching the JSONL reader\n // this store replaced: an unknown value must not silently drop a\n // message out of a `minPriority: 'normal'` query. Only an explicit\n // 'low' ranks below normal.\n where.push(`CASE priority WHEN 'high' THEN 2 WHEN 'low' THEN 0 ELSE 1 END >= ?`);\n params.push(minimumRank);\n }\n if (query.since !== undefined) {\n where.push('timestamp > ?');\n params.push(query.since);\n }\n if (!query.includeDeleted) where.push('deleted_at IS NULL');\n if (query.replyTo !== undefined) {\n where.push('reply_to = ?');\n params.push(query.replyTo);\n }\n const canPreLimit = query.unreadBy === undefined && !query.incompleteOnly;\n let sql = 'SELECT id, data, legacy_global_completion FROM messages';\n if (where.length > 0) sql += ` WHERE ${where.join(' AND ')}`;\n // `rowid DESC` breaks ties: two sends can land in the same millisecond and\n // ISO timestamps have no finer resolution. Without it SQLite is free to\n // return same-millisecond messages in any order, and \"newest first\"\n // becomes a coin flip. Insertion order is stable \u2014 `persistMessage`\n // upserts, so an ack never moves a message's rowid.\n sql += ' ORDER BY timestamp DESC, rowid DESC';\n if (canPreLimit) {\n sql += ' LIMIT ?';\n params.push(query.limit ?? 50);\n }\n const rows = this.stmt(sql).all(...params) as unknown as MessageRow[];\n const messages = this.materializeMessageRows(rows).filter((message) => {\n if (query.to !== undefined && message.to !== query.to && message.to !== '*') return false;\n if (query.from !== undefined && message.from !== query.from) return false;\n if (query.sessionId !== undefined && message.senderSessionId !== query.sessionId) return false;\n if (\n query.unreadBy !== undefined &&\n !isMailboxMessageVisibleTo(message, query.unreadBy, query.readerRole)\n ) return false;\n if (\n !query.incompleteOnly &&\n query.unreadBy !== undefined &&\n query.unreadBy in message.readBy\n ) return false;\n if (\n query.incompleteOnly &&\n (query.unreadBy === undefined\n ? projectMailboxCompletion(message, undefined, statuses).completed\n : isMessageCompletedForActor(message, query.unreadBy))\n ) return false;\n if (type !== undefined && message.type !== type) return false;\n if (priorityRank[message.priority] < minimumRank) return false;\n if (query.since !== undefined && message.timestamp <= query.since) return false;\n if (!query.includeDeleted && message.deletedAt !== undefined) return false;\n if (query.replyTo !== undefined && message.replyTo !== query.replyTo) return false;\n return true;\n });\n messages.sort((left, right) => right.timestamp.localeCompare(left.timestamp));\n return messages.slice(0, query.limit ?? 50).map((message) => {\n const copy = {\n ...projectMailboxCompletion(message, query.unreadBy, statuses),\n readBy: { ...message.readBy },\n };\n if (!query.includeReceiptState) {\n delete (copy as Partial<MailboxMessageProjection>).recipientState;\n delete (copy as Partial<MailboxMessageProjection>).legacyGlobalCompletion;\n }\n return copy;\n });\n }\n\n async ack(input: MailboxAckInput): Promise<MailboxMessage | null> {\n const results = await this.ackMany({ acks: [input] });\n return results[0] ?? null;\n }\n\n async ackMany(input: MailboxAckBatchInput): Promise<MailboxMessage[]> {\n if (input.acks.length === 0) return [];\n const timestamp = new Date().toISOString();\n const changed = new Set<string>();\n const updated = this.transaction(() => {\n const results: MailboxMessage[] = [];\n for (const ack of input.acks) {\n const message = this.findMessage(ack.messageId);\n if (message === undefined) continue;\n const current = message.recipientState[ack.readerId] ?? { actorId: ack.readerId };\n const state: MailboxRecipientState = { ...current };\n let didChange = false;\n\n if (ack.read !== false && state.readAt === undefined) {\n state.readAt = timestamp;\n message.readBy[ack.readerId] = timestamp;\n didChange = true;\n }\n if (\n ack.completed === true &&\n state.completedAt === undefined &&\n message.legacyGlobalCompletion !== true\n ) {\n state.completedAt = timestamp;\n state.completedBy = ack.readerId;\n didChange = true;\n }\n if (ack.read === false && ack.completed === false && state.completedAt !== undefined) {\n delete state.completedAt;\n delete state.completedBy;\n didChange = true;\n }\n if (ack.outcome !== undefined && state.outcome !== ack.outcome) {\n state.outcome = ack.outcome;\n didChange = true;\n }\n\n message.recipientState = {\n ...message.recipientState,\n [ack.readerId]: state,\n };\n const actorCompleted = state.completedAt !== undefined;\n message.completed = message.legacyGlobalCompletion === true || actorCompleted;\n if (actorCompleted) {\n message.completedBy = state.completedBy ?? ack.readerId;\n message.completedAt = state.completedAt;\n } else if (message.legacyGlobalCompletion !== true) {\n delete message.completedBy;\n delete message.completedAt;\n }\n message.outcome = state.outcome;\n\n if (didChange) {\n this.persistReceipt(message.id, state);\n // Aggregate completion is STORED only for a message with a single\n // addressee. One actor finishing a fan-out (`*`, `@session:`, a bare\n // role alias) must not mark it done for everyone else \u2014 that is what\n // the per-actor receipt model exists to prevent, and\n // `legacyGlobalCompletion` marks the historical v1 messages that\n // predate it. The value returned to the caller below still reports\n // that actor's own completion.\n this.persistMessage(\n isFanOutRecipient(message.to) ? withoutAggregateCompletion(message) : message,\n message.legacyGlobalCompletion === true,\n );\n changed.add(message.id);\n }\n results.push({ ...message, readBy: { ...message.readBy } });\n }\n return results;\n });\n\n for (const message of updated) {\n if (!changed.has(message.id)) continue;\n this.eventEmitter?.emit({\n type: 'message.acked',\n messageId: message.id,\n from: message.from,\n to: message.to,\n audience: message.audience,\n timestamp,\n });\n }\n return updated;\n }\n\n async unreadCount(forAgentId: string, sessionId?: string): Promise<number> {\n const sessionAddress = sessionId === undefined ? undefined : sessionRecipient(sessionId);\n return this.readMessages().filter(\n (message) =>\n (message.to === forAgentId || message.to === '*' || message.to === sessionAddress) &&\n isMailboxMessageVisibleTo(message, forAgentId) &&\n !(forAgentId in message.readBy) &&\n !isMessageCompletedForActor(message, forAgentId) &&\n message.deletedAt === undefined,\n ).length;\n }\n\n async softDelete(mailId: string, by: string): Promise<MailboxMessage | null> {\n const message = this.findMessage(mailId);\n if (message === undefined) return null;\n if (message.deletedAt !== undefined) return { ...message, readBy: { ...message.readBy } };\n const timestamp = new Date().toISOString();\n message.deletedAt = timestamp;\n message.deletedBy = by;\n const previousState = message.recipientState[by] ?? { actorId: by };\n const state = {\n ...previousState,\n readAt: previousState.readAt ?? timestamp,\n };\n message.readBy[by] = state.readAt;\n message.recipientState = { ...message.recipientState, [by]: state };\n this.transaction(() => {\n this.persistReceipt(message.id, state);\n this.persistMessage(message, message.legacyGlobalCompletion === true);\n });\n this.eventEmitter?.emit({\n type: 'message.deleted',\n messageId: message.id,\n from: message.from,\n to: message.to,\n audience: message.audience,\n timestamp,\n });\n return { ...message, readBy: { ...message.readBy } };\n }\n\n async restore(mailId: string): Promise<MailboxMessage | null> {\n const message = this.findMessage(mailId);\n if (message === undefined) return null;\n if (message.deletedAt === undefined && message.deletedBy === undefined) {\n return { ...message, readBy: { ...message.readBy } };\n }\n delete message.deletedAt;\n delete message.deletedBy;\n this.persistMessage(message, message.legacyGlobalCompletion === true);\n const timestamp = new Date().toISOString();\n this.eventEmitter?.emit({\n type: 'message.restored',\n messageId: message.id,\n from: message.from,\n to: message.to,\n audience: message.audience,\n timestamp,\n });\n return { ...message, readBy: { ...message.readBy } };\n }\n\n private persistAgent(agent: RegisteredAgent): void {\n persistAgent(this.db, agent);\n }\n\n private readAgents(): Map<string, RegisteredAgent> {\n return readAgents(this.db);\n }\n\n private pruneAgents(maxAgeMs = AGENT_STALE_MS): number {\n return pruneAgents(this.db, maxAgeMs);\n }\n\n async registerAgent(input: AgentRegistrationInput): Promise<void> {\n this.pruneAgents();\n const now = new Date().toISOString();\n this.persistAgent({\n agentId: input.agentId,\n sessionId: input.sessionId,\n name: input.name,\n ...(input.role !== undefined ? { role: input.role } : {}),\n status: 'idle',\n iterations: 0,\n toolCalls: 0,\n registeredAt: now,\n lastSeenAt: now,\n pid: input.pid ?? process.pid,\n ...(input.source !== undefined ? { source: input.source } : {}),\n });\n this.events?.emitCustom('mailbox.agent_registered', {\n agentId: input.agentId,\n sessionId: input.sessionId,\n name: input.name,\n role: input.role,\n source: input.source,\n });\n }\n\n /**\n * Throttle bookkeeping only: `agentId`/`clientId` -> last accepted heartbeat.\n *\n * Entries are deleted on a clean deregister, but a crashed or forcibly killed\n * peer never deregisters, so over a long-lived daemon's life these maps grew\n * with every distinct id ever seen. Dropping a stale entry is free: the next\n * heartbeat from that id simply is not throttled and writes once more.\n */\n private pruneHeartbeats(map: Map<string, number>, nowMs: number): void {\n if (map.size <= HEARTBEAT_TRACKING_MAX_ENTRIES) return;\n for (const [id, at] of map) {\n if (nowMs - at > HEARTBEAT_TRACKING_TTL_MS) map.delete(id);\n }\n }\n\n async deregisterAgent(agentId: string): Promise<void> {\n this.stmt('DELETE FROM agents WHERE agent_id = ?').run(agentId);\n this.lastHeartbeat.delete(agentId);\n this.events?.emitCustom('mailbox.agent_deregistered', { agentId });\n }\n\n async heartbeat(input: AgentHeartbeatInput): Promise<void> {\n const nowMs = Date.now();\n if (nowMs - (this.lastHeartbeat.get(input.agentId) ?? 0) < HEARTBEAT_THROTTLE_MS) return;\n this.lastHeartbeat.set(input.agentId, nowMs);\n this.pruneHeartbeats(this.lastHeartbeat, nowMs);\n this.pruneAgents();\n const agent = this.readAgents().get(input.agentId);\n if (agent !== undefined) {\n agent.lastSeenAt = new Date(nowMs).toISOString();\n if (input.status !== undefined) agent.status = input.status;\n if (input.currentTool !== undefined) agent.currentTool = input.currentTool;\n if (input.currentTask !== undefined) agent.currentTask = input.currentTask;\n if (input.iterations !== undefined) agent.iterations = input.iterations;\n if (input.toolCalls !== undefined) agent.toolCalls = input.toolCalls;\n this.persistAgent(agent);\n }\n this.events?.emitCustom('mailbox.agent_heartbeat', {\n agentId: input.agentId,\n status: input.status,\n currentTool: input.currentTool,\n currentTask: input.currentTask,\n });\n }\n\n async getAgentStatuses(): Promise<MailboxAgentStatus[]> {\n this.pruneAgents();\n return mapRegisteredAgentsToStatuses(this.readAgents(), Date.now(), AGENT_STALE_MS);\n }\n\n async purgeAgents(maxAgeMs = AGENT_STALE_MS): Promise<number> {\n return this.pruneAgents(maxAgeMs);\n }\n\n async getOnlineAgents(): Promise<MailboxAgentStatus[]> {\n return (await this.getAgentStatuses()).filter((agent) => agent.online);\n }\n\n private persistClient(client: RegisteredClient): void {\n persistClient(this.db, client);\n }\n\n private readClients(): Map<string, RegisteredClient> {\n return readClients(this.db);\n }\n\n private pruneClientsInPlace(): number {\n return pruneClients(this.db);\n }\n\n async registerClient(input: ClientRegistrationInput): Promise<void> {\n this.pruneClientsInPlace();\n const now = new Date().toISOString();\n this.persistClient({\n clientId: input.clientId,\n sessionId: input.sessionId,\n name: input.name,\n source: input.source,\n registeredAt: now,\n lastSeenAt: now,\n pid: input.pid ?? process.pid,\n });\n this.events?.emitCustom('mailbox.client_registered', {\n clientId: input.clientId,\n sessionId: input.sessionId,\n name: input.name,\n source: input.source,\n });\n }\n\n async deregisterClient(clientId: string): Promise<void> {\n this.stmt('DELETE FROM clients WHERE client_id = ?').run(clientId);\n this.lastClientHeartbeat.delete(clientId);\n this.events?.emitCustom('mailbox.client_deregistered', { clientId });\n }\n\n async clientHeartbeat(input: ClientHeartbeatInput): Promise<void> {\n const nowMs = Date.now();\n if (\n nowMs - (this.lastClientHeartbeat.get(input.clientId) ?? 0) <\n HEARTBEAT_THROTTLE_MS\n ) return;\n this.lastClientHeartbeat.set(input.clientId, nowMs);\n this.pruneHeartbeats(this.lastClientHeartbeat, nowMs);\n this.pruneClientsInPlace();\n const client = this.readClients().get(input.clientId);\n if (client !== undefined) {\n client.lastSeenAt = new Date(nowMs).toISOString();\n if (input.sessionId) client.sessionId = input.sessionId;\n this.persistClient(client);\n }\n this.events?.emitCustom('mailbox.client_heartbeat', {\n clientId: input.clientId,\n ...(input.sessionId ? { sessionId: input.sessionId } : {}),\n });\n }\n\n async getClientStatuses(): Promise<ClientStatus[]> {\n this.pruneClientsInPlace();\n return mapRegisteredClientsToStatuses(this.readClients(), Date.now(), CLIENT_STALE_MS);\n }\n\n async purgeClients(): Promise<number> {\n return this.pruneClientsInPlace();\n }\n\n async clearAll(): Promise<void> {\n this.stmt('DELETE FROM messages').run();\n }\n\n async purgeStale(options?: PurgeOptions): Promise<PurgeResult> {\n return purgeStale(this.compactionCtx(), options);\n }\n\n async autoCompact(options?: AutoCompactOptions): Promise<AutoCompactResult> {\n return autoCompact(this.compactionCtx(), options);\n }\n\n /** Bundle of store operations the retention sweeps drive. */\n private compactionCtx(): CompactionContext {\n return {\n getAgentStatuses: () => this.getAgentStatuses(),\n readMessages: () => this.readMessages(),\n deleteMessages: (ids) => this.deleteMessages(ids),\n };\n }\n\n private deleteMessages(ids: readonly string[]): void {\n if (ids.length === 0) return;\n this.transaction(() => deleteMessages(this.db, ids));\n }\n\n credentialGet(credentialId: string): MailboxCredential | null {\n return credentialGet(this.db, credentialId);\n }\n\n credentialList(): MailboxCredential[] {\n return credentialList(this.db);\n }\n\n credentialStatusCounts(): Record<string, number> {\n return credentialStatusCounts(this.db);\n }\n\n credentialIssue(\n options: IssueCredentialOptions,\n ): { credential: MailboxCredential; secret: string } {\n return credentialIssue(this.db, (run) => this.transaction(run), options);\n }\n\n credentialVerify(credentialId: string, secret: string): CredentialValidation {\n return credentialVerify(this.db, credentialId, secret);\n }\n\n credentialRevoke(credentialId: string, reason?: string, by?: string): boolean {\n return credentialRevoke(this.db, credentialId, reason, by);\n }\n\n credentialRotate(\n credentialId: string,\n options?: Partial<IssueCredentialOptions>,\n ): { credential: MailboxCredential; secret: string } | null {\n return credentialRotate(this.db, (run) => this.transaction(run), credentialId, options);\n }\n\n startAutoCompactTimer(options?: AutoCompactOptions): () => void {\n if (this.autoCompactTimer !== null) clearInterval(this.autoCompactTimer);\n const timer = setInterval(() => {\n void this.autoCompact(options).catch(() => {});\n }, options?.intervalMs ?? AUTO_COMPACT_INTERVAL_MS);\n timer.unref?.();\n this.autoCompactTimer = timer;\n return () => {\n clearInterval(timer);\n if (this.autoCompactTimer === timer) this.autoCompactTimer = null;\n };\n }\n\n async close(): Promise<void> {\n if (this.closed) return;\n this.closed = true;\n if (this.autoCompactTimer !== null) clearInterval(this.autoCompactTimer);\n this.autoCompactTimer = null;\n this.db.close();\n }\n}\n", "/**\n * Centralized constants for the mailbox system.\n *\n * Previously these magic numbers were scattered across global-mailbox.ts,\n * mailbox-attach.ts, mailbox-hooks.ts, and mailbox-health.ts. Keeping them\n * in one place ensures every surface agrees on timeouts, intervals, and\n * thresholds \u2014 and makes tuning a single-file change.\n *\n * @module mailbox-constants\n */\n\n/**\n * Agents without a heartbeat for this long are no longer live and are removed\n * from the registry. Presence registries are not history stores: retaining an\n * offline row makes dead agents and shadow workers look actionable in HQ.\n */\nexport const AGENT_STALE_MS = 60_000;\n\n/** Clients without a heartbeat for this long are considered offline. */\nexport const CLIENT_STALE_MS = 60_000;\n\n/** Heartbeat updates are throttled to at most this interval (per agent/client). */\nexport const HEARTBEAT_THROTTLE_MS = 5_000;\n\n/**\n * How long a read may be served from the in-process registry cache before\n * re-reading the shared file. Kept well below HEARTBEAT_THROTTLE_MS so\n * cross-process registrations become visible promptly.\n */\nexport const REGISTRY_CACHE_TTL_MS = 2_000;\n\n/** JSONL line separator. */\nexport const LINE_SEPARATOR = '\\n';\n\n/**\n * Soft cap on the in-memory message cache. The cache mirrors the JSONL\n * message file; under normal load it stays well under this. If a pathological\n * mailbox exceeds the cap we fall back to reading from disk rather than\n * holding an unbounded buffer in memory.\n */\nexport const MESSAGE_CACHE_MAX_ENTRIES = 10_000;\n\n// \u2500\u2500 Polling / heartbeat intervals (used by mailbox-attach.ts) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Background mailbox awareness polling interval (cross-process fallback). */\nexport const MAILBOX_AWARENESS_INTERVAL_MS = 30_000;\n\n/** Agent heartbeat interval in the attach layer. */\nexport const MAILBOX_HEARTBEAT_INTERVAL_MS = 30_000;\n\n/**\n * Floor on how often a full HQ mailbox snapshot may be published.\n *\n * The snapshot is a rollup (50 messages + every agent status, ~30 KB) that\n * exists so the HQ dashboard's counters are authoritative. It used to be\n * published after *every* message mutation and *every* agent heartbeat, which\n * made it the single largest thing HQ persists: 14,053 snapshots totalling\n * 415 MB in one measured `events.jsonl`, next to 8.3 MB for the 12,445\n * `mailbox.event` deltas that already carried the same information.\n *\n * Snapshots are now coalesced behind this interval \u2014 the dashboard converges\n * within a few seconds instead of on every keystroke-scale event, and the\n * deltas keep the live feed exact in between.\n */\nexport const HQ_MAILBOX_SNAPSHOT_MIN_INTERVAL_MS = 10_000;\n\n/** Min interval between registry reads for the fleet pulse digest. */\nexport const PULSE_MIN_READ_INTERVAL_MS = 30_000;\n\n/**\n * Floor on how often the pre-tool hook actually reads the mailbox.\n *\n * `beforeTool` fires once per tool call, and a busy turn issues dozens. Each\n * call stats the shared message file and, whenever another session has written\n * to it, pays a read. Collapsing bursts to one check per second keeps steer\n * messages effectively immediate (no tool completes fast enough for a human to\n * notice the difference) while removing the per-tool file churn. Set the hook's\n * `unreadCheckIntervalMs` to 0 to check on every call.\n */\nexport const UNREAD_CHECK_MIN_INTERVAL_MS = 1_000;\n\n// \u2500\u2500 Auto-cleanup / compaction \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Interval at which the background auto-compaction sweep runs.\n * Default: every 5 minutes.\n */\nexport const AUTO_COMPACT_INTERVAL_MS = 300_000;\n\n/**\n * Messages that have been read by ALL currently-online agents are eligible\n * for auto-removal after this many milliseconds since the last read.\n * Default: 10 minutes.\n */\nexport const AUTO_COMPACT_READ_MAX_AGE_MS = 600_000;\n\n/**\n * Messages whose TTL (time-to-live) has expired are eligible for auto-removal.\n * When a message has `expiresAt` set and that timestamp is in the past, the\n * next compaction sweep drops it. Default TTL for messages without an explicit\n * `expiresAt`: 24 hours.\n */\nexport const AUTO_COMPACT_DEFAULT_TTL_MS = 86_400_000; // 24h\n\n/**\n * Per-type TTL overrides for message classes that are pure live-awareness\n * chatter, applied when the message carries no explicit `expiresAt`.\n *\n * `status` is broadcast by the fleet supervisor, host supervisor, mailbox\n * health probe and handoff plugin purely so peers can see who is doing what\n * *right now*; nothing reads it back as history. Under the 24h default it\n * dominated the shared file \u2014 on a real project mailbox, 1807 of 2766 lines\n * and 1.5 MB of 3 MB \u2014 and every reader pays for that on any cache miss.\n * Half an hour is far longer than any consumer's interest window.\n *\n * Keyed by `MailboxMessageType`; unlisted types keep\n * {@link AUTO_COMPACT_DEFAULT_TTL_MS}.\n */\nexport const AUTO_COMPACT_TYPE_TTL_MS: Readonly<Record<string, number>> = {\n status: 1_800_000, // 30 min\n};\n\n// \u2500\u2500 HTTP bridge rate limiting \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Maximum requests per minute from a single external agent (bearer token). */\nexport const HTTP_RATE_LIMIT_PER_MINUTE = 120;\n\n/** Window size for the sliding-window rate limiter. */\nexport const HTTP_RATE_LIMIT_WINDOW_MS = 60_000;\n", "import type { MailboxMessage } from './mailbox-types.js';\nimport type { MailboxMessageProjection } from './mailbox-receipt-folding.js';\n\nexport function isMailboxMessageProjection(msg: MailboxMessage): msg is MailboxMessageProjection {\n if (!('recipientState' in msg)) return false;\n const recipientState: unknown = msg.recipientState;\n return (\n typeof recipientState === 'object' &&\n recipientState !== null &&\n !Array.isArray(recipientState)\n );\n}\n\nexport function isMessageCompletedForActor(\n msg: MailboxMessage,\n actorId?: string,\n): boolean {\n if (!isMailboxMessageProjection(msg)) return msg.completed === true;\n if (msg.legacyGlobalCompletion) return true;\n if (actorId !== undefined) {\n const state = msg.recipientState[actorId];\n if (state !== undefined) return state.completedAt !== undefined;\n if (Object.keys(msg.recipientState).length > 0) return false;\n }\n return msg.completed === true;\n}\n", "/**\n * Mailbox \u2014 persistent inter-agent messaging system with cross-session support.\n *\n * Agents can leave notes for specific agents or broadcast to all. Each agent\n * periodically checks the mailbox or retrieves messages via tool calls.\n *\n * ## Cross-session communication\n *\n * The mailbox is stored at **project level** (`~/.wrongstack/projects/<slug>/_mailbox.sqlite`, owned by one detached\n * project server and reached over IPC),\n * so agents in different terminal sessions / WebUI tabs working on the same\n * canonical project can communicate live, even when they run in different\n * processes, clients, branches, or linked Git worktrees.\n *\n * ## Agent registration\n *\n * Every agent that uses the mailbox registers itself with a heartbeat.\n * Other agents can discover online agents via `getOnlineAgents()`.\n * Stale agents (no heartbeat > 60s) are pruned automatically.\n *\n * ## Read receipts\n *\n * Each message tracks per-recipient read status via a `readBy` map:\n * `{ \"agentId\": \"ISO8601\" }`. When agent X reads a message, its entry\n * is added. The WebUI shows who read what and when.\n *\n * @module mailbox-types\n */\n\nimport {\n MAILBOX_TYPE_PROPERTIES,\n type MailboxMessageType,\n} from './mailbox-type-properties.js';\nexport {\n MAILBOX_TYPE_PROPERTIES,\n type MailboxMessageType,\n type MailboxTypeCategory,\n} from './mailbox-type-properties.js';\n\n// \u2500\u2500 Message type discriminator \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * The ten mail types each carry a distinct **semantic category**, a **sender\n * contract** (when the sender must use it), and a **recipient contract** (how\n * the runtime dispatches it and what the recipient agent must do).\n *\n * \u2500\u2500\u2500\u2500\u2500 Type semantics \u2014 decision matrix for senders \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * ## Categories\n *\n * | Category | Types | Purpose |\n * |--------------|---------------------------------------|--------------------------------|\n * | Actionable | `ask`, `assign`, `steer`, `review` | Require a substantive response |\n * | Informational| `note`, `btw`, `result`, `status` | Consume for context, no action |\n * | Routing | `broadcast` | Multi-recipient envelope |\n * | Control | `control` | Out-of-band signal (no render) |\n *\n * ## Per-type contract\n *\n * ### Actionable types\n *\n * | Type | When to send | Recipient must |\n * |----------|-----------------------------------------------------|----------------------------------------------------|\n * | `ask` | Blocking question \u2014 you need an answer to proceed | Answer as soon as possible; the sender is waiting. |\n * | `assign` | Delegating a task | Accept or decline; act on it when current op allows. |\n * | `steer` | Mid-task direction change \u2014 the recipient is | Pause current approach, adjust per instruction, |\n * | | already working on something and you need them | then resume. Rendered first in the mailbox block. |\n * | | to change course NOW | |\n * | `review` | Requesting a code/doc/PR review (passive) | Inspect when convenient; no immediate reply needed.|\n *\n * ### Informational types\n *\n * | Type | When to send | Recipient must |\n * |----------|-----------------------------------------------------|----------------------------------------------------|\n * | `note` | General-purpose FYI \u2014 a message that isn't any | Read for context; no reply needed. The untyped |\n * | | of the more specific types | default for directed messages. |\n * | `btw` | Low-priority aside \u2014 \"by the way\" | Absorb the information and stay on current task; |\n * | | | no reply needed. Injected via BTW block (separate |\n * | | | from the main mailbox fold) to minimise disruption.|\n * | `result` | Subagent/task completion notice \u2014 share the | Factor into next decision; treat as evidence, not |\n * | | outcome of finished work | a new task. |\n * | `status` | Agent or system status update (heartbeat, spawn, | Use to avoid redundant work; never act on it as |\n * | | task progress, error). Machine-generated. | a task or question. |\n * | `broadcast` | Multi-recipient envelope \u2014 the same message for | Read if addressed to you (direct, alias, session, |\n * | | every agent on the project. Auto-selected when | or `*`). The `*` recipient means \"everyone\". |\n * | | `to` is `\"*\"` or `\"@session\"` in `mail_send`. | |\n *\n * ### Control type\n *\n * | Type | When to send | Recipient must |\n * |----------|-----------------------------------------------------|----------------------------------------------------|\n * | `control`| Out-of-band signal (interrupt, halt, redirect). | NEVER folded into conversation content. The agent |\n * | | Machine-generated by the runtime, not by agents. | loop intercepts it separately. `control:interrupt` |\n * | | | causes a cooperative halt at the next iteration |\n * | | | boundary. |\n *\n * \u2500\u2500\u2500\u2500\u2500 Dispatch behavior (runtime contract) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * The mailbox system enforces these dispatch rules:\n *\n * 1. **Send-side**: `mail_send` auto-defaults the type: `broadcast` when\n * `to` is `\"*\"` or `\"@session::...\"`, otherwise `note`.\n * 2. **Send-side validation**: `assign` always requires a specific `to`\n * (not `\"*\"`). `control` is reserved for runtime use \u2014 agents passing it\n * via the tool surface will be rejected.\n * 3. **Render-order guarantee**: `steer` messages are ALWAYS rendered first\n * in `buildMailboxBlock()`, before any other type, to ensure mid-task\n * direction changes are seen before other action items.\n * 4. **Control isolation**: `control`-type messages are filtered by\n * `injectPendingMailboxMessages()` and NEVER enter the folded\n * conversation block \u2014 they are out-of-band signals only.\n * 5. **Background routing**: in `background` delivery mode, only\n * `ACTIONABLE_BACKGROUND_TYPES` (`steer`, `ask`, `assign`, `result`,\n * `review`) are escalated; `note`, `btw`, `status`, and `broadcast`\n * are suppressed to minimise disruption during tool work.\n * 6. **Awareness polling**: `btw` messages intercepted by background\n * polling are queued via `setBtwNote()` for injection at a safe loop\n * boundary, not folded inline.\n * 7. **Agent registry**: `getAgentStatuses()` reads the dedicated agent\n * registry (`_mailbox.registry.json`), not mailbox message content. The\n * registry is populated by agent heartbeat calls (not by `status`-type\n * messages). `Mailbox.getAgentStatuses()` derives\n * a registry snapshot from `status`-type messages as a fallback when no\n * shared registry file exists.\n * 8. **Request-scoped context**: delivered raw mailbox blocks are removed\n * after one successful provider evaluation. Durable assistant/tool/task\n * consequences remain; routine mail does not occupy later requests.\n *\n * When a type is missing from any dispatch table, the fallback is:\n * - Render with `\uD83D\uDCE8 <TYPE>` label (generic emoji prefix)\n * - Route inline (not background)\n * - No special instruction added\n */\n\n/**\n * Which class of agent may consume a mailbox message.\n *\n * `leaders` is a delivery boundary, not merely a UI hint: agent-loop and\n * inbox readers must exclude these messages for subagents. The optional\n * persisted field keeps older JSONL records backwards-compatible (`all`).\n */\nexport type MailboxAudience = 'all' | 'leaders';\n\n/** Return the stable base portion of a session-qualified mailbox identity. */\nexport function mailboxIdentityBase(agentId: string): string {\n return agentId.split(/[@#]/, 1)[0]!.trim().toLowerCase();\n}\n\n/** Whether a mailbox identity belongs to the session's main/leader agent. */\nexport function isMailboxLeader(agentId: string, role?: string): boolean {\n return mailboxIdentityBase(agentId) === 'leader' || role?.trim().toLowerCase() === 'leader';\n}\n\n/** Whether a message may be consumed by the supplied agent identity. */\nexport function isMailboxMessageVisibleTo(\n message: Pick<MailboxMessage, 'audience'>,\n agentId: string,\n role?: string,\n): boolean {\n return message.audience !== 'leaders' || isMailboxLeader(agentId, role);\n}\n\n/** Category + expectsReply are provided by MAILBOX_TYPE_PROPERTIES directly. */\n\n/**\n * Validate that a given (type, to) pair is internally consistent.\n * Throws when the combination breaks a fundamental rule.\n */\nexport function validateSendType(type: MailboxMessageType, to: string): void {\n if (type === 'control') {\n throw new TypeError(\n 'Type \"control\" is reserved for runtime use and cannot be set by agents',\n );\n }\n const isMultiRecipient = to === '*' || to.startsWith('@session:');\n if (type === 'assign' && isMultiRecipient) {\n throw new TypeError(\n `Type \"assign\" requires a specific recipient \u2014 multi-recipient target \"${to}\" is ambiguous`,\n );\n }\n if (type === 'steer' && isMultiRecipient) {\n throw new TypeError(\n `Type \"steer\" requires a specific recipient \u2014 multi-recipient target \"${to}\" is ambiguous`,\n );\n }\n}\n\n// \u2500\u2500 Read receipt \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Per-recipient read status. `readBy` maps agentId \u2192 ISO8601 timestamp of\n * when that agent first read the message. An empty map means unread by all.\n */\nexport interface ReadReceipts {\n [agentId: string]: string; // ISO8601 timestamp\n}\n\n// \u2500\u2500 Core message \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface MailboxMessage {\n /** Unique message id (UUID). */\n id: string;\n /** Sender agent id. */\n from: string;\n /** Recipient agent id, or '*' for broadcast. */\n to: string;\n /** Message category. */\n type: MailboxMessageType;\n /** Delivery audience. Omitted legacy values mean `all`. */\n audience?: MailboxAudience | undefined;\n /** Short subject line \u2014 one sentence. */\n subject: string;\n /** Full message content. */\n body: string;\n /** Priority \u2014 high priority messages surface first. */\n priority: 'low' | 'normal' | 'high';\n /**\n * Per-recipient read receipts. agentId \u2192 ISO8601 when they first read it.\n * Replaces the old single `read: boolean` + `readAt` fields.\n */\n readBy: ReadReceipts;\n /** Has any recipient acted on / completed this? */\n completed: boolean;\n /** Who completed it (agentId). */\n completedBy?: string | undefined;\n /** Optional summary of what happened after handling. */\n outcome?: string | undefined;\n /** ISO8601 \u2014 when the message was sent. */\n timestamp: string;\n /** ISO8601 \u2014 when the message was marked complete. */\n completedAt?: string | undefined;\n /**\n * ISO8601 \u2014 when the message was soft-deleted. When present, the\n * default `Mailbox.query()` filter excludes the message from the\n * normal inbox view; {@link Mailbox.restore} clears the\n * field to undo the delete. Hard deletes (removing the line from\n * the JSONL) are reserved for the CLI and never happen via the\n * server route handlers.\n */\n deletedAt?: string | undefined;\n /** When the soft-delete happened, the agentId that issued it. */\n deletedBy?: string | undefined;\n /** If this is a reply, the id of the parent message. */\n replyTo?: string | undefined;\n /** For assign-type messages \u2014 task context for agent discovery. */\n taskContext?: MailboxTaskContext | undefined;\n /** Session id of the sender. Enables cross-session communication. */\n senderSessionId?: string | undefined;\n /**\n * ISO8601 \u2014 when the message expires. Set at send time from `ttlMs`\n * (default: 24h via AUTO_COMPACT_DEFAULT_TTL_MS). The auto-compaction\n * sweep removes messages whose `expiresAt` is in the past. When\n * undefined, the compaction sweep uses the default TTL from the\n * caller's options.\n */\n expiresAt?: string | undefined;\n}\n\n// \u2500\u2500 Task context for agent discovery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface MailboxTaskContext {\n /** The role that should handle this task (e.g. \"tech-stack\", \"audit-log\"). */\n agentRole?: string | undefined;\n /** Human-readable agent name (e.g. \"Tesla (Executor)\"). */\n agentName?: string | undefined;\n /** Task id if already assigned via coordinator. */\n taskId?: string | undefined;\n /** Current task status. */\n status?: 'pending' | 'in_progress' | 'completed' | 'failed' | undefined;\n}\n\n// \u2500\u2500 Agent registration \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface RegisteredAgent {\n /** Unique agent id. */\n agentId: string;\n /** Session id this agent belongs to. */\n sessionId: string;\n /** Human-readable name. */\n name: string;\n /** Role (e.g. \"leader\", \"tech-stack\", \"bug-hunter\"). */\n role?: string | undefined;\n /** Current status. */\n status: 'idle' | 'running' | 'streaming' | 'waiting_user' | 'error';\n /** Current tool being executed, if any. */\n currentTool?: string | undefined;\n /** Current task description. */\n currentTask?: string | undefined;\n /** Iteration count so far. */\n iterations: number;\n /** Tool calls so far. */\n toolCalls: number;\n /** ISO8601 \u2014 registered at. */\n registeredAt: string;\n /** ISO8601 \u2014 last heartbeat (updated on every mailbox op). */\n lastSeenAt: string;\n /** Which process registered this agent (PID). */\n pid: number;\n /** Where the agent is running (e.g. \"cli\", \"webui\"). */\n source?: 'cli' | 'webui' | 'mcp' | 'acp' | 'http' | undefined;\n}\n\n// \u2500\u2500 Agent status entry (for discovery) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface MailboxAgentStatus {\n /** Agent id. */\n agentId: string;\n /** Human-readable name. */\n name: string;\n /** Role. */\n role?: string | undefined;\n /** Session id. */\n sessionId: string;\n /** Current status. */\n status: 'idle' | 'running' | 'streaming' | 'waiting_user' | 'error' | 'offline';\n /** Current tool being executed, if any. */\n currentTool?: string | undefined;\n /** Current task description. */\n currentTask?: string | undefined;\n /** Iteration count so far. */\n iterations: number;\n /** Tool calls so far. */\n toolCalls: number;\n /** ISO8601 \u2014 last activity timestamp. */\n lastActivityAt: string;\n /** ISO8601 \u2014 last heartbeat. */\n lastSeenAt: string;\n /** Whether this agent is currently online (heartbeat within threshold). */\n online: boolean;\n /** Which process. */\n pid: number;\n /** Source. */\n source?: 'cli' | 'webui' | 'mcp' | 'acp' | 'http' | undefined;\n}\n\n// \u2500\u2500 Mailbox query \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface MailboxQuery {\n /** Filter by recipient agent id. */\n to?: string | undefined;\n /** Filter by sender agent id. */\n from?: string | undefined;\n /** Only messages unread by this agent. */\n unreadBy?: string | undefined;\n /** Trusted caller role used with `unreadBy` for audience filtering. */\n readerRole?: string | undefined;\n /** Only incomplete messages. */\n incompleteOnly?: boolean | undefined;\n /**\n * Internal trusted-read option: retain folded per-actor receipt state so a\n * boundary can derive an actor-safe projection. Untrusted query codecs must\n * never accept this field from request payloads.\n */\n includeReceiptState?: boolean | undefined;\n /** Filter by message type. */\n type?: MailboxMessageType | undefined;\n /** Filter by priority (>= this level). */\n minPriority?: 'low' | 'normal' | 'high' | undefined;\n /** Maximum number of messages to return. */\n limit?: number | undefined;\n /** ISO8601 \u2014 only messages after this timestamp. */\n since?: string | undefined;\n /** Filter by the sender's session id (`MailboxMessage.senderSessionId`). */\n sessionId?: string | undefined;\n /**\n * Include soft-deleted messages (where `deletedAt` is set). When\n * `false` (the default), soft-deleted messages are filtered out so\n * the normal inbox view stays clean. The \"trash\" view passes\n * `true` to surface them.\n */\n includeDeleted?: boolean | undefined;\n /**\n * Filter by replyTo parent message id (UUID). When set, only messages\n * whose `replyTo` exactly matches this value are returned. An empty\n * string matches nothing \u2014 empty strings are technically allowed by\n * `send()` (it passes through `MailboxSendInput.replyTo` directly with\n * no normalization), but are never produced by chimera/execution callers.\n * The query filter is exact-match.\n * Useful for polling the response to a specific `ask` message.\n */\n replyTo?: string | undefined;\n}\n\n// \u2500\u2500 Mailbox operations \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Canonical prefix for mail addressed to every agent in one session. */\nexport const SESSION_RECIPIENT_PREFIX = '@session:';\n\n/** Build the canonical recipient address for a session-scoped broadcast. */\nexport function sessionRecipient(sessionId: string): string {\n const normalizedSessionId = sessionId.trim();\n if (!normalizedSessionId) {\n throw new TypeError('sessionId is required for the \"@session\" recipient');\n }\n return `${SESSION_RECIPIENT_PREFIX}${normalizedSessionId}`;\n}\n\n/**\n * Normalize a recipient address.\n *\n * - `\"all\"` (any casing) is canonicalized to `'*'`.\n * - `\"@session\"` (any casing) is canonicalized to\n * `\"@session:<sessionId>\"`; callers must provide the sender's session id.\n * - Already-canonical `\"@session:<sessionId>\"` addresses are preserved.\n */\nexport function normalizeRecipient(to: string, sessionId?: string): string {\n const trimmed = to.trim();\n const normalized = trimmed.toLowerCase();\n if (normalized === 'all') return '*';\n if (normalized === '@session') return sessionRecipient(sessionId ?? '');\n return trimmed;\n}\n\nexport interface MailboxSendInput {\n /** Sender agent id. */\n from: string;\n /** Recipient agent id, '*' / \"all\" for project broadcast, or \"@session\" for the sender's session. */\n to: string;\n /** Message category. */\n type: MailboxMessageType;\n /** Restrict consumption to main/leader agents. Default: `all`. */\n audience?: MailboxAudience | undefined;\n /** Short subject line. */\n subject: string;\n /** Full message content. */\n body: string;\n /** Priority. Default: 'normal'. */\n priority?: 'low' | 'normal' | 'high' | undefined;\n /** If replying, the id of the parent message. */\n replyTo?: string | undefined;\n /** Task context for assign-type messages. */\n taskContext?: MailboxTaskContext | undefined;\n /** Sender session id. Required when `to` is the `\"@session\"` alias. */\n senderSessionId?: string | undefined;\n /**\n * Time-to-live in milliseconds. When set, the message's `expiresAt` is\n * computed as `now + ttlMs` at send time. The auto-compaction sweep\n * removes expired messages. Default: none (use compaction sweep default).\n */\n ttlMs?: number | undefined;\n}\n\n/**\n * Append-only ack record stored in the JSONL alongside messages.\n *\n * Instead of rewriting the entire mailbox file to mark a message as read or\n * completed, we append a small ack record. At read time, ack records are\n * folded into their target messages. The `__ack` discriminator distinguishes\n * ack records from regular messages.\n *\n * Compaction (autoCompact / purgeStale) folds these into the messages and\n * removes the ack lines from the file, keeping the file bounded.\n */\nexport interface AckRecord {\n /** Discriminator \u2014 always `true` to distinguish from MailboxMessage. */\n __ack: true;\n /** The message this ack applies to. */\n messageId: string;\n /** Agent acknowledging the message. */\n readerId: string;\n /** ISO8601 timestamp of the ack. */\n timestamp: string;\n /** Was the message read? */\n read: boolean;\n /** Was the message marked completed? */\n completed?: boolean | undefined;\n /** Who completed it (when completed === true). */\n completedBy?: string | undefined;\n /** Optional outcome summary. */\n outcome?: string | undefined;\n /**\n * Soft-delete or restore the target message.\n * - `true`: set `deletedAt`/`deletedBy` on the message\n * - `false`: clear `deletedAt`/`deletedBy` on the message\n * - `undefined`: not a delete/restore operation (backward-compat default)\n *\n * When `deleted` is `true`, `deletedBy` records who performed the delete.\n */\n deleted?: boolean | undefined;\n /** Who deleted the message (set when `deleted === true`). */\n deletedBy?: string | undefined;\n}\n\nexport interface MailboxAckInput {\n /** Message id to acknowledge. */\n messageId: string;\n /** Agent id of who is reading/acking. */\n readerId: string;\n /** Mark as read by this agent? Defaults to true if not specified. */\n read?: boolean | undefined;\n /** Mark as completed? */\n completed?: boolean | undefined;\n /** Optional outcome summary. */\n outcome?: string | undefined;\n}\n\n/**\n * Batch acknowledgment input \u2014 applies a batch of acks under a single file\n * lock + single file rewrite. Each entry has the same shape as\n * {@link MailboxAckInput} minus the per-batch defaults documented on\n * `ackMany`. Use this when an agent is acking several fresh messages at\n * once (the common case in the mailbox loop) \u2014 it collapses N full-file\n * rewrites into one.\n */\nexport interface MailboxAckBatchInput {\n /** Ack entries to apply. */\n acks: MailboxAckInput[];\n}\n\n// \u2500\u2500 Agent registration input \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface AgentRegistrationInput {\n agentId: string;\n sessionId: string;\n name: string;\n role?: string | undefined;\n pid?: number | undefined;\n source?: 'cli' | 'webui' | 'mcp' | 'acp' | 'http' | undefined;\n}\n\n// \u2500\u2500 Client (REPL/TUI/WebUI) registration \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type ClientSource = 'repl' | 'tui' | 'webui' | 'http';\n\nexport interface RegisteredClient {\n /** Unique client id. */\n clientId: string;\n /** Session/project context id. */\n sessionId: string;\n /** Human-readable name (e.g. \"TUI [main]\", \"WebUI [chrome]\"). */\n name: string;\n /** Client type. */\n source: ClientSource;\n /** ISO8601 \u2014 registered at. */\n registeredAt: string;\n /** ISO8601 \u2014 last heartbeat. */\n lastSeenAt: string;\n /** Which process. */\n pid: number;\n}\n\nexport interface ClientStatus {\n /** Client id. */\n clientId: string;\n /** Human-readable name. */\n name: string;\n /** Client type. */\n source: ClientSource;\n /** Session id. */\n sessionId: string;\n /** ISO8601 \u2014 last activity timestamp. */\n lastSeenAt: string;\n /** Whether this client is currently online (heartbeat within threshold). */\n online: boolean;\n /** Which process. */\n pid: number;\n}\n\nexport interface ClientRegistrationInput {\n clientId: string;\n sessionId: string;\n name: string;\n source: ClientSource;\n pid?: number | undefined;\n}\n\nexport interface ClientHeartbeatInput {\n clientId: string;\n /** Active session id for this client. When present, updates the registry entry. */\n sessionId?: string | undefined;\n}\n\n// \u2500\u2500 Agent heartbeat input \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface AgentHeartbeatInput {\n agentId: string;\n status?: RegisteredAgent['status'] | undefined;\n currentTool?: string | undefined;\n currentTask?: string | undefined;\n iterations?: number | undefined;\n toolCalls?: number | undefined;\n}\n\n// \u2500\u2500 Purge options & result \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface PurgeOptions {\n /**\n * Purge completed messages older than this many milliseconds.\n * Default: 1 day (86_400_000 ms)\n */\n completedMaxAgeMs?: number | undefined;\n /**\n * Purge incomplete messages older than this many milliseconds.\n * Default: 7 days (604_800_000 ms)\n */\n incompleteMaxAgeMs?: number | undefined;\n}\n\nexport interface PurgeResult {\n /** Messages removed because they were completed and too old. */\n completedPurged: number;\n /** Messages removed because they were incomplete and too old. */\n incompletePurged: number;\n /** Total messages removed. */\n totalPurged: number;\n /** Messages remaining in the mailbox after purge. */\n remaining: number;\n}\n\n// \u2500\u2500 Auto-compact options & result \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface AutoCompactOptions {\n /**\n * Remove messages read by ALL currently-online agents that are older\n * than this many milliseconds since the last read receipt was stamped.\n * Default: 10 minutes (AUTO_COMPACT_READ_MAX_AGE_MS).\n */\n readMaxAgeMs?: number | undefined;\n /**\n * Default TTL for messages without an explicit `expiresAt`. Messages\n * whose `timestamp` is older than `now - defaultTtlMs` are removed.\n * Default: 24 hours (AUTO_COMPACT_DEFAULT_TTL_MS).\n */\n defaultTtlMs?: number | undefined;\n /**\n * Per-message-type TTL overrides, consulted before `defaultTtlMs` for\n * messages with no explicit `expiresAt`. Keyed by `MailboxMessageType`.\n * Default: {@link AUTO_COMPACT_TYPE_TTL_MS} (transient `status` chatter\n * expires in 30 minutes instead of 24 hours).\n */\n typeTtlMs?: Readonly<Record<string, number>> | undefined;\n /**\n * Also run `purgeStale` logic in the same pass \u2014 purge completed\n * messages older than this many ms. Default: 1 day.\n */\n completedMaxAgeMs?: number | undefined;\n /**\n * Also run `purgeStale` logic in the same pass \u2014 purge incomplete\n * messages older than this many ms. Default: 7 days.\n */\n incompleteMaxAgeMs?: number | undefined;\n /**\n * Interval for the background auto-compact timer.\n * Default: 5 minutes (AUTO_COMPACT_INTERVAL_MS).\n */\n intervalMs?: number | undefined;\n /**\n * Also run `purgeStale` logic in the same pass (completed > 1 day,\n * incomplete > 7 days). Default: true.\n */\n includePurgeStale?: boolean | undefined;\n}\n\nexport interface AutoCompactResult {\n /** Messages removed because they were read by all online agents. */\n readByAllRemoved: number;\n /** Messages removed because their TTL expired (explicit or default). */\n expiredRemoved: number;\n /** Messages removed by the purgeStale pass (if enabled). */\n stalePurged: number;\n /** Total messages removed. */\n totalRemoved: number;\n /** Messages remaining in the mailbox after compaction. */\n remaining: number;\n}\n\n// \u2500\u2500 Mailbox interface \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface Mailbox {\n /** Send a message. Returns the created message. */\n send(input: MailboxSendInput): Promise<MailboxMessage>;\n\n /** Query messages matching criteria. */\n query(query: MailboxQuery): Promise<MailboxMessage[]>;\n\n /** Acknowledge a message (read/complete). Returns updated message. */\n ack(input: MailboxAckInput): Promise<MailboxMessage | null>;\n\n /**\n * Acknowledge many messages in one shot. Acquires the file lock once and\n * rewrites the message file once, regardless of how many acks are in the\n * batch. Returns the messages that were actually updated (messages whose\n * ids are not in the file are skipped silently).\n *\n * This is the preferred path when an agent has multiple fresh messages\n * to receipt at once \u2014 the per-message {@link ack} path does a full\n * read-modify-rewrite of the mailbox file for every call.\n */\n ackMany(input: MailboxAckBatchInput): Promise<MailboxMessage[]>;\n\n /**\n * Soft-delete a message. Sets `deletedAt` to the current timestamp\n * and records the acting agent in `deletedBy`. Reversible via\n * {@link restore}. The default `query()` filter hides the message\n * once `deletedAt` is set; pass `includeDeleted: true` to see the\n * trash.\n */\n softDelete(mailId: string, by: string): Promise<MailboxMessage | null>;\n\n /**\n * Undo a {@link softDelete}. Clears `deletedAt` and `deletedBy` on\n * the message. No-op (returns the message as-is) if the message is\n * not soft-deleted.\n */\n restore(mailId: string): Promise<MailboxMessage | null>;\n\n /** Get a snapshot of online/offline agents and their current tasks. */\n getAgentStatuses(): Promise<MailboxAgentStatus[]>;\n\n /**\n * Get only online agents (heartbeat within 60s).\n * Useful for \"who can I talk to right now?\" queries.\n */\n getOnlineAgents(): Promise<MailboxAgentStatus[]>;\n\n /**\n * Register an agent. Called once per agent on first mailbox use.\n * Subsequent calls are idempotent \u2014 they update lastSeenAt.\n */\n registerAgent(input: AgentRegistrationInput): Promise<void>;\n /** Remove an agent from the registry entirely. Called on session shutdown. */\n deregisterAgent(agentId: string): Promise<void>;\n\n /**\n * Update agent heartbeat and optional status fields.\n * Called periodically (every tool call / iteration).\n */\n heartbeat(input: AgentHeartbeatInput): Promise<void>;\n\n /**\n * Count unread messages for a specific agent.\n * Used for \"new mail\" notifications without pulling full message bodies.\n */\n unreadCount(forAgentId: string, sessionId?: string): Promise<number>;\n\n /** Close and flush any pending writes. */\n close(): Promise<void>;\n\n /**\n * Delete all messages from the mailbox file.\n * Agents and read receipts are preserved; only messages are cleared.\n */\n clearAll(): Promise<void>;\n\n /**\n * Purge orphaned and stale messages from the mailbox.\n *\n * Stale messages are:\n * - Completed messages older than `completedMaxAgeMs` (default: 1 day)\n * - Incomplete messages older than `incompleteMaxAgeMs` (default: 7 days)\n *\n * This does NOT touch agent registrations or client registry.\n */\n purgeStale(opts?: PurgeOptions): Promise<PurgeResult>;\n\n /**\n * Auto-compact: remove messages that are no longer needed.\n *\n * Two cleanup passes run in a single file rewrite:\n * 1. **Read-by-all**: Messages read by every currently-online agent,\n * older than `readMaxAgeMs` (default 10 min).\n * 2. **Expired**: Messages whose `expiresAt` is in the past, or whose\n * `timestamp` is older than `defaultTtlMs` (default 24h) when no\n * explicit `expiresAt` is set.\n *\n * Also runs `purgeStale` logic (completed > 1 day, incomplete > 7 days)\n * in the same pass to avoid a second rewrite.\n */\n autoCompact(opts?: AutoCompactOptions): Promise<AutoCompactResult>;\n\n /**\n * Start a background timer that periodically calls `autoCompact`.\n * Returns a dispose function that stops the timer. Idempotent \u2014\n * calling start twice replaces the prior timer.\n */\n startAutoCompactTimer(opts?: AutoCompactOptions): () => void;\n\n // \u2500\u2500 Client (REPL/TUI/WebUI) registry \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Register a client (REPL/TUI/WebUI). Called once per client on startup.\n * Subsequent calls are idempotent \u2014 they update lastSeenAt.\n */\n registerClient(input: ClientRegistrationInput): Promise<void>;\n\n /**\n * Update client heartbeat. Called periodically (every 15s for clients).\n */\n clientHeartbeat(input: ClientHeartbeatInput): Promise<void>;\n\n /** Remove a client immediately on clean shutdown. */\n deregisterClient(clientId: string): Promise<void>;\n\n /**\n * Get snapshot of online/offline clients and their last activity.\n */\n getClientStatuses(): Promise<ClientStatus[]>;\n\n /**\n * Explicitly purge stale clients from the registry.\n * Removes client entries whose lastSeenAt is older than CLIENT_STALE_MS.\n * Returns the number of entries purged.\n */\n purgeClients(): Promise<number>;\n}\n\nexport {\n expandMailboxCapabilities,\n hasMailboxCapability,\n MAILBOX_CAPABILITY_IMPLICATIONS,\n type MailboxActorContext,\n type MailboxAuthMode,\n type MailboxCapability,\n type MailboxPrincipalKind,\n} from './mailbox-auth-types.js';\n\n// \u2500\u2500 Recipient-scoped receipt state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Per-recipient delivery/action state for a single message.\n *\n * Keyed by actor ID. Each entry tracks when the actor read, completed,\n * or otherwise interacted with the message \u2014 independently of other actors.\n */\nexport interface MailboxRecipientState {\n /** Actor ID this state belongs to. */\n actorId: string;\n /** ISO8601 \u2014 when this actor first read the message. */\n readAt?: string | undefined;\n /** ISO8601 \u2014 when this actor completed the message. */\n completedAt?: string | undefined;\n /** Who recorded the completion (usually same as actorId). */\n completedBy?: string | undefined;\n /** Optional outcome summary recorded by this actor. */\n outcome?: string | undefined;\n}\n\n/**\n * V2 JSONL receipt record. Appended alongside messages and v1 ack records.\n *\n * Has an explicit `__mailboxReceipt: 2` discriminator so:\n * 1. The v2 reader folds these into per-actor `MailboxRecipientState`.\n * 2. A v1 reader ignores the unknown JSON line (no `__ack` field).\n *\n * Fold algebra (applied during materialization):\n * - Keyed by `(messageId, actorId)`.\n * - `read`: first-write-wins (earliest read timestamp is preserved).\n * - `completed`: monotonic upward (once `true`, cannot revert unless an\n * explicit reopen record with `completed: false` is appended).\n * - `outcome`: last-write-wins.\n * - Duplicate records (same messageId, actorId, timestamp): idempotent no-ops.\n */\nexport interface MailboxReceiptRecordV2 {\n /** Discriminator \u2014 always `2` to distinguish from messages and v1 acks. */\n __mailboxReceipt: 2;\n /** Target message this receipt applies to. */\n messageId: string;\n /** Actor this receipt belongs to. */\n actorId: string;\n /** ISO8601 \u2014 when the receipt event occurred. */\n timestamp: string;\n /** Was the message read by this actor? */\n read?: boolean | undefined;\n /** Was the message completed by this actor? */\n completed?: boolean | undefined;\n /** Optional outcome summary. */\n outcome?: string | undefined;\n}\n\n/**\n * Check if a parsed JSONL value is a v2 receipt record.\n * Validates the discriminator AND required structural fields.\n */\nexport function isMailboxReceiptRecordV2(value: unknown): value is MailboxReceiptRecordV2 {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const v = value as Record<string, unknown>;\n if (v['__mailboxReceipt'] !== 2) return false;\n if (typeof v['messageId'] !== 'string' || v['messageId'].length === 0) return false;\n if (typeof v['actorId'] !== 'string' || v['actorId'].length === 0) return false;\n if (typeof v['timestamp'] !== 'string' || v['timestamp'].length === 0) return false;\n // Validate optional fields when present \u2014 prevents malformed JSONL records\n // from entering typed receipt-folding code (e.g. completed:\"false\" truthy string).\n if ('read' in v && typeof v['read'] !== 'boolean') return false;\n if ('completed' in v && typeof v['completed'] !== 'boolean') return false;\n if ('outcome' in v && v['outcome'] !== undefined && typeof v['outcome'] !== 'string') return false;\n return true;\n}\n\n// \u2500\u2500 Message projections \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Materialized message with per-actor recipient state.\n *\n * This is the internal representation after folding all v1 acks and v2\n * receipt records. It carries both the legacy fields (for backward\n * compatibility) and the new actor-specific state map.\n *\n * `legacyGlobalCompletion` is set ONLY for historical v1 fan-out messages\n * that were globally completed. It is never set for new v2 writes.\n */\nexport interface MailboxMessageProjection extends MailboxMessage {\n /** Per-actor delivery/action state, keyed by actorId. */\n recipientState: Readonly<Record<string, MailboxRecipientState>>;\n /**\n * True ONLY for historical v1 fan-out messages that were globally completed\n * (completed before the v2 migration). These remain globally suppressed to\n * prevent upgrade re-delivery. New v2 writes NEVER set this.\n */\n legacyGlobalCompletion?: boolean | undefined;\n}\n\n/**\n * Self-facing message \u2014 what a specific actor sees.\n *\n * This does NOT extend `MailboxMessage` because self-facing responses must NOT\n * contain aggregate receipt metadata (`readBy`, `completedBy`, `completedAt`,\n * `outcome`) that would leak other actors' activity. Only actor-specific\n * derived fields are added on top of the non-sensitive message fields.\n */\nexport interface ActorMailboxMessage\n extends Omit<MailboxMessage, 'readBy' | 'completed' | 'completedBy' | 'completedAt' | 'outcome'> {\n /** Has this actor read the message? */\n readByMe: boolean;\n /** Has this actor completed the message? */\n completedByMe: boolean;\n /** Does this message require action from this actor? */\n actionRequiredForMe: boolean;\n /** This actor's outcome, if any. */\n myOutcome?: string | undefined;\n /**\n * True for historical v1 fan-out messages that were globally completed.\n * Lets the UI distinguish \"completed by me\" from \"completed globally\n * before migration.\"\n */\n legacyGlobalCompletion?: boolean | undefined;\n}\n\n/**\n * Derive `actionRequiredForMe` from the canonical type properties and actor state.\n *\n * Defined as:\n * `MAILBOX_TYPE_PROPERTIES[type].requiresAction && visible && !completedByMe && !deleted && !legacyGlobalCompletion`\n *\n * For historical legacy-global messages, `actionRequiredForMe` is always false\n * because the message is suppressed and should not re-enter any actor's flow.\n */\nexport function isActionRequiredForActor(\n message: Pick<MailboxMessage, 'type' | 'deletedAt' | 'completed'>,\n projection: Pick<ActorMailboxMessage, 'completedByMe' | 'legacyGlobalCompletion'>,\n): boolean {\n if (projection.legacyGlobalCompletion) return false;\n if (message.deletedAt !== undefined) return false;\n if (projection.completedByMe) return false;\n return MAILBOX_TYPE_PROPERTIES[message.type]?.requiresAction === true;\n}\n", "/**\n * V2 receipt record folding and message materialization.\n *\n * GM-P0.4: This module implements the per-actor receipt state materialization\n * that replaces the message-global `completed` boolean with actor-scoped\n * delivery state. It also implements the v1\u2192v2 migration classification rules.\n *\n * The key insight: v1 ack records (`__ack: true`) and v2 receipt records\n * (`__mailboxReceipt: 2`) coexist in the same JSONL file during migration.\n * This module folds BOTH into a unified `MailboxMessageProjection` that\n * carries per-actor `recipientState`.\n *\n * @module mailbox-receipt-folding\n */\n\nimport type {\n MailboxMessage,\n MailboxMessageProjection,\n MailboxRecipientState,\n MailboxReceiptRecordV2,\n} from './mailbox-types.js';\nimport { isMailboxReceiptRecordV2 } from './mailbox-types.js';\n\nexport type { MailboxMessageProjection };\n\n/**\n * Determine if a message's recipient is a fan-out form (broadcast, alias, or\n * session-scoped). Fan-out messages use `legacyGlobalCompletion` for v1 acks\n * because the original semantic was message-global.\n *\n * Heuristic: exact agent IDs are qualified with either `@` (session identity)\n * or `#` (process identity), matching `mailboxIdentityBase()`. A `to` value\n * without either delimiter is a bare base alias such as `leader` or `worker`\n * and therefore fans out. `*` and `@session:...` are explicit broadcasts.\n */\nexport function isFanOutRecipient(to: string): boolean {\n if (to === '*') return true;\n if (to.startsWith('@session:')) return true;\n // A bare base alias contains neither exact-recipient delimiter.\n return !to.includes('@') && !to.includes('#');\n}\n\n/**\n * Materialize messages with per-actor recipient state.\n *\n * Input: the raw parsed messages (already folded with v1 acks by\n * `parseMailboxLines()`), plus any v2 receipt records found in the file.\n *\n * Output: `MailboxMessageProjection[]` carrying:\n * - `recipientState`: per-actor delivery/action state\n * - `legacyGlobalCompletion`: true for historical v1 fan-out completions\n *\n * v1 completion classification:\n * - Direct exact-recipient message + completed v1 ack \u2192 actor-scoped for\n * that recipient. The `completed` boolean is projected from\n * `recipientState[recipient].completedAt !== undefined`.\n * - Fan-out message (broadcast/alias/session) + completed v1 ack \u2192\n * `legacyGlobalCompletion: true`. The message remains globally\n * suppressed; NO actor-scoped completion is created.\n *\n * v2 receipt folding:\n * - Keyed by `(messageId, actorId)`.\n * - `read`: first-write-wins (earliest timestamp preserved).\n * - `completed`: monotonic upward (once true, cannot revert unless an\n * explicit `completed: false` record is appended).\n * - `outcome`: last-write-wins.\n * - Duplicate records (same messageId, actorId, timestamp): idempotent.\n */\nexport function materializeMessages(\n messages: readonly MailboxMessage[],\n v2Receipts: readonly MailboxReceiptRecordV2[],\n): MailboxMessageProjection[] {\n // Index v2 receipts by messageId for efficient lookup.\n const receiptsByMessage = new Map<string, MailboxReceiptRecordV2[]>();\n for (const receipt of v2Receipts) {\n const list = receiptsByMessage.get(receipt.messageId);\n if (list) list.push(receipt);\n else receiptsByMessage.set(receipt.messageId, [receipt]);\n }\n\n return messages.map((msg) => materializeMessage(msg, receiptsByMessage.get(msg.id) ?? []));\n}\n\n/**\n * Materialize a single message against the receipts that target it.\n *\n * Split out of {@link materializeMessages} so the incremental read path\n * (see `mailbox-parse-state.ts`) can re-fold exactly the messages an appended\n * chunk touched instead of re-projecting the entire file. Callers MUST pass\n * the message's COMPLETE receipt list, not just the newly appended ones \u2014\n * `foldRecipientState` sorts by timestamp and `classifyLegacyCompletion`\n * scans for any `completed: true`, so a partial list would diverge from a\n * full parse.\n */\nexport function materializeMessage(\n msg: MailboxMessage,\n msgReceipts: readonly MailboxReceiptRecordV2[],\n): MailboxMessageProjection {\n const recipientState = foldRecipientState(msg, msgReceipts);\n const legacyGlobalCompletion = classifyLegacyCompletion(msg, msgReceipts);\n\n return {\n ...msg,\n recipientState,\n ...(legacyGlobalCompletion ? { legacyGlobalCompletion: true } : {}),\n };\n}\n\n/**\n * Fold v2 receipt records into a per-actor `recipientState` map for a\n * single message. Also seeds from v1 `readBy` entries (which are\n * per-recipient read timestamps from the existing schema).\n *\n * Fold algebra:\n * - `readAt`: first-write-wins (earliest read timestamp is preserved).\n * - `completedAt`: monotonic upward (once set, cannot be cleared by\n * a new receipt unless `completed: false` is explicitly set, which\n * acts as a reopen).\n * - `outcome`: last-write-wins.\n */\nfunction foldRecipientState(\n msg: MailboxMessage,\n v2Receipts: readonly MailboxReceiptRecordV2[],\n): Record<string, MailboxRecipientState> {\n const state: Record<string, MailboxRecipientState> = {};\n\n // Seed from v1 readBy entries (these are already per-recipient read timestamps).\n for (const [actorId, readAt] of Object.entries(msg.readBy)) {\n state[actorId] = { actorId, readAt };\n }\n\n // Seed from v1 completion (only for direct messages \u2014 fan-out uses legacyGlobalCompletion).\n if (msg.completed && msg.completedBy && !isFanOutRecipient(msg.to)) {\n const existing = state[msg.completedBy] ?? { actorId: msg.completedBy };\n state[msg.completedBy] = {\n ...existing,\n completedAt: msg.completedAt ?? msg.timestamp,\n completedBy: msg.completedBy,\n ...(msg.outcome !== undefined ? { outcome: msg.outcome } : {}),\n };\n }\n\n // Fold v2 receipt records.\n // Sort by timestamp to ensure deterministic fold order. ECMAScript's stable\n // sort preserves persisted file order when timestamps compare equal.\n const sorted = [...v2Receipts].sort((a, b) => a.timestamp.localeCompare(b.timestamp));\n\n for (const receipt of sorted) {\n const actorId = receipt.actorId;\n const existing = state[actorId] ?? { actorId };\n\n // readAt: first-write-wins.\n const readAt = existing.readAt ?? (receipt.read === true ? receipt.timestamp : undefined);\n\n // completedAt: monotonic upward. Can be cleared by explicit completed: false (reopen).\n let completedAt = existing.completedAt;\n let completedBy = existing.completedBy;\n if (receipt.completed === true) {\n completedAt = receipt.timestamp;\n completedBy = actorId;\n } else if (receipt.completed === false) {\n completedAt = undefined;\n completedBy = undefined;\n }\n\n // outcome: last-write-wins.\n const outcome = receipt.outcome !== undefined ? receipt.outcome : existing.outcome;\n\n state[actorId] = { actorId, readAt, completedAt, completedBy, outcome };\n }\n\n return state;\n}\n\n/**\n * Classify whether a v1 message's completion should be treated as\n * `legacyGlobalCompletion`.\n *\n * Rules (from SDD R3):\n * - Fan-out message (broadcast/alias/session) with `completed: true`\n * \u2192 `legacyGlobalCompletion: true` regardless of `readerId`.\n * - Direct exact-recipient message with `completed: true`\n * \u2192 NOT legacy (it's actor-scoped, handled in foldRecipientState).\n */\nfunction classifyLegacyCompletion(msg: MailboxMessage, v2Receipts: readonly MailboxReceiptRecordV2[]): boolean {\n if (!msg.completed) return false;\n // Suppress legacy-global classification only when v2 data carries\n // unambiguous actor-scoped completion provenance \u2014 at least one v2\n // receipt with completed:true. A read-only v2 receipt must NOT\n // suppress legacy completion (GM-P0.4 R3).\n if (v2Receipts.some((r) => r.completed === true)) return false;\n return isFanOutRecipient(msg.to);\n}\n\n/**\n * Serialize a v2 receipt record to a JSONL line.\n */\nexport function serializeReceiptRecordV2(record: MailboxReceiptRecordV2): string {\n return JSON.stringify(record) + '\\n';\n}\n\n/**\n * Extract v2 receipt records from a set of parsed JSONL lines.\n * Messages and v1 ack records are ignored.\n *\n * This is used by the read path to separate receipts from messages\n * before materialization.\n *\n * @param parsed - Array of parsed JSON values from the JSONL file.\n * @returns Only the values that pass `isMailboxReceiptRecordV2`.\n */\nexport function extractV2Receipts(parsed: readonly unknown[]): MailboxReceiptRecordV2[] {\n const receipts: MailboxReceiptRecordV2[] = [];\n for (const item of parsed) {\n if (isMailboxReceiptRecordV2(item)) {\n receipts.push(item);\n }\n }\n return receipts;\n}\n\n/**\n * Build a v2 receipt record from an ack operation.\n * Used when folding legacy v1 ack records during the one-shot import.\n */\nexport function buildReceiptRecordV2(\n messageId: string,\n actorId: string,\n timestamp: string,\n opts: { read?: boolean; completed?: boolean; outcome?: string },\n): MailboxReceiptRecordV2 {\n const record: MailboxReceiptRecordV2 = {\n __mailboxReceipt: 2,\n messageId,\n actorId,\n timestamp,\n };\n if (opts.read !== undefined) record.read = opts.read;\n if (opts.completed !== undefined) record.completed = opts.completed;\n if (opts.outcome !== undefined) record.outcome = opts.outcome;\n return record;\n}\n", "import type {\n MailboxAgentStatus,\n MailboxMessage,\n MailboxMessageProjection,\n MailboxRecipientState,\n} from './mailbox-types.js';\nimport { isMailboxMessageVisibleTo, mailboxIdentityBase } from './mailbox-types.js';\n\nexport interface MailboxRetentionState {\n completed: boolean;\n completedAt?: string | undefined;\n}\n\n/**\n * Resolve whether retention may treat a message as completed.\n *\n * Historical fan-out completion remains global. New v2 fan-out completion is\n * eligible for the short completed TTL only when every currently relevant\n * recipient has an actor-scoped completion receipt. Otherwise the message\n * stays on the incomplete retention path.\n */\nexport function resolveMailboxRetentionState(\n message: MailboxMessage,\n agentStatuses: readonly MailboxAgentStatus[] | undefined,\n): MailboxRetentionState {\n const projection = message as MailboxMessageProjection;\n if (projection.legacyGlobalCompletion) {\n return { completed: true, completedAt: message.completedAt ?? message.timestamp };\n }\n\n const recipientState = projection.recipientState;\n if (recipientState === undefined) {\n return message.completed\n ? { completed: true, completedAt: message.completedAt ?? message.timestamp }\n : { completed: false };\n }\n\n const relevantRecipients = resolveRelevantRecipients(message, recipientState, agentStatuses);\n if (relevantRecipients.length === 0) return { completed: false };\n\n const completionTimes: string[] = [];\n for (const actorId of relevantRecipients) {\n const completedAt = recipientState[actorId]?.completedAt;\n if (completedAt === undefined) return { completed: false };\n completionTimes.push(completedAt);\n }\n\n return {\n completed: true,\n // Retention starts only after the last intended recipient completed.\n completedAt: completionTimes.reduce((latest, time) => (time > latest ? time : latest)),\n };\n}\n\n/**\n * Project a stored message's completion state for a project-wide or\n * actor-scoped query without mutating the authoritative record.\n */\nexport function projectMailboxCompletion(\n message: MailboxMessage,\n actorId: string | undefined,\n agentStatuses: readonly MailboxAgentStatus[] | undefined,\n): MailboxMessageProjection {\n const projection = message as MailboxMessageProjection;\n let state: MailboxRetentionState;\n if (actorId === undefined) {\n state = resolveMailboxRetentionState(message, agentStatuses);\n } else if (projection.legacyGlobalCompletion) {\n state = { completed: true, completedAt: message.completedAt ?? message.timestamp };\n } else if (projection.recipientState !== undefined) {\n const completedAt = projection.recipientState[actorId]?.completedAt;\n state =\n completedAt === undefined ? { completed: false } : { completed: true, completedAt };\n } else {\n state = message.completed\n ? { completed: true, completedAt: message.completedAt ?? message.timestamp }\n : { completed: false };\n }\n\n const result: MailboxMessageProjection = {\n ...projection,\n completed: state.completed,\n readBy: { ...message.readBy },\n };\n if (state.completedAt === undefined) delete result.completedAt;\n else result.completedAt = state.completedAt;\n return result;\n}\n\nfunction resolveRelevantRecipients(\n message: MailboxMessage,\n recipientState: Readonly<Record<string, MailboxRecipientState>>,\n agentStatuses: readonly MailboxAgentStatus[] | undefined,\n): string[] {\n const statuses = agentStatuses ?? [];\n const receiptActors = Object.keys(recipientState);\n if (message.to === '*') {\n if (statuses.length === 0) return [];\n const registeredRecipients = statuses\n .filter((status) => isMailboxMessageVisibleTo(message, status.agentId, status.role))\n .map((status) => status.agentId);\n // Include receipt actors even after they fall out of the live registry;\n // otherwise a later registry snapshot can forget an incomplete recipient\n // and move a fan-out message onto the short completed TTL.\n return [...new Set([...registeredRecipients, ...receiptActors])];\n }\n\n if (message.to.startsWith('@session:')) {\n if (statuses.length === 0) return [];\n const sessionId = message.to.slice('@session:'.length);\n const registeredRecipients = statuses\n .filter(\n (status) =>\n status.sessionId === sessionId &&\n isMailboxMessageVisibleTo(message, status.agentId, status.role),\n )\n .map((status) => status.agentId);\n return [...new Set([...registeredRecipients, ...receiptActors])];\n }\n\n if (message.to.includes('@')) return [message.to];\n\n if (statuses.length === 0) return [];\n\n const aliasRecipients = statuses\n .filter(\n (status) =>\n (status.role?.toLowerCase() === message.to.toLowerCase() ||\n mailboxIdentityBase(status.agentId) === message.to.toLowerCase()) &&\n isMailboxMessageVisibleTo(message, status.agentId, status.role),\n )\n .map((status) => status.agentId);\n return [...new Set([...aliasRecipients, ...receiptActors])];\n}\n", "import type {\n ClientStatus,\n MailboxAgentStatus,\n RegisteredAgent,\n RegisteredClient,\n} from './mailbox-types.js';\n\nexport function mapRegisteredAgentsToStatuses(\n registry: ReadonlyMap<string, RegisteredAgent>,\n now: number,\n staleMs: number,\n): MailboxAgentStatus[] {\n return Array.from(registry.values())\n .map((agent) => ({\n agentId: agent.agentId,\n name: agent.name,\n role: agent.role,\n sessionId: agent.sessionId,\n status: agent.status,\n currentTool: agent.currentTool,\n currentTask: agent.currentTask,\n iterations: agent.iterations,\n toolCalls: agent.toolCalls,\n lastActivityAt: agent.lastSeenAt,\n lastSeenAt: agent.lastSeenAt,\n online: now - new Date(agent.lastSeenAt).getTime() < staleMs,\n pid: agent.pid,\n source: agent.source,\n }))\n .sort((a, b) => b.lastSeenAt.localeCompare(a.lastSeenAt));\n}\n\nexport function mapRegisteredClientsToStatuses(\n registry: ReadonlyMap<string, RegisteredClient>,\n now: number,\n staleMs: number,\n): ClientStatus[] {\n return Array.from(registry.values())\n .map((client) => ({\n clientId: client.clientId,\n name: client.name,\n source: client.source,\n sessionId: client.sessionId,\n lastSeenAt: client.lastSeenAt,\n online: now - new Date(client.lastSeenAt).getTime() < staleMs,\n pid: client.pid,\n }))\n .sort((a, b) => b.lastSeenAt.localeCompare(a.lastSeenAt));\n}\n", "import type {\n AckRecord,\n MailboxAudience,\n MailboxMessage,\n MailboxMessageType,\n MailboxTaskContext,\n ReadReceipts,\n} from './mailbox-types.js';\nimport { LINE_SEPARATOR } from './mailbox-constants.js';\nimport { normalizeRecipient, validateSendType } from './mailbox-types.js';\n\nconst MESSAGE_TYPES = new Set<MailboxMessageType>([\n 'note',\n 'ask',\n 'assign',\n 'steer',\n 'btw',\n 'broadcast',\n 'status',\n 'result',\n 'review',\n 'control',\n]);\n\nconst PRIORITIES = new Set<MailboxMessage['priority']>(['low', 'normal', 'high']);\nconst AUDIENCES = new Set<MailboxAudience>(['all', 'leaders']);\nconst TASK_STATUSES = new Set([\n 'pending',\n 'in_progress',\n 'completed',\n 'failed',\n 'idle',\n 'running',\n 'streaming',\n 'waiting_user',\n 'error',\n 'offline',\n 'busy',\n]);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction requiredString(record: Record<string, unknown>, key: string): string {\n const value = record[key];\n if (typeof value !== 'string') {\n throw new TypeError(`mailbox message field \"${key}\" must be a string`);\n }\n return value;\n}\n\nfunction optionalString(record: Record<string, unknown>, key: string): Record<string, string> {\n const value = record[key];\n if (value === undefined) return {};\n if (typeof value !== 'string') {\n throw new TypeError(`mailbox message field \"${key}\" must be a string when present`);\n }\n return { [key]: value };\n}\n\nfunction parseMessageType(value: unknown): MailboxMessageType {\n if (value === 'info') return 'note';\n if (value === 'task') return 'assign';\n if (typeof value === 'string' && MESSAGE_TYPES.has(value as MailboxMessageType)) {\n return value as MailboxMessageType;\n }\n throw new TypeError('mailbox message field \"type\" is invalid');\n}\n\n/** Normalize message types emitted by pre-union mailbox builds. */\nexport function normalizeMailboxMessageType(value: unknown): MailboxMessageType {\n return parseMessageType(value);\n}\n\n/**\n * Resolve the message type for a SEND operation, applying default-type logic\n * and cross-field validation.\n *\n * ** Default-type rules ** (mirror the `mail_send` tool's logic):\n * - When `type` is explicitly provided, use it directly.\n * - When `type` is omitted AND the resolved `to` is `\"*\"` or starts with\n * `\"@session:\"`, the default is `\"broadcast\"`.\n * - Otherwise (omitted, non-broadcast target), the default is `\"note\"`.\n *\n * **Send-side validation** (from `validateSendType`):\n * - `control` is rejected \u2014 it is reserved for runtime use.\n * - `assign` and `steer` with `to=\"*\"` are rejected \u2014 these types require a\n * specific recipient.\n *\n * @returns The resolved type (explicit or defaulted).\n * @throws {TypeError} When the type is reserved or the (type, to) pair is\n * semantically invalid.\n */\nexport function resolveSendType(\n type: MailboxMessageType | undefined,\n to: string,\n): MailboxMessageType {\n // Normalize recipient aliases (\"all\" \u2192 \"*\", \"@session\" \u2192 \"@session:<id>\")\n // BEFORE default-type selection and cross-field validation, so every\n // caller (mail_send, mailbox tool, HTTP bridge) gets consistent behavior\n // even when they forget to normalize beforehand.\n const normalizedTo = normalizeRecipient(to);\n const resolved: MailboxMessageType =\n type ?? (normalizedTo === '*' || normalizedTo.startsWith('@session:') ? 'broadcast' : 'note');\n // Validate the resolved type against the CANONICAL recipient \u2014 after\n // normalization \u2014 so \"all\" with type \"assign\" is correctly rejected\n // as a multi-recipient target.\n validateSendType(resolved, normalizedTo);\n return resolved;\n}\n\n/**\n * Resolve the message type for a SEND, returning a descriptive error instead\n * of throwing. Convenience wrapper for use in tool handlers where a thrown\n * TypeError would be awkward to catch.\n *\n * Returns `{ ok: true, type }` on success, or `{ ok: false, error }` when\n * the (type, to) pair is invalid.\n */\nexport function resolveSendTypeSafe(\n type: MailboxMessageType | undefined,\n to: string,\n): { ok: true; type: MailboxMessageType } | { ok: false; error: string } {\n try {\n return { ok: true, type: resolveSendType(type, to) };\n } catch (err) {\n return { ok: false, error: (err as Error).message };\n }\n}\n\nfunction parsePriority(value: unknown): MailboxMessage['priority'] {\n if (typeof value === 'string' && PRIORITIES.has(value as MailboxMessage['priority'])) {\n return value as MailboxMessage['priority'];\n }\n // Older callers were intentionally tolerant here and ranked unknown values\n // as normal. Normalize rather than dropping an otherwise valid message.\n if (typeof value === 'string') return 'normal';\n throw new TypeError('mailbox message field \"priority\" must be a string');\n}\n\nfunction parseAudience(value: unknown): MailboxAudience | undefined {\n if (value === undefined || value === 'all') return undefined;\n if (typeof value === 'string' && AUDIENCES.has(value as MailboxAudience)) {\n return value as MailboxAudience;\n }\n throw new TypeError('mailbox message field \"audience\" is invalid');\n}\n\nfunction parseReadReceipts(record: Record<string, unknown>, to: string): ReadReceipts {\n const value = record['readBy'];\n if (value === undefined) {\n const legacyReadAt = record['readAt'];\n return record['read'] === true && typeof legacyReadAt === 'string'\n ? { [to || 'unknown']: legacyReadAt }\n : {};\n }\n if (!isRecord(value)) {\n throw new TypeError('mailbox message field \"readBy\" must be an object');\n }\n\n const receipts: ReadReceipts = {};\n for (const [agentId, timestamp] of Object.entries(value)) {\n if (typeof timestamp !== 'string') {\n throw new TypeError('mailbox message read receipt timestamps must be strings');\n }\n receipts[agentId] = timestamp;\n }\n return receipts;\n}\n\nfunction parseTaskContext(value: unknown): MailboxTaskContext | undefined {\n if (value === undefined) return undefined;\n if (!isRecord(value)) {\n throw new TypeError('mailbox message field \"taskContext\" must be an object');\n }\n\n const status = value['status'];\n if (\n status !== undefined &&\n (typeof status !== 'string' ||\n !TASK_STATUSES.has(status as NonNullable<MailboxTaskContext['status']>))\n ) {\n throw new TypeError('mailbox message taskContext status is invalid');\n }\n\n return {\n ...optionalString(value, 'agentRole'),\n ...optionalString(value, 'agentName'),\n ...optionalString(value, 'taskId'),\n ...(status === undefined\n ? {}\n : { status: status as NonNullable<MailboxTaskContext['status']> }),\n };\n}\n\n/** Parse, migrate, and structurally validate one persisted mailbox message. */\nexport function parseMailboxMessage(value: unknown): MailboxMessage {\n if (!isRecord(value)) throw new TypeError('mailbox message must be an object');\n\n const to = value['to'] === undefined ? '' : requiredString(value, 'to');\n const completed = value['completed'];\n if (typeof completed !== 'boolean') {\n throw new TypeError('mailbox message field \"completed\" must be a boolean');\n }\n\n const taskContext = parseTaskContext(value['taskContext']);\n const audience = parseAudience(value['audience']);\n return {\n id: requiredString(value, 'id'),\n from: requiredString(value, 'from'),\n to,\n type: parseMessageType(value['type']),\n ...(audience === undefined ? {} : { audience }),\n subject: requiredString(value, 'subject'),\n body: requiredString(value, 'body'),\n priority: parsePriority(value['priority']),\n readBy: parseReadReceipts(value, to),\n completed,\n timestamp: requiredString(value, 'timestamp'),\n ...optionalString(value, 'completedBy'),\n ...optionalString(value, 'outcome'),\n ...optionalString(value, 'completedAt'),\n ...optionalString(value, 'deletedAt'),\n ...optionalString(value, 'deletedBy'),\n ...optionalString(value, 'replyTo'),\n ...optionalString(value, 'senderSessionId'),\n ...optionalString(value, 'expiresAt'),\n ...(taskContext === undefined ? {} : { taskContext }),\n };\n}\n\n/** Parse one JSONL line and validate the decoded mailbox message. */\nexport function parseMailboxMessageLine(line: string): MailboxMessage {\n return parseMailboxMessage(JSON.parse(line) as unknown);\n}\n\n// \u2500\u2500 Ack record helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Check if a parsed JSONL value is an append-only ack record (not a message).\n * Ack records carry a `__ack: true` discriminator.\n */\nexport function isAckRecord(value: unknown): value is AckRecord {\n return (\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n (value as Record<string, unknown>)['__ack'] === true\n );\n}\n\n/**\n * Parse one JSONL line, returning either a MailboxMessage or an AckRecord.\n * Returns null when the line is neither (corrupt/malformed).\n */\nexport function parseMailboxLine(line: string): MailboxMessage | AckRecord | null {\n try {\n const parsed = JSON.parse(line) as unknown;\n if (isAckRecord(parsed)) return parsed;\n return parseMailboxMessage(parsed);\n } catch {\n return null;\n }\n}\n\n/** Parse a JSONL mailbox body into messages, applying append-only ack records. */\nexport function parseMailboxLines(raw: string): MailboxMessage[] {\n const lines = raw.split(LINE_SEPARATOR).filter((line) => line.trim().length > 0);\n const messages: MailboxMessage[] = [];\n const acks: AckRecord[] = [];\n for (const line of lines) {\n const parsed = parseMailboxLine(line);\n if (isAckRecord(parsed)) {\n acks.push(parsed);\n } else if (parsed !== null) {\n messages.push(parsed);\n }\n }\n for (const ack of acks) {\n const target = messages.find((message) => message.id === ack.messageId);\n if (target) applyAckToMessage(target, ack);\n }\n return messages;\n}\n\n/**\n * Apply an ack record's effects to a MailboxMessage in-place.\n * This mutates the message object (readBy, completed, completedBy, completedAt,\n * outcome, deletedAt, deletedBy).\n */\nexport function applyAckToMessage(msg: MailboxMessage, ack: AckRecord): void {\n if (ack.read && !(ack.readerId in msg.readBy)) {\n msg.readBy[ack.readerId] = ack.timestamp;\n }\n if (ack.completed && !msg.completed) {\n msg.completed = true;\n msg.completedBy = ack.completedBy ?? ack.readerId;\n msg.completedAt = ack.timestamp;\n }\n if (ack.outcome !== undefined && msg.outcome !== ack.outcome) {\n msg.outcome = ack.outcome;\n }\n // Soft-delete: set deletedAt/deletedBy.\n if (ack.deleted === true) {\n msg.deletedAt = ack.timestamp;\n msg.deletedBy = ack.deletedBy ?? ack.readerId;\n }\n // Restore: clear deletedAt/deletedBy.\n if (ack.deleted === false) {\n delete msg.deletedAt;\n delete msg.deletedBy;\n }\n}\n\n/**\n * Serialize an ack record to a JSONL line.\n */\nexport function serializeAckRecord(ack: AckRecord): string {\n return JSON.stringify(ack) + '\\n';\n}\n\n/**\n * Serialize a MailboxMessage to a JSONL line.\n *\n * Strips any extra fields added by a projection (recipientState,\n * legacyGlobalCompletion) so compaction rewrites produce clean\n * v1-parseable lines. V2 receipt records are preserved as separate\n * lines \u2014 they are NOT embedded in the message object.\n */\nexport function serializeMailboxMessage(msg: MailboxMessage): string {\n const obj: Record<string, unknown> = {\n id: msg.id,\n from: msg.from,\n to: msg.to,\n type: msg.type,\n subject: msg.subject,\n body: msg.body,\n priority: msg.priority,\n readBy: msg.readBy,\n completed: msg.completed,\n timestamp: msg.timestamp,\n };\n if (msg.audience !== undefined && msg.audience !== 'all') obj.audience = msg.audience;\n if (msg.completedBy !== undefined) obj.completedBy = msg.completedBy;\n if (msg.outcome !== undefined) obj.outcome = msg.outcome;\n if (msg.completedAt !== undefined) obj.completedAt = msg.completedAt;\n if (msg.deletedAt !== undefined) obj.deletedAt = msg.deletedAt;\n if (msg.deletedBy !== undefined) obj.deletedBy = msg.deletedBy;\n if (msg.replyTo !== undefined) obj.replyTo = msg.replyTo;\n if (msg.senderSessionId !== undefined) obj.senderSessionId = msg.senderSessionId;\n if (msg.expiresAt !== undefined) obj.expiresAt = msg.expiresAt;\n if (msg.taskContext !== undefined) obj.taskContext = msg.taskContext;\n return JSON.stringify(obj) + '\\n';\n}\n", "/**\n * Retention sweeps over the mailbox message table: the age-based `purgeStale`\n * and the richer `autoCompact` (expiry + read-by-all + stale).\n *\n * Split out of `sqlite-mailbox.ts`. Both walk the materialized message\n * projections rather than SQL predicates, because retention state is derived\n * from per-recipient receipts plus live agent status \u2014 see\n * `resolveMailboxRetentionState`.\n *\n * @module coordination/sqlite-mailbox-compaction\n */\nimport {\n AUTO_COMPACT_DEFAULT_TTL_MS,\n AUTO_COMPACT_READ_MAX_AGE_MS,\n AUTO_COMPACT_TYPE_TTL_MS,\n} from './mailbox-constants.js';\nimport { resolveMailboxRetentionState } from './mailbox-retention-state.js';\nimport type {\n AutoCompactOptions,\n AutoCompactResult,\n MailboxAgentStatus,\n MailboxMessageProjection,\n PurgeOptions,\n PurgeResult,\n} from './mailbox-types.js';\nimport { isMailboxMessageVisibleTo } from './mailbox-types.js';\n\n/** The store operations a sweep needs. */\nexport interface CompactionContext {\n getAgentStatuses: () => Promise<MailboxAgentStatus[]>;\n readMessages: () => MailboxMessageProjection[];\n deleteMessages: (ids: readonly string[]) => void;\n}\n\nexport async function purgeStale(\n ctx: CompactionContext,\n options?: PurgeOptions,\n): Promise<PurgeResult> {\n const completedMaxAgeMs = options?.completedMaxAgeMs ?? 86_400_000;\n const incompleteMaxAgeMs = options?.incompleteMaxAgeMs ?? 604_800_000;\n const statuses = await ctx.getAgentStatuses();\n const now = Date.now();\n let completedPurged = 0;\n let incompletePurged = 0;\n const ids: string[] = [];\n const messages = ctx.readMessages();\n for (const message of messages) {\n const retention = resolveMailboxRetentionState(message, statuses);\n const messageTime = new Date(message.timestamp).getTime();\n const completionTime = new Date(retention.completedAt ?? 0).getTime();\n if (retention.completed && completionTime < now - completedMaxAgeMs) {\n completedPurged++;\n ids.push(message.id);\n } else if (!retention.completed && messageTime < now - incompleteMaxAgeMs) {\n incompletePurged++;\n ids.push(message.id);\n }\n }\n ctx.deleteMessages(ids);\n return {\n completedPurged,\n incompletePurged,\n totalPurged: ids.length,\n remaining: messages.length - ids.length,\n };\n}\n\nexport async function autoCompact(\n ctx: CompactionContext,\n options?: AutoCompactOptions,\n): Promise<AutoCompactResult> {\n const readMaxAgeMs = options?.readMaxAgeMs ?? AUTO_COMPACT_READ_MAX_AGE_MS;\n const defaultTtlMs = options?.defaultTtlMs ?? AUTO_COMPACT_DEFAULT_TTL_MS;\n const typeTtlMs = options?.typeTtlMs ?? AUTO_COMPACT_TYPE_TTL_MS;\n const completedMaxAgeMs = options?.completedMaxAgeMs ?? 86_400_000;\n const incompleteMaxAgeMs = options?.incompleteMaxAgeMs ?? 604_800_000;\n const statuses = await ctx.getAgentStatuses();\n const online = statuses.filter((status) => status.online);\n const now = Date.now();\n let readByAllRemoved = 0;\n let expiredRemoved = 0;\n let stalePurged = 0;\n const ids: string[] = [];\n const messages = ctx.readMessages();\n\n for (const message of messages) {\n const messageTime = new Date(message.timestamp).getTime();\n const expiry =\n message.expiresAt !== undefined\n ? new Date(message.expiresAt).getTime()\n : messageTime + (typeTtlMs[message.type] ?? defaultTtlMs);\n if (expiry < now) {\n expiredRemoved++;\n ids.push(message.id);\n continue;\n }\n\n const retention = resolveMailboxRetentionState(message, statuses);\n const eligible = online.filter((status) =>\n isMailboxMessageVisibleTo(message, status.agentId, status.role),\n );\n if (!retention.completed && eligible.length > 0) {\n const readByAll = eligible.every((status) => status.agentId in message.readBy);\n const latestRead = Math.max(\n ...eligible.map((status) => new Date(message.readBy[status.agentId] ?? 0).getTime()),\n );\n if (readByAll && latestRead < now - readMaxAgeMs) {\n readByAllRemoved++;\n ids.push(message.id);\n continue;\n }\n }\n\n const completionTime = new Date(retention.completedAt ?? 0).getTime();\n if (\n (retention.completed && completionTime < now - completedMaxAgeMs) ||\n (!retention.completed && messageTime < now - incompleteMaxAgeMs)\n ) {\n stalePurged++;\n ids.push(message.id);\n }\n }\n\n ctx.deleteMessages(ids);\n return {\n readByAllRemoved,\n expiredRemoved,\n stalePurged,\n totalRemoved: ids.length,\n remaining: messages.length - ids.length,\n };\n}\n", "/**\n * Mailbox credential lifecycle and storage.\n *\n * GM-P0.6: opaque per-principal credential issuance, rotation, revocation,\n * verification and audit. Credentials are stored as keyed hashes so a store\n * leak does not expose reusable tokens.\n *\n * Types and policy only. The storage half used to live here as\n * `JsonlCredentialStore` over `_mailbox_credentials.json`; credentials now\n * live in `_mailbox.sqlite` behind the project owner, so the only thing that\n * still reads the old file is `SqliteMailbox.migrateLegacyCredentials()` \u2014\n * hence `CREDENTIAL_STORE_FILE` and `resolveCredentialStorePath` staying.\n *\n * @module mailbox-credential-store\n */\n\nimport * as crypto from 'node:crypto';\nimport * as path from 'node:path';\nimport type { MailboxCapability } from './mailbox-types.js';\n\n// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type CredentialStatus = 'active' | 'expired' | 'revoked' | 'rotated_out';\n\nexport interface MailboxCredential {\n /** Public identifier for this credential. */\n credentialId: string;\n /** Keyed hash of the secret (HMAC-SHA-256 verifier). Never the raw token. */\n verifier: string;\n /** Algorithm used for the verifier. */\n verifierAlgorithm: 'hmac-sha256';\n /** Principal identity this credential authorizes. */\n principalId: string;\n /** Project this credential is bound to. */\n projectId?: string | undefined;\n /** Capabilities granted to this credential. */\n capabilities: MailboxCapability[];\n /** Credential kind. */\n kind: 'agent' | 'operator' | 'service';\n /** ISO8601 \u2014 when this credential was issued. */\n issuedAt: string;\n /** ISO8601 \u2014 when this credential expires. */\n expiresAt: string;\n /** Optional ISO8601 \u2014 not valid before this time. */\n notBefore?: string | undefined;\n /** Current status. */\n status: CredentialStatus;\n /** ISO8601 \u2014 last status change. */\n statusChangedAt: string;\n /** Reason for the current status. */\n statusReason?: string | undefined;\n /** Previous credential ID this one supersedes. */\n supersedes?: string | undefined;\n /** ISO8601 \u2014 rotated credentials remain valid until this overlap expires. */\n rotationValidUntil?: string | undefined;\n /** Auditor: session/agent that performed the last mutation. */\n lastModifiedBy?: string | undefined;\n}\n\nexport interface CredentialStoreEntry {\n credential: MailboxCredential;\n /** Auditor: session/agent that performed the last mutation. */\n lastModifiedBy?: string | undefined;\n}\n\nexport interface IssueCredentialOptions {\n principalId: string;\n projectId?: string | undefined;\n kind: 'agent' | 'operator' | 'service';\n capabilities: MailboxCapability[];\n ttlMs: number;\n notBefore?: Date | undefined;\n supersedes?: string | undefined;\n issuedBy?: string | undefined;\n}\n\nexport interface CredentialValidation {\n valid: boolean;\n credential?: MailboxCredential | undefined;\n reason?: string | undefined;\n}\n\n/** Minimal verification contract shared by file-backed and remote stores. */\nexport interface MailboxCredentialVerifier {\n load(): Promise<void>;\n verify(\n credentialId: string,\n secret: string,\n ): CredentialValidation | Promise<CredentialValidation>;\n verifyPersisted(credentialId: string, secret: string): Promise<CredentialValidation>;\n}\n\n// \u2500\u2500 Constants \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Default credential file name. */\nexport const CREDENTIAL_STORE_FILE = '_mailbox_credentials.json';\n\n/** Maximum lifetime by credential kind. */\nexport const MAX_CREDENTIAL_TTL: Record<MailboxCredential['kind'], number> = {\n agent: 7 * 24 * 60 * 60 * 1000, // 7 days\n operator: 24 * 60 * 60 * 1000, // 24 hours\n service: 30 * 24 * 60 * 60 * 1000, // 30 days\n};\n\n/** Default rotation overlap window (old + new both valid). */\nexport const ROTATION_OVERLAP_MS = 60 * 60 * 1000; // 1 hour\n\n/** Create an opaque credential without choosing a persistence backend. */\nexport function createMailboxCredential(\n opts: IssueCredentialOptions,\n now = Date.now(),\n): { credential: MailboxCredential; secret: string } {\n const ttlMs = Math.min(opts.ttlMs, MAX_CREDENTIAL_TTL[opts.kind]);\n const credentialId = crypto.randomUUID();\n const secret = crypto.randomBytes(32).toString('hex');\n const verifierKey = crypto.createHash('sha256').update(secret).digest();\n const verifier = crypto.createHmac('sha256', verifierKey).update(credentialId).digest('hex');\n\n return {\n credential: {\n credentialId,\n verifier,\n verifierAlgorithm: 'hmac-sha256',\n principalId: opts.principalId,\n projectId: opts.projectId,\n capabilities: opts.capabilities,\n kind: opts.kind,\n issuedAt: new Date(now).toISOString(),\n expiresAt: new Date(now + ttlMs).toISOString(),\n notBefore: opts.notBefore?.toISOString(),\n status: 'active',\n statusChangedAt: new Date(now).toISOString(),\n supersedes: opts.supersedes,\n lastModifiedBy: opts.issuedBy,\n },\n secret,\n };\n}\n\n/** Verify an opaque secret against a stored credential snapshot. */\nexport function verifyMailboxCredential(\n credential: MailboxCredential | undefined,\n secret: string,\n now = Date.now(),\n): CredentialValidation {\n if (credential === undefined) {\n return { valid: false, reason: 'credential not found' };\n }\n\n const rotationStillValid =\n credential.status === 'rotated_out' &&\n credential.rotationValidUntil !== undefined &&\n new Date(credential.rotationValidUntil).getTime() >= now;\n if (credential.status !== 'active' && !rotationStillValid) {\n return { valid: false, reason: `credential is ${credential.status}`, credential };\n }\n // Inclusive: a credential that expires AT `now` is expired, mirroring\n // `notBefore` below (valid at exactly `notBefore`). With the exclusive\n // comparison a zero-TTL credential was accepted for the millisecond it was\n // issued in \u2014 invisible against the file store, which was slow enough that\n // the clock had usually moved on by the time `verify` ran, and reproducible\n // against SQLite, which is not.\n if (new Date(credential.expiresAt).getTime() <= now) {\n return { valid: false, reason: 'credential expired', credential };\n }\n if (credential.notBefore !== undefined && new Date(credential.notBefore).getTime() > now) {\n return { valid: false, reason: 'credential not yet valid', credential };\n }\n\n const verifierKey = crypto.createHash('sha256').update(secret).digest();\n const expected = crypto\n .createHmac('sha256', verifierKey)\n .update(credential.credentialId)\n .digest('hex');\n const actualBytes = Buffer.from(credential.verifier, 'hex');\n const expectedBytes = Buffer.from(expected, 'hex');\n if (\n actualBytes.length !== expectedBytes.length ||\n !crypto.timingSafeEqual(actualBytes, expectedBytes)\n ) {\n return { valid: false, reason: 'invalid secret', credential };\n }\n\n return { valid: true, credential };\n}\n\n// \u2500\u2500 Store \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Resolve the credential store file path from the project directory.\n */\nexport function resolveCredentialStorePath(projectDir: string): string {\n return path.join(projectDir, CREDENTIAL_STORE_FILE);\n}\n", "/**\n * Row codecs for the SQLite mailbox \u2014 the SQL that turns domain records into\n * table rows and back.\n *\n * Split out of `sqlite-mailbox.ts`. Every function takes the open database and\n * prepares its own statement, exactly as the private methods it replaced did\n * via `this.stmt()`. No message-flow policy lives here: `send`/`query`/`ack`\n * stay in the store.\n *\n * @module coordination/sqlite-mailbox-rows\n */\nimport type { DatabaseSync } from 'node:sqlite';\nimport { AGENT_STALE_MS, CLIENT_STALE_MS } from './mailbox-constants.js';\nimport type { MailboxCredential } from './mailbox-credential-store.js';\nimport type {\n MailboxMessage,\n MailboxMessageProjection,\n MailboxRecipientState,\n RegisteredAgent,\n RegisteredClient,\n} from './mailbox-types.js';\n\nexport type SqliteStatement = ReturnType<DatabaseSync['prepare']>;\n\nexport interface MessageRow {\n id: string;\n data: string;\n legacy_global_completion: number;\n}\n\nexport interface ReceiptRow {\n message_id: string;\n actor_id: string;\n read_at: string | null;\n completed_at: string | null;\n completed_by: string | null;\n outcome: string | null;\n}\n\n/**\n * Predicate matching a `last_seen_at` that is not an ISO-8601 timestamp.\n *\n * A registration whose heartbeat timestamp is garbage would otherwise outlive\n * every sweep: string comparison puts `'invalid'` after any real timestamp, so\n * `last_seen_at < cutoff` never matches it and the row shows up as a\n * permanently offline agent. The JSONL registry it replaced pruned these via\n * `Number.isFinite(Date.parse(...))`.\n */\nexport const MALFORMED_TIMESTAMP =\n \"last_seen_at NOT GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T*'\";\n\n/**\n * Strip the message-level completion fields from a fan-out message before it\n * is stored. Per-actor state lives in `message_receipts`; the aggregate fields\n * would claim the message is done for every recipient.\n */\nexport function withoutAggregateCompletion(\n message: MailboxMessageProjection,\n): MailboxMessageProjection {\n const stored: MailboxMessageProjection = {\n ...message,\n completed: message.legacyGlobalCompletion === true,\n };\n if (!stored.completed) {\n delete stored.completedBy;\n delete stored.completedAt;\n }\n delete stored.outcome;\n return stored;\n}\n\n// \u2500\u2500 Messages \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function persistMessage(\n db: DatabaseSync,\n message: MailboxMessage,\n legacyGlobalCompletion = false,\n): void {\n const stored = { ...message, readBy: { ...message.readBy } } as MailboxMessageProjection;\n delete (stored as Partial<MailboxMessageProjection>).recipientState;\n delete (stored as Partial<MailboxMessageProjection>).legacyGlobalCompletion;\n db.prepare(`\n INSERT INTO messages(\n id, from_id, to_id, type, priority, timestamp, completed, completed_at,\n deleted_at, sender_session_id, reply_to, expires_at,\n legacy_global_completion, data\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET\n from_id = excluded.from_id,\n to_id = excluded.to_id,\n type = excluded.type,\n priority = excluded.priority,\n timestamp = excluded.timestamp,\n completed = excluded.completed,\n completed_at = excluded.completed_at,\n deleted_at = excluded.deleted_at,\n sender_session_id = excluded.sender_session_id,\n reply_to = excluded.reply_to,\n expires_at = excluded.expires_at,\n legacy_global_completion = excluded.legacy_global_completion,\n data = excluded.data\n `).run(\n message.id,\n message.from,\n message.to,\n message.type,\n message.priority,\n message.timestamp,\n message.completed ? 1 : 0,\n message.completedAt ?? null,\n message.deletedAt ?? null,\n message.senderSessionId ?? null,\n message.replyTo ?? null,\n message.expiresAt ?? null,\n legacyGlobalCompletion ? 1 : 0,\n JSON.stringify(stored),\n );\n}\n\nexport function persistReceipt(\n db: DatabaseSync,\n messageId: string,\n state: MailboxRecipientState,\n): void {\n db.prepare(`\n INSERT INTO message_receipts(\n message_id, actor_id, read_at, completed_at, completed_by, outcome\n ) VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT(message_id, actor_id) DO UPDATE SET\n read_at = excluded.read_at,\n completed_at = excluded.completed_at,\n completed_by = excluded.completed_by,\n outcome = excluded.outcome\n `).run(\n messageId,\n state.actorId,\n state.readAt ?? null,\n state.completedAt ?? null,\n state.completedBy ?? null,\n state.outcome ?? null,\n );\n}\n\nexport function materializeMessageRows(\n db: DatabaseSync,\n rows: readonly MessageRow[],\n): MailboxMessageProjection[] {\n if (rows.length === 0) return [];\n\n const useTargetedReceipts = rows.length <= 500;\n const receiptSql = useTargetedReceipts\n ? `\n SELECT message_id, actor_id, read_at, completed_at, completed_by, outcome\n FROM message_receipts\n WHERE message_id IN (${rows.map(() => '?').join(', ')})\n `\n : `\n SELECT message_id, actor_id, read_at, completed_at, completed_by, outcome\n FROM message_receipts\n `;\n const receiptRows = db\n .prepare(receiptSql)\n .all(...(useTargetedReceipts ? rows.map((row) => row.id) : [])) as unknown as ReceiptRow[];\n const receiptState = new Map<string, Record<string, MailboxRecipientState>>();\n for (const row of receiptRows) {\n const states = receiptState.get(row.message_id) ?? {};\n states[row.actor_id] = {\n actorId: row.actor_id,\n ...(row.read_at !== null ? { readAt: row.read_at } : {}),\n ...(row.completed_at !== null ? { completedAt: row.completed_at } : {}),\n ...(row.completed_by !== null ? { completedBy: row.completed_by } : {}),\n ...(row.outcome !== null ? { outcome: row.outcome } : {}),\n };\n receiptState.set(row.message_id, states);\n }\n\n return rows.map((row) => {\n const base = JSON.parse(row.data) as MailboxMessage;\n const recipientState = receiptState.get(row.id) ?? {};\n const readBy = { ...base.readBy };\n for (const state of Object.values(recipientState)) {\n if (state.readAt !== undefined) readBy[state.actorId] = state.readAt;\n }\n return {\n ...base,\n readBy,\n recipientState,\n ...(row.legacy_global_completion === 1 ? { legacyGlobalCompletion: true } : {}),\n };\n });\n}\n\nexport function deleteMessages(db: DatabaseSync, ids: readonly string[]): void {\n const statement = db.prepare('DELETE FROM messages WHERE id = ?');\n for (const id of ids) statement.run(id);\n}\n\n// \u2500\u2500 Agents \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function persistAgent(db: DatabaseSync, agent: RegisteredAgent): void {\n db.prepare(`\n INSERT INTO agents(\n agent_id, session_id, name, role, status, current_tool, current_task,\n iterations, tool_calls, registered_at, last_seen_at, pid, source\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(agent_id) DO UPDATE SET\n session_id = excluded.session_id,\n name = excluded.name,\n role = excluded.role,\n status = excluded.status,\n current_tool = excluded.current_tool,\n current_task = excluded.current_task,\n iterations = excluded.iterations,\n tool_calls = excluded.tool_calls,\n registered_at = excluded.registered_at,\n last_seen_at = excluded.last_seen_at,\n pid = excluded.pid,\n source = excluded.source\n `).run(\n agent.agentId,\n agent.sessionId,\n agent.name,\n agent.role ?? null,\n agent.status,\n agent.currentTool ?? null,\n agent.currentTask ?? null,\n agent.iterations,\n agent.toolCalls,\n agent.registeredAt,\n agent.lastSeenAt,\n agent.pid,\n agent.source ?? null,\n );\n}\n\nexport function readAgents(db: DatabaseSync): Map<string, RegisteredAgent> {\n const rows = db.prepare('SELECT * FROM agents').all() as unknown as Array<\n Record<string, unknown>\n >;\n const agents = new Map<string, RegisteredAgent>();\n for (const row of rows) {\n const agent: RegisteredAgent = {\n agentId: String(row['agent_id']),\n sessionId: String(row['session_id']),\n name: String(row['name']),\n ...(row['role'] !== null ? { role: String(row['role']) } : {}),\n status: row['status'] as RegisteredAgent['status'],\n ...(row['current_tool'] !== null ? { currentTool: String(row['current_tool']) } : {}),\n ...(row['current_task'] !== null ? { currentTask: String(row['current_task']) } : {}),\n iterations: Number(row['iterations']),\n toolCalls: Number(row['tool_calls']),\n registeredAt: String(row['registered_at']),\n lastSeenAt: String(row['last_seen_at']),\n pid: Number(row['pid']),\n ...(row['source'] !== null ? { source: row['source'] as RegisteredAgent['source'] } : {}),\n };\n agents.set(agent.agentId, agent);\n }\n return agents;\n}\n\nexport function pruneAgents(db: DatabaseSync, maxAgeMs = AGENT_STALE_MS): number {\n const cutoff = new Date(Date.now() - Math.max(0, maxAgeMs)).toISOString();\n const result = db\n .prepare(`DELETE FROM agents WHERE last_seen_at < ? OR ${MALFORMED_TIMESTAMP}`)\n .run(cutoff);\n return Number(result.changes);\n}\n\n// \u2500\u2500 Clients \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function persistClient(db: DatabaseSync, client: RegisteredClient): void {\n db.prepare(`\n INSERT INTO clients(\n client_id, session_id, name, source, registered_at, last_seen_at, pid\n ) VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(client_id) DO UPDATE SET\n session_id = excluded.session_id,\n name = excluded.name,\n source = excluded.source,\n registered_at = excluded.registered_at,\n last_seen_at = excluded.last_seen_at,\n pid = excluded.pid\n `).run(\n client.clientId,\n client.sessionId,\n client.name,\n client.source,\n client.registeredAt,\n client.lastSeenAt,\n client.pid,\n );\n}\n\nexport function readClients(db: DatabaseSync): Map<string, RegisteredClient> {\n const rows = db.prepare('SELECT * FROM clients').all() as unknown as Array<\n Record<string, unknown>\n >;\n const clients = new Map<string, RegisteredClient>();\n for (const row of rows) {\n const client: RegisteredClient = {\n clientId: String(row['client_id']),\n sessionId: String(row['session_id']),\n name: String(row['name']),\n source: row['source'] as RegisteredClient['source'],\n registeredAt: String(row['registered_at']),\n lastSeenAt: String(row['last_seen_at']),\n pid: Number(row['pid']),\n };\n clients.set(client.clientId, client);\n }\n return clients;\n}\n\nexport function pruneClients(db: DatabaseSync): number {\n const cutoff = new Date(Date.now() - CLIENT_STALE_MS).toISOString();\n const result = db\n .prepare(`DELETE FROM clients WHERE last_seen_at < ? OR ${MALFORMED_TIMESTAMP}`)\n .run(cutoff);\n return Number(result.changes);\n}\n\n// \u2500\u2500 Credentials \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function persistCredential(db: DatabaseSync, credential: MailboxCredential): void {\n db.prepare(`\n INSERT INTO credentials(credential_id, status, principal_id, expires_at, data)\n VALUES (?, ?, ?, ?, ?)\n ON CONFLICT(credential_id) DO UPDATE SET\n status = excluded.status,\n principal_id = excluded.principal_id,\n expires_at = excluded.expires_at,\n data = excluded.data\n `).run(\n credential.credentialId,\n credential.status,\n credential.principalId,\n credential.expiresAt,\n JSON.stringify(credential),\n );\n}\n", "/**\n * Credential issue / verify / revoke / rotate against the mailbox `credentials`\n * table.\n *\n * Split out of `sqlite-mailbox.ts`; the store keeps thin `credential*` methods\n * that delegate here, so its public surface is unchanged.\n *\n * @module coordination/sqlite-mailbox-credentials\n */\nimport type { DatabaseSync } from 'node:sqlite';\nimport {\n createMailboxCredential,\n type CredentialValidation,\n type IssueCredentialOptions,\n MAX_CREDENTIAL_TTL,\n type MailboxCredential,\n ROTATION_OVERLAP_MS,\n verifyMailboxCredential,\n} from './mailbox-credential-store.js';\nimport { persistCredential } from './sqlite-mailbox-rows.js';\n\nexport function credentialGet(db: DatabaseSync, credentialId: string): MailboxCredential | null {\n const row = db.prepare('SELECT data FROM credentials WHERE credential_id = ?').get(credentialId) as\n | { data: string }\n | undefined;\n return row === undefined ? null : (JSON.parse(row.data) as MailboxCredential);\n}\n\nexport function credentialList(db: DatabaseSync): MailboxCredential[] {\n const rows = db.prepare('SELECT data FROM credentials').all() as unknown as {\n data: string;\n }[];\n return rows\n .map((row) => JSON.parse(row.data) as MailboxCredential)\n .sort((left, right) => {\n if (left.status === 'active' && right.status !== 'active') return -1;\n if (left.status !== 'active' && right.status === 'active') return 1;\n return right.issuedAt.localeCompare(left.issuedAt);\n });\n}\n\nexport function credentialStatusCounts(db: DatabaseSync): Record<string, number> {\n const rows = db\n .prepare('SELECT status, COUNT(*) AS count FROM credentials GROUP BY status')\n .all() as unknown as { status: string; count: number }[];\n return Object.fromEntries(rows.map((row) => [row.status, row.count]));\n}\n\nexport function credentialIssue(\n db: DatabaseSync,\n transaction: <T>(run: () => T) => T,\n options: IssueCredentialOptions,\n): { credential: MailboxCredential; secret: string } {\n const now = Date.now();\n const issued = createMailboxCredential(options, now);\n transaction(() => {\n if (options.supersedes !== undefined) {\n const old = credentialGet(db, options.supersedes);\n if (old?.status === 'active') {\n old.status = 'rotated_out';\n old.statusChangedAt = new Date(now).toISOString();\n old.statusReason = 'superseded by rotation';\n old.rotationValidUntil = new Date(now + ROTATION_OVERLAP_MS).toISOString();\n persistCredential(db, old);\n }\n }\n persistCredential(db, issued.credential);\n });\n return issued;\n}\n\nexport function credentialVerify(\n db: DatabaseSync,\n credentialId: string,\n secret: string,\n): CredentialValidation {\n return verifyMailboxCredential(credentialGet(db, credentialId) ?? undefined, secret);\n}\n\nexport function credentialRevoke(\n db: DatabaseSync,\n credentialId: string,\n reason?: string,\n by?: string,\n): boolean {\n const credential = credentialGet(db, credentialId);\n if (credential === null || credential.status === 'revoked') return false;\n credential.status = 'revoked';\n credential.statusChangedAt = new Date().toISOString();\n credential.statusReason = reason ?? 'revoked';\n credential.lastModifiedBy = by;\n persistCredential(db, credential);\n return true;\n}\n\nexport function credentialRotate(\n db: DatabaseSync,\n transaction: <T>(run: () => T) => T,\n credentialId: string,\n options?: Partial<IssueCredentialOptions>,\n): { credential: MailboxCredential; secret: string } | null {\n const old = credentialGet(db, credentialId);\n if (old === null) return null;\n return credentialIssue(db, transaction, {\n principalId: old.principalId,\n projectId: old.projectId ?? options?.projectId,\n kind: old.kind,\n capabilities: options?.capabilities ?? old.capabilities,\n ttlMs: options?.ttlMs ?? MAX_CREDENTIAL_TTL[old.kind],\n supersedes: credentialId,\n issuedBy: options?.issuedBy,\n });\n}\n", "/**\n * Schema creation, version fencing, and one-time legacy-file import for the\n * SQLite mailbox.\n *\n * Split out of `sqlite-mailbox.ts`. Everything here runs once, from the store's\n * constructor; keeping it separate leaves that file to the message flow.\n *\n * @module coordination/sqlite-mailbox-schema\n */\nimport * as fs from 'node:fs';\nimport { createRequire } from 'node:module';\nimport * as path from 'node:path';\nimport type { DatabaseSync } from 'node:sqlite';\nimport { withSqliteExperimentalWarningSuppressed } from '../utils/sqlite-warning.js';\nimport { GLOBAL_MAILBOX_CLIENT_REGISTRY_FILE, GLOBAL_MAILBOX_FILE } from './global-mailbox-paths.js';\nimport {\n CREDENTIAL_STORE_FILE,\n type MailboxCredential,\n} from './mailbox-credential-store.js';\nimport { parseMailboxFile } from './mailbox-parse-state.js';\nimport { parseAgentRegistryEntry, parseClientRegistryEntry } from './mailbox-registry-codec.js';\nimport type { MailboxMessage, MailboxMessageProjection } from './mailbox-types.js';\nimport {\n persistAgent,\n persistClient,\n persistCredential,\n persistMessage,\n persistReceipt,\n} from './sqlite-mailbox-rows.js';\n\nexport const SQLITE_MAILBOX_SCHEMA_VERSION = 2;\n\nlet DatabaseSyncCtor: typeof DatabaseSync | undefined;\n\nexport function loadDatabaseSync(): typeof DatabaseSync {\n if (DatabaseSyncCtor) return DatabaseSyncCtor;\n return withSqliteExperimentalWarningSuppressed(() => {\n const require = createRequire(import.meta.url);\n DatabaseSyncCtor = (require('node:sqlite') as typeof import('node:sqlite')).DatabaseSync;\n return DatabaseSyncCtor;\n });\n}\n\n/** The store state schema setup and migration need. */\nexport interface SchemaContext {\n db: DatabaseSync;\n projectDir: string;\n transaction: <T>(run: () => T) => T;\n}\n\nexport function initializeSchema(ctx: SchemaContext): void {\n const { db } = ctx;\n db.exec(`\n CREATE TABLE IF NOT EXISTS mailbox_meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n CREATE TABLE IF NOT EXISTS messages (\n id TEXT PRIMARY KEY,\n from_id TEXT NOT NULL,\n to_id TEXT NOT NULL,\n type TEXT NOT NULL,\n priority TEXT NOT NULL,\n timestamp TEXT NOT NULL,\n completed INTEGER NOT NULL DEFAULT 0,\n completed_at TEXT,\n deleted_at TEXT,\n sender_session_id TEXT,\n reply_to TEXT,\n expires_at TEXT,\n legacy_global_completion INTEGER NOT NULL DEFAULT 0,\n data TEXT NOT NULL\n );\n CREATE TABLE IF NOT EXISTS message_receipts (\n message_id TEXT NOT NULL REFERENCES messages(id) ON DELETE CASCADE,\n actor_id TEXT NOT NULL,\n read_at TEXT,\n completed_at TEXT,\n completed_by TEXT,\n outcome TEXT,\n PRIMARY KEY (message_id, actor_id)\n );\n CREATE TABLE IF NOT EXISTS agents (\n agent_id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL,\n name TEXT NOT NULL,\n role TEXT,\n status TEXT NOT NULL,\n current_tool TEXT,\n current_task TEXT,\n iterations INTEGER NOT NULL,\n tool_calls INTEGER NOT NULL,\n registered_at TEXT NOT NULL,\n last_seen_at TEXT NOT NULL,\n pid INTEGER NOT NULL,\n source TEXT\n );\n CREATE TABLE IF NOT EXISTS clients (\n client_id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL,\n name TEXT NOT NULL,\n source TEXT NOT NULL,\n registered_at TEXT NOT NULL,\n last_seen_at TEXT NOT NULL,\n pid INTEGER NOT NULL\n );\n CREATE TABLE IF NOT EXISTS credentials (\n credential_id TEXT PRIMARY KEY,\n status TEXT NOT NULL,\n principal_id TEXT NOT NULL,\n expires_at TEXT NOT NULL,\n data TEXT NOT NULL\n );\n CREATE INDEX IF NOT EXISTS idx_messages_to_timestamp ON messages(to_id, timestamp DESC);\n CREATE INDEX IF NOT EXISTS idx_messages_from_timestamp ON messages(from_id, timestamp DESC);\n CREATE INDEX IF NOT EXISTS idx_messages_type_timestamp ON messages(type, timestamp DESC);\n CREATE INDEX IF NOT EXISTS idx_messages_deleted_at ON messages(deleted_at);\n CREATE INDEX IF NOT EXISTS idx_messages_session_timestamp ON messages(sender_session_id, timestamp DESC);\n CREATE INDEX IF NOT EXISTS idx_messages_reply_timestamp ON messages(reply_to, timestamp DESC);\n CREATE INDEX IF NOT EXISTS idx_receipts_actor ON message_receipts(actor_id, message_id);\n CREATE INDEX IF NOT EXISTS idx_agents_last_seen ON agents(last_seen_at);\n CREATE INDEX IF NOT EXISTS idx_clients_last_seen ON clients(last_seen_at);\n CREATE INDEX IF NOT EXISTS idx_credentials_status ON credentials(status, expires_at);\n `);\n db.prepare('INSERT INTO mailbox_meta(key, value) VALUES (?, ?) ON CONFLICT(key) DO NOTHING').run(\n 'schema_version',\n String(SQLITE_MAILBOX_SCHEMA_VERSION),\n );\n const schema = db.prepare('SELECT value FROM mailbox_meta WHERE key = ?').get('schema_version') as\n | { value: string }\n | undefined;\n const foundVersion = Number(schema?.value);\n if (\n !Number.isInteger(foundVersion) ||\n foundVersion < 1 ||\n foundVersion > SQLITE_MAILBOX_SCHEMA_VERSION\n ) {\n throw new Error(\n `Unsupported mailbox SQLite schema ${schema?.value ?? 'missing'}; this build supports ${SQLITE_MAILBOX_SCHEMA_VERSION}`,\n );\n }\n if (foundVersion < SQLITE_MAILBOX_SCHEMA_VERSION) {\n db.prepare('UPDATE mailbox_meta SET value = ? WHERE key = ?').run(\n String(SQLITE_MAILBOX_SCHEMA_VERSION),\n 'schema_version',\n );\n }\n migrateLegacyCredentials(ctx);\n}\n\nfunction migrateLegacyCredentials(ctx: SchemaContext): void {\n const { db } = ctx;\n const marker = db\n .prepare('SELECT value FROM mailbox_meta WHERE key = ?')\n .get('legacy_credentials_imported') as { value: string } | undefined;\n if (marker !== undefined) return;\n const legacyPath = path.join(ctx.projectDir, CREDENTIAL_STORE_FILE);\n const credentials: MailboxCredential[] = [];\n try {\n for (const line of fs.readFileSync(legacyPath, 'utf8').split(/\\r?\\n/u)) {\n if (!line.trim()) continue;\n try {\n const credential = JSON.parse(line) as MailboxCredential;\n if (\n typeof credential.credentialId === 'string' &&\n typeof credential.verifier === 'string' &&\n typeof credential.principalId === 'string'\n )\n credentials.push(credential);\n } catch {\n // Preserve legacy adapter behavior: malformed records are skipped.\n }\n }\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== 'ENOENT') throw error;\n }\n ctx.transaction(() => {\n for (const credential of credentials) persistCredential(db, credential);\n db.prepare('INSERT INTO mailbox_meta(key, value) VALUES (?, ?)').run(\n 'legacy_credentials_imported',\n new Date().toISOString(),\n );\n });\n}\n\nexport function migrateLegacyFiles(ctx: SchemaContext): void {\n const { db } = ctx;\n const marker = db\n .prepare('SELECT value FROM mailbox_meta WHERE key = ?')\n .get('legacy_files_imported') as { value: string } | undefined;\n if (marker !== undefined) return;\n\n const messages = readLegacyMessages(ctx.projectDir);\n const agents = readLegacyRegistry(\n path.join(ctx.projectDir, '_mailbox.registry.json'),\n parseAgentRegistryEntry,\n );\n const clients = readLegacyRegistry(\n path.join(ctx.projectDir, GLOBAL_MAILBOX_CLIENT_REGISTRY_FILE),\n parseClientRegistryEntry,\n );\n\n ctx.transaction(() => {\n for (const message of messages) {\n const projection = message as MailboxMessageProjection;\n persistMessage(db, message, projection.legacyGlobalCompletion === true);\n for (const state of Object.values(projection.recipientState ?? {})) {\n persistReceipt(db, message.id, state);\n }\n }\n for (const agent of agents.values()) persistAgent(db, agent);\n for (const client of clients.values()) persistClient(db, client);\n db.prepare('INSERT INTO mailbox_meta(key, value) VALUES (?, ?)').run(\n 'legacy_files_imported',\n new Date().toISOString(),\n );\n });\n}\n\nfunction readLegacyMessages(projectDir: string): MailboxMessage[] {\n try {\n return parseMailboxFile(\n fs.readFileSync(path.join(projectDir, GLOBAL_MAILBOX_FILE), 'utf8'),\n );\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return [];\n throw error;\n }\n}\n\nfunction readLegacyRegistry<T>(\n filePath: string,\n parseEntry: (value: unknown) => T | null,\n): Map<string, T> {\n try {\n const raw = JSON.parse(fs.readFileSync(filePath, 'utf8')) as Record<string, unknown>;\n const result = new Map<string, T>();\n for (const [id, value] of Object.entries(raw)) {\n const parsed = parseEntry(value);\n if (parsed !== null) result.set(id, parsed);\n }\n return result;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return new Map();\n throw error;\n }\n}\n", "const SQLITE_EXPERIMENTAL_WARNING_RE = /sqlite is an experimental feature/i;\n\nfunction isSqliteExperimentalWarning(warning: unknown, rest: readonly unknown[]): boolean {\n const message = typeof warning === 'string' ? warning : warning instanceof Error ? warning.message : '';\n const typeOrOptions = rest[0];\n const warningType =\n typeof warning === 'string'\n ? typeof typeOrOptions === 'string'\n ? typeOrOptions\n : typeof typeOrOptions === 'object' &&\n typeOrOptions !== null &&\n 'type' in typeOrOptions &&\n typeof typeOrOptions.type === 'string'\n ? typeOrOptions.type\n : ''\n : warning instanceof Error\n ? warning.name\n : '';\n const warningCode =\n typeof warning === 'string'\n ? typeof typeOrOptions === 'object' &&\n typeOrOptions !== null &&\n 'code' in typeOrOptions &&\n typeof typeOrOptions.code === 'string'\n ? typeOrOptions.code\n : typeof rest[1] === 'string'\n ? rest[1]\n : ''\n : warning instanceof Error && 'code' in warning && typeof warning.code === 'string'\n ? warning.code\n : '';\n\n return (\n SQLITE_EXPERIMENTAL_WARNING_RE.test(message) &&\n (warningType === 'ExperimentalWarning' || warningCode === 'ExperimentalWarning')\n );\n}\n\n/**\n * Run a synchronous `node:sqlite` load while filtering only Node's built-in\n * SQLite ExperimentalWarning. All other warnings still go through the original\n * process warning path, and the patch is removed before returning.\n */\nexport function withSqliteExperimentalWarningSuppressed<T>(run: () => T): T {\n const originalEmitWarning = process.emitWarning;\n const forwardWarning = originalEmitWarning.bind(process) as (\n warning: unknown,\n ...rest: unknown[]\n ) => void;\n\n process.emitWarning = ((warning: unknown, ...rest: unknown[]): void => {\n if (isSqliteExperimentalWarning(warning, rest)) return;\n forwardWarning(warning, ...rest);\n }) as typeof process.emitWarning;\n\n try {\n return run();\n } finally {\n process.emitWarning = originalEmitWarning;\n }\n}\n", "import * as path from 'node:path';\nimport { projectSlug } from '../utils/wstack-paths.js';\n\nexport const GLOBAL_MAILBOX_FILE = '_mailbox.jsonl';\nexport const GLOBAL_MAILBOX_CLIENT_REGISTRY_FILE = '_mailbox.clients.json';\n\n/**\n * Derive the project-level mailbox directory path.\n *\n * Delegates to the canonical projectSlug() from wstack-paths so every surface\n * lands in the same ~/.wrongstack/projects/<slug>/ directory.\n */\nexport function resolveProjectDir(projectRoot: string, globalRoot: string): string {\n return path.join(globalRoot, 'projects', projectSlug(projectRoot));\n}\n", "/**\n * Incremental parse state for the mailbox JSONL file.\n *\n * `parseMailboxFile()` is a whole-file operation: it JSON-parses every line and\n * re-projects every message. That is the correct shape for a one-shot read, but\n * the read path is anything but one-shot \u2014 `unreadCount()`/`query()` consult the\n * cache on every tool call, and any append by another session invalidates it.\n * On a mailbox holding a day of fleet traffic (~3 MB / ~2.8k lines) that turned\n * into the single largest allocation source in the whole TUI process: ~78% of\n * all bytes allocated while idle, which V8 then let pile up as garbage until a\n * major GC \u2014 read as \"RAM keeps growing and /clear doesn't help\".\n *\n * This module keeps enough state alongside the projections that an APPEND can\n * be folded in without touching the bytes that were already parsed:\n *\n * - `messages` \u2014 base messages in file order, v1 acks already folded\n * - `receiptsByMessage` \u2014 every v2 receipt, keyed by target message id\n * - `indexById` \u2014 message id \u2192 indices (plural: duplicate ids are\n * pathological but must fold exactly as a full parse\n * would \u2014 acks hit the last, receipts hit them all)\n * - `projections` \u2014 the materialized result, parallel to `messages`\n *\n * The fold is *exact*, not approximate: appended receipts are accumulated into\n * the full per-message list and the affected messages are re-materialized from\n * that complete list, so the output is byte-for-byte what `parseMailboxFile()`\n * would have produced over the whole file. `parseMailboxFile()` itself is now\n * implemented on top of this module, so there is one fold, not two.\n *\n * @module mailbox-parse-state\n */\n\nimport { LINE_SEPARATOR } from './mailbox-constants.js';\nimport {\n applyAckToMessage,\n isAckRecord,\n parseMailboxMessage,\n} from './mailbox-message-codec.js';\nimport { materializeMessage } from './mailbox-receipt-folding.js';\nimport type {\n AckRecord,\n MailboxMessage,\n MailboxMessageProjection,\n MailboxReceiptRecordV2,\n} from './mailbox-types.js';\nimport { isMailboxReceiptRecordV2 } from './mailbox-types.js';\n\nexport interface MailboxParseState {\n /** Base messages in file order, with v1 ack records already applied. */\n messages: MailboxMessage[];\n /** Materialized projections, index-parallel to {@link messages}. */\n projections: MailboxMessageProjection[];\n /** Message id \u2192 every index in {@link messages} carrying that id. */\n indexById: Map<string, number[]>;\n /** Message id \u2192 every v2 receipt targeting it, in file order. */\n receiptsByMessage: Map<string, MailboxReceiptRecordV2[]>;\n}\n\n/**\n * Parse the raw JSONL content of a mailbox file into MailboxMessageProjection[].\n *\n * This is the canonical read-path entry point: it parses each line once,\n * classifies v1 messages, v1 ack records, and v2 receipt records, then folds\n * them into a unified MailboxMessageProjection carrying per-actor state.\n *\n * Malformed lines are silently skipped (same tolerance as parseMailboxLines).\n *\n * Lives here rather than in `mailbox-receipt-folding.ts` so the whole-file and\n * incremental paths share one fold; the dependency stays one-directional\n * (parse-state \u2192 receipt-folding) instead of forming an import cycle.\n */\nexport function parseMailboxFile(raw: string): MailboxMessageProjection[] {\n return createMailboxParseState(raw).projections;\n}\n\n/** Build parse state from the complete raw contents of a mailbox file. */\nexport function createMailboxParseState(raw: string): MailboxParseState {\n const state: MailboxParseState = {\n messages: [],\n projections: [],\n indexById: new Map(),\n receiptsByMessage: new Map(),\n };\n ingestMailboxChunk(state, raw);\n return state;\n}\n\n/**\n * Fold an appended chunk of JSONL into existing parse state, in place.\n *\n * `chunk` must be a run of WHOLE lines starting exactly where the previously\n * ingested content ended \u2014 the caller is responsible for trimming a partially\n * written trailing line (see `MailboxMessageCache`). Malformed lines are\n * skipped with the same tolerance as a full parse.\n *\n * Ordering matches a full parse: within the chunk, messages are collected\n * first and ack records applied afterwards, so an ack may target a message\n * that appears later in the same chunk. Ack records whose target is in\n * neither the chunk nor the existing state are dropped, exactly as the\n * whole-file fold drops them.\n */\nexport function ingestMailboxChunk(state: MailboxParseState, chunk: string): void {\n const firstNewIndex = state.messages.length;\n const ackRecords: AckRecord[] = [];\n // Indices of PRE-EXISTING messages whose projection is now stale. Newly\n // appended messages are materialized unconditionally below, so they are\n // deliberately not tracked here.\n const staleExisting = new Set<number>();\n\n for (const line of chunk.split(LINE_SEPARATOR)) {\n if (line.trim().length === 0) continue;\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n continue; // skip malformed lines\n }\n\n if (isMailboxReceiptRecordV2(parsed)) {\n const list = state.receiptsByMessage.get(parsed.messageId);\n if (list) list.push(parsed);\n else state.receiptsByMessage.set(parsed.messageId, [parsed]);\n // A receipt re-folds EVERY message carrying that id, matching\n // `materializeMessages`, which looks receipts up per message.\n for (const index of state.indexById.get(parsed.messageId) ?? []) {\n if (index < firstNewIndex) staleExisting.add(index);\n }\n continue;\n }\n\n if (isAckRecord(parsed)) {\n ackRecords.push(parsed);\n continue;\n }\n\n let message: MailboxMessage;\n try {\n message = parseMailboxMessage(parsed);\n } catch {\n continue; // codec rejected the record \u2014 same tolerance as a full parse\n }\n const index = state.messages.length;\n state.messages.push(message);\n const indices = state.indexById.get(message.id);\n if (indices) indices.push(index);\n else state.indexById.set(message.id, [index]);\n }\n\n // v1 acks resolve against the last message carrying the id, mirroring the\n // whole-file fold's `new Map(messages.map(m => [m.id, m]))` (last wins).\n for (const ack of ackRecords) {\n const indices = state.indexById.get(ack.messageId);\n if (indices === undefined || indices.length === 0) continue;\n const index = indices[indices.length - 1] as number;\n applyAckToMessage(state.messages[index] as MailboxMessage, ack);\n if (index < firstNewIndex) staleExisting.add(index);\n }\n\n for (const index of staleExisting) {\n const message = state.messages[index] as MailboxMessage;\n state.projections[index] = materializeMessage(\n message,\n state.receiptsByMessage.get(message.id) ?? [],\n );\n }\n for (let index = firstNewIndex; index < state.messages.length; index++) {\n const message = state.messages[index] as MailboxMessage;\n state.projections.push(\n materializeMessage(message, state.receiptsByMessage.get(message.id) ?? []),\n );\n }\n}\n", "import type { RegisteredAgent, RegisteredClient } from './mailbox-types.js';\n\n/**\n * Minimal shape-check for a deserialized agent registry entry.\n *\n * Identity fields are the only hard requirement. Everything else is coerced\n * to a safe default so an unrecognised entry from another/newer process\n * survives a shared read-modify-write instead of being permanently evicted.\n */\nexport function parseAgentRegistryEntry(value: unknown): RegisteredAgent | null {\n if (typeof value !== 'object' || value === null) return null;\n const v = value as Record<string, unknown>;\n if (typeof v.agentId !== 'string') return null;\n if (typeof v.sessionId !== 'string') return null;\n const statuses = ['idle', 'busy', 'running', 'streaming', 'waiting_user', 'error'] as const;\n const status =\n typeof v.status === 'string' && (statuses as readonly string[]).includes(v.status)\n ? v.status\n : 'idle';\n return {\n ...v,\n agentId: v.agentId,\n sessionId: v.sessionId,\n name: typeof v.name === 'string' ? v.name : v.agentId,\n registeredAt: typeof v.registeredAt === 'string' ? v.registeredAt : new Date(0).toISOString(),\n lastSeenAt: typeof v.lastSeenAt === 'string' ? v.lastSeenAt : new Date(0).toISOString(),\n iterations: typeof v.iterations === 'number' && Number.isFinite(v.iterations) ? v.iterations : 0,\n toolCalls: typeof v.toolCalls === 'number' && Number.isFinite(v.toolCalls) ? v.toolCalls : 0,\n pid: typeof v.pid === 'number' && Number.isFinite(v.pid) ? v.pid : 0,\n status,\n } as unknown as RegisteredAgent;\n}\n\n/** Minimal shape-check for a deserialized client registry entry. */\nexport function parseClientRegistryEntry(value: unknown): RegisteredClient | null {\n if (typeof value !== 'object' || value === null) return null;\n const v = value as Record<string, unknown>;\n if (typeof v.clientId !== 'string') return null;\n if (typeof v.sessionId !== 'string') return null;\n const sources = ['repl', 'tui', 'webui', 'http'] as const;\n const source =\n typeof v.source === 'string' && (sources as readonly string[]).includes(v.source)\n ? v.source\n : 'http';\n return {\n ...v,\n clientId: v.clientId,\n sessionId: v.sessionId,\n name: typeof v.name === 'string' ? v.name : v.clientId,\n registeredAt: typeof v.registeredAt === 'string' ? v.registeredAt : new Date(0).toISOString(),\n lastSeenAt: typeof v.lastSeenAt === 'string' ? v.lastSeenAt : new Date(0).toISOString(),\n pid: typeof v.pid === 'number' && Number.isFinite(v.pid) ? v.pid : 0,\n source,\n } as unknown as RegisteredClient;\n}\n"],
5
- "mappings": "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",
3
+ "sources": ["../../src/coordination/mailbox-project-server.ts", "../../src/kernel/events.ts", "../../src/utils/perf-profile.ts", "../../src/coordination/mailbox-events.ts", "../../src/coordination/mailbox-project-server-endpoint.ts", "../../src/utils/socket-path.ts", "../../src/coordination/mailbox-project-server-protocol.ts", "../../src/coordination/sqlite-mailbox.ts", "../../src/coordination/mailbox-constants.ts", "../../src/coordination/global-mailbox-completion.ts", "../../src/coordination/mailbox-types.ts", "../../src/coordination/mailbox-receipt-folding.ts", "../../src/coordination/mailbox-retention-state.ts", "../../src/coordination/mailbox-status-mappers.ts", "../../src/coordination/mailbox-message-codec.ts", "../../src/coordination/sqlite-mailbox-compaction.ts", "../../src/coordination/mailbox-credential-store.ts", "../../src/coordination/sqlite-mailbox-rows.ts", "../../src/coordination/sqlite-mailbox-credentials.ts", "../../src/coordination/sqlite-mailbox-schema.ts", "../../src/utils/sqlite-warning.ts", "../../src/coordination/global-mailbox-paths.ts", "../../src/coordination/mailbox-parse-state.ts", "../../src/coordination/mailbox-registry-codec.ts"],
4
+ "sourcesContent": ["#!/usr/bin/env node\n/**\n * One detached mailbox owner per local WrongStack project state directory.\n *\n * Only this process opens the project SQLite database. Every CLI/TUI/WebUI/HQ\n * process talks to it through the deterministic local IPC endpoint.\n */\n\nimport * as fs from 'node:fs';\nimport * as fsPromises from 'node:fs/promises';\nimport * as net from 'node:net';\nimport * as path from 'node:path';\nimport { EventBus } from '../kernel/events.js';\nimport { useDaemonPerfDefaults } from '../utils/perf-profile.js';\nimport { MailboxEventEmitter } from './mailbox-events.js';\nimport {\n ensureMailboxProjectServerSocketDirectory,\n mailboxProjectServerEndpoint,\n mailboxProjectServerMetadataPath,\n} from './mailbox-project-server-endpoint.js';\nimport {\n encodeMailboxProjectServerMessage,\n isMailboxProjectServerClientMessage,\n MAILBOX_PROJECT_SERVER_MAX_FRAME_CHARS,\n MAILBOX_PROJECT_SERVER_PROTOCOL_VERSION,\n type MailboxProjectServerClientMessage,\n type MailboxProjectServerInfo,\n type MailboxProjectServerMessage,\n type MailboxServerOperationName,\n type MailboxServerOperations,\n} from './mailbox-project-server-protocol.js';\nimport { SQLITE_MAILBOX_FILE, SqliteMailbox } from './sqlite-mailbox.js';\n\nconst DEFAULT_IDLE_MS = 5 * 60_000;\nconst DEFAULT_CLIENT_LEASE_MS = 45_000;\n\n/**\n * Cap on outbound bytes queued for a single client before it is dropped.\n *\n * `socket.write()` returns `false` once its internal queue passes the stream's\n * high-water mark; that is the signal to stop producing. This server\n * broadcasts every `mailbox.*` event to every connected client, so ignoring\n * that signal meant one client that stopped reading \u2014 a suspended process, a\n * TUI stuck behind a modal, a debugger-paused peer \u2014 made the owner buffer\n * every subsequent broadcast for it, without limit. Nothing else here is big:\n * the SQLite file is single-digit MB, so an owner holding hundreds of MB is\n * this queue and nothing else.\n *\n * Dropping is the right response rather than throttling: these are\n * notifications, and SQLite remains the authority. A client that reconnects\n * re-queries current state, so it loses nothing but the events it was already\n * too far behind to have processed.\n */\nconst MAX_CLIENT_WRITE_BUFFER_BYTES = 8 * 1024 * 1024;\n\ninterface ClientState {\n socket: net.Socket;\n buffer: string;\n lastSeenAt: number;\n}\n\nfunction parseArgs(argv: string[]): { projectDir: string } {\n let projectDir: string | undefined;\n for (let index = 0; index < argv.length; index++) {\n if (argv[index] === '--project-dir') projectDir = argv[++index];\n }\n if (!projectDir) throw new Error('mailbox project server requires --project-dir');\n return { projectDir: path.resolve(projectDir) };\n}\n\n// Long-lived daemon: lean SQLite residency unless the operator says\n// otherwise. Must run before any store opens.\nuseDaemonPerfDefaults();\n\nconst { projectDir } = parseArgs(process.argv.slice(2));\nconst endpoint = mailboxProjectServerEndpoint(projectDir);\nconst metadataPath = mailboxProjectServerMetadataPath(projectDir);\nconst idleInput = Number(process.env['WRONGSTACK_MAILBOX_SERVER_IDLE_MS']);\nconst idleMs = Number.isFinite(idleInput) && idleInput >= 100 ? idleInput : DEFAULT_IDLE_MS;\nconst leaseInput = Number(process.env['WRONGSTACK_MAILBOX_SERVER_CLIENT_LEASE_MS']);\nconst clientLeaseMs =\n Number.isFinite(leaseInput) && leaseInput >= 100 ? leaseInput : DEFAULT_CLIENT_LEASE_MS;\nconst leaseSweepMs = Math.min(10_000, Math.max(100, Math.floor(clientLeaseMs / 3)));\nconst startedAt = new Date().toISOString();\nconst events = new EventBus();\nconst eventEmitter = new MailboxEventEmitter();\nlet mailbox: SqliteMailbox | undefined;\nconst clients = new Set<ClientState>();\nlet pendingRequests = 0;\nlet idleTimer: ReturnType<typeof setTimeout> | undefined;\nlet stopping = false;\nlet stopAutoCompact: (() => void) | undefined;\n\nconst serverInfo: MailboxProjectServerInfo = {\n protocolVersion: MAILBOX_PROJECT_SERVER_PROTOCOL_VERSION,\n pid: process.pid,\n projectDir,\n endpoint,\n startedAt,\n};\n\nfunction writeEncoded(state: ClientState, encoded: string): void {\n if (state.socket.destroyed) return;\n // A client that has stopped draining must not be allowed to grow the\n // owner's heap one broadcast at a time. `writableLength` is what is still\n // queued in this socket, so checking it before writing bounds the worst\n // case at roughly one message beyond the cap.\n if (state.socket.writableLength > MAX_CLIENT_WRITE_BUFFER_BYTES) {\n state.socket.destroy(new Error('Mailbox client fell too far behind on reads'));\n return;\n }\n state.socket.write(encoded);\n}\n\nfunction send(state: ClientState, message: MailboxProjectServerMessage): void {\n if (state.socket.destroyed) return;\n writeEncoded(state, encodeMailboxProjectServerMessage(message));\n}\n\n/**\n * Encode once, write to every client.\n *\n * Serializing inside the per-client loop meant the same payload was\n * stringified once per connected client. Mailbox snapshot events are tens of\n * KB, so a handful of attached surfaces (TUI, WebUI, HQ) turned every event\n * into a multiple of that in short-lived garbage \u2014 visible as a sawtooth of\n * hundreds of MB in a daemon whose database is single-digit MB.\n */\nfunction broadcast(message: MailboxProjectServerMessage): void {\n if (clients.size === 0) return;\n const encoded = encodeMailboxProjectServerMessage(message);\n for (const state of clients) writeEncoded(state, encoded);\n}\n\nevents.onAny((event, payload) => {\n if (event.startsWith('mailbox.')) broadcast({ type: 'event', event, payload });\n});\neventEmitter.subscribe((event) => broadcast({ type: 'mailbox-event', event }));\n\nfunction serverStatus(): MailboxServerOperations['ping']['result'] {\n const databasePath = mailbox?.databasePath ?? path.join(projectDir, SQLITE_MAILBOX_FILE);\n return {\n ...serverInfo,\n clients: clients.size,\n pendingRequests,\n messagePath: databasePath,\n databasePath,\n storageKind: 'sqlite',\n };\n}\n\nasync function dispatch(op: MailboxServerOperationName, rawArgs: unknown): Promise<unknown> {\n const activeMailbox = mailbox;\n if (activeMailbox === undefined) throw new Error('Mailbox SQLite owner is not initialized');\n switch (op) {\n case 'ping':\n return serverStatus();\n case 'send': {\n const args = rawArgs as MailboxServerOperations['send']['args'];\n return activeMailbox.send(args.input);\n }\n case 'sendRuntimeControl': {\n const args = rawArgs as MailboxServerOperations['sendRuntimeControl']['args'];\n return activeMailbox.sendRuntimeControl(args.input);\n }\n case 'query': {\n const args = rawArgs as MailboxServerOperations['query']['args'];\n return activeMailbox.query(args.query);\n }\n case 'ack': {\n const args = rawArgs as MailboxServerOperations['ack']['args'];\n return activeMailbox.ack(args.input);\n }\n case 'ackMany': {\n const args = rawArgs as MailboxServerOperations['ackMany']['args'];\n return activeMailbox.ackMany(args.input);\n }\n case 'unreadCount': {\n const args = rawArgs as MailboxServerOperations['unreadCount']['args'];\n return activeMailbox.unreadCount(args.forAgentId, args.sessionId);\n }\n case 'softDelete': {\n const args = rawArgs as MailboxServerOperations['softDelete']['args'];\n return activeMailbox.softDelete(args.mailId, args.by);\n }\n case 'restore': {\n const args = rawArgs as MailboxServerOperations['restore']['args'];\n return activeMailbox.restore(args.mailId);\n }\n case 'registerAgent': {\n const args = rawArgs as MailboxServerOperations['registerAgent']['args'];\n return activeMailbox.registerAgent(args.input);\n }\n case 'deregisterAgent': {\n const args = rawArgs as MailboxServerOperations['deregisterAgent']['args'];\n return activeMailbox.deregisterAgent(args.agentId);\n }\n case 'heartbeat': {\n const args = rawArgs as MailboxServerOperations['heartbeat']['args'];\n return activeMailbox.heartbeat(args.input);\n }\n case 'getAgentStatuses':\n return activeMailbox.getAgentStatuses();\n case 'getOnlineAgents':\n return activeMailbox.getOnlineAgents();\n case 'purgeAgents': {\n const args = rawArgs as MailboxServerOperations['purgeAgents']['args'];\n return activeMailbox.purgeAgents(args.maxAgeMs);\n }\n case 'registerClient': {\n const args = rawArgs as MailboxServerOperations['registerClient']['args'];\n return activeMailbox.registerClient(args.input);\n }\n case 'deregisterClient': {\n const args = rawArgs as MailboxServerOperations['deregisterClient']['args'];\n return activeMailbox.deregisterClient(args.clientId);\n }\n case 'clientHeartbeat': {\n const args = rawArgs as MailboxServerOperations['clientHeartbeat']['args'];\n return activeMailbox.clientHeartbeat(args.input);\n }\n case 'getClientStatuses':\n return activeMailbox.getClientStatuses();\n case 'purgeClients':\n return activeMailbox.purgeClients();\n case 'clearAll':\n return activeMailbox.clearAll();\n case 'purgeStale': {\n const args = rawArgs as MailboxServerOperations['purgeStale']['args'];\n return activeMailbox.purgeStale(args.options);\n }\n case 'autoCompact': {\n const args = rawArgs as MailboxServerOperations['autoCompact']['args'];\n return activeMailbox.autoCompact(args.options);\n }\n case 'credentialIssue': {\n const args = rawArgs as MailboxServerOperations['credentialIssue']['args'];\n return activeMailbox.credentialIssue(args.options);\n }\n case 'credentialVerify': {\n const args = rawArgs as MailboxServerOperations['credentialVerify']['args'];\n return activeMailbox.credentialVerify(args.credentialId, args.secret);\n }\n case 'credentialRevoke': {\n const args = rawArgs as MailboxServerOperations['credentialRevoke']['args'];\n return activeMailbox.credentialRevoke(args.credentialId, args.reason, args.by);\n }\n case 'credentialRotate': {\n const args = rawArgs as MailboxServerOperations['credentialRotate']['args'];\n return activeMailbox.credentialRotate(args.credentialId, args.options);\n }\n case 'credentialGet': {\n const args = rawArgs as MailboxServerOperations['credentialGet']['args'];\n return activeMailbox.credentialGet(args.credentialId);\n }\n case 'credentialList':\n return activeMailbox.credentialList();\n case 'credentialStatusCounts':\n return activeMailbox.credentialStatusCounts();\n }\n}\n\nfunction handleMessage(state: ClientState, message: MailboxProjectServerClientMessage): void {\n state.lastSeenAt = Date.now();\n if (message.type === 'heartbeat') return;\n if (message.type === 'shutdown') {\n send(state, {\n type: 'response',\n id: message.id,\n ok: true,\n result: { stopped: true, pid: process.pid, reason: message.reason },\n });\n setImmediate(() => void stop(message.reason ?? 'client-request'));\n return;\n }\n pendingRequests++;\n void dispatch(message.op, message.args)\n .then((result) => {\n // JSON.stringify omits `undefined` object properties. Keep successful\n // void operations structurally valid for the client runtime guard.\n send(state, { type: 'response', id: message.id, ok: true, result: result ?? null });\n })\n .catch((error) => {\n send(state, {\n type: 'response',\n id: message.id,\n ok: false,\n error: error instanceof Error ? error.message : String(error),\n errorName: error instanceof Error ? error.name : undefined,\n });\n })\n .finally(() => {\n pendingRequests = Math.max(0, pendingRequests - 1);\n // A client may disconnect while its last request is still settling.\n // The close handler cannot arm the idle timer while pendingRequests > 0,\n // so re-check after every request or an owner can remain alive forever.\n scheduleIdleStop();\n });\n}\n\nfunction onData(state: ClientState, chunk: string): void {\n state.lastSeenAt = Date.now();\n state.buffer += chunk;\n while (true) {\n const newline = state.buffer.indexOf('\\n');\n if (newline < 0) {\n if (state.buffer.length > MAILBOX_PROJECT_SERVER_MAX_FRAME_CHARS) {\n state.socket.destroy(new Error('Mailbox request frame exceeded maximum size'));\n }\n return;\n }\n if (newline > MAILBOX_PROJECT_SERVER_MAX_FRAME_CHARS) {\n state.socket.destroy(new Error('Mailbox request frame exceeded maximum size'));\n return;\n }\n const line = state.buffer.slice(0, newline);\n state.buffer = state.buffer.slice(newline + 1);\n if (!line) continue;\n let parsed: unknown;\n try {\n parsed = JSON.parse(line) as unknown;\n } catch {\n state.socket.destroy(new Error('Invalid mailbox project server request'));\n return;\n }\n if (!isMailboxProjectServerClientMessage(parsed)) {\n state.socket.destroy(new Error('Invalid mailbox project server request'));\n return;\n }\n handleMessage(state, parsed);\n }\n}\n\nfunction scheduleIdleStop(): void {\n if (stopping || clients.size > 0 || pendingRequests > 0) return;\n if (idleTimer) clearTimeout(idleTimer);\n idleTimer = setTimeout(() => void stop('idle-timeout'), idleMs);\n idleTimer.unref?.();\n}\n\nasync function writeMetadata(): Promise<void> {\n await fsPromises.mkdir(projectDir, { recursive: true });\n const temporary = `${metadataPath}.${process.pid}.tmp`;\n await fsPromises.writeFile(temporary, `${JSON.stringify(serverStatus(), null, 2)}\\n`, {\n encoding: 'utf8',\n mode: 0o600,\n });\n try {\n await fsPromises.rename(temporary, metadataPath);\n } catch {\n await fsPromises.rm(metadataPath, { force: true });\n await fsPromises.rename(temporary, metadataPath);\n }\n}\n\nasync function removeOwnedMetadata(): Promise<void> {\n try {\n const current = JSON.parse(await fsPromises.readFile(metadataPath, 'utf8')) as {\n pid?: number;\n };\n if (current.pid === process.pid) await fsPromises.rm(metadataPath, { force: true });\n } catch {\n // Missing or replaced metadata does not belong to this process.\n }\n}\n\nasync function stop(_reason: string): Promise<void> {\n if (stopping) return;\n stopping = true;\n if (idleTimer) clearTimeout(idleTimer);\n idleTimer = undefined;\n clearInterval(leaseSweep);\n stopAutoCompact?.();\n // Stop accepting new clients, then actively close the existing sockets.\n // Waiting for server.close() before closing them deadlocks explicit shutdown:\n // the requester keeps its IPC socket open while server.close() waits for\n // that same socket to disappear.\n const serverClosed = new Promise<void>((resolve) => server.close(() => resolve()));\n for (const state of clients) state.socket.end();\n const forceCloseTimer = setTimeout(() => {\n for (const state of clients) state.socket.destroy();\n }, 1_000);\n forceCloseTimer.unref?.();\n await serverClosed;\n clearTimeout(forceCloseTimer);\n for (const state of clients) state.socket.destroy();\n clients.clear();\n await mailbox?.close().catch(() => {});\n mailbox = undefined;\n await removeOwnedMetadata();\n if (process.platform !== 'win32') {\n await fsPromises.rm(endpoint, { force: true }).catch(() => {});\n }\n}\n\nensureMailboxProjectServerSocketDirectory(endpoint);\nconst server = net.createServer((socket) => {\n if (stopping) {\n socket.destroy();\n return;\n }\n if (idleTimer) clearTimeout(idleTimer);\n idleTimer = undefined;\n socket.setEncoding('utf8');\n const state: ClientState = { socket, buffer: '', lastSeenAt: Date.now() };\n clients.add(state);\n send(state, { type: 'hello', ...serverInfo });\n socket.on('data', (chunk: string) => onData(state, chunk));\n socket.on('error', () => {\n // Close handling below owns cleanup; socket errors must not crash the owner.\n });\n socket.on('close', () => {\n clients.delete(state);\n scheduleIdleStop();\n });\n});\n\nconst leaseSweep = setInterval(() => {\n const cutoff = Date.now() - clientLeaseMs;\n for (const state of clients) {\n if (state.lastSeenAt < cutoff) state.socket.destroy();\n }\n scheduleIdleStop();\n}, leaseSweepMs);\nleaseSweep.unref?.();\n\nlet probingExistingEndpoint = false;\nfunction listenForOwnership(): void {\n server.listen(endpoint);\n}\n\nserver.on('error', (error: NodeJS.ErrnoException) => {\n if (error.code === 'EADDRINUSE' && process.platform === 'win32') {\n process.exitCode = 0;\n return;\n }\n if (error.code === 'EADDRINUSE' && !probingExistingEndpoint) {\n probingExistingEndpoint = true;\n const probe = net.createConnection(endpoint);\n probe.once('connect', () => {\n probe.destroy();\n process.exitCode = 0;\n });\n probe.once('error', () => {\n probe.destroy();\n try {\n fs.rmSync(endpoint, { force: true });\n } catch {\n // Another contender may already have removed the stale socket.\n }\n probingExistingEndpoint = false;\n listenForOwnership();\n });\n return;\n }\n process.exitCode = 1;\n});\n\nserver.on('listening', () => {\n if (process.platform !== 'win32') {\n try {\n fs.chmodSync(endpoint, 0o600);\n } catch {\n // The containing 0700 directory still restricts access.\n }\n }\n try {\n // The IPC bind is the ownership election. Open SQLite only after winning\n // that election so losing detached contenders never become DB owners.\n mailbox = new SqliteMailbox(projectDir, events, eventEmitter);\n } catch {\n void stop('sqlite-initialization-failed').finally(() => {\n process.exitCode = 1;\n });\n return;\n }\n stopAutoCompact = mailbox.startAutoCompactTimer();\n void writeMetadata()\n .then(() => scheduleIdleStop())\n .catch(() => {\n void stop('metadata-write-failed').finally(() => {\n process.exitCode = 1;\n });\n });\n});\n\nlistenForOwnership();\n\nfor (const signal of ['SIGINT', 'SIGTERM'] as const) {\n process.once(signal, () => {\n void stop(signal).finally(() => {\n process.exitCode = 0;\n });\n });\n}\n", "/**\n * EventBus \u2014 observe-only typed event bus.\n * Subscribers cannot modify or cancel. Subscriber exceptions are caught.\n */\n\nimport type { AgentEventMap } from './events/agent-events.js';\nimport type { BrainEventMap } from './events/brain-events.js';\nimport type { FileEventMap } from './events/file-events.js';\nimport type { FleetEventMap } from './events/fleet-events.js';\nimport type { MemoryEventMap } from './events/memory-events.js';\nimport type { NetworkEventMap } from './events/network-events.js';\nimport type { ProcessEventMap } from './events/process-events.js';\nimport type { ProviderEventMap } from './events/provider-events.js';\nimport type { SddEventMap } from './events/sdd-events.js';\nimport type { SessionEventMap } from './events/session-events.js';\nimport type { ToolEventMap } from './events/tool-events.js';\nimport type { WorktreeEventMap } from './events/worktree-events.js';\n\n/** Safety cap on the wildcard listener array to prevent unbounded growth from\n * undisposed onPattern/onRegex/onAny callers. No legitimate usage needs more\n * than this \u2014 past the cap, new registrations are rejected with a warning. */\nconst MAX_WILDCARDS = 500;\n\n/**\n * Safety cap on total named listeners (all event names combined) to prevent\n * unbounded heap growth when callers forget to dispose their `.on()` registrations.\n * While each `.on()` returns a disposer, long-lived sessions with missing cleanup\n * could accumulate thousands of listener closures (each holding references to its\n * captured scope). Past this cap, new `.on()` registrations are rejected with a\n * logged warning and a no-op disposer is returned, making the leak visible without\n * crashing the process.\n */\nconst MAX_NAMED_LISTENERS = 2000;\n\n/** Distress signals the BrainMonitor watches. See `coordination/brain-monitor.ts`. */\nexport type BrainInterventionKind =\n | 'tool_failure_streak'\n | 'error_storm'\n | 'agent_stall'\n | 'file_churn';\n\n/**\n * Structural shape of a tracked agent as flushed by AgentStatusTracker. Kept\n * structural (not imported from the root `session-registry` module) so the\n * low-level kernel layer takes on no dependency on composition modules. The\n * real `AgentEntry` is assignable to this.\n */\nexport interface TrackedAgentSnapshot {\n id: string;\n name: string;\n startedAt?: string | undefined;\n status: string;\n currentTool?: string | undefined;\n currentTask?: string | undefined;\n taskId?: string | undefined;\n iterations: number;\n toolCalls: number;\n costUsd?: number | undefined;\n tokensIn?: number | undefined;\n tokensOut?: number | undefined;\n ctxPct?: number | undefined;\n model?: string | undefined;\n partialText?: string | undefined;\n todos?:\n | Array<{\n id: string;\n content: string;\n status: 'pending' | 'in_progress' | 'completed';\n activeForm?: string | undefined;\n }>\n | undefined;\n latestPrompt?: string | undefined;\n latestPromptAt?: number | undefined;\n lastActivityAt: string;\n}\n\nexport interface EventMap\n extends AgentEventMap,\n BrainEventMap,\n SessionEventMap,\n ProviderEventMap,\n ProcessEventMap,\n NetworkEventMap,\n FileEventMap,\n ToolEventMap,\n MemoryEventMap,\n SddEventMap,\n WorktreeEventMap,\n FleetEventMap {}\n\nexport type EventName = keyof EventMap;\nexport type Listener<E extends EventName> = (payload: EventMap[E]) => void;\n\nexport interface EventLogger {\n error(msg: string, ctx?: unknown): void | undefined;\n}\n\nexport class EventBus {\n protected readonly listeners = new Map<EventName, Set<Listener<EventName>>>();\n protected readonly wildcards: Array<{\n match: (event: string) => boolean;\n fn: (event: string, payload: unknown) => void;\n }> = [];\n protected logger?: EventLogger | undefined;\n /**\n * Dispatch arrays cached per event name, rebuilt lazily after a\n * subscription change. See {@link namedSnapshot}. Every mutation of\n * `listeners` must invalidate the matching entry, and every mutation of\n * `wildcards` must null `wildcardSnapshotCache` \u2014 a missed invalidation\n * means an emit dispatches to a stale listener set.\n */\n private readonly listenerSnapshots = new Map<EventName, readonly Listener<EventName>[]>();\n private wildcardSnapshotCache:\n | readonly {\n match: (event: string) => boolean;\n fn: (event: string, payload: unknown) => void;\n }[]\n | null = null;\n\n setLogger(logger: EventLogger): void {\n this.logger = logger;\n }\n\n on<E extends EventName>(event: E, fn: Listener<E>): () => void {\n // Prevent unbounded accumulation of named listeners when callers\n // forget to dispose their registrations. Past the cap, new `.on()`\n // calls are rejected with a warning and a no-op disposer \u2014 the\n // process keeps running and the developer sees the symptom.\n if (this.listenerCount() >= MAX_NAMED_LISTENERS) {\n this.logger?.error(\n `EventBus named listener limit (~${MAX_NAMED_LISTENERS}) reached \u2014 rejecting on(\"${event}\"). ` +\n 'Callers must dispose their named listeners to prevent unbounded memory growth.',\n );\n return () => {};\n }\n let set = this.listeners.get(event);\n if (!set) {\n set = new Set();\n this.listeners.set(event, set);\n }\n set.add(fn as Listener<EventName>);\n this.listenerSnapshots.delete(event);\n return () => this.off(event, fn);\n }\n\n off<E extends EventName>(event: E, fn: Listener<E>): void {\n const set = this.listeners.get(event);\n if (!set) return;\n set.delete(fn as Listener<EventName>);\n this.listenerSnapshots.delete(event);\n // Prune the now-empty Set so the map doesn't accumulate dead entries that\n // listenerCount() and iteration would otherwise walk. Safe during an\n // in-flight emit() because emit snapshots the Set before iterating, so it\n // never observes the live Set being deleted.\n if (set.size === 0) this.listeners.delete(event);\n }\n\n once<E extends EventName>(event: E, fn: Listener<E>): () => void {\n const wrapper: Listener<E> = (payload) => {\n this.off(event, wrapper as Listener<EventName>);\n (fn as Listener<E>)(payload);\n };\n this.on(event, wrapper as Listener<E>);\n return () => {\n this.off(event, wrapper as Listener<EventName>);\n };\n }\n\n /**\n * Subscribe to all events, regardless of name. Short-hand for\n * `onPattern('*')`. Use for logging, debugging, or forwarding every\n * event to another bus (as FleetBus does).\n *\n * Returns an unsubscribe function.\n */\n onAny(fn: (event: string, payload: unknown) => void): () => void {\n return this.onPattern('*', fn);\n }\n\n /**\n * Subscribe to all events whose name matches a glob-style prefix.\n * `'tool.*'` matches `tool.started`, `tool.executed`, `tool.progress`, etc.\n * `'*'` matches every event.\n *\n * The handler receives `(eventName, payload)` with the event name as a\n * string and the payload as `unknown`. Use for logging, debugging, or\n * metrics collection across a family of events.\n *\n * Returns an unsubscribe function.\n */\n onPattern(pattern: string, fn: (event: string, payload: unknown) => void): () => void {\n if (this.wildcards.length >= MAX_WILDCARDS) {\n this.logger?.error(\n `EventBus wildcard limit (${MAX_WILDCARDS}) reached \u2014 rejecting onPattern(\"${pattern}\"). ` +\n 'Callers must dispose their wildcard listeners to prevent unbounded growth.',\n );\n return () => {};\n }\n const match = makePatternMatcher(pattern);\n const entry = { match, fn };\n this.wildcards.push(entry);\n this.wildcardSnapshotCache = null;\n return () => {\n const idx = this.wildcards.indexOf(entry);\n if (idx >= 0) {\n this.wildcards.splice(idx, 1);\n this.wildcardSnapshotCache = null;\n }\n };\n }\n\n /**\n * Subscribe to all events whose name matches a RegExp.\n * More flexible than `onPattern` \u2014 use when you need regex features\n * (alternation, character classes, capture groups).\n *\n * Returns an unsubscribe function.\n */\n onRegex(regex: RegExp, fn: (event: string, payload: unknown) => void): () => void {\n if (this.wildcards.length >= MAX_WILDCARDS) {\n this.logger?.error(\n `EventBus wildcard limit (${MAX_WILDCARDS}) reached \u2014 rejecting onRegex(${regex}). ` +\n 'Callers must dispose their wildcard listeners to prevent unbounded growth.',\n );\n return () => {};\n }\n const entry = { match: (e: string) => regex.test(e), fn };\n this.wildcards.push(entry);\n this.wildcardSnapshotCache = null;\n return () => {\n const idx = this.wildcards.indexOf(entry);\n if (idx >= 0) {\n this.wildcards.splice(idx, 1);\n this.wildcardSnapshotCache = null;\n }\n };\n }\n\n emit<E extends EventName>(event: E, payload: EventMap[E]): void {\n const snapshot = this.namedSnapshot(event);\n if (snapshot !== undefined) {\n for (const fn of snapshot) {\n try {\n (fn as Listener<E>)(payload);\n } catch (err) {\n this.logger?.error(`EventBus listener for \"${event}\" threw`, err);\n }\n }\n }\n if (this.wildcards.length > 0) {\n const name = event as string;\n for (const { match, fn } of this.wildcardSnapshot()) {\n if (!match(name)) continue;\n try {\n fn(name, payload);\n } catch (err) {\n this.logger?.error(`EventBus wildcard listener for \"${name}\" threw`, err);\n }\n }\n }\n }\n\n /**\n * Dispatch array for one event name, or `undefined` when nothing is\n * subscribed.\n *\n * Dispatch iterates a stable array rather than the live Set so a listener\n * that subscribes or unsubscribes mid-emit cannot change what this round\n * delivers: an addition fires from the next emit, a removal may still fire\n * this round. That is the contract callers rely on, and it is unchanged.\n *\n * What changed is who pays for it. Building the array per emit did O(number\n * of listeners) copying on every event, including `tool.progress` and\n * streaming deltas \u2014 the highest-frequency paths in the process. The array\n * is now cached and rebuilt only when the subscription set actually changes,\n * which is wiring time and essentially never during a run. Measured at 2M\n * emits with 12 named + 6 wildcard listeners: 207 ms \u2192 141 ms.\n *\n * This is a throughput win, not a footprint one: the per-emit arrays died in\n * the nursery and never showed up as retained heap (measured heap growth was\n * the same either way). Do not cite this as a memory fix.\n *\n * A mutation during dispatch invalidates the cache for the *next* emit while\n * the in-flight loop keeps walking the array it started with \u2014 which is\n * exactly the snapshot semantics described above.\n */\n private namedSnapshot(event: EventName): readonly Listener<EventName>[] | undefined {\n const cached = this.listenerSnapshots.get(event);\n if (cached !== undefined) return cached;\n const set = this.listeners.get(event);\n if (!set || set.size === 0) return undefined;\n const snapshot = [...set];\n this.listenerSnapshots.set(event, snapshot);\n return snapshot;\n }\n\n /** Wildcard counterpart to {@link namedSnapshot}; same caching rationale. */\n private wildcardSnapshot(): readonly {\n match: (event: string) => boolean;\n fn: (event: string, payload: unknown) => void;\n }[] {\n this.wildcardSnapshotCache ??= this.wildcards.slice();\n return this.wildcardSnapshotCache;\n }\n\n /**\n * Emit a plugin-defined event that is intentionally outside EventMap.\n * Custom events are delivered to wildcard/pattern listeners only; typed\n * listeners remain reserved for core EventMap keys.\n */\n emitCustom(event: string, payload: unknown): void {\n if (this.wildcards.length === 0) return;\n for (const { match, fn } of this.wildcardSnapshot()) {\n if (!match(event)) continue;\n try {\n fn(event, payload);\n } catch (err) {\n this.logger?.error(`EventBus wildcard listener for \"${event}\" threw`, err);\n }\n }\n }\n\n clear(): void {\n this.listeners.clear();\n this.wildcards.length = 0;\n this.listenerSnapshots.clear();\n this.wildcardSnapshotCache = null;\n }\n\n /**\n * V2-D: introspection helper. Pass an `event` to count handlers for a\n * single key, or omit to get the total across every event. Used by the\n * leak-detection smoke test to flag handler accumulation across runs.\n * Does NOT include wildcard listeners.\n */\n listenerCount(event?: EventName): number {\n if (event !== undefined) return this.listeners.get(event)?.size ?? 0;\n let total = 0;\n for (const set of this.listeners.values()) total += set.size;\n return total;\n }\n\n /**\n * Number of wildcard listeners currently registered.\n */\n wildcardCount(): number {\n return this.wildcards.length;\n }\n\n /**\n * True if anything would receive an emit for `event` \u2014 a named listener\n * OR a wildcard/regex pattern that matches the event name. Unlike\n * `listenerCount`, this DOES account for wildcards, so callers that gate\n * behavior on \"is anyone listening?\" (e.g. SubagentBudget deciding whether\n * to negotiate a soft limit vs hard-stop) don't misfire when the only\n * subscriber is a pattern listener like the FleetBus's `onPattern('*')`.\n */\n hasListenerFor(event: string): boolean {\n if ((this.listeners.get(event as EventName)?.size ?? 0) > 0) return true;\n return this.wildcards.some((w) => w.match(event));\n }\n}\n\n// \u2500\u2500 Scoped EventBus \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * A decorator over `EventBus` that records every listener registration\n * (`.on`, `.once`, `.onPattern`, `.onRegex`) so that `teardown()` can\n * remove all of them at once \u2014 preventing the memory leaks that occur\n * when dynamic plugins or long-lived TUI/WebUI interfaces forget to\n * call `.off()` during session termination.\n *\n * Usage:\n * ```ts\n * const bus = new ScopedEventBus();\n * bus.on('tool.executed', handler1); // tracked\n * bus.on('provider.response', handler2); // tracked\n * bus.onPattern('subagent.*', handler3); // tracked\n * // ... later, when the plugin or session is torn down:\n * bus.teardown(); // removes all three listeners\n * ```\n *\n * Also implements `Disposable` (via `[Symbol.dispose]`) for use with\n * the `using` keyword in Node \u2265 22, or can be used manually with\n * `bus.teardown()`.\n */\nexport class ScopedEventBus extends EventBus {\n // Track registrations by a unique counter key so that EventBus.once()'s\n // internal listener-removal doesn't affect our tracking (once removes the\n // fn from EventBus but we still need to call our unsub during teardown).\n private readonly registrations = new Map<number, () => void>();\n private nextKey = 0;\n\n /**\n * Identical to `EventBus.on` but the listener is tracked so that\n * `teardown()` will remove it automatically.\n */\n override on<E extends EventName>(event: E, fn: Listener<E>): () => void {\n const key = this.nextKey++;\n const unsub = super.on(event, fn);\n this.registrations.set(key, unsub);\n return () => {\n this.registrations.delete(key);\n unsub();\n };\n }\n\n /**\n * Identical to `EventBus.once` but the listener is tracked so that\n * `teardown()` will remove it automatically.\n *\n * Uses EventBus's public API directly to avoid triggering our own `on()`\n * override (which would consume a key slot for the wrapper, then orphan\n * our registration entry under a different key).\n *\n * When the wrapper fires, it cleans up BOTH the underlying EventBus\n * listener AND the tracking entry \u2014 so `scopedListenerCount` returns to\n * its pre-`once()` value without requiring the caller to invoke the\n * returned unsubscribe. The returned `unsub` is still safe to call\n * after auto-removal (its delete is a no-op and its off() finds\n * nothing to remove).\n */\n override once<E extends EventName>(event: E, fn: Listener<E>): () => void {\n const key = this.nextKey++;\n const wrapper: Listener<E> = (payload) => {\n // Bypass ScopedEventBus.on() \u2014 go straight to EventBus.off() so we\n // don't recurse and don't consume another key.\n EventBus.prototype.off.call(this, event, wrapper as Listener<EventName>);\n // Drop the tracking entry so scopedListenerCount is honest. Done\n // before calling `fn` so a handler that calls scopedListenerCount\n // mid-fire sees the post-removal state.\n this.registrations.delete(key);\n (fn as Listener<E>)(payload);\n };\n // Use the EventBus prototype directly to register without triggering\n // ScopedEventBus.on() which would consume a second key.\n EventBus.prototype.on.call(this, event, wrapper as Listener<EventName>);\n const unsub = () => {\n this.registrations.delete(key);\n EventBus.prototype.off.call(this, event, wrapper as Listener<EventName>);\n };\n this.registrations.set(key, unsub);\n return unsub;\n }\n\n /**\n * Subscribe to all events. Alias for `onPattern('*')` \u2014 the listener is\n * tracked so that `teardown()` will remove it automatically.\n */\n override onAny(fn: (event: string, payload: unknown) => void): () => void {\n if (this.wildcards.length >= MAX_WILDCARDS) {\n this.logger?.error(\n `EventBus wildcard limit (${MAX_WILDCARDS}) reached \u2014 rejecting onAny(). ` +\n 'Callers must dispose their wildcard listeners to prevent unbounded growth.',\n );\n return () => {};\n }\n const key = this.nextKey++;\n // Call EventBus.onPattern directly so the wrapper-consumption in\n // ScopedEventBus.on() doesn't re-enter and create a second registration slot.\n const unsub = EventBus.prototype.onPattern.call(this, '*', fn);\n this.registrations.set(key, unsub);\n return () => {\n this.registrations.delete(key);\n unsub();\n };\n }\n\n /**\n * Identical to `EventBus.onPattern` but the listener is tracked so that\n * `teardown()` will remove it automatically.\n */\n override onPattern(pattern: string, fn: (event: string, payload: unknown) => void): () => void {\n // Pre-check the cap before delegating to EventBus.onPattern so we never\n // store a no-op disposer in our registrations map, which would inflate\n // scopedListenerCount metrics without providing any cleanup.\n if (this.wildcards.length >= MAX_WILDCARDS) {\n this.logger?.error(\n `EventBus wildcard limit (${MAX_WILDCARDS}) reached \u2014 rejecting onPattern(\"${pattern}\"). ` +\n 'Callers must dispose their wildcard listeners to prevent unbounded growth.',\n );\n return () => {};\n }\n const key = this.nextKey++;\n const unsub = super.onPattern(pattern, fn);\n this.registrations.set(key, unsub);\n return () => {\n this.registrations.delete(key);\n unsub();\n };\n }\n\n /**\n * Identical to `EventBus.onRegex` but the listener is tracked so that\n * `teardown()` will remove it automatically.\n */\n override onRegex(regex: RegExp, fn: (event: string, payload: unknown) => void): () => void {\n if (this.wildcards.length >= MAX_WILDCARDS) {\n this.logger?.error(\n `EventBus wildcard limit (${MAX_WILDCARDS}) reached \u2014 rejecting onRegex(${regex}). ` +\n 'Callers must dispose their wildcard listeners to prevent unbounded growth.',\n );\n return () => {};\n }\n const key = this.nextKey++;\n const unsub = super.onRegex(regex, fn);\n this.registrations.set(key, unsub);\n return () => {\n this.registrations.delete(key);\n unsub();\n };\n }\n\n /**\n * Remove every listener that was registered through this scoped bus.\n * Idempotent \u2014 calling it multiple times is safe.\n *\n * Also available as `[Symbol.dispose]` for explicit resource management:\n * ```ts\n * using scope = new ScopedEventBus();\n * scope.on('tool.executed', handler);\n * // automatically teardown()'d when scope exits\n * ```\n */\n teardown(): void {\n for (const unsub of this.registrations.values()) {\n try {\n unsub();\n } catch {\n /* ignore \u2014 best effort */\n }\n }\n this.registrations.clear();\n this.clear();\n }\n\n /** Alias for `teardown()` \u2014 enables `using new ScopedEventBus()` in Node \u2265 22. */\n [Symbol.dispose](): void {\n this.teardown();\n }\n\n /** Number of tracked registrations. */\n get scopedListenerCount(): number {\n return this.registrations.size;\n }\n}\n\n/**\n * Reused matcher for the `'*'` wildcard \u2014 equivalent to `() => true`\n * but allocated once at module load rather than on every `onPattern('*')`\n * or `onAny()` call. The wildcard array can grow to hundreds of entries\n * during long-lived sessions, so caching the function avoids GC pressure.\n */\nconst MATCH_ALL: (event: string) => boolean = () => true;\n\n/**\n * Convert a glob-style pattern to a matcher function.\n * Only supports `*` at the end of a prefix \u2014 `'tool.*'` becomes\n * \"starts with tool.\". `'*'` matches everything.\n */\nfunction makePatternMatcher(pattern: string): (event: string) => boolean {\n if (pattern === '*') return MATCH_ALL;\n if (pattern.endsWith('.*')) {\n const prefix = pattern.slice(0, -2);\n return (e: string) => e.startsWith(`${prefix}.`);\n }\n // Exact match fallback\n return (e: string) => e === pattern;\n}\n", "/**\n * Process-wide performance profile.\n *\n * `WRONGSTACK_PERF_PROFILE` (alias `WSTACK_PERF_PROFILE`):\n * - `balanced` (default) \u2014 current throughput-oriented defaults\n * - `frugal` / `cimri` \u2014 lower CPU concurrency, leaner SQLite caches,\n * coarser UI stream paint. Correctness and APIs unchanged.\n */\n\nexport type PerfProfile = 'balanced' | 'frugal';\n\n/**\n * Long-lived IPC daemons default to `frugal`.\n *\n * The SQLite pragmas below are per *connection*, and a daemon holds its\n * connections for its whole lifetime \u2014 the codebase-index daemon measured\n * 336MB RSS, essentially all of it the 128MiB page cache plus 512MiB mmap\n * reservation, while sitting idle. A foreground host pays that cost briefly;\n * a daemon pays it for hours. An explicit `WRONGSTACK_PERF_PROFILE` from the\n * operator still wins in both directions.\n */\nlet daemonDefaults = false;\n\n/** Call once from a daemon entry point, before opening any store. */\nexport function useDaemonPerfDefaults(): void {\n daemonDefaults = true;\n}\n\n/** Resolve the active profile from the environment (evaluated each call). */\nexport function getPerfProfile(): PerfProfile {\n const explicit = process.env.WRONGSTACK_PERF_PROFILE ?? process.env.WSTACK_PERF_PROFILE;\n if (explicit === undefined || explicit.trim() === '') {\n return daemonDefaults ? 'frugal' : 'balanced';\n }\n const raw = explicit.trim().toLowerCase();\n if (raw === 'frugal' || raw === 'cimri' || raw === 'low' || raw === 'eco') {\n return 'frugal';\n }\n return 'balanced';\n}\n\nexport function isFrugalPerf(): boolean {\n return getPerfProfile() === 'frugal';\n}\n\n/** Parallel file-parse batch size for the codebase indexer. */\nexport function indexParallelBatchSize(availableCores: number): number {\n const cores = Math.max(1, Math.floor(availableCores) || 1);\n if (isFrugalPerf()) {\n // Serial-ish: at most 4 files concurrent, never more than core count.\n return Math.min(4, cores);\n }\n // Historical default: cores\u00D74, hard-capped at 40.\n return Math.min(cores * 4, 40);\n}\n\n/**\n * SQLite page-cache / mmap sizes in KiB (negative PRAGMA = KiB units for cache).\n * Frugal keeps correctness; just spends less RSS.\n */\nexport function sqliteCachePragmas(): { cacheSizeKiB: number; mmapBytes: number } {\n if (isFrugalPerf()) {\n return { cacheSizeKiB: 16_384, mmapBytes: 64 * 1024 * 1024 }; // 16 MiB / 64 MiB\n }\n return { cacheSizeKiB: 131_072, mmapBytes: 512 * 1024 * 1024 }; // 128 MiB / 512 MiB\n}\n\n/** sage store defaults (slightly smaller than index). */\nexport function SageCachePragmas(): { cacheSizeKiB: number; mmapBytes: number } {\n if (isFrugalPerf()) {\n return { cacheSizeKiB: 8_192, mmapBytes: 32 * 1024 * 1024 }; // 8 MiB / 32 MiB\n }\n return { cacheSizeKiB: 65_536, mmapBytes: 256 * 1024 * 1024 }; // 64 MiB / 256 MiB\n}\n\n/**\n * TUI stream paint interval. Higher = fewer React dispatches (less CPU/heap\n * churn). Balanced keeps the historical ~10fps; frugal ~6\u20137fps.\n */\nexport function tuiStreamFlushMs(): number {\n return isFrugalPerf() ? 150 : 100;\n}\n", "/**\n * MailboxEventEmitter \u2014 minimal pub/sub for real-time push to SSE clients.\n *\n * The HTTP bridge uses this to push `send`/`ack`/`delete` events to\n * connected SSE clients without requiring them to poll. Each event is a\n * shallow copy of the relevant data (message id, action, timestamp) \u2014\n * never the full mailbox state.\n *\n * The emitter is intentionally simple: a Set of listeners, add/remove,\n * and emit. No buffering, no replay \u2014 if a client connects after a send,\n * it won't receive past events (it should query first to catch up).\n *\n * @module mailbox-events\n */\n\nimport type { MailboxAudience } from './mailbox-types.js';\n\nexport type MailboxEventType = 'message.sent' | 'message.acked' | 'message.deleted' | 'message.restored';\n\nexport interface MailboxEvent {\n type: MailboxEventType;\n messageId: string;\n from?: string | undefined;\n to?: string | undefined;\n audience?: MailboxAudience | undefined;\n timestamp: string;\n}\n\nexport type MailboxEventListener = (event: MailboxEvent) => void;\n\nexport class MailboxEventEmitter {\n private listeners = new Set<MailboxEventListener>();\n\n subscribe(fn: MailboxEventListener): () => void {\n this.listeners.add(fn);\n return () => { this.listeners.delete(fn); };\n }\n\n emit(event: MailboxEvent): void {\n const snapshot = [...this.listeners];\n for (const fn of snapshot) {\n try { fn(event); } catch { /* listener must not crash the emitter */ }\n }\n }\n\n /** Number of active subscribers (for observability / metrics). */\n get subscriberCount(): number {\n return this.listeners.size;\n }\n\n clear(): void {\n this.listeners.clear();\n }\n}\n", "import { createHash } from 'node:crypto';\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { assertUnixSocketPathWithinLimit } from '../utils/socket-path.js';\nimport { MAILBOX_PROJECT_SERVER_PROTOCOL_VERSION } from './mailbox-project-server-protocol.js';\n\nexport const MAILBOX_PROJECT_SERVER_METADATA_FILE = '.mailbox-server.json';\n\nfunction normalizeLocalPath(value: string): string {\n const resolved = path.resolve(value);\n return process.platform === 'win32' ? resolved.toLowerCase() : resolved;\n}\n\nexport function mailboxProjectServerKey(projectDir: string): string {\n return createHash('sha256')\n .update(normalizeLocalPath(projectDir))\n .digest('hex')\n .slice(0, 24);\n}\n\n/**\n * Deterministic per-project mailbox IPC endpoint.\n *\n * The Unix subdirectory is the short `wsmb-v<V>/` (was\n * `wrongstack-mailbox-v<V>/`, which left only 3 bytes of macOS `sun_path`\n * headroom under the ~48-byte per-user TMPDIR \u2014 see the codebase-index macOS\n * incident and `@wrongstack/persistence` socket-path helpers). ~86 bytes\n * worst-case macOS now.\n *\n * Migration: the protocol version stays embedded in the path, so this rename\n * behaves exactly like a protocol bump \u2014 old daemons keep listening on the old\n * `wrongstack-mailbox-v<V>/` path, are never contacted again, and exit on\n * their idle timeout. No coexistence window: a client build always talks only\n * to the endpoint scheme it derives. Bump\n * `MAILBOX_PROJECT_SERVER_PROTOCOL_VERSION` for wire changes as before; the\n * prefix itself must not grow without re-checking the byte budget.\n * The Windows pipe name keeps the long prefix \u2014 named pipes have no\n * `sun_path` limit.\n */\nexport function mailboxProjectServerEndpoint(projectDir: string): string {\n const key = mailboxProjectServerKey(projectDir);\n if (process.platform === 'win32') {\n return `\\\\\\\\.\\\\pipe\\\\wrongstack-mailbox-v${MAILBOX_PROJECT_SERVER_PROTOCOL_VERSION}-${key}`;\n }\n return path.join(\n os.tmpdir(),\n `wsmb-v${MAILBOX_PROJECT_SERVER_PROTOCOL_VERSION}`,\n `${key}.sock`,\n );\n}\n\nexport function mailboxProjectServerMetadataPath(projectDir: string): string {\n return path.join(path.resolve(projectDir), MAILBOX_PROJECT_SERVER_METADATA_FILE);\n}\n\nexport function ensureMailboxProjectServerSocketDirectory(endpoint: string): void {\n if (process.platform !== 'win32') {\n // ~86 bytes under a canonical macOS TMPDIR since the wsmb-v1/ rename.\n // Assert so growth fails loudly instead of as a silent bind error in the\n // detached daemon (see the codebase-index macOS incident).\n assertUnixSocketPathWithinLimit(endpoint, 'mailbox');\n fs.mkdirSync(path.dirname(endpoint), { recursive: true, mode: 0o700 });\n }\n}\n", "/**\n * Re-export of the Unix socket path-length helpers from\n * `@wrongstack/persistence` so packages that depend on core (tools, sage)\n * share one implementation with packages that depend on persistence directly\n * (kanban). See `packages/persistence/src/socket-path.ts` for rationale.\n */\nexport {\n assertUnixSocketPathWithinLimit,\n checkUnixSocketPath,\n type UnixSocketPathCheck,\n unixSocketPathLimit,\n} from '@wrongstack/persistence';\n", "import type { MailboxEvent } from './mailbox-events.js';\nimport type {\n CredentialValidation,\n IssueCredentialOptions,\n MailboxCredential,\n} from './mailbox-credential-store.js';\nimport type {\n AgentHeartbeatInput,\n AgentRegistrationInput,\n AutoCompactOptions,\n AutoCompactResult,\n ClientHeartbeatInput,\n ClientRegistrationInput,\n ClientStatus,\n MailboxAckBatchInput,\n MailboxAckInput,\n MailboxAgentStatus,\n MailboxMessage,\n MailboxQuery,\n MailboxSendInput,\n PurgeOptions,\n PurgeResult,\n} from './mailbox-types.js';\n\nexport const MAILBOX_PROJECT_SERVER_PROTOCOL_VERSION = 3;\nexport const MAILBOX_PROJECT_SERVER_MAX_FRAME_CHARS = 16 * 1024 * 1024;\n\nexport interface MailboxProjectServerInfo {\n protocolVersion: number;\n pid: number;\n projectDir: string;\n endpoint: string;\n startedAt: string;\n}\n\nexport interface MailboxProjectServerStatus extends MailboxProjectServerInfo {\n clients: number;\n pendingRequests: number;\n /** Compatibility alias; points to databasePath for protocol v2+. */\n messagePath: string;\n databasePath: string;\n storageKind: 'sqlite' | 'legacy-test-adapter';\n}\n\nexport interface MailboxServerOperations {\n ping: { args: Record<string, never>; result: MailboxProjectServerStatus };\n send: { args: { input: MailboxSendInput }; result: MailboxMessage };\n sendRuntimeControl: {\n args: { input: Omit<MailboxSendInput, 'type'> & { type?: 'control' } };\n result: MailboxMessage;\n };\n query: { args: { query: MailboxQuery }; result: MailboxMessage[] };\n ack: { args: { input: MailboxAckInput }; result: MailboxMessage | null };\n ackMany: { args: { input: MailboxAckBatchInput }; result: MailboxMessage[] };\n unreadCount: {\n args: { forAgentId: string; sessionId?: string | undefined };\n result: number;\n };\n softDelete: {\n args: { mailId: string; by: string };\n result: MailboxMessage | null;\n };\n restore: { args: { mailId: string }; result: MailboxMessage | null };\n registerAgent: { args: { input: AgentRegistrationInput }; result: void };\n deregisterAgent: { args: { agentId: string }; result: void };\n heartbeat: { args: { input: AgentHeartbeatInput }; result: void };\n getAgentStatuses: { args: Record<string, never>; result: MailboxAgentStatus[] };\n getOnlineAgents: { args: Record<string, never>; result: MailboxAgentStatus[] };\n purgeAgents: { args: { maxAgeMs?: number | undefined }; result: number };\n registerClient: { args: { input: ClientRegistrationInput }; result: void };\n deregisterClient: { args: { clientId: string }; result: void };\n clientHeartbeat: { args: { input: ClientHeartbeatInput }; result: void };\n getClientStatuses: { args: Record<string, never>; result: ClientStatus[] };\n purgeClients: { args: Record<string, never>; result: number };\n clearAll: { args: Record<string, never>; result: void };\n purgeStale: { args: { options?: PurgeOptions | undefined }; result: PurgeResult };\n autoCompact: {\n args: { options?: AutoCompactOptions | undefined };\n result: AutoCompactResult;\n };\n credentialIssue: {\n args: { options: IssueCredentialOptions };\n result: { credential: MailboxCredential; secret: string };\n };\n credentialVerify: {\n args: { credentialId: string; secret: string };\n result: CredentialValidation;\n };\n credentialRevoke: {\n args: { credentialId: string; reason?: string | undefined; by?: string | undefined };\n result: boolean;\n };\n credentialRotate: {\n args: { credentialId: string; options?: Partial<IssueCredentialOptions> | undefined };\n result: { credential: MailboxCredential; secret: string } | null;\n };\n credentialGet: {\n args: { credentialId: string };\n result: MailboxCredential | null;\n };\n credentialList: {\n args: Record<string, never>;\n result: MailboxCredential[];\n };\n credentialStatusCounts: {\n args: Record<string, never>;\n result: Record<string, number>;\n };\n}\n\nexport type MailboxServerOperationName = keyof MailboxServerOperations;\n\nexport type MailboxProjectServerClientMessage =\n | {\n type: 'request';\n id: number;\n op: MailboxServerOperationName;\n args: unknown;\n }\n | { type: 'heartbeat' }\n | { type: 'shutdown'; id: number; reason?: string | undefined };\n\nconst MAILBOX_SERVER_OPERATION_NAMES: Readonly<Record<MailboxServerOperationName, true>> = {\n ping: true,\n send: true,\n sendRuntimeControl: true,\n query: true,\n ack: true,\n ackMany: true,\n unreadCount: true,\n softDelete: true,\n restore: true,\n registerAgent: true,\n deregisterAgent: true,\n heartbeat: true,\n getAgentStatuses: true,\n getOnlineAgents: true,\n purgeAgents: true,\n registerClient: true,\n deregisterClient: true,\n clientHeartbeat: true,\n getClientStatuses: true,\n purgeClients: true,\n clearAll: true,\n purgeStale: true,\n autoCompact: true,\n credentialIssue: true,\n credentialVerify: true,\n credentialRevoke: true,\n credentialRotate: true,\n credentialGet: true,\n credentialList: true,\n credentialStatusCounts: true,\n};\n\nfunction isRequestId(value: unknown): value is number {\n return Number.isSafeInteger(value) && (value as number) >= 0;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction hasString(record: Record<string, unknown>, key: string): boolean {\n return typeof record[key] === 'string' && (record[key] as string).length > 0;\n}\n\nfunction hasRecord(record: Record<string, unknown>, key: string): boolean {\n return isRecord(record[key]);\n}\n\nfunction isMailboxServerOperationArgs(\n op: MailboxServerOperationName,\n value: unknown,\n): boolean {\n if (!isRecord(value)) return false;\n switch (op) {\n case 'ping':\n case 'getAgentStatuses':\n case 'getOnlineAgents':\n case 'getClientStatuses':\n case 'purgeClients':\n case 'clearAll':\n case 'credentialList':\n case 'credentialStatusCounts':\n return true;\n case 'send':\n case 'sendRuntimeControl':\n case 'ack':\n case 'ackMany':\n case 'registerAgent':\n case 'heartbeat':\n case 'registerClient':\n case 'clientHeartbeat':\n return hasRecord(value, 'input');\n case 'query':\n return hasRecord(value, 'query');\n case 'unreadCount':\n return hasString(value, 'forAgentId');\n case 'softDelete':\n return hasString(value, 'mailId') && hasString(value, 'by');\n case 'restore':\n return hasString(value, 'mailId');\n case 'deregisterAgent':\n return hasString(value, 'agentId');\n case 'purgeAgents':\n case 'purgeStale':\n case 'autoCompact':\n return true;\n case 'deregisterClient':\n return hasString(value, 'clientId');\n case 'credentialIssue':\n return hasRecord(value, 'options');\n case 'credentialVerify':\n return hasString(value, 'credentialId') && hasString(value, 'secret');\n case 'credentialRevoke':\n case 'credentialRotate':\n case 'credentialGet':\n return hasString(value, 'credentialId');\n }\n}\n\n/** Runtime boundary guard for untrusted newline-delimited IPC frames. */\nexport function isMailboxProjectServerClientMessage(\n value: unknown,\n): value is MailboxProjectServerClientMessage {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const message = value as Record<string, unknown>;\n if (message['type'] === 'heartbeat') return true;\n if (message['type'] === 'shutdown') {\n return (\n isRequestId(message['id']) &&\n (message['reason'] === undefined || typeof message['reason'] === 'string')\n );\n }\n if (message['type'] !== 'request' || !isRequestId(message['id'])) return false;\n const op = message['op'];\n return (\n typeof op === 'string' &&\n Object.hasOwn(MAILBOX_SERVER_OPERATION_NAMES, op) &&\n isMailboxServerOperationArgs(op as MailboxServerOperationName, message['args'])\n );\n}\n\nexport type MailboxProjectServerMessage =\n | ({ type: 'hello' } & MailboxProjectServerInfo)\n | { type: 'mailbox-event'; event: MailboxEvent }\n | { type: 'event'; event: string; payload: unknown }\n | { type: 'response'; id: number; ok: true; result: unknown }\n | {\n type: 'response';\n id: number;\n ok: false;\n error: string;\n errorName?: string | undefined;\n };\n\n/** Runtime guard for server frames before the client touches discriminants. */\nexport function isMailboxProjectServerMessage(\n value: unknown,\n): value is MailboxProjectServerMessage {\n if (!isRecord(value) || typeof value['type'] !== 'string') return false;\n if (value['type'] === 'hello') {\n return (\n Number.isInteger(value['protocolVersion']) &&\n Number.isInteger(value['pid']) &&\n hasString(value, 'projectDir') &&\n hasString(value, 'endpoint') &&\n hasString(value, 'startedAt')\n );\n }\n if (value['type'] === 'event') return hasString(value, 'event');\n if (value['type'] === 'mailbox-event') return isRecord(value['event']);\n if (value['type'] !== 'response' || !isRequestId(value['id'])) return false;\n if (value['ok'] === true) return Object.hasOwn(value, 'result');\n return value['ok'] === false && typeof value['error'] === 'string';\n}\n\nexport function encodeMailboxProjectServerMessage(message: object): string {\n return `${JSON.stringify(message)}\\n`;\n}\n", "import { randomUUID } from 'node:crypto';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { DatabaseSync } from 'node:sqlite';\n\nimport type { EventBus } from '../kernel/events.js';\nimport {\n AGENT_STALE_MS,\n AUTO_COMPACT_INTERVAL_MS,\n CLIENT_STALE_MS,\n HEARTBEAT_THROTTLE_MS,\n} from './mailbox-constants.js';\nimport type {\n CredentialValidation,\n IssueCredentialOptions,\n MailboxCredential,\n} from './mailbox-credential-store.js';\nimport type { MailboxEventEmitter } from './mailbox-events.js';\nimport { isMessageCompletedForActor } from './global-mailbox-completion.js';\nimport { isFanOutRecipient } from './mailbox-receipt-folding.js';\nimport {\n projectMailboxCompletion,\n} from './mailbox-retention-state.js';\nimport { mapRegisteredAgentsToStatuses, mapRegisteredClientsToStatuses } from './mailbox-status-mappers.js';\nimport type {\n AgentHeartbeatInput,\n AgentRegistrationInput,\n AutoCompactOptions,\n AutoCompactResult,\n ClientHeartbeatInput,\n ClientRegistrationInput,\n ClientStatus,\n Mailbox,\n MailboxAckBatchInput,\n MailboxAckInput,\n MailboxAgentStatus,\n MailboxMessage,\n MailboxMessageProjection,\n MailboxQuery,\n MailboxRecipientState,\n MailboxSendInput,\n PurgeOptions,\n PurgeResult,\n RegisteredAgent,\n RegisteredClient,\n} from './mailbox-types.js';\nimport {\n isMailboxMessageVisibleTo,\n normalizeRecipient,\n sessionRecipient,\n validateSendType,\n} from './mailbox-types.js';\nimport { normalizeMailboxMessageType } from './mailbox-message-codec.js';\nimport {\n autoCompact,\n type CompactionContext,\n purgeStale,\n} from './sqlite-mailbox-compaction.js';\nimport {\n credentialGet,\n credentialIssue,\n credentialList,\n credentialRevoke,\n credentialRotate,\n credentialStatusCounts,\n credentialVerify,\n} from './sqlite-mailbox-credentials.js';\nimport {\n deleteMessages,\n materializeMessageRows,\n type MessageRow,\n type SqliteStatement,\n persistAgent,\n persistClient,\n persistMessage,\n persistReceipt,\n pruneAgents,\n pruneClients,\n readAgents,\n readClients,\n withoutAggregateCompletion,\n} from './sqlite-mailbox-rows.js';\nimport {\n initializeSchema,\n loadDatabaseSync,\n migrateLegacyFiles,\n type SchemaContext,\n} from './sqlite-mailbox-schema.js';\nexport const SQLITE_MAILBOX_FILE = '_mailbox.sqlite';\n/**\n * Server-owned project mailbox persistence.\n *\n * Production callers must reach this store through RemoteMailbox. The detached\n * project server is the only process that opens the database connection.\n */\n/**\n * Bounds for the in-memory heartbeat throttle maps. The sweep only runs once a\n * map is over the entry cap, so the steady state costs nothing.\n */\nconst HEARTBEAT_TRACKING_MAX_ENTRIES = 512;\nconst HEARTBEAT_TRACKING_TTL_MS = 30 * 60_000;\n\nexport class SqliteMailbox implements Mailbox {\n readonly databasePath: string;\n /** Compatibility alias used by project-server health/status consumers. */\n readonly messagePath: string;\n readonly eventEmitter?: MailboxEventEmitter | undefined;\n\n private readonly db: DatabaseSync;\n private readonly events?: EventBus | undefined;\n private readonly lastHeartbeat = new Map<string, number>();\n private readonly lastClientHeartbeat = new Map<string, number>();\n private autoCompactTimer: NodeJS.Timeout | null = null;\n private closed = false;\n\n constructor(\n readonly projectDir: string,\n events?: EventBus,\n eventEmitter?: MailboxEventEmitter,\n ) {\n fs.mkdirSync(projectDir, { recursive: true });\n this.databasePath = path.join(projectDir, SQLITE_MAILBOX_FILE);\n this.messagePath = this.databasePath;\n this.events = events;\n this.eventEmitter = eventEmitter;\n const Database = loadDatabaseSync();\n this.db = new Database(this.databasePath);\n this.db.exec('PRAGMA journal_mode = WAL');\n this.db.exec('PRAGMA synchronous = NORMAL');\n this.db.exec('PRAGMA foreign_keys = ON');\n this.db.exec('PRAGMA busy_timeout = 5000');\n initializeSchema(this.schemaCtx());\n migrateLegacyFiles(this.schemaCtx());\n }\n\n private stmt(sql: string): SqliteStatement {\n return this.db.prepare(sql);\n }\n\n private transaction<T>(run: () => T): T {\n this.db.exec('BEGIN IMMEDIATE');\n try {\n const result = run();\n this.db.exec('COMMIT');\n return result;\n } catch (error) {\n this.db.exec('ROLLBACK');\n throw error;\n }\n }\n\n /** Bundle of store state the schema/migration module operates on. */\n private schemaCtx(): SchemaContext {\n return {\n db: this.db,\n projectDir: this.projectDir,\n transaction: (run) => this.transaction(run),\n };\n }\n\n private persistMessage(message: MailboxMessage, legacyGlobalCompletion = false): void {\n persistMessage(this.db, message, legacyGlobalCompletion);\n }\n\n private persistReceipt(messageId: string, state: MailboxRecipientState): void {\n persistReceipt(this.db, messageId, state);\n }\n\n private materializeMessageRows(rows: readonly MessageRow[]): MailboxMessageProjection[] {\n return materializeMessageRows(this.db, rows);\n }\n\n private readMessages(): MailboxMessageProjection[] {\n const rows = this.stmt(\n 'SELECT id, data, legacy_global_completion FROM messages',\n ).all() as unknown as MessageRow[];\n return this.materializeMessageRows(rows);\n }\n\n private findMessage(messageId: string): MailboxMessageProjection | undefined {\n const row = this.stmt(\n 'SELECT id, data, legacy_global_completion FROM messages WHERE id = ?',\n ).get(messageId) as MessageRow | undefined;\n return row === undefined ? undefined : this.materializeMessageRows([row])[0];\n }\n\n async send(input: MailboxSendInput): Promise<MailboxMessage> {\n return this.sendMessage(input, false);\n }\n\n async sendRuntimeControl(\n input: Omit<MailboxSendInput, 'type'> & { type?: 'control' },\n ): Promise<MailboxMessage> {\n return this.sendMessage({ ...input, type: 'control' }, true);\n }\n\n private async sendMessage(\n input: MailboxSendInput,\n allowRuntimeControl: boolean,\n ): Promise<MailboxMessage> {\n const type = normalizeMailboxMessageType(input.type);\n const to = normalizeRecipient(input.to, input.senderSessionId);\n if (!(allowRuntimeControl && type === 'control')) validateSendType(type, to);\n const timestamp = new Date().toISOString();\n const message: MailboxMessage = {\n id: randomUUID(),\n from: input.from,\n to,\n type,\n ...(input.audience !== undefined && input.audience !== 'all'\n ? { audience: input.audience }\n : {}),\n subject: input.subject,\n body: input.body,\n priority: input.priority ?? 'normal',\n readBy: {},\n completed: false,\n timestamp,\n ...(input.replyTo !== undefined ? { replyTo: input.replyTo } : {}),\n ...(input.taskContext !== undefined ? { taskContext: input.taskContext } : {}),\n ...(input.senderSessionId !== undefined ? { senderSessionId: input.senderSessionId } : {}),\n ...(input.ttlMs !== undefined\n ? { expiresAt: new Date(Date.now() + input.ttlMs).toISOString() }\n : {}),\n };\n this.persistMessage(message);\n this.events?.emitCustom('mailbox.message_sent', {\n messageId: message.id,\n from: message.from,\n to: message.to,\n type: message.type,\n subject: message.subject,\n });\n this.eventEmitter?.emit({\n type: 'message.sent',\n messageId: message.id,\n from: message.from,\n to: message.to,\n audience: message.audience,\n timestamp,\n });\n return message;\n }\n\n async query(query: MailboxQuery): Promise<MailboxMessage[]> {\n const type = query.type === undefined ? undefined : normalizeMailboxMessageType(query.type);\n const priorityRank = { low: 0, normal: 1, high: 2 } as const;\n const minimumRank = query.minPriority === undefined ? 0 : priorityRank[query.minPriority];\n const statuses =\n query.unreadBy === undefined ? await this.getAgentStatuses() : undefined;\n const where: string[] = [];\n const params: Array<string | number> = [];\n if (query.to !== undefined) {\n where.push('(to_id = ? OR to_id = ?)');\n params.push(query.to, '*');\n }\n if (query.from !== undefined) {\n where.push('from_id = ?');\n params.push(query.from);\n }\n if (query.sessionId !== undefined) {\n where.push('sender_session_id = ?');\n params.push(query.sessionId);\n }\n if (type !== undefined) {\n where.push('type = ?');\n params.push(type);\n }\n if (query.minPriority !== undefined) {\n // Unrecognized priorities rank as `normal`, matching the JSONL reader\n // this store replaced: an unknown value must not silently drop a\n // message out of a `minPriority: 'normal'` query. Only an explicit\n // 'low' ranks below normal.\n where.push(`CASE priority WHEN 'high' THEN 2 WHEN 'low' THEN 0 ELSE 1 END >= ?`);\n params.push(minimumRank);\n }\n if (query.since !== undefined) {\n where.push('timestamp > ?');\n params.push(query.since);\n }\n if (!query.includeDeleted) where.push('deleted_at IS NULL');\n if (query.replyTo !== undefined) {\n where.push('reply_to = ?');\n params.push(query.replyTo);\n }\n const canPreLimit = query.unreadBy === undefined && !query.incompleteOnly;\n let sql = 'SELECT id, data, legacy_global_completion FROM messages';\n if (where.length > 0) sql += ` WHERE ${where.join(' AND ')}`;\n // `rowid DESC` breaks ties: two sends can land in the same millisecond and\n // ISO timestamps have no finer resolution. Without it SQLite is free to\n // return same-millisecond messages in any order, and \"newest first\"\n // becomes a coin flip. Insertion order is stable \u2014 `persistMessage`\n // upserts, so an ack never moves a message's rowid.\n sql += ' ORDER BY timestamp DESC, rowid DESC';\n if (canPreLimit) {\n sql += ' LIMIT ?';\n params.push(query.limit ?? 50);\n }\n const rows = this.stmt(sql).all(...params) as unknown as MessageRow[];\n const messages = this.materializeMessageRows(rows).filter((message) => {\n if (query.to !== undefined && message.to !== query.to && message.to !== '*') return false;\n if (query.from !== undefined && message.from !== query.from) return false;\n if (query.sessionId !== undefined && message.senderSessionId !== query.sessionId) return false;\n if (\n query.unreadBy !== undefined &&\n !isMailboxMessageVisibleTo(message, query.unreadBy, query.readerRole)\n ) return false;\n if (\n !query.incompleteOnly &&\n query.unreadBy !== undefined &&\n query.unreadBy in message.readBy\n ) return false;\n if (\n query.incompleteOnly &&\n (query.unreadBy === undefined\n ? projectMailboxCompletion(message, undefined, statuses).completed\n : isMessageCompletedForActor(message, query.unreadBy))\n ) return false;\n if (type !== undefined && message.type !== type) return false;\n if (priorityRank[message.priority] < minimumRank) return false;\n if (query.since !== undefined && message.timestamp <= query.since) return false;\n if (!query.includeDeleted && message.deletedAt !== undefined) return false;\n if (query.replyTo !== undefined && message.replyTo !== query.replyTo) return false;\n return true;\n });\n messages.sort((left, right) => right.timestamp.localeCompare(left.timestamp));\n return messages.slice(0, query.limit ?? 50).map((message) => {\n const copy = {\n ...projectMailboxCompletion(message, query.unreadBy, statuses),\n readBy: { ...message.readBy },\n };\n if (!query.includeReceiptState) {\n delete (copy as Partial<MailboxMessageProjection>).recipientState;\n delete (copy as Partial<MailboxMessageProjection>).legacyGlobalCompletion;\n }\n return copy;\n });\n }\n\n async ack(input: MailboxAckInput): Promise<MailboxMessage | null> {\n const results = await this.ackMany({ acks: [input] });\n return results[0] ?? null;\n }\n\n async ackMany(input: MailboxAckBatchInput): Promise<MailboxMessage[]> {\n if (input.acks.length === 0) return [];\n const timestamp = new Date().toISOString();\n const changed = new Set<string>();\n const updated = this.transaction(() => {\n const results: MailboxMessage[] = [];\n for (const ack of input.acks) {\n const message = this.findMessage(ack.messageId);\n if (message === undefined) continue;\n const current = message.recipientState[ack.readerId] ?? { actorId: ack.readerId };\n const state: MailboxRecipientState = { ...current };\n let didChange = false;\n\n if (ack.read !== false && state.readAt === undefined) {\n state.readAt = timestamp;\n message.readBy[ack.readerId] = timestamp;\n didChange = true;\n }\n if (\n ack.completed === true &&\n state.completedAt === undefined &&\n message.legacyGlobalCompletion !== true\n ) {\n state.completedAt = timestamp;\n state.completedBy = ack.readerId;\n didChange = true;\n }\n if (ack.read === false && ack.completed === false && state.completedAt !== undefined) {\n delete state.completedAt;\n delete state.completedBy;\n didChange = true;\n }\n if (ack.outcome !== undefined && state.outcome !== ack.outcome) {\n state.outcome = ack.outcome;\n didChange = true;\n }\n\n message.recipientState = {\n ...message.recipientState,\n [ack.readerId]: state,\n };\n const actorCompleted = state.completedAt !== undefined;\n message.completed = message.legacyGlobalCompletion === true || actorCompleted;\n if (actorCompleted) {\n message.completedBy = state.completedBy ?? ack.readerId;\n message.completedAt = state.completedAt;\n } else if (message.legacyGlobalCompletion !== true) {\n delete message.completedBy;\n delete message.completedAt;\n }\n message.outcome = state.outcome;\n\n if (didChange) {\n this.persistReceipt(message.id, state);\n // Aggregate completion is STORED only for a message with a single\n // addressee. One actor finishing a fan-out (`*`, `@session:`, a bare\n // role alias) must not mark it done for everyone else \u2014 that is what\n // the per-actor receipt model exists to prevent, and\n // `legacyGlobalCompletion` marks the historical v1 messages that\n // predate it. The value returned to the caller below still reports\n // that actor's own completion.\n this.persistMessage(\n isFanOutRecipient(message.to) ? withoutAggregateCompletion(message) : message,\n message.legacyGlobalCompletion === true,\n );\n changed.add(message.id);\n }\n results.push({ ...message, readBy: { ...message.readBy } });\n }\n return results;\n });\n\n for (const message of updated) {\n if (!changed.has(message.id)) continue;\n this.eventEmitter?.emit({\n type: 'message.acked',\n messageId: message.id,\n from: message.from,\n to: message.to,\n audience: message.audience,\n timestamp,\n });\n }\n return updated;\n }\n\n async unreadCount(forAgentId: string, sessionId?: string): Promise<number> {\n const sessionAddress = sessionId === undefined ? undefined : sessionRecipient(sessionId);\n return this.readMessages().filter(\n (message) =>\n (message.to === forAgentId || message.to === '*' || message.to === sessionAddress) &&\n isMailboxMessageVisibleTo(message, forAgentId) &&\n !(forAgentId in message.readBy) &&\n !isMessageCompletedForActor(message, forAgentId) &&\n message.deletedAt === undefined,\n ).length;\n }\n\n async softDelete(mailId: string, by: string): Promise<MailboxMessage | null> {\n const message = this.findMessage(mailId);\n if (message === undefined) return null;\n if (message.deletedAt !== undefined) return { ...message, readBy: { ...message.readBy } };\n const timestamp = new Date().toISOString();\n message.deletedAt = timestamp;\n message.deletedBy = by;\n const previousState = message.recipientState[by] ?? { actorId: by };\n const state = {\n ...previousState,\n readAt: previousState.readAt ?? timestamp,\n };\n message.readBy[by] = state.readAt;\n message.recipientState = { ...message.recipientState, [by]: state };\n this.transaction(() => {\n this.persistReceipt(message.id, state);\n this.persistMessage(message, message.legacyGlobalCompletion === true);\n });\n this.eventEmitter?.emit({\n type: 'message.deleted',\n messageId: message.id,\n from: message.from,\n to: message.to,\n audience: message.audience,\n timestamp,\n });\n return { ...message, readBy: { ...message.readBy } };\n }\n\n async restore(mailId: string): Promise<MailboxMessage | null> {\n const message = this.findMessage(mailId);\n if (message === undefined) return null;\n if (message.deletedAt === undefined && message.deletedBy === undefined) {\n return { ...message, readBy: { ...message.readBy } };\n }\n delete message.deletedAt;\n delete message.deletedBy;\n this.persistMessage(message, message.legacyGlobalCompletion === true);\n const timestamp = new Date().toISOString();\n this.eventEmitter?.emit({\n type: 'message.restored',\n messageId: message.id,\n from: message.from,\n to: message.to,\n audience: message.audience,\n timestamp,\n });\n return { ...message, readBy: { ...message.readBy } };\n }\n\n private persistAgent(agent: RegisteredAgent): void {\n persistAgent(this.db, agent);\n }\n\n private readAgents(): Map<string, RegisteredAgent> {\n return readAgents(this.db);\n }\n\n private pruneAgents(maxAgeMs = AGENT_STALE_MS): number {\n return pruneAgents(this.db, maxAgeMs);\n }\n\n async registerAgent(input: AgentRegistrationInput): Promise<void> {\n this.pruneAgents();\n const now = new Date().toISOString();\n this.persistAgent({\n agentId: input.agentId,\n sessionId: input.sessionId,\n name: input.name,\n ...(input.role !== undefined ? { role: input.role } : {}),\n status: 'idle',\n iterations: 0,\n toolCalls: 0,\n registeredAt: now,\n lastSeenAt: now,\n pid: input.pid ?? process.pid,\n ...(input.source !== undefined ? { source: input.source } : {}),\n });\n this.events?.emitCustom('mailbox.agent_registered', {\n agentId: input.agentId,\n sessionId: input.sessionId,\n name: input.name,\n role: input.role,\n source: input.source,\n });\n }\n\n /**\n * Throttle bookkeeping only: `agentId`/`clientId` -> last accepted heartbeat.\n *\n * Entries are deleted on a clean deregister, but a crashed or forcibly killed\n * peer never deregisters, so over a long-lived daemon's life these maps grew\n * with every distinct id ever seen. Dropping a stale entry is free: the next\n * heartbeat from that id simply is not throttled and writes once more.\n */\n private pruneHeartbeats(map: Map<string, number>, nowMs: number): void {\n if (map.size <= HEARTBEAT_TRACKING_MAX_ENTRIES) return;\n for (const [id, at] of map) {\n if (nowMs - at > HEARTBEAT_TRACKING_TTL_MS) map.delete(id);\n }\n }\n\n async deregisterAgent(agentId: string): Promise<void> {\n this.stmt('DELETE FROM agents WHERE agent_id = ?').run(agentId);\n this.lastHeartbeat.delete(agentId);\n this.events?.emitCustom('mailbox.agent_deregistered', { agentId });\n }\n\n async heartbeat(input: AgentHeartbeatInput): Promise<void> {\n const nowMs = Date.now();\n if (nowMs - (this.lastHeartbeat.get(input.agentId) ?? 0) < HEARTBEAT_THROTTLE_MS) return;\n this.lastHeartbeat.set(input.agentId, nowMs);\n this.pruneHeartbeats(this.lastHeartbeat, nowMs);\n this.pruneAgents();\n const agent = this.readAgents().get(input.agentId);\n if (agent !== undefined) {\n agent.lastSeenAt = new Date(nowMs).toISOString();\n if (input.status !== undefined) agent.status = input.status;\n if (input.currentTool !== undefined) agent.currentTool = input.currentTool;\n if (input.currentTask !== undefined) agent.currentTask = input.currentTask;\n if (input.iterations !== undefined) agent.iterations = input.iterations;\n if (input.toolCalls !== undefined) agent.toolCalls = input.toolCalls;\n this.persistAgent(agent);\n }\n this.events?.emitCustom('mailbox.agent_heartbeat', {\n agentId: input.agentId,\n status: input.status,\n currentTool: input.currentTool,\n currentTask: input.currentTask,\n });\n }\n\n async getAgentStatuses(): Promise<MailboxAgentStatus[]> {\n this.pruneAgents();\n return mapRegisteredAgentsToStatuses(this.readAgents(), Date.now(), AGENT_STALE_MS);\n }\n\n async purgeAgents(maxAgeMs = AGENT_STALE_MS): Promise<number> {\n return this.pruneAgents(maxAgeMs);\n }\n\n async getOnlineAgents(): Promise<MailboxAgentStatus[]> {\n return (await this.getAgentStatuses()).filter((agent) => agent.online);\n }\n\n private persistClient(client: RegisteredClient): void {\n persistClient(this.db, client);\n }\n\n private readClients(): Map<string, RegisteredClient> {\n return readClients(this.db);\n }\n\n private pruneClientsInPlace(): number {\n return pruneClients(this.db);\n }\n\n async registerClient(input: ClientRegistrationInput): Promise<void> {\n this.pruneClientsInPlace();\n const now = new Date().toISOString();\n this.persistClient({\n clientId: input.clientId,\n sessionId: input.sessionId,\n name: input.name,\n source: input.source,\n registeredAt: now,\n lastSeenAt: now,\n pid: input.pid ?? process.pid,\n });\n this.events?.emitCustom('mailbox.client_registered', {\n clientId: input.clientId,\n sessionId: input.sessionId,\n name: input.name,\n source: input.source,\n });\n }\n\n async deregisterClient(clientId: string): Promise<void> {\n this.stmt('DELETE FROM clients WHERE client_id = ?').run(clientId);\n this.lastClientHeartbeat.delete(clientId);\n this.events?.emitCustom('mailbox.client_deregistered', { clientId });\n }\n\n async clientHeartbeat(input: ClientHeartbeatInput): Promise<void> {\n const nowMs = Date.now();\n if (\n nowMs - (this.lastClientHeartbeat.get(input.clientId) ?? 0) <\n HEARTBEAT_THROTTLE_MS\n ) return;\n this.lastClientHeartbeat.set(input.clientId, nowMs);\n this.pruneHeartbeats(this.lastClientHeartbeat, nowMs);\n this.pruneClientsInPlace();\n const client = this.readClients().get(input.clientId);\n if (client !== undefined) {\n client.lastSeenAt = new Date(nowMs).toISOString();\n if (input.sessionId) client.sessionId = input.sessionId;\n this.persistClient(client);\n }\n this.events?.emitCustom('mailbox.client_heartbeat', {\n clientId: input.clientId,\n ...(input.sessionId ? { sessionId: input.sessionId } : {}),\n });\n }\n\n async getClientStatuses(): Promise<ClientStatus[]> {\n this.pruneClientsInPlace();\n return mapRegisteredClientsToStatuses(this.readClients(), Date.now(), CLIENT_STALE_MS);\n }\n\n async purgeClients(): Promise<number> {\n return this.pruneClientsInPlace();\n }\n\n async clearAll(): Promise<void> {\n this.stmt('DELETE FROM messages').run();\n }\n\n async purgeStale(options?: PurgeOptions): Promise<PurgeResult> {\n return purgeStale(this.compactionCtx(), options);\n }\n\n async autoCompact(options?: AutoCompactOptions): Promise<AutoCompactResult> {\n return autoCompact(this.compactionCtx(), options);\n }\n\n /** Bundle of store operations the retention sweeps drive. */\n private compactionCtx(): CompactionContext {\n return {\n getAgentStatuses: () => this.getAgentStatuses(),\n readMessages: () => this.readMessages(),\n deleteMessages: (ids) => this.deleteMessages(ids),\n };\n }\n\n private deleteMessages(ids: readonly string[]): void {\n if (ids.length === 0) return;\n this.transaction(() => deleteMessages(this.db, ids));\n }\n\n credentialGet(credentialId: string): MailboxCredential | null {\n return credentialGet(this.db, credentialId);\n }\n\n credentialList(): MailboxCredential[] {\n return credentialList(this.db);\n }\n\n credentialStatusCounts(): Record<string, number> {\n return credentialStatusCounts(this.db);\n }\n\n credentialIssue(\n options: IssueCredentialOptions,\n ): { credential: MailboxCredential; secret: string } {\n return credentialIssue(this.db, (run) => this.transaction(run), options);\n }\n\n credentialVerify(credentialId: string, secret: string): CredentialValidation {\n return credentialVerify(this.db, credentialId, secret);\n }\n\n credentialRevoke(credentialId: string, reason?: string, by?: string): boolean {\n return credentialRevoke(this.db, credentialId, reason, by);\n }\n\n credentialRotate(\n credentialId: string,\n options?: Partial<IssueCredentialOptions>,\n ): { credential: MailboxCredential; secret: string } | null {\n return credentialRotate(this.db, (run) => this.transaction(run), credentialId, options);\n }\n\n startAutoCompactTimer(options?: AutoCompactOptions): () => void {\n if (this.autoCompactTimer !== null) clearInterval(this.autoCompactTimer);\n const timer = setInterval(() => {\n void this.autoCompact(options).catch(() => {});\n }, options?.intervalMs ?? AUTO_COMPACT_INTERVAL_MS);\n timer.unref?.();\n this.autoCompactTimer = timer;\n return () => {\n clearInterval(timer);\n if (this.autoCompactTimer === timer) this.autoCompactTimer = null;\n };\n }\n\n async close(): Promise<void> {\n if (this.closed) return;\n this.closed = true;\n if (this.autoCompactTimer !== null) clearInterval(this.autoCompactTimer);\n this.autoCompactTimer = null;\n this.db.close();\n }\n}\n", "/**\n * Centralized constants for the mailbox system.\n *\n * Previously these magic numbers were scattered across global-mailbox.ts,\n * mailbox-attach.ts, mailbox-hooks.ts, and mailbox-health.ts. Keeping them\n * in one place ensures every surface agrees on timeouts, intervals, and\n * thresholds \u2014 and makes tuning a single-file change.\n *\n * @module mailbox-constants\n */\n\n/**\n * Agents without a heartbeat for this long are no longer live and are removed\n * from the registry. Presence registries are not history stores: retaining an\n * offline row makes dead agents and shadow workers look actionable in HQ.\n */\nexport const AGENT_STALE_MS = 60_000;\n\n/** Clients without a heartbeat for this long are considered offline. */\nexport const CLIENT_STALE_MS = 60_000;\n\n/** Heartbeat updates are throttled to at most this interval (per agent/client). */\nexport const HEARTBEAT_THROTTLE_MS = 5_000;\n\n/**\n * How long a read may be served from the in-process registry cache before\n * re-reading the shared file. Kept well below HEARTBEAT_THROTTLE_MS so\n * cross-process registrations become visible promptly.\n */\nexport const REGISTRY_CACHE_TTL_MS = 2_000;\n\n/** JSONL line separator. */\nexport const LINE_SEPARATOR = '\\n';\n\n/**\n * Soft cap on the in-memory message cache. The cache mirrors the JSONL\n * message file; under normal load it stays well under this. If a pathological\n * mailbox exceeds the cap we fall back to reading from disk rather than\n * holding an unbounded buffer in memory.\n */\nexport const MESSAGE_CACHE_MAX_ENTRIES = 10_000;\n\n// \u2500\u2500 Polling / heartbeat intervals (used by mailbox-attach.ts) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Background mailbox awareness polling interval (cross-process fallback). */\nexport const MAILBOX_AWARENESS_INTERVAL_MS = 30_000;\n\n/** Agent heartbeat interval in the attach layer. */\nexport const MAILBOX_HEARTBEAT_INTERVAL_MS = 30_000;\n\n/**\n * Floor on how often a full HQ mailbox snapshot may be published.\n *\n * The snapshot is a rollup (50 messages + every agent status, ~30 KB) that\n * exists so the HQ dashboard's counters are authoritative. It used to be\n * published after *every* message mutation and *every* agent heartbeat, which\n * made it the single largest thing HQ persists: 14,053 snapshots totalling\n * 415 MB in one measured `events.jsonl`, next to 8.3 MB for the 12,445\n * `mailbox.event` deltas that already carried the same information.\n *\n * Snapshots are now coalesced behind this interval \u2014 the dashboard converges\n * within a few seconds instead of on every keystroke-scale event, and the\n * deltas keep the live feed exact in between.\n */\nexport const HQ_MAILBOX_SNAPSHOT_MIN_INTERVAL_MS = 10_000;\n\n/** Min interval between registry reads for the fleet pulse digest. */\nexport const PULSE_MIN_READ_INTERVAL_MS = 30_000;\n\n/**\n * Floor on how often the pre-tool hook actually reads the mailbox.\n *\n * `beforeTool` fires once per tool call, and a busy turn issues dozens. Each\n * call stats the shared message file and, whenever another session has written\n * to it, pays a read. Collapsing bursts to one check per second keeps steer\n * messages effectively immediate (no tool completes fast enough for a human to\n * notice the difference) while removing the per-tool file churn. Set the hook's\n * `unreadCheckIntervalMs` to 0 to check on every call.\n */\nexport const UNREAD_CHECK_MIN_INTERVAL_MS = 1_000;\n\n// \u2500\u2500 Auto-cleanup / compaction \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Interval at which the background auto-compaction sweep runs.\n * Default: every 5 minutes.\n */\nexport const AUTO_COMPACT_INTERVAL_MS = 300_000;\n\n/**\n * Messages that have been read by ALL currently-online agents are eligible\n * for auto-removal after this many milliseconds since the last read.\n * Default: 10 minutes.\n */\nexport const AUTO_COMPACT_READ_MAX_AGE_MS = 600_000;\n\n/**\n * Messages whose TTL (time-to-live) has expired are eligible for auto-removal.\n * When a message has `expiresAt` set and that timestamp is in the past, the\n * next compaction sweep drops it. Default TTL for messages without an explicit\n * `expiresAt`: 24 hours.\n */\nexport const AUTO_COMPACT_DEFAULT_TTL_MS = 86_400_000; // 24h\n\n/**\n * Per-type TTL overrides for message classes that are pure live-awareness\n * chatter, applied when the message carries no explicit `expiresAt`.\n *\n * `status` is broadcast by the fleet supervisor, host supervisor, mailbox\n * health probe and handoff plugin purely so peers can see who is doing what\n * *right now*; nothing reads it back as history. Under the 24h default it\n * dominated the shared file \u2014 on a real project mailbox, 1807 of 2766 lines\n * and 1.5 MB of 3 MB \u2014 and every reader pays for that on any cache miss.\n * Half an hour is far longer than any consumer's interest window.\n *\n * Keyed by `MailboxMessageType`; unlisted types keep\n * {@link AUTO_COMPACT_DEFAULT_TTL_MS}.\n */\nexport const AUTO_COMPACT_TYPE_TTL_MS: Readonly<Record<string, number>> = {\n status: 1_800_000, // 30 min\n};\n\n// \u2500\u2500 HTTP bridge rate limiting \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Maximum requests per minute from a single external agent (bearer token). */\nexport const HTTP_RATE_LIMIT_PER_MINUTE = 120;\n\n/** Window size for the sliding-window rate limiter. */\nexport const HTTP_RATE_LIMIT_WINDOW_MS = 60_000;\n", "import type { MailboxMessage } from './mailbox-types.js';\nimport type { MailboxMessageProjection } from './mailbox-receipt-folding.js';\n\nexport function isMailboxMessageProjection(msg: MailboxMessage): msg is MailboxMessageProjection {\n if (!('recipientState' in msg)) return false;\n const recipientState: unknown = msg.recipientState;\n return (\n typeof recipientState === 'object' &&\n recipientState !== null &&\n !Array.isArray(recipientState)\n );\n}\n\nexport function isMessageCompletedForActor(\n msg: MailboxMessage,\n actorId?: string,\n): boolean {\n if (!isMailboxMessageProjection(msg)) return msg.completed === true;\n if (msg.legacyGlobalCompletion) return true;\n if (actorId !== undefined) {\n const state = msg.recipientState[actorId];\n if (state !== undefined) return state.completedAt !== undefined;\n if (Object.keys(msg.recipientState).length > 0) return false;\n }\n return msg.completed === true;\n}\n", "/**\n * Mailbox \u2014 persistent inter-agent messaging system with cross-session support.\n *\n * Agents can leave notes for specific agents or broadcast to all. Each agent\n * periodically checks the mailbox or retrieves messages via tool calls.\n *\n * ## Cross-session communication\n *\n * The mailbox is stored at **project level** (`~/.wrongstack/projects/<slug>/_mailbox.sqlite`, owned by one detached\n * project server and reached over IPC),\n * so agents in different terminal sessions / WebUI tabs working on the same\n * canonical project can communicate live, even when they run in different\n * processes, clients, branches, or linked Git worktrees.\n *\n * ## Agent registration\n *\n * Every agent that uses the mailbox registers itself with a heartbeat.\n * Other agents can discover online agents via `getOnlineAgents()`.\n * Stale agents (no heartbeat > 60s) are pruned automatically.\n *\n * ## Read receipts\n *\n * Each message tracks per-recipient read status via a `readBy` map:\n * `{ \"agentId\": \"ISO8601\" }`. When agent X reads a message, its entry\n * is added. The WebUI shows who read what and when.\n *\n * @module mailbox-types\n */\n\nimport {\n MAILBOX_TYPE_PROPERTIES,\n type MailboxMessageType,\n} from './mailbox-type-properties.js';\nexport {\n MAILBOX_TYPE_PROPERTIES,\n type MailboxMessageType,\n type MailboxTypeCategory,\n} from './mailbox-type-properties.js';\n\n// \u2500\u2500 Message type discriminator \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * The ten mail types each carry a distinct **semantic category**, a **sender\n * contract** (when the sender must use it), and a **recipient contract** (how\n * the runtime dispatches it and what the recipient agent must do).\n *\n * \u2500\u2500\u2500\u2500\u2500 Type semantics \u2014 decision matrix for senders \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * ## Categories\n *\n * | Category | Types | Purpose |\n * |--------------|---------------------------------------|--------------------------------|\n * | Actionable | `ask`, `assign`, `steer`, `review` | Require a substantive response |\n * | Informational| `note`, `btw`, `result`, `status` | Consume for context, no action |\n * | Routing | `broadcast` | Multi-recipient envelope |\n * | Control | `control` | Out-of-band signal (no render) |\n *\n * ## Per-type contract\n *\n * ### Actionable types\n *\n * | Type | When to send | Recipient must |\n * |----------|-----------------------------------------------------|----------------------------------------------------|\n * | `ask` | Blocking question \u2014 you need an answer to proceed | Answer as soon as possible; the sender is waiting. |\n * | `assign` | Delegating a task | Accept or decline; act on it when current op allows. |\n * | `steer` | Mid-task direction change \u2014 the recipient is | Pause current approach, adjust per instruction, |\n * | | already working on something and you need them | then resume. Rendered first in the mailbox block. |\n * | | to change course NOW | |\n * | `review` | Requesting a code/doc/PR review (passive) | Inspect when convenient; no immediate reply needed.|\n *\n * ### Informational types\n *\n * | Type | When to send | Recipient must |\n * |----------|-----------------------------------------------------|----------------------------------------------------|\n * | `note` | General-purpose FYI \u2014 a message that isn't any | Read for context; no reply needed. The untyped |\n * | | of the more specific types | default for directed messages. |\n * | `btw` | Low-priority aside \u2014 \"by the way\" | Absorb the information and stay on current task; |\n * | | | no reply needed. Injected via BTW block (separate |\n * | | | from the main mailbox fold) to minimise disruption.|\n * | `result` | Subagent/task completion notice \u2014 share the | Factor into next decision; treat as evidence, not |\n * | | outcome of finished work | a new task. |\n * | `status` | Agent or system status update (heartbeat, spawn, | Use to avoid redundant work; never act on it as |\n * | | task progress, error). Machine-generated. | a task or question. |\n * | `broadcast` | Multi-recipient envelope \u2014 the same message for | Read if addressed to you (direct, alias, session, |\n * | | every agent on the project. Auto-selected when | or `*`). The `*` recipient means \"everyone\". |\n * | | `to` is `\"*\"` or `\"@session\"` in `mail_send`. | |\n *\n * ### Control type\n *\n * | Type | When to send | Recipient must |\n * |----------|-----------------------------------------------------|----------------------------------------------------|\n * | `control`| Out-of-band signal (interrupt, halt, redirect). | NEVER folded into conversation content. The agent |\n * | | Machine-generated by the runtime, not by agents. | loop intercepts it separately. `control:interrupt` |\n * | | | causes a cooperative halt at the next iteration |\n * | | | boundary. |\n *\n * \u2500\u2500\u2500\u2500\u2500 Dispatch behavior (runtime contract) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * The mailbox system enforces these dispatch rules:\n *\n * 1. **Send-side**: `mail_send` auto-defaults the type: `broadcast` when\n * `to` is `\"*\"` or `\"@session::...\"`, otherwise `note`.\n * 2. **Send-side validation**: `assign` always requires a specific `to`\n * (not `\"*\"`). `control` is reserved for runtime use \u2014 agents passing it\n * via the tool surface will be rejected.\n * 3. **Render-order guarantee**: `steer` messages are ALWAYS rendered first\n * in `buildMailboxBlock()`, before any other type, to ensure mid-task\n * direction changes are seen before other action items.\n * 4. **Control isolation**: `control`-type messages are filtered by\n * `injectPendingMailboxMessages()` and NEVER enter the folded\n * conversation block \u2014 they are out-of-band signals only.\n * 5. **Background routing**: in `background` delivery mode, only\n * `ACTIONABLE_BACKGROUND_TYPES` (`steer`, `ask`, `assign`, `result`,\n * `review`) are escalated; `note`, `btw`, `status`, and `broadcast`\n * are suppressed to minimise disruption during tool work.\n * 6. **Awareness polling**: `btw` messages intercepted by background\n * polling are queued via `setBtwNote()` for injection at a safe loop\n * boundary, not folded inline.\n * 7. **Agent registry**: `getAgentStatuses()` reads the dedicated agent\n * registry (`_mailbox.registry.json`), not mailbox message content. The\n * registry is populated by agent heartbeat calls (not by `status`-type\n * messages). `Mailbox.getAgentStatuses()` derives\n * a registry snapshot from `status`-type messages as a fallback when no\n * shared registry file exists.\n * 8. **Request-scoped context**: delivered raw mailbox blocks are removed\n * after one successful provider evaluation. Durable assistant/tool/task\n * consequences remain; routine mail does not occupy later requests.\n *\n * When a type is missing from any dispatch table, the fallback is:\n * - Render with `\uD83D\uDCE8 <TYPE>` label (generic emoji prefix)\n * - Route inline (not background)\n * - No special instruction added\n */\n\n/**\n * Which class of agent may consume a mailbox message.\n *\n * `leaders` is a delivery boundary, not merely a UI hint: agent-loop and\n * inbox readers must exclude these messages for subagents. The optional\n * persisted field keeps older JSONL records backwards-compatible (`all`).\n */\nexport type MailboxAudience = 'all' | 'leaders';\n\n/** Return the stable base portion of a session-qualified mailbox identity. */\nexport function mailboxIdentityBase(agentId: string): string {\n return agentId.split(/[@#]/, 1)[0]!.trim().toLowerCase();\n}\n\n/** Whether a mailbox identity belongs to the session's main/leader agent. */\nexport function isMailboxLeader(agentId: string, role?: string): boolean {\n return mailboxIdentityBase(agentId) === 'leader' || role?.trim().toLowerCase() === 'leader';\n}\n\n/** Whether a message may be consumed by the supplied agent identity. */\nexport function isMailboxMessageVisibleTo(\n message: Pick<MailboxMessage, 'audience'>,\n agentId: string,\n role?: string,\n): boolean {\n return message.audience !== 'leaders' || isMailboxLeader(agentId, role);\n}\n\n/** Category + expectsReply are provided by MAILBOX_TYPE_PROPERTIES directly. */\n\n/**\n * Validate that a given (type, to) pair is internally consistent.\n * Throws when the combination breaks a fundamental rule.\n */\nexport function validateSendType(type: MailboxMessageType, to: string): void {\n if (type === 'control') {\n throw new TypeError(\n 'Type \"control\" is reserved for runtime use and cannot be set by agents',\n );\n }\n const isMultiRecipient = to === '*' || to.startsWith('@session:');\n if (type === 'assign' && isMultiRecipient) {\n throw new TypeError(\n `Type \"assign\" requires a specific recipient \u2014 multi-recipient target \"${to}\" is ambiguous`,\n );\n }\n if (type === 'steer' && isMultiRecipient) {\n throw new TypeError(\n `Type \"steer\" requires a specific recipient \u2014 multi-recipient target \"${to}\" is ambiguous`,\n );\n }\n}\n\n// \u2500\u2500 Read receipt \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Per-recipient read status. `readBy` maps agentId \u2192 ISO8601 timestamp of\n * when that agent first read the message. An empty map means unread by all.\n */\nexport interface ReadReceipts {\n [agentId: string]: string; // ISO8601 timestamp\n}\n\n// \u2500\u2500 Core message \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface MailboxMessage {\n /** Unique message id (UUID). */\n id: string;\n /** Sender agent id. */\n from: string;\n /** Recipient agent id, or '*' for broadcast. */\n to: string;\n /** Message category. */\n type: MailboxMessageType;\n /** Delivery audience. Omitted legacy values mean `all`. */\n audience?: MailboxAudience | undefined;\n /** Short subject line \u2014 one sentence. */\n subject: string;\n /** Full message content. */\n body: string;\n /** Priority \u2014 high priority messages surface first. */\n priority: 'low' | 'normal' | 'high';\n /**\n * Per-recipient read receipts. agentId \u2192 ISO8601 when they first read it.\n * Replaces the old single `read: boolean` + `readAt` fields.\n */\n readBy: ReadReceipts;\n /** Has any recipient acted on / completed this? */\n completed: boolean;\n /** Who completed it (agentId). */\n completedBy?: string | undefined;\n /** Optional summary of what happened after handling. */\n outcome?: string | undefined;\n /** ISO8601 \u2014 when the message was sent. */\n timestamp: string;\n /** ISO8601 \u2014 when the message was marked complete. */\n completedAt?: string | undefined;\n /**\n * ISO8601 \u2014 when the message was soft-deleted. When present, the\n * default `Mailbox.query()` filter excludes the message from the\n * normal inbox view; {@link Mailbox.restore} clears the\n * field to undo the delete. Hard deletes (removing the line from\n * the JSONL) are reserved for the CLI and never happen via the\n * server route handlers.\n */\n deletedAt?: string | undefined;\n /** When the soft-delete happened, the agentId that issued it. */\n deletedBy?: string | undefined;\n /** If this is a reply, the id of the parent message. */\n replyTo?: string | undefined;\n /** For assign-type messages \u2014 task context for agent discovery. */\n taskContext?: MailboxTaskContext | undefined;\n /** Session id of the sender. Enables cross-session communication. */\n senderSessionId?: string | undefined;\n /**\n * ISO8601 \u2014 when the message expires. Set at send time from `ttlMs`\n * (default: 24h via AUTO_COMPACT_DEFAULT_TTL_MS). The auto-compaction\n * sweep removes messages whose `expiresAt` is in the past. When\n * undefined, the compaction sweep uses the default TTL from the\n * caller's options.\n */\n expiresAt?: string | undefined;\n}\n\n// \u2500\u2500 Task context for agent discovery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface MailboxTaskContext {\n /** The role that should handle this task (e.g. \"tech-stack\", \"audit-log\"). */\n agentRole?: string | undefined;\n /** Human-readable agent name (e.g. \"Tesla (Executor)\"). */\n agentName?: string | undefined;\n /** Task id if already assigned via coordinator. */\n taskId?: string | undefined;\n /** Current task status. */\n status?: 'pending' | 'in_progress' | 'completed' | 'failed' | undefined;\n}\n\n// \u2500\u2500 Agent registration \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface RegisteredAgent {\n /** Unique agent id. */\n agentId: string;\n /** Session id this agent belongs to. */\n sessionId: string;\n /** Human-readable name. */\n name: string;\n /** Role (e.g. \"leader\", \"tech-stack\", \"bug-hunter\"). */\n role?: string | undefined;\n /** Current status. */\n status: 'idle' | 'running' | 'streaming' | 'waiting_user' | 'error';\n /** Current tool being executed, if any. */\n currentTool?: string | undefined;\n /** Current task description. */\n currentTask?: string | undefined;\n /** Iteration count so far. */\n iterations: number;\n /** Tool calls so far. */\n toolCalls: number;\n /** ISO8601 \u2014 registered at. */\n registeredAt: string;\n /** ISO8601 \u2014 last heartbeat (updated on every mailbox op). */\n lastSeenAt: string;\n /** Which process registered this agent (PID). */\n pid: number;\n /** Where the agent is running (e.g. \"cli\", \"webui\"). */\n source?: 'cli' | 'webui' | 'mcp' | 'acp' | 'http' | undefined;\n}\n\n// \u2500\u2500 Agent status entry (for discovery) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface MailboxAgentStatus {\n /** Agent id. */\n agentId: string;\n /** Human-readable name. */\n name: string;\n /** Role. */\n role?: string | undefined;\n /** Session id. */\n sessionId: string;\n /** Current status. */\n status: 'idle' | 'running' | 'streaming' | 'waiting_user' | 'error' | 'offline';\n /** Current tool being executed, if any. */\n currentTool?: string | undefined;\n /** Current task description. */\n currentTask?: string | undefined;\n /** Iteration count so far. */\n iterations: number;\n /** Tool calls so far. */\n toolCalls: number;\n /** ISO8601 \u2014 last activity timestamp. */\n lastActivityAt: string;\n /** ISO8601 \u2014 last heartbeat. */\n lastSeenAt: string;\n /** Whether this agent is currently online (heartbeat within threshold). */\n online: boolean;\n /** Which process. */\n pid: number;\n /** Source. */\n source?: 'cli' | 'webui' | 'mcp' | 'acp' | 'http' | undefined;\n}\n\n// \u2500\u2500 Mailbox query \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface MailboxQuery {\n /** Filter by recipient agent id. */\n to?: string | undefined;\n /** Filter by sender agent id. */\n from?: string | undefined;\n /** Only messages unread by this agent. */\n unreadBy?: string | undefined;\n /** Trusted caller role used with `unreadBy` for audience filtering. */\n readerRole?: string | undefined;\n /** Only incomplete messages. */\n incompleteOnly?: boolean | undefined;\n /**\n * Internal trusted-read option: retain folded per-actor receipt state so a\n * boundary can derive an actor-safe projection. Untrusted query codecs must\n * never accept this field from request payloads.\n */\n includeReceiptState?: boolean | undefined;\n /** Filter by message type. */\n type?: MailboxMessageType | undefined;\n /** Filter by priority (>= this level). */\n minPriority?: 'low' | 'normal' | 'high' | undefined;\n /** Maximum number of messages to return. */\n limit?: number | undefined;\n /** ISO8601 \u2014 only messages after this timestamp. */\n since?: string | undefined;\n /** Filter by the sender's session id (`MailboxMessage.senderSessionId`). */\n sessionId?: string | undefined;\n /**\n * Include soft-deleted messages (where `deletedAt` is set). When\n * `false` (the default), soft-deleted messages are filtered out so\n * the normal inbox view stays clean. The \"trash\" view passes\n * `true` to surface them.\n */\n includeDeleted?: boolean | undefined;\n /**\n * Filter by replyTo parent message id (UUID). When set, only messages\n * whose `replyTo` exactly matches this value are returned. An empty\n * string matches nothing \u2014 empty strings are technically allowed by\n * `send()` (it passes through `MailboxSendInput.replyTo` directly with\n * no normalization), but are never produced by chimera/execution callers.\n * The query filter is exact-match.\n * Useful for polling the response to a specific `ask` message.\n */\n replyTo?: string | undefined;\n}\n\n// \u2500\u2500 Mailbox operations \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Canonical prefix for mail addressed to every agent in one session. */\nexport const SESSION_RECIPIENT_PREFIX = '@session:';\n\n/** Build the canonical recipient address for a session-scoped broadcast. */\nexport function sessionRecipient(sessionId: string): string {\n const normalizedSessionId = sessionId.trim();\n if (!normalizedSessionId) {\n throw new TypeError('sessionId is required for the \"@session\" recipient');\n }\n return `${SESSION_RECIPIENT_PREFIX}${normalizedSessionId}`;\n}\n\n/**\n * Normalize a recipient address.\n *\n * - `\"all\"` (any casing) is canonicalized to `'*'`.\n * - `\"@session\"` (any casing) is canonicalized to\n * `\"@session:<sessionId>\"`; callers must provide the sender's session id.\n * - Already-canonical `\"@session:<sessionId>\"` addresses are preserved.\n */\nexport function normalizeRecipient(to: string, sessionId?: string): string {\n const trimmed = to.trim();\n const normalized = trimmed.toLowerCase();\n if (normalized === 'all') return '*';\n if (normalized === '@session') return sessionRecipient(sessionId ?? '');\n return trimmed;\n}\n\nexport interface MailboxSendInput {\n /** Sender agent id. */\n from: string;\n /** Recipient agent id, '*' / \"all\" for project broadcast, or \"@session\" for the sender's session. */\n to: string;\n /** Message category. */\n type: MailboxMessageType;\n /** Restrict consumption to main/leader agents. Default: `all`. */\n audience?: MailboxAudience | undefined;\n /** Short subject line. */\n subject: string;\n /** Full message content. */\n body: string;\n /** Priority. Default: 'normal'. */\n priority?: 'low' | 'normal' | 'high' | undefined;\n /** If replying, the id of the parent message. */\n replyTo?: string | undefined;\n /** Task context for assign-type messages. */\n taskContext?: MailboxTaskContext | undefined;\n /** Sender session id. Required when `to` is the `\"@session\"` alias. */\n senderSessionId?: string | undefined;\n /**\n * Time-to-live in milliseconds. When set, the message's `expiresAt` is\n * computed as `now + ttlMs` at send time. The auto-compaction sweep\n * removes expired messages. Default: none (use compaction sweep default).\n */\n ttlMs?: number | undefined;\n}\n\n/**\n * Append-only ack record stored in the JSONL alongside messages.\n *\n * Instead of rewriting the entire mailbox file to mark a message as read or\n * completed, we append a small ack record. At read time, ack records are\n * folded into their target messages. The `__ack` discriminator distinguishes\n * ack records from regular messages.\n *\n * Compaction (autoCompact / purgeStale) folds these into the messages and\n * removes the ack lines from the file, keeping the file bounded.\n */\nexport interface AckRecord {\n /** Discriminator \u2014 always `true` to distinguish from MailboxMessage. */\n __ack: true;\n /** The message this ack applies to. */\n messageId: string;\n /** Agent acknowledging the message. */\n readerId: string;\n /** ISO8601 timestamp of the ack. */\n timestamp: string;\n /** Was the message read? */\n read: boolean;\n /** Was the message marked completed? */\n completed?: boolean | undefined;\n /** Who completed it (when completed === true). */\n completedBy?: string | undefined;\n /** Optional outcome summary. */\n outcome?: string | undefined;\n /**\n * Soft-delete or restore the target message.\n * - `true`: set `deletedAt`/`deletedBy` on the message\n * - `false`: clear `deletedAt`/`deletedBy` on the message\n * - `undefined`: not a delete/restore operation (backward-compat default)\n *\n * When `deleted` is `true`, `deletedBy` records who performed the delete.\n */\n deleted?: boolean | undefined;\n /** Who deleted the message (set when `deleted === true`). */\n deletedBy?: string | undefined;\n}\n\nexport interface MailboxAckInput {\n /** Message id to acknowledge. */\n messageId: string;\n /** Agent id of who is reading/acking. */\n readerId: string;\n /** Mark as read by this agent? Defaults to true if not specified. */\n read?: boolean | undefined;\n /** Mark as completed? */\n completed?: boolean | undefined;\n /** Optional outcome summary. */\n outcome?: string | undefined;\n}\n\n/**\n * Batch acknowledgment input \u2014 applies a batch of acks under a single file\n * lock + single file rewrite. Each entry has the same shape as\n * {@link MailboxAckInput} minus the per-batch defaults documented on\n * `ackMany`. Use this when an agent is acking several fresh messages at\n * once (the common case in the mailbox loop) \u2014 it collapses N full-file\n * rewrites into one.\n */\nexport interface MailboxAckBatchInput {\n /** Ack entries to apply. */\n acks: MailboxAckInput[];\n}\n\n// \u2500\u2500 Agent registration input \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface AgentRegistrationInput {\n agentId: string;\n sessionId: string;\n name: string;\n role?: string | undefined;\n pid?: number | undefined;\n source?: 'cli' | 'webui' | 'mcp' | 'acp' | 'http' | undefined;\n}\n\n// \u2500\u2500 Client (REPL/TUI/WebUI) registration \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type ClientSource = 'repl' | 'tui' | 'webui' | 'http';\n\nexport interface RegisteredClient {\n /** Unique client id. */\n clientId: string;\n /** Session/project context id. */\n sessionId: string;\n /** Human-readable name (e.g. \"TUI [main]\", \"WebUI [chrome]\"). */\n name: string;\n /** Client type. */\n source: ClientSource;\n /** ISO8601 \u2014 registered at. */\n registeredAt: string;\n /** ISO8601 \u2014 last heartbeat. */\n lastSeenAt: string;\n /** Which process. */\n pid: number;\n}\n\nexport interface ClientStatus {\n /** Client id. */\n clientId: string;\n /** Human-readable name. */\n name: string;\n /** Client type. */\n source: ClientSource;\n /** Session id. */\n sessionId: string;\n /** ISO8601 \u2014 last activity timestamp. */\n lastSeenAt: string;\n /** Whether this client is currently online (heartbeat within threshold). */\n online: boolean;\n /** Which process. */\n pid: number;\n}\n\nexport interface ClientRegistrationInput {\n clientId: string;\n sessionId: string;\n name: string;\n source: ClientSource;\n pid?: number | undefined;\n}\n\nexport interface ClientHeartbeatInput {\n clientId: string;\n /** Active session id for this client. When present, updates the registry entry. */\n sessionId?: string | undefined;\n}\n\n// \u2500\u2500 Agent heartbeat input \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface AgentHeartbeatInput {\n agentId: string;\n status?: RegisteredAgent['status'] | undefined;\n currentTool?: string | undefined;\n currentTask?: string | undefined;\n iterations?: number | undefined;\n toolCalls?: number | undefined;\n}\n\n// \u2500\u2500 Purge options & result \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface PurgeOptions {\n /**\n * Purge completed messages older than this many milliseconds.\n * Default: 1 day (86_400_000 ms)\n */\n completedMaxAgeMs?: number | undefined;\n /**\n * Purge incomplete messages older than this many milliseconds.\n * Default: 7 days (604_800_000 ms)\n */\n incompleteMaxAgeMs?: number | undefined;\n}\n\nexport interface PurgeResult {\n /** Messages removed because they were completed and too old. */\n completedPurged: number;\n /** Messages removed because they were incomplete and too old. */\n incompletePurged: number;\n /** Total messages removed. */\n totalPurged: number;\n /** Messages remaining in the mailbox after purge. */\n remaining: number;\n}\n\n// \u2500\u2500 Auto-compact options & result \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface AutoCompactOptions {\n /**\n * Remove messages read by ALL currently-online agents that are older\n * than this many milliseconds since the last read receipt was stamped.\n * Default: 10 minutes (AUTO_COMPACT_READ_MAX_AGE_MS).\n */\n readMaxAgeMs?: number | undefined;\n /**\n * Default TTL for messages without an explicit `expiresAt`. Messages\n * whose `timestamp` is older than `now - defaultTtlMs` are removed.\n * Default: 24 hours (AUTO_COMPACT_DEFAULT_TTL_MS).\n */\n defaultTtlMs?: number | undefined;\n /**\n * Per-message-type TTL overrides, consulted before `defaultTtlMs` for\n * messages with no explicit `expiresAt`. Keyed by `MailboxMessageType`.\n * Default: {@link AUTO_COMPACT_TYPE_TTL_MS} (transient `status` chatter\n * expires in 30 minutes instead of 24 hours).\n */\n typeTtlMs?: Readonly<Record<string, number>> | undefined;\n /**\n * Also run `purgeStale` logic in the same pass \u2014 purge completed\n * messages older than this many ms. Default: 1 day.\n */\n completedMaxAgeMs?: number | undefined;\n /**\n * Also run `purgeStale` logic in the same pass \u2014 purge incomplete\n * messages older than this many ms. Default: 7 days.\n */\n incompleteMaxAgeMs?: number | undefined;\n /**\n * Interval for the background auto-compact timer.\n * Default: 5 minutes (AUTO_COMPACT_INTERVAL_MS).\n */\n intervalMs?: number | undefined;\n /**\n * Also run `purgeStale` logic in the same pass (completed > 1 day,\n * incomplete > 7 days). Default: true.\n */\n includePurgeStale?: boolean | undefined;\n}\n\nexport interface AutoCompactResult {\n /** Messages removed because they were read by all online agents. */\n readByAllRemoved: number;\n /** Messages removed because their TTL expired (explicit or default). */\n expiredRemoved: number;\n /** Messages removed by the purgeStale pass (if enabled). */\n stalePurged: number;\n /** Total messages removed. */\n totalRemoved: number;\n /** Messages remaining in the mailbox after compaction. */\n remaining: number;\n}\n\n// \u2500\u2500 Mailbox interface \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface Mailbox {\n /** Send a message. Returns the created message. */\n send(input: MailboxSendInput): Promise<MailboxMessage>;\n\n /** Query messages matching criteria. */\n query(query: MailboxQuery): Promise<MailboxMessage[]>;\n\n /** Acknowledge a message (read/complete). Returns updated message. */\n ack(input: MailboxAckInput): Promise<MailboxMessage | null>;\n\n /**\n * Acknowledge many messages in one shot. Acquires the file lock once and\n * rewrites the message file once, regardless of how many acks are in the\n * batch. Returns the messages that were actually updated (messages whose\n * ids are not in the file are skipped silently).\n *\n * This is the preferred path when an agent has multiple fresh messages\n * to receipt at once \u2014 the per-message {@link ack} path does a full\n * read-modify-rewrite of the mailbox file for every call.\n */\n ackMany(input: MailboxAckBatchInput): Promise<MailboxMessage[]>;\n\n /**\n * Soft-delete a message. Sets `deletedAt` to the current timestamp\n * and records the acting agent in `deletedBy`. Reversible via\n * {@link restore}. The default `query()` filter hides the message\n * once `deletedAt` is set; pass `includeDeleted: true` to see the\n * trash.\n */\n softDelete(mailId: string, by: string): Promise<MailboxMessage | null>;\n\n /**\n * Undo a {@link softDelete}. Clears `deletedAt` and `deletedBy` on\n * the message. No-op (returns the message as-is) if the message is\n * not soft-deleted.\n */\n restore(mailId: string): Promise<MailboxMessage | null>;\n\n /** Get a snapshot of online/offline agents and their current tasks. */\n getAgentStatuses(): Promise<MailboxAgentStatus[]>;\n\n /**\n * Get only online agents (heartbeat within 60s).\n * Useful for \"who can I talk to right now?\" queries.\n */\n getOnlineAgents(): Promise<MailboxAgentStatus[]>;\n\n /**\n * Register an agent. Called once per agent on first mailbox use.\n * Subsequent calls are idempotent \u2014 they update lastSeenAt.\n */\n registerAgent(input: AgentRegistrationInput): Promise<void>;\n /** Remove an agent from the registry entirely. Called on session shutdown. */\n deregisterAgent(agentId: string): Promise<void>;\n\n /**\n * Update agent heartbeat and optional status fields.\n * Called periodically (every tool call / iteration).\n */\n heartbeat(input: AgentHeartbeatInput): Promise<void>;\n\n /**\n * Count unread messages for a specific agent.\n * Used for \"new mail\" notifications without pulling full message bodies.\n */\n unreadCount(forAgentId: string, sessionId?: string): Promise<number>;\n\n /** Close and flush any pending writes. */\n close(): Promise<void>;\n\n /**\n * Delete all messages from the mailbox file.\n * Agents and read receipts are preserved; only messages are cleared.\n */\n clearAll(): Promise<void>;\n\n /**\n * Purge orphaned and stale messages from the mailbox.\n *\n * Stale messages are:\n * - Completed messages older than `completedMaxAgeMs` (default: 1 day)\n * - Incomplete messages older than `incompleteMaxAgeMs` (default: 7 days)\n *\n * This does NOT touch agent registrations or client registry.\n */\n purgeStale(opts?: PurgeOptions): Promise<PurgeResult>;\n\n /**\n * Auto-compact: remove messages that are no longer needed.\n *\n * Two cleanup passes run in a single file rewrite:\n * 1. **Read-by-all**: Messages read by every currently-online agent,\n * older than `readMaxAgeMs` (default 10 min).\n * 2. **Expired**: Messages whose `expiresAt` is in the past, or whose\n * `timestamp` is older than `defaultTtlMs` (default 24h) when no\n * explicit `expiresAt` is set.\n *\n * Also runs `purgeStale` logic (completed > 1 day, incomplete > 7 days)\n * in the same pass to avoid a second rewrite.\n */\n autoCompact(opts?: AutoCompactOptions): Promise<AutoCompactResult>;\n\n /**\n * Start a background timer that periodically calls `autoCompact`.\n * Returns a dispose function that stops the timer. Idempotent \u2014\n * calling start twice replaces the prior timer.\n */\n startAutoCompactTimer(opts?: AutoCompactOptions): () => void;\n\n // \u2500\u2500 Client (REPL/TUI/WebUI) registry \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Register a client (REPL/TUI/WebUI). Called once per client on startup.\n * Subsequent calls are idempotent \u2014 they update lastSeenAt.\n */\n registerClient(input: ClientRegistrationInput): Promise<void>;\n\n /**\n * Update client heartbeat. Called periodically (every 15s for clients).\n */\n clientHeartbeat(input: ClientHeartbeatInput): Promise<void>;\n\n /** Remove a client immediately on clean shutdown. */\n deregisterClient(clientId: string): Promise<void>;\n\n /**\n * Get snapshot of online/offline clients and their last activity.\n */\n getClientStatuses(): Promise<ClientStatus[]>;\n\n /**\n * Explicitly purge stale clients from the registry.\n * Removes client entries whose lastSeenAt is older than CLIENT_STALE_MS.\n * Returns the number of entries purged.\n */\n purgeClients(): Promise<number>;\n}\n\nexport {\n expandMailboxCapabilities,\n hasMailboxCapability,\n MAILBOX_CAPABILITY_IMPLICATIONS,\n type MailboxActorContext,\n type MailboxAuthMode,\n type MailboxCapability,\n type MailboxPrincipalKind,\n} from './mailbox-auth-types.js';\n\n// \u2500\u2500 Recipient-scoped receipt state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Per-recipient delivery/action state for a single message.\n *\n * Keyed by actor ID. Each entry tracks when the actor read, completed,\n * or otherwise interacted with the message \u2014 independently of other actors.\n */\nexport interface MailboxRecipientState {\n /** Actor ID this state belongs to. */\n actorId: string;\n /** ISO8601 \u2014 when this actor first read the message. */\n readAt?: string | undefined;\n /** ISO8601 \u2014 when this actor completed the message. */\n completedAt?: string | undefined;\n /** Who recorded the completion (usually same as actorId). */\n completedBy?: string | undefined;\n /** Optional outcome summary recorded by this actor. */\n outcome?: string | undefined;\n}\n\n/**\n * V2 JSONL receipt record. Appended alongside messages and v1 ack records.\n *\n * Has an explicit `__mailboxReceipt: 2` discriminator so:\n * 1. The v2 reader folds these into per-actor `MailboxRecipientState`.\n * 2. A v1 reader ignores the unknown JSON line (no `__ack` field).\n *\n * Fold algebra (applied during materialization):\n * - Keyed by `(messageId, actorId)`.\n * - `read`: first-write-wins (earliest read timestamp is preserved).\n * - `completed`: monotonic upward (once `true`, cannot revert unless an\n * explicit reopen record with `completed: false` is appended).\n * - `outcome`: last-write-wins.\n * - Duplicate records (same messageId, actorId, timestamp): idempotent no-ops.\n */\nexport interface MailboxReceiptRecordV2 {\n /** Discriminator \u2014 always `2` to distinguish from messages and v1 acks. */\n __mailboxReceipt: 2;\n /** Target message this receipt applies to. */\n messageId: string;\n /** Actor this receipt belongs to. */\n actorId: string;\n /** ISO8601 \u2014 when the receipt event occurred. */\n timestamp: string;\n /** Was the message read by this actor? */\n read?: boolean | undefined;\n /** Was the message completed by this actor? */\n completed?: boolean | undefined;\n /** Optional outcome summary. */\n outcome?: string | undefined;\n}\n\n/**\n * Check if a parsed JSONL value is a v2 receipt record.\n * Validates the discriminator AND required structural fields.\n */\nexport function isMailboxReceiptRecordV2(value: unknown): value is MailboxReceiptRecordV2 {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const v = value as Record<string, unknown>;\n if (v['__mailboxReceipt'] !== 2) return false;\n if (typeof v['messageId'] !== 'string' || v['messageId'].length === 0) return false;\n if (typeof v['actorId'] !== 'string' || v['actorId'].length === 0) return false;\n if (typeof v['timestamp'] !== 'string' || v['timestamp'].length === 0) return false;\n // Validate optional fields when present \u2014 prevents malformed JSONL records\n // from entering typed receipt-folding code (e.g. completed:\"false\" truthy string).\n if ('read' in v && typeof v['read'] !== 'boolean') return false;\n if ('completed' in v && typeof v['completed'] !== 'boolean') return false;\n if ('outcome' in v && v['outcome'] !== undefined && typeof v['outcome'] !== 'string') return false;\n return true;\n}\n\n// \u2500\u2500 Message projections \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Materialized message with per-actor recipient state.\n *\n * This is the internal representation after folding all v1 acks and v2\n * receipt records. It carries both the legacy fields (for backward\n * compatibility) and the new actor-specific state map.\n *\n * `legacyGlobalCompletion` is set ONLY for historical v1 fan-out messages\n * that were globally completed. It is never set for new v2 writes.\n */\nexport interface MailboxMessageProjection extends MailboxMessage {\n /** Per-actor delivery/action state, keyed by actorId. */\n recipientState: Readonly<Record<string, MailboxRecipientState>>;\n /**\n * True ONLY for historical v1 fan-out messages that were globally completed\n * (completed before the v2 migration). These remain globally suppressed to\n * prevent upgrade re-delivery. New v2 writes NEVER set this.\n */\n legacyGlobalCompletion?: boolean | undefined;\n}\n\n/**\n * Self-facing message \u2014 what a specific actor sees.\n *\n * This does NOT extend `MailboxMessage` because self-facing responses must NOT\n * contain aggregate receipt metadata (`readBy`, `completedBy`, `completedAt`,\n * `outcome`) that would leak other actors' activity. Only actor-specific\n * derived fields are added on top of the non-sensitive message fields.\n */\nexport interface ActorMailboxMessage\n extends Omit<MailboxMessage, 'readBy' | 'completed' | 'completedBy' | 'completedAt' | 'outcome'> {\n /** Has this actor read the message? */\n readByMe: boolean;\n /** Has this actor completed the message? */\n completedByMe: boolean;\n /** Does this message require action from this actor? */\n actionRequiredForMe: boolean;\n /** This actor's outcome, if any. */\n myOutcome?: string | undefined;\n /**\n * True for historical v1 fan-out messages that were globally completed.\n * Lets the UI distinguish \"completed by me\" from \"completed globally\n * before migration.\"\n */\n legacyGlobalCompletion?: boolean | undefined;\n}\n\n/**\n * Derive `actionRequiredForMe` from the canonical type properties and actor state.\n *\n * Defined as:\n * `MAILBOX_TYPE_PROPERTIES[type].requiresAction && visible && !completedByMe && !deleted && !legacyGlobalCompletion`\n *\n * For historical legacy-global messages, `actionRequiredForMe` is always false\n * because the message is suppressed and should not re-enter any actor's flow.\n */\nexport function isActionRequiredForActor(\n message: Pick<MailboxMessage, 'type' | 'deletedAt' | 'completed'>,\n projection: Pick<ActorMailboxMessage, 'completedByMe' | 'legacyGlobalCompletion'>,\n): boolean {\n if (projection.legacyGlobalCompletion) return false;\n if (message.deletedAt !== undefined) return false;\n if (projection.completedByMe) return false;\n return MAILBOX_TYPE_PROPERTIES[message.type]?.requiresAction === true;\n}\n", "/**\n * V2 receipt record folding and message materialization.\n *\n * GM-P0.4: This module implements the per-actor receipt state materialization\n * that replaces the message-global `completed` boolean with actor-scoped\n * delivery state. It also implements the v1\u2192v2 migration classification rules.\n *\n * The key insight: v1 ack records (`__ack: true`) and v2 receipt records\n * (`__mailboxReceipt: 2`) coexist in the same JSONL file during migration.\n * This module folds BOTH into a unified `MailboxMessageProjection` that\n * carries per-actor `recipientState`.\n *\n * @module mailbox-receipt-folding\n */\n\nimport type {\n MailboxMessage,\n MailboxMessageProjection,\n MailboxRecipientState,\n MailboxReceiptRecordV2,\n} from './mailbox-types.js';\nimport { isMailboxReceiptRecordV2 } from './mailbox-types.js';\n\nexport type { MailboxMessageProjection };\n\n/**\n * Determine if a message's recipient is a fan-out form (broadcast, alias, or\n * session-scoped). Fan-out messages use `legacyGlobalCompletion` for v1 acks\n * because the original semantic was message-global.\n *\n * Heuristic: exact agent IDs are qualified with either `@` (session identity)\n * or `#` (process identity), matching `mailboxIdentityBase()`. A `to` value\n * without either delimiter is a bare base alias such as `leader` or `worker`\n * and therefore fans out. `*` and `@session:...` are explicit broadcasts.\n */\nexport function isFanOutRecipient(to: string): boolean {\n if (to === '*') return true;\n if (to.startsWith('@session:')) return true;\n // A bare base alias contains neither exact-recipient delimiter.\n return !to.includes('@') && !to.includes('#');\n}\n\n/**\n * Materialize messages with per-actor recipient state.\n *\n * Input: the raw parsed messages (already folded with v1 acks by\n * `parseMailboxLines()`), plus any v2 receipt records found in the file.\n *\n * Output: `MailboxMessageProjection[]` carrying:\n * - `recipientState`: per-actor delivery/action state\n * - `legacyGlobalCompletion`: true for historical v1 fan-out completions\n *\n * v1 completion classification:\n * - Direct exact-recipient message + completed v1 ack \u2192 actor-scoped for\n * that recipient. The `completed` boolean is projected from\n * `recipientState[recipient].completedAt !== undefined`.\n * - Fan-out message (broadcast/alias/session) + completed v1 ack \u2192\n * `legacyGlobalCompletion: true`. The message remains globally\n * suppressed; NO actor-scoped completion is created.\n *\n * v2 receipt folding:\n * - Keyed by `(messageId, actorId)`.\n * - `read`: first-write-wins (earliest timestamp preserved).\n * - `completed`: monotonic upward (once true, cannot revert unless an\n * explicit `completed: false` record is appended).\n * - `outcome`: last-write-wins.\n * - Duplicate records (same messageId, actorId, timestamp): idempotent.\n */\nexport function materializeMessages(\n messages: readonly MailboxMessage[],\n v2Receipts: readonly MailboxReceiptRecordV2[],\n): MailboxMessageProjection[] {\n // Index v2 receipts by messageId for efficient lookup.\n const receiptsByMessage = new Map<string, MailboxReceiptRecordV2[]>();\n for (const receipt of v2Receipts) {\n const list = receiptsByMessage.get(receipt.messageId);\n if (list) list.push(receipt);\n else receiptsByMessage.set(receipt.messageId, [receipt]);\n }\n\n return messages.map((msg) => materializeMessage(msg, receiptsByMessage.get(msg.id) ?? []));\n}\n\n/**\n * Materialize a single message against the receipts that target it.\n *\n * Split out of {@link materializeMessages} so the incremental read path\n * (see `mailbox-parse-state.ts`) can re-fold exactly the messages an appended\n * chunk touched instead of re-projecting the entire file. Callers MUST pass\n * the message's COMPLETE receipt list, not just the newly appended ones \u2014\n * `foldRecipientState` sorts by timestamp and `classifyLegacyCompletion`\n * scans for any `completed: true`, so a partial list would diverge from a\n * full parse.\n */\nexport function materializeMessage(\n msg: MailboxMessage,\n msgReceipts: readonly MailboxReceiptRecordV2[],\n): MailboxMessageProjection {\n const recipientState = foldRecipientState(msg, msgReceipts);\n const legacyGlobalCompletion = classifyLegacyCompletion(msg, msgReceipts);\n\n return {\n ...msg,\n recipientState,\n ...(legacyGlobalCompletion ? { legacyGlobalCompletion: true } : {}),\n };\n}\n\n/**\n * Fold v2 receipt records into a per-actor `recipientState` map for a\n * single message. Also seeds from v1 `readBy` entries (which are\n * per-recipient read timestamps from the existing schema).\n *\n * Fold algebra:\n * - `readAt`: first-write-wins (earliest read timestamp is preserved).\n * - `completedAt`: monotonic upward (once set, cannot be cleared by\n * a new receipt unless `completed: false` is explicitly set, which\n * acts as a reopen).\n * - `outcome`: last-write-wins.\n */\nfunction foldRecipientState(\n msg: MailboxMessage,\n v2Receipts: readonly MailboxReceiptRecordV2[],\n): Record<string, MailboxRecipientState> {\n const state: Record<string, MailboxRecipientState> = {};\n\n // Seed from v1 readBy entries (these are already per-recipient read timestamps).\n for (const [actorId, readAt] of Object.entries(msg.readBy)) {\n state[actorId] = { actorId, readAt };\n }\n\n // Seed from v1 completion (only for direct messages \u2014 fan-out uses legacyGlobalCompletion).\n if (msg.completed && msg.completedBy && !isFanOutRecipient(msg.to)) {\n const existing = state[msg.completedBy] ?? { actorId: msg.completedBy };\n state[msg.completedBy] = {\n ...existing,\n completedAt: msg.completedAt ?? msg.timestamp,\n completedBy: msg.completedBy,\n ...(msg.outcome !== undefined ? { outcome: msg.outcome } : {}),\n };\n }\n\n // Fold v2 receipt records.\n // Sort by timestamp to ensure deterministic fold order. ECMAScript's stable\n // sort preserves persisted file order when timestamps compare equal.\n const sorted = [...v2Receipts].sort((a, b) => a.timestamp.localeCompare(b.timestamp));\n\n for (const receipt of sorted) {\n const actorId = receipt.actorId;\n const existing = state[actorId] ?? { actorId };\n\n // readAt: first-write-wins.\n const readAt = existing.readAt ?? (receipt.read === true ? receipt.timestamp : undefined);\n\n // completedAt: monotonic upward. Can be cleared by explicit completed: false (reopen).\n let completedAt = existing.completedAt;\n let completedBy = existing.completedBy;\n if (receipt.completed === true) {\n completedAt = receipt.timestamp;\n completedBy = actorId;\n } else if (receipt.completed === false) {\n completedAt = undefined;\n completedBy = undefined;\n }\n\n // outcome: last-write-wins.\n const outcome = receipt.outcome !== undefined ? receipt.outcome : existing.outcome;\n\n state[actorId] = { actorId, readAt, completedAt, completedBy, outcome };\n }\n\n return state;\n}\n\n/**\n * Classify whether a v1 message's completion should be treated as\n * `legacyGlobalCompletion`.\n *\n * Rules (from SDD R3):\n * - Fan-out message (broadcast/alias/session) with `completed: true`\n * \u2192 `legacyGlobalCompletion: true` regardless of `readerId`.\n * - Direct exact-recipient message with `completed: true`\n * \u2192 NOT legacy (it's actor-scoped, handled in foldRecipientState).\n */\nfunction classifyLegacyCompletion(msg: MailboxMessage, v2Receipts: readonly MailboxReceiptRecordV2[]): boolean {\n if (!msg.completed) return false;\n // Suppress legacy-global classification only when v2 data carries\n // unambiguous actor-scoped completion provenance \u2014 at least one v2\n // receipt with completed:true. A read-only v2 receipt must NOT\n // suppress legacy completion (GM-P0.4 R3).\n if (v2Receipts.some((r) => r.completed === true)) return false;\n return isFanOutRecipient(msg.to);\n}\n\n/**\n * Serialize a v2 receipt record to a JSONL line.\n */\nexport function serializeReceiptRecordV2(record: MailboxReceiptRecordV2): string {\n return JSON.stringify(record) + '\\n';\n}\n\n/**\n * Extract v2 receipt records from a set of parsed JSONL lines.\n * Messages and v1 ack records are ignored.\n *\n * This is used by the read path to separate receipts from messages\n * before materialization.\n *\n * @param parsed - Array of parsed JSON values from the JSONL file.\n * @returns Only the values that pass `isMailboxReceiptRecordV2`.\n */\nexport function extractV2Receipts(parsed: readonly unknown[]): MailboxReceiptRecordV2[] {\n const receipts: MailboxReceiptRecordV2[] = [];\n for (const item of parsed) {\n if (isMailboxReceiptRecordV2(item)) {\n receipts.push(item);\n }\n }\n return receipts;\n}\n\n/**\n * Build a v2 receipt record from an ack operation.\n * Used when folding legacy v1 ack records during the one-shot import.\n */\nexport function buildReceiptRecordV2(\n messageId: string,\n actorId: string,\n timestamp: string,\n opts: { read?: boolean; completed?: boolean; outcome?: string },\n): MailboxReceiptRecordV2 {\n const record: MailboxReceiptRecordV2 = {\n __mailboxReceipt: 2,\n messageId,\n actorId,\n timestamp,\n };\n if (opts.read !== undefined) record.read = opts.read;\n if (opts.completed !== undefined) record.completed = opts.completed;\n if (opts.outcome !== undefined) record.outcome = opts.outcome;\n return record;\n}\n", "import type {\n MailboxAgentStatus,\n MailboxMessage,\n MailboxMessageProjection,\n MailboxRecipientState,\n} from './mailbox-types.js';\nimport { isMailboxMessageVisibleTo, mailboxIdentityBase } from './mailbox-types.js';\n\nexport interface MailboxRetentionState {\n completed: boolean;\n completedAt?: string | undefined;\n}\n\n/**\n * Resolve whether retention may treat a message as completed.\n *\n * Historical fan-out completion remains global. New v2 fan-out completion is\n * eligible for the short completed TTL only when every currently relevant\n * recipient has an actor-scoped completion receipt. Otherwise the message\n * stays on the incomplete retention path.\n */\nexport function resolveMailboxRetentionState(\n message: MailboxMessage,\n agentStatuses: readonly MailboxAgentStatus[] | undefined,\n): MailboxRetentionState {\n const projection = message as MailboxMessageProjection;\n if (projection.legacyGlobalCompletion) {\n return { completed: true, completedAt: message.completedAt ?? message.timestamp };\n }\n\n const recipientState = projection.recipientState;\n if (recipientState === undefined) {\n return message.completed\n ? { completed: true, completedAt: message.completedAt ?? message.timestamp }\n : { completed: false };\n }\n\n const relevantRecipients = resolveRelevantRecipients(message, recipientState, agentStatuses);\n if (relevantRecipients.length === 0) return { completed: false };\n\n const completionTimes: string[] = [];\n for (const actorId of relevantRecipients) {\n const completedAt = recipientState[actorId]?.completedAt;\n if (completedAt === undefined) return { completed: false };\n completionTimes.push(completedAt);\n }\n\n return {\n completed: true,\n // Retention starts only after the last intended recipient completed.\n completedAt: completionTimes.reduce((latest, time) => (time > latest ? time : latest)),\n };\n}\n\n/**\n * Project a stored message's completion state for a project-wide or\n * actor-scoped query without mutating the authoritative record.\n */\nexport function projectMailboxCompletion(\n message: MailboxMessage,\n actorId: string | undefined,\n agentStatuses: readonly MailboxAgentStatus[] | undefined,\n): MailboxMessageProjection {\n const projection = message as MailboxMessageProjection;\n let state: MailboxRetentionState;\n if (actorId === undefined) {\n state = resolveMailboxRetentionState(message, agentStatuses);\n } else if (projection.legacyGlobalCompletion) {\n state = { completed: true, completedAt: message.completedAt ?? message.timestamp };\n } else if (projection.recipientState !== undefined) {\n const completedAt = projection.recipientState[actorId]?.completedAt;\n state =\n completedAt === undefined ? { completed: false } : { completed: true, completedAt };\n } else {\n state = message.completed\n ? { completed: true, completedAt: message.completedAt ?? message.timestamp }\n : { completed: false };\n }\n\n const result: MailboxMessageProjection = {\n ...projection,\n completed: state.completed,\n readBy: { ...message.readBy },\n };\n if (state.completedAt === undefined) delete result.completedAt;\n else result.completedAt = state.completedAt;\n return result;\n}\n\nfunction resolveRelevantRecipients(\n message: MailboxMessage,\n recipientState: Readonly<Record<string, MailboxRecipientState>>,\n agentStatuses: readonly MailboxAgentStatus[] | undefined,\n): string[] {\n const statuses = agentStatuses ?? [];\n const receiptActors = Object.keys(recipientState);\n if (message.to === '*') {\n if (statuses.length === 0) return [];\n const registeredRecipients = statuses\n .filter((status) => isMailboxMessageVisibleTo(message, status.agentId, status.role))\n .map((status) => status.agentId);\n // Include receipt actors even after they fall out of the live registry;\n // otherwise a later registry snapshot can forget an incomplete recipient\n // and move a fan-out message onto the short completed TTL.\n return [...new Set([...registeredRecipients, ...receiptActors])];\n }\n\n if (message.to.startsWith('@session:')) {\n if (statuses.length === 0) return [];\n const sessionId = message.to.slice('@session:'.length);\n const registeredRecipients = statuses\n .filter(\n (status) =>\n status.sessionId === sessionId &&\n isMailboxMessageVisibleTo(message, status.agentId, status.role),\n )\n .map((status) => status.agentId);\n return [...new Set([...registeredRecipients, ...receiptActors])];\n }\n\n if (message.to.includes('@')) return [message.to];\n\n if (statuses.length === 0) return [];\n\n const aliasRecipients = statuses\n .filter(\n (status) =>\n (status.role?.toLowerCase() === message.to.toLowerCase() ||\n mailboxIdentityBase(status.agentId) === message.to.toLowerCase()) &&\n isMailboxMessageVisibleTo(message, status.agentId, status.role),\n )\n .map((status) => status.agentId);\n return [...new Set([...aliasRecipients, ...receiptActors])];\n}\n", "import type {\n ClientStatus,\n MailboxAgentStatus,\n RegisteredAgent,\n RegisteredClient,\n} from './mailbox-types.js';\n\nexport function mapRegisteredAgentsToStatuses(\n registry: ReadonlyMap<string, RegisteredAgent>,\n now: number,\n staleMs: number,\n): MailboxAgentStatus[] {\n return Array.from(registry.values())\n .map((agent) => ({\n agentId: agent.agentId,\n name: agent.name,\n role: agent.role,\n sessionId: agent.sessionId,\n status: agent.status,\n currentTool: agent.currentTool,\n currentTask: agent.currentTask,\n iterations: agent.iterations,\n toolCalls: agent.toolCalls,\n lastActivityAt: agent.lastSeenAt,\n lastSeenAt: agent.lastSeenAt,\n online: now - new Date(agent.lastSeenAt).getTime() < staleMs,\n pid: agent.pid,\n source: agent.source,\n }))\n .sort((a, b) => b.lastSeenAt.localeCompare(a.lastSeenAt));\n}\n\nexport function mapRegisteredClientsToStatuses(\n registry: ReadonlyMap<string, RegisteredClient>,\n now: number,\n staleMs: number,\n): ClientStatus[] {\n return Array.from(registry.values())\n .map((client) => ({\n clientId: client.clientId,\n name: client.name,\n source: client.source,\n sessionId: client.sessionId,\n lastSeenAt: client.lastSeenAt,\n online: now - new Date(client.lastSeenAt).getTime() < staleMs,\n pid: client.pid,\n }))\n .sort((a, b) => b.lastSeenAt.localeCompare(a.lastSeenAt));\n}\n", "import type {\n AckRecord,\n MailboxAudience,\n MailboxMessage,\n MailboxMessageType,\n MailboxTaskContext,\n ReadReceipts,\n} from './mailbox-types.js';\nimport { LINE_SEPARATOR } from './mailbox-constants.js';\nimport { normalizeRecipient, validateSendType } from './mailbox-types.js';\n\nconst MESSAGE_TYPES = new Set<MailboxMessageType>([\n 'note',\n 'ask',\n 'assign',\n 'steer',\n 'btw',\n 'broadcast',\n 'status',\n 'result',\n 'review',\n 'control',\n]);\n\nconst PRIORITIES = new Set<MailboxMessage['priority']>(['low', 'normal', 'high']);\nconst AUDIENCES = new Set<MailboxAudience>(['all', 'leaders']);\nconst TASK_STATUSES = new Set([\n 'pending',\n 'in_progress',\n 'completed',\n 'failed',\n 'idle',\n 'running',\n 'streaming',\n 'waiting_user',\n 'error',\n 'offline',\n 'busy',\n]);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction requiredString(record: Record<string, unknown>, key: string): string {\n const value = record[key];\n if (typeof value !== 'string') {\n throw new TypeError(`mailbox message field \"${key}\" must be a string`);\n }\n return value;\n}\n\nfunction optionalString(record: Record<string, unknown>, key: string): Record<string, string> {\n const value = record[key];\n if (value === undefined) return {};\n if (typeof value !== 'string') {\n throw new TypeError(`mailbox message field \"${key}\" must be a string when present`);\n }\n return { [key]: value };\n}\n\nfunction parseMessageType(value: unknown): MailboxMessageType {\n if (value === 'info') return 'note';\n if (value === 'task') return 'assign';\n if (typeof value === 'string' && MESSAGE_TYPES.has(value as MailboxMessageType)) {\n return value as MailboxMessageType;\n }\n throw new TypeError('mailbox message field \"type\" is invalid');\n}\n\n/** Normalize message types emitted by pre-union mailbox builds. */\nexport function normalizeMailboxMessageType(value: unknown): MailboxMessageType {\n return parseMessageType(value);\n}\n\n/**\n * Resolve the message type for a SEND operation, applying default-type logic\n * and cross-field validation.\n *\n * ** Default-type rules ** (mirror the `mail_send` tool's logic):\n * - When `type` is explicitly provided, use it directly.\n * - When `type` is omitted AND the resolved `to` is `\"*\"` or starts with\n * `\"@session:\"`, the default is `\"broadcast\"`.\n * - Otherwise (omitted, non-broadcast target), the default is `\"note\"`.\n *\n * **Send-side validation** (from `validateSendType`):\n * - `control` is rejected \u2014 it is reserved for runtime use.\n * - `assign` and `steer` with `to=\"*\"` are rejected \u2014 these types require a\n * specific recipient.\n *\n * @returns The resolved type (explicit or defaulted).\n * @throws {TypeError} When the type is reserved or the (type, to) pair is\n * semantically invalid.\n */\nexport function resolveSendType(\n type: MailboxMessageType | undefined,\n to: string,\n): MailboxMessageType {\n // Normalize recipient aliases (\"all\" \u2192 \"*\", \"@session\" \u2192 \"@session:<id>\")\n // BEFORE default-type selection and cross-field validation, so every\n // caller (mail_send, mailbox tool, HTTP bridge) gets consistent behavior\n // even when they forget to normalize beforehand.\n const normalizedTo = normalizeRecipient(to);\n const resolved: MailboxMessageType =\n type ?? (normalizedTo === '*' || normalizedTo.startsWith('@session:') ? 'broadcast' : 'note');\n // Validate the resolved type against the CANONICAL recipient \u2014 after\n // normalization \u2014 so \"all\" with type \"assign\" is correctly rejected\n // as a multi-recipient target.\n validateSendType(resolved, normalizedTo);\n return resolved;\n}\n\n/**\n * Resolve the message type for a SEND, returning a descriptive error instead\n * of throwing. Convenience wrapper for use in tool handlers where a thrown\n * TypeError would be awkward to catch.\n *\n * Returns `{ ok: true, type }` on success, or `{ ok: false, error }` when\n * the (type, to) pair is invalid.\n */\nexport function resolveSendTypeSafe(\n type: MailboxMessageType | undefined,\n to: string,\n): { ok: true; type: MailboxMessageType } | { ok: false; error: string } {\n try {\n return { ok: true, type: resolveSendType(type, to) };\n } catch (err) {\n return { ok: false, error: (err as Error).message };\n }\n}\n\nfunction parsePriority(value: unknown): MailboxMessage['priority'] {\n if (typeof value === 'string' && PRIORITIES.has(value as MailboxMessage['priority'])) {\n return value as MailboxMessage['priority'];\n }\n // Older callers were intentionally tolerant here and ranked unknown values\n // as normal. Normalize rather than dropping an otherwise valid message.\n if (typeof value === 'string') return 'normal';\n throw new TypeError('mailbox message field \"priority\" must be a string');\n}\n\nfunction parseAudience(value: unknown): MailboxAudience | undefined {\n if (value === undefined || value === 'all') return undefined;\n if (typeof value === 'string' && AUDIENCES.has(value as MailboxAudience)) {\n return value as MailboxAudience;\n }\n throw new TypeError('mailbox message field \"audience\" is invalid');\n}\n\nfunction parseReadReceipts(record: Record<string, unknown>, to: string): ReadReceipts {\n const value = record['readBy'];\n if (value === undefined) {\n const legacyReadAt = record['readAt'];\n return record['read'] === true && typeof legacyReadAt === 'string'\n ? { [to || 'unknown']: legacyReadAt }\n : {};\n }\n if (!isRecord(value)) {\n throw new TypeError('mailbox message field \"readBy\" must be an object');\n }\n\n const receipts: ReadReceipts = {};\n for (const [agentId, timestamp] of Object.entries(value)) {\n if (typeof timestamp !== 'string') {\n throw new TypeError('mailbox message read receipt timestamps must be strings');\n }\n receipts[agentId] = timestamp;\n }\n return receipts;\n}\n\nfunction parseTaskContext(value: unknown): MailboxTaskContext | undefined {\n if (value === undefined) return undefined;\n if (!isRecord(value)) {\n throw new TypeError('mailbox message field \"taskContext\" must be an object');\n }\n\n const status = value['status'];\n if (\n status !== undefined &&\n (typeof status !== 'string' ||\n !TASK_STATUSES.has(status as NonNullable<MailboxTaskContext['status']>))\n ) {\n throw new TypeError('mailbox message taskContext status is invalid');\n }\n\n return {\n ...optionalString(value, 'agentRole'),\n ...optionalString(value, 'agentName'),\n ...optionalString(value, 'taskId'),\n ...(status === undefined\n ? {}\n : { status: status as NonNullable<MailboxTaskContext['status']> }),\n };\n}\n\n/** Parse, migrate, and structurally validate one persisted mailbox message. */\nexport function parseMailboxMessage(value: unknown): MailboxMessage {\n if (!isRecord(value)) throw new TypeError('mailbox message must be an object');\n\n const to = value['to'] === undefined ? '' : requiredString(value, 'to');\n const completed = value['completed'];\n if (typeof completed !== 'boolean') {\n throw new TypeError('mailbox message field \"completed\" must be a boolean');\n }\n\n const taskContext = parseTaskContext(value['taskContext']);\n const audience = parseAudience(value['audience']);\n return {\n id: requiredString(value, 'id'),\n from: requiredString(value, 'from'),\n to,\n type: parseMessageType(value['type']),\n ...(audience === undefined ? {} : { audience }),\n subject: requiredString(value, 'subject'),\n body: requiredString(value, 'body'),\n priority: parsePriority(value['priority']),\n readBy: parseReadReceipts(value, to),\n completed,\n timestamp: requiredString(value, 'timestamp'),\n ...optionalString(value, 'completedBy'),\n ...optionalString(value, 'outcome'),\n ...optionalString(value, 'completedAt'),\n ...optionalString(value, 'deletedAt'),\n ...optionalString(value, 'deletedBy'),\n ...optionalString(value, 'replyTo'),\n ...optionalString(value, 'senderSessionId'),\n ...optionalString(value, 'expiresAt'),\n ...(taskContext === undefined ? {} : { taskContext }),\n };\n}\n\n/** Parse one JSONL line and validate the decoded mailbox message. */\nexport function parseMailboxMessageLine(line: string): MailboxMessage {\n return parseMailboxMessage(JSON.parse(line) as unknown);\n}\n\n// \u2500\u2500 Ack record helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Check if a parsed JSONL value is an append-only ack record (not a message).\n * Ack records carry a `__ack: true` discriminator.\n */\nexport function isAckRecord(value: unknown): value is AckRecord {\n return (\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n (value as Record<string, unknown>)['__ack'] === true\n );\n}\n\n/**\n * Parse one JSONL line, returning either a MailboxMessage or an AckRecord.\n * Returns null when the line is neither (corrupt/malformed).\n */\nexport function parseMailboxLine(line: string): MailboxMessage | AckRecord | null {\n try {\n const parsed = JSON.parse(line) as unknown;\n if (isAckRecord(parsed)) return parsed;\n return parseMailboxMessage(parsed);\n } catch {\n return null;\n }\n}\n\n/** Parse a JSONL mailbox body into messages, applying append-only ack records. */\nexport function parseMailboxLines(raw: string): MailboxMessage[] {\n const lines = raw.split(LINE_SEPARATOR).filter((line) => line.trim().length > 0);\n const messages: MailboxMessage[] = [];\n const acks: AckRecord[] = [];\n for (const line of lines) {\n const parsed = parseMailboxLine(line);\n if (isAckRecord(parsed)) {\n acks.push(parsed);\n } else if (parsed !== null) {\n messages.push(parsed);\n }\n }\n for (const ack of acks) {\n const target = messages.find((message) => message.id === ack.messageId);\n if (target) applyAckToMessage(target, ack);\n }\n return messages;\n}\n\n/**\n * Apply an ack record's effects to a MailboxMessage in-place.\n * This mutates the message object (readBy, completed, completedBy, completedAt,\n * outcome, deletedAt, deletedBy).\n */\nexport function applyAckToMessage(msg: MailboxMessage, ack: AckRecord): void {\n if (ack.read && !(ack.readerId in msg.readBy)) {\n msg.readBy[ack.readerId] = ack.timestamp;\n }\n if (ack.completed && !msg.completed) {\n msg.completed = true;\n msg.completedBy = ack.completedBy ?? ack.readerId;\n msg.completedAt = ack.timestamp;\n }\n if (ack.outcome !== undefined && msg.outcome !== ack.outcome) {\n msg.outcome = ack.outcome;\n }\n // Soft-delete: set deletedAt/deletedBy.\n if (ack.deleted === true) {\n msg.deletedAt = ack.timestamp;\n msg.deletedBy = ack.deletedBy ?? ack.readerId;\n }\n // Restore: clear deletedAt/deletedBy.\n if (ack.deleted === false) {\n delete msg.deletedAt;\n delete msg.deletedBy;\n }\n}\n\n/**\n * Serialize an ack record to a JSONL line.\n */\nexport function serializeAckRecord(ack: AckRecord): string {\n return JSON.stringify(ack) + '\\n';\n}\n\n/**\n * Serialize a MailboxMessage to a JSONL line.\n *\n * Strips any extra fields added by a projection (recipientState,\n * legacyGlobalCompletion) so compaction rewrites produce clean\n * v1-parseable lines. V2 receipt records are preserved as separate\n * lines \u2014 they are NOT embedded in the message object.\n */\nexport function serializeMailboxMessage(msg: MailboxMessage): string {\n const obj: Record<string, unknown> = {\n id: msg.id,\n from: msg.from,\n to: msg.to,\n type: msg.type,\n subject: msg.subject,\n body: msg.body,\n priority: msg.priority,\n readBy: msg.readBy,\n completed: msg.completed,\n timestamp: msg.timestamp,\n };\n if (msg.audience !== undefined && msg.audience !== 'all') obj.audience = msg.audience;\n if (msg.completedBy !== undefined) obj.completedBy = msg.completedBy;\n if (msg.outcome !== undefined) obj.outcome = msg.outcome;\n if (msg.completedAt !== undefined) obj.completedAt = msg.completedAt;\n if (msg.deletedAt !== undefined) obj.deletedAt = msg.deletedAt;\n if (msg.deletedBy !== undefined) obj.deletedBy = msg.deletedBy;\n if (msg.replyTo !== undefined) obj.replyTo = msg.replyTo;\n if (msg.senderSessionId !== undefined) obj.senderSessionId = msg.senderSessionId;\n if (msg.expiresAt !== undefined) obj.expiresAt = msg.expiresAt;\n if (msg.taskContext !== undefined) obj.taskContext = msg.taskContext;\n return JSON.stringify(obj) + '\\n';\n}\n", "/**\n * Retention sweeps over the mailbox message table: the age-based `purgeStale`\n * and the richer `autoCompact` (expiry + read-by-all + stale).\n *\n * Split out of `sqlite-mailbox.ts`. Both walk the materialized message\n * projections rather than SQL predicates, because retention state is derived\n * from per-recipient receipts plus live agent status \u2014 see\n * `resolveMailboxRetentionState`.\n *\n * @module coordination/sqlite-mailbox-compaction\n */\nimport {\n AUTO_COMPACT_DEFAULT_TTL_MS,\n AUTO_COMPACT_READ_MAX_AGE_MS,\n AUTO_COMPACT_TYPE_TTL_MS,\n} from './mailbox-constants.js';\nimport { resolveMailboxRetentionState } from './mailbox-retention-state.js';\nimport type {\n AutoCompactOptions,\n AutoCompactResult,\n MailboxAgentStatus,\n MailboxMessageProjection,\n PurgeOptions,\n PurgeResult,\n} from './mailbox-types.js';\nimport { isMailboxMessageVisibleTo } from './mailbox-types.js';\n\n/** The store operations a sweep needs. */\nexport interface CompactionContext {\n getAgentStatuses: () => Promise<MailboxAgentStatus[]>;\n readMessages: () => MailboxMessageProjection[];\n deleteMessages: (ids: readonly string[]) => void;\n}\n\nexport async function purgeStale(\n ctx: CompactionContext,\n options?: PurgeOptions,\n): Promise<PurgeResult> {\n const completedMaxAgeMs = options?.completedMaxAgeMs ?? 86_400_000;\n const incompleteMaxAgeMs = options?.incompleteMaxAgeMs ?? 604_800_000;\n const statuses = await ctx.getAgentStatuses();\n const now = Date.now();\n let completedPurged = 0;\n let incompletePurged = 0;\n const ids: string[] = [];\n const messages = ctx.readMessages();\n for (const message of messages) {\n const retention = resolveMailboxRetentionState(message, statuses);\n const messageTime = new Date(message.timestamp).getTime();\n const completionTime = new Date(retention.completedAt ?? 0).getTime();\n if (retention.completed && completionTime < now - completedMaxAgeMs) {\n completedPurged++;\n ids.push(message.id);\n } else if (!retention.completed && messageTime < now - incompleteMaxAgeMs) {\n incompletePurged++;\n ids.push(message.id);\n }\n }\n ctx.deleteMessages(ids);\n return {\n completedPurged,\n incompletePurged,\n totalPurged: ids.length,\n remaining: messages.length - ids.length,\n };\n}\n\nexport async function autoCompact(\n ctx: CompactionContext,\n options?: AutoCompactOptions,\n): Promise<AutoCompactResult> {\n const readMaxAgeMs = options?.readMaxAgeMs ?? AUTO_COMPACT_READ_MAX_AGE_MS;\n const defaultTtlMs = options?.defaultTtlMs ?? AUTO_COMPACT_DEFAULT_TTL_MS;\n const typeTtlMs = options?.typeTtlMs ?? AUTO_COMPACT_TYPE_TTL_MS;\n const completedMaxAgeMs = options?.completedMaxAgeMs ?? 86_400_000;\n const incompleteMaxAgeMs = options?.incompleteMaxAgeMs ?? 604_800_000;\n const statuses = await ctx.getAgentStatuses();\n const online = statuses.filter((status) => status.online);\n const now = Date.now();\n let readByAllRemoved = 0;\n let expiredRemoved = 0;\n let stalePurged = 0;\n const ids: string[] = [];\n const messages = ctx.readMessages();\n\n for (const message of messages) {\n const messageTime = new Date(message.timestamp).getTime();\n const expiry =\n message.expiresAt !== undefined\n ? new Date(message.expiresAt).getTime()\n : messageTime + (typeTtlMs[message.type] ?? defaultTtlMs);\n if (expiry < now) {\n expiredRemoved++;\n ids.push(message.id);\n continue;\n }\n\n const retention = resolveMailboxRetentionState(message, statuses);\n const eligible = online.filter((status) =>\n isMailboxMessageVisibleTo(message, status.agentId, status.role),\n );\n if (!retention.completed && eligible.length > 0) {\n const readByAll = eligible.every((status) => status.agentId in message.readBy);\n const latestRead = Math.max(\n ...eligible.map((status) => new Date(message.readBy[status.agentId] ?? 0).getTime()),\n );\n if (readByAll && latestRead < now - readMaxAgeMs) {\n readByAllRemoved++;\n ids.push(message.id);\n continue;\n }\n }\n\n const completionTime = new Date(retention.completedAt ?? 0).getTime();\n if (\n (retention.completed && completionTime < now - completedMaxAgeMs) ||\n (!retention.completed && messageTime < now - incompleteMaxAgeMs)\n ) {\n stalePurged++;\n ids.push(message.id);\n }\n }\n\n ctx.deleteMessages(ids);\n return {\n readByAllRemoved,\n expiredRemoved,\n stalePurged,\n totalRemoved: ids.length,\n remaining: messages.length - ids.length,\n };\n}\n", "/**\n * Mailbox credential lifecycle and storage.\n *\n * GM-P0.6: opaque per-principal credential issuance, rotation, revocation,\n * verification and audit. Credentials are stored as keyed hashes so a store\n * leak does not expose reusable tokens.\n *\n * Types and policy only. The storage half used to live here as\n * `JsonlCredentialStore` over `_mailbox_credentials.json`; credentials now\n * live in `_mailbox.sqlite` behind the project owner, so the only thing that\n * still reads the old file is `SqliteMailbox.migrateLegacyCredentials()` \u2014\n * hence `CREDENTIAL_STORE_FILE` and `resolveCredentialStorePath` staying.\n *\n * @module mailbox-credential-store\n */\n\nimport * as crypto from 'node:crypto';\nimport * as path from 'node:path';\nimport type { MailboxCapability } from './mailbox-types.js';\n\n// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type CredentialStatus = 'active' | 'expired' | 'revoked' | 'rotated_out';\n\nexport interface MailboxCredential {\n /** Public identifier for this credential. */\n credentialId: string;\n /** Keyed hash of the secret (HMAC-SHA-256 verifier). Never the raw token. */\n verifier: string;\n /** Algorithm used for the verifier. */\n verifierAlgorithm: 'hmac-sha256';\n /** Principal identity this credential authorizes. */\n principalId: string;\n /** Project this credential is bound to. */\n projectId?: string | undefined;\n /** Capabilities granted to this credential. */\n capabilities: MailboxCapability[];\n /** Credential kind. */\n kind: 'agent' | 'operator' | 'service';\n /** ISO8601 \u2014 when this credential was issued. */\n issuedAt: string;\n /** ISO8601 \u2014 when this credential expires. */\n expiresAt: string;\n /** Optional ISO8601 \u2014 not valid before this time. */\n notBefore?: string | undefined;\n /** Current status. */\n status: CredentialStatus;\n /** ISO8601 \u2014 last status change. */\n statusChangedAt: string;\n /** Reason for the current status. */\n statusReason?: string | undefined;\n /** Previous credential ID this one supersedes. */\n supersedes?: string | undefined;\n /** ISO8601 \u2014 rotated credentials remain valid until this overlap expires. */\n rotationValidUntil?: string | undefined;\n /** Auditor: session/agent that performed the last mutation. */\n lastModifiedBy?: string | undefined;\n}\n\nexport interface CredentialStoreEntry {\n credential: MailboxCredential;\n /** Auditor: session/agent that performed the last mutation. */\n lastModifiedBy?: string | undefined;\n}\n\nexport interface IssueCredentialOptions {\n principalId: string;\n projectId?: string | undefined;\n kind: 'agent' | 'operator' | 'service';\n capabilities: MailboxCapability[];\n ttlMs: number;\n notBefore?: Date | undefined;\n supersedes?: string | undefined;\n issuedBy?: string | undefined;\n}\n\nexport interface CredentialValidation {\n valid: boolean;\n credential?: MailboxCredential | undefined;\n reason?: string | undefined;\n}\n\n/** Minimal verification contract shared by file-backed and remote stores. */\nexport interface MailboxCredentialVerifier {\n load(): Promise<void>;\n verify(\n credentialId: string,\n secret: string,\n ): CredentialValidation | Promise<CredentialValidation>;\n verifyPersisted(credentialId: string, secret: string): Promise<CredentialValidation>;\n}\n\n// \u2500\u2500 Constants \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Default credential file name. */\nexport const CREDENTIAL_STORE_FILE = '_mailbox_credentials.json';\n\n/** Maximum lifetime by credential kind. */\nexport const MAX_CREDENTIAL_TTL: Record<MailboxCredential['kind'], number> = {\n agent: 7 * 24 * 60 * 60 * 1000, // 7 days\n operator: 24 * 60 * 60 * 1000, // 24 hours\n service: 30 * 24 * 60 * 60 * 1000, // 30 days\n};\n\n/** Default rotation overlap window (old + new both valid). */\nexport const ROTATION_OVERLAP_MS = 60 * 60 * 1000; // 1 hour\n\n/** Create an opaque credential without choosing a persistence backend. */\nexport function createMailboxCredential(\n opts: IssueCredentialOptions,\n now = Date.now(),\n): { credential: MailboxCredential; secret: string } {\n const ttlMs = Math.min(opts.ttlMs, MAX_CREDENTIAL_TTL[opts.kind]);\n const credentialId = crypto.randomUUID();\n const secret = crypto.randomBytes(32).toString('hex');\n const verifierKey = crypto.createHash('sha256').update(secret).digest();\n const verifier = crypto.createHmac('sha256', verifierKey).update(credentialId).digest('hex');\n\n return {\n credential: {\n credentialId,\n verifier,\n verifierAlgorithm: 'hmac-sha256',\n principalId: opts.principalId,\n projectId: opts.projectId,\n capabilities: opts.capabilities,\n kind: opts.kind,\n issuedAt: new Date(now).toISOString(),\n expiresAt: new Date(now + ttlMs).toISOString(),\n notBefore: opts.notBefore?.toISOString(),\n status: 'active',\n statusChangedAt: new Date(now).toISOString(),\n supersedes: opts.supersedes,\n lastModifiedBy: opts.issuedBy,\n },\n secret,\n };\n}\n\n/** Verify an opaque secret against a stored credential snapshot. */\nexport function verifyMailboxCredential(\n credential: MailboxCredential | undefined,\n secret: string,\n now = Date.now(),\n): CredentialValidation {\n if (credential === undefined) {\n return { valid: false, reason: 'credential not found' };\n }\n\n const rotationStillValid =\n credential.status === 'rotated_out' &&\n credential.rotationValidUntil !== undefined &&\n new Date(credential.rotationValidUntil).getTime() >= now;\n if (credential.status !== 'active' && !rotationStillValid) {\n return { valid: false, reason: `credential is ${credential.status}`, credential };\n }\n // Inclusive: a credential that expires AT `now` is expired, mirroring\n // `notBefore` below (valid at exactly `notBefore`). With the exclusive\n // comparison a zero-TTL credential was accepted for the millisecond it was\n // issued in \u2014 invisible against the file store, which was slow enough that\n // the clock had usually moved on by the time `verify` ran, and reproducible\n // against SQLite, which is not.\n if (new Date(credential.expiresAt).getTime() <= now) {\n return { valid: false, reason: 'credential expired', credential };\n }\n if (credential.notBefore !== undefined && new Date(credential.notBefore).getTime() > now) {\n return { valid: false, reason: 'credential not yet valid', credential };\n }\n\n const verifierKey = crypto.createHash('sha256').update(secret).digest();\n const expected = crypto\n .createHmac('sha256', verifierKey)\n .update(credential.credentialId)\n .digest('hex');\n const actualBytes = Buffer.from(credential.verifier, 'hex');\n const expectedBytes = Buffer.from(expected, 'hex');\n if (\n actualBytes.length !== expectedBytes.length ||\n !crypto.timingSafeEqual(actualBytes, expectedBytes)\n ) {\n return { valid: false, reason: 'invalid secret', credential };\n }\n\n return { valid: true, credential };\n}\n\n// \u2500\u2500 Store \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Resolve the credential store file path from the project directory.\n */\nexport function resolveCredentialStorePath(projectDir: string): string {\n return path.join(projectDir, CREDENTIAL_STORE_FILE);\n}\n", "/**\n * Row codecs for the SQLite mailbox \u2014 the SQL that turns domain records into\n * table rows and back.\n *\n * Split out of `sqlite-mailbox.ts`. Every function takes the open database and\n * prepares its own statement, exactly as the private methods it replaced did\n * via `this.stmt()`. No message-flow policy lives here: `send`/`query`/`ack`\n * stay in the store.\n *\n * @module coordination/sqlite-mailbox-rows\n */\nimport type { DatabaseSync } from 'node:sqlite';\nimport { AGENT_STALE_MS, CLIENT_STALE_MS } from './mailbox-constants.js';\nimport type { MailboxCredential } from './mailbox-credential-store.js';\nimport type {\n MailboxMessage,\n MailboxMessageProjection,\n MailboxRecipientState,\n RegisteredAgent,\n RegisteredClient,\n} from './mailbox-types.js';\n\nexport type SqliteStatement = ReturnType<DatabaseSync['prepare']>;\n\nexport interface MessageRow {\n id: string;\n data: string;\n legacy_global_completion: number;\n}\n\nexport interface ReceiptRow {\n message_id: string;\n actor_id: string;\n read_at: string | null;\n completed_at: string | null;\n completed_by: string | null;\n outcome: string | null;\n}\n\n/**\n * Predicate matching a `last_seen_at` that is not an ISO-8601 timestamp.\n *\n * A registration whose heartbeat timestamp is garbage would otherwise outlive\n * every sweep: string comparison puts `'invalid'` after any real timestamp, so\n * `last_seen_at < cutoff` never matches it and the row shows up as a\n * permanently offline agent. The JSONL registry it replaced pruned these via\n * `Number.isFinite(Date.parse(...))`.\n */\nexport const MALFORMED_TIMESTAMP =\n \"last_seen_at NOT GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T*'\";\n\n/**\n * Strip the message-level completion fields from a fan-out message before it\n * is stored. Per-actor state lives in `message_receipts`; the aggregate fields\n * would claim the message is done for every recipient.\n */\nexport function withoutAggregateCompletion(\n message: MailboxMessageProjection,\n): MailboxMessageProjection {\n const stored: MailboxMessageProjection = {\n ...message,\n completed: message.legacyGlobalCompletion === true,\n };\n if (!stored.completed) {\n delete stored.completedBy;\n delete stored.completedAt;\n }\n delete stored.outcome;\n return stored;\n}\n\n// \u2500\u2500 Messages \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function persistMessage(\n db: DatabaseSync,\n message: MailboxMessage,\n legacyGlobalCompletion = false,\n): void {\n const stored = { ...message, readBy: { ...message.readBy } } as MailboxMessageProjection;\n delete (stored as Partial<MailboxMessageProjection>).recipientState;\n delete (stored as Partial<MailboxMessageProjection>).legacyGlobalCompletion;\n db.prepare(`\n INSERT INTO messages(\n id, from_id, to_id, type, priority, timestamp, completed, completed_at,\n deleted_at, sender_session_id, reply_to, expires_at,\n legacy_global_completion, data\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(id) DO UPDATE SET\n from_id = excluded.from_id,\n to_id = excluded.to_id,\n type = excluded.type,\n priority = excluded.priority,\n timestamp = excluded.timestamp,\n completed = excluded.completed,\n completed_at = excluded.completed_at,\n deleted_at = excluded.deleted_at,\n sender_session_id = excluded.sender_session_id,\n reply_to = excluded.reply_to,\n expires_at = excluded.expires_at,\n legacy_global_completion = excluded.legacy_global_completion,\n data = excluded.data\n `).run(\n message.id,\n message.from,\n message.to,\n message.type,\n message.priority,\n message.timestamp,\n message.completed ? 1 : 0,\n message.completedAt ?? null,\n message.deletedAt ?? null,\n message.senderSessionId ?? null,\n message.replyTo ?? null,\n message.expiresAt ?? null,\n legacyGlobalCompletion ? 1 : 0,\n JSON.stringify(stored),\n );\n}\n\nexport function persistReceipt(\n db: DatabaseSync,\n messageId: string,\n state: MailboxRecipientState,\n): void {\n db.prepare(`\n INSERT INTO message_receipts(\n message_id, actor_id, read_at, completed_at, completed_by, outcome\n ) VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT(message_id, actor_id) DO UPDATE SET\n read_at = excluded.read_at,\n completed_at = excluded.completed_at,\n completed_by = excluded.completed_by,\n outcome = excluded.outcome\n `).run(\n messageId,\n state.actorId,\n state.readAt ?? null,\n state.completedAt ?? null,\n state.completedBy ?? null,\n state.outcome ?? null,\n );\n}\n\nexport function materializeMessageRows(\n db: DatabaseSync,\n rows: readonly MessageRow[],\n): MailboxMessageProjection[] {\n if (rows.length === 0) return [];\n\n const useTargetedReceipts = rows.length <= 500;\n const receiptSql = useTargetedReceipts\n ? `\n SELECT message_id, actor_id, read_at, completed_at, completed_by, outcome\n FROM message_receipts\n WHERE message_id IN (${rows.map(() => '?').join(', ')})\n `\n : `\n SELECT message_id, actor_id, read_at, completed_at, completed_by, outcome\n FROM message_receipts\n `;\n const receiptRows = db\n .prepare(receiptSql)\n .all(...(useTargetedReceipts ? rows.map((row) => row.id) : [])) as unknown as ReceiptRow[];\n const receiptState = new Map<string, Record<string, MailboxRecipientState>>();\n for (const row of receiptRows) {\n const states = receiptState.get(row.message_id) ?? {};\n states[row.actor_id] = {\n actorId: row.actor_id,\n ...(row.read_at !== null ? { readAt: row.read_at } : {}),\n ...(row.completed_at !== null ? { completedAt: row.completed_at } : {}),\n ...(row.completed_by !== null ? { completedBy: row.completed_by } : {}),\n ...(row.outcome !== null ? { outcome: row.outcome } : {}),\n };\n receiptState.set(row.message_id, states);\n }\n\n return rows.map((row) => {\n const base = JSON.parse(row.data) as MailboxMessage;\n const recipientState = receiptState.get(row.id) ?? {};\n const readBy = { ...base.readBy };\n for (const state of Object.values(recipientState)) {\n if (state.readAt !== undefined) readBy[state.actorId] = state.readAt;\n }\n return {\n ...base,\n readBy,\n recipientState,\n ...(row.legacy_global_completion === 1 ? { legacyGlobalCompletion: true } : {}),\n };\n });\n}\n\nexport function deleteMessages(db: DatabaseSync, ids: readonly string[]): void {\n const statement = db.prepare('DELETE FROM messages WHERE id = ?');\n for (const id of ids) statement.run(id);\n}\n\n// \u2500\u2500 Agents \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function persistAgent(db: DatabaseSync, agent: RegisteredAgent): void {\n db.prepare(`\n INSERT INTO agents(\n agent_id, session_id, name, role, status, current_tool, current_task,\n iterations, tool_calls, registered_at, last_seen_at, pid, source\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(agent_id) DO UPDATE SET\n session_id = excluded.session_id,\n name = excluded.name,\n role = excluded.role,\n status = excluded.status,\n current_tool = excluded.current_tool,\n current_task = excluded.current_task,\n iterations = excluded.iterations,\n tool_calls = excluded.tool_calls,\n registered_at = excluded.registered_at,\n last_seen_at = excluded.last_seen_at,\n pid = excluded.pid,\n source = excluded.source\n `).run(\n agent.agentId,\n agent.sessionId,\n agent.name,\n agent.role ?? null,\n agent.status,\n agent.currentTool ?? null,\n agent.currentTask ?? null,\n agent.iterations,\n agent.toolCalls,\n agent.registeredAt,\n agent.lastSeenAt,\n agent.pid,\n agent.source ?? null,\n );\n}\n\nexport function readAgents(db: DatabaseSync): Map<string, RegisteredAgent> {\n const rows = db.prepare('SELECT * FROM agents').all() as unknown as Array<\n Record<string, unknown>\n >;\n const agents = new Map<string, RegisteredAgent>();\n for (const row of rows) {\n const agent: RegisteredAgent = {\n agentId: String(row['agent_id']),\n sessionId: String(row['session_id']),\n name: String(row['name']),\n ...(row['role'] !== null ? { role: String(row['role']) } : {}),\n status: row['status'] as RegisteredAgent['status'],\n ...(row['current_tool'] !== null ? { currentTool: String(row['current_tool']) } : {}),\n ...(row['current_task'] !== null ? { currentTask: String(row['current_task']) } : {}),\n iterations: Number(row['iterations']),\n toolCalls: Number(row['tool_calls']),\n registeredAt: String(row['registered_at']),\n lastSeenAt: String(row['last_seen_at']),\n pid: Number(row['pid']),\n ...(row['source'] !== null ? { source: row['source'] as RegisteredAgent['source'] } : {}),\n };\n agents.set(agent.agentId, agent);\n }\n return agents;\n}\n\nexport function pruneAgents(db: DatabaseSync, maxAgeMs = AGENT_STALE_MS): number {\n const cutoff = new Date(Date.now() - Math.max(0, maxAgeMs)).toISOString();\n const result = db\n .prepare(`DELETE FROM agents WHERE last_seen_at < ? OR ${MALFORMED_TIMESTAMP}`)\n .run(cutoff);\n return Number(result.changes);\n}\n\n// \u2500\u2500 Clients \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function persistClient(db: DatabaseSync, client: RegisteredClient): void {\n db.prepare(`\n INSERT INTO clients(\n client_id, session_id, name, source, registered_at, last_seen_at, pid\n ) VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(client_id) DO UPDATE SET\n session_id = excluded.session_id,\n name = excluded.name,\n source = excluded.source,\n registered_at = excluded.registered_at,\n last_seen_at = excluded.last_seen_at,\n pid = excluded.pid\n `).run(\n client.clientId,\n client.sessionId,\n client.name,\n client.source,\n client.registeredAt,\n client.lastSeenAt,\n client.pid,\n );\n}\n\nexport function readClients(db: DatabaseSync): Map<string, RegisteredClient> {\n const rows = db.prepare('SELECT * FROM clients').all() as unknown as Array<\n Record<string, unknown>\n >;\n const clients = new Map<string, RegisteredClient>();\n for (const row of rows) {\n const client: RegisteredClient = {\n clientId: String(row['client_id']),\n sessionId: String(row['session_id']),\n name: String(row['name']),\n source: row['source'] as RegisteredClient['source'],\n registeredAt: String(row['registered_at']),\n lastSeenAt: String(row['last_seen_at']),\n pid: Number(row['pid']),\n };\n clients.set(client.clientId, client);\n }\n return clients;\n}\n\nexport function pruneClients(db: DatabaseSync): number {\n const cutoff = new Date(Date.now() - CLIENT_STALE_MS).toISOString();\n const result = db\n .prepare(`DELETE FROM clients WHERE last_seen_at < ? OR ${MALFORMED_TIMESTAMP}`)\n .run(cutoff);\n return Number(result.changes);\n}\n\n// \u2500\u2500 Credentials \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function persistCredential(db: DatabaseSync, credential: MailboxCredential): void {\n db.prepare(`\n INSERT INTO credentials(credential_id, status, principal_id, expires_at, data)\n VALUES (?, ?, ?, ?, ?)\n ON CONFLICT(credential_id) DO UPDATE SET\n status = excluded.status,\n principal_id = excluded.principal_id,\n expires_at = excluded.expires_at,\n data = excluded.data\n `).run(\n credential.credentialId,\n credential.status,\n credential.principalId,\n credential.expiresAt,\n JSON.stringify(credential),\n );\n}\n", "/**\n * Credential issue / verify / revoke / rotate against the mailbox `credentials`\n * table.\n *\n * Split out of `sqlite-mailbox.ts`; the store keeps thin `credential*` methods\n * that delegate here, so its public surface is unchanged.\n *\n * @module coordination/sqlite-mailbox-credentials\n */\nimport type { DatabaseSync } from 'node:sqlite';\nimport {\n createMailboxCredential,\n type CredentialValidation,\n type IssueCredentialOptions,\n MAX_CREDENTIAL_TTL,\n type MailboxCredential,\n ROTATION_OVERLAP_MS,\n verifyMailboxCredential,\n} from './mailbox-credential-store.js';\nimport { persistCredential } from './sqlite-mailbox-rows.js';\n\nexport function credentialGet(db: DatabaseSync, credentialId: string): MailboxCredential | null {\n const row = db.prepare('SELECT data FROM credentials WHERE credential_id = ?').get(credentialId) as\n | { data: string }\n | undefined;\n return row === undefined ? null : (JSON.parse(row.data) as MailboxCredential);\n}\n\nexport function credentialList(db: DatabaseSync): MailboxCredential[] {\n const rows = db.prepare('SELECT data FROM credentials').all() as unknown as {\n data: string;\n }[];\n return rows\n .map((row) => JSON.parse(row.data) as MailboxCredential)\n .sort((left, right) => {\n if (left.status === 'active' && right.status !== 'active') return -1;\n if (left.status !== 'active' && right.status === 'active') return 1;\n return right.issuedAt.localeCompare(left.issuedAt);\n });\n}\n\nexport function credentialStatusCounts(db: DatabaseSync): Record<string, number> {\n const rows = db\n .prepare('SELECT status, COUNT(*) AS count FROM credentials GROUP BY status')\n .all() as unknown as { status: string; count: number }[];\n return Object.fromEntries(rows.map((row) => [row.status, row.count]));\n}\n\nexport function credentialIssue(\n db: DatabaseSync,\n transaction: <T>(run: () => T) => T,\n options: IssueCredentialOptions,\n): { credential: MailboxCredential; secret: string } {\n const now = Date.now();\n const issued = createMailboxCredential(options, now);\n transaction(() => {\n if (options.supersedes !== undefined) {\n const old = credentialGet(db, options.supersedes);\n if (old?.status === 'active') {\n old.status = 'rotated_out';\n old.statusChangedAt = new Date(now).toISOString();\n old.statusReason = 'superseded by rotation';\n old.rotationValidUntil = new Date(now + ROTATION_OVERLAP_MS).toISOString();\n persistCredential(db, old);\n }\n }\n persistCredential(db, issued.credential);\n });\n return issued;\n}\n\nexport function credentialVerify(\n db: DatabaseSync,\n credentialId: string,\n secret: string,\n): CredentialValidation {\n return verifyMailboxCredential(credentialGet(db, credentialId) ?? undefined, secret);\n}\n\nexport function credentialRevoke(\n db: DatabaseSync,\n credentialId: string,\n reason?: string,\n by?: string,\n): boolean {\n const credential = credentialGet(db, credentialId);\n if (credential === null || credential.status === 'revoked') return false;\n credential.status = 'revoked';\n credential.statusChangedAt = new Date().toISOString();\n credential.statusReason = reason ?? 'revoked';\n credential.lastModifiedBy = by;\n persistCredential(db, credential);\n return true;\n}\n\nexport function credentialRotate(\n db: DatabaseSync,\n transaction: <T>(run: () => T) => T,\n credentialId: string,\n options?: Partial<IssueCredentialOptions>,\n): { credential: MailboxCredential; secret: string } | null {\n const old = credentialGet(db, credentialId);\n if (old === null) return null;\n return credentialIssue(db, transaction, {\n principalId: old.principalId,\n projectId: old.projectId ?? options?.projectId,\n kind: old.kind,\n capabilities: options?.capabilities ?? old.capabilities,\n ttlMs: options?.ttlMs ?? MAX_CREDENTIAL_TTL[old.kind],\n supersedes: credentialId,\n issuedBy: options?.issuedBy,\n });\n}\n", "/**\n * Schema creation, version fencing, and one-time legacy-file import for the\n * SQLite mailbox.\n *\n * Split out of `sqlite-mailbox.ts`. Everything here runs once, from the store's\n * constructor; keeping it separate leaves that file to the message flow.\n *\n * @module coordination/sqlite-mailbox-schema\n */\nimport * as fs from 'node:fs';\nimport { createRequire } from 'node:module';\nimport * as path from 'node:path';\nimport type { DatabaseSync } from 'node:sqlite';\nimport { withSqliteExperimentalWarningSuppressed } from '../utils/sqlite-warning.js';\nimport { GLOBAL_MAILBOX_CLIENT_REGISTRY_FILE, GLOBAL_MAILBOX_FILE } from './global-mailbox-paths.js';\nimport {\n CREDENTIAL_STORE_FILE,\n type MailboxCredential,\n} from './mailbox-credential-store.js';\nimport { parseMailboxFile } from './mailbox-parse-state.js';\nimport { parseAgentRegistryEntry, parseClientRegistryEntry } from './mailbox-registry-codec.js';\nimport type { MailboxMessage, MailboxMessageProjection } from './mailbox-types.js';\nimport {\n persistAgent,\n persistClient,\n persistCredential,\n persistMessage,\n persistReceipt,\n} from './sqlite-mailbox-rows.js';\n\nexport const SQLITE_MAILBOX_SCHEMA_VERSION = 2;\n\nlet DatabaseSyncCtor: typeof DatabaseSync | undefined;\n\nexport function loadDatabaseSync(): typeof DatabaseSync {\n if (DatabaseSyncCtor) return DatabaseSyncCtor;\n return withSqliteExperimentalWarningSuppressed(() => {\n const require = createRequire(import.meta.url);\n DatabaseSyncCtor = (require('node:sqlite') as typeof import('node:sqlite')).DatabaseSync;\n return DatabaseSyncCtor;\n });\n}\n\n/** The store state schema setup and migration need. */\nexport interface SchemaContext {\n db: DatabaseSync;\n projectDir: string;\n transaction: <T>(run: () => T) => T;\n}\n\nexport function initializeSchema(ctx: SchemaContext): void {\n const { db } = ctx;\n db.exec(`\n CREATE TABLE IF NOT EXISTS mailbox_meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n CREATE TABLE IF NOT EXISTS messages (\n id TEXT PRIMARY KEY,\n from_id TEXT NOT NULL,\n to_id TEXT NOT NULL,\n type TEXT NOT NULL,\n priority TEXT NOT NULL,\n timestamp TEXT NOT NULL,\n completed INTEGER NOT NULL DEFAULT 0,\n completed_at TEXT,\n deleted_at TEXT,\n sender_session_id TEXT,\n reply_to TEXT,\n expires_at TEXT,\n legacy_global_completion INTEGER NOT NULL DEFAULT 0,\n data TEXT NOT NULL\n );\n CREATE TABLE IF NOT EXISTS message_receipts (\n message_id TEXT NOT NULL REFERENCES messages(id) ON DELETE CASCADE,\n actor_id TEXT NOT NULL,\n read_at TEXT,\n completed_at TEXT,\n completed_by TEXT,\n outcome TEXT,\n PRIMARY KEY (message_id, actor_id)\n );\n CREATE TABLE IF NOT EXISTS agents (\n agent_id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL,\n name TEXT NOT NULL,\n role TEXT,\n status TEXT NOT NULL,\n current_tool TEXT,\n current_task TEXT,\n iterations INTEGER NOT NULL,\n tool_calls INTEGER NOT NULL,\n registered_at TEXT NOT NULL,\n last_seen_at TEXT NOT NULL,\n pid INTEGER NOT NULL,\n source TEXT\n );\n CREATE TABLE IF NOT EXISTS clients (\n client_id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL,\n name TEXT NOT NULL,\n source TEXT NOT NULL,\n registered_at TEXT NOT NULL,\n last_seen_at TEXT NOT NULL,\n pid INTEGER NOT NULL\n );\n CREATE TABLE IF NOT EXISTS credentials (\n credential_id TEXT PRIMARY KEY,\n status TEXT NOT NULL,\n principal_id TEXT NOT NULL,\n expires_at TEXT NOT NULL,\n data TEXT NOT NULL\n );\n CREATE INDEX IF NOT EXISTS idx_messages_to_timestamp ON messages(to_id, timestamp DESC);\n CREATE INDEX IF NOT EXISTS idx_messages_from_timestamp ON messages(from_id, timestamp DESC);\n CREATE INDEX IF NOT EXISTS idx_messages_type_timestamp ON messages(type, timestamp DESC);\n CREATE INDEX IF NOT EXISTS idx_messages_deleted_at ON messages(deleted_at);\n CREATE INDEX IF NOT EXISTS idx_messages_session_timestamp ON messages(sender_session_id, timestamp DESC);\n CREATE INDEX IF NOT EXISTS idx_messages_reply_timestamp ON messages(reply_to, timestamp DESC);\n CREATE INDEX IF NOT EXISTS idx_receipts_actor ON message_receipts(actor_id, message_id);\n CREATE INDEX IF NOT EXISTS idx_agents_last_seen ON agents(last_seen_at);\n CREATE INDEX IF NOT EXISTS idx_clients_last_seen ON clients(last_seen_at);\n CREATE INDEX IF NOT EXISTS idx_credentials_status ON credentials(status, expires_at);\n `);\n db.prepare('INSERT INTO mailbox_meta(key, value) VALUES (?, ?) ON CONFLICT(key) DO NOTHING').run(\n 'schema_version',\n String(SQLITE_MAILBOX_SCHEMA_VERSION),\n );\n const schema = db.prepare('SELECT value FROM mailbox_meta WHERE key = ?').get('schema_version') as\n | { value: string }\n | undefined;\n const foundVersion = Number(schema?.value);\n if (\n !Number.isInteger(foundVersion) ||\n foundVersion < 1 ||\n foundVersion > SQLITE_MAILBOX_SCHEMA_VERSION\n ) {\n throw new Error(\n `Unsupported mailbox SQLite schema ${schema?.value ?? 'missing'}; this build supports ${SQLITE_MAILBOX_SCHEMA_VERSION}`,\n );\n }\n if (foundVersion < SQLITE_MAILBOX_SCHEMA_VERSION) {\n db.prepare('UPDATE mailbox_meta SET value = ? WHERE key = ?').run(\n String(SQLITE_MAILBOX_SCHEMA_VERSION),\n 'schema_version',\n );\n }\n migrateLegacyCredentials(ctx);\n}\n\nfunction migrateLegacyCredentials(ctx: SchemaContext): void {\n const { db } = ctx;\n const marker = db\n .prepare('SELECT value FROM mailbox_meta WHERE key = ?')\n .get('legacy_credentials_imported') as { value: string } | undefined;\n if (marker !== undefined) return;\n const legacyPath = path.join(ctx.projectDir, CREDENTIAL_STORE_FILE);\n const credentials: MailboxCredential[] = [];\n try {\n for (const line of fs.readFileSync(legacyPath, 'utf8').split(/\\r?\\n/u)) {\n if (!line.trim()) continue;\n try {\n const credential = JSON.parse(line) as MailboxCredential;\n if (\n typeof credential.credentialId === 'string' &&\n typeof credential.verifier === 'string' &&\n typeof credential.principalId === 'string'\n )\n credentials.push(credential);\n } catch {\n // Preserve legacy adapter behavior: malformed records are skipped.\n }\n }\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== 'ENOENT') throw error;\n }\n ctx.transaction(() => {\n for (const credential of credentials) persistCredential(db, credential);\n db.prepare('INSERT INTO mailbox_meta(key, value) VALUES (?, ?)').run(\n 'legacy_credentials_imported',\n new Date().toISOString(),\n );\n });\n}\n\nexport function migrateLegacyFiles(ctx: SchemaContext): void {\n const { db } = ctx;\n const marker = db\n .prepare('SELECT value FROM mailbox_meta WHERE key = ?')\n .get('legacy_files_imported') as { value: string } | undefined;\n if (marker !== undefined) return;\n\n const messages = readLegacyMessages(ctx.projectDir);\n const agents = readLegacyRegistry(\n path.join(ctx.projectDir, '_mailbox.registry.json'),\n parseAgentRegistryEntry,\n );\n const clients = readLegacyRegistry(\n path.join(ctx.projectDir, GLOBAL_MAILBOX_CLIENT_REGISTRY_FILE),\n parseClientRegistryEntry,\n );\n\n ctx.transaction(() => {\n for (const message of messages) {\n const projection = message as MailboxMessageProjection;\n persistMessage(db, message, projection.legacyGlobalCompletion === true);\n for (const state of Object.values(projection.recipientState ?? {})) {\n persistReceipt(db, message.id, state);\n }\n }\n for (const agent of agents.values()) persistAgent(db, agent);\n for (const client of clients.values()) persistClient(db, client);\n db.prepare('INSERT INTO mailbox_meta(key, value) VALUES (?, ?)').run(\n 'legacy_files_imported',\n new Date().toISOString(),\n );\n });\n}\n\nfunction readLegacyMessages(projectDir: string): MailboxMessage[] {\n try {\n return parseMailboxFile(\n fs.readFileSync(path.join(projectDir, GLOBAL_MAILBOX_FILE), 'utf8'),\n );\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return [];\n throw error;\n }\n}\n\nfunction readLegacyRegistry<T>(\n filePath: string,\n parseEntry: (value: unknown) => T | null,\n): Map<string, T> {\n try {\n const raw = JSON.parse(fs.readFileSync(filePath, 'utf8')) as Record<string, unknown>;\n const result = new Map<string, T>();\n for (const [id, value] of Object.entries(raw)) {\n const parsed = parseEntry(value);\n if (parsed !== null) result.set(id, parsed);\n }\n return result;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return new Map();\n throw error;\n }\n}\n", "const SQLITE_EXPERIMENTAL_WARNING_RE = /sqlite is an experimental feature/i;\n\nfunction isSqliteExperimentalWarning(warning: unknown, rest: readonly unknown[]): boolean {\n const message = typeof warning === 'string' ? warning : warning instanceof Error ? warning.message : '';\n const typeOrOptions = rest[0];\n const warningType =\n typeof warning === 'string'\n ? typeof typeOrOptions === 'string'\n ? typeOrOptions\n : typeof typeOrOptions === 'object' &&\n typeOrOptions !== null &&\n 'type' in typeOrOptions &&\n typeof typeOrOptions.type === 'string'\n ? typeOrOptions.type\n : ''\n : warning instanceof Error\n ? warning.name\n : '';\n const warningCode =\n typeof warning === 'string'\n ? typeof typeOrOptions === 'object' &&\n typeOrOptions !== null &&\n 'code' in typeOrOptions &&\n typeof typeOrOptions.code === 'string'\n ? typeOrOptions.code\n : typeof rest[1] === 'string'\n ? rest[1]\n : ''\n : warning instanceof Error && 'code' in warning && typeof warning.code === 'string'\n ? warning.code\n : '';\n\n return (\n SQLITE_EXPERIMENTAL_WARNING_RE.test(message) &&\n (warningType === 'ExperimentalWarning' || warningCode === 'ExperimentalWarning')\n );\n}\n\n/**\n * Run a synchronous `node:sqlite` load while filtering only Node's built-in\n * SQLite ExperimentalWarning. All other warnings still go through the original\n * process warning path, and the patch is removed before returning.\n */\nexport function withSqliteExperimentalWarningSuppressed<T>(run: () => T): T {\n const originalEmitWarning = process.emitWarning;\n const forwardWarning = originalEmitWarning.bind(process) as (\n warning: unknown,\n ...rest: unknown[]\n ) => void;\n\n process.emitWarning = ((warning: unknown, ...rest: unknown[]): void => {\n if (isSqliteExperimentalWarning(warning, rest)) return;\n forwardWarning(warning, ...rest);\n }) as typeof process.emitWarning;\n\n try {\n return run();\n } finally {\n process.emitWarning = originalEmitWarning;\n }\n}\n", "import * as path from 'node:path';\nimport { projectSlug } from '../utils/wstack-paths.js';\n\nexport const GLOBAL_MAILBOX_FILE = '_mailbox.jsonl';\nexport const GLOBAL_MAILBOX_CLIENT_REGISTRY_FILE = '_mailbox.clients.json';\n\n/**\n * Derive the project-level mailbox directory path.\n *\n * Delegates to the canonical projectSlug() from wstack-paths so every surface\n * lands in the same ~/.wrongstack/projects/<slug>/ directory.\n */\nexport function resolveProjectDir(projectRoot: string, globalRoot: string): string {\n return path.join(globalRoot, 'projects', projectSlug(projectRoot));\n}\n", "/**\n * Incremental parse state for the mailbox JSONL file.\n *\n * `parseMailboxFile()` is a whole-file operation: it JSON-parses every line and\n * re-projects every message. That is the correct shape for a one-shot read, but\n * the read path is anything but one-shot \u2014 `unreadCount()`/`query()` consult the\n * cache on every tool call, and any append by another session invalidates it.\n * On a mailbox holding a day of fleet traffic (~3 MB / ~2.8k lines) that turned\n * into the single largest allocation source in the whole TUI process: ~78% of\n * all bytes allocated while idle, which V8 then let pile up as garbage until a\n * major GC \u2014 read as \"RAM keeps growing and /clear doesn't help\".\n *\n * This module keeps enough state alongside the projections that an APPEND can\n * be folded in without touching the bytes that were already parsed:\n *\n * - `messages` \u2014 base messages in file order, v1 acks already folded\n * - `receiptsByMessage` \u2014 every v2 receipt, keyed by target message id\n * - `indexById` \u2014 message id \u2192 indices (plural: duplicate ids are\n * pathological but must fold exactly as a full parse\n * would \u2014 acks hit the last, receipts hit them all)\n * - `projections` \u2014 the materialized result, parallel to `messages`\n *\n * The fold is *exact*, not approximate: appended receipts are accumulated into\n * the full per-message list and the affected messages are re-materialized from\n * that complete list, so the output is byte-for-byte what `parseMailboxFile()`\n * would have produced over the whole file. `parseMailboxFile()` itself is now\n * implemented on top of this module, so there is one fold, not two.\n *\n * @module mailbox-parse-state\n */\n\nimport { LINE_SEPARATOR } from './mailbox-constants.js';\nimport {\n applyAckToMessage,\n isAckRecord,\n parseMailboxMessage,\n} from './mailbox-message-codec.js';\nimport { materializeMessage } from './mailbox-receipt-folding.js';\nimport type {\n AckRecord,\n MailboxMessage,\n MailboxMessageProjection,\n MailboxReceiptRecordV2,\n} from './mailbox-types.js';\nimport { isMailboxReceiptRecordV2 } from './mailbox-types.js';\n\nexport interface MailboxParseState {\n /** Base messages in file order, with v1 ack records already applied. */\n messages: MailboxMessage[];\n /** Materialized projections, index-parallel to {@link messages}. */\n projections: MailboxMessageProjection[];\n /** Message id \u2192 every index in {@link messages} carrying that id. */\n indexById: Map<string, number[]>;\n /** Message id \u2192 every v2 receipt targeting it, in file order. */\n receiptsByMessage: Map<string, MailboxReceiptRecordV2[]>;\n}\n\n/**\n * Parse the raw JSONL content of a mailbox file into MailboxMessageProjection[].\n *\n * This is the canonical read-path entry point: it parses each line once,\n * classifies v1 messages, v1 ack records, and v2 receipt records, then folds\n * them into a unified MailboxMessageProjection carrying per-actor state.\n *\n * Malformed lines are silently skipped (same tolerance as parseMailboxLines).\n *\n * Lives here rather than in `mailbox-receipt-folding.ts` so the whole-file and\n * incremental paths share one fold; the dependency stays one-directional\n * (parse-state \u2192 receipt-folding) instead of forming an import cycle.\n */\nexport function parseMailboxFile(raw: string): MailboxMessageProjection[] {\n return createMailboxParseState(raw).projections;\n}\n\n/** Build parse state from the complete raw contents of a mailbox file. */\nexport function createMailboxParseState(raw: string): MailboxParseState {\n const state: MailboxParseState = {\n messages: [],\n projections: [],\n indexById: new Map(),\n receiptsByMessage: new Map(),\n };\n ingestMailboxChunk(state, raw);\n return state;\n}\n\n/**\n * Fold an appended chunk of JSONL into existing parse state, in place.\n *\n * `chunk` must be a run of WHOLE lines starting exactly where the previously\n * ingested content ended \u2014 the caller is responsible for trimming a partially\n * written trailing line (see `MailboxMessageCache`). Malformed lines are\n * skipped with the same tolerance as a full parse.\n *\n * Ordering matches a full parse: within the chunk, messages are collected\n * first and ack records applied afterwards, so an ack may target a message\n * that appears later in the same chunk. Ack records whose target is in\n * neither the chunk nor the existing state are dropped, exactly as the\n * whole-file fold drops them.\n */\nexport function ingestMailboxChunk(state: MailboxParseState, chunk: string): void {\n const firstNewIndex = state.messages.length;\n const ackRecords: AckRecord[] = [];\n // Indices of PRE-EXISTING messages whose projection is now stale. Newly\n // appended messages are materialized unconditionally below, so they are\n // deliberately not tracked here.\n const staleExisting = new Set<number>();\n\n for (const line of chunk.split(LINE_SEPARATOR)) {\n if (line.trim().length === 0) continue;\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n continue; // skip malformed lines\n }\n\n if (isMailboxReceiptRecordV2(parsed)) {\n const list = state.receiptsByMessage.get(parsed.messageId);\n if (list) list.push(parsed);\n else state.receiptsByMessage.set(parsed.messageId, [parsed]);\n // A receipt re-folds EVERY message carrying that id, matching\n // `materializeMessages`, which looks receipts up per message.\n for (const index of state.indexById.get(parsed.messageId) ?? []) {\n if (index < firstNewIndex) staleExisting.add(index);\n }\n continue;\n }\n\n if (isAckRecord(parsed)) {\n ackRecords.push(parsed);\n continue;\n }\n\n let message: MailboxMessage;\n try {\n message = parseMailboxMessage(parsed);\n } catch {\n continue; // codec rejected the record \u2014 same tolerance as a full parse\n }\n const index = state.messages.length;\n state.messages.push(message);\n const indices = state.indexById.get(message.id);\n if (indices) indices.push(index);\n else state.indexById.set(message.id, [index]);\n }\n\n // v1 acks resolve against the last message carrying the id, mirroring the\n // whole-file fold's `new Map(messages.map(m => [m.id, m]))` (last wins).\n for (const ack of ackRecords) {\n const indices = state.indexById.get(ack.messageId);\n if (indices === undefined || indices.length === 0) continue;\n const index = indices[indices.length - 1] as number;\n applyAckToMessage(state.messages[index] as MailboxMessage, ack);\n if (index < firstNewIndex) staleExisting.add(index);\n }\n\n for (const index of staleExisting) {\n const message = state.messages[index] as MailboxMessage;\n state.projections[index] = materializeMessage(\n message,\n state.receiptsByMessage.get(message.id) ?? [],\n );\n }\n for (let index = firstNewIndex; index < state.messages.length; index++) {\n const message = state.messages[index] as MailboxMessage;\n state.projections.push(\n materializeMessage(message, state.receiptsByMessage.get(message.id) ?? []),\n );\n }\n}\n", "import type { RegisteredAgent, RegisteredClient } from './mailbox-types.js';\n\n/**\n * Minimal shape-check for a deserialized agent registry entry.\n *\n * Identity fields are the only hard requirement. Everything else is coerced\n * to a safe default so an unrecognised entry from another/newer process\n * survives a shared read-modify-write instead of being permanently evicted.\n */\nexport function parseAgentRegistryEntry(value: unknown): RegisteredAgent | null {\n if (typeof value !== 'object' || value === null) return null;\n const v = value as Record<string, unknown>;\n if (typeof v.agentId !== 'string') return null;\n if (typeof v.sessionId !== 'string') return null;\n const statuses = ['idle', 'busy', 'running', 'streaming', 'waiting_user', 'error'] as const;\n const status =\n typeof v.status === 'string' && (statuses as readonly string[]).includes(v.status)\n ? v.status\n : 'idle';\n return {\n ...v,\n agentId: v.agentId,\n sessionId: v.sessionId,\n name: typeof v.name === 'string' ? v.name : v.agentId,\n registeredAt: typeof v.registeredAt === 'string' ? v.registeredAt : new Date(0).toISOString(),\n lastSeenAt: typeof v.lastSeenAt === 'string' ? v.lastSeenAt : new Date(0).toISOString(),\n iterations: typeof v.iterations === 'number' && Number.isFinite(v.iterations) ? v.iterations : 0,\n toolCalls: typeof v.toolCalls === 'number' && Number.isFinite(v.toolCalls) ? v.toolCalls : 0,\n pid: typeof v.pid === 'number' && Number.isFinite(v.pid) ? v.pid : 0,\n status,\n } as unknown as RegisteredAgent;\n}\n\n/** Minimal shape-check for a deserialized client registry entry. */\nexport function parseClientRegistryEntry(value: unknown): RegisteredClient | null {\n if (typeof value !== 'object' || value === null) return null;\n const v = value as Record<string, unknown>;\n if (typeof v.clientId !== 'string') return null;\n if (typeof v.sessionId !== 'string') return null;\n const sources = ['repl', 'tui', 'webui', 'http'] as const;\n const source =\n typeof v.source === 'string' && (sources as readonly string[]).includes(v.source)\n ? v.source\n : 'http';\n return {\n ...v,\n clientId: v.clientId,\n sessionId: v.sessionId,\n name: typeof v.name === 'string' ? v.name : v.clientId,\n registeredAt: typeof v.registeredAt === 'string' ? v.registeredAt : new Date(0).toISOString(),\n lastSeenAt: typeof v.lastSeenAt === 'string' ? v.lastSeenAt : new Date(0).toISOString(),\n pid: typeof v.pid === 'number' && Number.isFinite(v.pid) ? v.pid : 0,\n source,\n } as unknown as RegisteredClient;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["fs", "path", "projectDir", "endpoint", "randomUUID", "fs", "path", "isRecord", "isRecord", "clients", "fs", "path", "index", "require", "clients", "projectDir", "projectDir", "events", "eventEmitter", "randomUUID", "projectDir", "resolve"]
7
7
  }