import type { AgentConfig, Skill } from "../contracts.js"; export interface PrefixStabilityConformanceOptions { /** * The host's own agent config, minus `provider`, `providerSource`, and `skills`: * the runner installs its fixture provider and fixture skill registry so the * scenario is deterministic and comparable across hosts. */ readonly host: Omit; /** Two distinct skills: the fixture loads `[0]` on the first turn and `[1]` on the second. */ readonly skills: readonly [Skill, Skill]; /** Minimum shared byte-prefix fraction between consecutive requests. Default `0.95`. */ readonly minContinuity?: number; /** * Which fraction gates the run: `"providerPrefix"` (default, today's behavior) asserts the * provider-visible prefix; `"cacheablePrefix"` asserts the same measurement with tail segments * removed, so a body-heavy or eager host is not failed for the tail it deliberately re-sends. */ readonly assertOn?: "providerPrefix" | "cacheablePrefix"; /** Turn inputs; defaults are fixed strings so runs are comparable across hosts. */ readonly inputs?: readonly [string, string]; /** * How many request pairs may break below `minContinuity` (default `0`, today's behavior). Use * `1` for an assembly that folds or evicts exactly one boundary — an attention-compiler fold, * a compaction, a budget eviction. More resets than declared fail, and fewer fail too: the * fixture was supposed to invalidate the prefix, so a run that never did cannot pass vacuously. */ readonly allowedResets?: number; } export interface PrefixStabilityConformanceResult { /** Provider requests captured by the fixture (two per turn: skill load, then completion). */ readonly requests: number; /** Lowest shared-prefix fraction observed across consecutive captured requests. */ readonly minContinuity: number; /** * The same lowest fraction with the session's tail segments removed from both requests of each * pair — the provider-visible prefix the cache can actually keep paying for. Equals * `minContinuity` when no captured request carried a tail segment. */ readonly cacheableContinuity: number; /** * 1-based indexes of the captured requests whose asserted prefix broke below `minContinuity` * (the later request of each pair), in ascending order — where the assembly invalidated the * prefix instead of appending. Empty when every gap stayed above the minimum. */ readonly resets: readonly number[]; } /** * Drive a real session through two staggered skill loads and assert that each * provider request keeps a byte-identical leading prefix (messages **and** tool * schemas) with its predecessor. Progressive disclosure appends a loaded body * after the stable prefix, so the shared prefix stays intact; a host that * rewrites the context block, the skill catalog, or any leading message per * request fails with the offending request pair and the measured fraction. * Reports both the provider-visible fraction and the same fraction with the * session's tail segments removed; `assertOn` picks which one gates the run. * A gap below the minimum is collected as a reset instead of failing in the * loop, so `allowedResets` can permit the one boundary an assembly folds at. */ export declare function runPrefixStabilityConformance(options: PrefixStabilityConformanceOptions): Promise;