@kernloop/workflows 0.1.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/LICENSE +21 -0
- package/dist/budget.d.ts +111 -0
- package/dist/budget.d.ts.map +1 -0
- package/dist/budget.js +146 -0
- package/dist/budget.js.map +1 -0
- package/dist/checkpoints.d.ts +40 -0
- package/dist/checkpoints.d.ts.map +1 -0
- package/dist/checkpoints.js +92 -0
- package/dist/checkpoints.js.map +1 -0
- package/dist/child-iterate-fixtures.d.ts +36 -0
- package/dist/child-iterate-fixtures.d.ts.map +1 -0
- package/dist/child-iterate-fixtures.js +86 -0
- package/dist/child-iterate-fixtures.js.map +1 -0
- package/dist/child-iterate.d.ts +71 -0
- package/dist/child-iterate.d.ts.map +1 -0
- package/dist/child-iterate.js +61 -0
- package/dist/child-iterate.js.map +1 -0
- package/dist/child-spend.d.ts +41 -0
- package/dist/child-spend.d.ts.map +1 -0
- package/dist/child-spend.js +76 -0
- package/dist/child-spend.js.map +1 -0
- package/dist/config.d.ts +43 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +90 -0
- package/dist/config.js.map +1 -0
- package/dist/engine-errors.d.ts +11 -0
- package/dist/engine-errors.d.ts.map +1 -0
- package/dist/engine-errors.js +23 -0
- package/dist/engine-errors.js.map +1 -0
- package/dist/engine-testkit.d.ts +44 -0
- package/dist/engine-testkit.d.ts.map +1 -0
- package/dist/engine-testkit.js +93 -0
- package/dist/engine-testkit.js.map +1 -0
- package/dist/engine-types.d.ts +78 -0
- package/dist/engine-types.d.ts.map +1 -0
- package/dist/engine-types.js +2 -0
- package/dist/engine-types.js.map +1 -0
- package/dist/engine.d.ts +12 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +262 -0
- package/dist/engine.js.map +1 -0
- package/dist/graph.d.ts +87 -0
- package/dist/graph.d.ts.map +1 -0
- package/dist/graph.js +72 -0
- package/dist/graph.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.d.ts +19 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +41 -0
- package/dist/manifest.js.map +1 -0
- package/dist/state.d.ts +1078 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +151 -0
- package/dist/state.js.map +1 -0
- package/dist/steps.d.ts +77 -0
- package/dist/steps.d.ts.map +1 -0
- package/dist/steps.js +270 -0
- package/dist/steps.js.map +1 -0
- package/dist/verdict-disposition.d.ts +23 -0
- package/dist/verdict-disposition.d.ts.map +1 -0
- package/dist/verdict-disposition.js +28 -0
- package/dist/verdict-disposition.js.map +1 -0
- package/package.json +38 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"child-iterate.d.ts","sourceRoot":"","sources":["../src/child-iterate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGxD,gEAAgE;AAChE,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,CAAC;AAE5D,uFAAuF;AACvF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED;oEACoE;AACpE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;CACnC;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAKtF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,WAAW,EACnB,EAAE,EAAE,MAAM,EACV,YAAY,EAAE,OAAO,GACpB,WAAW,CAMb;AAED,0FAA0F;AAC1F,wBAAgB,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,IAAI,CAEjF;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,QAAQ,EACf,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,SAAS,OAAO,EAAE,GAC3B,IAAI,CAKN;AAED,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,IAAI,CAGrF"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { verdictDisposition } from './verdict-disposition.js';
|
|
2
|
+
/**
|
|
3
|
+
* Whether THIS gate sub-node drives child iteration. Quality always drives.
|
|
4
|
+
* Review drives only when `reviewDrives` is on (the review gate is at enforce)
|
|
5
|
+
* — the honesty guard. Parsimony drives only when `parsimonyDrives` is on (the
|
|
6
|
+
* overlay's `gates.parsimony.intensity` is full/ultra, #9/#415) — at lite/off it
|
|
7
|
+
* is advisory/disabled. Non-driving gates never trigger a re-implement; their
|
|
8
|
+
* findings still fold in as hints (see {@link foldHints}).
|
|
9
|
+
*/
|
|
10
|
+
export function gateDrivesIteration(node, drivers) {
|
|
11
|
+
if (node.gate === 'quality')
|
|
12
|
+
return true;
|
|
13
|
+
if (node.gate === 'review')
|
|
14
|
+
return drivers.reviewDrives;
|
|
15
|
+
if (node.gate === 'parsimony')
|
|
16
|
+
return drivers.parsimonyDrives;
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Decide the branch after a driving gate ran for a child. `pass` advances the
|
|
21
|
+
* sub-chain; `reiterate` re-runs implement (within Kc and budget); `escalate`
|
|
22
|
+
* stops the child at the bound. `withinBudget` is false when a re-entry would
|
|
23
|
+
* exceed the run budget (Part B) — that forces `escalate` before Kc.
|
|
24
|
+
*
|
|
25
|
+
* An `escalate` VERDICT (#192) — the gate ruling "a human must decide" — forces
|
|
26
|
+
* `escalate` IMMEDIATELY, regardless of Kc or budget: a human ruling is not a
|
|
27
|
+
* re-attempt. Routing goes through {@link verdictDisposition} so a future
|
|
28
|
+
* `VerdictResult` value is a compile error here, never a silent mis-branch.
|
|
29
|
+
*/
|
|
30
|
+
export function childBranch(verdict, result, kc, withinBudget) {
|
|
31
|
+
const disposition = verdictDisposition(verdict.result);
|
|
32
|
+
if (disposition === 'advance')
|
|
33
|
+
return 'pass';
|
|
34
|
+
if (disposition === 'escalate')
|
|
35
|
+
return 'escalate';
|
|
36
|
+
if (result.iteration >= kc || !withinBudget)
|
|
37
|
+
return 'escalate';
|
|
38
|
+
return 'reiterate';
|
|
39
|
+
}
|
|
40
|
+
/** Fold a non-driving gate's findings into the child as hints (review → next attempt). */
|
|
41
|
+
export function foldHints(result, findings) {
|
|
42
|
+
result.findings.push(...findings);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Re-enter the child's implement sub-node: fold the driving gate's findings,
|
|
46
|
+
* bump the child iteration, reset the sub-cursor to 0 (implement). Mirrors a
|
|
47
|
+
* rejected vote pushing findings and re-entering plan.
|
|
48
|
+
*/
|
|
49
|
+
export function reiterateChild(state, result, findings) {
|
|
50
|
+
if (state.cursor.phase !== 'fanout')
|
|
51
|
+
return;
|
|
52
|
+
result.findings.push(...findings);
|
|
53
|
+
result.iteration += 1;
|
|
54
|
+
state.cursor = { phase: 'fanout', childIndex: state.cursor.childIndex, sub: 0 };
|
|
55
|
+
}
|
|
56
|
+
/** Mark a child escalated at the bound: record the findings, never re-attempt. */
|
|
57
|
+
export function escalateChild(result, findings) {
|
|
58
|
+
result.findings.push(...findings);
|
|
59
|
+
result.escalated = true;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=child-iterate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"child-iterate.js","sourceRoot":"","sources":["../src/child-iterate.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAoB9D;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAc,EAAE,OAAyB;IAC3E,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACzC,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC,YAAY,CAAC;IACxD,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW;QAAE,OAAO,OAAO,CAAC,eAAe,CAAC;IAC9D,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,WAAW,CACzB,OAAgB,EAChB,MAAmB,EACnB,EAAU,EACV,YAAqB;IAErB,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACvD,IAAI,WAAW,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IAC7C,IAAI,WAAW,KAAK,UAAU;QAAE,OAAO,UAAU,CAAC;IAClD,IAAI,MAAM,CAAC,SAAS,IAAI,EAAE,IAAI,CAAC,YAAY;QAAE,OAAO,UAAU,CAAC;IAC/D,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,SAAS,CAAC,MAAmB,EAAE,QAA4B;IACzE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;AACpC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,KAAe,EACf,MAAmB,EACnB,QAA4B;IAE5B,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,KAAK,QAAQ;QAAE,OAAO;IAC5C,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;IAClC,MAAM,CAAC,SAAS,IAAI,CAAC,CAAC;IACtB,KAAK,CAAC,MAAM,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;AAClF,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,aAAa,CAAC,MAAmB,EAAE,QAA4B;IAC7E,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;IAClC,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-child spend attribution for the fan-out (#56). Because the canonical loop
|
|
3
|
+
* runs children SEQUENTIALLY, the engine slices the run-global meter by the
|
|
4
|
+
* child boundary: snapshot an injected `meteredSpend` readout when it first
|
|
5
|
+
* steps into a child, and the delta to any later point is that child's spend,
|
|
6
|
+
* summed across all its Kc iterations. Pure of I/O — the engine owns the loop;
|
|
7
|
+
* this owns the arithmetic and the per-child budget verdict.
|
|
8
|
+
*/
|
|
9
|
+
import { type BudgetSpend } from './budget.js';
|
|
10
|
+
import type { RunResult, RunState } from './state.js';
|
|
11
|
+
/**
|
|
12
|
+
* Tracks the spend baseline of the child the fan-out is currently running and
|
|
13
|
+
* derives each child's attributed slice from the live meter. Unmetered (no
|
|
14
|
+
* `meteredSpend` seam) → every readout is undefined and nothing is attributed.
|
|
15
|
+
*/
|
|
16
|
+
export declare class ChildSpendTracker {
|
|
17
|
+
private readonly meteredSpend;
|
|
18
|
+
private baseline;
|
|
19
|
+
constructor(meteredSpend: (() => BudgetSpend) | undefined);
|
|
20
|
+
/**
|
|
21
|
+
* Start-of-loop reset: forget the baseline AND drop any pre-resume child spend
|
|
22
|
+
* (#212), so attribution is per-PROCESS — a resumed run re-attributes from the
|
|
23
|
+
* fresh meter and `childSpend` stays within the (also per-process) run cost.
|
|
24
|
+
*/
|
|
25
|
+
reset(state: RunState): void;
|
|
26
|
+
/** Snapshot the meter as child `index`'s baseline the first time it is stepped. */
|
|
27
|
+
ensureBaseline(index: number): void;
|
|
28
|
+
/** Spend attributed to child `index` so far: meter now minus its baseline (≥ 0). */
|
|
29
|
+
delta(index: number): BudgetSpend | undefined;
|
|
30
|
+
/** Record child `index`'s attributed spend onto its result row (#56). */
|
|
31
|
+
attribute(state: RunState, index: number): void;
|
|
32
|
+
/**
|
|
33
|
+
* False when the CURRENT fan-out child has overspent its OWN sliced budget —
|
|
34
|
+
* gating re-iteration in ENFORCE mode only (`enforce` false → never halts
|
|
35
|
+
* per-child, mirroring the run-level discipline). Sibling-independent.
|
|
36
|
+
*/
|
|
37
|
+
withinOwnBudget(enforce: boolean, state: RunState): boolean;
|
|
38
|
+
}
|
|
39
|
+
/** Per-child spend entries for a RunResult, or undefined when none was metered (#56). */
|
|
40
|
+
export declare function childSpends(state: RunState): RunResult['childSpend'];
|
|
41
|
+
//# sourceMappingURL=child-spend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"child-spend.d.ts","sourceRoot":"","sources":["../src/child-spend.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtD;;;;GAIG;AACH,qBAAa,iBAAiB;IAGhB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAFzC,OAAO,CAAC,QAAQ,CAAoD;gBAEvC,YAAY,EAAE,CAAC,MAAM,WAAW,CAAC,GAAG,SAAS;IAE1E;;;;OAIG;IACH,KAAK,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAK5B,mFAAmF;IACnF,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAMnC,oFAAoF;IACpF,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAU7C,yEAAyE;IACzE,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAM/C;;;;OAIG;IACH,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO;CAO5D;AAED,yFAAyF;AACzF,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC,YAAY,CAAC,CAKpE"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-child spend attribution for the fan-out (#56). Because the canonical loop
|
|
3
|
+
* runs children SEQUENTIALLY, the engine slices the run-global meter by the
|
|
4
|
+
* child boundary: snapshot an injected `meteredSpend` readout when it first
|
|
5
|
+
* steps into a child, and the delta to any later point is that child's spend,
|
|
6
|
+
* summed across all its Kc iterations. Pure of I/O — the engine owns the loop;
|
|
7
|
+
* this owns the arithmetic and the per-child budget verdict.
|
|
8
|
+
*/
|
|
9
|
+
import { childOverOwnBudget } from './budget.js';
|
|
10
|
+
/**
|
|
11
|
+
* Tracks the spend baseline of the child the fan-out is currently running and
|
|
12
|
+
* derives each child's attributed slice from the live meter. Unmetered (no
|
|
13
|
+
* `meteredSpend` seam) → every readout is undefined and nothing is attributed.
|
|
14
|
+
*/
|
|
15
|
+
export class ChildSpendTracker {
|
|
16
|
+
meteredSpend;
|
|
17
|
+
baseline;
|
|
18
|
+
constructor(meteredSpend) {
|
|
19
|
+
this.meteredSpend = meteredSpend;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Start-of-loop reset: forget the baseline AND drop any pre-resume child spend
|
|
23
|
+
* (#212), so attribution is per-PROCESS — a resumed run re-attributes from the
|
|
24
|
+
* fresh meter and `childSpend` stays within the (also per-process) run cost.
|
|
25
|
+
*/
|
|
26
|
+
reset(state) {
|
|
27
|
+
this.baseline = undefined;
|
|
28
|
+
for (const r of state.childResults)
|
|
29
|
+
r.spend = undefined;
|
|
30
|
+
}
|
|
31
|
+
/** Snapshot the meter as child `index`'s baseline the first time it is stepped. */
|
|
32
|
+
ensureBaseline(index) {
|
|
33
|
+
const spend = this.meteredSpend?.();
|
|
34
|
+
if (spend === undefined || this.baseline?.index === index)
|
|
35
|
+
return;
|
|
36
|
+
this.baseline = { index, spend };
|
|
37
|
+
}
|
|
38
|
+
/** Spend attributed to child `index` so far: meter now minus its baseline (≥ 0). */
|
|
39
|
+
delta(index) {
|
|
40
|
+
const spend = this.meteredSpend?.();
|
|
41
|
+
if (spend === undefined || this.baseline?.index !== index)
|
|
42
|
+
return undefined;
|
|
43
|
+
const base = this.baseline.spend;
|
|
44
|
+
return {
|
|
45
|
+
tokens: Math.max(0, spend.tokens - base.tokens),
|
|
46
|
+
usd: Math.max(0, spend.usd - base.usd),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** Record child `index`'s attributed spend onto its result row (#56). */
|
|
50
|
+
attribute(state, index) {
|
|
51
|
+
const d = this.delta(index);
|
|
52
|
+
const result = state.childResults[index];
|
|
53
|
+
if (d !== undefined && result !== undefined)
|
|
54
|
+
result.spend = d;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* False when the CURRENT fan-out child has overspent its OWN sliced budget —
|
|
58
|
+
* gating re-iteration in ENFORCE mode only (`enforce` false → never halts
|
|
59
|
+
* per-child, mirroring the run-level discipline). Sibling-independent.
|
|
60
|
+
*/
|
|
61
|
+
withinOwnBudget(enforce, state) {
|
|
62
|
+
if (!enforce || state.cursor.phase !== 'fanout')
|
|
63
|
+
return true;
|
|
64
|
+
const d = this.delta(state.cursor.childIndex);
|
|
65
|
+
const result = state.childResults[state.cursor.childIndex];
|
|
66
|
+
if (d === undefined || result === undefined)
|
|
67
|
+
return true;
|
|
68
|
+
return !childOverOwnBudget(result.child.budget, d);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/** Per-child spend entries for a RunResult, or undefined when none was metered (#56). */
|
|
72
|
+
export function childSpends(state) {
|
|
73
|
+
const entries = state.childResults.flatMap((r) => r.spend === undefined ? [] : [{ childId: r.child.id, spend: r.spend }]);
|
|
74
|
+
return entries.length > 0 ? entries : undefined;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=child-spend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"child-spend.js","sourceRoot":"","sources":["../src/child-spend.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engine configuration schema (spec §6, §8). EngineConfig is the loop-relevant
|
|
3
|
+
* subset of the cli's `OverlaySchema` (`packages/cli/src/overlay.ts`): `K`,
|
|
4
|
+
* `Kc`, `reviewDrivesIteration`, `gates.vote.{strategy,panel}`, and
|
|
5
|
+
* `nodeOverrides` share its field names and value spaces, so the composition
|
|
6
|
+
* root maps `Overlay` → `EngineConfig` field-for-field [CLM-0045]. Kept apart
|
|
7
|
+
* from the engine so neither file outgrows the 400-line budget.
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
/** Engine configuration — see the module docs for the overlay mapping. */
|
|
11
|
+
export declare const EngineConfigSchema: z.ZodPrefault<z.ZodObject<{
|
|
12
|
+
K: z.ZodDefault<z.ZodNumber>;
|
|
13
|
+
Kc: z.ZodDefault<z.ZodNumber>;
|
|
14
|
+
reviewDrivesIteration: z.ZodDefault<z.ZodBoolean>;
|
|
15
|
+
parsimonyDrivesIteration: z.ZodDefault<z.ZodBoolean>;
|
|
16
|
+
budgetHeadroomFraction: z.ZodDefault<z.ZodNumber>;
|
|
17
|
+
gates: z.ZodPrefault<z.ZodObject<{
|
|
18
|
+
vote: z.ZodPrefault<z.ZodObject<{
|
|
19
|
+
strategy: z.ZodDefault<z.ZodEnum<{
|
|
20
|
+
simple_majority: "simple_majority";
|
|
21
|
+
supermajority: "supermajority";
|
|
22
|
+
unanimous: "unanimous";
|
|
23
|
+
}>>;
|
|
24
|
+
panel: z.ZodDefault<z.ZodUnion<readonly [z.ZodLiteral<3>, z.ZodLiteral<7>]>>;
|
|
25
|
+
providerDiverse: z.ZodDefault<z.ZodBoolean>;
|
|
26
|
+
escalateOnNoConsensus: z.ZodDefault<z.ZodBoolean>;
|
|
27
|
+
precisionWeighted: z.ZodDefault<z.ZodBoolean>;
|
|
28
|
+
correlationAware: z.ZodDefault<z.ZodBoolean>;
|
|
29
|
+
correlationForm: z.ZodDefault<z.ZodEnum<{
|
|
30
|
+
sqrt: "sqrt";
|
|
31
|
+
linear: "linear";
|
|
32
|
+
}>>;
|
|
33
|
+
minDistinctClasses: z.ZodOptional<z.ZodNumber>;
|
|
34
|
+
}, z.core.$strict>>;
|
|
35
|
+
}, z.core.$strict>>;
|
|
36
|
+
nodeOverrides: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
37
|
+
gate: z.ZodOptional<z.ZodString>;
|
|
38
|
+
specialists: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
39
|
+
}, z.core.$strict>>>;
|
|
40
|
+
}, z.core.$strict>>;
|
|
41
|
+
export type EngineConfig = z.infer<typeof EngineConfigSchema>;
|
|
42
|
+
export type EngineConfigInput = z.input<typeof EngineConfigSchema>;
|
|
43
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA2CxB,0EAA0E;AAC1E,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBAuChB,CAAC;AAChB,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engine configuration schema (spec §6, §8). EngineConfig is the loop-relevant
|
|
3
|
+
* subset of the cli's `OverlaySchema` (`packages/cli/src/overlay.ts`): `K`,
|
|
4
|
+
* `Kc`, `reviewDrivesIteration`, `gates.vote.{strategy,panel}`, and
|
|
5
|
+
* `nodeOverrides` share its field names and value spaces, so the composition
|
|
6
|
+
* root maps `Overlay` → `EngineConfig` field-for-field [CLM-0045]. Kept apart
|
|
7
|
+
* from the engine so neither file outgrows the 400-line budget.
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
/** Vote strategies in use (mirrors the cli overlay's VOTE_STRATEGIES). */
|
|
11
|
+
const VoteConfigSchema = z.strictObject({
|
|
12
|
+
strategy: z.enum(['simple_majority', 'supermajority', 'unanimous']).default('simple_majority'),
|
|
13
|
+
panel: z.union([z.literal(3), z.literal(7)]).default(3),
|
|
14
|
+
/** Opt-in PROVIDER-DIVERSE panel-7 voting (#369). Default FALSE (#461): a live
|
|
15
|
+
* experiment found 3 independent model families gave identical verdicts to a
|
|
16
|
+
* single strong model on every test proposal — the adversarial ROLES carry the
|
|
17
|
+
* signal, so a panel-7 ratification vote runs roles-on-the-run-adapter by default
|
|
18
|
+
* (one model, N personas) and does not require ≥2 authed adapters. Set true to
|
|
19
|
+
* route voters across the overlay's distinct CLI adapters for genuine model
|
|
20
|
+
* independence (the #405 distinct-class quorum + diversity findings then engage);
|
|
21
|
+
* off ⇒ no served identities, so the quorum/findings are inert. */
|
|
22
|
+
providerDiverse: z.boolean().default(false),
|
|
23
|
+
/** Opt-in ASK (#192): a deadlocked panel emits `escalate` → the loop halts as
|
|
24
|
+
* escalated for a human, instead of auto-rejecting. Default off (byte-identical).
|
|
25
|
+
* Liveness tradeoff (#364): in an UNATTENDED loop there is no "next interaction",
|
|
26
|
+
* so `escalate` halts indefinitely — keep off for autonomous runs. */
|
|
27
|
+
escalateOnNoConsensus: z.boolean().default(false),
|
|
28
|
+
/** Opt-in precision-weighted voting (#369 Inc3): weight each ballot by the
|
|
29
|
+
* voter's measured calibration. Default off (byte-identical). */
|
|
30
|
+
precisionWeighted: z.boolean().default(false),
|
|
31
|
+
/** Opt-in correlation-aware aggregation (#369 Inc4): downweight voters that share
|
|
32
|
+
* a served model class by `correlationDiscount(form, K)`. Default off (byte-identical);
|
|
33
|
+
* inert on a single-adapter panel. Mirrors the cli overlay's VoteGateSchema. */
|
|
34
|
+
correlationAware: z.boolean().default(false),
|
|
35
|
+
/** The `correlationAware` discount form (#369 Inc4): `sqrt` ⇒ 1/√K, `linear` ⇒ 1/K. */
|
|
36
|
+
correlationForm: z.enum(['sqrt', 'linear']).default('sqrt'),
|
|
37
|
+
/** Distinct-class independence quorum (#405/#369 Inc5b): require ≥ this many distinct
|
|
38
|
+
* served model classes on a diverse panel else the vote ESCALATES to a human instead
|
|
39
|
+
* of ruling. Absent ⇒ defaults to 2 for a panel-7 RATIFICATION vote (the human-ratified
|
|
40
|
+
* default-on), off for a panel-3 loop vote; set to 1 to disable it on a ratification
|
|
41
|
+
* panel. Inert on a single-adapter / endpoint-only panel (no served identities). */
|
|
42
|
+
minDistinctClasses: z.number().int().min(0).optional(),
|
|
43
|
+
});
|
|
44
|
+
/** One node override (mirrors the cli overlay's NodeOverrideSchema). */
|
|
45
|
+
const NodeOverrideSchema = z.strictObject({
|
|
46
|
+
gate: z.string().min(1).optional(),
|
|
47
|
+
specialists: z.array(z.string().min(1)).optional(),
|
|
48
|
+
});
|
|
49
|
+
/** Engine configuration — see the module docs for the overlay mapping. */
|
|
50
|
+
export const EngineConfigSchema = z
|
|
51
|
+
.strictObject({
|
|
52
|
+
/** Vote-iterate bound: at most K rejected re-entries into plan (spec §6). */
|
|
53
|
+
K: z.number().int().min(1).default(3),
|
|
54
|
+
/**
|
|
55
|
+
* Child-iterate bound [CLM-0043]: at most Kc re-runs of a child's
|
|
56
|
+
* implement on a quality reject before the child escalates (spec §6, §8).
|
|
57
|
+
* Bounds child iteration in BOTH budget modes — unlimited budget is not
|
|
58
|
+
* unlimited iterations; raising Kc is how an overlay allows more.
|
|
59
|
+
*/
|
|
60
|
+
Kc: z.number().int().min(1).default(3),
|
|
61
|
+
/**
|
|
62
|
+
* Honesty guard (CLM-0064): the review gate is advisory and does NOT drive
|
|
63
|
+
* child iteration. Default off; an overlay flips it on only when the review
|
|
64
|
+
* gate is promoted to enforce. We never claim review enforces iteration.
|
|
65
|
+
*/
|
|
66
|
+
reviewDrivesIteration: z.boolean().default(false),
|
|
67
|
+
/**
|
|
68
|
+
* Does the parsimony gate drive child re-iteration this run (#9/#415)? The
|
|
69
|
+
* CLI computes this from the overlay's `gates.parsimony.intensity`: true at
|
|
70
|
+
* `full`/`ultra` (a rejecting parsimony verdict re-runs implement within Kc),
|
|
71
|
+
* false at `lite`/`off` (advisory or disabled). Default false ⇒ a fresh
|
|
72
|
+
* EngineConfig is byte-identical (the engine never drives parsimony unless the
|
|
73
|
+
* mapping flips it). The INTENSITY itself lives in the cli Overlay
|
|
74
|
+
* (`gates.parsimony`) and reaches the executor via `kern.config`; only this
|
|
75
|
+
* derived drive-flag the engine needs is mirrored here [CLM-0045].
|
|
76
|
+
*/
|
|
77
|
+
parsimonyDrivesIteration: z.boolean().default(false),
|
|
78
|
+
/**
|
|
79
|
+
* Pre-node budget reserve floor as a FRACTION of the limit (#342): the
|
|
80
|
+
* pre-node guard halts before a node when remaining < max(this × limit,
|
|
81
|
+
* largest-node-seen). The floor covers COLD START (the first node, before any
|
|
82
|
+
* spend is observed). Default 0 — observed-max still caps steady-state
|
|
83
|
+
* overshoot; an overlay raises this to also bound the first node.
|
|
84
|
+
*/
|
|
85
|
+
budgetHeadroomFraction: z.number().min(0).max(1).default(0),
|
|
86
|
+
gates: z.strictObject({ vote: VoteConfigSchema.prefault({}) }).prefault({}),
|
|
87
|
+
nodeOverrides: z.record(z.string().min(1), NodeOverrideSchema).default({}),
|
|
88
|
+
})
|
|
89
|
+
.prefault({});
|
|
90
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engine error classification (split from engine.ts to keep it under the LOC
|
|
3
|
+
* budget, #58): the "kill" path vs an executor failure. Pure helpers the loop
|
|
4
|
+
* calls when a node throws.
|
|
5
|
+
*/
|
|
6
|
+
import { WorkflowError } from './state.js';
|
|
7
|
+
/** True for AbortError throws and fired signals — the "kill" path [CLM-0044]. */
|
|
8
|
+
export declare function isAbort(error: unknown, signal?: AbortSignal): boolean;
|
|
9
|
+
/** Wrap a non-engine throw in a typed WorkflowError. */
|
|
10
|
+
export declare function asWorkflowError(error: unknown, node: string, signal?: AbortSignal): WorkflowError;
|
|
11
|
+
//# sourceMappingURL=engine-errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-errors.d.ts","sourceRoot":"","sources":["../src/engine-errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,iFAAiF;AACjF,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAErE;AAED,wDAAwD;AACxD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,aAAa,CASjG"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engine error classification (split from engine.ts to keep it under the LOC
|
|
3
|
+
* budget, #58): the "kill" path vs an executor failure. Pure helpers the loop
|
|
4
|
+
* calls when a node throws.
|
|
5
|
+
*/
|
|
6
|
+
import { WorkflowError } from './state.js';
|
|
7
|
+
/** True for AbortError throws and fired signals — the "kill" path [CLM-0044]. */
|
|
8
|
+
export function isAbort(error, signal) {
|
|
9
|
+
return signal?.aborted === true || (error instanceof Error && error.name === 'AbortError');
|
|
10
|
+
}
|
|
11
|
+
/** Wrap a non-engine throw in a typed WorkflowError. */
|
|
12
|
+
export function asWorkflowError(error, node, signal) {
|
|
13
|
+
if (error instanceof WorkflowError)
|
|
14
|
+
return error;
|
|
15
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
16
|
+
return isAbort(error, signal)
|
|
17
|
+
? new WorkflowError('aborted', `run aborted at node "${node}": ${message}`, { node })
|
|
18
|
+
: new WorkflowError('executor_failed', `node "${node}" failed: ${message}`, {
|
|
19
|
+
node,
|
|
20
|
+
cause: error,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=engine-errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-errors.js","sourceRoot":"","sources":["../src/engine-errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,iFAAiF;AACjF,MAAM,UAAU,OAAO,CAAC,KAAc,EAAE,MAAoB;IAC1D,OAAO,MAAM,EAAE,OAAO,KAAK,IAAI,IAAI,CAAC,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;AAC7F,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,eAAe,CAAC,KAAc,EAAE,IAAY,EAAE,MAAoB;IAChF,IAAI,KAAK,YAAY,aAAa;QAAE,OAAO,KAAK,CAAC;IACjD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC;QAC3B,CAAC,CAAC,IAAI,aAAa,CAAC,SAAS,EAAE,wBAAwB,IAAI,MAAM,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QACrF,CAAC,CAAC,IAAI,aAAa,CAAC,iBAAiB,EAAE,SAAS,IAAI,aAAa,OAAO,EAAE,EAAE;YACxE,IAAI;YACJ,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;AACT,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared scripted-executor harness for the engine tests (child iteration,
|
|
3
|
+
* budget, per-child spend). A deterministic stand-in for the real faculties:
|
|
4
|
+
* every node returns a canned contract so a test drives the loop's CONTROL
|
|
5
|
+
* flow (re-iterate, escalate, attribute) without any model call. Not test code
|
|
6
|
+
* itself — it carries no `describe`/`it`; the `.test.ts` files import it.
|
|
7
|
+
*/
|
|
8
|
+
import type { Brief, Finding, Outcome, TaskContract, Verdict } from '@kernloop/contracts';
|
|
9
|
+
import type { NodeContext, NodeExecutor } from './engine.js';
|
|
10
|
+
/** The root task every engine test decomposes. */
|
|
11
|
+
export declare const task: TaskContract;
|
|
12
|
+
/** A scripted compiler Brief for `taskId`. */
|
|
13
|
+
export declare const brief: (taskId: string) => Brief;
|
|
14
|
+
/** A scripted gate Verdict; a non-pass result carries one finding to fold. */
|
|
15
|
+
export declare const verdict: (taskId: string, gate: string, result: Verdict["result"]) => Verdict;
|
|
16
|
+
/** A scripted success Outcome for `taskId`. */
|
|
17
|
+
export declare const outcome: (taskId: string) => Outcome;
|
|
18
|
+
/** Render a trace as `node[:childId]` labels for order assertions. */
|
|
19
|
+
export declare const names: (trace: readonly {
|
|
20
|
+
node: string;
|
|
21
|
+
childId?: string;
|
|
22
|
+
}[]) => string[];
|
|
23
|
+
/**
|
|
24
|
+
* A scripted executor set. `qualityByChild` maps a child id to the sequence of
|
|
25
|
+
* quality results it returns (last entry repeats). Records every implement's
|
|
26
|
+
* NodeContext so tests can assert the folded child findings + childIteration.
|
|
27
|
+
*/
|
|
28
|
+
export declare function scripted(qualityByChild?: Record<string, Array<Verdict['result']>>): {
|
|
29
|
+
executors: Record<string, NodeExecutor>;
|
|
30
|
+
qualityCalls: Record<string, number>;
|
|
31
|
+
implementCtx: {
|
|
32
|
+
childId: string;
|
|
33
|
+
iteration: number;
|
|
34
|
+
findings: readonly Finding[];
|
|
35
|
+
}[];
|
|
36
|
+
};
|
|
37
|
+
/** Wrap executors to count calls per node name. */
|
|
38
|
+
export declare function counted(executors: Record<string, NodeExecutor>): {
|
|
39
|
+
executors: {
|
|
40
|
+
[k: string]: (input: unknown, ctx: NodeContext) => Promise<unknown>;
|
|
41
|
+
};
|
|
42
|
+
calls: Record<string, number>;
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=engine-testkit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-testkit.d.ts","sourceRoot":"","sources":["../src/engine-testkit.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC1F,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE7D,kDAAkD;AAClD,eAAO,MAAM,IAAI,EAAE,YASlB,CAAC;AAEF,8CAA8C;AAC9C,eAAO,MAAM,KAAK,GAAI,QAAQ,MAAM,KAAG,KAKrC,CAAC;AAEH,8EAA8E;AAC9E,eAAO,MAAM,OAAO,GAAI,QAAQ,MAAM,EAAE,MAAM,MAAM,EAAE,QAAQ,OAAO,CAAC,QAAQ,CAAC,KAAG,OAUhF,CAAC;AAEH,+CAA+C;AAC/C,eAAO,MAAM,OAAO,GAAI,QAAQ,MAAM,KAAG,OAOvC,CAAC;AAEH,sEAAsE;AACtE,eAAO,MAAM,KAAK,GAAI,OAAO,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,KAAG,MAAM,EACF,CAAC;AAElF;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,cAAc,GAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAM;;;;iBAE/C,MAAM;mBAAa,MAAM;kBAAY,SAAS,OAAO,EAAE;;EAmC7F;AAED,mDAAmD;AACnD,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC;;6BAKjD,OAAO,OAAO,WAAW;;;EAOtC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/** The root task every engine test decomposes. */
|
|
2
|
+
export const task = {
|
|
3
|
+
id: 'task-1',
|
|
4
|
+
goal: 'ship the feature',
|
|
5
|
+
constraints: [],
|
|
6
|
+
budget: { tokens: 1000, usd: 1, wallClockMin: 10 },
|
|
7
|
+
evidence: [],
|
|
8
|
+
definitionOfDone: [],
|
|
9
|
+
authorityCeiling: 'suggest',
|
|
10
|
+
overlay: 'repo',
|
|
11
|
+
};
|
|
12
|
+
/** A scripted compiler Brief for `taskId`. */
|
|
13
|
+
export const brief = (taskId) => ({
|
|
14
|
+
taskId,
|
|
15
|
+
sections: [],
|
|
16
|
+
budget: { allotted: 10, used: 0 },
|
|
17
|
+
compilerVersion: 'scripted-1',
|
|
18
|
+
});
|
|
19
|
+
/** A scripted gate Verdict; a non-pass result carries one finding to fold. */
|
|
20
|
+
export const verdict = (taskId, gate, result) => ({
|
|
21
|
+
taskId,
|
|
22
|
+
gate,
|
|
23
|
+
result,
|
|
24
|
+
confidence: 1,
|
|
25
|
+
findings: result === 'approve' || result === 'pass'
|
|
26
|
+
? []
|
|
27
|
+
: [{ severity: 'error', message: `${gate} wants ${taskId} fixed` }],
|
|
28
|
+
cost: { tokens: 0, usd: 0 },
|
|
29
|
+
});
|
|
30
|
+
/** A scripted success Outcome for `taskId`. */
|
|
31
|
+
export const outcome = (taskId) => ({
|
|
32
|
+
taskId,
|
|
33
|
+
status: 'success',
|
|
34
|
+
signals: [],
|
|
35
|
+
cost: { tokens: 0, usd: 0 },
|
|
36
|
+
traceRef: `trace-${taskId}`,
|
|
37
|
+
distillCandidates: [],
|
|
38
|
+
});
|
|
39
|
+
/** Render a trace as `node[:childId]` labels for order assertions. */
|
|
40
|
+
export const names = (trace) => trace.map((t) => (t.childId === undefined ? t.node : `${t.node}:${t.childId}`));
|
|
41
|
+
/**
|
|
42
|
+
* A scripted executor set. `qualityByChild` maps a child id to the sequence of
|
|
43
|
+
* quality results it returns (last entry repeats). Records every implement's
|
|
44
|
+
* NodeContext so tests can assert the folded child findings + childIteration.
|
|
45
|
+
*/
|
|
46
|
+
export function scripted(qualityByChild = {}) {
|
|
47
|
+
const qualityCalls = {};
|
|
48
|
+
const implementCtx = [];
|
|
49
|
+
const executors = {
|
|
50
|
+
frame: () => Promise.resolve(task),
|
|
51
|
+
research: () => Promise.resolve(brief(task.id)),
|
|
52
|
+
plan: () => Promise.resolve(brief(task.id)),
|
|
53
|
+
vote: (_i, ctx) => Promise.resolve(verdict(ctx.taskId, 'vote', 'approve')),
|
|
54
|
+
decompose: () => Promise.resolve([
|
|
55
|
+
{ ...task, id: `${task.id}.c1`, parent: task.id },
|
|
56
|
+
{ ...task, id: `${task.id}.c2`, parent: task.id },
|
|
57
|
+
]),
|
|
58
|
+
implement: (input, ctx) => {
|
|
59
|
+
const c = input;
|
|
60
|
+
implementCtx.push({
|
|
61
|
+
childId: c.id,
|
|
62
|
+
iteration: ctx.childIteration ?? -1,
|
|
63
|
+
findings: ctx.findings,
|
|
64
|
+
});
|
|
65
|
+
return Promise.resolve(outcome(c.id));
|
|
66
|
+
},
|
|
67
|
+
quality: (_i, ctx) => {
|
|
68
|
+
const id = ctx.child?.id ?? ctx.taskId;
|
|
69
|
+
const seq = qualityByChild[id] ?? ['pass'];
|
|
70
|
+
const n = qualityCalls[id] ?? 0;
|
|
71
|
+
qualityCalls[id] = n + 1;
|
|
72
|
+
return Promise.resolve(verdict(id, 'quality', seq[Math.min(n, seq.length - 1)] ?? 'pass'));
|
|
73
|
+
},
|
|
74
|
+
review: (_i, ctx) => Promise.resolve(verdict(ctx.child?.id ?? ctx.taskId, 'review', 'approve')),
|
|
75
|
+
parsimony: (_i, ctx) => Promise.resolve(verdict(ctx.child?.id ?? ctx.taskId, 'parsimony', 'pass')),
|
|
76
|
+
integrate: () => Promise.resolve(outcome(task.id)),
|
|
77
|
+
retrospect: (input) => Promise.resolve(input),
|
|
78
|
+
};
|
|
79
|
+
return { executors, qualityCalls, implementCtx };
|
|
80
|
+
}
|
|
81
|
+
/** Wrap executors to count calls per node name. */
|
|
82
|
+
export function counted(executors) {
|
|
83
|
+
const calls = {};
|
|
84
|
+
const wrapped = Object.fromEntries(Object.entries(executors).map(([key, fn]) => [
|
|
85
|
+
key,
|
|
86
|
+
(input, ctx) => {
|
|
87
|
+
calls[key] = (calls[key] ?? 0) + 1;
|
|
88
|
+
return fn(input, ctx);
|
|
89
|
+
},
|
|
90
|
+
]));
|
|
91
|
+
return { executors: wrapped, calls };
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=engine-testkit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-testkit.js","sourceRoot":"","sources":["../src/engine-testkit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The execution engine's public type surface — the contracts a caller of
|
|
3
|
+
* `createEngine` touches: the per-node {@link NodeContext}, the injected
|
|
4
|
+
* {@link NodeExecutor}, the {@link EngineDeps} bag, {@link RunOptions}, and the
|
|
5
|
+
* {@link Engine} interface itself. Split out of engine.ts to keep that file under
|
|
6
|
+
* the 400-line ceiling (#58); engine.ts re-exports every name here, so consumers
|
|
7
|
+
* still import from `./engine.js` (or `@kernloop/workflows`) unchanged.
|
|
8
|
+
*/
|
|
9
|
+
import type { Finding, TaskContract } from '@kernloop/contracts';
|
|
10
|
+
import type { CheckpointStore } from './checkpoints.js';
|
|
11
|
+
import type { RunResult } from './state.js';
|
|
12
|
+
import type { BudgetGuard, BudgetSpend } from './budget.js';
|
|
13
|
+
import type { ChildIterateEvent } from './child-iterate.js';
|
|
14
|
+
import type { EngineConfig, EngineConfigInput } from './config.js';
|
|
15
|
+
/** Per-invocation context handed to every node executor. */
|
|
16
|
+
export interface NodeContext {
|
|
17
|
+
readonly runId: string;
|
|
18
|
+
readonly taskId: string;
|
|
19
|
+
/** Vote-iterate cycle count: 0 on first entry, +1 per rejected re-entry. */
|
|
20
|
+
readonly iteration: number;
|
|
21
|
+
readonly config: EngineConfig;
|
|
22
|
+
/** The node being executed (resolved gate executors see the gate node). */
|
|
23
|
+
readonly node: string;
|
|
24
|
+
/**
|
|
25
|
+
* Findings the executing node must address: the run-level vote-iterate
|
|
26
|
+
* findings on the main chain; inside the fan-out the CHILD's accumulated gate
|
|
27
|
+
* findings — what the re-running coder must fix [CLM-0043].
|
|
28
|
+
*/
|
|
29
|
+
readonly findings: readonly Finding[];
|
|
30
|
+
/** The child contract, inside the fan-out sub-chain. */
|
|
31
|
+
readonly child?: TaskContract;
|
|
32
|
+
/** This child's actor-critic iteration (0 on first implement), inside the fan-out. */
|
|
33
|
+
readonly childIteration?: number;
|
|
34
|
+
readonly signal?: AbortSignal;
|
|
35
|
+
}
|
|
36
|
+
/** An injected unit of work: consumes the edge value, emits the declared contract. */
|
|
37
|
+
export type NodeExecutor = (input: unknown, ctx: NodeContext) => Promise<unknown>;
|
|
38
|
+
/** What `createEngine` needs. Executors are keyed by node name, node kind, or gate name. */
|
|
39
|
+
export interface EngineDeps {
|
|
40
|
+
readonly executors: Readonly<Record<string, NodeExecutor>>;
|
|
41
|
+
readonly checkpoints: CheckpointStore;
|
|
42
|
+
readonly config?: EngineConfigInput;
|
|
43
|
+
/**
|
|
44
|
+
* Runtime budget guard (spec §8) [CLM-0077]. Absent → no budget enforcement
|
|
45
|
+
* (Kc still bounds child iteration). In `enforce` mode the run escalates when
|
|
46
|
+
* metered spend exceeds the parent budget; `unlimited` never halts but spend
|
|
47
|
+
* is still tracked. Injected by the CLI from the mode + parent budget + live
|
|
48
|
+
* `totals`; workflows imports no kernel, so `spent()` is a plain seam.
|
|
49
|
+
*/
|
|
50
|
+
readonly budget?: BudgetGuard;
|
|
51
|
+
/**
|
|
52
|
+
* Always-on metered-spend readout for PER-CHILD attribution (#56) — the raw
|
|
53
|
+
* run-global meter the engine snapshots at each child boundary to slice spend
|
|
54
|
+
* per child (see {@link ChildSpendTracker}), in BOTH budget modes. Absent → no
|
|
55
|
+
* per-child attribution or halt. The CLI wires it to the budget guard's
|
|
56
|
+
* `totals`; workflows imports no kernel, so this is a plain seam.
|
|
57
|
+
*/
|
|
58
|
+
readonly meteredSpend?: () => BudgetSpend;
|
|
59
|
+
/**
|
|
60
|
+
* Audit hook fired on each child re-iteration [CLM-0043] — the CLI appends a
|
|
61
|
+
* `loop.child.iterate` event to the hash chain so the refine history is
|
|
62
|
+
* recorded (the Observer can later read iterations-to-pass as fitness).
|
|
63
|
+
*/
|
|
64
|
+
readonly onChildIterate?: (event: ChildIterateEvent) => void;
|
|
65
|
+
}
|
|
66
|
+
/** Per-run options. */
|
|
67
|
+
export interface RunOptions {
|
|
68
|
+
/** Caller-chosen run id (defaults to a UUID). */
|
|
69
|
+
readonly runId?: string;
|
|
70
|
+
/** Abort signal: an aborted run halts mid-node, last checkpoint intact. */
|
|
71
|
+
readonly signal?: AbortSignal;
|
|
72
|
+
}
|
|
73
|
+
/** The engine: run the canonical loop, or resume a checkpointed run. */
|
|
74
|
+
export interface Engine {
|
|
75
|
+
run(task: TaskContract, options?: RunOptions): Promise<RunResult>;
|
|
76
|
+
resume(runId: string, options?: Pick<RunOptions, 'signal'>): Promise<RunResult>;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=engine-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-types.d.ts","sourceRoot":"","sources":["../src/engine-types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEnE,4DAA4D;AAC5D,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IACtC,wDAAwD;IACxD,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC;IAC9B,sFAAsF;IACtF,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC/B;AAED,sFAAsF;AACtF,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAElF,4FAA4F;AAC5F,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IAC3D,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC;IACtC,QAAQ,CAAC,MAAM,CAAC,EAAE,iBAAiB,CAAC;IACpC;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,WAAW,CAAC;IAC1C;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;CAC9D;AAED,uBAAuB;AACvB,MAAM,WAAW,UAAU;IACzB,iDAAiD;IACjD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC/B;AAED,wEAAwE;AACxE,MAAM,WAAW,MAAM;IACrB,GAAG,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAClE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;CACjF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-types.js","sourceRoot":"","sources":["../src/engine-types.ts"],"names":[],"mappings":""}
|