@miller-tech/uap 1.59.0 → 1.61.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/.tsbuildinfo +1 -1
- package/dist/benchmarks/paired/adapter.d.ts.map +1 -1
- package/dist/benchmarks/paired/adapter.js +14 -1
- package/dist/benchmarks/paired/adapter.js.map +1 -1
- package/dist/benchmarks/paired/scaffold.d.ts.map +1 -1
- package/dist/benchmarks/paired/scaffold.js +6 -1
- package/dist/benchmarks/paired/scaffold.js.map +1 -1
- package/dist/bin/cli.js +58 -0
- package/dist/bin/cli.js.map +1 -1
- package/dist/cli/deliver.d.ts +33 -0
- package/dist/cli/deliver.d.ts.map +1 -1
- package/dist/cli/deliver.js +90 -7
- package/dist/cli/deliver.js.map +1 -1
- package/dist/cli/self-harness.d.ts +36 -0
- package/dist/cli/self-harness.d.ts.map +1 -0
- package/dist/cli/self-harness.js +213 -0
- package/dist/cli/self-harness.js.map +1 -0
- package/dist/mcp-router/executor/client.d.ts.map +1 -1
- package/dist/mcp-router/executor/client.js +16 -2
- package/dist/mcp-router/executor/client.js.map +1 -1
- package/dist/mcp-router/output-compressor.d.ts.map +1 -1
- package/dist/mcp-router/output-compressor.js +51 -0
- package/dist/mcp-router/output-compressor.js.map +1 -1
- package/dist/self-harness/decide.d.ts +41 -0
- package/dist/self-harness/decide.d.ts.map +1 -0
- package/dist/self-harness/decide.js +69 -0
- package/dist/self-harness/decide.js.map +1 -0
- package/dist/self-harness/index.d.ts +23 -0
- package/dist/self-harness/index.d.ts.map +1 -0
- package/dist/self-harness/index.js +23 -0
- package/dist/self-harness/index.js.map +1 -0
- package/dist/self-harness/middleware/path-normalizer.d.ts +53 -0
- package/dist/self-harness/middleware/path-normalizer.d.ts.map +1 -0
- package/dist/self-harness/middleware/path-normalizer.js +116 -0
- package/dist/self-harness/middleware/path-normalizer.js.map +1 -0
- package/dist/self-harness/mine.d.ts +25 -0
- package/dist/self-harness/mine.d.ts.map +1 -0
- package/dist/self-harness/mine.js +78 -0
- package/dist/self-harness/mine.js.map +1 -0
- package/dist/self-harness/mods.d.ts +136 -0
- package/dist/self-harness/mods.d.ts.map +1 -0
- package/dist/self-harness/mods.js +152 -0
- package/dist/self-harness/mods.js.map +1 -0
- package/dist/self-harness/orchestrator.d.ts +61 -0
- package/dist/self-harness/orchestrator.d.ts.map +1 -0
- package/dist/self-harness/orchestrator.js +110 -0
- package/dist/self-harness/orchestrator.js.map +1 -0
- package/dist/self-harness/pending.d.ts +57 -0
- package/dist/self-harness/pending.d.ts.map +1 -0
- package/dist/self-harness/pending.js +86 -0
- package/dist/self-harness/pending.js.map +1 -0
- package/dist/self-harness/profile.d.ts +38 -0
- package/dist/self-harness/profile.d.ts.map +1 -0
- package/dist/self-harness/profile.js +80 -0
- package/dist/self-harness/profile.js.map +1 -0
- package/dist/self-harness/propose.d.ts +25 -0
- package/dist/self-harness/propose.d.ts.map +1 -0
- package/dist/self-harness/propose.js +86 -0
- package/dist/self-harness/propose.js.map +1 -0
- package/dist/self-harness/trace-mine.d.ts +39 -0
- package/dist/self-harness/trace-mine.d.ts.map +1 -0
- package/dist/self-harness/trace-mine.js +109 -0
- package/dist/self-harness/trace-mine.js.map +1 -0
- package/dist/self-harness/transfer.d.ts +99 -0
- package/dist/self-harness/transfer.d.ts.map +1 -0
- package/dist/self-harness/transfer.js +140 -0
- package/dist/self-harness/transfer.js.map +1 -0
- package/dist/self-harness/weakness.d.ts +56 -0
- package/dist/self-harness/weakness.d.ts.map +1 -0
- package/dist/self-harness/weakness.js +0 -0
- package/dist/self-harness/weakness.js.map +1 -0
- package/dist/tasks/coordination.d.ts.map +1 -1
- package/dist/tasks/coordination.js +9 -7
- package/dist/tasks/coordination.js.map +1 -1
- package/dist/tasks/service.d.ts +10 -0
- package/dist/tasks/service.d.ts.map +1 -1
- package/dist/tasks/service.js +41 -5
- package/dist/tasks/service.js.map +1 -1
- package/docs/INDEX.md +1 -0
- package/docs/design/SELF_HARNESS.md +206 -0
- package/package.json +1 -1
- package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
- package/tools/agents/scripts/anthropic_proxy.py +160 -18
- package/tools/agents/scripts/toolcall_path_normalizer.py +140 -0
- package/tools/agents/tests/test_anthropic_proxy_streaming.py +93 -2
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-Harness — Stage 1 weakness mining from paired-bench run records.
|
|
3
|
+
*
|
|
4
|
+
* P1 mines from the structured `RunRecord`s the paired bench already produces
|
|
5
|
+
* (correct, error, latency, turns) — a HALO-trace miner is additive (P3). Each
|
|
6
|
+
* failing record is classified into a `FailureKind`; classifications aggregate
|
|
7
|
+
* into ranked `WeaknessReport`s keyed by a stable signature. Pure + testable.
|
|
8
|
+
*/
|
|
9
|
+
import { signatureHash, rankWeaknesses, } from './weakness.js';
|
|
10
|
+
/**
|
|
11
|
+
* Classify a single run's failure into a FailureKind, or null if it succeeded.
|
|
12
|
+
* Heuristics are derived from the observed Qwen3.6-A3B failure modes
|
|
13
|
+
* (see memory project_uap_paired_bench): timeout vs verify-fail vs runaway etc.
|
|
14
|
+
*/
|
|
15
|
+
export function classifyFailure(rec) {
|
|
16
|
+
if (rec.metrics.correct)
|
|
17
|
+
return null;
|
|
18
|
+
const err = (rec.metrics.error ?? '').toLowerCase();
|
|
19
|
+
if (err.includes('timed out') || err.includes('timeout'))
|
|
20
|
+
return 'agent.timeout';
|
|
21
|
+
if (err.includes('verify failed')) {
|
|
22
|
+
// A verify failure with very high turns is a non-termination/garble loop;
|
|
23
|
+
// otherwise it's a plain wrong answer.
|
|
24
|
+
if ((rec.metrics.turns ?? 0) >= 40)
|
|
25
|
+
return 'loop.nonterminate';
|
|
26
|
+
return 'verify.fail';
|
|
27
|
+
}
|
|
28
|
+
if (err.includes('exit') || err.includes('spawn'))
|
|
29
|
+
return 'agent.error';
|
|
30
|
+
// Fell through with no error but incorrect → treat as a wrong answer.
|
|
31
|
+
return 'verify.fail';
|
|
32
|
+
}
|
|
33
|
+
/** Mine ranked weaknesses from a set of paired-bench run records. */
|
|
34
|
+
export function mineFromRecords(records, opts) {
|
|
35
|
+
const minFreq = opts.minFrequency ?? 1;
|
|
36
|
+
const byKind = new Map();
|
|
37
|
+
for (const rec of records) {
|
|
38
|
+
const kind = classifyFailure(rec);
|
|
39
|
+
if (!kind)
|
|
40
|
+
continue;
|
|
41
|
+
let agg = byKind.get(kind);
|
|
42
|
+
if (!agg) {
|
|
43
|
+
agg = { tasks: new Set(), evidence: [], count: 0 };
|
|
44
|
+
byKind.set(kind, agg);
|
|
45
|
+
}
|
|
46
|
+
agg.count += 1;
|
|
47
|
+
agg.tasks.add(rec.taskId);
|
|
48
|
+
if (agg.evidence.length < 5) {
|
|
49
|
+
agg.evidence.push(`${rec.taskId}#${rec.seed} ${rec.condition}: ${rec.metrics.error ?? 'incorrect'}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const reports = [];
|
|
53
|
+
for (const [kind, agg] of byKind) {
|
|
54
|
+
if (agg.count < minFreq)
|
|
55
|
+
continue;
|
|
56
|
+
reports.push({
|
|
57
|
+
signature: signatureHash({ kind, model: opts.model }),
|
|
58
|
+
kind,
|
|
59
|
+
model: opts.model,
|
|
60
|
+
frequency: agg.count,
|
|
61
|
+
affectedTasks: [...agg.tasks],
|
|
62
|
+
hypothesis: HYPOTHESIS[kind],
|
|
63
|
+
evidence: agg.evidence,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return rankWeaknesses(reports);
|
|
67
|
+
}
|
|
68
|
+
const HYPOTHESIS = {
|
|
69
|
+
'toolcall.path.garbled': 'The model mangles tool-call file paths (case/extension/stray dirs) and never lands a correct edit.',
|
|
70
|
+
'toolcall.args.truncated': 'Tool-call arguments are cut off mid-value, producing empty/partial writes.',
|
|
71
|
+
'gen.runaway.npredict': 'A single turn generates up to the n-predict cap, consuming the wall-clock budget.',
|
|
72
|
+
'loop.nonterminate': 'The agent keeps emitting tool calls without converging on a terminal answer.',
|
|
73
|
+
'guardrail.poison.recon': 'A guardrail (recon-convergence) wedged tool access across requests.',
|
|
74
|
+
'verify.fail': 'The agent terminates and submits, but the deterministic verifier rejects the answer.',
|
|
75
|
+
'agent.timeout': 'The agent exceeded its wall-clock budget without producing a verifiable result.',
|
|
76
|
+
'agent.error': 'The agent process exited non-zero or failed to spawn.',
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=mine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mine.js","sourceRoot":"","sources":["../../src/self-harness/mine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-Harness — the Modification ("Mod") DSL.
|
|
3
|
+
*
|
|
4
|
+
* The autonomous proposer may ONLY emit values of the `Mod` union below — never
|
|
5
|
+
* free-form code. Each Mod is mechanically applicable and automatically
|
|
6
|
+
* reversible, and `env` Mods are constrained to an allow-list of knobs with
|
|
7
|
+
* declared safe ranges. This is the "minimal, targeted modification" surface
|
|
8
|
+
* from the Self-Harness paper (arXiv:2606.09498), widened to UAP's three layers
|
|
9
|
+
* (scaffold text, proxy/llama env knobs, proxy middleware).
|
|
10
|
+
*
|
|
11
|
+
* See docs/design/SELF_HARNESS.md.
|
|
12
|
+
*/
|
|
13
|
+
import { UapComponent } from '../benchmarks/paired/types.js';
|
|
14
|
+
export type JsonScalar = string | number | boolean;
|
|
15
|
+
export interface NumericKnob {
|
|
16
|
+
target: 'proxy' | 'llama';
|
|
17
|
+
type: 'number';
|
|
18
|
+
/** Inclusive safe range. A proposed value outside this is rejected. */
|
|
19
|
+
min: number;
|
|
20
|
+
max: number;
|
|
21
|
+
/** Whether the value must be an integer. */
|
|
22
|
+
integer?: boolean;
|
|
23
|
+
description: string;
|
|
24
|
+
}
|
|
25
|
+
export interface EnumKnob {
|
|
26
|
+
target: 'proxy' | 'llama';
|
|
27
|
+
type: 'enum';
|
|
28
|
+
values: readonly string[];
|
|
29
|
+
description: string;
|
|
30
|
+
}
|
|
31
|
+
export type KnobSpec = NumericKnob | EnumKnob;
|
|
32
|
+
export declare const KNOB_ALLOWLIST: {
|
|
33
|
+
readonly LLAMA_N_PREDICT: {
|
|
34
|
+
readonly target: "llama";
|
|
35
|
+
readonly type: "number";
|
|
36
|
+
readonly min: 512;
|
|
37
|
+
readonly max: 16384;
|
|
38
|
+
readonly integer: true;
|
|
39
|
+
readonly description: "per-turn generation cap; low values bound a runaway turn";
|
|
40
|
+
};
|
|
41
|
+
readonly LLAMA_REPEAT_PENALTY: {
|
|
42
|
+
readonly target: "llama";
|
|
43
|
+
readonly type: "number";
|
|
44
|
+
readonly min: 1;
|
|
45
|
+
readonly max: 1.3;
|
|
46
|
+
readonly description: "repetition penalty; damps token-level loops";
|
|
47
|
+
};
|
|
48
|
+
readonly PROXY_HARD_FINALIZE_TURNS: {
|
|
49
|
+
readonly target: "proxy";
|
|
50
|
+
readonly type: "number";
|
|
51
|
+
readonly min: 10;
|
|
52
|
+
readonly max: 80;
|
|
53
|
+
readonly integer: true;
|
|
54
|
+
readonly description: "tool-turn ceiling before the proxy strips tools to force termination";
|
|
55
|
+
};
|
|
56
|
+
readonly PROXY_RECON_CONVERGENCE_THRESHOLD: {
|
|
57
|
+
readonly target: "proxy";
|
|
58
|
+
readonly type: "number";
|
|
59
|
+
readonly min: 20;
|
|
60
|
+
readonly max: 200;
|
|
61
|
+
readonly integer: true;
|
|
62
|
+
readonly description: "no-write turns before the recon-convergence directive fires";
|
|
63
|
+
};
|
|
64
|
+
readonly PROXY_TOOL_NARROWING_KEEP: {
|
|
65
|
+
readonly target: "proxy";
|
|
66
|
+
readonly type: "number";
|
|
67
|
+
readonly min: 2;
|
|
68
|
+
readonly max: 24;
|
|
69
|
+
readonly integer: true;
|
|
70
|
+
readonly description: "how many tools to retain after relevance narrowing (soft floor)";
|
|
71
|
+
};
|
|
72
|
+
readonly PROXY_FORCED_THRESHOLD: {
|
|
73
|
+
readonly target: "proxy";
|
|
74
|
+
readonly type: "number";
|
|
75
|
+
readonly min: 5;
|
|
76
|
+
readonly max: 40;
|
|
77
|
+
readonly integer: true;
|
|
78
|
+
readonly description: "consecutive forced tool_choice=required turns before loop-breaker release";
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
export type KnownKnob = keyof typeof KNOB_ALLOWLIST;
|
|
82
|
+
export declare function isKnownKnob(k: string): k is KnownKnob;
|
|
83
|
+
/**
|
|
84
|
+
* Look up a knob spec as the full `KnobSpec` union. Indexing KNOB_ALLOWLIST
|
|
85
|
+
* directly preserves each entry's narrow literal type (all numeric today), which
|
|
86
|
+
* makes the enum branch in validateMod unreachable (`never`); returning the union
|
|
87
|
+
* keeps both branches type-checkable as enum knobs are added later.
|
|
88
|
+
*/
|
|
89
|
+
export declare function knobSpec(key: KnownKnob): KnobSpec;
|
|
90
|
+
export declare const MIDDLEWARE_IDS: readonly ["toolcall-path-normalizer"];
|
|
91
|
+
export type MiddlewareId = (typeof MIDDLEWARE_IDS)[number];
|
|
92
|
+
export declare function isMiddlewareId(s: string): s is MiddlewareId;
|
|
93
|
+
export interface EnvMod {
|
|
94
|
+
kind: 'env';
|
|
95
|
+
key: KnownKnob;
|
|
96
|
+
/** Prior value (for revert + audit). */
|
|
97
|
+
from: string;
|
|
98
|
+
/** Proposed value, as it will be written to the env file. */
|
|
99
|
+
to: string;
|
|
100
|
+
}
|
|
101
|
+
export interface ScaffoldMod {
|
|
102
|
+
kind: 'scaffold';
|
|
103
|
+
component: UapComponent;
|
|
104
|
+
op: 'replace' | 'append';
|
|
105
|
+
/** New text (replace) or text to append. */
|
|
106
|
+
text: string;
|
|
107
|
+
/** Prior text of the component block (for revert). */
|
|
108
|
+
from?: string;
|
|
109
|
+
}
|
|
110
|
+
export interface MiddlewareMod {
|
|
111
|
+
kind: 'middleware';
|
|
112
|
+
id: MiddlewareId;
|
|
113
|
+
params: Record<string, JsonScalar>;
|
|
114
|
+
}
|
|
115
|
+
export type Mod = EnvMod | ScaffoldMod | MiddlewareMod;
|
|
116
|
+
export interface ValidationOk {
|
|
117
|
+
ok: true;
|
|
118
|
+
}
|
|
119
|
+
export interface ValidationErr {
|
|
120
|
+
ok: false;
|
|
121
|
+
reason: string;
|
|
122
|
+
}
|
|
123
|
+
export type ValidationResult = ValidationOk | ValidationErr;
|
|
124
|
+
/**
|
|
125
|
+
* Validate a Mod against the DSL constraints. A proposer's output that fails
|
|
126
|
+
* this is rejected at parse time — it never reaches the apply/validate stages.
|
|
127
|
+
*/
|
|
128
|
+
export declare function validateMod(mod: Mod): ValidationResult;
|
|
129
|
+
/** One-line, human-readable description of a Mod (for logs and profile diffs). */
|
|
130
|
+
export declare function describeMod(mod: Mod): string;
|
|
131
|
+
/**
|
|
132
|
+
* Produce the inverse Mod that undoes `mod` (for rollback). Env/scaffold revert
|
|
133
|
+
* to their captured prior value; a middleware Mod reverts by disabling it.
|
|
134
|
+
*/
|
|
135
|
+
export declare function invertMod(mod: Mod): Mod;
|
|
136
|
+
//# sourceMappingURL=mods.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mods.d.ts","sourceRoot":"","sources":["../../src/self-harness/mods.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,YAAY,EAAkB,MAAM,+BAA+B,CAAC;AAE7E,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AASnD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC;IAC1B,IAAI,EAAE,QAAQ,CAAC;IACf,uEAAuE;IACvE,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,4CAA4C;IAC5C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE9C,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BkB,CAAC;AAE9C,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,cAAc,CAAC;AAEpD,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,IAAI,SAAS,CAErD;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,SAAS,GAAG,QAAQ,CAEjD;AASD,eAAO,MAAM,cAAc,uCAAwC,CAAC;AACpE,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,IAAI,YAAY,CAE3D;AAMD,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,KAAK,CAAC;IACZ,GAAG,EAAE,SAAS,CAAC;IACf,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,UAAU,CAAC;IACjB,SAAS,EAAE,YAAY,CAAC;IACxB,EAAE,EAAE,SAAS,GAAG,QAAQ,CAAC;IACzB,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,YAAY,CAAC;IACnB,EAAE,EAAE,YAAY,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACpC;AAED,MAAM,MAAM,GAAG,GAAG,MAAM,GAAG,WAAW,GAAG,aAAa,CAAC;AAEvD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,IAAI,CAAC;CACV;AACD,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EAAE,MAAM,CAAC;CAChB;AACD,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,aAAa,CAAC;AAE5D;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,gBAAgB,CAkDtD;AAED,kFAAkF;AAClF,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAS5C;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,CAiBvC"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-Harness — the Modification ("Mod") DSL.
|
|
3
|
+
*
|
|
4
|
+
* The autonomous proposer may ONLY emit values of the `Mod` union below — never
|
|
5
|
+
* free-form code. Each Mod is mechanically applicable and automatically
|
|
6
|
+
* reversible, and `env` Mods are constrained to an allow-list of knobs with
|
|
7
|
+
* declared safe ranges. This is the "minimal, targeted modification" surface
|
|
8
|
+
* from the Self-Harness paper (arXiv:2606.09498), widened to UAP's three layers
|
|
9
|
+
* (scaffold text, proxy/llama env knobs, proxy middleware).
|
|
10
|
+
*
|
|
11
|
+
* See docs/design/SELF_HARNESS.md.
|
|
12
|
+
*/
|
|
13
|
+
import { UAP_COMPONENTS } from '../benchmarks/paired/types.js';
|
|
14
|
+
export const KNOB_ALLOWLIST = {
|
|
15
|
+
// --- llama sampler knobs (hot-reload via env + server restart, no slot clear) ---
|
|
16
|
+
LLAMA_N_PREDICT: {
|
|
17
|
+
target: 'llama', type: 'number', min: 512, max: 16384, integer: true,
|
|
18
|
+
description: 'per-turn generation cap; low values bound a runaway turn',
|
|
19
|
+
},
|
|
20
|
+
LLAMA_REPEAT_PENALTY: {
|
|
21
|
+
target: 'llama', type: 'number', min: 1.0, max: 1.3,
|
|
22
|
+
description: 'repetition penalty; damps token-level loops',
|
|
23
|
+
},
|
|
24
|
+
// --- proxy guardrail knobs (live per-request, no restart) ---
|
|
25
|
+
PROXY_HARD_FINALIZE_TURNS: {
|
|
26
|
+
target: 'proxy', type: 'number', min: 10, max: 80, integer: true,
|
|
27
|
+
description: 'tool-turn ceiling before the proxy strips tools to force termination',
|
|
28
|
+
},
|
|
29
|
+
PROXY_RECON_CONVERGENCE_THRESHOLD: {
|
|
30
|
+
target: 'proxy', type: 'number', min: 20, max: 200, integer: true,
|
|
31
|
+
description: 'no-write turns before the recon-convergence directive fires',
|
|
32
|
+
},
|
|
33
|
+
PROXY_TOOL_NARROWING_KEEP: {
|
|
34
|
+
target: 'proxy', type: 'number', min: 2, max: 24, integer: true,
|
|
35
|
+
description: 'how many tools to retain after relevance narrowing (soft floor)',
|
|
36
|
+
},
|
|
37
|
+
PROXY_FORCED_THRESHOLD: {
|
|
38
|
+
target: 'proxy', type: 'number', min: 5, max: 40, integer: true,
|
|
39
|
+
description: 'consecutive forced tool_choice=required turns before loop-breaker release',
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
export function isKnownKnob(k) {
|
|
43
|
+
return Object.prototype.hasOwnProperty.call(KNOB_ALLOWLIST, k);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Look up a knob spec as the full `KnobSpec` union. Indexing KNOB_ALLOWLIST
|
|
47
|
+
* directly preserves each entry's narrow literal type (all numeric today), which
|
|
48
|
+
* makes the enum branch in validateMod unreachable (`never`); returning the union
|
|
49
|
+
* keeps both branches type-checkable as enum knobs are added later.
|
|
50
|
+
*/
|
|
51
|
+
export function knobSpec(key) {
|
|
52
|
+
return KNOB_ALLOWLIST[key];
|
|
53
|
+
}
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// Middleware Mods (Phase 2). Purpose-built proxy interceptors the proposer may
|
|
56
|
+
// toggle/parameterize. The first is the tool-call path-normalizer — a
|
|
57
|
+
// mechanical fix for the filename-garbling failure that prompt/param Mods can't
|
|
58
|
+
// reach (see SELF_HARNESS.md §4, §11 P2).
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
export const MIDDLEWARE_IDS = ['toolcall-path-normalizer'];
|
|
61
|
+
export function isMiddlewareId(s) {
|
|
62
|
+
return MIDDLEWARE_IDS.includes(s);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Validate a Mod against the DSL constraints. A proposer's output that fails
|
|
66
|
+
* this is rejected at parse time — it never reaches the apply/validate stages.
|
|
67
|
+
*/
|
|
68
|
+
export function validateMod(mod) {
|
|
69
|
+
switch (mod.kind) {
|
|
70
|
+
case 'env': {
|
|
71
|
+
if (!isKnownKnob(mod.key)) {
|
|
72
|
+
return { ok: false, reason: `unknown/non-allow-listed knob: ${mod.key}` };
|
|
73
|
+
}
|
|
74
|
+
const spec = knobSpec(mod.key);
|
|
75
|
+
if (spec.type === 'number') {
|
|
76
|
+
const n = Number(mod.to);
|
|
77
|
+
if (!Number.isFinite(n)) {
|
|
78
|
+
return { ok: false, reason: `${mod.key}: "${mod.to}" is not numeric` };
|
|
79
|
+
}
|
|
80
|
+
if (spec.integer && !Number.isInteger(n)) {
|
|
81
|
+
return { ok: false, reason: `${mod.key}: must be an integer, got ${mod.to}` };
|
|
82
|
+
}
|
|
83
|
+
if (n < spec.min || n > spec.max) {
|
|
84
|
+
return {
|
|
85
|
+
ok: false,
|
|
86
|
+
reason: `${mod.key}=${mod.to} out of safe range [${spec.min}, ${spec.max}]`,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
return { ok: true };
|
|
90
|
+
}
|
|
91
|
+
// enum
|
|
92
|
+
if (!spec.values.includes(mod.to)) {
|
|
93
|
+
return { ok: false, reason: `${mod.key}="${mod.to}" not in {${spec.values.join(', ')}}` };
|
|
94
|
+
}
|
|
95
|
+
return { ok: true };
|
|
96
|
+
}
|
|
97
|
+
case 'scaffold': {
|
|
98
|
+
if (!UAP_COMPONENTS.includes(mod.component)) {
|
|
99
|
+
return { ok: false, reason: `unknown UAP component: ${mod.component}` };
|
|
100
|
+
}
|
|
101
|
+
if (mod.op !== 'replace' && mod.op !== 'append') {
|
|
102
|
+
return { ok: false, reason: `scaffold op must be replace|append` };
|
|
103
|
+
}
|
|
104
|
+
if (!mod.text.trim()) {
|
|
105
|
+
return { ok: false, reason: `scaffold text is empty` };
|
|
106
|
+
}
|
|
107
|
+
return { ok: true };
|
|
108
|
+
}
|
|
109
|
+
case 'middleware': {
|
|
110
|
+
if (!isMiddlewareId(mod.id)) {
|
|
111
|
+
return { ok: false, reason: `unknown middleware id: ${mod.id}` };
|
|
112
|
+
}
|
|
113
|
+
return { ok: true };
|
|
114
|
+
}
|
|
115
|
+
default:
|
|
116
|
+
return { ok: false, reason: `unknown mod kind` };
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/** One-line, human-readable description of a Mod (for logs and profile diffs). */
|
|
120
|
+
export function describeMod(mod) {
|
|
121
|
+
switch (mod.kind) {
|
|
122
|
+
case 'env':
|
|
123
|
+
return `env ${mod.key}: ${mod.from} -> ${mod.to}`;
|
|
124
|
+
case 'scaffold':
|
|
125
|
+
return `scaffold ${mod.component} (${mod.op}, ${mod.text.length} chars)`;
|
|
126
|
+
case 'middleware':
|
|
127
|
+
return `middleware ${mod.id}(${JSON.stringify(mod.params)})`;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Produce the inverse Mod that undoes `mod` (for rollback). Env/scaffold revert
|
|
132
|
+
* to their captured prior value; a middleware Mod reverts by disabling it.
|
|
133
|
+
*/
|
|
134
|
+
export function invertMod(mod) {
|
|
135
|
+
switch (mod.kind) {
|
|
136
|
+
case 'env':
|
|
137
|
+
return { kind: 'env', key: mod.key, from: mod.to, to: mod.from };
|
|
138
|
+
case 'scaffold':
|
|
139
|
+
// Only a captured prior text can be restored; an append has no clean
|
|
140
|
+
// inverse without the original, so callers must supply `from` to revert.
|
|
141
|
+
return {
|
|
142
|
+
kind: 'scaffold',
|
|
143
|
+
component: mod.component,
|
|
144
|
+
op: 'replace',
|
|
145
|
+
text: mod.from ?? '',
|
|
146
|
+
from: mod.op === 'replace' ? mod.text : undefined,
|
|
147
|
+
};
|
|
148
|
+
case 'middleware':
|
|
149
|
+
return { kind: 'middleware', id: mod.id, params: { ...mod.params, enabled: false } };
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=mods.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mods.js","sourceRoot":"","sources":["../../src/self-harness/mods.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-Harness — the P1 orchestrator: one autonomous mine -> propose -> validate
|
|
3
|
+
* -> decide iteration.
|
|
4
|
+
*
|
|
5
|
+
* The `validate` dependency is INJECTED so the loop is testable without the slow
|
|
6
|
+
* paired bench: tests pass a stub; the CLI wires a real validator that runs
|
|
7
|
+
* `runPaired` + `analyze` on the validation and held-out suites (and, for env
|
|
8
|
+
* Mods, physically applies the env edit + restarts the server around the run).
|
|
9
|
+
* Each candidate is validated in isolation; rejected Mods are reverted, accepted
|
|
10
|
+
* Mods are recorded into the profile and logged. Budget-bounded.
|
|
11
|
+
*
|
|
12
|
+
* See docs/design/SELF_HARNESS.md §3, §7, §11 (P1).
|
|
13
|
+
*/
|
|
14
|
+
import type { RunRecord } from '../benchmarks/paired/types.js';
|
|
15
|
+
import type { Comparison } from '../benchmarks/paired/report.js';
|
|
16
|
+
import { Mod } from './mods.js';
|
|
17
|
+
import { WeaknessReport } from './weakness.js';
|
|
18
|
+
import { Proposer } from './propose.js';
|
|
19
|
+
import { Decision, DecisionOptions } from './decide.js';
|
|
20
|
+
import { HarnessProfile } from './profile.js';
|
|
21
|
+
import { TransferStore } from './transfer.js';
|
|
22
|
+
export interface ValidationOutcome {
|
|
23
|
+
validation: Comparison;
|
|
24
|
+
/** Held-out comparison; null when the held-out suite was skipped. */
|
|
25
|
+
heldout: Comparison | null;
|
|
26
|
+
}
|
|
27
|
+
export type Validator = (mod: Mod) => Promise<ValidationOutcome>;
|
|
28
|
+
export interface OrchestratorOptions {
|
|
29
|
+
model: string;
|
|
30
|
+
/** Records mined for weaknesses (e.g. a prior baseline bench). */
|
|
31
|
+
records: RunRecord[];
|
|
32
|
+
profile: HarnessProfile;
|
|
33
|
+
validate: Validator;
|
|
34
|
+
proposer?: Proposer;
|
|
35
|
+
/** Max candidate Mods to validate this iteration (token/time budget). Default 3. */
|
|
36
|
+
maxCandidates?: number;
|
|
37
|
+
decision?: DecisionOptions;
|
|
38
|
+
minFrequency?: number;
|
|
39
|
+
log?: (msg: string) => void;
|
|
40
|
+
/** Optional cross-model transfer store; outcomes are recorded into it (P3). */
|
|
41
|
+
transferStore?: TransferStore;
|
|
42
|
+
/** ISO timestamp + provenance string stamped on recorded transfer entries. */
|
|
43
|
+
validatedAt?: string;
|
|
44
|
+
provenance?: string;
|
|
45
|
+
}
|
|
46
|
+
export interface CandidateOutcome {
|
|
47
|
+
mod: Mod;
|
|
48
|
+
decision: Decision;
|
|
49
|
+
accepted: boolean;
|
|
50
|
+
}
|
|
51
|
+
export interface IterationResult {
|
|
52
|
+
weaknesses: WeaknessReport[];
|
|
53
|
+
proposed: Mod[];
|
|
54
|
+
outcomes: CandidateOutcome[];
|
|
55
|
+
accepted: Mod[];
|
|
56
|
+
/** Profile after applying all accepted Mods. */
|
|
57
|
+
profile: HarnessProfile;
|
|
58
|
+
}
|
|
59
|
+
/** Run one self-harness iteration. */
|
|
60
|
+
export declare function runIteration(opts: OrchestratorOptions): Promise<IterationResult>;
|
|
61
|
+
//# sourceMappingURL=orchestrator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/self-harness/orchestrator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,GAAG,EAAe,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,EAAE,QAAQ,EAAqB,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAgB,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAqB,MAAM,eAAe,CAAC;AAEjE,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,UAAU,CAAC;IACvB,qEAAqE;IACrE,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAEjE,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,OAAO,EAAE,cAAc,CAAC;IACxB,QAAQ,EAAE,SAAS,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,oFAAoF;IACpF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,+EAA+E;IAC/E,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,GAAG,CAAC;IACT,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,QAAQ,EAAE,GAAG,EAAE,CAAC;IAChB,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,QAAQ,EAAE,GAAG,EAAE,CAAC;IAChB,gDAAgD;IAChD,OAAO,EAAE,cAAc,CAAC;CACzB;AAED,sCAAsC;AACtC,wBAAsB,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,eAAe,CAAC,CAiEtF"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-Harness — the P1 orchestrator: one autonomous mine -> propose -> validate
|
|
3
|
+
* -> decide iteration.
|
|
4
|
+
*
|
|
5
|
+
* The `validate` dependency is INJECTED so the loop is testable without the slow
|
|
6
|
+
* paired bench: tests pass a stub; the CLI wires a real validator that runs
|
|
7
|
+
* `runPaired` + `analyze` on the validation and held-out suites (and, for env
|
|
8
|
+
* Mods, physically applies the env edit + restarts the server around the run).
|
|
9
|
+
* Each candidate is validated in isolation; rejected Mods are reverted, accepted
|
|
10
|
+
* Mods are recorded into the profile and logged. Budget-bounded.
|
|
11
|
+
*
|
|
12
|
+
* See docs/design/SELF_HARNESS.md §3, §7, §11 (P1).
|
|
13
|
+
*/
|
|
14
|
+
import { describeMod } from './mods.js';
|
|
15
|
+
import { mineFromRecords } from './mine.js';
|
|
16
|
+
import { heuristicProposer } from './propose.js';
|
|
17
|
+
import { decideAccept } from './decide.js';
|
|
18
|
+
import { modKey, makeEntry } from './transfer.js';
|
|
19
|
+
/** Run one self-harness iteration. */
|
|
20
|
+
export async function runIteration(opts) {
|
|
21
|
+
const log = opts.log ?? (() => { });
|
|
22
|
+
const proposer = opts.proposer ?? heuristicProposer;
|
|
23
|
+
const maxC = opts.maxCandidates ?? 3;
|
|
24
|
+
// Stage 1 — mine
|
|
25
|
+
const weaknesses = mineFromRecords(opts.records, {
|
|
26
|
+
model: opts.model,
|
|
27
|
+
minFrequency: opts.minFrequency,
|
|
28
|
+
});
|
|
29
|
+
log(`mined ${weaknesses.length} weakness(es): ${weaknesses.map((w) => w.kind).join(', ') || '(none)'}`);
|
|
30
|
+
// Stage 2 — propose (bounded, minimal)
|
|
31
|
+
const proposed = proposer.propose(weaknesses, opts.profile).slice(0, maxC);
|
|
32
|
+
log(`proposed ${proposed.length} candidate Mod(s) via ${proposer.id}`);
|
|
33
|
+
// Stage 3+4 — validate + decide, each candidate in isolation
|
|
34
|
+
const outcomes = [];
|
|
35
|
+
const accepted = [];
|
|
36
|
+
let profile = opts.profile;
|
|
37
|
+
for (const mod of proposed) {
|
|
38
|
+
log(`validating: ${describeMod(mod)}`);
|
|
39
|
+
let decision;
|
|
40
|
+
try {
|
|
41
|
+
const { validation, heldout } = await opts.validate(mod);
|
|
42
|
+
decision = decideAccept(validation, heldout, opts.decision);
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
decision = {
|
|
46
|
+
verdict: 'reject',
|
|
47
|
+
reason: `validation error: ${e instanceof Error ? e.message : String(e)}`,
|
|
48
|
+
validationDelta: NaN,
|
|
49
|
+
heldoutDelta: null,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
const ok = decision.verdict === 'accept';
|
|
53
|
+
log(` -> ${decision.verdict.toUpperCase()}: ${decision.reason}`);
|
|
54
|
+
outcomes.push({ mod, decision, accepted: ok });
|
|
55
|
+
if (ok) {
|
|
56
|
+
accepted.push(mod);
|
|
57
|
+
profile = applyAcceptedToProfile(profile, mod);
|
|
58
|
+
}
|
|
59
|
+
// Record the outcome (accept OR reject) into the transfer store, attributed
|
|
60
|
+
// to the weakness whose heuristic produced this Mod, so the fix transfers to
|
|
61
|
+
// future models and known-bad Mods aren't re-proposed.
|
|
62
|
+
if (opts.transferStore) {
|
|
63
|
+
const w = attributeWeakness(mod, weaknesses, proposer, profile);
|
|
64
|
+
if (w) {
|
|
65
|
+
opts.transferStore.record(makeEntry({
|
|
66
|
+
signature: w.signature,
|
|
67
|
+
kind: w.kind,
|
|
68
|
+
model: opts.model,
|
|
69
|
+
mod,
|
|
70
|
+
delta: Number.isFinite(decision.validationDelta) ? decision.validationDelta : 0,
|
|
71
|
+
accepted: ok,
|
|
72
|
+
validatedAt: opts.validatedAt ?? '',
|
|
73
|
+
provenance: opts.provenance ?? 'self-harness iteration',
|
|
74
|
+
}));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return { weaknesses, proposed, outcomes, accepted, profile };
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Attribute a Mod back to the weakness that produced it, by re-running the
|
|
82
|
+
* proposer on each single weakness and matching by structural key. Works for the
|
|
83
|
+
* heuristic and transfer proposers (deterministic kind -> Mod mapping).
|
|
84
|
+
*/
|
|
85
|
+
function attributeWeakness(mod, weaknesses, proposer, profile) {
|
|
86
|
+
const target = modKey(mod);
|
|
87
|
+
for (const w of weaknesses) {
|
|
88
|
+
if (proposer.propose([w], profile).some((m) => modKey(m) === target))
|
|
89
|
+
return w;
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
/** Fold an accepted Mod into the in-memory profile (env/scaffold/middleware). */
|
|
94
|
+
function applyAcceptedToProfile(profile, mod) {
|
|
95
|
+
switch (mod.kind) {
|
|
96
|
+
case 'env':
|
|
97
|
+
return { ...profile, env: { ...profile.env, [mod.key]: mod.to } };
|
|
98
|
+
case 'scaffold': {
|
|
99
|
+
const prev = profile.scaffold[mod.component] ?? '';
|
|
100
|
+
const text = mod.op === 'append' ? `${prev}\n${mod.text}`.trim() : mod.text;
|
|
101
|
+
return { ...profile, scaffold: { ...profile.scaffold, [mod.component]: text } };
|
|
102
|
+
}
|
|
103
|
+
case 'middleware':
|
|
104
|
+
return {
|
|
105
|
+
...profile,
|
|
106
|
+
middleware: { ...profile.middleware, [mod.id]: { ...mod.params } },
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=orchestrator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/self-harness/orchestrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-Harness — gated promotion queue (P3).
|
|
3
|
+
*
|
|
4
|
+
* Proposals mined from PRODUCTION traces are never auto-applied: they are
|
|
5
|
+
* enqueued here as `PendingProposal`s awaiting validation + a human gate. The
|
|
6
|
+
* promotion policy decides what may auto-promote after validation (low-risk env
|
|
7
|
+
* knobs) vs what always needs human review (scaffold/middleware). docs/design/
|
|
8
|
+
* SELF_HARNESS.md §9, §10.
|
|
9
|
+
*/
|
|
10
|
+
import { Mod } from './mods.js';
|
|
11
|
+
import { FailureKind } from './weakness.js';
|
|
12
|
+
export type PromotionGate = 'auto-after-validation' | 'human';
|
|
13
|
+
/**
|
|
14
|
+
* Promotion policy: env-knob Mods are low-risk and may auto-promote after they
|
|
15
|
+
* pass validation; scaffold + middleware Mods change behavior more broadly and
|
|
16
|
+
* always require a human gate. This is the safety boundary for online learning.
|
|
17
|
+
*/
|
|
18
|
+
export declare function promotionGate(mod: Mod): PromotionGate;
|
|
19
|
+
export interface PendingProposal {
|
|
20
|
+
id: string;
|
|
21
|
+
signature: string;
|
|
22
|
+
kind: FailureKind;
|
|
23
|
+
model: string;
|
|
24
|
+
mod: Mod;
|
|
25
|
+
gate: PromotionGate;
|
|
26
|
+
/** Where it came from: 'halo' | 'proxy-log' | transfer source. */
|
|
27
|
+
source: string;
|
|
28
|
+
frequency: number;
|
|
29
|
+
createdAt: string;
|
|
30
|
+
status: 'pending' | 'validated' | 'rejected' | 'promoted';
|
|
31
|
+
/** Set once validated. */
|
|
32
|
+
validationDelta?: number;
|
|
33
|
+
note?: string;
|
|
34
|
+
}
|
|
35
|
+
export declare class PendingQueue {
|
|
36
|
+
private readonly path;
|
|
37
|
+
private items;
|
|
38
|
+
constructor(path: string);
|
|
39
|
+
private persist;
|
|
40
|
+
/** Enqueue a proposal, de-duped by (model, signature, mod-shape) while pending. */
|
|
41
|
+
enqueue(p: Omit<PendingProposal, 'gate' | 'status' | 'createdAt'> & {
|
|
42
|
+
createdAt: string;
|
|
43
|
+
}): PendingProposal;
|
|
44
|
+
list(status?: PendingProposal['status']): PendingProposal[];
|
|
45
|
+
update(id: string, patch: Partial<PendingProposal>): void;
|
|
46
|
+
/**
|
|
47
|
+
* Drop terminal (promoted/rejected) entries older than `maxAgeDays`, and stale
|
|
48
|
+
* still-pending entries older than `maxPendingDays` (never validated → likely
|
|
49
|
+
* obsolete). Returns the removed items.
|
|
50
|
+
*/
|
|
51
|
+
prune(opts?: {
|
|
52
|
+
maxAgeDays?: number;
|
|
53
|
+
maxPendingDays?: number;
|
|
54
|
+
now?: number;
|
|
55
|
+
}): PendingProposal[];
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=pending.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pending.d.ts","sourceRoot":"","sources":["../../src/self-harness/pending.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,MAAM,aAAa,GAAG,uBAAuB,GAAG,OAAO,CAAC;AAE9D;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,GAAG,GAAG,aAAa,CAErD;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,GAAG,CAAC;IACT,IAAI,EAAE,aAAa,CAAC;IACpB,kEAAkE;IAClE,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,CAAC;IAC1D,0BAA0B;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,YAAY;IAGX,OAAO,CAAC,QAAQ,CAAC,IAAI;IAFjC,OAAO,CAAC,KAAK,CAAyB;gBAET,IAAI,EAAE,MAAM;IAUzC,OAAO,CAAC,OAAO;IAKf,mFAAmF;IACnF,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC,eAAe,EAAE,MAAM,GAAG,QAAQ,GAAG,WAAW,CAAC,GAAG;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,eAAe;IAgB3G,IAAI,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC,QAAQ,CAAC,GAAG,eAAe,EAAE;IAI3D,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI;IAQzD;;;;OAIG;IACH,KAAK,CAAC,IAAI,GAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,eAAe,EAAE;CAkBpG"}
|