/**
 * Inbound watcher (T-L3-LOOP LL.3; re-keyed project_uuid → UMBRELLA in
 * T-CHAT-AS-TERMINAL CAT.1c) — chokidar-backed tail of every live umbrella's
 * `~/.opensquid/umbrellas/<id>/inbox/<platform>.jsonl`. On each new row, parses
 * to `InboxRow`, resolves the target session via LL.2, constructs an
 * `InboundChannelEvent`, and calls `dispatchEvent` so any loaded pack with
 * `triggers: [{kind: 'inbound_channel', ...}]` fires.
 *
 * "Lazy push" semantics per L7: rows with no fresh session are appended
 * to `~/.opensquid/umbrellas/<id>/inbox/unrouted.jsonl` + LEFT in the
 * inbox (no ack). The LL.4 UPS hook drains the backlog on demand at the
 * next session prompt-submit.
 *
 * The watcher itself is dispatch-only — it does NOT inject into the
 * `additionalContext` envelope (that's LL.4's job at UPS fire time).
 * Splitting the two keeps dispatcher semantics (per-event) cleanly
 * distinct from the additionalContext semantics (per-turn aggregation).
 *
 * Performance: chokidar with `awaitWriteFinish: { stabilityThreshold: 100,
 * pollInterval: 50 }` (matches the precedent in
 * `src/runtime/agent_bridge/transport_bridge.ts`). Byte-offset tracking
 * via `stat.size`; re-read only the appended slice on each `change`.
 *
 * Durability: byte-offset state is in-memory only. Watcher restart loses
 * offsets → re-reads from start → multi-fires every existing row. The
 * LL.4 ack-set is the durability boundary — duplicate dispatches are
 * harmless because LL.4 dedups via `acked.jsonl`. Documented intent.
 *
 * Imports from: chokidar, node:fs/promises, node:path, ./inbox,
 *   ./session_routing, ../paths, ../bootstrap, ../hooks/dispatch.
 * Imported by: src/runtime/chat/watch_cli.ts (lifecycle start/stop).
 */
import { InboxRow, type Platform } from './inbox.js';
/**
 * Build a stable channelUri per L9: `<platform>://<channel>[/<thread_id>]`.
 * Lossless round-trip with `platformFromChannelUri`.
 */
export declare function buildChannelUri(row: InboxRow): string;
/**
 * Parse the scheme prefix from a channelUri. Used by the dispatcher filter
 * to compare against `Trigger.channel` (which is a bare literal like
 * `'telegram'`). Returns null for unrecognized schemes.
 */
export declare function platformFromChannelUri(uri: string): Platform | null;
/**
 * Process one newly-appended inbox row: resolve target session, fire
 * event, or record unrouted. Pure-ish (one lease read + one dispatch).
 */
export declare function processRow(umbrellaId: string, row: InboxRow): Promise<void>;
/** Extract `<id>` from `~/.opensquid/umbrellas/<id>/inbox/<platform>.jsonl`. */
export declare function extractUmbrellaId(path: string): string | null;
/**
 * Start watching every live umbrella's inbox files. Returns a cleanup
 * function the CLI calls on exit. Re-scans every 60s to pick up umbrellas
 * that come online after the watcher started.
 */
export declare function startInboundWatcher(): Promise<() => Promise<void>>;
//# sourceMappingURL=inbound_watch.d.ts.map