@rulvar/core 1.9.0 → 1.11.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
@@ -2643,8 +2643,16 @@ declare function countsAgainstLimit(kind: EscalationKind): boolean;
2643
2643
  */
2644
2644
  /** The committed no-progress detector N. */
2645
2645
  declare const DEFAULT_NO_PROGRESS_TURNS = 3;
2646
- /** The consumer-visible dedicated class marker (FR-424). */
2647
- type AbortClass = "no-progress";
2646
+ /**
2647
+ * The consumer-visible engine-decided abort classes (FR-424).
2648
+ * 'no-progress' is the detector below; 'output-truncated' is a
2649
+ * schema-less turn that ended at its output token allowance
2650
+ * (finish reason 'max-tokens') without visible output (v1.9.0
2651
+ * follow-up review). Both stamp memoizeOutcome on the terminal:
2652
+ * the work is paid, so every resume replays the abort instead of
2653
+ * re-paying the same bounded failure.
2654
+ */
2655
+ type AbortClass = "no-progress" | "output-truncated";
2648
2656
  /**
2649
2657
  * Counts consecutive progress-free turns. A turn with at least one tool
2650
2658
  * call (or, later, an artifact delta) resets the streak; a turn with
@@ -5096,6 +5104,7 @@ declare class ExternalRegistry {
5096
5104
  private readonly waiters;
5097
5105
  private readonly keysByScope;
5098
5106
  private activity;
5107
+ private closedFlag;
5099
5108
  private quiesceListener?;
5100
5109
  private quiesceScheduled;
5101
5110
  private readonly emitEvent?;
@@ -5118,6 +5127,22 @@ declare class ExternalRegistry {
5118
5127
  pending(): PendingExternal[];
5119
5128
  /** The synthesized resolveExternal key of an approval suspension. */
5120
5129
  static approvalKey(entryRef: number): string;
5130
+ /**
5131
+ * The resolveExternal key a journaled suspension answers to: externals
5132
+ * carry the workflow-chosen key in the payload; approvals and Flavor B
5133
+ * decisions synthesize `approval:<seq>`. Undefined for anything that
5134
+ * is not a suspended entry.
5135
+ */
5136
+ static suspensionKeyOf(entry: JournalEntry): string | undefined;
5137
+ /**
5138
+ * Settling the run closes this execution segment permanently: every
5139
+ * parked waiter is detached, so a resolution arriving after
5140
+ * handle.result settled appends durably through the fold and wakes
5141
+ * NOTHING; exactly one subsequent engine.resume owns the continuation.
5142
+ * Idempotent. (Suspension ownership rule; v1.10 deep E2E review.)
5143
+ */
5144
+ close(): void;
5145
+ get closed(): boolean;
5121
5146
  private scheduleQuiesceCheck;
5122
5147
  /**
5123
5148
  * ctx.awaitExternal: journal (or re-match) the suspended entry and park
@@ -5173,9 +5198,25 @@ declare class ExternalRegistry {
5173
5198
  /**
5174
5199
  * RunHandle.resolveExternal: the live path validates BEFORE append and
5175
5200
  * throws InvalidResolutionError without journaling; a winning attempt
5176
- * settles the waiting promise in place.
5201
+ * settles the waiting promise in place. Without an open waiter the
5202
+ * attempt goes through the journal fold instead: a repeated resolution
5203
+ * is the documented journaled no-op ('already_resolved'), and once the
5204
+ * segment settled the resolution appends durably WITHOUT waking the
5205
+ * closed body (exactly one engine.resume owns the continuation).
5177
5206
  */
5178
5207
  resolveExternal(key: string, value: Json): Promise<ResolutionOutcome>;
5208
+ /** The shared live-path payload validation (throws, journals nothing). */
5209
+ private validatePayload;
5210
+ /**
5211
+ * Resolution without a live waiter, over the journal fold. Three cases:
5212
+ * a key no suspension ever carried throws InvalidResolutionError; a key
5213
+ * whose suspensions are all closed submits through the arbiter and
5214
+ * returns the journaled no-op ('already_resolved' or
5215
+ * 'target_abandoned', durability.md contract); an OPEN suspension is
5216
+ * resolvable this way only once the segment settled (closed registry),
5217
+ * with the exact live-path validation and no wake.
5218
+ */
5219
+ private resolveDetached;
5179
5220
  }
5180
5221
  //#endregion
5181
5222
  //#region src/engine/ctx.d.ts
@@ -5333,6 +5374,15 @@ declare class AgentCallError extends Error implements AgentError {
5333
5374
  readonly entryRef?: number;
5334
5375
  constructor(message: string, result: AgentResult<unknown>, scope: string, entryRef?: number);
5335
5376
  }
5377
+ /**
5378
+ * Projects a settled AgentResult's error to its wire form, carrying the
5379
+ * engine-decided abort class in data. AgentError itself has no data
5380
+ * field, so without this every projection past the terminal entry (the
5381
+ * run-level outcome.error, thrown AgentCallError wires, dropped items)
5382
+ * would keep only the message text and lose the typed class (v1.9.0
5383
+ * follow-up review).
5384
+ */
5385
+ declare function agentResultWire(result: AgentResult<unknown>, fallbackMessage: string): WireError;
5336
5386
  /** Pipeline results plus the dropped evidence, returned by onItemError: 'collect'. */
