@rulvar/plan 1.33.0 → 1.35.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.js +47 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -923,6 +923,49 @@ function cascadeOf(plan, root) {
|
|
|
923
923
|
}
|
|
924
924
|
//#endregion
|
|
925
925
|
//#region src/guards.ts
|
|
926
|
+
/**
|
|
927
|
+
* RevisionGuards, the oscillation detector, and hysteresis (M7-T06).
|
|
928
|
+
*
|
|
929
|
+
* Guide: https://docs.rulvar.com/guide/adaptive-orchestration
|
|
930
|
+
* (DEF-8; DEF-2/DEF-5 interactions). The guards are non-HITL and
|
|
931
|
+
* terminating: a human in the loop is NEVER required for a run to end.
|
|
932
|
+
* Every guard verdict is a decision entry written strictly BEFORE its
|
|
933
|
+
* effects; verdict state is a pure fold of those entries, so replay
|
|
934
|
+
* re-derives the same freezes with zero live calls.
|
|
935
|
+
*
|
|
936
|
+
* Three detectors:
|
|
937
|
+
*
|
|
938
|
+
* - droppedRevisionStreak: `effectiveDroppedStreak` (the hashed counter
|
|
939
|
+
* plus trailing bad_base entries) reaching `droppedRevisionLimit`
|
|
940
|
+
* (default 3) fires the configured terminating fallback
|
|
941
|
+
* (reject-revision -> finish-with-partial -> fail-run; default
|
|
942
|
+
* finish-with-partial).
|
|
943
|
+
* - Oscillation: keyed on approachSigCoarse ACROSS LogicalTaskId
|
|
944
|
+
* boundaries (a content-identical rebirth under a fresh lineage root
|
|
945
|
+
* is still flagged): a re-add after a severing cancel of the same
|
|
946
|
+
* coarse signature counts one oscillation; at the per-key limit
|
|
947
|
+
* further re-adds FREEZE (the per-SpawnKey osc_guard of DEF-5 lands
|
|
948
|
+
* in M7-T07 and keys the DedupIndex instead).
|
|
949
|
+
* - Stall replans: hard-bounded per run; the streak already excludes
|
|
950
|
+
* transient and environment classes.
|
|
951
|
+
*
|
|
952
|
+
* Hysteresis on almost-done nodes is structural: park and cancel against
|
|
953
|
+
* RUNNING nodes only ever land as boundary flags (requestOnly), so a
|
|
954
|
+
* nearly-finished child is never killed mid-turn, and park/unpark churn
|
|
955
|
+
* feeds the oscillation counter.
|
|
956
|
+
*/
|
|
957
|
+
/**
|
|
958
|
+
* Local mirror of the core numeric-intake idiom (v1.34.0 review P2-3):
|
|
959
|
+
* guard limits are compared with `<` and `!==`, and every comparison
|
|
960
|
+
* with NaN is false, so an unvalidated NaN limit made the dropped and
|
|
961
|
+
* oscillation guards trip immediately and the stall cap never trip.
|
|
962
|
+
*/
|
|
963
|
+
function requireCount(value, site, min) {
|
|
964
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < min) throw new ConfigError(`${site} must be ${min === 1 ? "a positive integer" : "a nonnegative integer"}; got ${String(value)}`);
|
|
965
|
+
}
|
|
966
|
+
function requireGuardFraction(value, site) {
|
|
967
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0 || value > 1) throw new ConfigError(`${site} must be a fraction in (0, 1]; got ${String(value)}`);
|
|
968
|
+
}
|
|
926
969
|
/** Appendix A: osc_guard reject threshold per key (shared default). */
|
|
927
970
|
const DEFAULT_MAX_OSCILLATIONS_PER_KEY = 2;
|
|
928
971
|
/** The hard per-run stall replan bound. */
|
|
@@ -947,6 +990,10 @@ var RevisionGuards = class {
|
|
|
947
990
|
frozen = /* @__PURE__ */ new Set();
|
|
948
991
|
stallReplans = 0;
|
|
949
992
|
constructor(options) {
|
|
993
|
+
if (options?.droppedRevisionLimit !== void 0) requireCount(options.droppedRevisionLimit, "RevisionGuards droppedRevisionLimit", 1);
|
|
994
|
+
if (options?.maxOscillationsPerKey !== void 0) requireCount(options.maxOscillationsPerKey, "RevisionGuards maxOscillationsPerKey", 1);
|
|
995
|
+
if (options?.stallReplanCap !== void 0) requireCount(options.stallReplanCap, "RevisionGuards stallReplanCap", 0);
|
|
996
|
+
if (options?.maxAbandonedNetUsdFraction !== void 0) requireGuardFraction(options.maxAbandonedNetUsdFraction, "RevisionGuards maxAbandonedNetUsdFraction");
|
|
950
997
|
this.fallback = options?.fallback ?? "finish-with-partial";
|
|
951
998
|
this.droppedRevisionLimit = options?.droppedRevisionLimit ?? 3;
|
|
952
999
|
this.maxOscillationsPerKey = options?.maxOscillationsPerKey ?? 2;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulvar/plan",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.35.0",
|
|
4
4
|
"description": "Rulvar adaptive orchestration extension: PlanRunner, RunLedger, escalation extensions, ModelLadder configuration.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -22,13 +22,13 @@
|
|
|
22
22
|
"access": "public"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@rulvar/core": "1.
|
|
25
|
+
"@rulvar/core": "1.35.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "^22.20.0",
|
|
29
29
|
"tsdown": "^0.22.3",
|
|
30
30
|
"typescript": "~6.0.3",
|
|
31
|
-
"@rulvar/store-sqlite": "1.
|
|
31
|
+
"@rulvar/store-sqlite": "1.35.0"
|
|
32
32
|
},
|
|
33
33
|
"repository": {
|
|
34
34
|
"type": "git",
|