import type { Message } from "@slackwsh/contracts";
/**
 * Spec-level helpers for §5.2. The harness and the TLA+ model both treat
 * these formulas as the source of truth — not whatever a particular SQL
 * query or UI cache happens to compute today.
 *
 * Machine-checked by:
 *   - `invariants.test.ts` / `properties.test.ts` (fast-check)
 *   - `harness.seed.test.ts` (seeded fault injection)
 *   - `spec/Sync.tla` (I4 / I5 / I5b / I7)
 */
export interface PersistedMention {
    messageId: number;
    /** `user` | `here` | `channel` | `everyone` | `group` */
    targetType: string;
    targetId: number | null;
}
export declare function isChannelViewMessage(message: Message): boolean;
export declare function channelView(messages: readonly Message[]): Message[];
/** I1: identical seq order, ignoring delivery/wall-clock. */
export declare function seqOrder(messages: readonly Message[]): number[];
export declare function assertTotalOrder(messages: readonly Message[]): void;
/**
 * I4. Acks use GREATEST; mark-unread is the explicit-decrease exception
 * and uses LEAST. Both are monotonic in their own direction.
 */
export declare function clampReadSeq(current: number, incoming: number, explicitDecrease: boolean): number;
/** I5. */
export declare function channelUnreadCount(messages: readonly Message[], lastReadSeq: number, selfId: number): number;
/** I5b. */
export declare function threadUnreadCount(messages: readonly Message[], rootId: number, lastReadReplySeq: number, selfId: number): number;
/**
 * I6. Mention badges are counted from persisted `message_mentions` rows,
 * never from re-parsing `message.text`. Broad mentions (`here`/`channel`/
 * `everyone`) target every channel member except the author.
 */
export declare function mentionBadgeFromRows(messages: readonly Message[], mentions: readonly PersistedMention[], selfId: number, lastReadSeq: number, memberIds: readonly number[]): number;
/** I8: a lower-or-equal revision must not replace a higher one. */
export declare function shouldApplyRevision(existingRevision: number, incomingRevision: number): boolean;
export declare function reactionsConverged(a: ReadonlyArray<{
    emoji: string;
    count: number;
}> | undefined, b: ReadonlyArray<{
    emoji: string;
    count: number;
}> | undefined): boolean;
//# sourceMappingURL=invariants.d.ts.map