export { routeCostEvidence, attemptCostEvidence } from "./cost-evidence.js"; import type { BudgetLease, BudgetObservation, CostEvidence, CostKnowledge, CredentialRoute, Intent, PaidBudget, QuotaSnapshot } from "@claudexor/schema"; import { type SharedFinancialState } from "./shared-financial-state.js"; export type CircuitTier = "ok" | "soft" | "downgrade" | "hard"; /** Budget terminal REASON (D8 axes vocabulary): a subset of RunReason. A * budget stop always maps the run lifecycle to `failed` with one of these * reasons — the old status words exhausted/exhausted_overshoot are gone. */ export type BudgetTerminal = "budget_exhausted" | "budget_overshoot" | "cost_unverifiable" | null; /** One model-applicability predicate for every quota consumer. * Omitted/null scope is a vendor-wide window. A null model is the deliberate * vendor-native default: its concrete model is unknowable before spawn, so a * model-scoped window alone cannot refuse the route. Undefined means the * caller supplied no model context and preserves conservative matching. */ export declare function quotaConstraintAppliesToModel(constraint: { applies_to_models?: string[] | null; applies_to_unspecified_model?: boolean; }, model?: string | null): boolean; export interface CircuitThresholds { soft: number; downgrade: number; hard: number; } export interface ReserveInput { taskId: string; attemptId?: string; intent: Intent; harnessId: string; modelHint?: string | null; reason?: string[]; cost?: CostEvidence; } export interface BudgetSettlement { knowledge: CostKnowledge; /** Cash certainty is independent from subscription valuation certainty. */ cashKnowledge?: CostKnowledge; /** Valuation certainty is independent from billed cash certainty. */ valuationKnowledge?: CostKnowledge; source: string; provenance: string[]; cashUsd?: number; valuationUsd?: number; } export interface ReserveResult { granted: boolean; tier: CircuitTier; lease?: BudgetLease; reason?: string; denied?: "hard_cap" | "estimate_headroom" | "finite_zero" | "unknown_paid_in_flight"; } /** Stable fingerprint of a prompt for loop detection. */ export declare function promptFingerprint(prompt: string): string; /** Root and task-scoped views share family finances, leases, holds and caps. * Task views expose their own totals; routing, quota and prompt-loop evidence * stay view-local. */ export declare class BudgetLedger { markPhysicalDispatchStarted(leaseId: string): void; private readonly observations; private readonly quotaSnapshots; private readonly promptCounts; private readonly financial; private readonly taskScope; private readonly localOnCashSettled?; private released; constructor(budget?: PaidBudget, thresholds?: CircuitThresholds, deps?: { /** * Fires after every settle with the CUMULATIVE ledger truth. The ledger * is the one owner of "how much real money this run has spent" — * subscription-entitled work settles to cash 0 here (W4.3 sol #15), so * consumers (run events → UI) render cash without inferring from route * labels. Valuation rides along for telemetry, never for the cash fact. */ onCashSettled?: (cashSpendUsd: number, valuationUsd: number, cashEstimated: boolean, valuationKnowledge: CostKnowledge, cashKnowledge: CostKnowledge) => void; }, shared?: { financial: SharedFinancialState; taskScope: string; }); scopedToTask(taskId: string, onCashSettled?: (cashSpendUsd: number, valuationUsd: number, cashEstimated: boolean, valuationKnowledge: CostKnowledge, cashKnowledge: CostKnowledge) => void): BudgetLedger; private outstandingHolds; private cap; tier(): CircuitTier; remainingUsd(): number | null; reserve(input: ReserveInput): ReserveResult; /** Admit the exact next physical send under its existing logical lease. * Previous streamed amounts and unknown-paid debt survive until settlement. */ repriceReservedLease(leaseId: string, evidence: CostEvidence): ReserveResult; private reservationDenial; /** Raise the hold from actual streamed cash/unknown usage. Subscription * valuation never calls this; an in-attempt API fallback does. */ updateHold(leaseId: string, streamedCashUsd: number): void; settle(leaseId: string, settlement: BudgetSettlement): void; cancel(leaseId: string): void; spend(): number; cashKnowledge(): CostKnowledge; valuation(): number; estimated(): boolean; valuationKnowledge(): CostKnowledge; terminal(): BudgetTerminal; /** Cancel every still-reserved lease owned by this scoped task and detach * its callback. Used when a delegated child reaches terminal. */ releaseTask(): void; private assertTaskScope; private leaseForMutation; observe(observation: BudgetObservation): void; /** Seed durable quota projection without collapsing credential identities. */ observeQuotaSnapshot(snapshot: QuotaSnapshot): void; observationsFor(harnessId: string): BudgetObservation[]; cooldownActive(harnessId: string, credentialRoute?: CredentialRoute, credentialSubjectId?: string | null, now?: number, model?: string | null): boolean; /** Binding pacing slack across applicable windows; null means honestly unknown. */ bindingPaceSlack(harnessId: string, credentialRoute?: CredentialRoute, credentialSubjectId?: string | null, now?: number, model?: string | null): number | null; /** Fresh snapshots for a harness+route, optionally pinned to ONE credential * subject (release wave round-16 #2): when the caller knows the effective * subject — a profile id, or null for the engine default — only that * subject's windows apply, so profile A's exhaustion never cools profile B * or the default. `undefined` = subject unknown, conservative any-subject. */ private snapshotsFor; recordPrompt(fingerprint: string): number; isLoop(fingerprint: string, threshold?: number): boolean; } export declare function isBudgetTerminal(reason: string | null): reason is Exclude; //# sourceMappingURL=ledger.d.ts.map