/**
 * Serialize `value` to canonical JSON (deterministic across object key order
 * and identical-content equality).  Used by:
 *   - `computeInputHash` to derive inputHash for attempt input immutability
 *     checks (events doc §4.2 + §3.6).
 *   - any code path that needs hash-stable serialization of structured data.
 *
 * Rules:
 *   - Object keys are sorted ascending (lexicographic on UTF-16 code units,
 *     matching JS's default Array.sort).
 *   - `undefined` properties are dropped (matches `JSON.stringify` behaviour
 *     for plain objects).
 *   - `null` is preserved as `"null"`.
 *   - Arrays preserve order — they're ordered data, not bags.
 *   - Strings, numbers, booleans use `JSON.stringify` (handles escapes).
 *   - Non-finite numbers (`NaN`, `±Infinity`), BigInt, Function, Symbol,
 *     Date, and class instances throw.  Dates would need a project-wide
 *     decision on epoch-ms vs ISO string; v0 throws so the caller is forced
 *     to normalize upstream.
 */
export declare function canonicalJson(value: unknown): string;
/**
 * The 5-tuple that anchors workflow idempotency (events doc §3.2 / §4.2).
 * Each attempt is uniquely identified by this combination; the derived
 * key feeds into provider uuid fields (Feishu IM uuid, schedule-store id).
 */
export type IdempotencyKeyTuple = {
    workflowId: string;
    revisionId: string;
    runId: string;
    nodeId: string;
    attemptId: string;
};
export type DeriveIdempotencyKeyOptions = {
    /**
     * String prefix prepended to the truncated hash.  Defaults to `wf_`,
     * which keeps workflow-generated ids in a separate namespace from
     * randomUUID-derived ids (events doc §2.2 schedule case).  Pass empty
     * string to disable.  Must be ≤ `maxLength - 1`.
     */
    namespace?: string;
    /**
     * Max output length.  Defaults to 50 to match Feishu IM uuid field's
     * documented upper bound (spike report §1.2).
     */
    maxLength?: number;
};
/**
 * Deterministically derive an idempotency key from the 5-tuple.  Same tuple
 * always produces the same key; collisions are bounded by the truncated
 * SHA-256 birthday term.  With default namespace `wf_` and maxLength 50:
 *
 *   key = "wf_" + sha256(workflowId:revisionId:runId:nodeId:attemptId)[:47]
 *
 * 47 hex chars = 188 bits of entropy, ample for collision-free workflow
 * lifetimes.
 */
export declare function deriveIdempotencyKey(tuple: IdempotencyKeyTuple, opts?: DeriveIdempotencyKeyOptions): string;
/**
 * Hash an attempt's canonical input.  Returned in `sha256:<hex>` form so
 * it slots directly into event payloads (`effectAttempted.inputHash` and
 * resume reconcile evidence).
 *
 * The hash is over the **full canonical input** — for send/reply that
 * includes `receive_id`, `root_message_id?`, `msg_type`, `content`; for
 * schedule it includes the entire create-task input.  Spike report §1.3
 * + reply test 3c proved partial hashes leak silent state drift.
 *
 * inputHash is **separate** from idempotencyKey by design (codex v0.1.1
 * round 2): mixing content into the key would convert "input changed" into
 * "new effect", bypassing attempt-immutability.  inputHash lives as a
 * post-fact validator: same attemptId must always produce the same
 * inputHash; mismatches trigger `IdempotencyInputMismatch` (events doc
 * §4.2).
 */
export declare function computeInputHash(input: unknown): string;
//# sourceMappingURL=idempotency.d.ts.map