/**
 * Durable-plan application-shell contract.
 *
 * The sandbox SDK owns the authoritative plan lifecycle and decision APIs.
 * This module only projects that substrate state into chat events and
 * persisted message parts that products can render and restore.
 */
declare const PLAN_SUBMITTED_EVENT: "plan.submitted";
/** Sandbox plan lifecycle. `preparing` is the transient submission state and
 * is retained in the projection even though the chat card normally starts at
 * `pending`. */
type ChatPlanStatus = 'preparing' | 'pending' | 'approved' | 'rejected' | 'superseded' | 'withdrawn';
type ChatPlanBase = {
    /** The sandbox SDK calls this field `id`; the transcript projection names
     * it explicitly so it cannot collide with a message-part id. */
    planId: string;
    revision: number;
    title?: string;
    body: string;
    submittedAt: string;
    /** Provider/Sandbox metadata is deliberately opaque to this package. */
    metadata?: Record<string, unknown>;
    decidedBy?: string;
};
/** Browser/persisted projection of the sandbox SDK's durable-plan union. */
type ChatPlan = ChatPlanBase & ({
    status: 'preparing';
} | {
    status: 'pending';
} | {
    status: 'approved';
    decidedAt: string;
} | {
    status: 'rejected';
    decidedAt: string;
    feedback: string;
} | {
    status: 'superseded';
    supersededAt: string;
    supersededByPlanId: string;
} | {
    status: 'withdrawn';
    withdrawnAt: string;
    withdrawnReason: string;
});
/** Canonical transcript part for one durable plan. */
type ChatPlanPersistedPart = ChatPlan & {
    type: 'plan';
};
type ParsePlanSubmittedResult = {
    succeeded: true;
    value: ChatPlan;
} | {
    succeeded: false;
    error: string;
};
declare function planPartKey(planId: string): string;
declare function planRevisionKey(planId: string, revision: number): string;
declare function planFollowUpTurnId(planId: string, outcome: 'approved' | 'rejected'): string;
/** Plan status is monotonic: only a pending plan can settle. */
declare function canTransitionPlanStatus(from: ChatPlanStatus, to: ChatPlanStatus): boolean;
declare function planToPersistedPart(plan: ChatPlan): ChatPlanPersistedPart;
declare function persistedPartToPlan(part: Record<string, unknown>): ChatPlan | null;
/** Parses both direct sandbox events (`data.plan`) and session envelopes
 * (`properties.plan`). Session identity is carried by the surrounding stream
 * and is deliberately not required in the payload. */
declare function parsePlanSubmittedEvent(event: unknown): ParsePlanSubmittedResult;

export { type ChatPlan, type ChatPlanPersistedPart, type ChatPlanStatus, PLAN_SUBMITTED_EVENT, type ParsePlanSubmittedResult, canTransitionPlanStatus, parsePlanSubmittedEvent, persistedPartToPlan, planFollowUpTurnId, planPartKey, planRevisionKey, planToPersistedPart };
