/** * Org sections spec 6.9 and 13.2 (piece P4.1): spend aggregation by section, the 80 percent threshold and the * closure state, as one pure function over a snapshot of the per-role spend the runtime already keeps (a live * role's `usageUsd` and its slot's `retiredUsage.costUsd`). Nothing is persisted: the status is derived at * any moment, so a respawn or a resume neither resets nor double counts spend. Inert like the rest of P4.1. */ import { type BudgetDef } from './section-budget.js'; /** Share of an allocation or cap at which the lead and the root are warned. The same value as * `BUDGET_WARN_FRACTION` in budget-closure.ts (a test pins the two equal; that file is not imported so this * one stays free of the daemon). */ export declare const SECTION_BUDGET_WARN_FRACTION = 0.8; /** What one role has spent: the live incarnation and what replaced incarnations retired into its slot. One * entry per role (per slot), so a replaced incarnation is never a second entry and cannot count twice. */ export interface RoleSpend { usd: number; retiredUsd: number; } export type SpendSnapshot = Record; /** `unallocated`: nothing to measure against. `ok` below 80 percent, `warn` from 80 percent, `closed` at or * above the allocation (the comparison `PolicyEngine.overBudgetUsd` makes for a role). */ export type ClosureState = 'unallocated' | 'ok' | 'warn' | 'closed'; export declare const SNAPSHOT_PROBLEM_CODES: readonly ['SPEND_NOT_A_NUMBER', 'SPEND_NEGATIVE']; export type SnapshotProblemCode = (typeof SNAPSHOT_PROBLEM_CODES)[number]; export interface SnapshotProblem { code: SnapshotProblemCode; roleId: string; /** `usd` or `retiredUsd`. */ field: keyof RoleSpend; message: string; } export interface RoleStatus { roleId: string; spentUsd: number; retiredUsd: number; /** The role's own cap (`budget_usd`), when it has one that resolves. */ capUsd: number | undefined; fraction: number | undefined; state: ClosureState; } export interface GroupStatus { /** The allocation: the section's `budget.usd`, the root reserve, or the org budget. */ allocationUsd: number | undefined; /** Sum of the role caps charged to this allocation (the org: every role's). */ roleCapSumUsd: number; spentUsd: number; /** Of `spentUsd`, what replaced incarnations retired. */ retiredUsd: number; fraction: number | undefined; state: ClosureState; } export interface AllocationStatus { org: GroupStatus; sections: Array; reserve: GroupStatus & { roles: RoleStatus[]; }; /** Spend of snapshot roles the definition no longer has (a role removed by a reload keeps its spend). It * counts in the org total and in no section. */ unattributedUsd: number; /** Roles of the definition with no entry in the snapshot: spend unknown, not read as zero. */ unrecorded: string[]; problems: SnapshotProblem[]; } /** Per-section, root-reserve and org spend from a snapshot. Invariants (pinned by property tests): the spend * of every section plus the reserve plus `unattributedUsd` equals the org spend, which equals the sum over * the snapshot's roles of `usd + retiredUsd`; every role is counted once, a lead once, the root in the * reserve. A malformed amount (not finite, or negative) is reported in `problems` and counted as zero. */ export declare function allocationStatus(def: BudgetDef, snapshot: SpendSnapshot): AllocationStatus; //# sourceMappingURL=section-budget-status.d.ts.map