@rulvar/core 1.73.0 → 1.75.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
@@ -1531,7 +1531,17 @@ type ModelCaps = {
1531
1531
  supportsParallelTools: boolean; /** Canonical efforts this model accepts after mapping. */
1532
1532
  reasoningEfforts: Effort[];
1533
1533
  contextWindow: number;
1534
- maxOutputTokens: number; /** Adapter-reported fallback only; the versioned price table wins. */
1534
+ maxOutputTokens: number;
1535
+ /**
1536
+ * The smallest request output cap the provider accepts (the v1.74
1537
+ * experiment review, P0.1): OpenAI's Responses API rejects
1538
+ * max_output_tokens below 16, so a dispatch under this floor is a
1539
+ * guaranteed 400. The runtime never sends a request output cap below
1540
+ * it: a budget last gasp dispatches the floor instead of one token,
1541
+ * and a remainder that cannot buy the floor is refused typed before
1542
+ * the wire. Absent means one, the historical floor.
1543
+ */
1544
+ minOutputTokensPerTurn?: number; /** Adapter-reported fallback only; the versioned price table wins. */
1535
1545
  pricing?: Pricing;
1536
1546
  };
1537
1547
  interface ProviderAdapter {
@@ -3111,12 +3121,33 @@ interface EngineQuotaConfig {
3111
3121
  * knob. reconcile failures only ever warn.
3112
3122
  */
3113
3123
  onLimiterError?: "deny" | "allow";
3124
+ /**
3125
+ * The drift telemetry opt-in (the v1.71 experiment review, P0.5
3126
+ * resized): the SAME rule declaration `preflightEstimate` takes as
3127
+ * `quotaRules`, mirrored here so the engine can hold it against what
3128
+ * providers actually REPORT. When a live 429 carries
3129
+ * provider-normalized limits (the openai and anthropic adapters
3130
+ * parse the x-ratelimit headers into
3131
+ * `WireError.data.reportedLimits`) and a declared per-minute cap
3132
+ * EXCEEDS the reported one, the run journals a `quota_drift`
3133
+ * decision (provider, model, tenant, dimension, declared, reported;
3134
+ * one per invocation and dimension) and emits a warn log, because a
3135
+ * limiter configured above the provider's real ceiling
3136
+ * under-throttles and live denials follow: the experiment inflated
3137
+ * 12M TPM over a real 1M and paid seven live 429s with nothing
3138
+ * recording the mismatch. Purely observational: nothing clamps, the
3139
+ * limiter keeps enforcing the declaration (clamping is host policy).
3140
+ * Absent = byte identical journals and events.
3141
+ */
3142
+ declaredRules?: readonly QuotaRule[];
3114
3143
  }
3115
3144
  /** The resolved engine-side quota runtime threaded into every run. */
3116
3145
  interface EngineQuotaRuntime {
3117
3146
  limiter: QuotaLimiter;
3118
3147
  tenant?: string;
3119
3148
  onLimiterError: "deny" | "allow";
3149
+ /** The declared rule mirror for drift telemetry; see {@link EngineQuotaConfig}. */
3150
+ declaredRules?: readonly QuotaRule[];
3120
3151
  }
3121
3152
  /**
3122
3153
  * Validates createEngine's quota config as a typed ConfigError before
@@ -4136,6 +4167,16 @@ interface AgentResult<T> {
4136
4167
  */
4137
4168
  transportRetries?: number;
4138
4169
  /**
4170
+ * Provider-reported rate limits observed on this invocation's 429s
4171
+ * (the v1.71 experiment review, P0.5): one entry per (provider,
4172
+ * model), the latest observation winning, parsed by the adapters
4173
+ * into `WireError.data.reportedLimits`. Live telemetry only, exactly
4174
+ * like transportRetries: never journaled, absent on a replayed
4175
+ * result; the ctx layer holds it against `quota.declaredRules` and
4176
+ * journals the drift verdicts, which ARE durable.
4177
+ */
4178
+ rateLimitObservations?: RateLimitObservation[];
4179
+ /**
4139
4180
  * The exploration guard counters (RV-210): present whenever any of
4140
4181
  * the exploration limits (toolBudgetNotices, maxRepeatedToolSignature,
4141
4182
  * maxNoNewEvidenceCalls) was configured. Journaled inside the terminal
@@ -4157,6 +4198,24 @@ interface AgentResult<T> {
4157
4198
  */
4158
4199
  partial?: ProgressReport;
4159
4200
  }
