@rulvar/core 1.19.0 → 1.21.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
@@ -602,10 +602,20 @@ type AbandonPayload = {
602
602
  retainCheckpoint?: boolean; /** Default false; counts against the pin cap (DEF-5). */
603
603
  retainWorktree?: boolean;
604
604
  };
605
- /** One serving model's slice of a multi-model agent call's usage. */
605
+ /**
606
+ * One (invocation role, serving model) slice of an agent call's usage.
607
+ * `role` is the phase that PAID the slice (v1.19.0 review P1-2: the
608
+ * loop, extract, finalize, and summarize phases of one agent call must
609
+ * land in their own CostReport.byRole buckets even when a single model
610
+ * serves several of them). Absent on slices written before roles
611
+ * shipped: readers fall back to the entry's primary
612
+ * `costAttribution.role`, exactly like the other documented fallbacks.
613
+ * Policy, never identity.
614
+ */
606
615
  interface UsageSlice {
607
616
  servedBy: ModelRef;
608
617
  usage: Usage;
618
+ role?: InvocationRole;
609
619
  }
610
620
  /**
611
621
  * Cost-attribution facts a live run knows at settlement and a pure
@@ -646,7 +656,10 @@ interface PricedUsage {
646
656
  * The single pricing fold over one terminal entry, shared by the kernel
647
657
  * ledger and the CostReport fold so a run's total and its per-model
648
658
  * breakdown can never disagree. Each slice is priced at ITS OWN model's
649
- * rate.
659
+ * rate. A price function returning NaN or a negative amount (a broken
660
+ * user-supplied rate) is treated exactly like a missing row: the slice
661
+ * folds as unpriced instead of poisoning or crediting the totals
662
+ * (v1.20.0 review follow-up).
650
663
  */
651
664
  declare function priceEntryUsage(entry: JournalEntry, priceUsd: (servedBy: ModelRef, usage: Usage) => number | undefined): PricedUsage;
652
665
  /**
@@ -693,6 +706,21 @@ type JournalEntry = {
693
706
  * like usageByModel.
694
707
  */
695
708
  costAttribution?: CostAttributionFacts;
709
+ /**
710
+ * The serving adapters' declared usage-telemetry semantics at write
711
+ * time (ProviderAdapter.usageSemantics), stamped so cost numbers stay
712
+ * auditable across normalization corrections: an UNSTAMPED OpenAI
713
+ * entry with cacheWriteTokens > 0 may have been written by rulvar
714
+ * v1.19.0, whose adapter double-counted cache writes into inputTokens
715
+ * (v1.20.0 review P1/P2-2). The stamp unions every adapter that
716
+ * served a slice of the entry, distinct declarations joined with '+'
717
+ * in first-appearance order, so a mixed-adapter call whose primary
718
+ * declares nothing is still dated by its declaring slices. Absent
719
+ * only when NO serving adapter declares semantics, and on all entries
720
+ * written before this shipped. Policy, never identity, exactly like
721
+ * usageByModel.
722
+ */
723
+ usageSemantics?: string;
696
724
  transcriptRef?: string;
697
725
  checkpointRef?: string;
698
726
  /**
@@ -844,6 +872,51 @@ declare function maskSecretsDeep<T>(value: T): T;
844
872
  /** Convenience for hosts: masks a Json value (alias of the deep walk). */
845
873
  declare function maskSecretsJson(value: Json): Json;
846
874
  //#endregion
875
+ //#region src/l0/usage.d.ts
876
+ /**
877
+ * Names every rule the given usage violates; an empty array means the
878
+ * usage satisfies the full canonical invariant: each present count is a
879
+ * finite nonnegative integer and
880
+ * `cacheReadTokens + cacheWriteTokens <= inputTokens`. The subset rule
881
+ * is checked with a negated comparison so a NaN operand counts as a
882
+ * violation rather than vacuously passing.
883
+ */
884
+ declare function usageViolations(usage: Usage): string[];
885
+ /**
886
+ * One count, repaired in the conservative direction: non-numbers and
887
+ * non-finite values floor to zero (no evidence, no charge and no
888
+ * credit), negatives floor to zero (a negative count can only CREDIT
889
+ * the budget, which hostile telemetry must never do), and fractions
890
+ * round UP so a repaired charge is never an undercharge.
891
+ */
892
+ declare function sanitizeTokenCount(value: number | undefined): number;
893
+ /**
894
+ * One field read per property, returning a detached plain copy. Both
895
+ * accounting boundaries validate and consume THIS snapshot, never the
896
+ * adapter-owned object, so a hostile accessor cannot answer the
897
+ * validator with valid counts and the accumulator with garbage.
898
+ */
899
+ declare function snapshotUsage(usage: Usage): Usage;
900
+ /**
901
+ * The per-field repair for DELTAS (mid-stream usage reports and other
902
+ * partial increments): each count is repaired like `sanitizeTokenCount`,
903
+ * but the whole-usage subset rule is deliberately NOT applied, because a
904
+ * delta legitimately carries cache counts without restating the full
905
+ * input in the same event; clamping those to the subset rule would
906
+ * silently drop a paid cache debit. Always returns a fresh object and
907
+ * is the identity on valid deltas.
908
+ */
909
+ declare function sanitizeUsageDelta(delta: Usage): Usage;
910
+ /**
911
+ * Conservative repair for accounting. Pairs with `usageViolations`: the
912
+ * violation fails the call loud, and the sanitized numbers are the only
913
+ * ones the journal, the cost report, and the budget may see. After the
914
+ * per-field repair the cache subsets clamp into the input with reads
915
+ * keeping priority, mirroring the adapter-level subset clamp. Valid
916
+ * usage passes through structurally unchanged.
917
+ */
918
+ declare function sanitizeUsage(usage: Usage): Usage;
919
+ //#endregion
847
920
  //#region src/vendor/standard-schema.d.ts
848
921
  // Vendored from @standard-schema/spec@1.1.0 (MIT, Copyright (c) 2024 Colin
849
922
  // McDonnell), file dist/index.d.ts, byte-identical below this header.
