@rulvar/core 1.72.0 → 1.74.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
@@ -3111,12 +3111,33 @@ interface EngineQuotaConfig {
3111
3111
  * knob. reconcile failures only ever warn.
3112
3112
  */
3113
3113
  onLimiterError?: "deny" | "allow";
3114
+ /**
3115
+ * The drift telemetry opt-in (the v1.71 experiment review, P0.5
3116
+ * resized): the SAME rule declaration `preflightEstimate` takes as
3117
+ * `quotaRules`, mirrored here so the engine can hold it against what
3118
+ * providers actually REPORT. When a live 429 carries
3119
+ * provider-normalized limits (the openai and anthropic adapters
3120
+ * parse the x-ratelimit headers into
3121
+ * `WireError.data.reportedLimits`) and a declared per-minute cap
3122
+ * EXCEEDS the reported one, the run journals a `quota_drift`
3123
+ * decision (provider, model, tenant, dimension, declared, reported;
3124
+ * one per invocation and dimension) and emits a warn log, because a
3125
+ * limiter configured above the provider's real ceiling
3126
+ * under-throttles and live denials follow: the experiment inflated
3127
+ * 12M TPM over a real 1M and paid seven live 429s with nothing
3128
+ * recording the mismatch. Purely observational: nothing clamps, the
3129
+ * limiter keeps enforcing the declaration (clamping is host policy).
3130
+ * Absent = byte identical journals and events.
3131
+ */
3132
+ declaredRules?: readonly QuotaRule[];
3114
3133
  }
3115
3134
  /** The resolved engine-side quota runtime threaded into every run. */
3116
3135
  interface EngineQuotaRuntime {
3117
3136
  limiter: QuotaLimiter;
3118
3137
  tenant?: string;
3119
3138
  onLimiterError: "deny" | "allow";
3139
+ /** The declared rule mirror for drift telemetry; see {@link EngineQuotaConfig}. */
3140
+ declaredRules?: readonly QuotaRule[];
3120
3141
  }
3121
3142
  /**
3122
3143
  * Validates createEngine's quota config as a typed ConfigError before
@@ -4136,6 +4157,16 @@ interface AgentResult<T> {
4136
4157
  */
4137
4158
  transportRetries?: number;
4138
4159
  /**
4160
+ * Provider-reported rate limits observed on this invocation's 429s
4161
+ * (the v1.71 experiment review, P0.5): one entry per (provider,
4162
+ * model), the latest observation winning, parsed by the adapters
4163
+ * into `WireError.data.reportedLimits`. Live telemetry only, exactly
4164
+ * like transportRetries: never journaled, absent on a replayed
4165
+ * result; the ctx layer holds it against `quota.declaredRules` and
4166
+ * journals the drift verdicts, which ARE durable.
4167
+ */
4168
+ rateLimitObservations?: RateLimitObservation[];
4169
+ /**
4139
4170
  * The exploration guard counters (RV-210): present whenever any of
4140
4171
  * the exploration limits (toolBudgetNotices, maxRepeatedToolSignature,
4141
4172
  * maxNoNewEvidenceCalls) was configured. Journaled inside the terminal
@@ -4157,6 +4188,24 @@ interface AgentResult<T> {
4157
4188
  */
4158
4189
  partial?: ProgressReport;
4159
4190
  }
4191
+ /** One 429's provider-normalized limits, per (provider, model). */
4192
+ interface RateLimitObservation {
4193
+ provider: string;
4194
+ model: string;
4195
+ /**
4196
+ * Per-minute limits the provider REPORTED in its rate-limit
4197
+ * headers, normalized by the adapter: openai fills
4198
+ * requestsPerMinute and tokensPerMinute; anthropic fills
4199
+ * requestsPerMinute plus the split inputTokensPerMinute and
4200
+ * outputTokensPerMinute.
4201
+ */
4202
+ reportedLimits: {
4203
+ requestsPerMinute?: number;
4204
+ tokensPerMinute?: number;
4205
+ inputTokensPerMinute?: number;
4206
+ outputTokensPerMinute?: number;
4207
+ };
4208
+ }
4160
4209
  type EscalatedResult<T> = AgentResult<T> & {
4161
4210
  status: "escalated";
4162
4211
  escalation: EscalationReport;
@@ -4405,6 +4454,18 @@ interface RunAgentOptions<S extends SchemaSpec = JsonSchema> {
4405
4454
  ok: false;
4406
4455
  feedback: Record<string, unknown>;
4407
4456
  }>;
4457
+ /**
4458
+ * The repair reserve (the v1.71 experiment review, P0.4): max EXTRA
4459
+ * turns the loop may grant past limits.maxTurns, one per rejected
4460
+ * terminal-tool exchange, schema-invalid arguments and host
4461
+ * validation rejections alike. The grant count derives from the
4462
+ * message window itself (error tool results named after the
4463
+ * terminal tool, clamped to the reserve), so a resumed segment that
4464
+ * restored the window mid-exchange re-derives the same grants and
4465
+ * nothing needs journaling. Zero (or absent) keeps the ceiling
4466
+ * byte identical to the pre 1.73 loop.
4467
+ */
4468
+ repairTurnReserve?: number;
4408
4469
  };
