@rulvar/core 1.223.0 → 1.224.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
@@ -7623,8 +7623,10 @@ interface RunOptions {
7623
7623
  * used to be per-invocation and unrecorded, so a resumed segment
7624
7624
  * silently ran without the bound the original invocation declared
7625
7625
  * (the seventeenth comparison benchmark's top FinOps gap). A run
7626
- * started without the cap stays uncapped for its whole life, and
7627
- * ResumeOptions deliberately has no field to override it.
7626
+ * started without the cap stays uncapped for its whole life unless
7627
+ * a host changes the posture through the explicit, validated,
7628
+ * journaled ResumeOptions.run override (RV2208); nothing changes it
7629
+ * silently.
7628
7630
  */
7629
7631
  maxInFlightExposureUsd?: number;
7630
7632
  /**
@@ -7637,7 +7639,9 @@ interface RunOptions {
7637
7639
  * and `allowUnpriced` (exact model refs the host KNOWS are free,
7638
7640
  * the explicit exception). Recorded in RunMeta at genesis and
7639
7641
  * restored on every resume, the exposure cap's rule (RV1504): a
7640
- * FinOps posture a resumed segment silently drops is not a posture.
7642
+ * FinOps posture a resumed segment silently drops is not a posture
7643
+ * (and unlike the two ceilings, ResumeOptions.run has no field for
7644
+ * this gate: pricing hygiene is not a per-segment decision).
7641
7645
  * Absent by default: dispatch behavior stays byte identical, and an
7642
7646
  * unpriced model keeps debiting nothing, the documented ceiling
7643
7647
  * hole this mode exists to close.
@@ -7711,6 +7715,27 @@ interface ResumeOptions {
7711
7715
  * meta/blob surfaces remain advisory (the fenced run state RFC).
7712
7716
  */
7713
7717
  lease?: Lease;
7718
+ /**
7719
+ * Ceiling overrides for the resumed segment and the run's remaining
7720
+ * life (RV2208). The RV1504 rule stands: the RunMeta-recorded
7721
+ * posture is what a bare resume restores; this field is the ONE
7722
+ * explicit way to change that posture after genesis. Each supplied
7723
+ * value is validated exactly like its RunOptions counterpart,
7724
+ * applied to this segment's budget, written back by the segment's
7725
+ * first meta write (a LATER bare resume restores the overridden
7726
+ * posture, not the genesis one), and journaled as a
7727
+ * `run_budget_override` decision naming the recorded and applied
7728
+ * values and the settled spend it was judged against. A `budgetUsd`
7729
+ * below the journal's settled spend refuses typed before ownership,
7730
+ * meta, or any append: such a ceiling would exhaust the segment
7731
+ * before its first turn and read like a fresh money death. Absent
7732
+ * fields keep the recorded values; an absent object keeps the
7733
+ * historical behavior byte for byte.
7734
+ */
7735
+ run?: {
7736
+ budgetUsd?: number;
7737
+ maxInFlightExposureUsd?: number;
7738
+ };
7714
7739
  }
7715
7740
  interface ResumeHandle<R> extends RunHandle<R> {
7716
7741
  /** Resolves at settle with the replay accounting. */
@@ -7726,7 +7751,9 @@ interface Engine {
7726
7751
  * A compiled run resumes WITHOUT wf: the engine rehydrates the
7727
7752
  * persisted source pinned by workflowHash; supplying a compiled wf
7728
7753
  * whose source hash differs from the recorded one is a typed
7729
- * ConfigError (M6-T02).
7754
+ * ConfigError (M6-T02). ResumeOptions.run (RV2208) overrides the
7755
+ * recorded budget ceilings for the run's remaining life, with a
7756
+ * journaled decision and a typed floor at the settled spend.
7730
7757
  */
7731
7758
  resume<A, R>(runId: string, wf?: Workflow<A, R> | CompiledWorkflow, options?: ResumeOptions): ResumeHandle<R>;
7732
7759
  /**
package/dist/index.js CHANGED
@@ -26541,8 +26541,8 @@ function createEngine(options) {
26541
26541
  });
26542
26542
  const rootSpanId = spans.mint();
26543
26543
  let budgetSeed;
26544
- const ceilingUsd = opts?.budgetUsd ?? resumeCtx?.budgetUsd;
26545
- const exposureCapUsd = opts?.maxInFlightExposureUsd ?? resumeCtx?.maxInFlightExposureUsd;
26544
+ const ceilingUsd = opts?.budgetUsd ?? resumeCtx?.budgetOverride?.budgetUsd ?? resumeCtx?.budgetUsd;
26545
+ const exposureCapUsd = opts?.maxInFlightExposureUsd ?? resumeCtx?.budgetOverride?.maxInFlightExposureUsd ?? resumeCtx?.maxInFlightExposureUsd;
26546
26546
  const strictPricing = opts?.strictPricing === void 0 ? resumeCtx?.strictPricing : opts.strictPricing === true ? {} : opts.strictPricing === false ? void 0 : {
26547
26547
  ...opts.strictPricing.maxRatesAgeDays === void 0 ? {} : { maxRatesAgeDays: opts.strictPricing.maxRatesAgeDays },
26548
26548
  ...opts.strictPricing.allowUnpriced === void 0 ? {} : { allowUnpriced: [...opts.strictPricing.allowUnpriced] }
@@ -26590,6 +26590,8 @@ function createEngine(options) {
26590
26590
  agentsSpawned: prior.agentsSpawned,
26591
26591
  accounts: accountSpendFromJournal(replayer.snapshot(), priorPriceUsd)
26592
26592
  };
26593
+ const overrideCeilingUsd = resumeCtx.budgetOverride?.budgetUsd;
26594
+ if (overrideCeilingUsd !== void 0 && budgetSeed.usd > overrideCeilingUsd) throw new ConfigError(`ResumeOptions.run.budgetUsd ${String(overrideCeilingUsd)} is below the ${budgetSeed.usd.toFixed(4)} USD the journal already records as settled spend; a ceiling below spent exhausts the resumed segment before its first turn. Pass a value at or above the recorded spend, or resume without the override`);
26593
26595
  }
26594
26596
  const controller = new AbortController();
26595
26597
  let cancelReason;
@@ -26785,6 +26787,34 @@ function createEngine(options) {
26785
26787
  let wireError;
26786
26788
  let pending = [];
26787
26789
  if (compiled !== void 0 && resumeCtx?.strict !== true) await transcripts.put(workflowSourceRef(runId), new TextEncoder().encode(compiled.source), segmentLease.current);
26790
+ if (resumeCtx?.budgetOverride !== void 0 && resumeCtx.strict !== true) {
26791
+ const override = resumeCtx.budgetOverride;
26792
+ await replayer.appendSinglePhase({
26793
+ scope: "",
26794
+ key: deriverV2.deriveKey({
26795
+ kind: "run-budget-override",
26796
+ segment: segmentsBefore + 1
26797
+ }),
26798
+ kind: "decision",
26799
+ status: "ok",
26800
+ spanId: rootSpanId,
26801
+ site: "run-budget-override",
26802
+ value: {
26803
+ decisionType: "run_budget_override",
26804
+ source: "resume-options",
26805
+ segment: segmentsBefore + 1,
26806
+ ...override.budgetUsd === void 0 ? {} : { budgetUsd: {
26807
+ recorded: resumeCtx.budgetUsd ?? null,
26808
+ applied: override.budgetUsd
26809
+ } },
26810
+ ...override.maxInFlightExposureUsd === void 0 ? {} : { maxInFlightExposureUsd: {
26811
+ recorded: resumeCtx.maxInFlightExposureUsd ?? null,
26812
+ applied: override.maxInFlightExposureUsd
26813
+ } },
26814
+ ...budgetSeed === void 0 ? {} : { settledSpendUsd: budgetSeed.usd }
26815
+ }
26816
+ });
26817
+ }
26788
26818
  await putMeta("running");
26789
26819
  bus.emit({
26790
26820
  type: "run:start",
@@ -27029,6 +27059,8 @@ function createEngine(options) {
27029
27059
  previewResolve = resolve;
27030
27060
  });
27031
27061
  const handlePromise = (async () => {
27062
+ if (resumeOptions?.run?.budgetUsd !== void 0) requireNonNegativeNumber(resumeOptions.run.budgetUsd, "ResumeOptions.run.budgetUsd");
27063
+ if (resumeOptions?.run?.maxInFlightExposureUsd !== void 0) requireNonNegativeNumber(resumeOptions.run.maxInFlightExposureUsd, "ResumeOptions.run.maxInFlightExposureUsd");
27032
27064
  const meta = await readRunMeta(journal, runId);
27033
27065
  let supplied = wf;
27034
27066
  if (supplied === void 0 && meta?.workflowSourceRef === void 0) {
@@ -27070,12 +27102,18 @@ function createEngine(options) {
27070
27102
  code: "RULVAR_LEGACY_CACHE_SEMANTICS",
27071
27103
  type: "RulvarWarning"
27072
27104
  });
27105
+ const runOverride = resumeOptions?.run;
27106
+ const budgetOverride = runOverride === void 0 || runOverride.budgetUsd === void 0 && runOverride.maxInFlightExposureUsd === void 0 ? void 0 : {
27107
+ ...runOverride.budgetUsd === void 0 ? {} : { budgetUsd: runOverride.budgetUsd },
27108
+ ...runOverride.maxInFlightExposureUsd === void 0 ? {} : { maxInFlightExposureUsd: runOverride.maxInFlightExposureUsd }
27109
+ };
27073
27110
  return run(bound, resumeOptions?.args, void 0, {
27074
27111
  runId,
27075
27112
  priorEntries,
27076
27113
  strict: resumeOptions?.dryRun ?? false,
27077
27114
  invalidate: resumeOptions?.invalidate ?? [],
27078
27115
  ...resumeOptions?.lease === void 0 ? {} : { lease: resumeOptions.lease },
27116
+ ...budgetOverride === void 0 ? {} : { budgetOverride },
27079
27117
  ...typeof meta?.budgetUsd === "number" ? { budgetUsd: meta.budgetUsd } : {},
27080
27118
  ...typeof meta?.maxInFlightExposureUsd === "number" ? { maxInFlightExposureUsd: meta.maxInFlightExposureUsd } : {},
27081
27119
  ...typeof meta?.strictPricing === "object" && meta.strictPricing !== null ? { strictPricing: meta.strictPricing } : {},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rulvar/core",
3
- "version": "1.223.0",
3
+ "version": "1.224.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",