@rulvar/core 1.194.0 → 1.195.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
@@ -9329,6 +9329,23 @@ interface OrchestrateOptions {
9329
9329
  /** The opt in child completion policy; see {@link OrchestrateAcceptance}. */
9330
9330
  acceptance?: OrchestrateAcceptance;
9331
9331
  /**
9332
+ * The terminal child barrier policy (RV1903, the four-role
9333
+ * benchmark's recovery arm): what happens to children still running
9334
+ * when the orchestration exits, on EVERY exit path (an accepted or
9335
+ * rejected finish, a typed failure, a budget or exposure terminal).
9336
+ * 'cancel' (the default) aborts them and awaits their journaled
9337
+ * cancelled terminals; 'drain' awaits their natural terminals,
9338
+ * bounded by their own limits and budgets, preserving their evidence
9339
+ * at the price of the wait. Either way the orchestration returns
9340
+ * only after every spawned child has a terminal journal entry, so
9341
+ * `run_settle` can never precede a child's billing row again: the
9342
+ * benchmark's recovery journal recorded three child terminals AFTER
9343
+ * the settle decision, and four mutually inconsistent cost views
9344
+ * followed. The verdict the run settled with is already frozen
9345
+ * before the barrier runs, so late children never change it.
9346
+ */
9347
+ onUnsettledAtExit?: "cancel" | "drain";
9348
+ /**
9332
9349
  * The opt in deterministic host validation of the finish result, with
9333
9350
  * bounded repair; see {@link FinishValidationSpec}.
9334
9351
  */
package/dist/index.js CHANGED
@@ -20740,6 +20740,7 @@ function validateOrchestrateOptions(opts) {
20740
20740
  if (opts === void 0) return;
20741
20741
  if (opts.maxSpawns !== void 0) requireNonNegativeInteger(opts.maxSpawns, "orchestrate maxSpawns");
20742
20742
  if (opts.renderBudgetChars !== void 0) requireNonNegativeInteger(opts.renderBudgetChars, "orchestrate renderBudgetChars");
20743
+ if (opts.onUnsettledAtExit !== void 0 && opts.onUnsettledAtExit !== "cancel" && opts.onUnsettledAtExit !== "drain") throw new ConfigError(`orchestrate onUnsettledAtExit must be 'cancel' or 'drain'; got ${String(opts.onUnsettledAtExit)}`);
20743
20744
  if (opts.acceptance !== void 0) {
20744
20745
  const policy = opts.acceptance.childPolicy;
20745
20746
  const minSuccessful = typeof policy === "object" && policy !== null && !Array.isArray(policy) ? policy.minSuccessful : void 0;
@@ -21051,7 +21052,7 @@ function filterProfiles(registered, names) {
21051
21052
  */
21052
21053
  function makeOrchestratorWorkflow(goal, opts) {
21053
21054
  validateOrchestrateOptions(opts);
21054
- return defineWorkflow({ name: ORCHESTRATE_WORKFLOW_NAME }, async (ctx) => {
21055
+ const orchestrationBody = async (ctx, barrier) => {
21055
21056
  const runtime = runtimeOf(ctx);
21056
21057
  const { internals } = runtime;
21057
21058
  if (internals.admission === void 0) throw new ConfigError("orchestrate requires the engine run context (createEngine)");
@@ -21152,6 +21153,28 @@ function makeOrchestratorWorkflow(goal, opts) {
21152
21153
  const byOrdinal = /* @__PURE__ */ new Map();
21153
21154
  const rejectedByOrdinal = /* @__PURE__ */ new Map();
21154
21155
  /**
21156
+ * The terminal child barrier (RV1903): every exit of this
21157
+ * orchestration, returned or thrown, passes through the finally
21158
+ * below, so a child still running when the verdict froze reaches a
21159
+ * journaled terminal BEFORE the workflow settles. The benchmark's
21160
+ * recovery journal recorded run_settle at sequence 18 and three
21161
+ * child terminals at 19..21; the returned outcome, the terminal
21162
+ * invoice and the event snapshot all disagreed with the final
21163
+ * journal. 'cancel' (default) aborts the stragglers and awaits
21164
+ * their cancelled terminals; 'drain' awaits their natural
21165
+ * terminals, bounded by their own limits. The frozen verdict is
21166
+ * journaled before the barrier runs, so late children never change
21167
+ * it; result promises never reject (SpawnRecord contract), so the
21168
+ * barrier never masks the exit's own error.
21169
+ */
21170
+ const exitBarrier = async () => {
21171
+ const live = [...byOrdinal.values()].filter((record) => record.settled === void 0);
21172
+ if (live.length === 0) return;
21173
+ if ((opts?.onUnsettledAtExit ?? "cancel") === "cancel") for (const record of live) record.abort();
21174
+ await Promise.allSettled(live.map((record) => record.result));
21175
+ };
21176
+ barrier.run = exitBarrier;
21177
+ /**
21155
21178
  * The journaled spec behind each recovered ordinal: the idempotent
21156
21179
  * re-execution guard compares it against the incoming call, because
21157
21180
  * after a cross-attempt resume a REGENERATED turn (the boundary
@@ -23710,6 +23733,14 @@ function makeOrchestratorWorkflow(goal, opts) {
23710
23733
  claimConsistencyMeta
23711
23734
  }
23712
23735
  };
23736
+ };
23737
+ return defineWorkflow({ name: ORCHESTRATE_WORKFLOW_NAME }, async (ctx) => {
23738
+ const barrier = {};
23739
+ try {
23740
+ return await orchestrationBody(ctx, barrier);
23741
+ } finally {
23742
+ await barrier.run?.();
23743
+ }
23713
23744
  });
23714
23745
  }
23715
23746
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rulvar/core",
3
- "version": "1.194.0",
3
+ "version": "1.195.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",