/**
 * Pure helpers for the UPS hook's inbox-drain step (T-L3-LOOP LL.4).
 *
 * Split off from `user-prompt-submit.ts` so the inject logic is unit-testable
 * without spawning the hook binary. The hook calls these helpers in sequence:
 *   1. readInbox + readAcked (LL.1)
 *   2. computeUnackedRows (this module)
 *   3. buildInjectionEnvelope (this module) → appended to additionalContext
 *   4. appendAckRows (inbox_writer.ts, durable)
 *   5. purgeOldAcks + rewriteAckedAfterPurge (inbox_writer.ts, conditional)
 *
 * Per L6 of T-L3-LOOP locked decisions: multi-message aggregation happens
 * IN-HOOK (one envelope per UPS fire; one AckRow per included message).
 * Per L7 ("lazy push"): the LL.3 watcher already fired the inbound_channel
 * dispatch event; THIS module is the additionalContext injection — the
 * agent-facing surface that survives orphaned-watcher gaps.
 *
 * ACK-BEFORE-EMIT ordering (per L5): the hook MUST append AckRows BEFORE
 * printing the envelope to stdout. If the hook crashes between emit + ack,
 * the next fire re-injects (duplicate-in-conversation). If we acked first
 * then crashed before emit, the user would never see the message (silent
 * loss). Duplicate-on-rare-crash beats silent loss.
 */
import { type AckRow, type InboxRow } from './inbox.js';
/**
 * Filter inbox rows to those NOT yet acked. Dedup key is
 * `(platform, message_id)` per LL4FIX.1 (2026-05-31). Was previously
 * keyed with sessionId — that re-flooded every new session with the
 * entire backlog because no prior-session ack matched. The fix drops
 * sessionId from the SET-key derivation; the arg stays on this fn
 * signature because `buildAckRowsForInjected` still records
 * `injected_at_sessionId` as audit metadata + drives 7-day purge.
 */
export declare function computeUnackedRows(rows: readonly InboxRow[], acked: readonly AckRow[], sessionId: string): InboxRow[];
/**
 * Build the additionalContext envelope per L6. Format is human-scannable +
 * future-parser-friendly: a 📨 header line + per-row `<sender> (<platform>):
 * <text>` lines.
 *
 * Returns an empty envelope + zero injectedRows if `rows` is empty.
 * Overflow handling: if cumulative text would exceed
 * ENVELOPE_BUDGET_BYTES (8KB), the loop stops at the row that wouldn't
 * fit; remaining rows are NOT injected this turn and stay unacked
 * (drain on next UPS fire — preserves "lazy push" semantics).
 *
 * `injectedRows` is what the hook should pass to `buildAckRowsForInjected`
 * — only acked rows that actually made it into the envelope.
 */
export declare function buildInjectionEnvelope(rows: readonly InboxRow[]): {
    envelope: string;
    injectedRows: InboxRow[];
};
/**
 * Filter AckRows to those younger than 7 days. Used by the periodic purge
 * step to keep acked.jsonl from growing unbounded. Malformed timestamps
 * are dropped (defensive — schema validation upstream is best-effort).
 */
export declare function purgeOldAcks(acked: readonly AckRow[], now?: Date): AckRow[];
/**
 * Build AckRows from injected InboxRows, stamped with the current sessionId
 * + now. Hook passes the result to `appendAckRows` (inbox_writer.ts).
 */
export declare function buildAckRowsForInjected(injected: readonly InboxRow[], sessionId: string, now?: Date): AckRow[];
//# sourceMappingURL=inbox_inject.d.ts.map