import type { AskEffective } from "../core/wiring-manifest.js";
import { type PermissionModeClass } from "./cross-session-envelope.js";
/** The permission-mode words the fold reads (the engine's closed set, as the wire spells it). */
import type { PermissionMode } from "../core/ask-origin.js";
/**
 * The explicit values of `crossSessionInbound`, loosest first: `wake` (deliver, and the HOST may start
 * a turn on this session when its box grows), `next-turn` (deliver at the session's next turn
 * boundary), `hold` (park for a human), `refuse`. The UI's spelling `"default"` means UNSET (mode
 * parity) and is folded to `undefined` by the resolver — it is not a distinct policy.
 *
 * @contract cross_session.wake_is_the_hosts_leg — `wake` is judged exactly as `next-turn` at the drain
 * (deliver); what it adds is the HOST's leg: a host that observes a `peer_message` or `engine_frame`
 * record appended to a session whose setting resolves to `wake` may start ONE turn on that session,
 * bounded by `maxWakesPerHour`, and the engine promises that the turn's first drain pass ATTEMPTS the
 * box (a claim that loses, a setting a host cannot read, an admission stop or the pass budget can
 * still leave the record for a later boundary — every such outcome is observable, none is silent).
 * With the budget spent, or on a host that starts no turns, `wake` degrades to `next-turn`: the record
 * stays in the box and the next user turn reads it. The engine never starts a turn itself.
 */
export type CrossSessionInboundSetting = "wake" | "next-turn" | "hold" | "refuse";
export declare const CROSS_SESSION_INBOUND_SETTINGS: readonly CrossSessionInboundSetting[];
export declare function isCrossSessionInboundSetting(value: unknown): value is CrossSessionInboundSetting;
/** Which layer decided the effective value. `"invalid"` = an unrecognized value was found in some
 *  layer and the fail-closed rule forced `hold` (the loud arm). */
export type CrossSessionSettingSource = "managed" | "user" | "repo" | "invalid";
export interface CrossSessionInboundSettingLayers {
    /** Organization-managed layer (CC `policySettings`): beats the user layer when set. It is NOT
     *  immune to repository TIGHTENING (CC form: the repo loop runs over whatever the first two layers
     *  resolved to) — a repo may make a managed `next-turn` stricter, never looser. */
    managed?: unknown;
    /** The user's own layer (CC `userSettings`/`flagSettings`): consulted after managed. */
    user?: unknown;
    /** Repository layers (CC `localSettings`/`projectSettings`), in precedence order. A repo layer can
     *  only TIGHTEN the standing value (wake < next-turn < hold < refuse), whichever layer set it; it can
     *  never loosen it — so `wake` written in a repo layer never takes effect (the unset baseline is
     *  `next-turn`, and a repo layer cannot loosen past it). */
    repo?: readonly unknown[];
}
export interface ResolvedCrossSessionInboundSetting {
    /** The effective explicit value; `undefined` = unset ⇒ mode parity. */
    value?: CrossSessionInboundSetting;
    decidedBy?: CrossSessionSettingSource;
    /** Layers whose value was neither an explicit setting nor the `"default"` spelling. Non-empty
     *  ⇒ the resolver applied the fail-closed rule (see `decidedBy: "invalid"`) unless the effective
     *  value was already at least as tight as `hold`. Reported so a host can warn — never swallowed. */
    invalidLayers: Array<"managed" | "user" | "repo">;
}
/**
 * CC `I` transcribed: managed beats user; repo layers may only tighten the standing value — including a
 * managed one (tightening is the safe direction; the loosening direction is what policy forbids) — and
 * take attribution on a tie unless managed decided; an unrecognized value anywhere forces `hold` when
 * the standing value is looser than `hold` (bad-value loudness: a garbage setting never silently reads
 * as `next-turn`).
 */
export declare function resolveCrossSessionInboundSetting(layers: CrossSessionInboundSettingLayers): ResolvedCrossSessionInboundSetting;
/**
 * The layers a CROSS-PRINCIPAL record is judged on: the principal's own
 * (`managed`, `user`). The repository layers speak for the workspace one terminal runs in; a record in
 * the principal inbox is addressed to the principal, and any of its terminals may win the box's lease —
 * reading the winner's repository would let the lease race decide the verdict. One projection, applied by
 * every drain lane before {@link resolveCrossSessionInboundSetting}.
 */
export declare function principalInboundLayers(layers: CrossSessionInboundSettingLayers): CrossSessionInboundSettingLayers;
/**
 * Why a message was held. The first eight are CC 2.1.250's closed set (`sne`), reachable exactly
 * where CC reaches them. `invalid-mode-attestation` is a sema-only arm: CC's envelope parser drops a
 * non-vocabulary `from-mode` before any judgment (the state is unreachable there); sema receives the
 * attestation as a TYPED store/wire field, where a garbage value is a producer bug that must hold
 * loudly rather than fold into "no class asserted" (which would DELIVER to a prompting recipient).
 * `cross-principal-default` is the other sema-only arm (CC has no cross-principal lane): a record that
 * carries the delivery gate's trust anchor (`fromScope`) and meets no explicit setting is held — the
 * principal arm has no mode parity to fall back on.
 */
