/**
 * Inbox row + ack row schemas for the L3 communication loop (T-L3-LOOP LL.1).
 *
 * The chat-daemon writes one inbound message per line to
 * `~/.opensquid/umbrellas/<umbrellaId>/inbox/<platform>.jsonl` (the on-disk
 * contract documented at `src/runtime/paths.ts`, `umbrellaInboxFile`). Until
 * LL.1 this shape was implicit — declared inline in
 * `src/mcp/chat-bridge-server.ts` as `interface InboxMessage`. LL.1 lifts it
 * to a single Zod source-of-truth so the MCP tool, the chokidar tail watcher
 * (LL.3), and the UPS hook (LL.4) all bind to the same parser. CAT.1c re-keyed
 * the readers from per-cwd `project_uuid` to UMBRELLA (the row shape is
 * byte-identical; only the key + path change).
 *
 * `AckRow` is the LL.4-locked ack ledger row: append-only to
 * `~/.opensquid/umbrellas/<umbrellaId>/inbox/acked.jsonl`. The (platform,
 * message_id, injected_at_sessionId) triple is the dedup key per L2 of the
 * T-L3-LOOP locked decisions.
 *
 * `v: z.literal(1)` is a forward-compat envelope marker — when the daemon
 * eventually bumps the format, both readers + writer migrate atomically.
 * AckRow.safeParse on a v:2 row returns failure → row treated as "not acked"
 * → duplicate injection. LL.4 documents the mitigation in its dedup loop.
 *
 * `readInbox` + `readAcked` are best-effort: malformed lines are silently
 * skipped (the daemon writes valid JSON per row but a partial write at the
 * tail is possible during rotation). LL.5 documents the silent-skip behavior.
 *
 * Imports from: zod, node:fs/promises, ../paths.
 * Imported by: src/mcp/chat-bridge-server.ts (read tool); LL.3 inbound_watch.ts
 *   (chokidar tail); LL.4 user-prompt-submit.ts (inject + ack); tests.
 */
import { z } from 'zod';
export declare const Platform: z.ZodEnum<["telegram", "discord", "slack"]>;
export type Platform = z.infer<typeof Platform>;
export declare const InboxMedia: z.ZodObject<{
    kind: z.ZodEnum<["photo", "document"]>;
    path: z.ZodString;
    caption: z.ZodOptional<z.ZodString>;
    mime: z.ZodOptional<z.ZodString>;
}, "strict", z.ZodTypeAny, {
    path: string;
    kind: "photo" | "document";
    caption?: string | undefined;
    mime?: string | undefined;
}, {
    path: string;
    kind: "photo" | "document";
    caption?: string | undefined;
    mime?: string | undefined;
}>;
export type InboxMedia = z.infer<typeof InboxMedia>;
export declare const InboxRow: z.ZodObject<{
    v: z.ZodLiteral<1>;
    id: z.ZodString;
    thread_id: z.ZodOptional<z.ZodString>;
    platform: z.ZodEnum<["telegram", "discord", "slack"]>;
    channel: z.ZodString;
    sender: z.ZodString;
    sender_id: z.ZodString;
    text: z.ZodString;
    received_at: z.ZodString;
    enqueued_at: z.ZodString;
    mentions_bot: z.ZodBoolean;
    media: z.ZodOptional<z.ZodArray<z.ZodObject<{
        kind: z.ZodEnum<["photo", "document"]>;
        path: z.ZodString;
        caption: z.ZodOptional<z.ZodString>;
        mime: z.ZodOptional<z.ZodString>;
    }, "strict", z.ZodTypeAny, {
        path: string;
        kind: "photo" | "document";
        caption?: string | undefined;
        mime?: string | undefined;
    }, {
        path: string;
        kind: "photo" | "document";
        caption?: string | undefined;
        mime?: string | undefined;
    }>, "many">>;
}, "strict", z.ZodTypeAny, {
    id: string;
    sender: string;
    text: string;
    channel: string;
    platform: "telegram" | "discord" | "slack";
    v: 1;
    sender_id: string;
    received_at: string;
    enqueued_at: string;
    mentions_bot: boolean;
    media?: {
        path: string;
        kind: "photo" | "document";
        caption?: string | undefined;
        mime?: string | undefined;
    }[] | undefined;
    thread_id?: string | undefined;
}, {
    id: string;
    sender: string;
    text: string;
    channel: string;
    platform: "telegram" | "discord" | "slack";
    v: 1;
    sender_id: string;
    received_at: string;
    enqueued_at: string;
    mentions_bot: boolean;
    media?: {
        path: string;
        kind: "photo" | "document";
        caption?: string | undefined;
        mime?: string | undefined;
    }[] | undefined;
    thread_id?: string | undefined;
}>;
export type InboxRow = z.infer<typeof InboxRow>;
export declare const AckRow: z.ZodObject<{
    v: z.ZodLiteral<1>;
    message_id: z.ZodString;
    platform: z.ZodEnum<["telegram", "discord", "slack"]>;
    injected_at_sessionId: z.ZodString;
    injected_at_timestamp: z.ZodString;
}, "strict", z.ZodTypeAny, {
    platform: "telegram" | "discord" | "slack";
    message_id: string;
    v: 1;
    injected_at_sessionId: string;
    injected_at_timestamp: string;
}, {
    platform: "telegram" | "discord" | "slack";
    message_id: string;
    v: 1;
    injected_at_sessionId: string;
    injected_at_timestamp: string;
}>;
export type AckRow = z.infer<typeof AckRow>;
/**
 * Read every InboxRow from an umbrella's per-platform inbox file. Malformed
 * lines are silently skipped — the daemon writes valid JSON per row but a
 * partial write at the tail is possible during rotation. ENOENT → empty.
 */
export declare function readInbox(umbrellaId: string, platform: Platform): Promise<InboxRow[]>;
/**
 * Read every AckRow for an umbrella. Used by LL.4 UPS hook to build the
 * dedup set before deciding which inbox rows to inject. Same silent-skip
 * semantics as `readInbox`.
 */
export declare function readAcked(umbrellaId: string): Promise<AckRow[]>;
/**
 * Build the canonical dedup-key string used by the inject/ack loop.
 *
 * LL4FIX.1 (2026-05-31): drops `sessionId` from the key. Previously the
 * key was `${platform}::${messageId}::${sessionId}`, making acks per-session
 * — every new Claude Code session re-injected the entire backlog because
 * no prior-session ack matched. The fix derives dedup keys from
 * (platform, message_id) only; AckRow.injected_at_sessionId is still
 * RECORDED as audit metadata + drives 7-day purge eligibility.
 */
export declare function ackKey(platform: Platform, messageId: string): string;
//# sourceMappingURL=inbox.d.ts.map