4409
4470
  agentType?: string;
4410
4471
  /** The primary invocation role of the tool loop; default 'loop' (M6-T05; RV-211 adds synthesize). */
@@ -7038,6 +7099,23 @@ interface FinishValidationSpec {
7038
7099
  */
7039
7100
  maxRepairs?: number;
7040
7101
  /**
7102
+ * The repair turn reserve (the v1.71 experiment review, P0.4; the
7103
+ * reserve RV-204 deliberately deferred). A nonnegative integer,
7104
+ * default 0: max EXTRA turns the invocation the validators bind (the
7105
+ * synthesis invocation when `synthesis` is configured, the
7106
+ * coordination loop otherwise) may consume past its `maxTurns`, one
7107
+ * granted per rejected finish exchange, schema-invalid finish
7108
+ * arguments and host validation rejections alike. Without it, repair
7109
+ * exchanges and generation compete for the same turn budget: the
7110
+ * v1.71 experiment lost its whole run to one malformed finish plus
7111
+ * one validator rejection inside maxTurns 3. The reserve is bounded,
7112
+ * spends from the ordinary budget ceilings (a granted turn is a paid
7113
+ * provider turn), and folds into the preflight turn projection
7114
+ * (`projectedProviderTurns` and the run ceiling) when declared
7115
+ * there. Zero keeps the pre 1.73 ceiling byte identical.
7116
+ */
7117
+ repairTurnReserve?: number;
7118
+ /**
7041
7119
  * The unified output contract this validator set enforces (the v1.71
7042
7120
  * experiment review, P0.1/P0.2). Construction then runs the golden
7043
7121
  * self test with the contract's fixtures as defaults, the contract's
@@ -8626,6 +8704,17 @@ interface InvoiceRow {
8626
8704
  responseId?: string;
8627
8705
  usage: Usage;
8628
8706
  usageApprox?: boolean;
8707
+ /**
8708
+ * Present and true when this `unconfirmed` row recorded ZERO usage
8709
+ * on every counter (the v1.71 experiment review, P1.4): a failed
8710
+ * attempt whose usage this ledger never saw. The zeros mean
8711
+ * "nothing recorded", never "the provider metered nothing": the
8712
+ * provider may have billed prompt processing before the failure, so
8713
+ * a statement join must treat this row's usage as unknown, not as
8714
+ * zero. Derived at export time from the journaled record; rows with
8715
+ * any recorded usage, and every other verdict, never carry it.
8716
+ */
8717
+ usageUnknown?: true;
8629
8718
  /** This row priced at its own model's rate; absent when no price row covers it. */
8630
8719
  usd?: number;
8631
8720
  /**
@@ -8670,6 +8759,8 @@ interface InvoiceExport {
8670
8759
  }>;
8671
8760
  /** Rows whose reconciliation is not 'provider-id-present'. */
8672
8761
  reconciliationFailures: number;
8762
+ /** Rows carrying `usageUnknown`; present when at least one does. */
8763
+ usageUnknownRows?: number;
8673
8764
  /** Present and true when any contributing entry carried approximate usage. */
8674
8765
  usageApprox?: boolean;
8675
8766
  }
@@ -8749,6 +8840,23 @@ interface PreflightOrchestratorSpec {
8749
8840
  * root, so only they subtract it from spawn-admission headroom.
8750
8841
  */
8751
8842
  extension?: boolean;
8843
+ /**
8844
+ * The separate synthesis invocation (RV-211), when the orchestration
8845
+ * configures one (the v1.71 experiment review: the run ceiling used
8846
+ * to stop at the coordination loop, undercounting the synthesis
8847
+ * turns). `limits` mirrors OrchestrateSynthesis.limits exactly
8848
+ * (absent = the DEFAULT_SYNTHESIS_MAX_TURNS invocation), `model`
8849
+ * mirrors its model override (absent = defaults.routing.synthesize),
8850
+ * and `estInputTokens` is the prompt-size stand-in for the derived
8851
+ * synthesis prompt. When `finishValidation.repairTurnReserve` is
8852
+ * declared, the reserve folds into THIS invocation's projected turns,
8853
+ * because the validators bind the synthesis finish.
8854
+ */
8855
+ synthesis?: {
8856
+ model?: ModelSpec;
8857
+ limits?: UsageLimits;
8858
+ estInputTokens?: number;
8859
+ };
8752
8860
  }
