Rulvar API reference / @rulvar/core / CostReport
Interface: CostReport
Defined in: packages/core/src/engine/run-handle.ts:26
Full contract: https://docs.rulvar.com/guide/observability.
Properties
| Property | Type | Description | Defined in |
|---|---|---|---|
abandoned | { unpriced: { model: string; usage: Usage; }[]; usageApprox?: boolean; usd: number; } | Priced spend under abandoned subtrees, exactly the part totalUsd excludes. unpriced here surfaces abandoned slices with no price row (the top-level unpriced lists only slices contributing to totalUsd), and usageApprox follows the same semantics as the top-level flag over the abandoned entries; grossUsd is an estimate whenever either flag is raised. | packages/core/src/engine/run-handle.ts:74 |
abandoned.unpriced | { model: string; usage: Usage; }[] | - | packages/core/src/engine/run-handle.ts:76 |
abandoned.usageApprox? | boolean | - | packages/core/src/engine/run-handle.ts:77 |
abandoned.usd | number | - | packages/core/src/engine/run-handle.ts:75 |
basis | "locally-estimated" | Where every dollar of this report comes from (RV1413): journaled usage priced at the CALLER'S pricing table (declared rates or adapter caps), never a provider statement. Always 'locally-estimated' today, declared as a literal so finance tooling never has to guess, mirroring InvoiceExport.pricingBasis; reconcile real bills through the invoice export and reconcileStatement, which carry their own provenance. | packages/core/src/engine/run-handle.ts:36 |
byAgentType | Record<string, number> | Spawn agentType names; absent and empty fold under 'unknown' (RV3604). Since RV4206 the vacuum is FILLED by pure derivation from recorded facts (agentTypeBucket over agentType, role, and dispatch label, the RV3905 phase precedent): the orchestrator's own dispatches read 'orchestrator' (the coordination loop and the forced-finish wake), 'synthesizer' (compositions and incremental notes), 'claim-judge', and 'citation-judge'; a spawned profile always keeps its own name, no journal byte changes, and archived journals fold to the named rows retroactively. The sixth comparison run's report read this table 100% 'unknown' over a run whose every dispatch had a nameable stage. | packages/core/src/engine/run-handle.ts:115 |
byModel | Record<string, number> | Keyed by canonical ModelRef 'adapterId:model'. | packages/core/src/engine/run-handle.ts:80 |
byPhase | Record<string, number> | ctx.phase names; phase is structural for this map. Spend with no phase, or an EMPTY phase, folds under the named 'unknown' bucket (RV3604): a '' key is unaddressable in every downstream table, and the third comparison run's report read byPhase {"": 5.58} for the whole run. In dynamic runs the orchestrator's own stages name their dispatches since RV3905 ('fan-out' children, 'coordination' loop turns and the forced-finish wake, 'composition' synthesis and incremental notes, 'judge' claim passes, 'repair' the bounded claim repair round), filling only the vacuum: an explicit host ctx.phase around the orchestration keeps its own bucket. The fourth comparison run's report read byPhase 100% 'unknown' over stages the journal held apart. The 'repair' bucket additionally receives the granted mechanical repair turns' own wires (RV4002): the call that immediately follows a rejected terminal-tool exchange carries a wire-level override, so a draft or composition repair's money no longer drowns in its hosting dispatch's bucket (the fifth comparison run's one draft repair wire read 'coordination'). | packages/core/src/engine/run-handle.ts:101 |
byRole | Record<InvocationRole, number> | - | packages/core/src/engine/run-handle.ts:116 |
byScope | Record<string, number> | Spend per journal scope (RV3805): the root and every child are addressable rows whose sum equals totalUsd, so the children versus whole-workflow cut (the third comparison analysis had to hand-aggregate it from invoice rows) reads off the report directly. The root's OWN scope is the empty string BY CONSTRUCTION, present data rather than an absence, so it folds under the named 'root' bucket; children keep their scope strings verbatim, and only a truly absent scope folds under 'unknown', the RV3604 fallback. | packages/core/src/engine/run-handle.ts:128 |
grossUsd | number | The gross/net split (P1.3): totalUsd + abandoned.usd, every priced terminal slice with abandonment included. This is the immutable provider-spend figure an invoice reconciles against; abandoning a branch never shrinks it. | packages/core/src/engine/run-handle.ts:51 |
orchestrator | { forcedFinish: boolean; reserveUsedUsd: number; share: number; spentUsd: number; wakes: number; } | All-zero with forcedFinish false in runs without a dynamic orchestrator (or when no cap resolved, so no sub-account opened). Folded purely from the journal: spentUsd is the priced usage of entries debited to the orchestrator sub-account, reserveUsedUsd its reserve-funded forced-finish share, wakes the ARMED (journaled) wake suspensions (a wait satisfied synchronously never suspends and is not counted), and forcedFinish the journaled at-cap decision. | packages/core/src/engine/run-handle.ts:138 |
orchestrator.forcedFinish | boolean | - | packages/core/src/engine/run-handle.ts:143 |
orchestrator.reserveUsedUsd | number | - | packages/core/src/engine/run-handle.ts:144 |
orchestrator.share | number | spentUsd / max(totalUsd, 0.01): the epsilon-floored H-OrchShare input. | packages/core/src/engine/run-handle.ts:141 |
orchestrator.spentUsd | number | - | packages/core/src/engine/run-handle.ts:139 |
orchestrator.wakes | number | - | packages/core/src/engine/run-handle.ts:142 |
totalUsd | number | The NET ledger: priced terminal usage with abandoned subtrees contributing zero (their spend is a sunk cost of branches the orchestrator discarded, not of the work the run kept). The provider still billed them: reconcile invoices against grossUsd, never this. | packages/core/src/engine/run-handle.ts:44 |
unpriced | { model: string; usage: Usage; }[] | Usage on models absent from pricing; never a silent zero. | packages/core/src/engine/run-handle.ts:147 |
usageApprox? | boolean | Present and true when any terminal entry folded into totalUsd carried approximate usage (a transport cut, a stream the ceiling severed, or an abort estimated the turn instead of the provider reporting it), so totalUsd is a lower bound estimate, never an exact charge. Absent means every contributing entry reported exact usage. The field the v1.39.0 review asked the report to raise so approximate cost is never shown as though it were the provider invoice. | packages/core/src/engine/run-handle.ts:157 |
wireRequests? | number | Provider wire requests recorded by the per-dispatch ledger (RV1904): the sum of every settled entry's providerCalls, each record counting its absorbed continuations (wireRequests, RV905) and one otherwise, abandoned subtrees included, because their attempts hit the wire all the same. On ledger-covered runs this equals the invoice cardinality's wireRequests, the recovery benchmark's 55, so the terminal and the invoice finally share one denominator; pre-ledger slices carry no record and surface in the invoice as unattributed rows instead. Set by the journal fold; absent from a live buildCostReport accumulation that did not count wires. | packages/core/src/engine/run-handle.ts:65 |