/** One user-reachable navigation affordance, keyed stably across base/head. */ export type NavigableItem = { /** * Stable identity across captures. `route:` for internal * links; `:` for tabs / menu items / button-only nav — so a * tab labelled "MODEL CONFIG" keys as `tab:model-config` regardless of styling, * and lines up with an app's own view id. */ key: string; kind: 'link' | 'tab' | 'menuitem' | 'nav-button'; /** Visible accessible name at capture time (for the report). */ label: string; /** Resolved same-origin path, for `kind: 'link'`. */ href?: string; }; export type InventoryDelta = { /** Present on head, absent on base — a newly-offered affordance (informational). */ added: NavigableItem[]; /** Present on base, absent on head — a feature the UI stopped offering (gates). */ removed: NavigableItem[]; }; /** `key -> reason` — removals that are intentional, reviewed, and on the record. */ export type AllowedRemovals = Record; /** * Read the acknowledged-removals file (`$STYLEPROOF_INVENTORY` or * `styleproof.inventory.json`). `{}` when absent; THROWS on malformed JSON — the * caller picks the policy (the CI gate fails loud so a broken ack file can't silently * un-acknowledge a real loss; the advisory report degrades to `{}`). */ export declare function readAckFile(): AllowedRemovals; /** One raw navigable affordance as read from the DOM, before classification. */ export type RawAffordance = { tag: string; role: string; name: string; /** pathname+search for a same-origin ``; null otherwise. Resolved in-page. */ internalPath: string | null; /** `data-testid` — developer-authored, trusted as a stable identity when present. */ testId: string | null; /** `id` — used as a stable identity only when it doesn't look framework-generated. */ domId: string | null; /** `aria-controls` (a tab's panel) — a stable identity when not framework-generated. */ controls: string | null; }; /** In-page: collect visible navigable affordances. No classification. */ export declare function collectNavAffordances(): RawAffordance[]; /** * Whether an `id` / `aria-controls` value is a STABLE identity worth keying on, vs a * framework-generated one (React useId `:r0:`, Headless UI `headlessui-tabs-tab-3`, * Radix `radix-:r1:`, Emotion hashes) that wobbles across renders/builds. Keying by a * generated id would ADD churn, so those fall back to the label slug. (`data-testid` is * developer-authored by definition, so it's trusted without this check.) */ export declare function isStableId(id: string | null | undefined): id is string; /** Pure: turn raw affordances into keyed, deduped, sorted navigable items. */ export declare function classifyInventory(raw: RawAffordance[]): NavigableItem[]; /** Harvest a page's inventory: thin in-page collect + pure classify. */ export declare function harvestInventory(page: { evaluate: (fn: () => T) => Promise; }): Promise; /** Union the per-surface inventories of a whole run into one reachable set. */ export declare function unionInventory(perSurface: Array<{ inventory?: NavigableItem[]; } | undefined>): NavigableItem[]; /** Base vs head reachable sets → what the UI newly offers / stopped offering. */ export declare function diffInventory(base: NavigableItem[], head: NavigableItem[]): InventoryDelta; /** * The gate. Removals that aren't acknowledged in `allowed` (key -> reason) are * unexplained — the caller fails on a non-empty result. An `allowed` key that * isn't actually removed is a stale acknowledgement, returned separately so the * ledger can't quietly rot (mirrors the `exclude` coverage guard). */ export declare function auditRemovals(delta: InventoryDelta, allowed?: AllowedRemovals): { unexplained: NavigableItem[]; staleAllowances: string[]; }; /** * Run-level entry point: union both sides' per-surface `map.inventory`, diff, and * audit removals. This is what a gate calls — pass every base map and every head * map (the reachable set is the union across all surfaces). `unexplained` non-empty * ⇒ the gate should fail; `staleAllowances` non-empty ⇒ prune the ledger. */ export declare function auditRunInventory(baseMaps: Array<{ inventory?: NavigableItem[]; } | undefined>, headMaps: Array<{ inventory?: NavigableItem[]; } | undefined>, allowed?: AllowedRemovals): { delta: InventoryDelta; unexplained: NavigableItem[]; staleAllowances: string[]; };