8753
8861
  /** The full input: engine surface, run surface, and the declared wave. */
8754
8862
  interface PreflightInput {
@@ -8780,6 +8888,15 @@ interface PreflightInput {
8780
8888
  validators: FinishValidator[];
8781
8889
  contract?: FinishContract;
8782
8890
  selfTest?: FinishSelfTestFixtures;
8891
+ /**
8892
+ * Mirrors FinishValidationSpec.repairTurnReserve: folds the
8893
+ * declared repair headroom into the projected turns of the
8894
+ * invocation the validators bind (the synthesis invocation when
8895
+ * orchestrator.synthesis is declared, the coordination loop
8896
+ * otherwise), so the run ceiling prices the repair exchange the
8897
+ * runtime would actually grant.
8898
+ */
8899
+ repairTurnReserve?: number;
8783
8900
  };
8784
8901
  }
8785
8902
  /** One linter verdict; `spawn` names the wave entry it is about. */
@@ -8861,6 +8978,16 @@ interface PreflightReport {
8861
8978
  finalizeTurns: number; /** Whether the finalize reserve is committed against the run root (extension runs). */
8862
8979
  reserveCommitted: boolean; /** The orchestrator agent's own loop ceiling, derived exactly like a spawn's. */
8863
8980
  projectedProviderTurns: number;
8981
+ /**
8982
+ * The separate synthesis invocation's projection, present when
8983
+ * input.orchestrator.synthesis was declared and the role
8984
+ * resolves: its turn ceiling (the repair turn reserve folded in
8985
+ * when declared) and its serving model.
8986
+ */
8987
+ synthesis?: {
8988
+ projectedProviderTurns: number;
8989
+ servedBy?: ModelRef;
8990
+ };
8864
8991
  };
8865
8992
  };
