@rulvar/core 1.109.0 → 1.111.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -824,6 +824,15 @@ interface EntryBillingFold {
824
824
  * semantics. False folds the aggregate slices, the historical basis.
825
825
  */
826
826
  fullyAttributed: boolean;
827
+ /**
828
+ * The models this fold priced per call: record sums equal slice sums
829
+ * counter for counter under the symmetric per-model key (RV604).
830
+ * Published so a row builder can honor the same decision (RV703): a
831
+ * covered model's rows are exactly its records, so no per-slice
832
+ * remainder may be fabricated for it; recomputing coverage elsewhere
833
+ * is how the phantom-remainder skew was born.
834
+ */
835
+ coveredModels: ReadonlySet<ModelRef>;
827
836
  }
828
837
  /**
829
838
  * The billing fold over one terminal entry (RV504), shared by the
@@ -3713,6 +3722,18 @@ interface ToolBudgetSummary {
3713
3722
  limiter?: "maxToolCalls" | "toolUnits";
3714
3723
  }
3715
3724
  /**
3725
+ * How an event's `costUsd` was folded (RV702). `'per-call'`: the sum of
3726
+ * each provider request priced individually, the same basis the settled
3727
+ * CostReport and invoice use (RV504), so a nonlinear long-context tier
3728
+ * fires per REQUEST. `'aggregate-estimate'`: the aggregate usage priced
3729
+ * in one call, which a tier can inflate past what any single request
3730
+ * cost; emitted only when per-request records cannot cover the number
3731
+ * (a checkpoint written before the reconciliation ledger shipped, or a
3732
+ * terminal entry whose records do not cover its usage). An absent field
3733
+ * on an event stream recorded before RV702 means the aggregate basis.
3734
+ */
3735
+ type CostBasis = "per-call" | "aggregate-estimate";
3736
+ /**
3716
3737
  * Agent lifecycle. One logical agent dispatch emits EXACTLY ONE
3717
3738
  * `agent:start`/`agent:end` pair on its span (the start carries the
3718
3739
  * primary role), and each model invocation phase inside the span
@@ -3762,6 +3783,14 @@ type AgentEvents = {
3762
3783
  durationMs: number; /** The usage this activation added to its (role, model) slices. */
3763
3784
  usage: Usage; /** That usage priced at each serving model's own rate. */
3764
3785
  costUsd: number;
3786
+ /**
3787
+ * The fold behind `costUsd` (RV702). Live phase deltas are always
3788
+ * per-call (every slice a live activation adds is backed by a
3789
+ * recorded provider call); a replayed pair says 'aggregate-estimate'
3790
+ * exactly when its model's records do not cover its usage. Absent
3791
+ * on streams recorded before RV702, which priced the aggregate.
3792
+ */
3793
+ costBasis?: CostBasis;
3765
3794
  outcome: "ok" | "error";
3766
3795
  /**
3767
3796
  * Transport retries inside this activation. Present only when
@@ -3775,6 +3804,16 @@ type AgentEvents = {
3775
3804
  status: string;
3776
3805
  usage: Usage;
3777
3806
  costUsd: number;
3807
+ /**
3808
+ * The fold behind `costUsd` (RV702): 'per-call' when every usage
3809
+ * slice of the invocation (restored included) is covered by
3810
+ * per-request records priced individually, the settled fold's own
3811
+ * basis; 'aggregate-estimate' when it is not (the aggregate number
3812
+ * is kept so restored spend is never silently dropped, and labeled
3813
+ * so it is never mistaken for the per-request fold). Absent on
3814
+ * streams recorded before RV702, which priced the aggregate.
3815
+ */
3816
+ costBasis?: CostBasis;
3778
3817
  entryRef: number;
3779
3818
  /**
3780
3819
  * Present and true when this agent's usage is approximate rather
@@ -4376,6 +4415,15 @@ interface AgentResult<T> {
4376
4415
  output: T | null;
4377
4416
  usage: Usage;
4378
4417
  costUsd: number;
4418
+ /**
4419
+ * The fold behind `costUsd` (RV702): 'per-call' when every usage
4420
+ * slice (restored included) is covered by per-request records priced
4421
+ * individually, exactly the settled fold's basis; 'aggregate-estimate'
4422
+ * when a restored checkpoint left usage no record backs, in which case
4423
+ * the aggregate-priced number is kept (never silently dropped) and
4424
+ * labeled.
4425
+ */
4426
+ costBasis: CostBasis;
4379
4427
  turns: number;
4380
4428
  /**
4381
4429
  * The model that actually served the loop phase at the end (M4-T04):
@@ -10410,6 +10458,12 @@ interface PhaseRow {
10410
10458
  durationMs: number;
10411
10459
  usage: Usage;
10412
10460
  costUsd: number;
10461
+ /**
10462
+ * The fold behind `costUsd` (RV702). An event stream recorded before
10463
+ * the field shipped priced aggregates, so an absent field reduces to
10464
+ * 'aggregate-estimate', never to a per-call claim it cannot back.
10465
+ */
10466
+ costBasis: CostBasis;
10413
10467
  outcome?: "ok" | "error";
10414
10468
  retries: number;
10415
10469
  replayed: boolean;