export type CrossSessionHoldCause = "mode-mismatch" | "no-mode-asserted" | "explicit-setting" | "managed-setting" | "repo-setting" | "invalid-setting" | "bypass-default" | "mode-unknown" | "invalid-mode-attestation" | "cross-principal-default";
export declare const CROSS_SESSION_HOLD_CAUSES: readonly CrossSessionHoldCause[];
/** CC `sne` verbatim for the eight CC causes; the sema arm has its own sentence. */
export declare function describeCrossSessionHoldCause(cause: CrossSessionHoldCause): string;
export type CrossSessionInboundVerdict = {
    verdict: "deliver";
} | {
    verdict: "hold";
    cause: CrossSessionHoldCause;
    message: string;
    warning?: string;
} | {
    verdict: "refuse";
    cause: "opt-out";
};
export interface CrossSessionInboundInput {
    /** The recipient's resolved setting ({@link resolveCrossSessionInboundSetting}). */
    setting: ResolvedCrossSessionInboundSetting;
    /** The RECIPIENT's own permission-mode class right now ({@link foldPermissionModeClass});
     *  `"unknown"` fails closed (`mode-unknown`). */
    selfModeClass: PermissionModeClass | "unknown";
    /** The message under judgment. `undefined` = no message: the message-less POSTURE probe (CC `H`,
     *  what a session advertises as `cross_session_inbound: available|unavailable`) — the arm that
     *  reaches `bypass-default`. */
    sender?: {
        /** The sender's attestation as received (typed field; validated here, never assumed). */
        fromMode?: unknown;
        /** A session's message to itself never needs parity. */
        selfSent?: boolean;
        /** The organization delivery gate's typed trust anchor (`MailboxPeerMeta.fromScope`). Present ⇒
         *  the PRINCIPAL arm: the words come from another principal, so neither `fromMode` nor `selfSent` nor
         *  this session's own class is read, and an unset setting holds (`cross-principal-default`). The
         *  caller passes the principal's layers ({@link principalInboundLayers}) as `setting` for it. */
        fromScope?: string;
    };
}
/**
 * The four-state judgment at the RECIPIENT's drain point (judgment authority is the recipient's — its
 * settings, its current mode, judged when the message is consumed, not when it was sent).
 *
 * Explicit value always wins. Unset ⇒ mode parity: self-sent delivers; an undeterminable own mode
 * holds (`mode-unknown`); a message whose sender attested a class delivers on match and holds on
 * mismatch; a sender asserting no class is held only while this session bypasses prompts; the
 * message-less probe holds a bypassing session (`bypass-default`) and clears a prompting one.
 *
 * A record carrying the delivery gate's anchor (`sender.fromScope`) is judged on the PRINCIPAL arm: the
 * explicit value still wins exactly as above, and unset holds (`cross-principal-default`) — no parity, no
 * self-sent, no read of this session's class, so every terminal of the principal reaches the same verdict.
 */
export declare function judgeCrossSessionInbound(input: CrossSessionInboundInput): CrossSessionInboundVerdict;
/**
 * design/385 §4.4 — sema's two-class fold of its own permission posture, from the session's EFFECTIVE
 * permission mode (the engine's own resolution — never the requested one, never re-derived from spec shape)
 * and the wiring manifest's ask derivation ({@link AskEffective}):
 *  · `bypass` — the effective mode is `bypassPermissions`, OR no human decides an ask (`auto_allow`, a
 *    blanket answering seat — the adapter's own reading of "nobody is watching");
 *  · `"unknown"` — otherwise, when the ask derivation is `unresolved` (the judge fails closed on it);
 *  · `prompting` — otherwise: an ask reaches a human or parks for one (`human_reachable`, `park_only`),
 *    and — CC's literal rule for a never-prompting-never-bypassing mode — `auto_deny`.
 * `effective` absent (a leg with no mode fact) reads the ask derivation alone.
 *
 * WHAT THE CLASS IS: `fromMode` is a presence LABEL — whether a person is watching this session's approvals —
 * attested to a peer so a bypass session does not park work where nobody watches. It is not a permission
 * authority and authorizes no execution; the permission mode itself is read only from `effective`.
 */
export declare function foldPermissionModeClass(effective: PermissionMode | undefined, askEffective: AskEffective): PermissionModeClass | "unknown";
/** The synchronous send outcomes a sender can observe at the send point (CC's ten classes on sema's
 *  codes; `sender_paced` is expressed by the admission gate's `rate_limited` and is deliberately not a
 *  second code). `parked_offline` is a DISPOSITION (durable append succeeded, recipient offline) and
 *  not an error; `send_uncertain` exists only on the CC-adapter arm (a store append returns a seq or
 *  throws — there is no "written but unconfirmed" state to name). */
export type PeerSendVerdictCode = "peer_send.stale_socket" | "peer_send.socket_busy" | "peer_send.too_large" | "peer_send.invalid_target" | "peer_send.timeout" | "peer_send.recipient_refuses" | "peer_send.not_reachable" | "peer_send.subscription_cap" | "peer_send.send_uncertain" | "peer_send.other";
export declare const PEER_SEND_VERDICT_CODES: readonly PeerSendVerdictCode[];
/** CC `Be`: three classes are DEGRADED (the send may still have effect / the refusal is best-effort),
 *  the rest are errors. */
export declare function peerSendVerdictSeverity(code: PeerSendVerdictCode): "error" | "degraded";
/** How a successful send was carried and where it stands. `via` discloses the lane (store = durable
 *  mailbox, uds = the CC-dialect socket adapter); `parked_offline` promises crash-durability under the
 *  deployment's mailbox retirement policy, not unbounded delivery. */
export type PeerSendVerdict = {
    ok: true;
    disposition: "delivered" | "queued" | "parked_offline";
    via: "store" | "uds";
} | {
    ok: false;
    code: PeerSendVerdictCode;
    severity: "error" | "degraded";
    message: string;
};
