@rulvar/core 1.98.0 → 1.99.1

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
@@ -2762,7 +2762,7 @@ interface RefEntryAppender {
2762
2762
  /**
2763
2763
  * Per-run, per-target FIFO serializer of resolution/abandon attempts:
2764
2764
  * classification against the in-memory fold ->
2765
- * durable append -> settle exactly once; losing attempts are ALSO
2765
+ * durable append -> a single settle; losing attempts are ALSO
2766
2766
  * appended and become journaled noops by fold classification. Winner
2767
2767
  * effects run strictly after the critical section (the caller's job).
2768
2768
  * Cross-process protection remains the LeasableStore fencing epoch.
@@ -2959,7 +2959,7 @@ declare class Replayer {
2959
2959
  /** Suspended kinds (external, approval): appended once, closed by ref-entries (M2). */
2960
2960
  appendSuspended(input: SuspendedAppend): Promise<JournalEntry>;
2961
2961
  /**
2962
- * The budget ledger fold: usage sums over terminal entries exactly once; agentsSpawned
2962
+ * The budget ledger fold: usage sums over terminal entries once, never twice; agentsSpawned
2963
2963
  * counts agent dispatches.
2964
2964
  */
2965
2965
  ledger(): Ledger;
@@ -4440,6 +4440,17 @@ interface AgentResult<T> {
4440
4440
  * recoveries; absent when zero.
4441
4441
  */
4442
4442
  schemaRecoveredTerminalExchanges?: number;
4443
+ /**
4444
+ * The evidence floor refusal detail (RV507): present ONLY when an
4445
+ * enforced contract refused an otherwise-ok settle. The ctx layer
4446
+ * folds it into the journaled terminal error data and memoizes the
4447
+ * outcome (the refusal is deterministic from the paid transcript, so
4448
+ * a rerun would only re-pay the same bounded failure).
4449
+ */
4450
+ evidenceFloor?: {
4451
+ recordedEntries: number;
4452
+ minEntries: number;
4453
+ };
4443
4454
  }
4444
4455
  /** One 429's provider-normalized limits, per (provider, model). */
4445
4456
  interface RateLimitObservation {
@@ -4667,6 +4678,20 @@ interface RunAgentOptions<S extends SchemaSpec = JsonSchema> {
4667
4678
  save(state: CheckpointState): Promise<void>;
4668
4679
  };
4669
4680
  limits: EffectiveUsageLimits;
4681
+ /**
4682
+ * The resolved evidence contract of the invocation (RV507): under
4683
+ * enforce 'refuse' an ok settle whose message window carries fewer
4684
+ * successful `record_evidence` executions (result `recorded: true`)
4685
+ * than `minEntries` is refused as a typed 'terminal' error carrying
4686
+ * the machine-readable counter and threshold. Window-derived exactly
4687
+ * like the terminal partial, so live and resumed segments count the
4688
+ * same total. Absent, and under 'warn', the loop is byte-identical to
4689
+ * before.
4690
+ */
4691
+ evidenceContract?: {
4692
+ minEntries: number;
4693
+ enforce?: "warn" | "refuse";
4694
+ };
4670
4695
  /** Emits agent:stream deltas when true (telemetry only). */
4671
4696
  stream?: boolean;
4672
4697
  /** Host or sibling cancellation. */
@@ -6672,7 +6697,7 @@ declare function stripFencedBlocks(text: string): string;
6672
6697
  * heading nor trip exclusivity. Heading lines compare trimmed, whole
6673
6698
  * line. With `ordered` (default true) the declared headings must
6674
6699
  * appear in declaration order; with `exclusive` (default true) each
6675
- * declared heading must appear exactly once and no undeclared heading
6700
+ * declared heading must appear once, unrepeated, and no undeclared heading
6676
6701
  * of the governed level may exist (other levels stay free). Default
6677
6702
  * name 'heading-structure'.
6678
6703
  */
@@ -6736,7 +6761,10 @@ declare const DEFAULT_EVIDENCE_MIN_SHARE = .95;
6736
6761
  * {@link DEFAULT_EVIDENCE_MIN_SHARE}, the plan's 95 percent gate,
6737
6762
  * compared as a ceiling on the required count so an exact boundary like
6738
6763
  * 19 of 20 passes) must appear literally in the result text. Zero child
6739
- * citations pass vacuously. With `requireKnown: true` the contract also
6764
+ * citations pass vacuously UNLESS `requireNonEmptyPool: true` (RV507):
6765
+ * for an evidence-critical run the empty pool IS the failure, so that
6766
+ * mode refuses it with an `empty child citation pool` reason instead of
6767
+ * the vacuous pass. With `requireKnown: true` the contract also
6740
6768
  * runs in reverse: every citation in the RESULT must appear in some
6741
6769
  * child's output, so a fabricated but pattern valid citation is
6742
6770
  * rejected instead of silently counting as evidence. Rejection reasons
@@ -6750,6 +6778,7 @@ declare function evidencePreservedValidator(options?: {
6750
6778
  flags?: string;
6751
6779
  minShare?: number;
6752
6780
  requireKnown?: boolean;
6781
+ requireNonEmptyPool?: boolean;
6753
6782
  name?: string;
6754
6783
  }): FinishValidator;
6755
6784
  /**
@@ -7500,6 +7529,19 @@ interface OrchestrateAcceptance {
7500
7529
  */
7501
7530
  acceptPartialChildren?: boolean;
7502
7531
  /**
7532
+ * The spawned-roster floor (RV507): finish is rejected when FEWER
7533
+ * than this many children were spawned, under BOTH child policies.
7534
+ * 'all-ok' alone treats zero spawned children as vacuously complete
7535
+ * (spawn nothing you do not need to succeed), which lets a
7536
+ * fan-out-shaped task settle ok without ever fanning out; the floor
7537
+ * makes the intended decomposition binding. The journaled decision
7538
+ * (and a rejection's error data) carries the actual
7539
+ * `spawnedChildren` beside the configured floor, so a resume rolls
7540
+ * the same verdict forward. Positive integer; policy only, never
7541
+ * part of any identity.
7542
+ */
7543
+ minSpawnedChildren?: number;
7544
+ /**
7503
7545
  * The terminal-output salvage switch (the 1.64.0 experiment review,
7504
7546
  * P0.4 + P1.1; default false). When true, a child that settled
7505
7547
  * 'limit' CARRYING a terminal output counts as a successful child for
@@ -8129,21 +8171,26 @@ interface AgentProfile {
8129
8171
  estCost?: number;
8130
8172
  /**
8131
8173
  * The declared evidence contract of the profile's task (RV303, the
8132
- * seventh comparison experiment): how many evidence entries the
8133
- * spawned agent MUST record, and the declared call estimates behind
8134
- * them. Purely declarative, like estCost: the runtime never enforces
8135
- * it; {@link preflightEstimate} compares the resulting call floor
8174
+ * seventh comparison experiment; runtime enforcement RV507): how many
8175
+ * evidence entries the spawned agent MUST record, and the declared
8176
+ * call estimates behind them. Under the default `enforce: 'warn'` it
8177
+ * is purely declarative, like estCost: {@link preflightEstimate}
8178
+ * compares the resulting call floor
8136
8179
  * (`minEntries * estCallsPerEntry + overheadCalls`, defaults 3 and 8)
8137
8180
  * against the spawn's effective executed-call ceiling and warns
8138
8181
  * `tool-cap-below-evidence-floor` when the cap cannot fit the
8139
- * contract. The experiment shape: 14 mandatory entries against an
8140
- * 84-call cap that two workers exhausted at 10 recorded entries.
8182
+ * contract. Under `enforce: 'refuse'` the floor additionally binds at
8183
+ * the terminal: an ok settle with fewer successful `record_evidence`
8184
+ * executions than `minEntries` becomes a typed error terminal. The
8185
+ * experiment shape: 14 mandatory entries against an 84-call cap that
8186
+ * two workers exhausted at 10 recorded entries.
8141
8187
  */
8142
8188
  evidenceContract?: EvidenceContract;
8143
8189
  }
