@rulvar/core 1.64.0 → 1.66.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 +58 -1
- package/dist/index.js +37 -11
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -5577,7 +5577,31 @@ interface CostReport {
|
|
|
5577
5577
|
type RunOutcome<R> = {
|
|
5578
5578
|
status: "ok" | "error" | "cancelled" | "exhausted" | "suspended";
|
|
5579
5579
|
value?: R;
|
|
5580
|
-
error?: WireError;
|
|
5580
|
+
error?: WireError;
|
|
5581
|
+
/**
|
|
5582
|
+
* The semantic completion lift, mirrored from `run:end` (RV-207 tail;
|
|
5583
|
+
* the 1.65.0 experiment review, P0.5): present when the workflow
|
|
5584
|
+
* reported semantic completion through the completion envelope
|
|
5585
|
+
* contract, an `ok`/`exhausted` run whose result value is an object
|
|
5586
|
+
* carrying a valid `completion` literal, or an `error` run whose typed
|
|
5587
|
+
* error data carries one (the orchestrator acceptance path emits
|
|
5588
|
+
* both). Transport status says whether the run ran; completion says
|
|
5589
|
+
* whether the work is COMPLETE: an accepted degraded run is `status:
|
|
5590
|
+
* 'ok'` with `completion: 'partial'`. The engine computes the lift
|
|
5591
|
+
* ONCE and both surfaces spread the same object, so the outcome and
|
|
5592
|
+
* the event can never disagree; a host reads completeness here
|
|
5593
|
+
* without parsing workflow-specific value shapes on the accepted path
|
|
5594
|
+
* or digging typed error data on the rejected one. Absent when the
|
|
5595
|
+
* workflow makes no completion claim.
|
|
5596
|
+
*/
|
|
5597
|
+
completion?: "complete" | "partial" | "rejected";
|
|
5598
|
+
/**
|
|
5599
|
+
* Settled child statuses by status name, lifted from the same
|
|
5600
|
+
* envelope (or typed error data) when it carries a valid record of
|
|
5601
|
+
* nonnegative integers; the mirror of the `run:end` field. Absent
|
|
5602
|
+
* otherwise.
|
|
5603
|
+
*/
|
|
5604
|
+
childStatusCounts?: Record<string, number>; /** Pipeline drops and onError:'null' losses; silent losses are forbidden. */
|
|
5581
5605
|
dropped: DroppedItem[]; /** Suspensions open at settle time (M2). */
|
|
5582
5606
|
pending: PendingExternal[];
|
|
5583
5607
|
usage: Usage;
|
|
@@ -6169,6 +6193,16 @@ interface FinishValidationChild {
|
|
|
6169
6193
|
* same serialization the child result evidence tools page.
|
|
6170
6194
|
*/
|
|
6171
6195
|
readonly text: string;
|
|
6196
|
+
/**
|
|
6197
|
+
* Present and true ONLY when acceptance.acceptValidatedTerminalOutputOnLimit
|
|
6198
|
+
* is configured and this child settled 'limit' CARRYING a terminal
|
|
6199
|
+
* output (the finalization reserve summary that, for a schema child,
|
|
6200
|
+
* already validated against the declared output schema). Acceptance
|
|
6201
|
+
* will count such a child as a success, so evidencePreservedValidator
|
|
6202
|
+
* treats its text as part of the cited evidence pool. Absent in every
|
|
6203
|
+
* other configuration, keeping the old pool exactly.
|
|
6204
|
+
*/
|
|
6205
|
+
readonly salvageableOutput?: boolean;
|
|
6172
6206
|
}
|
|
6173
6207
|
/** What a {@link FinishValidator} judges. */
|
|
6174
6208
|
interface FinishValidationInput {
|
|
@@ -6790,6 +6824,29 @@ interface OrchestrateAcceptance {
|
|
|
6790
6824
|
* decision, so a resume rolls the same verdict forward.
|
|
6791
6825
|
*/
|
|
6792
6826
|
acceptPartialChildren?: boolean;
|
|
6827
|
+
/**
|
|
6828
|
+
* The terminal-output salvage switch (the 1.64.0 experiment review,
|
|
6829
|
+
* P0.4 + P1.1; default false). When true, a child that settled
|
|
6830
|
+
* 'limit' CARRYING a terminal output counts as a successful child for
|
|
6831
|
+
* the policy, exactly like acceptPartialChildren counts a
|
|
6832
|
+
* partial-bearing one. A limit terminal carries an output ONLY when
|
|
6833
|
+
* the child's limits.finalizationReserve summary turn produced one
|
|
6834
|
+
* AND, for a schema child, that summary already validated against the
|
|
6835
|
+
* declared output schema (an invalid summary keeps output null and is
|
|
6836
|
+
* never salvaged), so validation runs BEFORE acceptance by
|
|
6837
|
+
* construction. The verdict then reports completion 'partial' (never
|
|
6838
|
+
* 'complete'), lists the children in `salvagedTerminalOutputChildren`
|
|
6839
|
+
* on the result envelope, and keeps a per-child note in
|
|
6840
|
+
* degradedReasons. A child carrying BOTH an output and a progress
|
|
6841
|
+
* partial salvages by its output. The child's digest and
|
|
6842
|
+
* get_child_result surface the output unconditionally (paid, journaled
|
|
6843
|
+
* evidence is never withheld); this option gates only the acceptance
|
|
6844
|
+
* fold, the evidencePreservedValidator cited pool (via
|
|
6845
|
+
* FinishValidationChild.salvageableOutput), and the coordination
|
|
6846
|
+
* prompt line. The whole fold is journaled in the single acceptance
|
|
6847
|
+
* decision, so a resume rolls the same verdict forward.
|
|
6848
|
+
*/
|
|
6849
|
+
acceptValidatedTerminalOutputOnLimit?: boolean;
|
|
6793
6850
|
}
|
|
6794
6851
|
/** How many rejected finishes are repaired by default: the plan's repair once. */
|
|
6795
6852
|
declare const DEFAULT_FINISH_MAX_REPAIRS = 1;
|
package/dist/index.js
CHANGED
|
@@ -14689,6 +14689,10 @@ function summarizeOutput(result) {
|
|
|
14689
14689
|
if (result.status === "ok") raw = typeof result.output === "string" ? result.output : JSON.stringify(result.output ?? null);
|
|
14690
14690
|
else {
|
|
14691
14691
|
raw = result.errorMessage ?? `terminal status ${result.status}`;
|
|
14692
|
+
if (result.status === "limit" && result.output !== null && result.output !== void 0) {
|
|
14693
|
+
const final = typeof result.output === "string" ? result.output : JSON.stringify(result.output);
|
|
14694
|
+
raw = `${raw}; final: ${final}`;
|
|
14695
|
+
}
|
|
14692
14696
|
if (result.partial !== void 0) raw = `${raw}; partial: ${JSON.stringify(result.partial)}`;
|
|
14693
14697
|
}
|
|
14694
14698
|
return truncateToBudget(raw, 400);
|
|
@@ -15075,9 +15079,11 @@ function pageOf(content, rawOffset, rawMaxChars) {
|
|
|
15075
15079
|
function serializeChildOutput(result) {
|
|
15076
15080
|
if (result.status !== "ok") {
|
|
15077
15081
|
const base = result.errorMessage ?? `terminal status ${result.status}`;
|
|
15078
|
-
|
|
15082
|
+
const limitOutput = result.status === "limit" && result.output !== null && result.output !== void 0;
|
|
15083
|
+
if (limitOutput || result.partial !== void 0) return JSON.stringify({
|
|
15079
15084
|
error: base,
|
|
15080
|
-
|
|
15085
|
+
...limitOutput ? { output: result.output } : {},
|
|
15086
|
+
...result.partial === void 0 ? {} : { partial: result.partial }
|
|
15081
15087
|
});
|
|
15082
15088
|
return base;
|
|
15083
15089
|
}
|
|
@@ -15104,6 +15110,8 @@ function validateOrchestrateOptions(opts) {
|
|
|
15104
15110
|
if (policy !== "all-ok") requirePositiveInteger(minSuccessful, "orchestrate acceptance.childPolicy.minSuccessful");
|
|
15105
15111
|
const acceptPartial = opts.acceptance.acceptPartialChildren;
|
|
15106
15112
|
if (acceptPartial !== void 0 && typeof acceptPartial !== "boolean") throw new ConfigError(`orchestrate acceptance.acceptPartialChildren must be a boolean; got ${typeof acceptPartial}`);
|
|
15113
|
+
const acceptOutput = opts.acceptance.acceptValidatedTerminalOutputOnLimit;
|
|
15114
|
+
if (acceptOutput !== void 0 && typeof acceptOutput !== "boolean") throw new ConfigError("orchestrate acceptance.acceptValidatedTerminalOutputOnLimit must be a boolean; got " + typeof acceptOutput);
|
|
15107
15115
|
}
|
|
15108
15116
|
if (opts.finishValidation !== void 0) {
|
|
15109
15117
|
const fv = opts.finishValidation;
|
|
@@ -15174,8 +15182,10 @@ function finishValidationPromptLines(spec) {
|
|
|
15174
15182
|
* keeps byte-identical coordination prompts.
|
|
15175
15183
|
*/
|
|
15176
15184
|
function acceptancePromptLines(acceptance) {
|
|
15177
|
-
|
|
15178
|
-
|
|
15185
|
+
const lines = [];
|
|
15186
|
+
if (acceptance?.acceptPartialChildren === true) lines.push("Partial salvage is on: a child that ends at its limit AFTER recording progress with report_progress counts as a partial success for acceptance; its digest carries the partial and get_child_result (when enabled) pages the full report. When the gap matters, respawn a NARROWED child carrying the partial instead of repeating the task.");
|
|
15187
|
+
if (acceptance?.acceptValidatedTerminalOutputOnLimit === true) lines.push("Terminal-output salvage is on: a child that ends at its limit WITH a final answer (its finalization reserve summary, already validated against the declared output schema) counts as a successful child for acceptance; its digest carries it after the 'final:' marker and get_child_result (when enabled) pages it in full.");
|
|
15188
|
+
return lines;
|
|
15179
15189
|
}
|
|
15180
15190
|
/**
|
|
15181
15191
|
* Resolves per-spawn dispatch options against the engine registries
|
|
@@ -16080,11 +16090,13 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
16080
16090
|
let decision = known.find((candidate) => candidate.callId === call.id);
|
|
16081
16091
|
if (decision === void 0) {
|
|
16082
16092
|
const result = call.result ?? null;
|
|
16093
|
+
const salvageOutputOn = opts?.acceptance?.acceptValidatedTerminalOutputOnLimit === true;
|
|
16083
16094
|
const children = [...records.values()].sort((a, b) => a.spawnOrdinal - b.spawnOrdinal).map((record) => ({
|
|
16084
16095
|
handle: record.handle,
|
|
16085
16096
|
nodeId: record.nodeId,
|
|
16086
16097
|
status: record.settled?.status ?? "running",
|
|
16087
|
-
text: record.settled === void 0 ? "" : serializeChildOutput(record.settled)
|
|
16098
|
+
text: record.settled === void 0 ? "" : serializeChildOutput(record.settled),
|
|
16099
|
+
...salvageOutputOn && record.settled?.status === "limit" && record.settled.output !== null && record.settled.output !== void 0 ? { salvageableOutput: true } : {}
|
|
16088
16100
|
}));
|
|
16089
16101
|
const input = {
|
|
16090
16102
|
result,
|
|
@@ -16542,13 +16554,20 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
16542
16554
|
const childStatusCounts = {};
|
|
16543
16555
|
const degradedReasons = [];
|
|
16544
16556
|
const salvaged = [];
|
|
16557
|
+
const salvagedOutput = [];
|
|
16545
16558
|
let hardDegraded = 0;
|
|
16546
16559
|
const acceptPartial = opts.acceptance.acceptPartialChildren === true;
|
|
16560
|
+
const acceptOutput = opts.acceptance.acceptValidatedTerminalOutputOnLimit === true;
|
|
16547
16561
|
const sortedRecords = [...records.values()].sort((a, b) => a.spawnOrdinal - b.spawnOrdinal);
|
|
16548
16562
|
for (const record of sortedRecords) {
|
|
16549
16563
|
const status = record.settled?.status ?? "running";
|
|
16550
16564
|
childStatusCounts[status] = (childStatusCounts[status] ?? 0) + 1;
|
|
16551
16565
|
if (status === "ok") continue;
|
|
16566
|
+
if (acceptOutput && status === "limit" && record.settled?.output !== null && record.settled?.output !== void 0) {
|
|
16567
|
+
salvagedOutput.push(record.nodeId);
|
|
16568
|
+
degradedReasons.push(`child ${record.nodeId} accepted with its validated terminal output (settled 'limit' after the finalization reserve summary)`);
|
|
16569
|
+
continue;
|
|
16570
|
+
}
|
|
16552
16571
|
if (acceptPartial && status === "limit" && record.settled?.partial !== void 0) {
|
|
16553
16572
|
salvaged.push(record.nodeId);
|
|
16554
16573
|
degradedReasons.push(`child ${record.nodeId} accepted as partial (settled 'limit' with a structured partial)`);
|
|
@@ -16558,7 +16577,7 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
16558
16577
|
degradedReasons.push(status === "running" ? `child ${record.nodeId} was still running when finish validated` : `child ${record.nodeId} settled '${status}'`);
|
|
16559
16578
|
}
|
|
16560
16579
|
const childPolicy = opts.acceptance.childPolicy;
|
|
16561
|
-
const accepted = childPolicy === "all-ok" ? hardDegraded === 0 : (childStatusCounts.ok ?? 0) + salvaged.length >= childPolicy.minSuccessful;
|
|
16580
|
+
const accepted = childPolicy === "all-ok" ? hardDegraded === 0 : (childStatusCounts.ok ?? 0) + salvaged.length + salvagedOutput.length >= childPolicy.minSuccessful;
|
|
16562
16581
|
decision = {
|
|
16563
16582
|
decisionType: "orchestrator_acceptance",
|
|
16564
16583
|
verdict: accepted ? "accepted" : "rejected",
|
|
@@ -16566,7 +16585,8 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
16566
16585
|
childPolicy,
|
|
16567
16586
|
childStatusCounts,
|
|
16568
16587
|
degradedReasons,
|
|
16569
|
-
...salvaged.length === 0 ? {} : { salvagedPartialChildren: salvaged }
|
|
16588
|
+
...salvaged.length === 0 ? {} : { salvagedPartialChildren: salvaged },
|
|
16589
|
+
...salvagedOutput.length === 0 ? {} : { salvagedTerminalOutputChildren: salvagedOutput }
|
|
16570
16590
|
};
|
|
16571
16591
|
await internals.replayer.appendSinglePhase({
|
|
16572
16592
|
scope: callingState.scope,
|
|
@@ -16586,7 +16606,8 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
16586
16606
|
childPolicy: decision.childPolicy,
|
|
16587
16607
|
childStatusCounts: decision.childStatusCounts,
|
|
16588
16608
|
degradedReasons: decision.degradedReasons,
|
|
16589
|
-
...decision.salvagedPartialChildren === void 0 ? {} : { salvagedPartialChildren: decision.salvagedPartialChildren }
|
|
16609
|
+
...decision.salvagedPartialChildren === void 0 ? {} : { salvagedPartialChildren: decision.salvagedPartialChildren },
|
|
16610
|
+
...decision.salvagedTerminalOutputChildren === void 0 ? {} : { salvagedTerminalOutputChildren: decision.salvagedTerminalOutputChildren }
|
|
16590
16611
|
} });
|
|
16591
16612
|
}
|
|
16592
16613
|
return {
|
|
@@ -16594,7 +16615,8 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
16594
16615
|
completion: decision.completion,
|
|
16595
16616
|
childStatusCounts: decision.childStatusCounts,
|
|
16596
16617
|
degradedReasons: decision.degradedReasons,
|
|
16597
|
-
...decision.salvagedPartialChildren === void 0 ? {} : { salvagedPartialChildren: decision.salvagedPartialChildren }
|
|
16618
|
+
...decision.salvagedPartialChildren === void 0 ? {} : { salvagedPartialChildren: decision.salvagedPartialChildren },
|
|
16619
|
+
...decision.salvagedTerminalOutputChildren === void 0 ? {} : { salvagedTerminalOutputChildren: decision.salvagedTerminalOutputChildren }
|
|
16598
16620
|
};
|
|
16599
16621
|
});
|
|
16600
16622
|
}
|
|
@@ -17315,7 +17337,7 @@ function evidencePreservedValidator(options) {
|
|
|
17315
17337
|
validate: (input) => {
|
|
17316
17338
|
const cited = /* @__PURE__ */ new Set();
|
|
17317
17339
|
for (const child of input.children ?? []) {
|
|
17318
|
-
if (child.status !== "ok") continue;
|
|
17340
|
+
if (child.status !== "ok" && child.salvageableOutput !== true) continue;
|
|
17319
17341
|
for (const match of child.text.match(new RegExp(pattern, globalFlags)) ?? []) cited.add(match);
|
|
17320
17342
|
}
|
|
17321
17343
|
const reasons = [];
|
|
@@ -18466,6 +18488,11 @@ function createEngine(options) {
|
|
|
18466
18488
|
};
|
|
18467
18489
|
if (value !== void 0 && (status === "ok" || status === "exhausted")) outcome.value = value;
|
|
18468
18490
|
if (wireError !== void 0) outcome.error = wireError;
|
|
18491
|
+
const lifted = liftRunCompletion(status === "ok" || status === "exhausted" ? outcome.value : status === "error" ? wireError?.data : void 0);
|
|
18492
|
+
if (lifted !== void 0) {
|
|
18493
|
+
outcome.completion = lifted.completion;
|
|
18494
|
+
if (lifted.childStatusCounts !== void 0) outcome.childStatusCounts = lifted.childStatusCounts;
|
|
18495
|
+
}
|
|
18469
18496
|
let settlementFailure;
|
|
18470
18497
|
if (resumeCtx?.strict !== true) {
|
|
18471
18498
|
const priorCount = resumeCtx?.priorEntries.length ?? 0;
|
|
@@ -18510,7 +18537,6 @@ function createEngine(options) {
|
|
|
18510
18537
|
level: "warn",
|
|
18511
18538
|
msg: `settlement write failed (${settlementFailure.stage}); handle.result rejects with SettlementError; resume re-settles by replay without a provider call`
|
|
18512
18539
|
}, rootSpanId);
|
|
18513
|
-
const lifted = liftRunCompletion(status === "ok" || status === "exhausted" ? outcome.value : status === "error" ? wireError?.data : void 0);
|
|
18514
18540
|
bus.emit({
|
|
18515
18541
|
type: "run:end",
|
|
18516
18542
|
status,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulvar/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.66.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",
|