/**
 * window/strategies/drop — the mechanic both drop strategies share.
 *
 * Pattern: One pure function over a `WindowStrategyInput`.
 * Role:    core/ layer. `slidingWindow` and `tokenBudget` differ ONLY in when
 *          they engage and what they file; what actually leaves the window is
 *          decided here, once, so a refusal reason means the same thing under
 *          both — and under compaction, which asks the same `planRemoval`.
 * Emits:   N/A.
 *
 * A drop makes no LLM call and writes no summary. What it must still do is
 * keep the request valid and keep the record honest:
 *
 *   • the span comes from the shared refusal engine, so the CURRENT REQUEST,
 *     an unanswered tool call, the paused tool, a pending check-in and the
 *     recent turns never leave, and each refusal is named;
 *   • when the span reaches the front of what may leave, an authored notice
 *     takes that position — the window must open on a user turn (see
 *     notice.ts), and a message we are forced to author should tell the
 *     truth. That position is the window's HEAD in the ordinary case, and the
 *     slot just after the kept request when the request was the head;
 *   • when it does not, nothing is inserted: the original opening turn is
 *     still there, so there is no wire problem to solve.
 *
 * ## The notice is owed to the WIRE, not to politeness (9.57.0)
 *
 * That distinction used to be missing here, and it produced a livelock. The
 * notice was authored whenever the removal reached the front of what may
 * leave, and the whole removal was abandoned when the notice was not smaller
 * than the span — but the obligation being guarded is narrower: **the window
 * must open on a user turn.** When the message that would BECOME the head is
 * already a user turn (the kept request, or an older user turn from a restored
 * conversation), no notice is owed at all, and its 245–358 characters had no
 * business vetoing a legitimate drop.
 *
 * Because the span is the longest CONTIGUOUS removable run, a blocker one turn
 * along caps it at the same small span at every boundary — so the same verdict
 * came back for ever and the window grew without bound. Two locally-correct
 * rules composing into non-progress.
 *
 * So the decision is a LADDER: the rich notice, else the plain one, else no
 * notice at all — and `'replacement-not-smaller'` only when the wire genuinely
 * needs a message in that position and none of them is smaller than the span.
 */
import type { LLMMessage } from '../../../../provider-contract/types.js';
import type { WindowEviction, WindowStrategyInput } from '../strategy.js';
import type { WindowRefusal } from '../types.js';
/** What a drop attempt did, in the terms a record needs. */
export interface DropOutcome {
    /** Every turn that refused to leave, named. */
    readonly refusals: readonly WindowRefusal[];
    /** The new window; absent when nothing was dropped. */
    readonly window?: readonly LLMMessage[];
    readonly rebase?: {
        readonly headCount: number;
        readonly keptTailCount: number;
        readonly insertedAtMs?: number;
    };
    readonly removedStageIds: readonly string[];
    readonly removedMessageCount: number;
    readonly evictions: readonly WindowEviction[];
    readonly windowCharsBefore: number;
    readonly windowCharsAfter: number;
    /** Turns in the window before / after. Counted from the segmentation. */
    readonly turnsBefore: number;
    readonly turnsAfter: number;
}
/**
 * Drop the oldest contiguous removable span, if there is one.
 *
 * @param input            the strategy's input, with the bound refusal engine
 * @param keepRecentTurns  how many trailing turns are off-limits
 * @param strategyName     named in the authored notice, so a reader of the
 *                         window itself can tell which policy removed things
 */
export declare function dropOldestSpan(input: WindowStrategyInput, keepRecentTurns: number, strategyName: string): DropOutcome;
