/** * Ledger repair: remove usage that was never this repository's, and collapse * coverage that is counted twice. * * Two passes, both driven by evidence already in the ledger rather than by a * heuristic, and both going through `rewriteLedger` so a crash leaves either the * old file or the new one. * * **Foreign purge** (turn-scoped-cost/AC-34, AC-43). An entry's `cursor` is the * transcript uuid it was extracted from, so provenance is checkable. Measured on * this repo: 711 entries / 262.5M tokens came from an unrelated project — * `interactive-cli-menu` overstated by $131.67 and the whole of * `release-blog-tag-deadlock`'s $58.42 was another repo's work. Only entries * *positively shown* to be foreign are removed; `ambiguous` and `unknown` are * kept, because under-recovering is the safe direction when the alternative is * deleting real cost history. * * **Containment collapse** (turn-scoped-cost/AC-42). `applyPrecedence` reduces an * entry's weight only by coverage of a *higher* fidelity rank, so two entries of * the same session and fidelity where one window contains the other both keep * weight 1. A bulk `metered` sweep that recorded a whole transcript therefore * double-counts any narrower entry for the same session: verified minimally as * counted 1100 against a truth of 1000. This is why the purge cannot simply * delete foreign rows and stop — a nested entry for the surviving session waits in * `unattributed.ndjson`, and recovering it would take the repaired $354.32 straight * back up to $380.10. * * Requirements: turn-scoped-cost/AC-34, AC-42, AC-43, AC-45, AC-9 * Design: design.md Part 0 (D0.2, D0.6, D0.7, D0.8) */ import type { CostEntry } from './types.js'; import { type ProvenanceIndex } from './provenance.js'; import type { ProviderEnv } from './providers/provider.js'; export interface PurgeReport { /** Entries removed as positively foreign, per ledger. */ foreignRemoved: Record; /** Entries removed as redundant same-session same-fidelity containment. */ containedRemoved: Record; /** Entries left alone because provenance was ambiguous or unknown. */ keptUnprovable: number; /** Token totals before and after, so the delta is reported rather than asserted. */ tokensBefore: number; tokensAfter: number; } /** * Entries whose coverage is fully contained by another entry of the same session, * fidelity and model — and strictly narrower, so the pair is never mutually * eliminating. * * Model is part of the key on purpose. `capturePass` buckets per model, so two * entries of one session can share a window while describing genuinely different * tokens; collapsing those would delete real usage. Measured: 0 same-model * containment pairs currently sit inside any ledger, so this pass is a guard * against recovery reintroducing one rather than a cleanup of existing rows. */ export declare function containedEntries(entries: CostEntry[]): Set; /** * Repair every ledger in the project. * * Idempotent by construction, and idempotent against a subsequent * `aidlc cost sync` only because repo scoping landed first — without it, sync * re-adds exactly what this removes (AC-45). */ export declare function purgeLedgers(projectRoot: string, env?: ProviderEnv, index?: ProvenanceIndex): PurgeReport; //# sourceMappingURL=purge.d.ts.map