/** * Twelve services, one rollup, and the one that is actually bleeding. * * `profile` merges a directory of logs into one bill, which is right for one * service and wrong for a fleet: the merged report hides which service the * money is coming from, per-service budgets cannot exist at all, and the * findings a *comparison between services* could make are invisible — the * same workload on Opus in one team and Haiku in another is a decision * somebody should get to see, and no single merged total shows it. * * This module does the fleet arithmetic on reports the caller already built. * It reads no files and runs no globs against a filesystem — the caller hands * it file names and per-source reports, so the module stays browser-safe and * the CLI keeps its monopoly on I/O. * * **The rollup refuses to average what it cannot compare.** Two sources whose * logs cover different periods can be *summed* — a total is a total — but a * share of that total is not a comparison of rates, and the module says which * sources cover which days rather than letting a 3-day log look cheap beside * a 30-day one. */ import type { UsageProfileReport } from './usage.js'; /** * Which source each file belongs to. * * Assignment is by the most specific matching glob, so `services/api/**` * beats `services/**` on the same file — the same tie-break the budget * patterns use, because two rules for pattern precedence in one tool is one * rule too many. Files matching no source are returned rather than dropped: * a log that silently joined no report would be spend missing from every * bill, which is the flattering omission this repository refuses everywhere. */ export declare function assignSources(files: string[], sources: Record): { bySource: Map; unmatched: string[]; }; export interface FleetSource { name: string; report: UsageProfileReport; } export interface FleetRollup { /** Sum over every source. A total is a total, whatever the spans. */ totalUsd: number; calls: number; /** Every source, dearest first, with its share of the fleet's total. */ sources: { name: string; usd: number; calls: number; share: number; spanDays: number | null; }[]; /** * The one that is actually bleeding: the dearest source, with its share — * or null when the fleet spent nothing, because "nothing is bleeding" and * "the worst of nothing" are different statements. */ worst: { name: string; usd: number; share: number; } | null; /** * True when the sources' logs cover meaningfully different periods (their * spans differ by more than one day, or some carry no clock at all). Shares * of the total remain valid — they are shares of a sum — but reading them * as *rate* comparisons is exactly the mistake this flag exists to stop, * and every rendering states it when set. */ mismatchedSpans: boolean; /** * The same workload label running on different models in different sources * — one team on Opus, another on Haiku, same job. A merged bill renders * this invisible: the label's slices coexist with no seam. Only splits * where both sides carry real spend are reported, dearest gap first. */ splitBrains: { label: string; sources: { name: string; model: string; usd: number; }[]; }[]; /** * Sources where caching lost money while the fleet's aggregate paid off. * An aggregate verdict is the flattering rendering when three sources are * quietly underwater; each is named with its own delta. Sources whose * verdict matches the aggregate are not listed — this is the exception * report, not the census. */ cacheUnderwater: { name: string; deltaUsd: number; }[]; } export declare function fleetRollup(sources: FleetSource[], options?: { /** * Per-source cache verdict delta, positive meaning caching added money to * the bill — the caller computes it with `cacheEconomics` because that * module owns the counterfactual, and this one must not restate it. */ cacheDeltas?: Map; /** The fleet-wide delta under the same convention. */ aggregateCacheDelta?: number; }): FleetRollup; //# sourceMappingURL=fleet.d.ts.map