4201
+ /** One 429's provider-normalized limits, per (provider, model). */
4202
+ interface RateLimitObservation {
4203
+ provider: string;
4204
+ model: string;
4205
+ /**
4206
+ * Per-minute limits the provider REPORTED in its rate-limit
4207
+ * headers, normalized by the adapter: openai fills
4208
+ * requestsPerMinute and tokensPerMinute; anthropic fills
4209
+ * requestsPerMinute plus the split inputTokensPerMinute and
4210
+ * outputTokensPerMinute.
4211
+ */
4212
+ reportedLimits: {
4213
+ requestsPerMinute?: number;
4214
+ tokensPerMinute?: number;
4215
+ inputTokensPerMinute?: number;
4216
+ outputTokensPerMinute?: number;
4217
+ };
4218
+ }
4160
4219
  type EscalatedResult<T> = AgentResult<T> & {
4161
4220
  status: "escalated";
4162
4221
  escalation: EscalationReport;
@@ -8655,6 +8714,17 @@ interface InvoiceRow {
8655
8714
  responseId?: string;
8656
8715
  usage: Usage;
8657
8716
  usageApprox?: boolean;
8717
+ /**
8718
+ * Present and true when this `unconfirmed` row recorded ZERO usage
8719
+ * on every counter (the v1.71 experiment review, P1.4): a failed
8720
+ * attempt whose usage this ledger never saw. The zeros mean
8721
+ * "nothing recorded", never "the provider metered nothing": the
8722
+ * provider may have billed prompt processing before the failure, so
8723
+ * a statement join must treat this row's usage as unknown, not as
8724
+ * zero. Derived at export time from the journaled record; rows with
8725
+ * any recorded usage, and every other verdict, never carry it.
8726
+ */
8727
+ usageUnknown?: true;
8658
8728
  /** This row priced at its own model's rate; absent when no price row covers it. */
8659
8729
  usd?: number;
8660
8730
  /**
@@ -8699,6 +8769,8 @@ interface InvoiceExport {
8699
8769
  }>;
8700
8770
  /** Rows whose reconciliation is not 'provider-id-present'. */
8701
8771
  reconciliationFailures: number;
8772
+ /** Rows carrying `usageUnknown`; present when at least one does. */
8773
+ usageUnknownRows?: number;
8702
8774
  /** Present and true when any contributing entry carried approximate usage. */
8703
8775
  usageApprox?: boolean;
8704
8776
  }
@@ -9496,4 +9568,4 @@ interface SandboxBridge {
9496
9568
  declare const SANDBOX_AGENT_OPT_KEYS: readonly string[];
9497
9569
  declare function createSandboxBridge(ctx: Ctx<never>, options: SandboxBridgeOptions): SandboxBridge;
9498
9570
  //#endregion
9499
- 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 };
9571
+ 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
@@ -10172,31 +10181,53 @@ function estimateInputTokens(messages) {
10172
10181
  return Math.ceil(chars / 4);
10173
10182
  }
10174
10183
  /**
10184
+ * The serving model's declared minimum request output cap, default one.
10185
+ * OpenAI's Responses API rejects max_output_tokens below 16, so a
10186
+ * below-floor dispatch is a guaranteed provider 400: the v1.74
10187
+ * experiment's terminal repair died exactly there (the review, P0.1).
10188
+ * Defensive lookup: a caps() throw must not fail turns that never
10189
+ * consulted caps at this point before.
10190
+ */
10191
+ function outputFloorOf(target) {
10192
+ try {
10193
+ const declared = target.adapter.caps(target.resolved.model).minOutputTokensPerTurn;
10194
+ return declared !== void 0 && Number.isInteger(declared) && declared > 1 ? declared : 1;
10195
+ } catch {
10196
+ return 1;
10197
+ }
10198
+ }
10199
+ /**
10175
10200
  * Layer 2b at the wire boundary: clamps the outgoing request's
10176
10201
  * maxOutputTokens to what the remaining budget affords from the serving
10177
- * model. The clamp uses the heuristic prompt estimate; the DENIAL does
10178
- * not: a turn is refused (BudgetExhaustedError, never dispatched) only
10179
- * when the remainder cannot buy even ONE output token at zero input,
10180
- * which is exact. Denying on the estimate would kill turns the budget
10181
- * still funds, including the DEF-7 forced finish paid from the released
10182
- * finalize reserve; when the estimate says the prompt alone spends the
10183
- * remainder, the turn dispatches with a one-token output floor and the
10184
- * exact layers (2 and 3) settle the difference. A no-op without a hook
10185
- * or when the hook reports no bound. The clamp touches only the wire
10186
- * request, exactly like limits.maxOutputTokensPerTurn above it; identity
10187
- * is computed at the ctx layer and never sees it.
10202
+ * model, and holds every dispatch at or above the serving model's
10203
+ * output floor. The clamp uses the heuristic prompt estimate; the
10204
+ * DENIAL does not: a turn is refused (BudgetExhaustedError, never
10205
+ * dispatched) only when the remainder cannot buy the floor at zero
10206
+ * input, which is exact. Denying on the estimate would kill turns the
10207
+ * budget still funds, including the DEF-7 forced finish paid from the
10208
+ * released finalize reserve; when the estimate says the prompt alone
10209
+ * spends the remainder, the turn dispatches AT the floor and the exact
10210
+ * layers (2 and 3) settle the difference. A configured per-turn cap
10211
+ * below the floor is a ConfigError before any wire call: the provider
10212
+ * would reject every dispatch, so failing typed beats paying for a
10213
+ * guaranteed 400. A no-op without a hook or when the hook reports no
10214
+ * bound. The clamp touches only the wire request, exactly like
10215
+ * limits.maxOutputTokensPerTurn above it; identity is computed at the
10216
+ * ctx layer and never sees it.
10188
10217
  */
10189
10218
  function applyOutputBudget(req, target, budget) {
10219
+ const floor = outputFloorOf(target);
10220
+ if (req.maxOutputTokens !== void 0 && req.maxOutputTokens < floor) throw new ConfigError(`the per-turn output cap ${String(req.maxOutputTokens)} is below the ${String(floor)} token output floor of ${target.resolved.ref}; the provider would reject every dispatch, so raise limits.maxOutputTokensPerTurn to at least the floor`);
10190
10221
  const hook = budget?.maxAffordableOutputTokens;
10191
10222
  if (hook === void 0) return req;
10192
10223
  const affordable = hook(target.resolved.ref, estimateInputTokens(req.messages));
10193
10224
  if (affordable === void 0) return req;
10194
- if (affordable < 1) {
10225
+ if (affordable < floor) {
10195
10226
  const zeroInputAffordable = hook(target.resolved.ref, 0);
10196
- if (zeroInputAffordable !== void 0 && zeroInputAffordable < 1) throw new BudgetExhaustedError(`the remaining budget cannot afford one output token from ${target.resolved.ref}; the turn was not dispatched`);
10227
+ if (zeroInputAffordable !== void 0 && zeroInputAffordable < floor) throw new BudgetExhaustedError(floor === 1 ? `the remaining budget cannot afford one output token from ${target.resolved.ref}; the turn was not dispatched` : `the remaining budget cannot afford the ${String(floor)} token output floor of ${target.resolved.ref}; the turn was not dispatched`);
10197
10228
  return {
10198
10229
  ...req,
10199
- maxOutputTokens: 1
10230
+ maxOutputTokens: floor
10200
10231
  };
10201
10232
  }
10202
10233
  if (req.maxOutputTokens === void 0 || affordable < req.maxOutputTokens) return {
@@ -10251,6 +10282,101 @@ function assistantMsg(turn, retained = []) {
10251
10282
  };
10252
10283
  }
10253
10284
  /**
10285
+ * The adapter parse-failure wrapper, recognized by exact shape: both
10286
+ * first-class wires deliver tool arguments their single strict
10287
+ * JSON.parse rejected as `{__unparsed: raw}` and nothing else.
10288
+ */
10289
+ function unparsedMarkerOf(args) {
10290
+ if (typeof args !== "object" || args === null || Array.isArray(args)) return;
10291
+ const keys = Object.keys(args);
10292
+ const raw = args.__unparsed;
10293
+ return keys.length === 1 && keys[0] === "__unparsed" && typeof raw === "string" ? raw : void 0;
10294
+ }
10295
+ /** JSON.parse to a plain object, or undefined; never throws. */
10296
+ function parsePlainObject(text) {
10297
+ try {
10298
+ const value = JSON.parse(text);
10299
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
10300
+ } catch {
10301
+ return;
10302
+ }
10303
+ }
10304
+ /**
10305
+ * One bounded deterministic normalization of a near-JSON arguments
10306
+ * string: strip a single markdown fence, cut at the end of the first
10307
+ * balanced top-level object (drops trailing prose), and escape raw
10308
+ * control characters inside string literals (models writing markdown
10309
+ * documents into arguments emit real newlines, which strict JSON
10310
+ * forbids). Truncated payloads stay unbalanced and still fail the
10311
+ * parse; nothing here can invent structure the model did not write.
10312
+ */
10313
+ function normalizeNearJson(raw) {
10314
+ let text = raw.trim();
10315
+ const fence = /^```[a-zA-Z]*[\t ]*\r?\n([\s\S]*?)\r?\n?```$/.exec(text);
10316
+ if (fence?.[1] !== void 0) text = fence[1].trim();
10317
+ const start = text.indexOf("{");
10318
+ if (start >= 0) {
10319
+ let depth = 0;
10320
+ let inString = false;
10321
+ let escaped = false;
10322
+ for (let index = start; index < text.length; index += 1) {
10323
+ const char = text[index];
10324
+ if (escaped) {
10325
+ escaped = false;
10326
+ continue;
10327
+ }
10328
+ if (char === "\\") {
10329
+ escaped = inString;
10330
+ continue;
10331
+ }
10332
+ if (char === "\"") {
10333
+ inString = !inString;
10334
+ continue;
10335
+ }
10336
+ if (inString) continue;
10337
+ if (char === "{") depth += 1;
10338
+ else if (char === "}") {
10339
+ depth -= 1;
10340
+ if (depth === 0) {
10341
+ text = text.slice(start, index + 1);
10342
+ break;
10343
+ }
10344
+ }
10345
+ }
10346
+ }
10347
+ let escapedText = "";
10348
+ let inString = false;
10349
+ let escaped = false;
10350
+ for (const char of text) {
10351
+ if (!escaped && char === "\"") inString = !inString;
10352
+ escaped = inString && !escaped && char === "\\";
10353
+ const code = char.codePointAt(0) ?? 0;
10354
+ if (inString && code < 32) escapedText += char === "\n" ? "\\n" : char === "\r" ? "\\r" : char === " " ? "\\t" : `\\u${code.toString(16).padStart(4, "0")}`;
10355
+ else escapedText += char;
10356
+ }
10357
+ return escapedText;
10358
+ }
10359
+ /**
10360
+ * The deterministic second chance (the v1.74 experiment review, P1.5):
10361
+ * a strict re-parse of the wrapped raw string, then one normalization
10362
+ * pass. The v1.74 experiment durably proved three complete coordination
10363
+ * drafts were recoverable this way and were thrown away instead. Only a
10364
+ * plain object counts; the recovered value still faces the tool schema
10365
+ * at the caller.
10366
+ */
10367
+ function recoverUnparsedArgs(raw) {
10368
+ const strict = parsePlainObject(raw);
10369
+ if (strict !== void 0) return {
10370
+ value: strict,
10371
+ pass: "strict"
10372
+ };
10373
+ const normalized = parsePlainObject(normalizeNearJson(raw));
10374
+ if (normalized !== void 0) return {
10375
+ value: normalized,
10376
+ pass: "normalized"
10377
+ };
10378
+ }
10379
+ /**
10254
10380
  * Executes one model-issued tool call to a tool-result part. Failures are
10255
10381
  * surfaced to the model as error tool results and never thrown past
10256
10382
  * policy: unknown names, argument-validation issues, ModelRetry (bounded
@@ -10279,7 +10405,22 @@ async function executeToolCall(options) {
10279
10405
  return part;
10280
10406
  };
10281
10407
  if (def === void 0) return finish({ error: `unknown tool '${call.name}'` }, "error");
10282
- const validation = await validateSchemaSpec(def.parameters, call.args);
10408
+ let validation = await validateSchemaSpec(def.parameters, call.args);
10409
+ if (!validation.valid) {
10410
+ const unparsedRaw = unparsedMarkerOf(call.args);
10411
+ const recovered = unparsedRaw === void 0 ? void 0 : recoverUnparsedArgs(unparsedRaw);
10412
+ if (recovered !== void 0) {
10413
+ const revalidation = await validateSchemaSpec(def.parameters, recovered.value);
10414
+ if (revalidation.valid) {
10415
+ validation = revalidation;
10416
+ options.events?.emit({
10417
+ type: "log",
10418
+ level: "warn",
10419
+ msg: `arguments for '${call.name}' arrived unparsed (${String(unparsedRaw?.length ?? 0)} chars) and were recovered by a ${recovered.pass} JSON pass; the recovered object passed the tool schema and the call executed`
10420
+ });
10421
+ }
10422
+ }
10423
+ }
10283
10424
  if (!validation.valid) return finish({
10284
10425
  error: `arguments for '${call.name}' failed validation`,
10285
10426
  issues: validation.issues.map((issue) => issue.message)
@@ -10340,6 +10481,7 @@ async function runAgent(options) {
10340
10481
  const providerCalls = [];
10341
10482
  let invocationCounter = 0;
10342
10483
  let transportRetries = 0;
10484
+ const rateLimitObservations = /* @__PURE__ */ new Map();
10343
10485
  const roleUsageSnapshot = (role) => {
10344
10486
  const snapshot = /* @__PURE__ */ new Map();
10345
10487
  for (const [key, slice] of usageByPhaseModel) if (slice.role === role) snapshot.set(key, slice.usage);
@@ -11017,6 +11159,12 @@ async function runAgent(options) {
11017
11159
  if (outcome.aborted !== void 0) record.aborted = outcome.aborted;
11018
11160
  else if (outcome.wireError !== void 0) record.errorCode = outcome.wireError.code;
11019
11161
  providerCalls.push(record);
11162
+ const limited = outcome.wireError?.data;
11163
+ if (limited?.kind === "rate-limit" && typeof limited.reportedLimits === "object" && limited.reportedLimits !== null) rateLimitObservations.set(`${target.adapter.id}:${target.resolved.model}`, {
11164
+ provider: target.adapter.id,
11165
+ model: target.resolved.model,
11166
+ reportedLimits: limited.reportedLimits
11167
+ });
11020
11168
  }
11021
11169
  tries += 1;
11022
11170
  const retryClass = outcome.aborted === "idle" ? "transport" : outcome.wireError === void 0 ? void 0 : retryClassOf(outcome.wireError);
@@ -11839,6 +11987,7 @@ async function runAgent(options) {
11839
11987
  if (limitPartial !== void 0) result.partial = limitPartial;
11840
11988
  if (usageApprox) result.usageApprox = true;
11841
11989
  if (transportRetries > 0) result.transportRetries = transportRetries;
11990
+ if (rateLimitObservations.size > 0) result.rateLimitObservations = [...rateLimitObservations.values()];
11842
11991
  return result;
11843
11992
  }
11844
11993
  //#endregion
@@ -13991,6 +14140,59 @@ function createCtx(internals, rootWorkflow) {
13991
14140
  exitActivity?.();
13992
14141
  }
13993
14142
  internals.budget.releaseReserve(reserve, budgetAccount);
14143
+ const declaredRules = internals.quota?.declaredRules;
14144
+ if (declaredRules !== void 0 && result.rateLimitObservations !== void 0) for (const observation of result.rateLimitObservations) {
14145
+ const probe = {
14146
+ provider: observation.provider,
14147
+ model: observation.model,
14148
+ ...internals.quota?.tenant === void 0 ? {} : { tenant: internals.quota.tenant },
14149
+ estimate: {
14150
+ requests: 1,
14151
+ inputTokens: 0
14152
+ }
14153
+ };
14154
+ const matching = declaredRules.filter((rule) => quotaRuleMatches(rule, probe));
14155
+ const declaredOf = (pick) => {
14156
+ const caps = matching.map(pick).filter((cap) => cap !== void 0);
14157
+ return caps.length === 0 ? void 0 : Math.min(...caps);
14158
+ };
14159
+ const reported = observation.reportedLimits;
14160
+ const reportedTokens = reported.tokensPerMinute ?? (reported.inputTokensPerMinute !== void 0 && reported.outputTokensPerMinute !== void 0 ? reported.inputTokensPerMinute + reported.outputTokensPerMinute : void 0);
14161
+ const dimensions = [{
14162
+ dimension: "requests",
14163
+ declared: declaredOf((rule) => rule.requestsPerMinute),
14164
+ observed: reported.requestsPerMinute
14165
+ }, {
14166
+ dimension: "tokens",
14167
+ declared: declaredOf((rule) => rule.tokensPerMinute),
14168
+ observed: reportedTokens
14169
+ }];
14170
+ for (const { dimension, declared, observed } of dimensions) {
14171
+ if (declared === void 0 || observed === void 0 || declared <= observed) continue;
14172
+ const key = `quota-drift:${dimension}:${observation.provider}:${observation.model}`;
14173
+ if (!internals.replayer.snapshot().some((entry) => entry.kind === "decision" && entry.scope === state.scope && entry.key === key)) await internals.replayer.appendSinglePhase({
14174
+ scope: state.scope,
14175
+ key,
14176
+ kind: "decision",
14177
+ status: "ok",
14178
+ spanId,
14179
+ value: {
14180
+ decisionType: "quota_drift",
14181
+ provider: observation.provider,
14182
+ model: observation.model,
14183
+ ...internals.quota?.tenant === void 0 ? {} : { tenant: internals.quota.tenant },
14184
+ dimension,
14185
+ declaredPerMinute: declared,
14186
+ reportedPerMinute: observed
14187
+ }
14188
+ });
14189
+ internals.events.emit({
14190
+ type: "log",
14191
+ level: "warn",
14192
+ 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')`
14193
+ }, spanId);
14194
+ }
14195
+ }
13994
14196
  const collectAndDisposeWorktree = async () => {
13995
14197
  if (acquired === void 0) return;
13996
14198
  try {
@@ -17494,6 +17696,12 @@ function preflightEstimate(input) {
17494
17696
  message: `spawn '${label}' sets maxOutputTokensPerTurn ${String(limits.maxOutputTokensPerTurn)} above the model's maxOutputTokens ${String(caps.maxOutputTokens)}: the model clamp wins`,
17495
17697
  spawn: label
17496
17698
  });
17699
+ if (caps?.minOutputTokensPerTurn !== void 0 && limits.maxOutputTokensPerTurn !== void 0 && limits.maxOutputTokensPerTurn < caps.minOutputTokensPerTurn) say({
17700
+ severity: "error",
17701
+ code: "output-cap-below-provider-minimum",
17702
+ message: `spawn '${label}' sets maxOutputTokensPerTurn ${String(limits.maxOutputTokensPerTurn)} below the ${String(caps.minOutputTokensPerTurn)} token output floor of '${servedBy ?? ""}': every dispatch would be refused typed before the wire; raise the cap to at least the floor`,
17703
+ spawn: label
17704
+ });
17497
17705
  const turnFloorUsd = pricing === void 0 || outputBound === void 0 ? void 0 : priceUsdOf(pricing, {
17498
17706
  inputTokens: spec.estInputTokens ?? 0,
17499
17707
  outputTokens: outputBound,
@@ -17622,6 +17830,12 @@ function preflightEstimate(input) {
17622
17830
  const pricing = pricingOf(servedBy);
17623
17831
  const orchLimits = mergeUsageLimits(input.orchestrator.limits, void 0, defaults.limits);
17624
17832
  const outputBound = caps === void 0 ? orchLimits.maxOutputTokensPerTurn : orchLimits.maxOutputTokensPerTurn === void 0 ? caps.maxOutputTokens : Math.min(caps.maxOutputTokens, orchLimits.maxOutputTokensPerTurn);
17833
+ if (caps?.minOutputTokensPerTurn !== void 0 && orchLimits.maxOutputTokensPerTurn !== void 0 && orchLimits.maxOutputTokensPerTurn < caps.minOutputTokensPerTurn) say({
17834
+ severity: "error",
17835
+ code: "output-cap-below-provider-minimum",
17836
+ message: `the orchestrator sets maxOutputTokensPerTurn ${String(orchLimits.maxOutputTokensPerTurn)} below the ${String(caps.minOutputTokensPerTurn)} token output floor of '${servedBy}': every dispatch would be refused typed before the wire; raise the cap to at least the floor`,
17837
+ spawn: "orchestrator"
17838
+ });
17625
17839
  const { adapterId, model } = parseModelRef(servedBy);
17626
17840
  const unit = {
17627
17841
  label: "orchestrator",
@@ -17669,6 +17883,12 @@ function preflightEstimate(input) {
17669
17883
  const caps = capsOf(servedBy);
17670
17884
  const merged = mergeUsageLimits(synthesis.limits ?? { maxTurns: 4 }, void 0, defaults.limits);
17671
17885
  const outputBound = caps === void 0 ? merged.maxOutputTokensPerTurn : merged.maxOutputTokensPerTurn === void 0 ? caps.maxOutputTokens : Math.min(caps.maxOutputTokens, merged.maxOutputTokensPerTurn);
17886
+ if (caps?.minOutputTokensPerTurn !== void 0 && merged.maxOutputTokensPerTurn !== void 0 && merged.maxOutputTokensPerTurn < caps.minOutputTokensPerTurn) say({
17887
+ severity: "error",
17888
+ code: "output-cap-below-provider-minimum",
17889
+ message: `the synthesis invocation sets maxOutputTokensPerTurn ${String(merged.maxOutputTokensPerTurn)} below the ${String(caps.minOutputTokensPerTurn)} token output floor of '${servedBy}': every dispatch would be refused typed before the wire; raise the cap to at least the floor`,
17890
+ spawn: "synthesis"
17891
+ });
17672
17892
  const projected = projectedProviderTurnsOf(merged, overallExecutedCeiling(merged, toolCeilingsOf(merged))) + finishRepairReserve;
17673
17893
  if (orchestratorEcho !== void 0) orchestratorEcho.synthesis = {
17674
17894
  projectedProviderTurns: projected,
@@ -18830,7 +19050,8 @@ function createEngine(options) {
18830
19050
  const quotaRuntime = options.quota === void 0 ? void 0 : {
18831
19051
  limiter: options.quota.limiter,
18832
19052
  ...options.quota.tenant === void 0 ? {} : { tenant: options.quota.tenant },
18833
- onLimiterError: options.quota.onLimiterError ?? "deny"
19053
+ onLimiterError: options.quota.onLimiterError ?? "deny",
19054
+ ...options.quota.declaredRules === void 0 ? {} : { declaredRules: options.quota.declaredRules }
18834
19055
  };
18835
19056
  const knowledgeStore = options.stores?.modelKnowledge;
18836
19057
  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.73.0",
3
+ "version": "1.75.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",