@rulvar/core 1.64.0 → 1.65.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 +33 -0
- package/dist/index.js +32 -10
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -6169,6 +6169,16 @@ interface FinishValidationChild {
|
|
|
6169
6169
|
* same serialization the child result evidence tools page.
|
|
6170
6170
|
*/
|
|
6171
6171
|
readonly text: string;
|
|
6172
|
+
/**
|
|
6173
|
+
* Present and true ONLY when acceptance.acceptValidatedTerminalOutputOnLimit
|
|
6174
|
+
* is configured and this child settled 'limit' CARRYING a terminal
|
|
6175
|
+
* output (the finalization reserve summary that, for a schema child,
|
|
6176
|
+
* already validated against the declared output schema). Acceptance
|
|
6177
|
+
* will count such a child as a success, so evidencePreservedValidator
|
|
6178
|
+
* treats its text as part of the cited evidence pool. Absent in every
|
|
6179
|
+
* other configuration, keeping the old pool exactly.
|
|
6180
|
+
*/
|
|
6181
|
+
readonly salvageableOutput?: boolean;
|
|
6172
6182
|
}
|
|
6173
6183
|
/** What a {@link FinishValidator} judges. */
|
|
6174
6184
|
interface FinishValidationInput {
|
|
@@ -6790,6 +6800,29 @@ interface OrchestrateAcceptance {
|
|
|
6790
6800
|
* decision, so a resume rolls the same verdict forward.
|
|
6791
6801
|
*/
|
|
6792
6802
|
acceptPartialChildren?: boolean;
|
|
6803
|
+
/**
|
|
6804
|
+
* The terminal-output salvage switch (the 1.64.0 experiment review,
|
|
6805
|
+
* P0.4 + P1.1; default false). When true, a child that settled
|
|
6806
|
+
* 'limit' CARRYING a terminal output counts as a successful child for
|
|
6807
|
+
* the policy, exactly like acceptPartialChildren counts a
|
|
6808
|
+
* partial-bearing one. A limit terminal carries an output ONLY when
|
|
6809
|
+
* the child's limits.finalizationReserve summary turn produced one
|
|
6810
|
+
* AND, for a schema child, that summary already validated against the
|
|
6811
|
+
* declared output schema (an invalid summary keeps output null and is
|
|
6812
|
+
* never salvaged), so validation runs BEFORE acceptance by
|
|
6813
|
+
* construction. The verdict then reports completion 'partial' (never
|
|
6814
|
+
* 'complete'), lists the children in `salvagedTerminalOutputChildren`
|
|
6815
|
+
* on the result envelope, and keeps a per-child note in
|
|
6816
|
+
* degradedReasons. A child carrying BOTH an output and a progress
|
|
6817
|
+
* partial salvages by its output. The child's digest and
|
|
6818
|
+
* get_child_result surface the output unconditionally (paid, journaled
|
|
6819
|
+
* evidence is never withheld); this option gates only the acceptance
|
|
6820
|
+
* fold, the evidencePreservedValidator cited pool (via
|
|
6821
|
+
* FinishValidationChild.salvageableOutput), and the coordination
|
|
6822
|
+
* prompt line. The whole fold is journaled in the single acceptance
|
|
6823
|
+
* decision, so a resume rolls the same verdict forward.
|
|
6824
|
+
*/
|
|
6825
|
+
acceptValidatedTerminalOutputOnLimit?: boolean;
|
|
6793
6826
|
}
|
|
6794
6827
|
/** How many rejected finishes are repaired by default: the plan's repair once. */
|
|
6795
6828
|
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 = [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulvar/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.65.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",
|