@@ -10427,6 +10481,12 @@ interface AgentInvocationRow {
10427
10481
  status?: string;
10428
10482
  usage: Usage;
10429
10483
  costUsd: number;
10484
+ /**
10485
+ * The fold behind `costUsd` (RV702), from the span's agent:end; an
10486
+ * absent field (a pre-RV702 stream, or a span still open) reduces to
10487
+ * 'aggregate-estimate', never to a per-call claim it cannot back.
10488
+ */
10489
+ costBasis: CostBasis;
10430
10490
  usageApprox: boolean;
10431
10491
  retryCount: number;
10432
10492
  /**
@@ -10442,10 +10502,15 @@ interface AgentInvocationRow {
10442
10502
  /** The reduced table plus the per-role aggregate across every span. */
10443
10503
  interface InvocationTable {
10444
10504
  agents: AgentInvocationRow[];
10445
- /** Aggregated over COMPLETED phase pairs, keyed by role. */
10505
+ /**
10506
+ * Aggregated over COMPLETED phase pairs, keyed by role. The bucket's
10507
+ * `costBasis` is 'per-call' only while EVERY folded pair carried the
10508
+ * per-call basis; one aggregate-estimate pair degrades the bucket.
10509
+ */
10446
10510
  byRole: Record<string, {
10447
10511
  usage: Usage;
10448
10512
  costUsd: number;
10513
+ costBasis: CostBasis;
10449
10514
  }>;
10450
10515
  /** Sum of agent:end costUsd over settled spans. */
10451
10516
  totalCostUsd: number;
@@ -10557,4 +10622,4 @@ interface SandboxBridge {
10557
10622
  declare const SANDBOX_AGENT_OPT_KEYS: readonly string[];
10558
10623
  declare function createSandboxBridge(ctx: Ctx<never>, options: SandboxBridgeOptions): SandboxBridge;
10559
10624
  //#endregion
10560
- export { AWAIT_SCHEMA, AbandonAttempt, AbandonFold, AbandonPayload, AbandonedSpendView, AbortClass, type AdaptiveEvents, AdmissionController, AdmissionDecision, AdmissionRejectedError, AdmissionStatsBefore, AdmitLineage, AdmitRejectReason, AdmitSpec, AdmitVerdict, AgentCallError, AgentError, type AgentEvents, AgentIdentityInput, type AgentInvocationRow, AgentOpts, AgentProfile, AgentProfilePermissions, AgentProfileTemplateOptions, AgentResult, AgentResultMeta, AgentStatus, type AppliedPricingRow, ApproachSignatureInputs, ApprovalDecision, ApprovalIdentityInput, Artifact, AttemptOutcomeClass, AuditCategory, AuditRecord, AuditRunsOptions, BUDGET_ABORT_REASON, BaseAppend, BriefOpts, BudgetAccountView, BudgetDefaults, BudgetExhaustedError, BudgetExhaustionDiagnostics, BudgetHooks, BudgetReserve, type Bytes, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, CacheHint, CacheTtl, CanUseTool, CanonicalId, CanonicalIdentity, CanonicalLadderSpec, CanonicalModelSpec, ChatEvent, ChatRequest, CheckpointState, ChildArtifactPage, ChildIdentityInput, ChildResultPage, type ClaimClass, type ClaimOp, type ClaimStatus, ClaimValidationOptions, CollectOpts, CollectedTurn, CompactionConfig, CompiledPermissionChain, CompiledWorkflow, ConfigError, type CoreEvents, CostAttribution, CostAttributionFacts, CostReport, CreateEngineOptions, type CriticalPath, Ctx, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_CHILD_RESULT_PAGE_CHARS, DEFAULT_CITATION_PATTERN, DEFAULT_CITATION_SAMPLE, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, DEFAULT_EVIDENCE_CALLS_PER_ENTRY, DEFAULT_EVIDENCE_MIN_SHARE, DEFAULT_EVIDENCE_OVERHEAD_CALLS, DEFAULT_FINISH_MAX_REPAIRS, DEFAULT_FLAT_RESERVE_USD, DEFAULT_MAX_CHILDREN_PER_NODE, DEFAULT_MAX_DEPTH, DEFAULT_MAX_OSCILLATIONS_PER_KEY, DEFAULT_MAX_PINNED_WORKTREES, DEFAULT_MAX_REVISIONS_PER_RUN, DEFAULT_MAX_TOTAL_SPAWNS, DEFAULT_MAX_TURNS, DEFAULT_MODEL_RETRY_ATTEMPTS, DEFAULT_NO_PROGRESS_TURNS, DEFAULT_PER_RUN_CONCURRENCY, DEFAULT_RETRY_POLICY, DEFAULT_STREAM_IDLE_TIMEOUT_MS, DEFAULT_SYNTHESIS_MAX_TURNS, DEFAULT_SYNTHESIS_NOTE_MAX_TURNS, DataKeyProvider, DebitResult, DeclaredLadder, DedupIndex, DedupNote, DedupedClaims, DerivedKey, DeriverRegistry, type DeterminismConfig, DeterminismError, type DeterminismEvents, type DeterminismMode, DispositionRule, DispositionTable, DonorCandidate, DonorRef, DroppedItem, EMIT_RESULT_TOOL, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EVENT_SEGMENT_STRIDE, EffectiveUsageLimits, Effort, Engine, EngineDefaults, EngineQuotaConfig, EngineQuotaRuntime, EntryBillingFold, EntryBillingUnit, EntryKind, EntryRef, EntryStatus, EnvelopeEncryption, EnvelopeEncryptionOptions, ErrorClass, ErrorCode, ErrorPolicy, EscalatedResult, EscalationDecision, EscalationDecisionAbortedError, EscalationDigest, EscalationKind, EscalationLimits, EscalationOptions, EscalationReport, EscalationRequest, EventBus, EvidenceContract, type EvidenceRef, type ExecKeyDerivation, type ExecutorRegistry, type ExplorationSummary, ExtensionAppendInput, ExtensionDispatchSpec, ExternalIdentityInput, ExternalRegistry, ExtractNecessityInput, FINALIZE_SYNTHESIS_INSTRUCTION, FINISH_SCHEMA, FINISH_TOOL_NAME, FailRunError, FailoverTarget, FailoverTrigger, FallbackField, FallbackTrigger, FencedCodeMode, FileModelKnowledgeStore, FileModelKnowledgeStoreOptions, FileTranscriptStore, type FinalizationWindowBudget, FinishContract, FinishContractCitations, FinishContractGoldenReject, FinishContractManifest, FinishInfo, FinishSelfTestFailure, FinishSelfTestFixtures, FinishSelfTestReport, FinishValidationChild, FinishValidationInput, FinishValidationSpec, FinishValidationVerdict, FinishValidator, GET_CHILD_RESULT_SCHEMA, GET_CHILD_RESULT_TOOL_NAME, Gate, GateAudit, type GateRecord, GitWorktreeProvider, GitWorktreeProviderOptions, GraftBoot, HashVersion, HookVerdict, IMPLEMENTATION_PROFILE_LIMITS, INBOX_PROPOSAL_TTL_DAYS, IdentityInput, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, IncrementalSynthesisResult, InvalidResolutionError, InvocationRole, type InvocationTable, InvoiceExport, InvoicePricingProvenance, InvoiceReconciliation, InvoiceRow, type IsolatedExecContext, type IsolatedExecRequest, type IsolatedExecutorTag, type IsolationProvider, type IsolationSpec, Issue$1 as Issue, JOURNAL_ENVELOPE_MARKER, JournalCompatSubCode, JournalCompatibilityError, JournalEntry, JournalMatcher, JournalMissError, JournalOperation, JournalOrderViolation, type JournalPricingSnapshot, JournalSerializationContext, JournalSerializationHook, type JournalStore, type Json, JsonSchema, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, type KbProposal, type KbProposalTrigger, KeyDeriver, KeyRing, KeyedLimiter, KnowledgeCasError, type KnowledgeSnapshot, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LadderSpec, type LeasableStore, type Lease, LeaseHeldError, Ledger, LineageCounters, LineageIndex, LineageRef, LineageRelation, LineageStats, LogicalTaskId, MASKED_SECRET, MAX_CHILD_RESULT_PAGE_CHARS, MAX_DEPTH_CEILING, MAX_TIMER_DELAY_MS, MatchResult, McpConfig, McpToolSource, MechanicalGateProfile, MechanicalGateVerdict, MemoryQuotaLimiter, type MetaLookupStore, type ModelCaps, ModelChoice, type ModelClaim, ModelEpochInputs, type ModelKnowledgeHandle, type ModelKnowledgeStore, ModelListConstraint, ModelRef, ModelRetry, ModelSpec, Msg, NoProgressDetector, NodeId, NodeLinkValue, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OnEscalation, OperationDisposition, OrchestrateAcceptance, OrchestrateOptions, OrchestrateSynthesis, OrchestrateSynthesisSkipReason, OrchestratorBudgetSpec, OrchestratorCapConfigError, OrchestratorExtension, OrchestratorExtensionIO, OrchestratorRuntime, Out, PARALLEL_AGENTS_SCHEMA, PROGRESS_REPORT_TOOL_NAME, ParallelSiteCounter, Part, PendingExternal, PendingToolTurn, PermissionConfig, PermissionGate, PermissionHook, PermissionPreset, PermissionRule, PermissionVerdict, type PhaseRow, PhaseTarget, type PinnedPricingSegment, PipelineCollected, PipelineOpts, PlanInvariantError, PreflightAdmissionRow, PreflightFinding, PreflightInput, PreflightOrchestratorSpec, PreflightReport, PreflightSpawnReport, PreflightSpawnSpec, PreflightToolCeiling, PriceTable, PricedUsage, type Pricing, type PricingTier, ProgressReport, type ProviderAdapter, ProviderCallRecord, QUOTA_WINDOW_MS, QualityFloors, QuotaCounters, type QuotaDecision, type QuotaEstimate, type QuotaLimiter, type QuotaReservationRequest, QuotaRule, QuotaWindowSnapshot, READ_CHILD_ARTIFACT_SCHEMA, READ_CHILD_ARTIFACT_TOOL_NAME, RESEARCH_PROFILE_LIMITS, REVIEW_PROFILE_LIMITS, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_PROFILES, RUN_SETTLE_DECISION_TYPE, RandIdentityInput, RandPayload, RateLimitObservation, ReconcileOptions, ReconcileResult, RefEntryAppender, RefEntryClassification, RefusalInfo, RepeatedClaim, ReplayDisposition, ReplayMode, ReplayPlanHashMismatch, Replayer, RepositoryResearchToolset, RepositoryResearchToolsetOptions, ResearchAgentProfileOptions, ResearchAgentProfileResult, ResearchEvidenceEntry, ResolutionArbiter, ResolutionAttempt, ResolutionBy, ResolutionFold, ResolutionLayer, ResolutionOutcome, ResolutionPayload, ResolvedInvocation, ResolvedToolset, ResumeHandle, ResumeOptions, ResumePreview, ResumeReport, RetryClass, RetryPolicy, ReuseConfig, RiskRuleValue, Role, RulvarError, RulvarErrorCode, RunAgentOptions, RunAuditVerdict, RunBudget, RunEventSink, RunExport, type RunFilter, RunHandle, RunInternals, type RunMeta, RunOptions, RunOutcome, RunProfile, RunStateAudit, RunStatus, RuntimeEventSink, SANDBOX_AGENT_OPT_KEYS, SPAWN_AGENT_SCHEMA, SandboxBridge, SandboxBridgeOptions, SandboxError, SandboxHostToWorker, SandboxMethod, SandboxWorkerToHost, SchemaPair, SchemaSpec, SchemaValidationResult, ScopeSegment, ScriptRejected, ScriptRunner, ScrubNote, SecretMasker, SectionMatchMode, Semaphore, SerializationHook, Settled, SettlementError, ShellPatternRules, ShellSegment, ShellVerdict, SinglePhaseAppend, SpanMinter, SpanRegistry, SpawnAdmissionValue, SpawnAgentParams, SpawnKey, SpawnLineage, SpawnLineageOpt, SpawnOrigin, SpawnRecord, Spend, Stage, type StandardJSONSchemaV1, type StandardSchemaV1, StepIdentityInput, StructuredOutputTier, SuspendedAppend, SuspensionState, TOOL_NAME_PATTERN, type TaskClass, TaskDigest, TaskSpec, TerminalPatch, TerminationAccount, TerminationAccountSnapshot, TerminationDeniedValue, TerminationDeniedWriter, TerminationInitValue, TerminationLimits, TerminationResource, type ToolBudgetSummary, ToolCallRequest, ToolChoice, type ToolContext, ToolContextSeed, ToolContract, type ToolDef, type ToolEvents, type ToolExecutor, type ToolExecutorProvider, ToolInit, type ToolRisk, ToolRuntime, type ToolSource, type ToolSourceSession, ToolsOption, TranscriptSerializationHook, type TranscriptStore, TriggerClass, TtlState, Usage, UsageLimits, UsageSlice, VerifiedRecommendation, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, WakeBudgetBlock, WakeDigest, WakeTrigger, WireError, Workflow, WorkflowCallOpts, type WorkflowEvent, type WorkflowEventBody, WorkflowRegistry, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentResultWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, assertFencedWrites, atCompactionThreshold, auditRun, auditRuns, buildAbandonFold, buildAdapterRegistry, buildCostReport, buildDeriverRegistry, buildOrchestratorTools, buildTerminationInitValue, buildToolContext, canRideLoopTurn, canonicalIsolationTag, canonicalizeLadder, canonicalizeSchema, capIssues, capsHashOf, checkFloors, checkpointRefFor, childCoveragePrefix, claimExpired, claimExpiry, claimIssues, claimOpIssues, classifyAgentError, classifyAttemptOutcome, collectDeclaredLadders, compactMessages, compilePermissionChain, compilePermissionPreset, compileSecretMasker, compileVerifiedLayer, constantTimeEqual, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createEnvelopeEncryption, createSandboxBridge, currentOnlyKeyRing, decodeCheckpoint, dedupeRepeatedClaims, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispatchProjectionReserveUsd, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, evidencePreservedValidator, executeWorkflow, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, finishContract, foldTermination, formatRePrompt, formatScopePath, hasFencedWrites, hasMetaLookup, hashRunArgs, hashRunOutput, hashWorkflowBody, hashWorkflowSource, headingStructureValidator, identityJcs, implementationAgentProfile, invoiceFromJournal, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, journalPricingSnapshot, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lastRunSettle, latestProgressReport, lexShellCommand, liftRetainedParts, lineageWeightOf, localKeyProvider, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, memoryQuotaLimiter, mergeQuotaDenial, mergeUsageLimits, metaMatchesFilter, minMatchesValidator, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, orchestratorAdmissionEstCostUsd, parallelScope, parseModelRef, parseScopePath, phiInitialOf, pipelineScope, planNodeScope, preflightEstimate, priceEntryBilling, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, progressReportTool, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, quotaActualTokens, quotaEstimateTokens, quotaRuleAdmission, quotaRuleKey, quotaRuleMatches, readRunMeta, readTerminationInit, reconcileRunMeta, reduceAuditTrail, reduceCriticalPath, reduceInvocationTable, registryKeyRing, remeasureQueue, replayDisposition, repositoryResearchToolset, requiredFieldsValidator, requiredSectionsValidator, researchAgentProfile, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, reviewAgentProfile, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, sanitizeTerminalText, sanitizeTokenCount, sanitizeUsage, sanitizeUsageDelta, scanJournalCompatibility, schemaHash, schemaHashOfSpec, sectionCitationsValidator, selectStructuredOutputTier, selfTestFinishValidation, shouldCompact, snapshotQuotaRules, snapshotUsage, spawnDepthOf, stripFencedBlocks, summarizeInstruction, summarizeOutput, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolContract, toolsetHash, ttlState, usageViolations, validateEditorialCommit, validateEngineQuotaConfig, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateQuotaRules, validateRetryPolicy, validateSchemaSpec, validateTerminationLimits, validateUsageLimits, wordCountValidator, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
10625
+ export { AWAIT_SCHEMA, AbandonAttempt, AbandonFold, AbandonPayload, AbandonedSpendView, AbortClass, type AdaptiveEvents, AdmissionController, AdmissionDecision, AdmissionRejectedError, AdmissionStatsBefore, AdmitLineage, AdmitRejectReason, AdmitSpec, AdmitVerdict, AgentCallError, AgentError, type AgentEvents, AgentIdentityInput, type AgentInvocationRow, AgentOpts, AgentProfile, AgentProfilePermissions, AgentProfileTemplateOptions, AgentResult, AgentResultMeta, AgentStatus, type AppliedPricingRow, ApproachSignatureInputs, ApprovalDecision, ApprovalIdentityInput, Artifact, AttemptOutcomeClass, AuditCategory, AuditRecord, AuditRunsOptions, BUDGET_ABORT_REASON, BaseAppend, BriefOpts, BudgetAccountView, BudgetDefaults, BudgetExhaustedError, BudgetExhaustionDiagnostics, BudgetHooks, BudgetReserve, type Bytes, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, CacheHint, CacheTtl, CanUseTool, CanonicalId, CanonicalIdentity, CanonicalLadderSpec, CanonicalModelSpec, ChatEvent, ChatRequest, CheckpointState, ChildArtifactPage, ChildIdentityInput, ChildResultPage, type ClaimClass, type ClaimOp, type ClaimStatus, ClaimValidationOptions, CollectOpts, CollectedTurn, CompactionConfig, CompiledPermissionChain, CompiledWorkflow, ConfigError, type CoreEvents, CostAttribution, CostAttributionFacts, type CostBasis, CostReport, CreateEngineOptions, type CriticalPath, Ctx, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_CHILD_RESULT_PAGE_CHARS, DEFAULT_CITATION_PATTERN, DEFAULT_CITATION_SAMPLE, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, DEFAULT_EVIDENCE_CALLS_PER_ENTRY, DEFAULT_EVIDENCE_MIN_SHARE, DEFAULT_EVIDENCE_OVERHEAD_CALLS, DEFAULT_FINISH_MAX_REPAIRS, DEFAULT_FLAT_RESERVE_USD, DEFAULT_MAX_CHILDREN_PER_NODE, DEFAULT_MAX_DEPTH, DEFAULT_MAX_OSCILLATIONS_PER_KEY, DEFAULT_MAX_PINNED_WORKTREES, DEFAULT_MAX_REVISIONS_PER_RUN, DEFAULT_MAX_TOTAL_SPAWNS, DEFAULT_MAX_TURNS, DEFAULT_MODEL_RETRY_ATTEMPTS, DEFAULT_NO_PROGRESS_TURNS, DEFAULT_PER_RUN_CONCURRENCY, DEFAULT_RETRY_POLICY, DEFAULT_STREAM_IDLE_TIMEOUT_MS, DEFAULT_SYNTHESIS_MAX_TURNS, DEFAULT_SYNTHESIS_NOTE_MAX_TURNS, DataKeyProvider, DebitResult, DeclaredLadder, DedupIndex, DedupNote, DedupedClaims, DerivedKey, DeriverRegistry, type DeterminismConfig, DeterminismError, type DeterminismEvents, type DeterminismMode, DispositionRule, DispositionTable, DonorCandidate, DonorRef, DroppedItem, EMIT_RESULT_TOOL, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EVENT_SEGMENT_STRIDE, EffectiveUsageLimits, Effort, Engine, EngineDefaults, EngineQuotaConfig, EngineQuotaRuntime, EntryBillingFold, EntryBillingUnit, EntryKind, EntryRef, EntryStatus, EnvelopeEncryption, EnvelopeEncryptionOptions, ErrorClass, ErrorCode, ErrorPolicy, EscalatedResult, EscalationDecision, EscalationDecisionAbortedError, EscalationDigest, EscalationKind, EscalationLimits, EscalationOptions, EscalationReport, EscalationRequest, EventBus, EvidenceContract, type EvidenceRef, type ExecKeyDerivation, type ExecutorRegistry, type ExplorationSummary, ExtensionAppendInput, ExtensionDispatchSpec, ExternalIdentityInput, ExternalRegistry, ExtractNecessityInput, FINALIZE_SYNTHESIS_INSTRUCTION, FINISH_SCHEMA, FINISH_TOOL_NAME, FailRunError, FailoverTarget, FailoverTrigger, FallbackField, FallbackTrigger, FencedCodeMode, FileModelKnowledgeStore, FileModelKnowledgeStoreOptions, FileTranscriptStore, type FinalizationWindowBudget, FinishContract, FinishContractCitations, FinishContractGoldenReject, FinishContractManifest, FinishInfo, FinishSelfTestFailure, FinishSelfTestFixtures, FinishSelfTestReport, FinishValidationChild, FinishValidationInput, FinishValidationSpec, FinishValidationVerdict, FinishValidator, GET_CHILD_RESULT_SCHEMA, GET_CHILD_RESULT_TOOL_NAME, Gate, GateAudit, type GateRecord, GitWorktreeProvider, GitWorktreeProviderOptions, GraftBoot, HashVersion, HookVerdict, IMPLEMENTATION_PROFILE_LIMITS, INBOX_PROPOSAL_TTL_DAYS, IdentityInput, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, IncrementalSynthesisResult, InvalidResolutionError, InvocationRole, type InvocationTable, InvoiceExport, InvoicePricingProvenance, InvoiceReconciliation, InvoiceRow, type IsolatedExecContext, type IsolatedExecRequest, type IsolatedExecutorTag, type IsolationProvider, type IsolationSpec, Issue$1 as Issue, JOURNAL_ENVELOPE_MARKER, JournalCompatSubCode, JournalCompatibilityError, JournalEntry, JournalMatcher, JournalMissError, JournalOperation, JournalOrderViolation, type JournalPricingSnapshot, JournalSerializationContext, JournalSerializationHook, type JournalStore, type Json, JsonSchema, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, type KbProposal, type KbProposalTrigger, KeyDeriver, KeyRing, KeyedLimiter, KnowledgeCasError, type KnowledgeSnapshot, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LadderSpec, type LeasableStore, type Lease, LeaseHeldError, Ledger, LineageCounters, LineageIndex, LineageRef, LineageRelation, LineageStats, LogicalTaskId, MASKED_SECRET, MAX_CHILD_RESULT_PAGE_CHARS, MAX_DEPTH_CEILING, MAX_TIMER_DELAY_MS, MatchResult, McpConfig, McpToolSource, MechanicalGateProfile, MechanicalGateVerdict, MemoryQuotaLimiter, type MetaLookupStore, type ModelCaps, ModelChoice, type ModelClaim, ModelEpochInputs, type ModelKnowledgeHandle, type ModelKnowledgeStore, ModelListConstraint, ModelRef, ModelRetry, ModelSpec, Msg, NoProgressDetector, NodeId, NodeLinkValue, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OnEscalation, OperationDisposition, OrchestrateAcceptance, OrchestrateOptions, OrchestrateSynthesis, OrchestrateSynthesisSkipReason, OrchestratorBudgetSpec, OrchestratorCapConfigError, OrchestratorExtension, OrchestratorExtensionIO, OrchestratorRuntime, Out, PARALLEL_AGENTS_SCHEMA, PROGRESS_REPORT_TOOL_NAME, ParallelSiteCounter, Part, PendingExternal, PendingToolTurn, PermissionConfig, PermissionGate, PermissionHook, PermissionPreset, PermissionRule, PermissionVerdict, type PhaseRow, PhaseTarget, type PinnedPricingSegment, PipelineCollected, PipelineOpts, PlanInvariantError, PreflightAdmissionRow, PreflightFinding, PreflightInput, PreflightOrchestratorSpec, PreflightReport, PreflightSpawnReport, PreflightSpawnSpec, PreflightToolCeiling, PriceTable, PricedUsage, type Pricing, type PricingTier, ProgressReport, type ProviderAdapter, ProviderCallRecord, QUOTA_WINDOW_MS, QualityFloors, QuotaCounters, type QuotaDecision, type QuotaEstimate, type QuotaLimiter, type QuotaReservationRequest, QuotaRule, QuotaWindowSnapshot, READ_CHILD_ARTIFACT_SCHEMA, READ_CHILD_ARTIFACT_TOOL_NAME, RESEARCH_PROFILE_LIMITS, REVIEW_PROFILE_LIMITS, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_PROFILES, RUN_SETTLE_DECISION_TYPE, RandIdentityInput, RandPayload, RateLimitObservation, ReconcileOptions, ReconcileResult, RefEntryAppender, RefEntryClassification, RefusalInfo, RepeatedClaim, ReplayDisposition, ReplayMode, ReplayPlanHashMismatch, Replayer, RepositoryResearchToolset, RepositoryResearchToolsetOptions, ResearchAgentProfileOptions, ResearchAgentProfileResult, ResearchEvidenceEntry, ResolutionArbiter, ResolutionAttempt, ResolutionBy, ResolutionFold, ResolutionLayer, ResolutionOutcome, ResolutionPayload, ResolvedInvocation, ResolvedToolset, ResumeHandle, ResumeOptions, ResumePreview, ResumeReport, RetryClass, RetryPolicy, ReuseConfig, RiskRuleValue, Role, RulvarError, RulvarErrorCode, RunAgentOptions, RunAuditVerdict, RunBudget, RunEventSink, RunExport, type RunFilter, RunHandle, RunInternals, type RunMeta, RunOptions, RunOutcome, RunProfile, RunStateAudit, RunStatus, RuntimeEventSink, SANDBOX_AGENT_OPT_KEYS, SPAWN_AGENT_SCHEMA, SandboxBridge, SandboxBridgeOptions, SandboxError, SandboxHostToWorker, SandboxMethod, SandboxWorkerToHost, SchemaPair, SchemaSpec, SchemaValidationResult, ScopeSegment, ScriptRejected, ScriptRunner, ScrubNote, SecretMasker, SectionMatchMode, Semaphore, SerializationHook, Settled, SettlementError, ShellPatternRules, ShellSegment, ShellVerdict, SinglePhaseAppend, SpanMinter, SpanRegistry, SpawnAdmissionValue, SpawnAgentParams, SpawnKey, SpawnLineage, SpawnLineageOpt, SpawnOrigin, SpawnRecord, Spend, Stage, type StandardJSONSchemaV1, type StandardSchemaV1, StepIdentityInput, StructuredOutputTier, SuspendedAppend, SuspensionState, TOOL_NAME_PATTERN, type TaskClass, TaskDigest, TaskSpec, TerminalPatch, TerminationAccount, TerminationAccountSnapshot, TerminationDeniedValue, TerminationDeniedWriter, TerminationInitValue, TerminationLimits, TerminationResource, type ToolBudgetSummary, ToolCallRequest, ToolChoice, type ToolContext, ToolContextSeed, ToolContract, type ToolDef, type ToolEvents, type ToolExecutor, type ToolExecutorProvider, ToolInit, type ToolRisk, ToolRuntime, type ToolSource, type ToolSourceSession, ToolsOption, TranscriptSerializationHook, type TranscriptStore, TriggerClass, TtlState, Usage, UsageLimits, UsageSlice, VerifiedRecommendation, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, WakeBudgetBlock, WakeDigest, WakeTrigger, WireError, Workflow, WorkflowCallOpts, type WorkflowEvent, type WorkflowEventBody, WorkflowRegistry, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentResultWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, assertFencedWrites, atCompactionThreshold, auditRun, auditRuns, buildAbandonFold, buildAdapterRegistry, buildCostReport, buildDeriverRegistry, buildOrchestratorTools, buildTerminationInitValue, buildToolContext, canRideLoopTurn, canonicalIsolationTag, canonicalizeLadder, canonicalizeSchema, capIssues, capsHashOf, checkFloors, checkpointRefFor, childCoveragePrefix, claimExpired, claimExpiry, claimIssues, claimOpIssues, classifyAgentError, classifyAttemptOutcome, collectDeclaredLadders, compactMessages, compilePermissionChain, compilePermissionPreset, compileSecretMasker, compileVerifiedLayer, constantTimeEqual, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createEnvelopeEncryption, createSandboxBridge, currentOnlyKeyRing, decodeCheckpoint, dedupeRepeatedClaims, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispatchProjectionReserveUsd, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, evidencePreservedValidator, executeWorkflow, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, finishContract, foldTermination, formatRePrompt, formatScopePath, hasFencedWrites, hasMetaLookup, hashRunArgs, hashRunOutput, hashWorkflowBody, hashWorkflowSource, headingStructureValidator, identityJcs, implementationAgentProfile, invoiceFromJournal, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, journalPricingSnapshot, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lastRunSettle, latestProgressReport, lexShellCommand, liftRetainedParts, lineageWeightOf, localKeyProvider, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, memoryQuotaLimiter, mergeQuotaDenial, mergeUsageLimits, metaMatchesFilter, minMatchesValidator, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, orchestratorAdmissionEstCostUsd, parallelScope, parseModelRef, parseScopePath, phiInitialOf, pipelineScope, planNodeScope, preflightEstimate, priceEntryBilling, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, progressReportTool, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, quotaActualTokens, quotaEstimateTokens, quotaRuleAdmission, quotaRuleKey, quotaRuleMatches, readRunMeta, readTerminationInit, reconcileRunMeta, reduceAuditTrail, reduceCriticalPath, reduceInvocationTable, registryKeyRing, remeasureQueue, replayDisposition, repositoryResearchToolset, requiredFieldsValidator, requiredSectionsValidator, researchAgentProfile, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, reviewAgentProfile, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, sanitizeTerminalText, sanitizeTokenCount, sanitizeUsage, sanitizeUsageDelta, scanJournalCompatibility, schemaHash, schemaHashOfSpec, sectionCitationsValidator, selectStructuredOutputTier, selfTestFinishValidation, shouldCompact, snapshotQuotaRules, snapshotUsage, spawnDepthOf, stripFencedBlocks, summarizeInstruction, summarizeOutput, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolContract, toolsetHash, ttlState, usageViolations, validateEditorialCommit, validateEngineQuotaConfig, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateQuotaRules, validateRetryPolicy, validateSchemaSpec, validateTerminationLimits, validateUsageLimits, wordCountValidator, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
package/dist/index.js CHANGED
@@ -2532,7 +2532,8 @@ function priceEntryBilling(entry, priceUsd) {
2532
2532
  servedBy,
2533
2533
  usage
2534
2534
  })),
2535
- fullyAttributed
2535
+ fullyAttributed,
2536
+ coveredModels: covered
2536
2537
  };
2537
2538
  }
2538
2539
  /**
@@ -8542,16 +8543,22 @@ function costReportFromJournal(entries, priceUsd) {
8542
8543
  * and per-row `allocatedUsd` is the additive column whose flat sum
8543
8544
  * reproduces `totalUsd` exactly in every case.
8544
8545
  *
8545
- * Coverage is loss-free by construction: an entry whose records do not
8546
- * cover its usage total (a resume restored from a checkpoint written
8547
- * before the ledger shipped) contributes an `unattributed` remainder
8548
- * row, and an entry with no records at all (written before the ledger
8549
- * shipped, or a fully replayed invocation) contributes one
8550
- * `unattributed` row per usage slice. Missing provider ids are marked,
8551
- * never dropped: a finished call without one reconciles as
8552
- * `missing-provider-id`, a failed or severed call without one as
8553
- * `unconfirmed` (the provider may or may not have billed it; there is
8554
- * no id to match).
8546
+ * Coverage is loss-free by construction: a model whose records do not
8547
+ * cover its usage (a resume restored from a checkpoint written before
8548
+ * the ledger shipped) contributes an `unattributed` remainder row per
8549
+ * slice, and an entry with no records at all (written before the
8550
+ * ledger shipped, or a fully replayed invocation) contributes one
8551
+ * `unattributed` row per usage slice. A COVERED model contributes no
8552
+ * remainder rows at all (RV703): its rows are exactly its records, the
8553
+ * same per-model decision the billing fold makes, so a role mismatch
8554
+ * between records and slices (the schema-extract default splits one
8555
+ * model's usage by role while the record carries one role, or none)
8556
+ * can no longer fabricate a phantom row that breaks the
8557
+ * `rowUsdNonAdditive: false` promise and siphons allocation from the
8558
+ * real call. Missing provider ids are marked, never dropped: a
8559
+ * finished call without one reconciles as `missing-provider-id`, a
8560
+ * failed or severed call without one as `unconfirmed` (the provider
8561
+ * may or may not have billed it; there is no id to match).
8555
8562
  *
8556
8563
  * Pricing happens at fold time from the table you pass, exactly like
8557
8564
  * CostReport. For historical stability against price-table updates,
@@ -8577,6 +8584,12 @@ const USAGE_FIELDS = [
8577
8584
  * model: the whole-entry remainder was published under `entry.servedBy`,
8578
8585
  * so a slice with no records left its allocation pool rowless and the
8579
8586
  * dust pass moved its dollars onto another model's row.
8587
+ *
8588
+ * Consulted only for UNCOVERED models (RV703): coverage is a per-model
8589
+ * decision, so a covered model's slices never reach this arithmetic.
8590
+ * The per-role subtraction here against the per-model coverage key was
8591
+ * exactly the mismatch that fabricated a phantom remainder whenever a
8592
+ * covered model's record roles differed from its slice roles.
8580
8593
  */
8581
8594
  function sliceRemainder(slice, records) {
8582
8595
  const remainder = {
@@ -8686,7 +8699,8 @@ function invoiceFromJournal(entries, priceUsd, options) {
8686
8699
  let everyEntryFullyAttributed = true;
8687
8700
  for (const entry of entries) {
8688
8701
  if (entry.status === "running" || entry.usage === void 0) continue;
8689
- if (!priceEntryBilling(entry, priceUsd).fullyAttributed) everyEntryFullyAttributed = false;
8702
+ const billing = priceEntryBilling(entry, priceUsd);
8703
+ if (!billing.fullyAttributed) everyEntryFullyAttributed = false;
8690
8704
  const abandoned = entry.kind !== "resolution" && entry.kind !== "abandon" && abandonFold.isAbandoned(entry.ref ?? entry.seq);
8691
8705
  const base = {
8692
8706
  entrySeq: entry.seq,
@@ -8737,6 +8751,7 @@ function invoiceFromJournal(entries, priceUsd, options) {
8737
8751
  }
8738
8752
  let remainderOrdinal = records.length + 1;
8739
8753
  for (const slice of entryUsageSlices(entry)) {
8754
+ if (billing.coveredModels.has(slice.servedBy)) continue;
8740
8755
  const remainder = sliceRemainder(slice, records);
8741
8756
  if (remainder === void 0) continue;
8742
8757
  const usd = rowUsd(priceUsd, slice.servedBy, remainder, entry.seq);
@@ -11067,6 +11082,18 @@ async function runAgent(options) {
11067
11082
  });
11068
11083
  };
11069
11084
  const providerCalls = [];
11085
+ const usdByPhaseModel = /* @__PURE__ */ new Map();
11086
+ const addCallUsd = (role, ref, usage) => {
11087
+ const priced = options.priceUsd?.(ref, usage) ?? 0;
11088
+ const usd = Number.isFinite(priced) && priced > 0 ? priced : 0;
11089
+ const key = `${role}\u0000${ref}`;
11090
+ const prior = usdByPhaseModel.get(key);
11091
+ usdByPhaseModel.set(key, {
11092
+ role,
11093
+ usd: (prior?.usd ?? 0) + usd
11094
+ });
11095
+ };
11096
+ let perCallCoverage = true;
11070
11097
  let invocationCounter = 0;
11071
11098
  let transportRetries = 0;
11072
11099
  let schemaRecoveredTerminalExchanges = 0;
@@ -11076,6 +11103,11 @@ async function runAgent(options) {
11076
11103
  for (const [key, slice] of usageByPhaseModel) if (slice.role === role) snapshot.set(key, slice.usage);
11077
11104
  return snapshot;
11078
11105
  };
11106
+ const roleUsdSnapshot = (role) => {
11107
+ const snapshot = /* @__PURE__ */ new Map();
11108
+ for (const [key, cell] of usdByPhaseModel) if (cell.role === role) snapshot.set(key, cell.usd);
11109
+ return snapshot;
11110
+ };
11079
11111
  const usageDelta = (after, before) => {
11080
11112
  const base = before ?? ZERO_USAGE$1;
11081
11113
  const delta = {
@@ -11103,19 +11135,22 @@ async function runAgent(options) {
11103
11135
  role,
11104
11136
  model,
11105
11137
  before: roleUsageSnapshot(role),
11138
+ beforeUsd: roleUsdSnapshot(role),
11106
11139
  startedAtMs: now(),
11107
11140
  retriesBefore: transportRetries
11108
11141
  };
11109
11142
  };
11110
11143
  const endPhase = (phase, outcome, servedModel) => {
11111
11144
  let phaseUsage = ZERO_USAGE$1;
11112
- let phaseUsd = 0;
11113
11145
  for (const [key, slice] of usageByPhaseModel) {
11114
11146
  if (slice.role !== phase.role) continue;
11115
11147
  const delta = usageDelta(slice.usage, phase.before.get(key));
11116
11148
  phaseUsage = addUsage$1(phaseUsage, delta);
11117
- const priced = options.priceUsd?.(slice.servedBy, delta) ?? 0;
11118
- if (Number.isFinite(priced) && priced > 0) phaseUsd += priced;
11149
+ }
11150
+ let phaseUsd = 0;
11151
+ for (const [key, cell] of usdByPhaseModel) {
11152
+ if (cell.role !== phase.role) continue;
11153
+ phaseUsd += cell.usd - (phase.beforeUsd.get(key) ?? 0);
11119
11154
  }
11120
11155
  const retries = transportRetries - phase.retriesBefore;
11121
11156
  events?.emit({
@@ -11128,6 +11163,7 @@ async function runAgent(options) {
11128
11163
  durationMs: Math.max(0, now() - phase.startedAtMs),
11129
11164
  usage: phaseUsage,
11130
11165
  costUsd: phaseUsd,
11166
+ costBasis: "per-call",
11131
11167
  outcome,
11132
11168
  ...retries > 0 ? { retries } : {}
11133
11169
  });
@@ -11376,15 +11412,28 @@ async function runAgent(options) {
11376
11412
  servedBy,
11377
11413
  usage: totalUsage
11378
11414
  }];
11415
+ const restoredSliceSums = /* @__PURE__ */ new Map();
11379
11416
  for (const slice of restoredSlices) {
11380
11417
  const sliceUsage = usageViolations(slice.usage).length === 0 ? slice.usage : sanitizeUsage(slice.usage);
11381
11418
  addPhaseUsage(slice.role ?? primaryRole, slice.servedBy, sliceUsage);
11382
11419
  options.budget?.onUsage(sliceUsage, slice.servedBy);
11383
- }
11384
- for (const record of restored.providerCalls ?? []) providerCalls.push(usageViolations(record.usage).length === 0 ? record : {
11385
- ...record,
11386
- usage: sanitizeUsage(record.usage)
11387
- });
11420
+ const key = `${slice.role ?? primaryRole} ${slice.servedBy}`;
11421
+ restoredSliceSums.set(key, addUsage$1(restoredSliceSums.get(key) ?? ZERO_USAGE$1, sliceUsage));
11422
+ }
11423
+ const restoredRecordSums = /* @__PURE__ */ new Map();
11424
+ for (const record of restored.providerCalls ?? []) {
11425
+ const sane = usageViolations(record.usage).length === 0 ? record : {
11426
+ ...record,
11427
+ usage: sanitizeUsage(record.usage)
11428
+ };
11429
+ providerCalls.push(sane);
11430
+ addCallUsd(sane.role ?? primaryRole, sane.servedBy, sane.usage);
11431
+ const key = `${sane.role ?? primaryRole} ${sane.servedBy}`;
11432
+ restoredRecordSums.set(key, addUsage$1(restoredRecordSums.get(key) ?? ZERO_USAGE$1, sane.usage));
11433
+ }
11434
+ const usageEquals = (a, b) => a.inputTokens === b.inputTokens && a.outputTokens === b.outputTokens && a.cacheReadTokens === b.cacheReadTokens && a.cacheWriteTokens === b.cacheWriteTokens && (a.reasoningTokens ?? 0) === (b.reasoningTokens ?? 0);
11435
+ for (const [key, sliceSum] of restoredSliceSums) if (!usageEquals(sliceSum, restoredRecordSums.get(key) ?? ZERO_USAGE$1)) perCallCoverage = false;
11436
+ for (const key of restoredRecordSums.keys()) if (!restoredSliceSums.has(key)) perCallCoverage = false;
11388
11437
  guard?.restore(messages);
11389
11438
  if (limits.toolBudgetNotices === true && limits.maxToolCalls !== void 0) for (const threshold of crossedNoticeThresholds(toolCallsUsed, limits.maxToolCalls)) firedNotices.add(threshold);
11390
11439
  if (extension !== void 0 && limits.maxToolCalls !== void 0 && toolCallsUsed > limits.maxToolCalls) {
@@ -11435,6 +11484,25 @@ async function runAgent(options) {
11435
11484
  }
11436
11485
  return usd;
11437
11486
  };
11487
+ /**
11488
+ * The invocation's recorded spend (RV702): the per-call accumulator
11489
+ * when every slice is covered by records, the settled fold's own
11490
+ * basis; the labeled aggregate estimate when a restored checkpoint
11491
+ * left usage no record backs, so restored spend is never silently
11492
+ * dropped and an estimate never poses as the per-request fold.
11493
+ */
11494
+ const recordedSpend = () => {
11495
+ if (!perCallCoverage) return {
11496
+ usd: priceRecordedUsage(),
11497
+ basis: "aggregate-estimate"
11498
+ };
11499
+ let usd = 0;
11500
+ for (const cell of usdByPhaseModel.values()) usd += cell.usd;
11501
+ return {
11502
+ usd,
11503
+ basis: "per-call"
11504
+ };
11505
+ };
11438
11506
  const saveBoundary = async (pending) => {
11439
11507
  if (options.checkpoint === void 0) return;
11440
11508
  await options.checkpoint.save({
@@ -11608,7 +11676,7 @@ async function runAgent(options) {
11608
11676
  continue;
11609
11677
  }
11610
11678
  const request = validation.value;
11611
- const spentSoFar = priceRecordedUsage();
11679
+ const spentSoFar = recordedSpend().usd;
11612
11680
  if (countsAgainstLimit(request.kind) && spentSoFar < options.escalation.minSpendUsd) {
11613
11681
  events?.emit({
11614
11682
  type: "tool:end",
@@ -12016,6 +12084,7 @@ async function runAgent(options) {
12016
12084
  if (outcome.aborted !== void 0) record.aborted = outcome.aborted;
12017
12085
  else if (outcome.wireError !== void 0) record.errorCode = outcome.wireError.code;
12018
12086
  providerCalls.push(record);
12087
+ addCallUsd(site.role, target.resolved.ref, accounted);
12019
12088
  const limited = outcome.wireError?.data;
12020
12089
  if (limited?.kind === "rate-limit" && typeof limited.reportedLimits === "object" && limited.reportedLimits !== null) rateLimitObservations.set(`${target.adapter.id}:${target.resolved.model}`, {
12021
12090
  provider: target.adapter.id,
@@ -12846,12 +12915,13 @@ async function runAgent(options) {
12846
12915
  const blob = new TextEncoder().encode(JSON.stringify({ messages }));
12847
12916
  await options.transcript.put(transcriptRef, blob);
12848
12917
  }
12849
- const costUsd = priceRecordedUsage();
12918
+ const spend = recordedSpend();
12850
12919
  const result = {
12851
12920
  status,
12852
12921
  output: status === "ok" ? output : output ?? null,
12853
12922
  usage: totalUsage,
12854
- costUsd,
12923
+ costUsd: spend.usd,
12924
+ costBasis: spend.basis,
12855
12925
  turns,
12856
12926
  servedBy,
12857
12927
  transcriptRef
@@ -14667,13 +14737,15 @@ function createCtx(internals, rootWorkflow) {
14667
14737
  cacheReadTokens: 0,
14668
14738
  cacheWriteTokens: 0
14669
14739
  };
14670
- const replayPriced = terminal === void 0 ? void 0 : priceEntryUsage(terminal, (ref, sliceUsage) => internals.priceUsd(ref, sliceUsage));
14740
+ const replayPriced = terminal === void 0 ? void 0 : priceEntryBilling(terminal, (ref, sliceUsage) => internals.priceUsd(ref, sliceUsage));
14671
14741
  const costUsd = replayPriced?.usd ?? 0;
14742
+ const replayBasis = replayPriced === void 0 || replayPriced.fullyAttributed ? "per-call" : "aggregate-estimate";
14672
14743
  const result = {
14673
14744
  status: matched.kind === "skip" ? "skipped" : terminal?.status ?? "ok",
14674
14745
  output: matched.kind === "skip" ? null : terminal?.value ?? null,
14675
14746
  usage,
14676
14747
  costUsd,
14748
+ costBasis: replayBasis,
14677
14749
  servedBy: terminal?.servedBy ?? loopResolved.ref,
14678
14750
  turns: 0,
14679
14751
  transcriptRef: terminal?.transcriptRef ?? ""
@@ -14737,29 +14809,37 @@ function createCtx(internals, rootWorkflow) {
14737
14809
  durationMs: 0
14738
14810
  }, spanId, true);
14739
14811
  }
14740
- if (terminal !== void 0) entryUsageSlices(terminal).forEach((slice, index) => {
14741
- const priced = internals.priceUsd(slice.servedBy, slice.usage) ?? 0;
14742
- const sliceUsd = Number.isFinite(priced) && priced > 0 ? priced : 0;
14743
- const common = {
14744
- agentType,
14745
- label: opts.label,
14746
- role: slice.role ?? primaryRole,
14747
- model: slice.servedBy,
14748
- invocation: index + 1
14749
- };
14750
- internals.events.emit({
14751
- type: "agent:phase:start",
14752
- ...common
14753
- }, spanId, true);
14754
- internals.events.emit({
14755
- type: "agent:phase:end",
14756
- ...common,
14757
- durationMs: 0,
14758
- usage: slice.usage,
14759
- costUsd: sliceUsd,
14760
- outcome: terminal.status === "error" || terminal.status === "cancelled" ? "error" : "ok"
14761
- }, spanId, true);
14762
- });
14812
+ if (terminal !== void 0) {
14813
+ const usdByRoleModel = /* @__PURE__ */ new Map();
14814
+ const perCallModels = /* @__PURE__ */ new Set();
14815
+ for (const unit of replayPriced?.units ?? []) {
14816
+ const key = `${unit.role ?? primaryRole} ${unit.servedBy}`;
14817
+ usdByRoleModel.set(key, (usdByRoleModel.get(key) ?? 0) + unit.usd);
14818
+ if (unit.source === "call") perCallModels.add(unit.servedBy);
14819
+ }
14820
+ entryUsageSlices(terminal).forEach((slice, index) => {
14821
+ const common = {
14822
+ agentType,
14823
+ label: opts.label,
14824
+ role: slice.role ?? primaryRole,
14825
+ model: slice.servedBy,
14826
+ invocation: index + 1
14827
+ };
14828
+ internals.events.emit({
14829
+ type: "agent:phase:start",
14830
+ ...common
14831
+ }, spanId, true);
14832
+ internals.events.emit({
14833
+ type: "agent:phase:end",
14834
+ ...common,
14835
+ durationMs: 0,
14836
+ usage: slice.usage,
14837
+ costUsd: usdByRoleModel.get(`${slice.role ?? primaryRole} ${slice.servedBy}`) ?? 0,
14838
+ costBasis: perCallModels.has(slice.servedBy) ? "per-call" : "aggregate-estimate",
14839
+ outcome: terminal.status === "error" || terminal.status === "cancelled" ? "error" : "ok"
14840
+ }, spanId, true);
14841
+ });
14842
+ }
14763
14843
  internals.events.emit({
14764
14844
  type: "agent:end",
14765
14845
  agentType,
@@ -14767,12 +14847,13 @@ function createCtx(internals, rootWorkflow) {
14767
14847
  status: result.status,
14768
14848
  usage,
14769
14849
  costUsd,
14850
+ costBasis: replayBasis,
14770
14851
  entryRef: terminal?.seq ?? matched.running.seq,
14771
14852
  ...terminal?.usageApprox === true ? { usageApprox: true } : {},
14772
14853
  ...result.exploration === void 0 ? {} : { exploration: result.exploration },
14773
14854
  ...result.toolBudget === void 0 ? {} : { toolBudget: result.toolBudget }
14774
14855
  }, spanId, true);
14775
- for (const slice of replayPriced?.priced ?? []) bump(internals.cost.byModel, slice.servedBy, slice.usd);
14856
+ for (const unit of replayPriced?.units ?? []) bump(internals.cost.byModel, unit.servedBy, unit.usd);
14776
14857
  for (const slice of replayPriced?.unpriced ?? []) internals.cost.unpriced.push({
14777
14858
  model: slice.servedBy,
14778
14859
  usage: slice.usage
@@ -15404,6 +15485,7 @@ function createCtx(internals, rootWorkflow) {
15404
15485
  status: result.status,
15405
15486
  usage: result.usage,
15406
15487
  costUsd: result.costUsd,
15488
+ costBasis: result.costBasis,
15407
15489
  entryRef: terminal.seq,
15408
15490
  ...resultUsageApprox ? { usageApprox: true } : {},
15409
15491
  ...result.transportRetries !== void 0 && result.transportRetries > 0 ? { retryCount: result.transportRetries } : {},
@@ -17606,6 +17688,7 @@ function makeOrchestratorWorkflow(goal, opts) {
17606
17688
  cacheWriteTokens: 0
17607
17689
  },
17608
17690
  costUsd: 0,
17691
+ costBasis: "per-call",
17609
17692
  turns: 0,
17610
17693
  servedBy: "unknown:unknown",
17611
17694
  transcriptRef: "",
@@ -18583,6 +18666,7 @@ function makeOrchestratorWorkflow(goal, opts) {
18583
18666
  cacheWriteTokens: 0
18584
18667
  },
18585
18668
  costUsd: 0,
18669
+ costBasis: "per-call",
18586
18670
  turns: 0,
18587
18671
  servedBy: "unknown:unknown",
18588
18672
  transcriptRef: "",
@@ -20355,6 +20439,7 @@ function reduceInvocationTable(events) {
20355
20439
  ...event.label === void 0 ? {} : { label: event.label },
20356
20440
  usage: ZERO,
20357
20441
  costUsd: 0,
20442
+ costBasis: "aggregate-estimate",
20358
20443
  usageApprox: false,
20359
20444
  retryCount: 0,
20360
20445
  replayed: event.replayed === true,
@@ -20381,6 +20466,7 @@ function reduceInvocationTable(events) {
20381
20466
  durationMs: 0,
20382
20467
  usage: ZERO,
20383
20468
  costUsd: 0,
20469
+ costBasis: "aggregate-estimate",
20384
20470
  retries: 0,
20385
20471
  replayed: event.replayed === true,
20386
20472
  open: true
@@ -20400,6 +20486,7 @@ function reduceInvocationTable(events) {
20400
20486
  durationMs: 0,
20401
20487
  usage: ZERO,
20402
20488
  costUsd: 0,
20489
+ costBasis: "aggregate-estimate",
20403
20490
  retries: 0,
20404
20491
  replayed: event.replayed === true,
20405
20492
  open: true
@@ -20413,14 +20500,17 @@ function reduceInvocationTable(events) {
20413
20500
  phase.durationMs = event.durationMs;
20414
20501
  phase.usage = event.usage;
20415
20502
  phase.costUsd = event.costUsd;
20503
+ phase.costBasis = event.costBasis ?? "aggregate-estimate";
20416
20504
  phase.outcome = event.outcome;
20417
20505
  phase.retries = event.retries ?? 0;
20418
20506
  const bucket = byRole[event.role] ??= {
20419
20507
  usage: ZERO,
20420
- costUsd: 0
20508
+ costUsd: 0,
20509
+ costBasis: "per-call"
20421
20510
  };
20422
20511
  bucket.usage = addUsage(bucket.usage, event.usage);
20423
20512
  bucket.costUsd += event.costUsd;
20513
+ if (phase.costBasis === "aggregate-estimate") bucket.costBasis = "aggregate-estimate";
20424
20514
  break;
20425
20515
  }
20426
20516
  case "agent:end": {
@@ -20429,6 +20519,7 @@ function reduceInvocationTable(events) {
20429
20519
  row.status = event.status;
20430
20520
  row.usage = event.usage;
20431
20521
  row.costUsd = event.costUsd;
20522
+ row.costBasis = event.costBasis ?? "aggregate-estimate";
20432
20523
  row.usageApprox = event.usageApprox === true;
20433
20524
  row.retryCount = event.retryCount ?? 0;
20434
20525
  if (event.toolBudget !== void 0) row.toolBudget = event.toolBudget;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rulvar/core",
3
- "version": "1.109.0",
3
+ "version": "1.111.0",
4
4
  "description": "Rulvar core: L0 contracts, journal kernel, ctx primitives, agent runtime, model router, tool system, dynamic orchestrator, InMemory and JSONL stores, event stream.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",