@miller-tech/uap 1.60.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/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,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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
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 { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
11
|
+
import { dirname } from 'path';
|
|
12
|
+
/**
|
|
13
|
+
* Promotion policy: env-knob Mods are low-risk and may auto-promote after they
|
|
14
|
+
* pass validation; scaffold + middleware Mods change behavior more broadly and
|
|
15
|
+
* always require a human gate. This is the safety boundary for online learning.
|
|
16
|
+
*/
|
|
17
|
+
export function promotionGate(mod) {
|
|
18
|
+
return mod.kind === 'env' ? 'auto-after-validation' : 'human';
|
|
19
|
+
}
|
|
20
|
+
export class PendingQueue {
|
|
21
|
+
path;
|
|
22
|
+
items = [];
|
|
23
|
+
constructor(path) {
|
|
24
|
+
this.path = path;
|
|
25
|
+
if (existsSync(path)) {
|
|
26
|
+
try {
|
|
27
|
+
this.items = JSON.parse(readFileSync(path, 'utf-8'));
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
this.items = [];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
persist() {
|
|
35
|
+
mkdirSync(dirname(this.path), { recursive: true });
|
|
36
|
+
writeFileSync(this.path, JSON.stringify(this.items, null, 2), 'utf-8');
|
|
37
|
+
}
|
|
38
|
+
/** Enqueue a proposal, de-duped by (model, signature, mod-shape) while pending. */
|
|
39
|
+
enqueue(p) {
|
|
40
|
+
const full = { ...p, gate: promotionGate(p.mod), status: 'pending' };
|
|
41
|
+
const exists = this.items.some((x) => x.status === 'pending' &&
|
|
42
|
+
x.model === full.model &&
|
|
43
|
+
x.signature === full.signature &&
|
|
44
|
+
JSON.stringify(x.mod) === JSON.stringify(full.mod));
|
|
45
|
+
if (!exists) {
|
|
46
|
+
this.items.push(full);
|
|
47
|
+
this.persist();
|
|
48
|
+
}
|
|
49
|
+
return full;
|
|
50
|
+
}
|
|
51
|
+
list(status) {
|
|
52
|
+
return status ? this.items.filter((x) => x.status === status) : [...this.items];
|
|
53
|
+
}
|
|
54
|
+
update(id, patch) {
|
|
55
|
+
const it = this.items.find((x) => x.id === id);
|
|
56
|
+
if (it) {
|
|
57
|
+
Object.assign(it, patch);
|
|
58
|
+
this.persist();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Drop terminal (promoted/rejected) entries older than `maxAgeDays`, and stale
|
|
63
|
+
* still-pending entries older than `maxPendingDays` (never validated → likely
|
|
64
|
+
* obsolete). Returns the removed items.
|
|
65
|
+
*/
|
|
66
|
+
prune(opts = {}) {
|
|
67
|
+
const maxAge = (opts.maxAgeDays ?? 30) * 86_400_000;
|
|
68
|
+
const maxPending = (opts.maxPendingDays ?? 14) * 86_400_000;
|
|
69
|
+
const now = opts.now ?? Date.now();
|
|
70
|
+
const removed = [];
|
|
71
|
+
this.items = this.items.filter((it) => {
|
|
72
|
+
const age = now - (Date.parse(it.createdAt) || 0);
|
|
73
|
+
const terminalStale = (it.status === 'promoted' || it.status === 'rejected') && age > maxAge;
|
|
74
|
+
const pendingStale = it.status === 'pending' && age > maxPending;
|
|
75
|
+
if (terminalStale || pendingStale) {
|
|
76
|
+
removed.push(it);
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
return true;
|
|
80
|
+
});
|
|
81
|
+
if (removed.length)
|
|
82
|
+
this.persist();
|
|
83
|
+
return removed;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=pending.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pending.js","sourceRoot":"","sources":["../../src/self-harness/pending.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-Harness — the versioned harness profile + env-file apply/revert.
|
|
3
|
+
*
|
|
4
|
+
* A `HarnessProfile` is the source of truth for the current harness state the
|
|
5
|
+
* proposer reads and the orchestrator commits. P1 physically applies `env` Mods
|
|
6
|
+
* to a KEY=value env file (e.g. ~/.config/uap/llama-server.env) and captures the
|
|
7
|
+
* prior value for one-step revert; scaffold/middleware Mods are recorded in the
|
|
8
|
+
* profile (their physical wiring is P1+/P2). All edits are reversible.
|
|
9
|
+
*/
|
|
10
|
+
import type { UapComponent } from '../benchmarks/paired/types.js';
|
|
11
|
+
import { KnownKnob, EnvMod } from './mods.js';
|
|
12
|
+
export interface HarnessProfile {
|
|
13
|
+
/** Allow-listed env knob values currently in effect (string form). */
|
|
14
|
+
env: Partial<Record<KnownKnob, string>>;
|
|
15
|
+
/** Accepted scaffold component overrides (component -> full text). */
|
|
16
|
+
scaffold: Partial<Record<UapComponent, string>>;
|
|
17
|
+
/** Accepted middleware configs (id -> params). */
|
|
18
|
+
middleware: Record<string, Record<string, string | number | boolean>>;
|
|
19
|
+
}
|
|
20
|
+
export declare function emptyProfile(): HarnessProfile;
|
|
21
|
+
/** Parse a KEY=value env file into a flat map (ignores comments/blank lines). */
|
|
22
|
+
export declare function parseEnvFile(path: string): Record<string, string>;
|
|
23
|
+
/** Build a profile from an env file, keeping only allow-listed knobs. */
|
|
24
|
+
export declare function profileFromEnvFile(path: string): HarnessProfile;
|
|
25
|
+
/**
|
|
26
|
+
* Apply an `EnvMod` to a KEY=value env file in place (replacing the line if the
|
|
27
|
+
* key exists, else appending). Returns the prior value (or null if absent) so
|
|
28
|
+
* the caller can record a precise revert. Verifies the Mod's `from` matches the
|
|
29
|
+
* file's current value when present (guards against a stale proposal).
|
|
30
|
+
*/
|
|
31
|
+
export declare function applyEnvModToFile(path: string, mod: EnvMod): {
|
|
32
|
+
priorValue: string | null;
|
|
33
|
+
};
|
|
34
|
+
/** Apply an accepted Mod's effect to the in-memory profile (after acceptance). */
|
|
35
|
+
export declare function recordModInProfile(profile: HarnessProfile, mod: EnvMod): HarnessProfile;
|
|
36
|
+
/** Default values for allow-listed knobs (used to seed a profile if a knob is unset). */
|
|
37
|
+
export declare function knobDefault(key: KnownKnob): string | null;
|
|
38
|
+
//# sourceMappingURL=profile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../../src/self-harness/profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAkB,SAAS,EAAE,MAAM,EAAe,MAAM,WAAW,CAAC;AAE3E,MAAM,WAAW,cAAc;IAC7B,sEAAsE;IACtE,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;IACxC,sEAAsE;IACtE,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;IAChD,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;CACvE;AAED,wBAAgB,YAAY,IAAI,cAAc,CAE7C;AAED,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWjE;AAED,yEAAyE;AACzE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAO/D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG;IAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAkB1F;AAED,kFAAkF;AAClF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,GAAG,cAAc,CAEvF;AAED,yFAAyF;AACzF,wBAAgB,WAAW,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAMzD"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-Harness — the versioned harness profile + env-file apply/revert.
|
|
3
|
+
*
|
|
4
|
+
* A `HarnessProfile` is the source of truth for the current harness state the
|
|
5
|
+
* proposer reads and the orchestrator commits. P1 physically applies `env` Mods
|
|
6
|
+
* to a KEY=value env file (e.g. ~/.config/uap/llama-server.env) and captures the
|
|
7
|
+
* prior value for one-step revert; scaffold/middleware Mods are recorded in the
|
|
8
|
+
* profile (their physical wiring is P1+/P2). All edits are reversible.
|
|
9
|
+
*/
|
|
10
|
+
import { readFileSync, writeFileSync, existsSync } from 'fs';
|
|
11
|
+
import { KNOB_ALLOWLIST, isKnownKnob } from './mods.js';
|
|
12
|
+
export function emptyProfile() {
|
|
13
|
+
return { env: {}, scaffold: {}, middleware: {} };
|
|
14
|
+
}
|
|
15
|
+
/** Parse a KEY=value env file into a flat map (ignores comments/blank lines). */
|
|
16
|
+
export function parseEnvFile(path) {
|
|
17
|
+
if (!existsSync(path))
|
|
18
|
+
return {};
|
|
19
|
+
const out = {};
|
|
20
|
+
for (const line of readFileSync(path, 'utf-8').split('\n')) {
|
|
21
|
+
const t = line.trim();
|
|
22
|
+
if (!t || t.startsWith('#'))
|
|
23
|
+
continue;
|
|
24
|
+
const eq = t.indexOf('=');
|
|
25
|
+
if (eq <= 0)
|
|
26
|
+
continue;
|
|
27
|
+
out[t.slice(0, eq).trim()] = t.slice(eq + 1).trim();
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
30
|
+
}
|
|
31
|
+
/** Build a profile from an env file, keeping only allow-listed knobs. */
|
|
32
|
+
export function profileFromEnvFile(path) {
|
|
33
|
+
const all = parseEnvFile(path);
|
|
34
|
+
const p = emptyProfile();
|
|
35
|
+
for (const [k, v] of Object.entries(all)) {
|
|
36
|
+
if (isKnownKnob(k))
|
|
37
|
+
p.env[k] = v;
|
|
38
|
+
}
|
|
39
|
+
return p;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Apply an `EnvMod` to a KEY=value env file in place (replacing the line if the
|
|
43
|
+
* key exists, else appending). Returns the prior value (or null if absent) so
|
|
44
|
+
* the caller can record a precise revert. Verifies the Mod's `from` matches the
|
|
45
|
+
* file's current value when present (guards against a stale proposal).
|
|
46
|
+
*/
|
|
47
|
+
export function applyEnvModToFile(path, mod) {
|
|
48
|
+
const lines = existsSync(path) ? readFileSync(path, 'utf-8').split('\n') : [];
|
|
49
|
+
let prior = null;
|
|
50
|
+
let replaced = false;
|
|
51
|
+
const key = mod.key;
|
|
52
|
+
for (let i = 0; i < lines.length; i++) {
|
|
53
|
+
const t = lines[i].trim();
|
|
54
|
+
if (t.startsWith('#') || !t.includes('='))
|
|
55
|
+
continue;
|
|
56
|
+
if (t.slice(0, t.indexOf('=')).trim() === key) {
|
|
57
|
+
prior = t.slice(t.indexOf('=') + 1).trim();
|
|
58
|
+
lines[i] = `${key}=${mod.to}`;
|
|
59
|
+
replaced = true;
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (!replaced)
|
|
64
|
+
lines.push(`${key}=${mod.to}`);
|
|
65
|
+
writeFileSync(path, lines.join('\n'), 'utf-8');
|
|
66
|
+
return { priorValue: prior };
|
|
67
|
+
}
|
|
68
|
+
/** Apply an accepted Mod's effect to the in-memory profile (after acceptance). */
|
|
69
|
+
export function recordModInProfile(profile, mod) {
|
|
70
|
+
return { ...profile, env: { ...profile.env, [mod.key]: mod.to } };
|
|
71
|
+
}
|
|
72
|
+
/** Default values for allow-listed knobs (used to seed a profile if a knob is unset). */
|
|
73
|
+
export function knobDefault(key) {
|
|
74
|
+
// The allow-list declares ranges, not defaults; defaults live in the proxy/
|
|
75
|
+
// launch script. We return null and let the proposer skip knobs with no
|
|
76
|
+
// observed current value rather than guess.
|
|
77
|
+
void KNOB_ALLOWLIST[key];
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/self-harness/profile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-Harness — Stage 2 harness-proposal.
|
|
3
|
+
*
|
|
4
|
+
* A `Proposer` turns a ranked `WeaknessReport[]` + the current harness profile
|
|
5
|
+
* into candidate `Mod`s (all DSL-validated). P1 ships a deterministic
|
|
6
|
+
* `heuristicProposer` (a known-failure -> candidate-Mod mapping) so the whole
|
|
7
|
+
* loop runs and is testable without an LLM; the `Proposer` interface is the seam
|
|
8
|
+
* an LLM proposer (P1+) drops into. Proposals are biased toward MINIMAL edits
|
|
9
|
+
* (single knob / single block), per the paper.
|
|
10
|
+
*/
|
|
11
|
+
import { Mod, KNOB_ALLOWLIST } from './mods.js';
|
|
12
|
+
import { WeaknessReport } from './weakness.js';
|
|
13
|
+
import type { HarnessProfile } from './profile.js';
|
|
14
|
+
export interface Proposer {
|
|
15
|
+
readonly id: string;
|
|
16
|
+
propose(weaknesses: WeaknessReport[], profile: HarnessProfile): Mod[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Deterministic heuristic proposer: maps each weakness kind to a minimal,
|
|
20
|
+
* known-good candidate Mod. This intentionally encodes the fixes that worked in
|
|
21
|
+
* the manual campaign (e.g. halving LLAMA_N_PREDICT for runaway generation).
|
|
22
|
+
*/
|
|
23
|
+
export declare const heuristicProposer: Proposer;
|
|
24
|
+
export { KNOB_ALLOWLIST };
|
|
25
|
+
//# sourceMappingURL=propose.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"propose.d.ts","sourceRoot":"","sources":["../../src/self-harness/propose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,GAAG,EAAqB,cAAc,EAAyB,MAAM,WAAW,CAAC;AAC1F,OAAO,EAAE,cAAc,EAAe,MAAM,eAAe,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,UAAU,EAAE,cAAc,EAAE,EAAE,OAAO,EAAE,cAAc,GAAG,GAAG,EAAE,CAAC;CACvE;AA+BD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,QAU/B,CAAC;AA8BF,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-Harness — Stage 2 harness-proposal.
|
|
3
|
+
*
|
|
4
|
+
* A `Proposer` turns a ranked `WeaknessReport[]` + the current harness profile
|
|
5
|
+
* into candidate `Mod`s (all DSL-validated). P1 ships a deterministic
|
|
6
|
+
* `heuristicProposer` (a known-failure -> candidate-Mod mapping) so the whole
|
|
7
|
+
* loop runs and is testable without an LLM; the `Proposer` interface is the seam
|
|
8
|
+
* an LLM proposer (P1+) drops into. Proposals are biased toward MINIMAL edits
|
|
9
|
+
* (single knob / single block), per the paper.
|
|
10
|
+
*/
|
|
11
|
+
import { KNOB_ALLOWLIST, validateMod, knobSpec } from './mods.js';
|
|
12
|
+
/** Clamp a numeric knob value to its declared safe range. */
|
|
13
|
+
function clampKnob(key, value) {
|
|
14
|
+
const spec = knobSpec(key);
|
|
15
|
+
if (spec.type !== 'number')
|
|
16
|
+
return value;
|
|
17
|
+
const v = Math.max(spec.min, Math.min(spec.max, value));
|
|
18
|
+
return spec.integer ? Math.round(v) : v;
|
|
19
|
+
}
|
|
20
|
+
/** Read the current value of a knob from the profile (or its declared default). */
|
|
21
|
+
function currentKnob(profile, key) {
|
|
22
|
+
const raw = profile.env[key];
|
|
23
|
+
if (raw == null)
|
|
24
|
+
return null;
|
|
25
|
+
const n = Number(raw);
|
|
26
|
+
return Number.isFinite(n) ? n : null;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Build a numeric env Mod that moves `key` toward `factor`×current (clamped),
|
|
30
|
+
* or null if the current value is unknown or the move is a no-op / out of range.
|
|
31
|
+
*/
|
|
32
|
+
function scaleKnob(profile, key, factor) {
|
|
33
|
+
const cur = currentKnob(profile, key);
|
|
34
|
+
if (cur == null)
|
|
35
|
+
return null;
|
|
36
|
+
const next = clampKnob(key, cur * factor);
|
|
37
|
+
if (next === cur)
|
|
38
|
+
return null;
|
|
39
|
+
const mod = { kind: 'env', key, from: String(cur), to: String(next) };
|
|
40
|
+
return validateMod(mod).ok ? mod : null;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Deterministic heuristic proposer: maps each weakness kind to a minimal,
|
|
44
|
+
* known-good candidate Mod. This intentionally encodes the fixes that worked in
|
|
45
|
+
* the manual campaign (e.g. halving LLAMA_N_PREDICT for runaway generation).
|
|
46
|
+
*/
|
|
47
|
+
export const heuristicProposer = {
|
|
48
|
+
id: 'heuristic',
|
|
49
|
+
propose(weaknesses, profile) {
|
|
50
|
+
const out = [];
|
|
51
|
+
for (const w of weaknesses) {
|
|
52
|
+
const cand = HEURISTICS[w.kind]?.(profile);
|
|
53
|
+
if (cand && validateMod(cand).ok)
|
|
54
|
+
out.push(cand);
|
|
55
|
+
}
|
|
56
|
+
return out;
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
const HEURISTICS = {
|
|
60
|
+
// Runaway generation eating the wall-clock -> halve the per-turn cap.
|
|
61
|
+
'gen.runaway.npredict': (p) => scaleKnob(p, 'LLAMA_N_PREDICT', 0.5),
|
|
62
|
+
// Non-termination loops -> tighten the hard finalize ceiling.
|
|
63
|
+
'loop.nonterminate': (p) => scaleKnob(p, 'PROXY_HARD_FINALIZE_TURNS', 0.75),
|
|
64
|
+
// Wall-clock timeouts are usually runaway-driven on this stack -> cap n-predict.
|
|
65
|
+
'agent.timeout': (p) => scaleKnob(p, 'LLAMA_N_PREDICT', 0.5),
|
|
66
|
+
// Wrong answers -> append a "verify before done" directive to the gates block.
|
|
67
|
+
'verify.fail': () => ({
|
|
68
|
+
kind: 'scaffold',
|
|
69
|
+
component: 'gates',
|
|
70
|
+
op: 'append',
|
|
71
|
+
text: 'After writing, run the verify/test command and confirm exit 0 before declaring done. ' +
|
|
72
|
+
'If it fails, fix in place at the same path and re-run.',
|
|
73
|
+
}),
|
|
74
|
+
// Path garbling -> enable the mechanical path-normalizer middleware (P2). This
|
|
75
|
+
// snaps a garbled tool-call path to a path the model already used correctly,
|
|
76
|
+
// fixing the failure the instruction-level attempts couldn't (the small quant
|
|
77
|
+
// can't reliably follow "use the exact path").
|
|
78
|
+
'toolcall.path.garbled': () => ({
|
|
79
|
+
kind: 'middleware',
|
|
80
|
+
id: 'toolcall-path-normalizer',
|
|
81
|
+
params: { enabled: true },
|
|
82
|
+
}),
|
|
83
|
+
};
|
|
84
|
+
// Re-export so callers don't need the allow-list import path.
|
|
85
|
+
export { KNOB_ALLOWLIST };
|
|
86
|
+
//# sourceMappingURL=propose.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"propose.js","sourceRoot":"","sources":["../../src/self-harness/propose.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-Harness — online weakness mining from PRODUCTION traces (P3).
|
|
3
|
+
*
|
|
4
|
+
* The records-miner (mine.ts) needs a paired bench. Online mining works on real
|
|
5
|
+
* traffic from two sources:
|
|
6
|
+
* - HALO spans (.uap/halo/traces.jsonl) — the `uap deliver` pipeline.
|
|
7
|
+
* - Proxy log signals (journald) — the claude-local proxy path, where
|
|
8
|
+
* toolcall.path.garbled actually surfaces (records can't distinguish it from a
|
|
9
|
+
* logic error; the proxy's TOOLCALL PATH NORMALIZER line proves it occurred).
|
|
10
|
+
*
|
|
11
|
+
* Both produce the same ranked WeaknessReport[] keyed by stable signature.
|
|
12
|
+
* Mining is READ-ONLY; prod-mined proposals are enqueued for gated validation,
|
|
13
|
+
* never auto-applied (see pending.ts). docs/design/SELF_HARNESS.md §9.
|
|
14
|
+
*/
|
|
15
|
+
import { FailureKind, WeaknessReport } from './weakness.js';
|
|
16
|
+
/** Minimal shape of a HALO span we classify (subset of HaloSpan). */
|
|
17
|
+
export interface HaloSpanLike {
|
|
18
|
+
name?: string;
|
|
19
|
+
status?: {
|
|
20
|
+
code?: string;
|
|
21
|
+
};
|
|
22
|
+
attributes?: Record<string, unknown>;
|
|
23
|
+
}
|
|
24
|
+
/** Classify one HALO span into a FailureKind, or null if it's not a failure. */
|
|
25
|
+
export declare function classifyHaloSpan(span: HaloSpanLike): FailureKind | null;
|
|
26
|
+
/**
|
|
27
|
+
* Classify one proxy journal line. The proxy already logs the structured signals
|
|
28
|
+
* we care about; this turns them into FailureKinds for online mining.
|
|
29
|
+
*/
|
|
30
|
+
export declare function classifyProxyLogLine(line: string): FailureKind | null;
|
|
31
|
+
export interface OnlineMineOptions {
|
|
32
|
+
model: string;
|
|
33
|
+
minFrequency?: number;
|
|
34
|
+
}
|
|
35
|
+
/** Mine weaknesses from HALO spans (the deliver pipeline). */
|
|
36
|
+
export declare function mineFromHaloSpans(spans: HaloSpanLike[], opts: OnlineMineOptions): WeaknessReport[];
|
|
37
|
+
/** Mine weaknesses from proxy journal lines (the claude-local proxy path). */
|
|
38
|
+
export declare function mineFromProxyLogLines(lines: string[], opts: OnlineMineOptions): WeaknessReport[];
|
|
39
|
+
//# sourceMappingURL=trace-mine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-mine.d.ts","sourceRoot":"","sources":["../../src/self-harness/trace-mine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,WAAW,EACX,cAAc,EAGf,MAAM,eAAe,CAAC;AAEvB,qEAAqE;AACrE,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,gFAAgF;AAChF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,YAAY,GAAG,WAAW,GAAG,IAAI,CAmBvE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAOrE;AAwCD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,8DAA8D;AAC9D,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,iBAAiB,GAAG,cAAc,EAAE,CASlG;AAED,8EAA8E;AAC9E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,iBAAiB,GAAG,cAAc,EAAE,CAUhG"}
|