8866
8993
  quota: {
@@ -9431,4 +9558,4 @@ interface SandboxBridge {
9431
9558
  declare const SANDBOX_AGENT_OPT_KEYS: readonly string[];
9432
9559
  declare function createSandboxBridge(ctx: Ctx<never>, options: SandboxBridgeOptions): SandboxBridge;
9433
9560
  //#endregion
9434
- 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, 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_MIN_SHARE, 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, EntryKind, EntryRef, EntryStatus, EnvelopeEncryption, EnvelopeEncryptionOptions, ErrorClass, ErrorCode, ErrorPolicy, EscalatedResult, EscalationDecision, EscalationDecisionAbortedError, EscalationDigest, EscalationKind, EscalationLimits, EscalationOptions, EscalationReport, EscalationRequest, EventBus, type EvidenceRef, type ExecutorRegistry, type ExplorationSummary, ExtensionAppendInput, ExtensionDispatchSpec, ExternalIdentityInput, ExternalRegistry, ExtractNecessityInput, FINALIZE_SYNTHESIS_INSTRUCTION, FINISH_SCHEMA, FINISH_TOOL_NAME, FailRunError, FailoverTarget, FailoverTrigger, FallbackField, FallbackTrigger, FileModelKnowledgeStore, FileModelKnowledgeStoreOptions, FileTranscriptStore, FinishContract, FinishContractCitations, 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, 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, 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, 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, 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, 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, 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, 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, identityJcs, implementationAgentProfile, invoiceFromJournal, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, 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, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, progressReportTool, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, quotaActualTokens, quotaEstimateTokens, quotaRuleAdmission, 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, snapshotUsage, spawnDepthOf, 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 };
9561
+ 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, 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_MIN_SHARE, 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, EntryKind, EntryRef, EntryStatus, EnvelopeEncryption, EnvelopeEncryptionOptions, ErrorClass, ErrorCode, ErrorPolicy, EscalatedResult, EscalationDecision, EscalationDecisionAbortedError, EscalationDigest, EscalationKind, EscalationLimits, EscalationOptions, EscalationReport, EscalationRequest, EventBus, type EvidenceRef, type ExecutorRegistry, type ExplorationSummary, ExtensionAppendInput, ExtensionDispatchSpec, ExternalIdentityInput, ExternalRegistry, ExtractNecessityInput, FINALIZE_SYNTHESIS_INSTRUCTION, FINISH_SCHEMA, FINISH_TOOL_NAME, FailRunError, FailoverTarget, FailoverTrigger, FallbackField, FallbackTrigger, FileModelKnowledgeStore, FileModelKnowledgeStoreOptions, FileTranscriptStore, FinishContract, FinishContractCitations, 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, 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, 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, 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, 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, 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, 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, identityJcs, implementationAgentProfile, invoiceFromJournal, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, 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, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, progressReportTool, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, quotaActualTokens, quotaEstimateTokens, quotaRuleAdmission, 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, snapshotUsage, spawnDepthOf, 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
@@ -8361,6 +8361,8 @@ function invoiceFromJournal(entries, priceUsd) {
8361
8361
  const records = entry.providerCalls ?? [];
8362
8362
  for (const record of records) {
8363
8363
  const usd = rowUsd(priceUsd, record.servedBy, record.usage);
8364
+ const reconciliation = record.responseId !== void 0 ? "provider-id-present" : record.outcome === "ok" ? "missing-provider-id" : "unconfirmed";
8365
+ const usageUnknown = reconciliation === "unconfirmed" && USAGE_FIELDS.every((field) => record.usage[field] === 0) && (record.usage.reasoningTokens ?? 0) === 0;
8364
8366
  rows.push({
8365
8367
  ...base,
8366
8368
  ordinal: record.ordinal,
@@ -8371,10 +8373,11 @@ function invoiceFromJournal(entries, priceUsd) {
8371
8373
  ...record.responseId === void 0 ? {} : { responseId: record.responseId },
8372
8374
  usage: record.usage,
8373
8375
  ...record.usageApprox === true ? { usageApprox: true } : {},
8376
+ ...usageUnknown ? { usageUnknown: true } : {},
8374
8377
  ...usd === void 0 ? {} : { usd },
8375
8378
  allocatedUsd: 0,
8376
8379
  ...mark,
8377
- reconciliation: record.responseId !== void 0 ? "provider-id-present" : record.outcome === "ok" ? "missing-provider-id" : "unconfirmed"
8380
+ reconciliation
8378
8381
  });
8379
8382
  }
8380
8383
  if (records.length === 0) {
@@ -8424,6 +8427,10 @@ function invoiceFromJournal(entries, priceUsd) {
8424
8427
  rowUsdNonAdditive: true,
8425
8428
  unpriced: [...report.unpriced, ...report.abandoned.unpriced],
8426
8429
  reconciliationFailures: rows.filter((row) => row.reconciliation !== "provider-id-present").length,
8430
+ ...(() => {
8431
+ const count = rows.filter((row) => row.usageUnknown === true).length;
8432
+ return count === 0 ? {} : { usageUnknownRows: count };
8433
+ })(),
8427
8434
  ...usageApprox ? { usageApprox: true } : {}
8428
8435
  };
8429
8436
  }
@@ -8954,6 +8961,8 @@ function validateEngineQuotaConfig(config, site = "createEngine quota") {
8954
8961
  if (typeof limiter !== "object" || limiter === null || typeof limiter.reserve !== "function" || typeof limiter.reconcile !== "function") throw new ConfigError(`${site}.limiter must implement QuotaLimiter (reserve and reconcile functions)`);
8955
8962
  if (candidate.tenant !== void 0 && (typeof candidate.tenant !== "string" || candidate.tenant === "")) throw new ConfigError(`${site}.tenant must be a nonempty string when given`);
8956
8963
  if (candidate.onLimiterError !== void 0 && candidate.onLimiterError !== "deny" && candidate.onLimiterError !== "allow") throw new ConfigError(`${site}.onLimiterError must be 'deny' or 'allow' when given`);
8964
+ const declared = candidate.declaredRules;
8965
+ if (declared !== void 0) validateQuotaRules(declared, `${site}.declaredRules`);
8957
8966
  }
8958
8967
  //#endregion
8959
8968
  //#region src/runtime/usage-limits.ts
@@ -10340,6 +10349,7 @@ async function runAgent(options) {
10340
10349
  const providerCalls = [];
10341
10350
  let invocationCounter = 0;
10342
10351
  let transportRetries = 0;
10352
+ const rateLimitObservations = /* @__PURE__ */ new Map();
10343
10353
  const roleUsageSnapshot = (role) => {
10344
10354
  const snapshot = /* @__PURE__ */ new Map();
10345
10355
  for (const [key, slice] of usageByPhaseModel) if (slice.role === role) snapshot.set(key, slice.usage);
@@ -11017,6 +11027,12 @@ async function runAgent(options) {
11017
11027
  if (outcome.aborted !== void 0) record.aborted = outcome.aborted;
11018
11028
  else if (outcome.wireError !== void 0) record.errorCode = outcome.wireError.code;
11019
11029
  providerCalls.push(record);
11030
+ const limited = outcome.wireError?.data;
11031
+ if (limited?.kind === "rate-limit" && typeof limited.reportedLimits === "object" && limited.reportedLimits !== null) rateLimitObservations.set(`${target.adapter.id}:${target.resolved.model}`, {
11032
+ provider: target.adapter.id,
11033
+ model: target.resolved.model,
11034
+ reportedLimits: limited.reportedLimits
11035
+ });
11020
11036
  }
11021
11037
  tries += 1;
11022
11038
  const retryClass = outcome.aborted === "idle" ? "transport" : outcome.wireError === void 0 ? void 0 : retryClassOf(outcome.wireError);
@@ -11087,7 +11103,9 @@ async function runAgent(options) {
11087
11103
  status = "limit";
11088
11104
  break;
11089
11105
  }
11090
- if (turns >= limits.maxTurns) {
11106
+ const repairReserve = options.terminalTool?.repairTurnReserve ?? 0;
11107
+ const grantedRepairTurns = repairReserve === 0 ? 0 : Math.min(repairReserve, messages.reduce((count, message) => count + message.parts.filter((part) => part.type === "tool-result" && part.name === options.terminalTool?.name && part.isError === true).length, 0));
11108
+ if (turns >= limits.maxTurns + grantedRepairTurns) {
11091
11109
  status = "limit";
11092
11110
  break;
11093
11111
  }
@@ -11837,6 +11855,7 @@ async function runAgent(options) {
11837
11855
  if (limitPartial !== void 0) result.partial = limitPartial;
11838
11856
  if (usageApprox) result.usageApprox = true;
11839
11857
  if (transportRetries > 0) result.transportRetries = transportRetries;
11858
+ if (rateLimitObservations.size > 0) result.rateLimitObservations = [...rateLimitObservations.values()];
11840
11859
  return result;
11841
11860
  }
11842
11861
  //#endregion
@@ -13989,6 +14008,59 @@ function createCtx(internals, rootWorkflow) {
13989
14008
  exitActivity?.();
13990
14009
  }
13991
14010
  internals.budget.releaseReserve(reserve, budgetAccount);
14011
+ const declaredRules = internals.quota?.declaredRules;
14012
+ if (declaredRules !== void 0 && result.rateLimitObservations !== void 0) for (const observation of result.rateLimitObservations) {
14013
+ const probe = {
14014
+ provider: observation.provider,
14015
+ model: observation.model,
14016
+ ...internals.quota?.tenant === void 0 ? {} : { tenant: internals.quota.tenant },
14017
+ estimate: {
14018
+ requests: 1,
14019
+ inputTokens: 0
14020
+ }
14021
+ };
14022
+ const matching = declaredRules.filter((rule) => quotaRuleMatches(rule, probe));
14023
+ const declaredOf = (pick) => {
14024
+ const caps = matching.map(pick).filter((cap) => cap !== void 0);
14025
+ return caps.length === 0 ? void 0 : Math.min(...caps);
14026
+ };
14027
+ const reported = observation.reportedLimits;
14028
+ const reportedTokens = reported.tokensPerMinute ?? (reported.inputTokensPerMinute !== void 0 && reported.outputTokensPerMinute !== void 0 ? reported.inputTokensPerMinute + reported.outputTokensPerMinute : void 0);
14029
+ const dimensions = [{
14030
+ dimension: "requests",
14031
+ declared: declaredOf((rule) => rule.requestsPerMinute),
14032
+ observed: reported.requestsPerMinute
14033
+ }, {
14034
+ dimension: "tokens",
14035
+ declared: declaredOf((rule) => rule.tokensPerMinute),
14036
+ observed: reportedTokens
14037
+ }];
14038
+ for (const { dimension, declared, observed } of dimensions) {
14039
+ if (declared === void 0 || observed === void 0 || declared <= observed) continue;
14040
+ const key = `quota-drift:${dimension}:${observation.provider}:${observation.model}`;
14041
+ if (!internals.replayer.snapshot().some((entry) => entry.kind === "decision" && entry.scope === state.scope && entry.key === key)) await internals.replayer.appendSinglePhase({
14042
+ scope: state.scope,
14043
+ key,
14044
+ kind: "decision",
14045
+ status: "ok",
14046
+ spanId,
14047
+ value: {
14048
+ decisionType: "quota_drift",
14049
+ provider: observation.provider,
14050
+ model: observation.model,
14051
+ ...internals.quota?.tenant === void 0 ? {} : { tenant: internals.quota.tenant },
14052
+ dimension,
14053
+ declaredPerMinute: declared,
14054
+ reportedPerMinute: observed
14055
+ }
14056
+ });
14057
+ internals.events.emit({
14058
+ type: "log",
14059
+ level: "warn",
14060
+ msg: `declared quota exceeds the provider-reported limit: ${observation.provider}:${observation.model} ${dimension} declared ${String(declared)}/min, the provider reports ${String(observed)}/min; the limiter under-throttles and live 429s follow (journaled decision 'quota_drift')`
14061
+ }, spanId);
14062
+ }
14063
+ }
13992
14064
  const collectAndDisposeWorktree = async () => {
13993
14065
  if (acquired === void 0) return;
13994
14066
  try {
@@ -15651,6 +15723,7 @@ function validateOrchestrateOptions(opts) {
15651
15723
  seen.add(validator.name);
15652
15724
  }
15653
15725
  if (fv.maxRepairs !== void 0) requireNonNegativeInteger(fv.maxRepairs, "orchestrate finishValidation.maxRepairs");
15726
+ if (fv.repairTurnReserve !== void 0) requireNonNegativeInteger(fv.repairTurnReserve, "orchestrate finishValidation.repairTurnReserve");
15654
15727
  const contract = fv.contract;
15655
15728
  if (contract !== void 0) {
15656
15729
  const shape = contract;
@@ -16756,7 +16829,10 @@ function makeOrchestratorWorkflow(goal, opts) {
16756
16829
  },
16757
16830
  [kTerminalTool]: {
16758
16831
  name: FINISH_TOOL_NAME,
16759
- ...validationSpec === void 0 || opts?.synthesis !== void 0 ? {} : { validate: validateFinish }
16832
+ ...validationSpec === void 0 || opts?.synthesis !== void 0 ? {} : {
16833
+ validate: validateFinish,
16834
+ ...validationSpec.repairTurnReserve === void 0 ? {} : { repairTurnReserve: validationSpec.repairTurnReserve }
16835
+ }
16760
16836
  },
16761
16837
  ...(() => {
16762
16838
  const priorCancelledRoot = internals.replayer.snapshot().filter((entry) => entry.kind === "agent" && entry.scope === callingState.scope && entry.status === "cancelled" && entry.checkpointRef !== void 0).at(-1);
@@ -17056,7 +17132,10 @@ function makeOrchestratorWorkflow(goal, opts) {
17056
17132
  ...spec.estCost === void 0 ? {} : { estCost: spec.estCost },
17057
17133
  [kTerminalTool]: {
17058
17134
  name: FINISH_TOOL_NAME,
17059
- ...validationSpec === void 0 ? {} : { validate: validateFinish }
17135
+ ...validationSpec === void 0 ? {} : {
17136
+ validate: validateFinish,
17137
+ ...validationSpec.repairTurnReserve === void 0 ? {} : { repairTurnReserve: validationSpec.repairTurnReserve }
17138
+ }
17060
17139
  }
17061
17140
  };
17062
17141
  const synthesized = await runtime.runInScope(synthesisState, () => ctx.agent(prompt, synthesisOpts));
@@ -17136,7 +17215,40 @@ function makeOrchestratorWorkflow(goal, opts) {
17136
17215
  if (validationTermination !== void 0) throw validationTermination;
17137
17216
  if (orchestratorAccount !== void 0) internals.cost.orchestrator.spentUsd = internals.budget.accountView(orchestratorAccount)?.spentUsd ?? 0;
17138
17217
  if (result.status !== "ok") throw new ConfigError(`the orchestrator agent terminated with status '${result.status}'` + (result.errorMessage === void 0 ? "" : `: ${result.errorMessage}`));
17139
- if (opts?.acceptance === void 0) return await runSynthesis(result.output);
17218
+ /**
17219
+ * The synthesis failure enrichment (the v1.71 experiment review,
17220
+ * P0.8 remainder + P1.7): every typed failure a synthesis
17221
+ * invocation throws gains the verdict-derived repair taxonomy read
17222
+ * from the JOURNALED validation decisions (identical live and on
17223
+ * replay), and, when an acceptance verdict exists, the acceptance
17224
+ * snapshot the children already earned; the completion mirror then
17225
+ * lifts completion and childStatusCounts onto the error outcome,
17226
+ * exactly like the acceptance rejection path. The experiment's
17227
+ * outcome showed completion null beside four accepted children;
17228
+ * these are the fields that say "the fan-out work is complete, the
17229
+ * failure is downstream". The rejection-past-the-bound error keeps
17230
+ * its own repairsUsed/maxRepairs/failed untouched.
17231
+ */
17232
+ const enrichSynthesisFailure = (thrown, snapshot) => {
17233
+ if (!(thrown instanceof FailRunError)) throw thrown;
17234
+ const base = thrown.data ?? {};
17235
+ const spent = validationDecisions().filter((candidate) => candidate.verdict !== "accepted");
17236
+ const rejectedValidators = [...new Set(spent.flatMap((candidate) => candidate.failed.map((f) => f.name)))];
17237
+ throw new FailRunError(thrown.message, { data: {
17238
+ ...base,
17239
+ ...snapshot ?? {},
17240
+ ...spent.length === 0 || base.repairsUsed !== void 0 ? {} : {
17241
+ repairsUsed: spent.length,
17242
+ maxRepairs: validationSpec?.maxRepairs ?? 1,
17243
+ rejectedValidators
17244
+ }
17245
+ } });
17246
+ };
17247
+ if (opts?.acceptance === void 0) try {
17248
+ return await runSynthesis(result.output);
17249
+ } catch (thrown) {
17250
+ return enrichSynthesisFailure(thrown);
17251
+ }
17140
17252
  const acceptanceKey = "acceptance";
17141
17253
  const priorAcceptance = internals.replayer.snapshot().find((entry) => entry.kind === "decision" && entry.scope === callingState.scope && entry.key === acceptanceKey);
17142
17254
  let decision;
@@ -17209,8 +17321,17 @@ function makeOrchestratorWorkflow(goal, opts) {
17209
17321
  ...decision.synthesisSkipped === void 0 ? {} : { synthesisSkipped: decision.synthesisSkipped }
17210
17322
  } });
17211
17323
  }
17324
+ let synthesizedFinal;
17325
+ try {
17326
+ synthesizedFinal = await runSynthesis(result.output);
17327
+ } catch (thrown) {
17328
+ enrichSynthesisFailure(thrown, {
17329
+ completion: decision.completion,
17330
+ childStatusCounts: decision.childStatusCounts
17331
+ });
17332
+ }
17212
17333
  return {
17213
- result: await runSynthesis(result.output),
17334
+ result: synthesizedFinal,
17214
17335
  completion: decision.completion,
17215
17336
  childStatusCounts: decision.childStatusCounts,
17216
17337
  degradedReasons: decision.degradedReasons,
@@ -17351,6 +17472,8 @@ function preflightEstimate(input) {
17351
17472
  const maxDepth = engine.budgetDefaults?.maxDepth ?? 1;
17352
17473
  const perRun = engine.concurrency?.perRun ?? 12;
17353
17474
  const runLimits = mergeUsageLimits(void 0, input.run?.limits, defaults.limits);
17475
+ const finishRepairReserve = input.finishValidation?.repairTurnReserve ?? 0;
17476
+ const coordinationRepairReserve = input.orchestrator?.synthesis === void 0 ? finishRepairReserve : 0;
17354
17477
  let orchestratorEcho;
17355
17478
  let reservedForFinalizationUsd = 0;
17356
17479
  let effectiveCapUsd;
@@ -17371,7 +17494,7 @@ function preflightEstimate(input) {
17371
17494
  finalizeReserveUsd,
17372
17495
  finalizeTurns,
17373
17496
  reserveCommitted,
17374
- projectedProviderTurns: projectedProviderTurnsOf(echoLimits, overallExecutedCeiling(echoLimits, toolCeilingsOf(echoLimits)))
17497
+ projectedProviderTurns: projectedProviderTurnsOf(echoLimits, overallExecutedCeiling(echoLimits, toolCeilingsOf(echoLimits))) + coordinationRepairReserve
17375
17498
  };
17376
17499
  if (spec?.capUsd !== void 0 && spec.capFraction === void 0 && effectiveCapUsd !== void 0 && effectiveCapUsd < spec.capUsd) say({
17377
17500
  severity: "warning",
@@ -17589,7 +17712,7 @@ function preflightEstimate(input) {
17589
17712
  model,
17590
17713
  inputFloor: input.orchestrator.estInputTokens ?? 0,
17591
17714
  outputBound: outputBound ?? 0,
17592
- turns: projectedProviderTurnsOf(orchLimits, overallExecutedCeiling(orchLimits, toolCeilingsOf(orchLimits))),
17715
+ turns: projectedProviderTurnsOf(orchLimits, overallExecutedCeiling(orchLimits, toolCeilingsOf(orchLimits))) + coordinationRepairReserve,
17593
17716
  count: 1
17594
17717
  });
17595
17718
  if (effectiveCapUsd !== void 0) orchestratorReserveUsd = Math.max(0, orchestratorAdmissionEstCostUsd(effectiveCapUsd, reservedForFinalizationUsd));
@@ -17601,6 +17724,38 @@ function preflightEstimate(input) {
17601
17724
  flatReserveUsd
17602
17725
  });
17603
17726
  }
17727
+ if (input.orchestrator.synthesis !== void 0) {
17728
+ const synthesis = input.orchestrator.synthesis;
17729
+ if (synthesis.limits !== void 0) validateUsageLimits(synthesis.limits, "preflight orchestrator.synthesis.limits");
17730
+ if (synthesis.estInputTokens !== void 0) requireNonNegativeInteger(synthesis.estInputTokens, "preflight orchestrator.synthesis.estInputTokens");
17731
+ const servedBy = resolveServing(synthesis.model) ?? resolveServing(defaults.routing?.synthesize);
17732
+ if (servedBy === void 0) say({
17733
+ severity: "error",
17734
+ code: "unrouted-role",
17735
+ message: "the synthesis invocation resolves no model for role 'synthesize': set defaults.routing.synthesize or a synthesis model on the call",
17736
+ spawn: "synthesis"
17737
+ });
17738
+ else {
17739
+ const caps = capsOf(servedBy);
17740
+ const merged = mergeUsageLimits(synthesis.limits ?? { maxTurns: 4 }, void 0, defaults.limits);
17741
+ const outputBound = caps === void 0 ? merged.maxOutputTokensPerTurn : merged.maxOutputTokensPerTurn === void 0 ? caps.maxOutputTokens : Math.min(caps.maxOutputTokens, merged.maxOutputTokensPerTurn);
17742
+ const projected = projectedProviderTurnsOf(merged, overallExecutedCeiling(merged, toolCeilingsOf(merged))) + finishRepairReserve;
17743
+ if (orchestratorEcho !== void 0) orchestratorEcho.synthesis = {
17744
+ projectedProviderTurns: projected,
17745
+ servedBy
17746
+ };
17747
+ const { adapterId, model } = parseModelRef(servedBy);
17748
+ shapes.push({
17749
+ label: "synthesis",
17750
+ provider: adapterId,
17751
+ model,
17752
+ inputFloor: synthesis.estInputTokens ?? 0,
17753
+ outputBound: outputBound ?? 0,
17754
+ turns: projected,
17755
+ count: 1
17756
+ });
17757
+ }
17758
+ }
17604
17759
  }
17605
17760
  const wave = [];
17606
17761
  let committed = 0;
@@ -17807,6 +17962,7 @@ function preflightEstimate(input) {
17807
17962
  if (typeof validator.validate !== "function") throw new ConfigError(`preflight finish validator '${validator.name}' has no validate function`);
17808
17963
  names.add(validator.name);
17809
17964
  }
17965
+ if (fv.repairTurnReserve !== void 0) requireNonNegativeInteger(fv.repairTurnReserve, "preflight finishValidation.repairTurnReserve");
17810
17966
  if (fv.contract !== void 0) {
17811
17967
  for (const contractValidator of fv.contract.validators) if (!names.has(contractValidator.name)) findings.push({
17812
17968
  severity: "error",
@@ -18744,7 +18900,8 @@ function createEngine(options) {
18744
18900
  const quotaRuntime = options.quota === void 0 ? void 0 : {
18745
18901
  limiter: options.quota.limiter,
18746
18902
  ...options.quota.tenant === void 0 ? {} : { tenant: options.quota.tenant },
18747
- onLimiterError: options.quota.onLimiterError ?? "deny"
18903
+ onLimiterError: options.quota.onLimiterError ?? "deny",
18904
+ ...options.quota.declaredRules === void 0 ? {} : { declaredRules: options.quota.declaredRules }
18748
18905
  };
18749
18906
  const knowledgeStore = options.stores?.modelKnowledge;
18750
18907
  const knowledge = knowledgeStore === void 0 ? void 0 : { current: () => knowledgeStore.current() };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rulvar/core",
3
- "version": "1.72.0",
3
+ "version": "1.74.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",