import type { UsageFilter, UsageRepository } from '../db/repositories/usage-repository.js'; /** * Spend against a target, and where it is heading. * * Nothing in the tool surface accepted a budget number, so extrapolating * month-end spend meant reading the active days out of `daily` and picking a * denominator -- calendar days? active days? -- by hand. That is a modelling * choice, and the two answers differ by a factor of two on a machine used on * weekdays only. This reports BOTH, labelled, and never blends them into one * "projected" figure. * * The prior question the issue raises -- which cost figure a Pro/Max subscriber * should budget from -- is answered the same way `--fail-over` answers it: the * caller names the basis. There is no default. Reported and estimated cost are * separate figures that are never summed, so a budget with no stated basis is a * budget against nothing in particular. */ export type BudgetBasis = 'reported' | 'estimated'; export declare const BUDGET_BASES: BudgetBasis[]; /** A calendar period has an end to project towards; a rolling window does not. */ export type BudgetPeriod = 'month' | 'week'; export declare const BUDGET_PERIODS: BudgetPeriod[]; export interface Projection { /** Spend per day on this denominator. */ ratePerDay: number; /** Where the period ends up at this rate. */ projected: number; /** Positive when the projection exceeds the budget; absent when it does not. */ overBy?: number; /** The denominator used, so the figure can be checked by hand. */ days: number; } export interface BudgetReport { period: { since: string; until: string; label: string; }; basis: BudgetBasis; amount: number; /** Spend so far on the chosen basis only. Never a blend of the two. */ spent: number; remaining: number; /** Spend as a fraction of the budget. May exceed 1. */ fractionUsed: number; /** Whole and partial days elapsed, and the period's full length. */ elapsed: { days: number; totalDays: number; fraction: number; }; /** Elapsed days with any recorded activity. The second denominator. */ activeDays: number; /** Deliberately two, because the choice of denominator changes the answer. */ projections: { perCalendarDay: Projection; perActiveDay: Projection; }; /** True when SPENT already exceeds the budget. A fact, not a forecast. */ overBudget: boolean; /** Things that would make the figures misleading if unsaid. Never empty. */ caveats: string[]; } export declare function budgetWindow(period: BudgetPeriod, now?: Date): { since: Date; until: Date; label: string; }; export declare class BudgetService { private readonly repo; constructor(repo: UsageRepository); budget(options: { amount: number; basis: BudgetBasis; period: BudgetPeriod; filter?: UsageFilter; now?: Date; }): BudgetReport; private caveats; }