8144
8190
  /**
8145
- * A declared evidence floor for preflight to judge tool caps against
8146
- * (RV303). Declarative only; see {@link AgentProfile.evidenceContract}.
8191
+ * A declared evidence floor (RV303): preflight judges tool caps
8192
+ * against it, and under `enforce: 'refuse'` the runtime refuses an ok
8193
+ * settle below it (RV507); see {@link AgentProfile.evidenceContract}.
8147
8194
  */
8148
8195
  interface EvidenceContract {
8149
8196
  /** Evidence entries the task must record; positive integer. */
@@ -8152,6 +8199,19 @@ interface EvidenceContract {
8152
8199
  estCallsPerEntry?: number;
8153
8200
  /** Estimated non-evidence overhead calls; default 8. */
8154
8201
  overheadCalls?: number;
8202
+ /**
8203
+ * What the floor does at the child's terminal settle (RV507). The
8204
+ * default 'warn' keeps the historical behavior: the contract is a
8205
+ * preflight signal only. 'refuse' turns an ok finish whose message
8206
+ * window carries fewer successful `record_evidence` executions
8207
+ * (result `recorded: true`; duplicates and verification errors never
8208
+ * count) than `minEntries` into a typed error terminal (kind
8209
+ * 'terminal') whose journaled error data carries the machine-readable
8210
+ * `evidenceFloor: { recordedEntries, minEntries }`; the outcome is
8211
+ * memoized, so a resume rolls the refusal forward instead of
8212
+ * re-paying the invocation. Non-ok terminals are never re-judged.
8213
+ */
8214
+ enforce?: "warn" | "refuse";
8155
8215
  }
8156
8216
  /**
8157
8217
  * Per-spawn options. The
package/dist/index.js CHANGED
@@ -2781,17 +2781,19 @@ function requireTimerDelayMs(value, site) {
2781
2781
  if (typeof value !== "number" || !Number.isInteger(value) || value < 1 || value > 2147483647) refuse(site, "an integer between 1 and 2147483647 ms (the Node timer maximum)", value);
2782
2782
  }
2783
2783
  /**
2784
- * A declared evidence contract (RV303): minEntries and
2785
- * estCallsPerEntry positive integers, overheadCalls a nonnegative
2786
- * integer. Shared by the profile intake and the preflight spawn spec so
2787
- * both boundaries refuse the same shapes with the same wording.
2784
+ * A declared evidence contract (RV303, enforcement RV507): minEntries
2785
+ * and estCallsPerEntry positive integers, overheadCalls a nonnegative
2786
+ * integer, enforce one of 'warn' | 'refuse'. Shared by the profile
2787
+ * intake and the preflight spawn spec so both boundaries refuse the
2788
+ * same shapes with the same wording.
2788
2789
  */
2789
2790
  function validateEvidenceContract(value, site) {
2790
- if (typeof value !== "object" || value === null || Array.isArray(value)) throw new ConfigError(`${site} must be { minEntries, estCallsPerEntry?, overheadCalls? }; got ${typeof value}`);
2791
- const { minEntries, estCallsPerEntry, overheadCalls } = value;
2791
+ if (typeof value !== "object" || value === null || Array.isArray(value)) throw new ConfigError(`${site} must be { minEntries, estCallsPerEntry?, overheadCalls?, enforce? }; got ${typeof value}`);
2792
+ const { minEntries, estCallsPerEntry, overheadCalls, enforce } = value;
2792
2793
  requirePositiveInteger(minEntries, `${site}.minEntries`);
2793
2794
  if (estCallsPerEntry !== void 0) requirePositiveInteger(estCallsPerEntry, `${site}.estCallsPerEntry`);
2794
2795
  if (overheadCalls !== void 0) requireNonNegativeInteger(overheadCalls, `${site}.overheadCalls`);
2796
+ if (enforce !== void 0 && enforce !== "warn" && enforce !== "refuse") throw new ConfigError(`${site}.enforce must be 'warn' or 'refuse'; got ${JSON.stringify(enforce)}`);
2795
2797
  }
2796
2798
  //#endregion
2797
2799
  //#region src/knowledge/file-store.ts
@@ -6601,7 +6603,7 @@ var ResolutionFold = class {
6601
6603
  /**
6602
6604
  * Per-run, per-target FIFO serializer of resolution/abandon attempts:
6603
6605
  * classification against the in-memory fold ->
6604
- * durable append -> settle exactly once; losing attempts are ALSO
6606
+ * durable append -> a single settle; losing attempts are ALSO
6605
6607
  * appended and become journaled noops by fold classification. Winner
6606
6608
  * effects run strictly after the critical section (the caller's job).
6607
6609
  * Cross-process protection remains the LeasableStore fencing epoch.
@@ -7193,7 +7195,7 @@ var Replayer = class {
7193
7195
  });
7194
7196
  }
7195
7197
  /**
7196
- * The budget ledger fold: usage sums over terminal entries exactly once; agentsSpawned
7198
+ * The budget ledger fold: usage sums over terminal entries once, never twice; agentsSpawned
7197
7199
  * counts agent dispatches.
7198
7200
  */
7199
7201
  ledger() {
@@ -7762,7 +7764,7 @@ function metaMatchesFilter(meta, f) {
7762
7764
  * InMemoryStore (M1-T04): the default journal store. Process-local, so
7763
7765
  * nothing survives a process exit and cross-process resume is
7764
7766
  * impossible (same-process resume of a kept instance works); the store
7765
- * warns loudly exactly once per instance unless constructed with
7767
+ * warns loudly once per instance unless constructed with
7766
7768
  * `quiet: true` (the deliberate choice of a test tier).
7767
7769
  * An in-memory TranscriptStore ships alongside for the same default.
7768
7770
  */
@@ -8214,7 +8216,7 @@ var FileTranscriptStore = class {
8214
8216
  * agent type, role 'loop').
8215
8217
  *
8216
8218
  * Inclusion policy, applied to the total and EVERY breakdown alike:
8217
- * terminal usage exactly once, priced per serving slice, entries under
8219
+ * terminal usage once, priced per serving slice, entries under
8218
8220
  * abandoned subtrees contribute zero (their spend is tracked separately
8219
8221
  * in the abandoned-spend ledger the orchestrator sees). Attempts that
8220
8222
  * were paid but never abandoned (a cancelled root attempt, a dangling
@@ -11163,7 +11165,7 @@ async function runAgent(options) {
11163
11165
  * Gates and executes one turn's tool calls in source order. priorParts
11164
11166
  * carries results already executed before a mid-turn suspension; the
11165
11167
  * pending state checkpointed at an ask verdict stores RAW model args so
11166
- * a resume re-runs the chain (hooks apply exactly once) and re-matches
11168
+ * a resume re-runs the chain (hooks apply once) and re-matches
11167
11169
  * the same approval identity.
11168
11170
  */
11169
11171
  const runToolCalls = async (calls, priorParts) => {
@@ -12515,6 +12517,24 @@ async function runAgent(options) {
12515
12517
  }
12516
12518
  endPhase(extractPhase, phaseOutcome(), extractServed);
12517
12519
  }
12520
+ const evidenceFloor = options.evidenceContract;
12521
+ let evidenceRefusal;
12522
+ if (evidenceFloor?.enforce === "refuse" && status === "ok") {
12523
+ const recordedEntries = messages.reduce((count, message) => count + message.parts.filter((part) => part.type === "tool-result" && part.name === "record_evidence" && part.result?.recorded === true).length, 0);
12524
+ if (recordedEntries < evidenceFloor.minEntries) {
12525
+ status = "error";
12526
+ output = null;
12527
+ evidenceRefusal = {
12528
+ recordedEntries,
12529
+ minEntries: evidenceFloor.minEntries
12530
+ };
12531
+ agentError = {
12532
+ kind: "terminal",
12533
+ retryable: false
12534
+ };
12535
+ errorMessage = `evidence contract unmet: ${String(recordedEntries)} of ${String(evidenceFloor.minEntries)} required evidence entries recorded`;
12536
+ }
12537
+ }
12518
12538
  const limitPartial = status === "limit" ? latestProgressReport(messages) : void 0;
12519
12539
  if (limitPartial !== void 0) await saveBoundary();
12520
12540
  let transcriptRef = "";
@@ -12560,6 +12580,7 @@ async function runAgent(options) {
12560
12580
  const schemaRejectedTerminalExchanges = terminalName === void 0 ? 0 : messages.reduce((count, message) => count + message.parts.filter((part) => part.type === "tool-result" && part.name === terminalName && part.isError === true && part.result?.error === terminalSchemaRejectionMessage(terminalName)).length, 0);
12561
12581
  if (schemaRejectedTerminalExchanges > 0) result.schemaRejectedTerminalExchanges = schemaRejectedTerminalExchanges;
12562
12582
  if (schemaRecoveredTerminalExchanges > 0) result.schemaRecoveredTerminalExchanges = schemaRecoveredTerminalExchanges;
12583
+ if (evidenceRefusal !== void 0) result.evidenceFloor = evidenceRefusal;
12563
12584
  if (usageApprox) result.usageApprox = true;
12564
12585
  if (transportRetries > 0) result.transportRetries = transportRetries;
12565
12586
  if (rateLimitObservations.size > 0) result.rateLimitObservations = [...rateLimitObservations.values()];
@@ -14754,6 +14775,7 @@ function createCtx(internals, rootWorkflow) {
14754
14775
  if (finalize !== void 0) runAgentOptions.finalize = finalize;
14755
14776
  runAgentOptions.summarize = summarize;
14756
14777
  if (profile?.compaction !== void 0) runAgentOptions.compaction = profile.compaction;
14778
+ if (profile?.evidenceContract !== void 0) runAgentOptions.evidenceContract = profile.evidenceContract;
14757
14779
  if (loopFallbacks.length > 0) runAgentOptions.fallbacks = loopFallbacks;
14758
14780
  if (retryPolicy !== void 0) runAgentOptions.retry = { policy: retryPolicy };
14759
14781
  if (internals.quota !== void 0) {
@@ -14974,6 +14996,18 @@ function createCtx(internals, rootWorkflow) {
14974
14996
  };
14975
14997
  }
14976
14998
  }
14999
+ if (result.evidenceFloor !== void 0 && terminalPatch.error !== void 0) {
15000
+ terminalPatch.memoizeOutcome = true;
15001
+ const priorData = terminalPatch.error.data;
15002
+ const dataRecord = typeof priorData === "object" && priorData !== null && !Array.isArray(priorData) ? priorData : {};
15003
+ terminalPatch.error = {
15004
+ ...terminalPatch.error,
15005
+ data: {
15006
+ ...dataRecord,
15007
+ evidenceFloor: result.evidenceFloor
15008
+ }
15009
+ };
15010
+ }
14977
15011
  if (checkpointWritten) terminalPatch.checkpointRef = ckptRef;
14978
15012
  const terminal = await internals.replayer.appendTerminal(running.seq, terminalPatch);
14979
15013
  internals.events.emit({
@@ -16044,7 +16078,7 @@ const MAX_LISTED_EXTRA_HEADINGS = 5;
16044
16078
  * heading nor trip exclusivity. Heading lines compare trimmed, whole
16045
16079
  * line. With `ordered` (default true) the declared headings must
16046
16080
  * appear in declaration order; with `exclusive` (default true) each
16047
- * declared heading must appear exactly once and no undeclared heading
16081
+ * declared heading must appear once, unrepeated, and no undeclared heading
16048
16082
  * of the governed level may exist (other levels stay free). Default
16049
16083
  * name 'heading-structure'.
16050
16084
  */
@@ -16216,7 +16250,10 @@ function listCitations(values) {
16216
16250
  * {@link DEFAULT_EVIDENCE_MIN_SHARE}, the plan's 95 percent gate,
16217
16251
  * compared as a ceiling on the required count so an exact boundary like
16218
16252
  * 19 of 20 passes) must appear literally in the result text. Zero child
16219
- * citations pass vacuously. With `requireKnown: true` the contract also
16253
+ * citations pass vacuously UNLESS `requireNonEmptyPool: true` (RV507):
16254
+ * for an evidence-critical run the empty pool IS the failure, so that
16255
+ * mode refuses it with an `empty child citation pool` reason instead of
16256
+ * the vacuous pass. With `requireKnown: true` the contract also
16220
16257
  * runs in reverse: every citation in the RESULT must appear in some
16221
16258
  * child's output, so a fabricated but pattern valid citation is
16222
16259
  * rejected instead of silently counting as evidence. Rejection reasons
@@ -16245,6 +16282,7 @@ function evidencePreservedValidator(options) {
16245
16282
  for (const match of child.text.match(new RegExp(pattern, globalFlags)) ?? []) cited.add(match);
16246
16283
  }
16247
16284
  const reasons = [];
16285
+ if (cited.size === 0 && options?.requireNonEmptyPool === true) reasons.push("empty child citation pool: no ok child output contains a citation matching the pattern");
16248
16286
  if (cited.size > 0) {
16249
16287
  const missing = [...cited].filter((citation) => !input.text.includes(citation));
16250
16288
  const preserved = cited.size - missing.length;
@@ -16774,6 +16812,8 @@ function validateOrchestrateOptions(opts) {
16774
16812
  if (acceptPartial !== void 0 && typeof acceptPartial !== "boolean") throw new ConfigError(`orchestrate acceptance.acceptPartialChildren must be a boolean; got ${typeof acceptPartial}`);
16775
16813
  const acceptOutput = opts.acceptance.acceptValidatedTerminalOutputOnLimit;
16776
16814
  if (acceptOutput !== void 0 && typeof acceptOutput !== "boolean") throw new ConfigError("orchestrate acceptance.acceptValidatedTerminalOutputOnLimit must be a boolean; got " + typeof acceptOutput);
16815
+ const minSpawned = opts.acceptance.minSpawnedChildren;
16816
+ if (minSpawned !== void 0) requirePositiveInteger(minSpawned, "orchestrate acceptance.minSpawnedChildren");
16777
16817
  }
16778
16818
  if (opts.finishValidation !== void 0) {
16779
16819
  const fv = opts.finishValidation;
@@ -18530,7 +18570,10 @@ function makeOrchestratorWorkflow(goal, opts) {
18530
18570
  degradedReasons.push(status === "running" ? `child ${record.nodeId} was still running when finish validated` : `child ${record.nodeId} settled '${status}'`);
18531
18571
  }
18532
18572
  const childPolicy = opts.acceptance.childPolicy;
18533
- const accepted = childPolicy === "all-ok" ? hardDegraded === 0 : (childStatusCounts.ok ?? 0) + salvaged.length + salvagedOutput.length >= childPolicy.minSuccessful;
18573
+ const minSpawned = opts.acceptance.minSpawnedChildren;
18574
+ const rosterMet = minSpawned === void 0 || sortedRecords.length >= minSpawned;
18575
+ if (!rosterMet) degradedReasons.push(`only ${String(sortedRecords.length)} children were spawned; the acceptance policy requires at least ${String(minSpawned)} spawned children`);
18576
+ const accepted = rosterMet && (childPolicy === "all-ok" ? hardDegraded === 0 : (childStatusCounts.ok ?? 0) + salvaged.length + salvagedOutput.length >= childPolicy.minSuccessful);
18534
18577
  decision = {
18535
18578
  decisionType: "orchestrator_acceptance",
18536
18579
  verdict: accepted ? "accepted" : "rejected",
@@ -18538,6 +18581,10 @@ function makeOrchestratorWorkflow(goal, opts) {
18538
18581
  childPolicy,
18539
18582
  childStatusCounts,
18540
18583
  degradedReasons,
18584
+ ...minSpawned === void 0 ? {} : {
18585
+ minSpawnedChildren: minSpawned,
18586
+ spawnedChildren: sortedRecords.length
18587
+ },
18541
18588
  ...salvaged.length === 0 ? {} : { salvagedPartialChildren: salvaged },
18542
18589
  ...salvagedOutput.length === 0 ? {} : { salvagedTerminalOutputChildren: salvagedOutput },
18543
18590
  ...accepted || opts.synthesis === void 0 ? {} : { synthesisSkipped: "synthesis_skipped_by_acceptance" }
@@ -18559,13 +18606,17 @@ function makeOrchestratorWorkflow(goal, opts) {
18559
18606
  msg: "orchestrator synthesis skipped",
18560
18607
  data: { reason: decision.synthesisSkipped }
18561
18608
  }, callingState.spanId);
18562
- const required = decision.childPolicy === "all-ok" ? "every child ok" : `at least ${String(decision.childPolicy.minSuccessful)} children ok`;
18609
+ const required = (decision.childPolicy === "all-ok" ? "every child ok" : `at least ${String(decision.childPolicy.minSuccessful)} children ok`) + (decision.minSpawnedChildren === void 0 ? "" : `, with at least ${String(decision.minSpawnedChildren)} spawned children`);
18563
18610
  throw new FailRunError(`the orchestrator acceptance policy rejected the finish: ${String(decision.childStatusCounts.ok ?? 0)} children settled 'ok' but the policy requires ${required}; degraded: ${decision.degradedReasons.join("; ")}`, { data: {
18564
18611
  source: "orchestrator_acceptance",
18565
18612
  completion: "rejected",
18566
18613
  childPolicy: decision.childPolicy,
18567
18614
  childStatusCounts: decision.childStatusCounts,
18568
18615
  degradedReasons: decision.degradedReasons,
18616
+ ...decision.minSpawnedChildren === void 0 ? {} : {
18617
+ minSpawnedChildren: decision.minSpawnedChildren,
18618
+ spawnedChildren: decision.spawnedChildren ?? 0
18619
+ },
18569
18620
  ...decision.salvagedPartialChildren === void 0 ? {} : { salvagedPartialChildren: decision.salvagedPartialChildren },
18570
18621
  ...decision.salvagedTerminalOutputChildren === void 0 ? {} : { salvagedTerminalOutputChildren: decision.salvagedTerminalOutputChildren },
18571
18622
  ...decision.synthesisSkipped === void 0 ? {} : { synthesisSkipped: decision.synthesisSkipped }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rulvar/core",
3
- "version": "1.98.0",
3
+ "version": "1.99.1",
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",