5337
5387
  interface PipelineCollected<T> {
5338
5388
  results: T[];
@@ -5946,6 +5996,12 @@ declare class InMemoryTranscriptStore implements TranscriptStore {
5946
5996
  //#region src/stores/jsonl.d.ts
5947
5997
  declare class JsonlFileStore implements JournalStore {
5948
5998
  private readonly dir;
5999
+ /**
6000
+ * The stored tail seq per run, lazily initialized from the file on the
6001
+ * first append this instance performs (obligation A5). Per instance by
6002
+ * design: cross-process writers are the lease seam's job.
6003
+ */
6004
+ private readonly lastSeq;
5949
6005
  constructor(options: {
5950
6006
  dir: string;
5951
6007
  });
@@ -6333,4 +6389,4 @@ interface SandboxBridge {
6333
6389
  }
6334
6390
  declare function createSandboxBridge(ctx: Ctx<never>, options: SandboxBridgeOptions): SandboxBridge;
6335
6391
  //#endregion
6336
- export { AWAIT_SCHEMA, AbandonAttempt, AbandonFold, AbandonPayload, AbandonedSpendView, AbortClass, type AdaptiveEvents, AdmissionController, AdmissionDecision, AdmissionRejectedError, AdmissionStatsBefore, AdmitLineage, AdmitRejectReason, AdmitSpec, AdmitVerdict, AgentCallError, AgentError, type AgentEvents, AgentIdentityInput, AgentOpts, AgentProfile, AgentProfilePermissions, AgentResult, AgentResultMeta, AgentStatus, ApproachSignatureInputs, ApprovalDecision, ApprovalIdentityInput, Artifact, AttemptOutcomeClass, BUDGET_ABORT_REASON, BriefOpts, BudgetAccountView, BudgetDefaults, BudgetExhaustedError, BudgetExhaustionDiagnostics, BudgetHooks, BudgetReserve, type Bytes, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, CacheHint, CacheTtl, CanUseTool, CanonicalId, CanonicalIdentity, CanonicalLadderSpec, CanonicalModelSpec, ChatEvent, ChatRequest, CheckpointState, ChildIdentityInput, type ClaimClass, type ClaimOp, type ClaimStatus, ClaimValidationOptions, CollectOpts, CollectedTurn, CompactionConfig, CompiledPermissionChain, CompiledWorkflow, ConfigError, type CoreEvents, CostAttribution, CostAttributionFacts, CostReport, CreateEngineOptions, Ctx, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, DEFAULT_FLAT_RESERVE_USD, DEFAULT_MAX_CHILDREN_PER_NODE, DEFAULT_MAX_DEPTH, DEFAULT_MAX_OSCILLATIONS_PER_KEY, DEFAULT_MAX_PINNED_WORKTREES, DEFAULT_MAX_REVISIONS_PER_RUN, DEFAULT_MAX_TOTAL_SPAWNS, DEFAULT_MAX_TURNS, DEFAULT_MODEL_RETRY_ATTEMPTS, DEFAULT_NO_PROGRESS_TURNS, DEFAULT_PER_RUN_CONCURRENCY, DEFAULT_RETRY_POLICY, DEFAULT_STREAM_IDLE_TIMEOUT_MS, DebitResult, DeclaredLadder, DedupIndex, DedupNote, DerivedKey, DeriverRegistry, DispositionRule, DispositionTable, DonorCandidate, DonorRef, DroppedItem, EMIT_RESULT_TOOL, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EffectiveUsageLimits, Effort, Engine, EngineDefaults, EntryKind, EntryRef, EntryStatus, ErrorClass, ErrorCode, ErrorPolicy, EscalatedResult, EscalationDecision, EscalationDigest, EscalationKind, EscalationLimits, EscalationOptions, EscalationReport, EscalationRequest, EventBus, type EvidenceRef, ExtensionAppendInput, ExtensionDispatchSpec, ExternalIdentityInput, ExternalRegistry, ExtractNecessityInput, FINISH_SCHEMA, FINISH_TOOL_NAME, FailoverTarget, FailoverTrigger, FallbackField, FallbackTrigger, FileModelKnowledgeStore, FileModelKnowledgeStoreOptions, FileTranscriptStore, FinishInfo, Gate, GateAudit, type GateRecord, GitWorktreeProvider, GitWorktreeProviderOptions, GraftBoot, HashVersion, HookVerdict, INBOX_PROPOSAL_TTL_DAYS, IdentityInput, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, InvalidResolutionError, InvocationRole, type IsolationProvider, type IsolationSpec, Issue$1 as Issue, JournalCompatSubCode, JournalCompatibilityError, JournalEntry, JournalMatcher, JournalMissError, JournalOperation, JournalOrderViolation, JournalSerializationHook, type JournalStore, type Json, JsonSchema, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, type KbProposal, type KbProposalTrigger, KeyDeriver, KeyRing, KeyedLimiter, KnowledgeCasError, type KnowledgeSnapshot, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LadderSpec, type LeasableStore, type Lease, LeaseHeldError, Ledger, LineageCounters, LineageIndex, LineageRef, LineageRelation, LineageStats, LogicalTaskId, MASKED_SECRET, MAX_DEPTH_CEILING, MatchResult, McpConfig, MechanicalGateProfile, MechanicalGateVerdict, type ModelCaps, ModelChoice, type ModelClaim, ModelEpochInputs, type ModelKnowledgeHandle, type ModelKnowledgeStore, ModelListConstraint, ModelRef, ModelRetry, ModelSpec, Msg, NoProgressDetector, NodeId, NodeLinkValue, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OnEscalation, OperationDisposition, OrchestrateOptions, OrchestratorBudgetSpec, OrchestratorCapConfigError, OrchestratorExtension, OrchestratorExtensionIO, OrchestratorRuntime, Out, PARALLEL_AGENTS_SCHEMA, ParallelSiteCounter, Part, PendingExternal, PendingToolTurn, PermissionConfig, PermissionGate, PermissionHook, PermissionPreset, PermissionRule, PermissionVerdict, PhaseTarget, PipelineCollected, PipelineOpts, PlanInvariantError, PriceTable, PricedUsage, type Pricing, type PricingTier, type ProviderAdapter, QualityFloors, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_PROFILES, RandIdentityInput, RandPayload, RefEntryAppender, RefEntryClassification, RefusalInfo, ReplayDisposition, ReplayMode, ReplayPlanHashMismatch, Replayer, ResolutionArbiter, ResolutionAttempt, ResolutionBy, ResolutionFold, ResolutionLayer, ResolutionOutcome, ResolutionPayload, ResolvedInvocation, ResolvedToolset, ResumeHandle, ResumeOptions, ResumePreview, ResumeReport, RetryClass, RetryPolicy, ReuseConfig, RiskRuleValue, Role, RulvarError, RulvarErrorCode, RunAgentOptions, RunBudget, RunEventSink, type RunFilter, RunHandle, RunInternals, type RunMeta, RunOptions, RunOutcome, RunProfile, RunStatus, RuntimeEventSink, SPAWN_AGENT_SCHEMA, SandboxBridge, SandboxBridgeOptions, SandboxError, SandboxHostToWorker, SandboxMethod, SandboxWorkerToHost, SchemaPair, SchemaSpec, SchemaValidationResult, ScopeSegment, ScriptRejected, ScriptRunner, ScrubNote, Semaphore, SerializationHook, Settled, ShellPatternRules, ShellSegment, ShellVerdict, SinglePhaseAppend, SpanMinter, SpanRegistry, SpawnAdmissionValue, SpawnAgentParams, SpawnKey, SpawnLineage, SpawnLineageOpt, SpawnOrigin, SpawnRecord, Spend, Stage, type StandardJSONSchemaV1, type StandardSchemaV1, StepIdentityInput, StructuredOutputTier, SuspendedAppend, SuspensionState, TOOL_NAME_PATTERN, type TaskClass, TaskDigest, TaskSpec, TerminalPatch, TerminationAccount, TerminationAccountSnapshot, TerminationDeniedValue, TerminationDeniedWriter, TerminationInitValue, TerminationLimits, TerminationResource, ToolCallRequest, ToolChoice, type ToolContext, ToolContextSeed, ToolContract, type ToolDef, type ToolEvents, type ToolExecutor, ToolInit, type ToolRisk, ToolRuntime, type ToolSource, type ToolSourceSession, ToolsOption, TranscriptSerializationHook, type TranscriptStore, TriggerClass, TtlState, Usage, UsageLimits, UsageSlice, VerifiedRecommendation, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, WakeBudgetBlock, WakeDigest, WakeTrigger, WireError, Workflow, WorkflowCallOpts, type WorkflowEvent, type WorkflowEventBody, WorkflowRegistry, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, atCompactionThreshold, buildAbandonFold, buildAdapterRegistry, buildCostReport, buildDeriverRegistry, buildOrchestratorTools, buildTerminationInitValue, buildToolContext, canRideLoopTurn, canonicalIsolationTag, canonicalizeLadder, canonicalizeSchema, capIssues, capsHashOf, checkFloors, checkpointRefFor, childCoveragePrefix, claimExpired, claimExpiry, claimIssues, claimOpIssues, classifyAgentError, classifyAttemptOutcome, collectDeclaredLadders, compactMessages, compilePermissionChain, compilePermissionPreset, compileVerifiedLayer, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createSandboxBridge, currentOnlyKeyRing, decodeCheckpoint, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, executeWorkflow, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, foldTermination, formatRePrompt, formatScopePath, hashWorkflowBody, hashWorkflowSource, identityJcs, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lexShellCommand, liftRetainedParts, lineageWeightOf, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, mergeUsageLimits, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, parallelScope, parseModelRef, parseScopePath, phiInitialOf, pipelineScope, planNodeScope, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, readTerminationInit, registryKeyRing, remeasureQueue, replayDisposition, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, scanJournalCompatibility, schemaHash, schemaHashOfSpec, selectStructuredOutputTier, shouldCompact, spawnDepthOf, summarizeInstruction, summarizeOutput, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolContract, toolsetHash, ttlState, validateEditorialCommit, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateSchemaSpec, validateTerminationLimits, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
6392
+ export { AWAIT_SCHEMA, AbandonAttempt, AbandonFold, AbandonPayload, AbandonedSpendView, AbortClass, type AdaptiveEvents, AdmissionController, AdmissionDecision, AdmissionRejectedError, AdmissionStatsBefore, AdmitLineage, AdmitRejectReason, AdmitSpec, AdmitVerdict, AgentCallError, AgentError, type AgentEvents, AgentIdentityInput, AgentOpts, AgentProfile, AgentProfilePermissions, AgentResult, AgentResultMeta, AgentStatus, ApproachSignatureInputs, ApprovalDecision, ApprovalIdentityInput, Artifact, AttemptOutcomeClass, BUDGET_ABORT_REASON, BriefOpts, BudgetAccountView, BudgetDefaults, BudgetExhaustedError, BudgetExhaustionDiagnostics, BudgetHooks, BudgetReserve, type Bytes, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, CacheHint, CacheTtl, CanUseTool, CanonicalId, CanonicalIdentity, CanonicalLadderSpec, CanonicalModelSpec, ChatEvent, ChatRequest, CheckpointState, ChildIdentityInput, type ClaimClass, type ClaimOp, type ClaimStatus, ClaimValidationOptions, CollectOpts, CollectedTurn, CompactionConfig, CompiledPermissionChain, CompiledWorkflow, ConfigError, type CoreEvents, CostAttribution, CostAttributionFacts, CostReport, CreateEngineOptions, Ctx, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, DEFAULT_FLAT_RESERVE_USD, DEFAULT_MAX_CHILDREN_PER_NODE, DEFAULT_MAX_DEPTH, DEFAULT_MAX_OSCILLATIONS_PER_KEY, DEFAULT_MAX_PINNED_WORKTREES, DEFAULT_MAX_REVISIONS_PER_RUN, DEFAULT_MAX_TOTAL_SPAWNS, DEFAULT_MAX_TURNS, DEFAULT_MODEL_RETRY_ATTEMPTS, DEFAULT_NO_PROGRESS_TURNS, DEFAULT_PER_RUN_CONCURRENCY, DEFAULT_RETRY_POLICY, DEFAULT_STREAM_IDLE_TIMEOUT_MS, DebitResult, DeclaredLadder, DedupIndex, DedupNote, DerivedKey, DeriverRegistry, DispositionRule, DispositionTable, DonorCandidate, DonorRef, DroppedItem, EMIT_RESULT_TOOL, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EffectiveUsageLimits, Effort, Engine, EngineDefaults, EntryKind, EntryRef, EntryStatus, ErrorClass, ErrorCode, ErrorPolicy, EscalatedResult, EscalationDecision, EscalationDigest, EscalationKind, EscalationLimits, EscalationOptions, EscalationReport, EscalationRequest, EventBus, type EvidenceRef, ExtensionAppendInput, ExtensionDispatchSpec, ExternalIdentityInput, ExternalRegistry, ExtractNecessityInput, FINISH_SCHEMA, FINISH_TOOL_NAME, FailoverTarget, FailoverTrigger, FallbackField, FallbackTrigger, FileModelKnowledgeStore, FileModelKnowledgeStoreOptions, FileTranscriptStore, FinishInfo, Gate, GateAudit, type GateRecord, GitWorktreeProvider, GitWorktreeProviderOptions, GraftBoot, HashVersion, HookVerdict, INBOX_PROPOSAL_TTL_DAYS, IdentityInput, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, InvalidResolutionError, InvocationRole, type IsolationProvider, type IsolationSpec, Issue$1 as Issue, JournalCompatSubCode, JournalCompatibilityError, JournalEntry, JournalMatcher, JournalMissError, JournalOperation, JournalOrderViolation, JournalSerializationHook, type JournalStore, type Json, JsonSchema, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, type KbProposal, type KbProposalTrigger, KeyDeriver, KeyRing, KeyedLimiter, KnowledgeCasError, type KnowledgeSnapshot, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LadderSpec, type LeasableStore, type Lease, LeaseHeldError, Ledger, LineageCounters, LineageIndex, LineageRef, LineageRelation, LineageStats, LogicalTaskId, MASKED_SECRET, MAX_DEPTH_CEILING, MatchResult, McpConfig, MechanicalGateProfile, MechanicalGateVerdict, type ModelCaps, ModelChoice, type ModelClaim, ModelEpochInputs, type ModelKnowledgeHandle, type ModelKnowledgeStore, ModelListConstraint, ModelRef, ModelRetry, ModelSpec, Msg, NoProgressDetector, NodeId, NodeLinkValue, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OnEscalation, OperationDisposition, OrchestrateOptions, OrchestratorBudgetSpec, OrchestratorCapConfigError, OrchestratorExtension, OrchestratorExtensionIO, OrchestratorRuntime, Out, PARALLEL_AGENTS_SCHEMA, ParallelSiteCounter, Part, PendingExternal, PendingToolTurn, PermissionConfig, PermissionGate, PermissionHook, PermissionPreset, PermissionRule, PermissionVerdict, PhaseTarget, PipelineCollected, PipelineOpts, PlanInvariantError, PriceTable, PricedUsage, type Pricing, type PricingTier, type ProviderAdapter, QualityFloors, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_PROFILES, RandIdentityInput, RandPayload, RefEntryAppender, RefEntryClassification, RefusalInfo, ReplayDisposition, ReplayMode, ReplayPlanHashMismatch, Replayer, ResolutionArbiter, ResolutionAttempt, ResolutionBy, ResolutionFold, ResolutionLayer, ResolutionOutcome, ResolutionPayload, ResolvedInvocation, ResolvedToolset, ResumeHandle, ResumeOptions, ResumePreview, ResumeReport, RetryClass, RetryPolicy, ReuseConfig, RiskRuleValue, Role, RulvarError, RulvarErrorCode, RunAgentOptions, RunBudget, RunEventSink, type RunFilter, RunHandle, RunInternals, type RunMeta, RunOptions, RunOutcome, RunProfile, RunStatus, RuntimeEventSink, SPAWN_AGENT_SCHEMA, SandboxBridge, SandboxBridgeOptions, SandboxError, SandboxHostToWorker, SandboxMethod, SandboxWorkerToHost, SchemaPair, SchemaSpec, SchemaValidationResult, ScopeSegment, ScriptRejected, ScriptRunner, ScrubNote, Semaphore, SerializationHook, Settled, ShellPatternRules, ShellSegment, ShellVerdict, SinglePhaseAppend, SpanMinter, SpanRegistry, SpawnAdmissionValue, SpawnAgentParams, SpawnKey, SpawnLineage, SpawnLineageOpt, SpawnOrigin, SpawnRecord, Spend, Stage, type StandardJSONSchemaV1, type StandardSchemaV1, StepIdentityInput, StructuredOutputTier, SuspendedAppend, SuspensionState, TOOL_NAME_PATTERN, type TaskClass, TaskDigest, TaskSpec, TerminalPatch, TerminationAccount, TerminationAccountSnapshot, TerminationDeniedValue, TerminationDeniedWriter, TerminationInitValue, TerminationLimits, TerminationResource, ToolCallRequest, ToolChoice, type ToolContext, ToolContextSeed, ToolContract, type ToolDef, type ToolEvents, type ToolExecutor, ToolInit, type ToolRisk, ToolRuntime, type ToolSource, type ToolSourceSession, ToolsOption, TranscriptSerializationHook, type TranscriptStore, TriggerClass, TtlState, Usage, UsageLimits, UsageSlice, VerifiedRecommendation, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, WakeBudgetBlock, WakeDigest, WakeTrigger, WireError, Workflow, WorkflowCallOpts, type WorkflowEvent, type WorkflowEventBody, WorkflowRegistry, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentResultWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, atCompactionThreshold, buildAbandonFold, buildAdapterRegistry, buildCostReport, buildDeriverRegistry, buildOrchestratorTools, buildTerminationInitValue, buildToolContext, canRideLoopTurn, canonicalIsolationTag, canonicalizeLadder, canonicalizeSchema, capIssues, capsHashOf, checkFloors, checkpointRefFor, childCoveragePrefix, claimExpired, claimExpiry, claimIssues, claimOpIssues, classifyAgentError, classifyAttemptOutcome, collectDeclaredLadders, compactMessages, compilePermissionChain, compilePermissionPreset, compileVerifiedLayer, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createSandboxBridge, currentOnlyKeyRing, decodeCheckpoint, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, executeWorkflow, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, foldTermination, formatRePrompt, formatScopePath, hashWorkflowBody, hashWorkflowSource, identityJcs, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lexShellCommand, liftRetainedParts, lineageWeightOf, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, mergeUsageLimits, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, parallelScope, parseModelRef, parseScopePath, phiInitialOf, pipelineScope, planNodeScope, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, readTerminationInit, registryKeyRing, remeasureQueue, replayDisposition, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, scanJournalCompatibility, schemaHash, schemaHashOfSpec, selectStructuredOutputTier, shouldCompact, spawnDepthOf, summarizeInstruction, summarizeOutput, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolContract, toolsetHash, ttlState, validateEditorialCommit, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateSchemaSpec, validateTerminationLimits, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
package/dist/index.js CHANGED
@@ -5626,6 +5626,7 @@ var ExternalRegistry = class ExternalRegistry {
5626
5626
  waiters = /* @__PURE__ */ new Map();
5627
5627
  keysByScope = /* @__PURE__ */ new Set();
5628
5628
  activity = 0;
5629
+ closedFlag = false;
5629
5630
  quiesceListener;
5630
5631
  quiesceScheduled = false;
5631
5632
  emitEvent;
@@ -5697,6 +5698,34 @@ var ExternalRegistry = class ExternalRegistry {
5697
5698
  static approvalKey(entryRef) {
5698
5699
  return `approval:${entryRef}`;
5699
5700
  }
5701
+ /**
5702
+ * The resolveExternal key a journaled suspension answers to: externals
5703
+ * carry the workflow-chosen key in the payload; approvals and Flavor B
5704
+ * decisions synthesize `approval:<seq>`. Undefined for anything that
5705
+ * is not a suspended entry.
5706
+ */
5707
+ static suspensionKeyOf(entry) {
5708
+ if (entry.status !== "suspended") return;
5709
+ if (entry.kind === "external") {
5710
+ const key = entry.value?.key;
5711
+ return typeof key === "string" ? key : void 0;
5712
+ }
5713
+ if (entry.kind === "approval") return ExternalRegistry.approvalKey(entry.seq);
5714
+ }
5715
+ /**
5716
+ * Settling the run closes this execution segment permanently: every
5717
+ * parked waiter is detached, so a resolution arriving after
5718
+ * handle.result settled appends durably through the fold and wakes
5719
+ * NOTHING; exactly one subsequent engine.resume owns the continuation.
5720
+ * Idempotent. (Suspension ownership rule; v1.10 deep E2E review.)
5721
+ */
5722
+ close() {
5723
+ this.closedFlag = true;
5724
+ this.waiters.clear();
5725
+ }
5726
+ get closed() {
5727
+ return this.closedFlag;
5728
+ }
5700
5729
  scheduleQuiesceCheck() {
5701
5730
  if (this.quiesceScheduled) return;
5702
5731
  this.quiesceScheduled = true;
@@ -5885,7 +5914,7 @@ var ExternalRegistry = class ExternalRegistry {
5885
5914
  const waiter = this.waiters.get(entryRef);
5886
5915
  if (waiter !== void 0) {
5887
5916
  this.waiters.delete(entryRef);
5888
- waiter.resolve(attempt.value);
5917
+ if (!this.closedFlag) waiter.resolve(attempt.value);
5889
5918
  }
5890
5919
  }
5891
5920
  return outcome;
@@ -5893,37 +5922,76 @@ var ExternalRegistry = class ExternalRegistry {
5893
5922
  /**
5894
5923
  * RunHandle.resolveExternal: the live path validates BEFORE append and
5895
5924
  * throws InvalidResolutionError without journaling; a winning attempt
5896
- * settles the waiting promise in place.
5925
+ * settles the waiting promise in place. Without an open waiter the
5926
+ * attempt goes through the journal fold instead: a repeated resolution
5927
+ * is the documented journaled no-op ('already_resolved'), and once the
5928
+ * segment settled the resolution appends durably WITHOUT waking the
5929
+ * closed body (exactly one engine.resume owns the continuation).
5897
5930
  */
5898
5931
  async resolveExternal(key, value) {
5899
5932
  const waiter = [...this.waiters.values()].find((candidate) => candidate.key === key);
5900
- if (waiter === void 0) throw new InvalidResolutionError(`no open awaitExternal suspension with key '${key}' in this run`);
5901
- if (waiter.kind === "approval") {
5933
+ if (waiter === void 0) return this.resolveDetached(key, value);
5934
+ await this.validatePayload(waiter.kind, key, value, waiter.schemaSpec);
5935
+ const outcome = await this.replayer.resolveSuspended(waiter.entryRef, {
5936
+ by: "external",
5937
+ value
5938
+ });
5939
+ this.emitResolutionOutcome(waiter.entryRef, "external", outcome);
5940
+ if (outcome.applied) {
5941
+ this.waiters.delete(waiter.entryRef);
5942
+ if (!this.closedFlag) waiter.resolve(value);
5943
+ }
5944
+ return outcome;
5945
+ }
5946
+ /** The shared live-path payload validation (throws, journals nothing). */
5947
+ async validatePayload(kind, key, value, schemaSpec) {
5948
+ if (kind === "approval") {
5902
5949
  const decision = value?.decision;
5903
5950
  if (decision !== "allow" && decision !== "deny") throw new InvalidResolutionError(`approval '${key}' resolves with { decision: 'allow' | 'deny', reason? }`);
5904
5951
  }
5905
- if (waiter.kind === "decision") {
5906
- const kind = value?.kind;
5907
- if (kind !== "retry" && kind !== "decompose" && kind !== "cancel" && kind !== "accept") throw new InvalidResolutionError(`escalation '${key}' resolves with an EscalationDecision ({ kind: 'retry' | 'decompose' | 'cancel' | 'accept', ... })`);
5952
+ if (kind === "decision") {
5953
+ const decisionKind = value?.kind;
5954
+ if (decisionKind !== "retry" && decisionKind !== "decompose" && decisionKind !== "cancel" && decisionKind !== "accept") throw new InvalidResolutionError(`escalation '${key}' resolves with an EscalationDecision ({ kind: 'retry' | 'decompose' | 'cancel' | 'accept', ... })`);
5908
5955
  }
5909
- if (waiter.schemaSpec !== void 0) {
5910
- const validation = await validateSchemaSpec(waiter.schemaSpec, value);
5956
+ if (schemaSpec !== void 0) {
5957
+ const validation = await validateSchemaSpec(schemaSpec, value);
5911
5958
  if (!validation.valid) throw new InvalidResolutionError(`resolution for '${key}' does not validate against the pinned schema: ` + validation.issues.map((issue) => issue.message).join("; "), { data: { issues: validation.issues.map((issue) => issue.message) } });
5912
5959
  }
5913
- const outcome = await this.replayer.resolveSuspended(waiter.entryRef, {
5960
+ }
5961
+ /**
5962
+ * Resolution without a live waiter, over the journal fold. Three cases:
5963
+ * a key no suspension ever carried throws InvalidResolutionError; a key
5964
+ * whose suspensions are all closed submits through the arbiter and
5965
+ * returns the journaled no-op ('already_resolved' or
5966
+ * 'target_abandoned', durability.md contract); an OPEN suspension is
5967
+ * resolvable this way only once the segment settled (closed registry),
5968
+ * with the exact live-path validation and no wake.
5969
+ */
5970
+ async resolveDetached(key, value) {
5971
+ const candidates = this.replayer.snapshot().filter((entry) => ExternalRegistry.suspensionKeyOf(entry) === key);
5972
+ const open = candidates.find((entry) => this.replayer.suspensionState(entry.seq).state === "suspended");
5973
+ if (open === void 0 && candidates.length === 0) throw new InvalidResolutionError(`no open awaitExternal suspension with key '${key}' in this run`);
5974
+ if (open !== void 0 && !this.closedFlag) throw new InvalidResolutionError(`no open awaitExternal suspension with key '${key}' in this run`);
5975
+ const target = open ?? candidates[candidates.length - 1];
5976
+ await this.validatePayload(target.kind === "approval" ? target.deadlineAt === void 0 ? "approval" : "decision" : "external", key, value, target.value?.schema);
5977
+ const outcome = await this.replayer.resolveSuspended(target.seq, {
5914
5978
  by: "external",
5915
5979
  value
5916
5980
  });
5917
- this.emitResolutionOutcome(waiter.entryRef, "external", outcome);
5918
- if (outcome.applied) {
5919
- this.waiters.delete(waiter.entryRef);
5920
- waiter.resolve(value);
5921
- }
5981
+ this.emitResolutionOutcome(target.seq, "external", outcome);
5922
5982
  return outcome;
5923
5983
  }
5924
5984
  };
5925
5985
  //#endregion
5926
5986
  //#region src/stores/inmemory.ts
5987
+ /**
5988
+ * InMemoryStore (M1-T04): the default journal store. Process-local, so
5989
+ * nothing survives a process exit and cross-process resume is
5990
+ * impossible (same-process resume of a kept instance works); the store
5991
+ * warns loudly exactly once per instance unless constructed with
5992
+ * `quiet: true` (the deliberate choice of a test tier).
5993
+ * An in-memory TranscriptStore ships alongside for the same default.
5994
+ */
5927
5995
  function deepCopy(value) {
5928
5996
  return JSON.parse(JSON.stringify(value));
5929
5997
  }
@@ -5937,6 +6005,8 @@ var InMemoryStore = class {
5937
6005
  append(runId, e) {
5938
6006
  this.warnOnce();
5939
6007
  const entries = this.runs.get(runId) ?? [];
6008
+ const tail = entries[entries.length - 1];
6009
+ if (tail !== void 0 && Number.isFinite(e.seq) && Number.isFinite(tail.seq) && e.seq <= tail.seq) return Promise.reject(new JournalOrderViolation(`InMemoryStore: append of seq ${e.seq} to run '${runId}' is not after the stored tail seq ${tail.seq}; a concurrent writer raced this journal from a stale tail`));
5940
6010
  entries.push(deepCopy(e));
5941
6011
  this.runs.set(runId, entries);
5942
6012
  return Promise.resolve();
@@ -6023,6 +6093,12 @@ function safeName(runId) {
6023
6093
  }
6024
6094
  var JsonlFileStore = class {
6025
6095
  dir;
6096
+ /**
6097
+ * The stored tail seq per run, lazily initialized from the file on the
6098
+ * first append this instance performs (obligation A5). Per instance by
6099
+ * design: cross-process writers are the lease seam's job.
6100
+ */
6101
+ lastSeq = /* @__PURE__ */ new Map();
6026
6102
  constructor(options) {
6027
6103
  this.dir = options.dir;
6028
6104
  mkdirSync(this.dir, { recursive: true });
@@ -6034,7 +6110,16 @@ var JsonlFileStore = class {
6034
6110
  return join(this.dir, `${safeName(runId)}${META_SUFFIX}`);
6035
6111
  }
6036
6112
  async append(runId, e) {
6113
+ let tail = this.lastSeq.get(runId);
6114
+ if (tail === void 0) {
6115
+ const existing = await this.load(runId);
6116
+ const last = existing[existing.length - 1];
6117
+ tail = last !== void 0 && Number.isFinite(last.seq) ? last.seq : Number.NEGATIVE_INFINITY;
6118
+ this.lastSeq.set(runId, tail);
6119
+ }
6120
+ if (Number.isFinite(e.seq) && e.seq <= tail) throw new JournalOrderViolation(`JsonlFileStore: append of seq ${e.seq} to run '${runId}' is not after the stored tail seq ${tail}; a concurrent writer raced this journal from a stale tail`);
6037
6121
  appendFileSync(this.journalPath(runId), `${JSON.stringify(e)}\n`, "utf8");
6122
+ if (Number.isFinite(e.seq)) this.lastSeq.set(runId, e.seq);
6038
6123
  }
6039
6124
  async load(runId) {
6040
6125
  let raw;
@@ -6091,6 +6176,7 @@ var JsonlFileStore = class {
6091
6176
  async delete(runId) {
6092
6177
  rmSync(this.journalPath(runId), { force: true });
6093
6178
  rmSync(this.metaPath(runId), { force: true });
6179
+ this.lastSeq.delete(runId);
6094
6180
  }
6095
6181
  };
6096
6182
  const TRANSCRIPT_SUFFIX = ".bin";
@@ -7806,6 +7892,16 @@ function applyOutputBudget(req, target, budget) {
7806
7892
  return req;
7807
7893
  }
7808
7894
  /**
7895
+ * The output-truncation abort message (v1.9.0 follow-up review). The
7896
+ * constraint is named neutrally as the turn's output token allowance:
7897
+ * the effective request cap can come from limits.maxOutputTokensPerTurn,
7898
+ * the budget clamp above, or the adapter's own default, and the provider
7899
+ * can also cut at its model maximum with no request cap at all.
7900
+ */
7901
+ function outputTruncatedMessage(invocation) {
7902
+ return `the ${invocation} ended at its output token allowance (finish reason 'max-tokens') before producing visible output; raise limits.maxOutputTokensPerTurn, reduce the reasoning effort, or free budget for the turn (https://docs.rulvar.com/guide/agents#output-truncation)`;
7903
+ }
7904
+ /**
7809
7905
  * Builds the turn's canonical assistant message. Retained provider-raw
7810
7906
  * parts go at the HEAD: on both first-class providers the retained
7811
7907
  * blocks (thinking blocks, reasoning items) precede the turn's text and
@@ -8578,6 +8674,16 @@ async function runAgent(options) {
8578
8674
  continue loop;
8579
8675
  }
8580
8676
  if (options.schema === void 0) {
8677
+ if (options.finalize === void 0 && outcome.finish?.reason === "max-tokens" && outcome.turn.text.trim() === "") {
8678
+ status = "limit";
8679
+ abortClass = "output-truncated";
8680
+ agentError = {
8681
+ kind: "terminal",
8682
+ retryable: false
8683
+ };
8684
+ errorMessage = outputTruncatedMessage("turn");
8685
+ break;
8686
+ }
8581
8687
  output = outcome.turn.text;
8582
8688
  break;
8583
8689
  }
@@ -8718,6 +8824,14 @@ async function runAgent(options) {
8718
8824
  retryable: false
8719
8825
  };
8720
8826
  if (outcome.finish.reason === "refusal") errorMessage = `model refusal (${outcome.finish.refusal.provider})`;
8827
+ } else if (options.schema === void 0 && outcome.finish?.reason === "max-tokens" && outcome.turn.text.trim() === "") {
8828
+ status = "limit";
8829
+ abortClass = "output-truncated";
8830
+ agentError = {
8831
+ kind: "terminal",
8832
+ retryable: false
8833
+ };
8834
+ errorMessage = outputTruncatedMessage("finalize invocation");
8721
8835
  } else if (options.schema === void 0) output = outcome.turn.text;
8722
8836
  }
8723
8837
  }
@@ -9983,6 +10097,29 @@ var AgentCallError = class extends Error {
9983
10097
  if (entryRef !== void 0) this.entryRef = entryRef;
9984
10098
  }
9985
10099
  };
10100
+ /**
10101
+ * Projects a settled AgentResult's error to its wire form, carrying the
10102
+ * engine-decided abort class in data. AgentError itself has no data
10103
+ * field, so without this every projection past the terminal entry (the
10104
+ * run-level outcome.error, thrown AgentCallError wires, dropped items)
10105
+ * would keep only the message text and lose the typed class (v1.9.0
10106
+ * follow-up review).
10107
+ */
10108
+ function agentResultWire(result, fallbackMessage) {
10109
+ const wire = agentErrorToWire(result.error ?? {
10110
+ kind: "terminal",
10111
+ retryable: false
10112
+ }, result.errorMessage ?? fallbackMessage);
10113
+ if (result.abortClass === void 0) return wire;
10114
+ const data = typeof wire.data === "object" && wire.data !== null && !Array.isArray(wire.data) ? wire.data : {};
10115
+ return {
10116
+ ...wire,
10117
+ data: {
10118
+ ...data,
10119
+ abortClass: result.abortClass
10120
+ }
10121
+ };
10122
+ }
9986
10123
  /** The workflow-defaults layer a Workflow value contributes, or nothing. */
9987
10124
  function workflowLayerOf(wf) {
9988
10125
  const layer = {};
@@ -10349,7 +10486,10 @@ function createCtx(internals, rootWorkflow) {
10349
10486
  }
10350
10487
  if (terminal?.artifacts !== void 0) result.artifacts = terminal.artifacts;
10351
10488
  if (terminal?.status === "escalated" && terminal.escalation !== void 0) result.escalation = terminal.escalation;
10352
- if ((terminal?.error?.data)?.abortClass === "no-progress") result.abortClass = "no-progress";
10489
+ {
10490
+ const stamped = (terminal?.error?.data)?.abortClass;
10491
+ if (stamped !== void 0) result.abortClass = stamped;
10492
+ }
10353
10493
  let replayedToolResults = [];
10354
10494
  if (matched.kind === "replay" && terminal?.checkpointRef !== void 0) {
10355
10495
  const blob = await internals.transcripts.get(terminal.checkpointRef);
@@ -10424,10 +10564,7 @@ function createCtx(internals, rootWorkflow) {
10424
10564
  if (result.status === "ok") return result.output;
10425
10565
  if (result.status === "escalated") throw new AgentCallError(`agent escalated: ${result.escalation?.scopeDelta ?? ""}`, result, state.scope, terminal?.seq ?? matched.running.seq);
10426
10566
  const effectivePolicy = opts.onError ?? (internals.errorPolicy === "lenient" ? "null" : "throw");
10427
- const replayWire = agentErrorToWire(result.error ?? {
10428
- kind: "terminal",
10429
- retryable: false
10430
- }, result.errorMessage ?? `agent replayed with status ${result.status}`);
10567
+ const replayWire = agentResultWire(result, `agent replayed with status ${result.status}`);
10431
10568
  if (effectivePolicy === "null") {
10432
10569
  const droppedItem = {
10433
10570
  source: "agent-onerror-null",
@@ -10812,7 +10949,7 @@ function createCtx(internals, rootWorkflow) {
10812
10949
  if (result.error !== void 0) terminalPatch.error = agentErrorToWire(result.error, result.errorMessage ?? `agent terminated with status ${result.status}`);
10813
10950
  if (result.usageApprox === true) terminalPatch.usageApprox = true;
10814
10951
  if (result.artifacts !== void 0) terminalPatch.artifacts = result.artifacts;
10815
- if (result.abortClass === "no-progress") {
10952
+ if (result.abortClass !== void 0) {
10816
10953
  terminalPatch.memoizeOutcome = true;
10817
10954
  if (terminalPatch.error !== void 0) {
10818
10955
  const priorData = terminalPatch.error.data;
@@ -10821,7 +10958,7 @@ function createCtx(internals, rootWorkflow) {
10821
10958
  ...terminalPatch.error,
10822
10959
  data: {
10823
10960
  ...dataRecord,
10824
- abortClass: "no-progress"
10961
+ abortClass: result.abortClass
10825
10962
  }
10826
10963
  };
10827
10964
  }
@@ -10899,10 +11036,7 @@ function createCtx(internals, rootWorkflow) {
10899
11036
  if (result.status === "ok") return result.output;
10900
11037
  if (result.status === "escalated") throw new AgentCallError(`agent escalated: ${result.escalation?.scopeDelta ?? ""}`, result, state.scope, terminal.seq);
10901
11038
  const effectiveOnError = opts.onError ?? (internals.errorPolicy === "lenient" ? "null" : "throw");
10902
- const wire = agentErrorToWire(result.error ?? {
10903
- kind: "terminal",
10904
- retryable: false
10905
- }, result.errorMessage ?? `agent terminated with status ${result.status}`);
11039
+ const wire = agentResultWire(result, `agent terminated with status ${result.status}`);
10906
11040
  if (effectiveOnError === "null") {
10907
11041
  const droppedItem = {
10908
11042
  source: "agent-onerror-null",
@@ -11016,10 +11150,7 @@ function createCtx(internals, rootWorkflow) {
11016
11150
  value = await als.run(stageState, () => stages[stageIndex](value));
11017
11151
  } catch (thrown) {
11018
11152
  if (thrown instanceof BudgetExhaustedError || onItemError === "throw") throw thrown;
11019
- const wire = thrown instanceof AgentCallError ? agentErrorToWire(thrown.result.error ?? {
11020
- kind: "terminal",
11021
- retryable: false
11022
- }, thrown.message) : thrown instanceof RulvarError ? thrown.toWire() : {
11153
+ const wire = thrown instanceof AgentCallError ? agentResultWire(thrown.result, thrown.message) : thrown instanceof RulvarError ? thrown.toWire() : {
11023
11154
  code: "error",
11024
11155
  message: thrown instanceof Error ? thrown.message : String(thrown),
11025
11156
  retryable: false
@@ -12512,6 +12643,7 @@ function createEngine(options) {
12512
12643
  return priceUsdOf(pricing, usage);
12513
12644
  };
12514
12645
  const providerLimiter = new KeyedLimiter(options.concurrency?.perProvider);
12646
+ const activeSegments = /* @__PURE__ */ new Set();
12515
12647
  function run(wf, args, opts, resumeCtx) {
12516
12648
  if (wf.kind !== "workflow" && wf.kind !== "compiled-workflow") throw new ConfigError("engine.run accepts in-process Workflow values or compileScript CompiledWorkflow values");
12517
12649
  const compiled = wf.kind === "compiled-workflow" ? wf : void 0;
@@ -12656,6 +12788,8 @@ function createEngine(options) {
12656
12788
  workflowHash: compiled === void 0 ? hashWorkflowBody(wf) : hashWorkflowSource(compiled.source),
12657
12789
  ...compiled === void 0 ? {} : { workflowSourceRef: workflowSourceRef(runId) }
12658
12790
  });
12791
+ if (activeSegments.has(runId)) throw new ConfigError(`run '${runId}' already has a live execution segment in this engine; await its settled result before starting another one (exactly one segment owns a run; https://docs.rulvar.com/guide/durability#resolving-a-settled-run)`);
12792
+ activeSegments.add(runId);
12659
12793
  const result = (async () => {
12660
12794
  let status = "ok";
12661
12795
  let value;
@@ -12696,8 +12830,9 @@ function createEngine(options) {
12696
12830
  }))]);
12697
12831
  if (raced.kind === "suspended") {
12698
12832
  bodyPromise.catch(() => void 0);
12833
+ external.close();
12699
12834
  status = "suspended";
12700
- pending = raced.open;
12835
+ pending = raced.open.filter((item) => replayer.suspensionState(item.entryRef).state === "suspended");
12701
12836
  for (const item of pending) bus.emit({
12702
12837
  type: "external:waiting",
12703
12838
  key: item.key,
@@ -12729,10 +12864,7 @@ function createEngine(options) {
12729
12864
  };
12730
12865
  } else {
12731
12866
  status = "error";
12732
- wireError = thrown instanceof AgentCallError ? agentErrorToWire(thrown.result.error ?? {
12733
- kind: "terminal",
12734
- retryable: false
12735
- }, thrown.message) : thrown instanceof RulvarError ? thrown.toWire() : {
12867
+ wireError = thrown instanceof AgentCallError ? agentResultWire(thrown.result, thrown.message) : thrown instanceof RulvarError ? thrown.toWire() : {
12736
12868
  code: "error",
12737
12869
  message: thrown instanceof Error ? thrown.message : String(thrown),
12738
12870
  retryable: false
@@ -12740,6 +12872,7 @@ function createEngine(options) {
12740
12872
  }
12741
12873
  } finally {
12742
12874
  if (deadlineTimer !== void 0) clearTimeout(deadlineTimer);
12875
+ external.close();
12743
12876
  await replayer.flush().catch(() => void 0);
12744
12877
  }
12745
12878
  const ledger = replayer.ledger();
@@ -12765,7 +12898,9 @@ function createEngine(options) {
12765
12898
  });
12766
12899
  return outcome;
12767
12900
  })();
12768
- result.catch(() => void 0);
12901
+ result.catch(() => void 0).finally(() => {
12902
+ activeSegments.delete(runId);
12903
+ });
12769
12904
  return {
12770
12905
  runId,
12771
12906
  result,
@@ -13181,4 +13316,4 @@ function createSandboxBridge(ctx, options) {
13181
13316
  };
13182
13317
  }
13183
13318
  //#endregion
13184
- export { AWAIT_SCHEMA, AdmissionController, AdmissionRejectedError, AgentCallError, BUDGET_ABORT_REASON, BudgetExhaustedError, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, ConfigError, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, DEFAULT_FLAT_RESERVE_USD, DEFAULT_MAX_CHILDREN_PER_NODE, DEFAULT_MAX_DEPTH, DEFAULT_MAX_OSCILLATIONS_PER_KEY, DEFAULT_MAX_PINNED_WORKTREES, DEFAULT_MAX_REVISIONS_PER_RUN, DEFAULT_MAX_TOTAL_SPAWNS, DEFAULT_MAX_TURNS, DEFAULT_MODEL_RETRY_ATTEMPTS, DEFAULT_NO_PROGRESS_TURNS, DEFAULT_PER_RUN_CONCURRENCY, DEFAULT_RETRY_POLICY, DEFAULT_STREAM_IDLE_TIMEOUT_MS, DedupIndex, EMIT_RESULT_TOOL, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EventBus, ExternalRegistry, FINISH_SCHEMA, FINISH_TOOL_NAME, FileModelKnowledgeStore, FileTranscriptStore, GitWorktreeProvider, INBOX_PROPOSAL_TTL_DAYS, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, InvalidResolutionError, JournalCompatibilityError, JournalMatcher, JournalMissError, JournalOrderViolation, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, KeyedLimiter, KnowledgeCasError, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LeaseHeldError, LineageIndex, MASKED_SECRET, MAX_DEPTH_CEILING, ModelRetry, NoProgressDetector, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OrchestratorCapConfigError, PARALLEL_AGENTS_SCHEMA, ParallelSiteCounter, PlanInvariantError, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_PROFILES, ReplayPlanHashMismatch, Replayer, ResolutionArbiter, ResolutionFold, RulvarError, RunBudget, SPAWN_AGENT_SCHEMA, SandboxError, ScriptRejected, Semaphore, SpanRegistry, TOOL_NAME_PATTERN, TerminationAccount, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, atCompactionThreshold, buildAbandonFold, buildAdapterRegistry, buildCostReport, buildDeriverRegistry, buildOrchestratorTools, buildTerminationInitValue, buildToolContext, canRideLoopTurn, canonicalIsolationTag, canonicalizeLadder, canonicalizeSchema, capIssues, capsHashOf, checkFloors, checkpointRefFor, childCoveragePrefix, claimExpired, claimExpiry, claimIssues, claimOpIssues, classifyAgentError, classifyAttemptOutcome, collectDeclaredLadders, compactMessages, compilePermissionChain, compilePermissionPreset, compileVerifiedLayer, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createSandboxBridge, currentOnlyKeyRing, decodeCheckpoint, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, executeWorkflow, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, foldTermination, formatRePrompt, formatScopePath, hashWorkflowBody, hashWorkflowSource, identityJcs, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lexShellCommand, liftRetainedParts, lineageWeightOf, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, mergeUsageLimits, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, parallelScope, parseModelRef, parseScopePath, phiInitialOf, pipelineScope, planNodeScope, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, readTerminationInit, registryKeyRing, remeasureQueue, replayDisposition, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, scanJournalCompatibility, schemaHash, schemaHashOfSpec, selectStructuredOutputTier, shouldCompact, spawnDepthOf, summarizeInstruction, summarizeOutput, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolContract, toolsetHash, ttlState, validateEditorialCommit, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateSchemaSpec, validateTerminationLimits, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
13319
+ export { AWAIT_SCHEMA, AdmissionController, AdmissionRejectedError, AgentCallError, BUDGET_ABORT_REASON, BudgetExhaustedError, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, ConfigError, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, DEFAULT_FLAT_RESERVE_USD, DEFAULT_MAX_CHILDREN_PER_NODE, DEFAULT_MAX_DEPTH, DEFAULT_MAX_OSCILLATIONS_PER_KEY, DEFAULT_MAX_PINNED_WORKTREES, DEFAULT_MAX_REVISIONS_PER_RUN, DEFAULT_MAX_TOTAL_SPAWNS, DEFAULT_MAX_TURNS, DEFAULT_MODEL_RETRY_ATTEMPTS, DEFAULT_NO_PROGRESS_TURNS, DEFAULT_PER_RUN_CONCURRENCY, DEFAULT_RETRY_POLICY, DEFAULT_STREAM_IDLE_TIMEOUT_MS, DedupIndex, EMIT_RESULT_TOOL, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EventBus, ExternalRegistry, FINISH_SCHEMA, FINISH_TOOL_NAME, FileModelKnowledgeStore, FileTranscriptStore, GitWorktreeProvider, INBOX_PROPOSAL_TTL_DAYS, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, InvalidResolutionError, JournalCompatibilityError, JournalMatcher, JournalMissError, JournalOrderViolation, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, KeyedLimiter, KnowledgeCasError, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LeaseHeldError, LineageIndex, MASKED_SECRET, MAX_DEPTH_CEILING, ModelRetry, NoProgressDetector, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OrchestratorCapConfigError, PARALLEL_AGENTS_SCHEMA, ParallelSiteCounter, PlanInvariantError, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_PROFILES, ReplayPlanHashMismatch, Replayer, ResolutionArbiter, ResolutionFold, RulvarError, RunBudget, SPAWN_AGENT_SCHEMA, SandboxError, ScriptRejected, Semaphore, SpanRegistry, TOOL_NAME_PATTERN, TerminationAccount, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentResultWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, atCompactionThreshold, buildAbandonFold, buildAdapterRegistry, buildCostReport, buildDeriverRegistry, buildOrchestratorTools, buildTerminationInitValue, buildToolContext, canRideLoopTurn, canonicalIsolationTag, canonicalizeLadder, canonicalizeSchema, capIssues, capsHashOf, checkFloors, checkpointRefFor, childCoveragePrefix, claimExpired, claimExpiry, claimIssues, claimOpIssues, classifyAgentError, classifyAttemptOutcome, collectDeclaredLadders, compactMessages, compilePermissionChain, compilePermissionPreset, compileVerifiedLayer, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createSandboxBridge, currentOnlyKeyRing, decodeCheckpoint, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, executeWorkflow, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, foldTermination, formatRePrompt, formatScopePath, hashWorkflowBody, hashWorkflowSource, identityJcs, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lexShellCommand, liftRetainedParts, lineageWeightOf, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, mergeUsageLimits, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, parallelScope, parseModelRef, parseScopePath, phiInitialOf, pipelineScope, planNodeScope, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, readTerminationInit, registryKeyRing, remeasureQueue, replayDisposition, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, scanJournalCompatibility, schemaHash, schemaHashOfSpec, selectStructuredOutputTier, shouldCompact, spawnDepthOf, summarizeInstruction, summarizeOutput, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolContract, toolsetHash, ttlState, validateEditorialCommit, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateSchemaSpec, validateTerminationLimits, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rulvar/core",
3
- "version": "1.9.0",
3
+ "version": "1.11.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",