@@ -1106,6 +1179,20 @@ interface ProviderAdapter {
1106
1179
  * family share retained blocks and projections; default = id.
1107
1180
  */
1108
1181
  provider?: string;
1182
+ /**
1183
+ * Declares WHICH reading of the provider's usage telemetry this
1184
+ * adapter normalizes under; the engine stamps it on usage-bearing
1185
+ * terminal entries so a journal records not only the numbers but the
1186
+ * semantics they were produced under (v1.20.0 review P1/P2-2). Bump
1187
+ * the string whenever the MEANING of a reported Usage field changes,
1188
+ * even when no pricing rate moves; a rate change is a PriceTable
1189
+ * pricingVersion bump instead. Entries persisted before this shipped
1190
+ * carry no stamp, which is itself information: an unstamped OpenAI
1191
+ * entry with cache writes may predate the v1.20.0 cache-subset
1192
+ * correction. Optional; adapters that never changed semantics can
1193
+ * omit it.
1194
+ */
1195
+ usageSemantics?: string;
1109
1196
  caps(model: string): ModelCaps;
1110
1197
  /** Refresh the capability table from live model lists. */
1111
1198
  refreshCaps?(): Promise<void>;
@@ -2120,6 +2207,8 @@ interface TerminalPatch {
2120
2207
  usageByModel?: UsageSlice[];
2121
2208
  /** Attribution facts behind the CostReport breakdowns; see JournalEntry. */
2122
2209
  costAttribution?: CostAttributionFacts;
2210
+ /** The serving adapter's usage-semantics version; see JournalEntry. */
2211
+ usageSemantics?: string;
2123
2212
  transcriptRef?: string;
2124
2213
  checkpointRef?: string;
2125
2214
  /** Terminal agent entries: Artifact list. */
@@ -2760,11 +2849,13 @@ interface AgentResult<T> {
2760
2849
  */
2761
2850
  servedBy: ModelRef;
2762
2851
  /**
2763
- * Present only when the call spanned MORE THAN ONE serving model (the
2764
- * loop, extract, finalize, and summarize roles resolve independently):
2765
- * usage split per model, so `costUsd` and every cost bucket price each
2766
- * slice at its own rate. Absent for a single-model call, which
2767
- * (usage, servedBy) already describes exactly.
2852
+ * Present only when the call spanned MORE THAN ONE (invocation role,
2853
+ * serving model) pair (the loop, extract, finalize, and summarize
2854
+ * roles resolve independently): usage split per (role, model), so
2855
+ * `costUsd` and every cost bucket price each slice at its own rate
2856
+ * and `CostReport.byRole` attributes each phase to its own bucket
2857
+ * (v1.19.0 review P1-2). Absent for a single-phase single-model call,
2858
+ * which (usage, servedBy) already describes exactly.
2768
2859
  */
2769
2860
  usageByModel?: UsageSlice[];
2770
2861
  transcriptRef: string;
@@ -3460,6 +3551,8 @@ declare class RunBudget {
3460
3551
  private exhaustedInternal;
3461
3552
  /** Models already warned about; the warning fires once per model per run. */
3462
3553
  private readonly unpricedWarned;
3554
+ /** Models whose price function already returned an invalid USD once. */
3555
+ private readonly invalidPriceWarned;
3463
3556
  constructor(options: {
3464
3557
  ceilingUsd?: number;
3465
3558
  lifetimeSpawnCap?: number;
@@ -6426,4 +6519,4 @@ interface SandboxBridge {
6426
6519
  }
6427
6520
  declare function createSandboxBridge(ctx: Ctx<never>, options: SandboxBridgeOptions): SandboxBridge;
6428
6521
  //#endregion
6429
- export { AWAIT_SCHEMA, AbandonAttempt, AbandonFold, AbandonPayload, AbandonedSpendView, AbortClass, type AdaptiveEvents, AdmissionController, AdmissionDecision, AdmissionRejectedError, AdmissionStatsBefore, AdmitLineage, AdmitRejectReason, AdmitSpec, AdmitVerdict, AgentCallError, AgentError, type AgentEvents, AgentIdentityInput, AgentOpts, AgentProfile, AgentProfilePermissions, AgentResult, AgentResultMeta, AgentStatus, ApproachSignatureInputs, ApprovalDecision, ApprovalIdentityInput, Artifact, AttemptOutcomeClass, BUDGET_ABORT_REASON, 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, ChildIdentityInput, type ClaimClass, type ClaimOp, type ClaimStatus, ClaimValidationOptions, CollectOpts, CollectedTurn, CompactionConfig, CompiledPermissionChain, CompiledWorkflow, ConfigError, type CoreEvents, CostAttribution, CostAttributionFacts, CostReport, CreateEngineOptions, Ctx, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, 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, DebitResult, DeclaredLadder, DedupIndex, DedupNote, DerivedKey, DeriverRegistry, DispositionRule, DispositionTable, DonorCandidate, DonorRef, DroppedItem, EMIT_RESULT_TOOL, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EffectiveUsageLimits, Effort, Engine, EngineDefaults, EntryKind, EntryRef, EntryStatus, ErrorClass, ErrorCode, ErrorPolicy, EscalatedResult, EscalationDecision, EscalationDigest, EscalationKind, EscalationLimits, EscalationOptions, EscalationReport, EscalationRequest, EventBus, type EvidenceRef, ExtensionAppendInput, ExtensionDispatchSpec, ExternalIdentityInput, ExternalRegistry, ExtractNecessityInput, FINALIZE_SYNTHESIS_INSTRUCTION, FINISH_SCHEMA, FINISH_TOOL_NAME, FailoverTarget, FailoverTrigger, FallbackField, FallbackTrigger, FileModelKnowledgeStore, FileModelKnowledgeStoreOptions, FileTranscriptStore, FinishInfo, Gate, GateAudit, type GateRecord, GitWorktreeProvider, GitWorktreeProviderOptions, GraftBoot, HashVersion, HookVerdict, INBOX_PROPOSAL_TTL_DAYS, IdentityInput, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, InvalidResolutionError, InvocationRole, type IsolationProvider, type IsolationSpec, Issue$1 as Issue, JournalCompatSubCode, JournalCompatibilityError, JournalEntry, JournalMatcher, JournalMissError, JournalOperation, JournalOrderViolation, 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_DEPTH_CEILING, MatchResult, McpConfig, MechanicalGateProfile, MechanicalGateVerdict, type ModelCaps, ModelChoice, type ModelClaim, ModelEpochInputs, type ModelKnowledgeHandle, type ModelKnowledgeStore, ModelListConstraint, ModelRef, ModelRetry, ModelSpec, Msg, NoProgressDetector, NodeId, NodeLinkValue, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OnEscalation, OperationDisposition, OrchestrateOptions, OrchestratorBudgetSpec, OrchestratorCapConfigError, OrchestratorExtension, OrchestratorExtensionIO, OrchestratorRuntime, Out, PARALLEL_AGENTS_SCHEMA, ParallelSiteCounter, Part, PendingExternal, PendingToolTurn, PermissionConfig, PermissionGate, PermissionHook, PermissionPreset, PermissionRule, PermissionVerdict, PhaseTarget, PipelineCollected, PipelineOpts, PlanInvariantError, PriceTable, PricedUsage, type Pricing, type PricingTier, type ProviderAdapter, QualityFloors, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_PROFILES, RandIdentityInput, RandPayload, RefEntryAppender, RefEntryClassification, RefusalInfo, ReplayDisposition, ReplayMode, ReplayPlanHashMismatch, Replayer, ResolutionArbiter, ResolutionAttempt, ResolutionBy, ResolutionFold, ResolutionLayer, ResolutionOutcome, ResolutionPayload, ResolvedInvocation, ResolvedToolset, ResumeHandle, ResumeOptions, ResumePreview, ResumeReport, RetryClass, RetryPolicy, ReuseConfig, RiskRuleValue, Role, RulvarError, RulvarErrorCode, RunAgentOptions, RunBudget, RunEventSink, type RunFilter, RunHandle, RunInternals, type RunMeta, RunOptions, RunOutcome, RunProfile, RunStatus, RuntimeEventSink, SPAWN_AGENT_SCHEMA, SandboxBridge, SandboxBridgeOptions, SandboxError, SandboxHostToWorker, SandboxMethod, SandboxWorkerToHost, SchemaPair, SchemaSpec, SchemaValidationResult, ScopeSegment, ScriptRejected, ScriptRunner, ScrubNote, Semaphore, SerializationHook, Settled, 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, ToolCallRequest, ToolChoice, type ToolContext, ToolContextSeed, ToolContract, type ToolDef, type ToolEvents, type ToolExecutor, 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, atCompactionThreshold, 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, compileVerifiedLayer, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createSandboxBridge, currentOnlyKeyRing, decodeCheckpoint, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, executeWorkflow, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, foldTermination, formatRePrompt, formatScopePath, hashWorkflowBody, hashWorkflowSource, identityJcs, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lexShellCommand, liftRetainedParts, lineageWeightOf, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, mergeUsageLimits, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, parallelScope, parseModelRef, parseScopePath, phiInitialOf, pipelineScope, planNodeScope, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, readTerminationInit, registryKeyRing, remeasureQueue, replayDisposition, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, scanJournalCompatibility, schemaHash, schemaHashOfSpec, selectStructuredOutputTier, shouldCompact, spawnDepthOf, summarizeInstruction, summarizeOutput, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolContract, toolsetHash, ttlState, validateEditorialCommit, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateSchemaSpec, validateTerminationLimits, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
6522
+ export { AWAIT_SCHEMA, AbandonAttempt, AbandonFold, AbandonPayload, AbandonedSpendView, AbortClass, type AdaptiveEvents, AdmissionController, AdmissionDecision, AdmissionRejectedError, AdmissionStatsBefore, AdmitLineage, AdmitRejectReason, AdmitSpec, AdmitVerdict, AgentCallError, AgentError, type AgentEvents, AgentIdentityInput, AgentOpts, AgentProfile, AgentProfilePermissions, AgentResult, AgentResultMeta, AgentStatus, ApproachSignatureInputs, ApprovalDecision, ApprovalIdentityInput, Artifact, AttemptOutcomeClass, BUDGET_ABORT_REASON, 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, ChildIdentityInput, type ClaimClass, type ClaimOp, type ClaimStatus, ClaimValidationOptions, CollectOpts, CollectedTurn, CompactionConfig, CompiledPermissionChain, CompiledWorkflow, ConfigError, type CoreEvents, CostAttribution, CostAttributionFacts, CostReport, CreateEngineOptions, Ctx, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, 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, DebitResult, DeclaredLadder, DedupIndex, DedupNote, DerivedKey, DeriverRegistry, DispositionRule, DispositionTable, DonorCandidate, DonorRef, DroppedItem, EMIT_RESULT_TOOL, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EffectiveUsageLimits, Effort, Engine, EngineDefaults, EntryKind, EntryRef, EntryStatus, ErrorClass, ErrorCode, ErrorPolicy, EscalatedResult, EscalationDecision, EscalationDigest, EscalationKind, EscalationLimits, EscalationOptions, EscalationReport, EscalationRequest, EventBus, type EvidenceRef, ExtensionAppendInput, ExtensionDispatchSpec, ExternalIdentityInput, ExternalRegistry, ExtractNecessityInput, FINALIZE_SYNTHESIS_INSTRUCTION, FINISH_SCHEMA, FINISH_TOOL_NAME, FailoverTarget, FailoverTrigger, FallbackField, FallbackTrigger, FileModelKnowledgeStore, FileModelKnowledgeStoreOptions, FileTranscriptStore, FinishInfo, Gate, GateAudit, type GateRecord, GitWorktreeProvider, GitWorktreeProviderOptions, GraftBoot, HashVersion, HookVerdict, INBOX_PROPOSAL_TTL_DAYS, IdentityInput, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, InvalidResolutionError, InvocationRole, type IsolationProvider, type IsolationSpec, Issue$1 as Issue, JournalCompatSubCode, JournalCompatibilityError, JournalEntry, JournalMatcher, JournalMissError, JournalOperation, JournalOrderViolation, 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_DEPTH_CEILING, MatchResult, McpConfig, MechanicalGateProfile, MechanicalGateVerdict, type ModelCaps, ModelChoice, type ModelClaim, ModelEpochInputs, type ModelKnowledgeHandle, type ModelKnowledgeStore, ModelListConstraint, ModelRef, ModelRetry, ModelSpec, Msg, NoProgressDetector, NodeId, NodeLinkValue, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OnEscalation, OperationDisposition, OrchestrateOptions, OrchestratorBudgetSpec, OrchestratorCapConfigError, OrchestratorExtension, OrchestratorExtensionIO, OrchestratorRuntime, Out, PARALLEL_AGENTS_SCHEMA, ParallelSiteCounter, Part, PendingExternal, PendingToolTurn, PermissionConfig, PermissionGate, PermissionHook, PermissionPreset, PermissionRule, PermissionVerdict, PhaseTarget, PipelineCollected, PipelineOpts, PlanInvariantError, PriceTable, PricedUsage, type Pricing, type PricingTier, type ProviderAdapter, QualityFloors, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_PROFILES, RandIdentityInput, RandPayload, RefEntryAppender, RefEntryClassification, RefusalInfo, ReplayDisposition, ReplayMode, ReplayPlanHashMismatch, Replayer, ResolutionArbiter, ResolutionAttempt, ResolutionBy, ResolutionFold, ResolutionLayer, ResolutionOutcome, ResolutionPayload, ResolvedInvocation, ResolvedToolset, ResumeHandle, ResumeOptions, ResumePreview, ResumeReport, RetryClass, RetryPolicy, ReuseConfig, RiskRuleValue, Role, RulvarError, RulvarErrorCode, RunAgentOptions, RunBudget, RunEventSink, type RunFilter, RunHandle, RunInternals, type RunMeta, RunOptions, RunOutcome, RunProfile, RunStatus, RuntimeEventSink, SPAWN_AGENT_SCHEMA, SandboxBridge, SandboxBridgeOptions, SandboxError, SandboxHostToWorker, SandboxMethod, SandboxWorkerToHost, SchemaPair, SchemaSpec, SchemaValidationResult, ScopeSegment, ScriptRejected, ScriptRunner, ScrubNote, Semaphore, SerializationHook, Settled, 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, ToolCallRequest, ToolChoice, type ToolContext, ToolContextSeed, ToolContract, type ToolDef, type ToolEvents, type ToolExecutor, 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, atCompactionThreshold, 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, compileVerifiedLayer, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createSandboxBridge, currentOnlyKeyRing, decodeCheckpoint, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, executeWorkflow, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, foldTermination, formatRePrompt, formatScopePath, hashWorkflowBody, hashWorkflowSource, identityJcs, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lexShellCommand, liftRetainedParts, lineageWeightOf, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, mergeUsageLimits, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, parallelScope, parseModelRef, parseScopePath, phiInitialOf, pipelineScope, planNodeScope, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, readTerminationInit, registryKeyRing, remeasureQueue, replayDisposition, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, sanitizeTokenCount, sanitizeUsage, sanitizeUsageDelta, scanJournalCompatibility, schemaHash, schemaHashOfSpec, selectStructuredOutputTier, shouldCompact, snapshotUsage, spawnDepthOf, summarizeInstruction, summarizeOutput, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolContract, toolsetHash, ttlState, usageViolations, validateEditorialCommit, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateSchemaSpec, validateTerminationLimits, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
package/dist/index.js CHANGED
@@ -547,6 +547,105 @@ function createCanonicalIdMinter(options) {
547
547
  return monotonicUlidFactory(options);
548
548
  }
549
549
  //#endregion
550
+ //#region src/l0/usage.ts
551
+ const COUNT_FIELDS = [
552
+ "inputTokens",
553
+ "outputTokens",
554
+ "cacheReadTokens",
555
+ "cacheWriteTokens",
556
+ "reasoningTokens"
557
+ ];
558
+ /**
559
+ * Names every rule the given usage violates; an empty array means the
560
+ * usage satisfies the full canonical invariant: each present count is a
561
+ * finite nonnegative integer and
562
+ * `cacheReadTokens + cacheWriteTokens <= inputTokens`. The subset rule
563
+ * is checked with a negated comparison so a NaN operand counts as a
564
+ * violation rather than vacuously passing.
565
+ */
566
+ function usageViolations(usage) {
567
+ const out = [];
568
+ for (const field of COUNT_FIELDS) {
569
+ const value = usage[field];
570
+ if (field === "reasoningTokens" && value === void 0) continue;
571
+ if (typeof value !== "number" || !Number.isFinite(value)) out.push(`${field} is ${String(value)}, not a finite number`);
572
+ else if (value < 0) out.push(`${field} is negative (${String(value)})`);
573
+ else if (!Number.isInteger(value)) out.push(`${field} is fractional (${String(value)})`);
574
+ else if (!Number.isSafeInteger(value)) out.push(`${field} is beyond the safe integer range (${String(value)})`);
575
+ }
576
+ if (!(usage.inputTokens >= usage.cacheReadTokens + usage.cacheWriteTokens)) out.push(`inputTokens (${String(usage.inputTokens)}) < cacheReadTokens + cacheWriteTokens (${String(usage.cacheReadTokens)} + ${String(usage.cacheWriteTokens)})`);
577
+ return out;
578
+ }
579
+ /**
580
+ * One count, repaired in the conservative direction: non-numbers and
581
+ * non-finite values floor to zero (no evidence, no charge and no
582
+ * credit), negatives floor to zero (a negative count can only CREDIT
583
+ * the budget, which hostile telemetry must never do), and fractions
584
+ * round UP so a repaired charge is never an undercharge.
585
+ */
586
+ function sanitizeTokenCount(value) {
587
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return 0;
588
+ return Math.min(Math.ceil(value), Number.MAX_SAFE_INTEGER);
589
+ }
590
+ /**
591
+ * One field read per property, returning a detached plain copy. Both
592
+ * accounting boundaries validate and consume THIS snapshot, never the
593
+ * adapter-owned object, so a hostile accessor cannot answer the
594
+ * validator with valid counts and the accumulator with garbage.
595
+ */
596
+ function snapshotUsage(usage) {
597
+ const out = {
598
+ inputTokens: usage.inputTokens,
599
+ outputTokens: usage.outputTokens,
600
+ cacheReadTokens: usage.cacheReadTokens,
601
+ cacheWriteTokens: usage.cacheWriteTokens
602
+ };
603
+ const reasoning = usage.reasoningTokens;
604
+ if (reasoning !== void 0) out.reasoningTokens = reasoning;
605
+ return out;
606
+ }
607
+ /**
608
+ * The per-field repair for DELTAS (mid-stream usage reports and other
609
+ * partial increments): each count is repaired like `sanitizeTokenCount`,
610
+ * but the whole-usage subset rule is deliberately NOT applied, because a
611
+ * delta legitimately carries cache counts without restating the full
612
+ * input in the same event; clamping those to the subset rule would
613
+ * silently drop a paid cache debit. Always returns a fresh object and
614
+ * is the identity on valid deltas.
615
+ */
616
+ function sanitizeUsageDelta(delta) {
617
+ const snapshot = snapshotUsage(delta);
618
+ const out = {
619
+ inputTokens: sanitizeTokenCount(snapshot.inputTokens),
620
+ outputTokens: sanitizeTokenCount(snapshot.outputTokens),
621
+ cacheReadTokens: sanitizeTokenCount(snapshot.cacheReadTokens),
622
+ cacheWriteTokens: sanitizeTokenCount(snapshot.cacheWriteTokens)
623
+ };
624
+ if (snapshot.reasoningTokens !== void 0) out.reasoningTokens = sanitizeTokenCount(snapshot.reasoningTokens);
625
+ return out;
626
+ }
627
+ /**
628
+ * Conservative repair for accounting. Pairs with `usageViolations`: the
629
+ * violation fails the call loud, and the sanitized numbers are the only
630
+ * ones the journal, the cost report, and the budget may see. After the
631
+ * per-field repair the cache subsets clamp into the input with reads
632
+ * keeping priority, mirroring the adapter-level subset clamp. Valid
633
+ * usage passes through structurally unchanged.
634
+ */
635
+ function sanitizeUsage(usage) {
636
+ const inputTokens = sanitizeTokenCount(usage.inputTokens);
637
+ const cacheReadTokens = Math.min(sanitizeTokenCount(usage.cacheReadTokens), inputTokens);
638
+ const cacheWriteTokens = Math.min(sanitizeTokenCount(usage.cacheWriteTokens), inputTokens - cacheReadTokens);
639
+ const out = {
640
+ inputTokens,
641
+ outputTokens: sanitizeTokenCount(usage.outputTokens),
642
+ cacheReadTokens,
643
+ cacheWriteTokens
644
+ };
645
+ if (usage.reasoningTokens !== void 0) out.reasoningTokens = sanitizeTokenCount(usage.reasoningTokens);
646
+ return out;
647
+ }
648
+ //#endregion
550
649
  //#region src/vendor/json-schema/deep-compare-strict.ts
551
650
  function deepCompareStrict(a, b) {
552
651
  const typeofa = typeof a;
@@ -1772,7 +1871,10 @@ function entryUsageSlices(entry) {
1772
1871
  * The single pricing fold over one terminal entry, shared by the kernel
1773
1872
  * ledger and the CostReport fold so a run's total and its per-model
1774
1873
  * breakdown can never disagree. Each slice is priced at ITS OWN model's
1775
- * rate.
1874
+ * rate. A price function returning NaN or a negative amount (a broken
1875
+ * user-supplied rate) is treated exactly like a missing row: the slice
1876
+ * folds as unpriced instead of poisoning or crediting the totals
1877
+ * (v1.20.0 review follow-up).
1776
1878
  */
1777
1879
  function priceEntryUsage(entry, priceUsd) {
1778
1880
  const result = {
@@ -1782,7 +1884,7 @@ function priceEntryUsage(entry, priceUsd) {
1782
1884
  };
1783
1885
  for (const slice of entryUsageSlices(entry)) {
1784
1886
  const usd = priceUsd(slice.servedBy, slice.usage);
1785
- if (usd === void 0) {
1887
+ if (usd === void 0 || !Number.isFinite(usd) || usd < 0) {
1786
1888
  result.unpriced.push(slice);
1787
1889
  continue;
1788
1890
  }
@@ -5535,6 +5637,7 @@ var Replayer = class {
5535
5637
  if (patch.servedBy !== void 0) entry.servedBy = patch.servedBy;
5536
5638
  if (patch.usageByModel !== void 0) entry.usageByModel = patch.usageByModel;
5537
5639
  if (patch.costAttribution !== void 0) entry.costAttribution = patch.costAttribution;
5640
+ if (patch.usageSemantics !== void 0) entry.usageSemantics = patch.usageSemantics;
5538
5641
  if (patch.transcriptRef !== void 0) entry.transcriptRef = patch.transcriptRef;
5539
5642
  if (patch.checkpointRef !== void 0) entry.checkpointRef = patch.checkpointRef;
5540
5643
  if (patch.artifacts !== void 0) entry.artifacts = toJournalValue(patch.artifacts, "terminal artifacts");
@@ -6386,7 +6489,8 @@ function costReportFromJournal(entries, priceUsd) {
6386
6489
  byPhase[phase] = (byPhase[phase] ?? 0) + priced.usd;
6387
6490
  const agentType = facts?.agentType ?? "unknown";
6388
6491
  byAgentType[agentType] = (byAgentType[agentType] ?? 0) + priced.usd;
6389
- byRole[facts?.role ?? "loop"] += priced.usd;
6492
+ const primaryRole = facts?.role ?? "loop";
6493
+ for (const slice of priced.priced) byRole[slice.role ?? primaryRole] += slice.usd;
6390
6494
  if (facts?.budgetAccount !== void 0 && isOrchestratorAccount(facts.budgetAccount)) {
6391
6495
  orchestratorSpentUsd += priced.usd;
6392
6496
  if (facts.finalizeReserve === true) reserveUsedUsd += priced.usd;
@@ -7758,8 +7862,17 @@ function addUsage(total, turn) {
7758
7862
  * The Usage invariant is verified at the adapter boundary: inputTokens is
7759
7863
  * the FULL prompt including cache reads and writes.
7760
7864
  */
7761
- function assertUsageInvariant(usage, adapterId) {
7762
- if (usage.inputTokens < usage.cacheReadTokens + usage.cacheWriteTokens) throw new Error(`adapter '${adapterId}' violated the Usage invariant: inputTokens (${usage.inputTokens}) < cacheReadTokens + cacheWriteTokens (${usage.cacheReadTokens} + ${usage.cacheWriteTokens})`);
7865
+ /**
7866
+ * The full canonical invariant at the adapter boundary (v1.20.0 review
7867
+ * P1-1): every count finite, integral, and nonnegative, and the cache
7868
+ * subsets inside the input. One violation message covers every adapter,
7869
+ * injected clients and mocks included; the financial invariant never
7870
+ * depends on the good faith of an external transport.
7871
+ */
7872
+ function usageInvariantViolation(usage, adapterId) {
7873
+ const violations = usageViolations(usage);
7874
+ if (violations.length === 0) return;
7875
+ return `adapter '${adapterId}' violated the Usage invariant: ${violations.join("; ")}`;
7763
7876
  }
7764
7877
  async function streamTurn(adapter, req, options) {
7765
7878
  const idle = new AbortController();
@@ -7773,6 +7886,7 @@ async function streamTurn(adapter, req, options) {
7773
7886
  const pendingArgs = /* @__PURE__ */ new Map();
7774
7887
  let usage = ZERO_USAGE$1;
7775
7888
  let reported = ZERO_USAGE$1;
7889
+ let usageViolation;
7776
7890
  let sawFinish = false;
7777
7891
  let finish;
7778
7892
  let providerMetadata;
@@ -7816,22 +7930,46 @@ async function streamTurn(adapter, req, options) {
7816
7930
  break;
7817
7931
  }
7818
7932
  case "usage": {
7933
+ if (sawFinish) {
7934
+ usageViolation ??= "a usage event arrived after the finish event";
7935
+ break;
7936
+ }
7937
+ const cleaned = {};
7938
+ for (const field of [
7939
+ "inputTokens",
7940
+ "outputTokens",
7941
+ "cacheReadTokens",
7942
+ "cacheWriteTokens",
7943
+ "reasoningTokens"
7944
+ ]) {
7945
+ const value = event.usage[field];
7946
+ if (value === void 0) continue;
7947
+ if (Number.isInteger(value) && value >= 0) cleaned[field] = value;
7948
+ else {
7949
+ usageViolation ??= `mid-stream usage event carried invalid ${field} (${String(value)})`;
7950
+ cleaned[field] = sanitizeTokenCount(value);
7951
+ }
7952
+ }
7819
7953
  usage = {
7820
7954
  ...usage,
7821
- ...event.usage
7955
+ ...cleaned
7822
7956
  };
7823
7957
  const delta = {
7824
- inputTokens: event.usage.inputTokens ?? 0,
7825
- outputTokens: event.usage.outputTokens ?? 0,
7826
- cacheReadTokens: event.usage.cacheReadTokens ?? 0,
7827
- cacheWriteTokens: event.usage.cacheWriteTokens ?? 0
7958
+ inputTokens: cleaned.inputTokens ?? 0,
7959
+ outputTokens: cleaned.outputTokens ?? 0,
7960
+ cacheReadTokens: cleaned.cacheReadTokens ?? 0,
7961
+ cacheWriteTokens: cleaned.cacheWriteTokens ?? 0
7828
7962
  };
7829
- if (event.usage.reasoningTokens !== void 0) delta.reasoningTokens = event.usage.reasoningTokens;
7963
+ if (cleaned.reasoningTokens !== void 0) delta.reasoningTokens = cleaned.reasoningTokens;
7830
7964
  reported = addUsage(reported, delta);
7831
7965
  options.onUsage?.(delta);
7832
7966
  break;
7833
7967
  }
7834
7968
  case "finish":
7969
+ if (sawFinish) {
7970
+ usageViolation ??= "a second finish event arrived on one stream";
7971
+ break;
7972
+ }
7835
7973
  sawFinish = true;
7836
7974
  finish = event.finish;
7837
7975
  usage = event.usage;
@@ -7863,6 +8001,7 @@ async function streamTurn(adapter, req, options) {
7863
8001
  aborted
7864
8002
  };
7865
8003
  if (finish !== void 0) outcome.finish = finish;
8004
+ if (usageViolation !== void 0) outcome.usageViolation = usageViolation;
7866
8005
  return outcome;
7867
8006
  }
7868
8007
  const outcome = {
@@ -7872,6 +8011,7 @@ async function streamTurn(adapter, req, options) {
7872
8011
  usageApprox: !sawFinish
7873
8012
  };
7874
8013
  if (finish !== void 0) outcome.finish = finish;
8014
+ if (usageViolation !== void 0) outcome.usageViolation = usageViolation;
7875
8015
  if (providerMetadata !== void 0) outcome.providerMetadata = providerMetadata;
7876
8016
  if (wireError !== void 0) outcome.wireError = wireError;
7877
8017
  return outcome;
@@ -8058,7 +8198,17 @@ async function runAgent(options) {
8058
8198
  }]
8059
8199
  }];
8060
8200
  let totalUsage = ZERO_USAGE$1;
8061
- const usageByModel = /* @__PURE__ */ new Map();
8201
+ const primaryRole = options.role ?? "loop";
8202
+ const usageByPhaseModel = /* @__PURE__ */ new Map();
8203
+ const addPhaseUsage = (role, ref, usage) => {
8204
+ const key = `${role}${ref}`;
8205
+ const prior = usageByPhaseModel.get(key);
8206
+ usageByPhaseModel.set(key, {
8207
+ role,
8208
+ servedBy: ref,
8209
+ usage: addUsage(prior?.usage ?? ZERO_USAGE$1, usage)
8210
+ });
8211
+ };
8062
8212
  let turns = 0;
8063
8213
  let schemaAttempts = 0;
8064
8214
  let output = null;
@@ -8084,22 +8234,24 @@ async function runAgent(options) {
8084
8234
  messages.length = 0;
8085
8235
  messages.push(...restored.messages);
8086
8236
  turns = restored.turns;
8087
- totalUsage = restored.usage;
8237
+ totalUsage = usageViolations(restored.usage).length === 0 ? restored.usage : sanitizeUsage(restored.usage);
8088
8238
  toolCallsUsed = restored.toolCallsUsed;
8089
8239
  schemaAttempts = restored.schemaAttempts;
8090
8240
  compactionPoints.push(...restored.compaction);
8091
8241
  const restoredSlices = restored.usageByModel ?? [{
8092
8242
  servedBy,
8093
- usage: restored.usage
8243
+ usage: totalUsage
8094
8244
  }];
8095
8245
  for (const slice of restoredSlices) {
8096
- usageByModel.set(slice.servedBy, addUsage(usageByModel.get(slice.servedBy) ?? ZERO_USAGE$1, slice.usage));
8097
- options.budget?.onUsage(slice.usage, slice.servedBy);
8246
+ const sliceUsage = usageViolations(slice.usage).length === 0 ? slice.usage : sanitizeUsage(slice.usage);
8247
+ addPhaseUsage(slice.role ?? primaryRole, slice.servedBy, sliceUsage);
8248
+ options.budget?.onUsage(sliceUsage, slice.servedBy);
8098
8249
  }
8099
8250
  }
8100
- const usageSlices = () => [...usageByModel].map(([sliceServedBy, usage]) => ({
8251
+ const usageSlices = () => [...usageByPhaseModel.values()].map(({ role, servedBy: sliceServedBy, usage }) => ({
8101
8252
  servedBy: sliceServedBy,
8102
- usage
8253
+ usage,
8254
+ role
8103
8255
  }));
8104
8256
  /**
8105
8257
  * Every slice priced at ITS OWN model's rate. An unpriced model
@@ -8110,7 +8262,10 @@ async function runAgent(options) {
8110
8262
  const price = options.priceUsd;
8111
8263
  if (price === void 0) return 0;
8112
8264
  let usd = 0;
8113
- for (const [sliceServedBy, usage] of usageByModel) usd += price(sliceServedBy, usage) ?? 0;
8265
+ for (const slice of usageByPhaseModel.values()) {
8266
+ const sliceUsd = price(slice.servedBy, slice.usage) ?? 0;
8267
+ if (Number.isFinite(sliceUsd) && sliceUsd > 0) usd += sliceUsd;
8268
+ }
8114
8269
  return usd;
8115
8270
  };
8116
8271
  const saveBoundary = async (pending) => {
@@ -8343,24 +8498,32 @@ async function runAgent(options) {
8343
8498
  agentType,
8344
8499
  label: options.label,
8345
8500
  model: servedBy,
8346
- role: options.role ?? "loop"
8501
+ role: primaryRole
8347
8502
  });
8348
8503
  let invariantViolation;
8349
- const recordUsage = (usage, reported, adapterId, ref) => {
8350
- try {
8351
- assertUsageInvariant(usage, adapterId);
8352
- } catch (thrown) {
8353
- invariantViolation = thrown instanceof Error ? thrown.message : String(thrown);
8354
- }
8355
- totalUsage = addUsage(totalUsage, usage);
8356
- usageByModel.set(ref, addUsage(usageByModel.get(ref) ?? ZERO_USAGE$1, usage));
8504
+ const recordUsage = (usage, reported, adapterId, ref, role, streamViolation) => {
8505
+ if (streamViolation !== void 0) invariantViolation ??= `adapter '${adapterId}' violated the Usage invariant: ${streamViolation}`;
8506
+ const snapshot = snapshotUsage(usage);
8507
+ const violation = usageInvariantViolation(snapshot, adapterId);
8508
+ if (violation !== void 0) invariantViolation ??= violation;
8509
+ const safe = violation === void 0 ? snapshot : sanitizeUsage(snapshot);
8510
+ totalUsage = addUsage(totalUsage, safe);
8511
+ addPhaseUsage(role, ref, safe);
8357
8512
  const remainder = {
8358
- inputTokens: Math.max(0, usage.inputTokens - reported.inputTokens),
8359
- outputTokens: Math.max(0, usage.outputTokens - reported.outputTokens),
8360
- cacheReadTokens: Math.max(0, usage.cacheReadTokens - reported.cacheReadTokens),
8361
- cacheWriteTokens: Math.max(0, usage.cacheWriteTokens - reported.cacheWriteTokens)
8513
+ inputTokens: Math.max(0, safe.inputTokens - reported.inputTokens),
8514
+ outputTokens: Math.max(0, safe.outputTokens - reported.outputTokens),
8515
+ cacheReadTokens: Math.max(0, safe.cacheReadTokens - reported.cacheReadTokens),
8516
+ cacheWriteTokens: Math.max(0, safe.cacheWriteTokens - reported.cacheWriteTokens)
8362
8517
  };
8363
- const reasoningRemainder = Math.max(0, (usage.reasoningTokens ?? 0) - (reported.reasoningTokens ?? 0));
8518
+ for (const field of [
8519
+ "inputTokens",
8520
+ "outputTokens",
8521
+ "cacheReadTokens",
8522
+ "cacheWriteTokens"
8523
+ ]) if (reported[field] > safe[field]) invariantViolation ??= `adapter '${adapterId}' violated the Usage invariant: mid-stream ${field} (${String(reported[field])}) exceeded the finish total (${String(safe[field])})`;
8524
+ const overReportedReads = Math.max(0, reported.cacheReadTokens - safe.cacheReadTokens);
8525
+ if (overReportedReads > 0) remainder.inputTokens = Math.min(Number.MAX_SAFE_INTEGER, remainder.inputTokens + overReportedReads);
8526
+ const reasoningRemainder = Math.max(0, (safe.reasoningTokens ?? 0) - (reported.reasoningTokens ?? 0));
8364
8527
  if (reasoningRemainder > 0) remainder.reasoningTokens = reasoningRemainder;
8365
8528
  if (remainder.inputTokens > 0 || remainder.outputTokens > 0 || remainder.cacheReadTokens > 0 || remainder.cacheWriteTokens > 0) options.budget?.onUsage(remainder, ref);
8366
8529
  };
@@ -8375,7 +8538,7 @@ async function runAgent(options) {
8375
8538
  inner: for (;;) {
8376
8539
  const dispatch = () => streamTurn(target.adapter, site.requestFor(target), site.streamOptionsFor(target));
8377
8540
  const outcome = await (options.providerSlot === void 0 ? dispatch() : options.providerSlot(target.adapter.id, dispatch));
8378
- recordUsage(outcome.usage, outcome.reported, target.adapter.id, target.resolved.ref);
8541
+ recordUsage(outcome.usage, outcome.reported, target.adapter.id, target.resolved.ref, site.role, outcome.usageViolation);
8379
8542
  tries += 1;
8380
8543
  const retryClass = outcome.aborted === "idle" ? "transport" : outcome.wireError === void 0 ? void 0 : retryClassOf(outcome.wireError);
8381
8544
  if (retryClass === void 0) return {
@@ -8452,6 +8615,7 @@ async function runAgent(options) {
8452
8615
  let loopDispatch;
8453
8616
  try {
8454
8617
  loopDispatch = await dispatchPhase({
8618
+ role: primaryRole,
8455
8619
  chain: loopChain,
8456
8620
  cursor: loopCursor,
8457
8621
  requestFor: (target) => {
@@ -8643,6 +8807,7 @@ async function runAgent(options) {
8643
8807
  let summaryDispatch;
8644
8808
  try {
8645
8809
  summaryDispatch = await dispatchPhase({
8810
+ role: "summarize",
8646
8811
  chain: [{
8647
8812
  adapter: options.summarize.adapter,
8648
8813
  resolved: options.summarize.resolved
@@ -8822,6 +8987,7 @@ async function runAgent(options) {
8822
8987
  let finalizeDispatch;
8823
8988
  try {
8824
8989
  finalizeDispatch = await dispatchPhase({
8990
+ role: "finalize",
8825
8991
  chain: [{
8826
8992
  adapter: options.finalize.adapter,
8827
8993
  resolved: options.finalize.resolved
@@ -8944,6 +9110,7 @@ async function runAgent(options) {
8944
9110
  let extractDispatch;
8945
9111
  try {
8946
9112
  extractDispatch = await dispatchPhase({
9113
+ role: "extract",
8947
9114
  chain: extractChain,
8948
9115
  cursor: extractCursor,
8949
9116
  requestFor: (target) => {
@@ -9047,7 +9214,7 @@ async function runAgent(options) {
9047
9214
  servedBy,
9048
9215
  transcriptRef
9049
9216
  };
9050
- if (usageByModel.size > 1) result.usageByModel = usageSlices();
9217
+ if (usageByPhaseModel.size > 1) result.usageByModel = usageSlices();
9051
9218
  if (agentError !== void 0) result.error = agentError;
9052
9219
  if (escalationRequest !== void 0) result.escalationRequest = escalationRequest;
9053
9220
  if (abortClass !== void 0) result.abortClass = abortClass;
@@ -9093,6 +9260,15 @@ const ZERO_USAGE = {
9093
9260
  cacheWriteTokens: 0
9094
9261
  };
9095
9262
  /**
9263
+ * A ceiling that is NaN or negative silently disarms every layer (each
9264
+ * comparison against it is false), which is indistinguishable from
9265
+ * uncapped. That must be a loud configuration error, never a silent
9266
+ * fail-open (v1.20.0 review P1-1).
9267
+ */
9268
+ function requireValidCeiling(ceilingUsd, what) {
9269
+ if (!Number.isFinite(ceilingUsd) || ceilingUsd < 0) throw new ConfigError(`${what} must be a finite nonnegative USD amount, got ${String(ceilingUsd)}`);
9270
+ }
9271
+ /**
9096
9272
  * The admission reserve for a spawn: opts.estCost, else profile.estCost,
9097
9273
  * else price(countTokens(input) + one turn's worth of output), else the
9098
9274
  * engine flat default. The output term is caps.maxOutputTokens clamped to
@@ -9135,8 +9311,13 @@ var RunBudget = class {
9135
9311
  exhaustedInternal = false;
9136
9312
  /** Models already warned about; the warning fires once per model per run. */
9137
9313
  unpricedWarned = /* @__PURE__ */ new Set();
9314
+ /** Models whose price function already returned an invalid USD once. */
9315
+ invalidPriceWarned = /* @__PURE__ */ new Set();
9138
9316
  constructor(options) {
9139
- if (options.ceilingUsd !== void 0) this.ceilingUsd = options.ceilingUsd;
9317
+ if (options.ceilingUsd !== void 0) {
9318
+ requireValidCeiling(options.ceilingUsd, "budget ceiling");
9319
+ this.ceilingUsd = options.ceilingUsd;
9320
+ }
9140
9321
  this.lifetimeSpawnCap = options.lifetimeSpawnCap ?? 500;
9141
9322
  if (options.events !== void 0) this.events = options.events;
9142
9323
  if (options.priceUsd !== void 0) this.priceUsd = options.priceUsd;
@@ -9151,8 +9332,9 @@ var RunBudget = class {
9151
9332
  if (options.ceilingUsd !== void 0) root.ceilingUsd = options.ceilingUsd;
9152
9333
  this.accounts.set("run", root);
9153
9334
  if (options.seed !== void 0) {
9335
+ if (!Number.isFinite(options.seed.usd) || options.seed.usd < 0) throw new ConfigError(`budget resume seed is not a finite nonnegative USD amount: ${String(options.seed.usd)}`);
9154
9336
  root.spentUsd = options.seed.usd;
9155
- this.usageInternal = { ...options.seed.usage };
9337
+ this.usageInternal = sanitizeUsage(options.seed.usage);
9156
9338
  this.agentsSpawnedInternal = options.seed.agentsSpawned;
9157
9339
  }
9158
9340
  }
@@ -9192,7 +9374,10 @@ var RunBudget = class {
9192
9374
  parentScope,
9193
9375
  controller: new AbortController()
9194
9376
  };
9195
- if (options.ceilingUsd !== void 0) account.ceilingUsd = options.ceilingUsd;
9377
+ if (options.ceilingUsd !== void 0) {
9378
+ requireValidCeiling(options.ceilingUsd, `ceiling of budget account '${scope}'`);
9379
+ account.ceilingUsd = options.ceilingUsd;
9380
+ }
9196
9381
  if (options.kind !== void 0) account.kind = options.kind;
9197
9382
  this.accounts.set(scope, account);
9198
9383
  }
@@ -9420,15 +9605,16 @@ var RunBudget = class {
9420
9605
  * in-flight agent; providers bill severed streams).
9421
9606
  */
9422
9607
  onUsage(usage, servedBy, accountScope = "run") {
9608
+ const safe = sanitizeUsageDelta(usage);
9423
9609
  this.usageInternal = {
9424
- inputTokens: this.usageInternal.inputTokens + usage.inputTokens,
9425
- outputTokens: this.usageInternal.outputTokens + usage.outputTokens,
9426
- cacheReadTokens: this.usageInternal.cacheReadTokens + usage.cacheReadTokens,
9427
- cacheWriteTokens: this.usageInternal.cacheWriteTokens + usage.cacheWriteTokens
9610
+ inputTokens: this.usageInternal.inputTokens + safe.inputTokens,
9611
+ outputTokens: this.usageInternal.outputTokens + safe.outputTokens,
9612
+ cacheReadTokens: this.usageInternal.cacheReadTokens + safe.cacheReadTokens,
9613
+ cacheWriteTokens: this.usageInternal.cacheWriteTokens + safe.cacheWriteTokens
9428
9614
  };
9429
- const reasoning = (this.usageInternal.reasoningTokens ?? 0) + (usage.reasoningTokens ?? 0);
9615
+ const reasoning = (this.usageInternal.reasoningTokens ?? 0) + (safe.reasoningTokens ?? 0);
9430
9616
  if (reasoning > 0) this.usageInternal.reasoningTokens = reasoning;
9431
- const priced = this.priceUsd?.(servedBy, usage);
9617
+ const priced = this.priceUsd?.(servedBy, safe);
9432
9618
  if (priced === void 0 && this.ceilingUsd !== void 0 && !this.unpricedWarned.has(servedBy)) {
9433
9619
  this.unpricedWarned.add(servedBy);
9434
9620
  this.events?.emit({
@@ -9437,7 +9623,18 @@ var RunBudget = class {
9437
9623
  msg: `no price row for '${servedBy}': its usage does not debit the budget, so the ${this.ceilingUsd} USD run ceiling does NOT bound this model. Add it to createEngine({ pricing }) to cap it; its usage is reported under CostReport.unpriced`
9438
9624
  });
9439
9625
  }
9440
- const usd = priced ?? 0;
9626
+ let usd = priced ?? 0;
9627
+ if (!Number.isFinite(usd) || usd < 0) {
9628
+ if (!this.invalidPriceWarned.has(servedBy)) {
9629
+ this.invalidPriceWarned.add(servedBy);
9630
+ this.events?.emit({
9631
+ type: "log",
9632
+ level: "error",
9633
+ msg: `price function returned ${String(usd)} USD for '${servedBy}'; charging 0 for this slice so the budget stays finite and monotone. Fix the pricing row: this usage is NOT debited and any ceiling under-counts it`
9634
+ });
9635
+ }
9636
+ usd = 0;
9637
+ }
9441
9638
  for (const account of this.chainOf(accountScope)) {
9442
9639
  account.spentUsd += usd;
9443
9640
  if (account.ceilingUsd !== void 0 && account.spentUsd >= account.ceilingUsd && !account.controller.signal.aborted) {
@@ -11000,10 +11197,18 @@ function createCtx(internals, rootWorkflow) {
11000
11197
  result.escalation = report;
11001
11198
  delete result.escalationRequest;
11002
11199
  }
11200
+ const adapterOfRef = (ref) => ref.slice(0, ref.indexOf(":"));
11201
+ const declaredSemantics = [];
11202
+ for (const ref of [result.servedBy, ...(result.usageByModel ?? []).map((slice) => slice.servedBy)]) {
11203
+ const declared = internals.adapters.get(adapterOfRef(ref))?.usageSemantics;
11204
+ if (declared !== void 0 && !declaredSemantics.includes(declared)) declaredSemantics.push(declared);
11205
+ }
11206
+ const servedSemantics = declaredSemantics.length === 0 ? void 0 : declaredSemantics.join("+");
11003
11207
  const terminalPatch = {
11004
11208
  status: result.status === "skipped" ? "error" : result.status,
11005
11209
  usage: result.usage,
11006
11210
  servedBy: result.servedBy,
11211
+ ...servedSemantics === void 0 ? {} : { usageSemantics: servedSemantics },
11007
11212
  ...result.usageByModel === void 0 ? {} : { usageByModel: result.usageByModel },
11008
11213
  costAttribution: {
11009
11214
  ...state.phase === void 0 ? {} : { phase: state.phase },
@@ -11062,12 +11267,13 @@ function createCtx(internals, rootWorkflow) {
11062
11267
  });
11063
11268
  }
11064
11269
  const usd = result.costUsd;
11065
- for (const slice of result.usageByModel ?? [{
11270
+ const attributionSlices = result.usageByModel ?? [{
11066
11271
  servedBy: result.servedBy,
11067
11272
  usage: result.usage
11068
- }]) {
11273
+ }];
11274
+ for (const slice of attributionSlices) {
11069
11275
  const priced = internals.priceUsd(slice.servedBy, slice.usage);
11070
- if (priced === void 0) {
11276
+ if (priced === void 0 || !Number.isFinite(priced) || priced < 0) {
11071
11277
  internals.cost.unpriced.push({
11072
11278
  model: slice.servedBy,
11073
11279
  usage: slice.usage
@@ -11075,10 +11281,11 @@ function createCtx(internals, rootWorkflow) {
11075
11281
  continue;
11076
11282
  }
11077
11283
  bump(internals.cost.byModel, slice.servedBy, priced);
11284
+ const sliceRole = slice.role ?? primaryRole;
11285
+ internals.cost.byRole.set(sliceRole, (internals.cost.byRole.get(sliceRole) ?? 0) + priced);
11078
11286
  }
11079
11287
  bump(internals.cost.byPhase, state.phase ?? "", usd);
11080
11288
  bump(internals.cost.byAgentType, agentType, usd);
11081
- internals.cost.byRole.set(primaryRole, (internals.cost.byRole.get(primaryRole) ?? 0) + usd);
11082
11289
  if (result.error?.kind === "budget" || internals.budget.exhausted && result.status !== "ok") {
11083
11290
  const diagnostics = internals.budget.exhaustionDiagnostics(state.budgetScope ?? "run");
11084
11291
  const crossed = diagnostics.crossed;
@@ -13039,6 +13246,10 @@ function createEngine(options) {
13039
13246
  }
13040
13247
  const priorEntries = (await journal.load(runId)).map((entry) => normalizeEntry(entry));
13041
13248
  scanJournalCompatibility(runId, priorEntries, buildDeriverRegistry(options.extraDerivers));
13249
+ if (priorEntries.some((entry) => entry.usageSemantics === void 0 && (entry.servedBy?.startsWith("openai:") === true && (entry.usage?.cacheWriteTokens ?? 0) > 0 || (entry.usageByModel?.some((slice) => slice.servedBy.startsWith("openai:") && slice.usage.cacheWriteTokens > 0) ?? false)))) process.emitWarning(`resume: run '${runId}' contains OpenAI cache-write usage recorded without a usage-semantics stamp. Entries written by rulvar v1.19.0 double-counted cache writes into inputTokens, so their recorded cost and budget debits are OVERSTATED; unstamped entries from v1.20.0 are correct. Resuming keeps the recorded debits. Audit procedure: https://docs.rulvar.com/guide/providers#openai-legacy-cache-journals`, {
13250
+ code: "RULVAR_LEGACY_CACHE_SEMANTICS",
13251
+ type: "RulvarWarning"
13252
+ });
13042
13253
  return run(bound, resumeOptions?.args, void 0, {
13043
13254
  runId,
13044
13255
  priorEntries,
@@ -13399,4 +13610,4 @@ function createSandboxBridge(ctx, options) {
13399
13610
  };
13400
13611
  }
13401
13612
  //#endregion
13402
- export { AWAIT_SCHEMA, AdmissionController, AdmissionRejectedError, AgentCallError, BUDGET_ABORT_REASON, BudgetExhaustedError, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, ConfigError, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, 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, DedupIndex, EMIT_RESULT_TOOL, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EventBus, ExternalRegistry, FINALIZE_SYNTHESIS_INSTRUCTION, FINISH_SCHEMA, FINISH_TOOL_NAME, FileModelKnowledgeStore, FileTranscriptStore, GitWorktreeProvider, INBOX_PROPOSAL_TTL_DAYS, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, InvalidResolutionError, JournalCompatibilityError, JournalMatcher, JournalMissError, JournalOrderViolation, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, KeyedLimiter, KnowledgeCasError, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LeaseHeldError, LineageIndex, MASKED_SECRET, MAX_DEPTH_CEILING, ModelRetry, NoProgressDetector, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OrchestratorCapConfigError, PARALLEL_AGENTS_SCHEMA, ParallelSiteCounter, PlanInvariantError, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_PROFILES, ReplayPlanHashMismatch, Replayer, ResolutionArbiter, ResolutionFold, RulvarError, RunBudget, SPAWN_AGENT_SCHEMA, SandboxError, ScriptRejected, Semaphore, SpanRegistry, TOOL_NAME_PATTERN, TerminationAccount, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentResultWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, atCompactionThreshold, 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, compileVerifiedLayer, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createSandboxBridge, currentOnlyKeyRing, decodeCheckpoint, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, executeWorkflow, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, foldTermination, formatRePrompt, formatScopePath, hashWorkflowBody, hashWorkflowSource, identityJcs, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lexShellCommand, liftRetainedParts, lineageWeightOf, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, mergeUsageLimits, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, parallelScope, parseModelRef, parseScopePath, phiInitialOf, pipelineScope, planNodeScope, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, readTerminationInit, registryKeyRing, remeasureQueue, replayDisposition, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, scanJournalCompatibility, schemaHash, schemaHashOfSpec, selectStructuredOutputTier, shouldCompact, spawnDepthOf, summarizeInstruction, summarizeOutput, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolContract, toolsetHash, ttlState, validateEditorialCommit, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateSchemaSpec, validateTerminationLimits, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
13613
+ export { AWAIT_SCHEMA, AdmissionController, AdmissionRejectedError, AgentCallError, BUDGET_ABORT_REASON, BudgetExhaustedError, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, ConfigError, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, 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, DedupIndex, EMIT_RESULT_TOOL, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EventBus, ExternalRegistry, FINALIZE_SYNTHESIS_INSTRUCTION, FINISH_SCHEMA, FINISH_TOOL_NAME, FileModelKnowledgeStore, FileTranscriptStore, GitWorktreeProvider, INBOX_PROPOSAL_TTL_DAYS, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, InvalidResolutionError, JournalCompatibilityError, JournalMatcher, JournalMissError, JournalOrderViolation, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, KeyedLimiter, KnowledgeCasError, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LeaseHeldError, LineageIndex, MASKED_SECRET, MAX_DEPTH_CEILING, ModelRetry, NoProgressDetector, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OrchestratorCapConfigError, PARALLEL_AGENTS_SCHEMA, ParallelSiteCounter, PlanInvariantError, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_PROFILES, ReplayPlanHashMismatch, Replayer, ResolutionArbiter, ResolutionFold, RulvarError, RunBudget, SPAWN_AGENT_SCHEMA, SandboxError, ScriptRejected, Semaphore, SpanRegistry, TOOL_NAME_PATTERN, TerminationAccount, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentResultWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, atCompactionThreshold, 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, compileVerifiedLayer, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createSandboxBridge, currentOnlyKeyRing, decodeCheckpoint, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, executeWorkflow, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, foldTermination, formatRePrompt, formatScopePath, hashWorkflowBody, hashWorkflowSource, identityJcs, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lexShellCommand, liftRetainedParts, lineageWeightOf, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, mergeUsageLimits, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, parallelScope, parseModelRef, parseScopePath, phiInitialOf, pipelineScope, planNodeScope, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, readTerminationInit, registryKeyRing, remeasureQueue, replayDisposition, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, sanitizeTokenCount, sanitizeUsage, sanitizeUsageDelta, scanJournalCompatibility, schemaHash, schemaHashOfSpec, selectStructuredOutputTier, shouldCompact, snapshotUsage, spawnDepthOf, summarizeInstruction, summarizeOutput, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolContract, toolsetHash, ttlState, usageViolations, validateEditorialCommit, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateSchemaSpec, validateTerminationLimits, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rulvar/core",
3
- "version": "1.19.0",
3
+ "version": "1.21.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",