@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,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-Harness middleware — tool-call path normalizer.
|
|
3
|
+
*
|
|
4
|
+
* The mechanical fix for `toolcall.path.garbled`: a small quant fat-fingers the
|
|
5
|
+
* file path in Write/Edit/Read tool calls (case changes, dropped/altered
|
|
6
|
+
* extension, stray subdirectory, trailing whitespace/newline), so the edit lands
|
|
7
|
+
* nowhere and the task never completes. No prompt/param Mod fixes this (the model
|
|
8
|
+
* can't reliably follow "use the exact path"); a deterministic normalizer that
|
|
9
|
+
* snaps the proposed path to the nearest REAL file in the workdir does.
|
|
10
|
+
*
|
|
11
|
+
* This module is the pure, filesystem-free core (the snapping algorithm) so it is
|
|
12
|
+
* unit-testable against the real garble cases observed this cycle. The runner
|
|
13
|
+
* (a Claude Code PreToolUse hook) supplies the actual workdir file list. See
|
|
14
|
+
* docs/design/SELF_HARNESS.md §4 (P2).
|
|
15
|
+
*/
|
|
16
|
+
export interface NormalizeResult {
|
|
17
|
+
/** The resolved path (possibly corrected). */
|
|
18
|
+
path: string;
|
|
19
|
+
changed: boolean;
|
|
20
|
+
/** Why it was changed, or null if unchanged. */
|
|
21
|
+
reason: string | null;
|
|
22
|
+
}
|
|
23
|
+
export interface NormalizeOptions {
|
|
24
|
+
/**
|
|
25
|
+
* Max Levenshtein distance (on the basename) for the typo fallback to fire.
|
|
26
|
+
* Defaults to max(2, 30% of basename length).
|
|
27
|
+
*/
|
|
28
|
+
maxEditDistance?: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Snap `proposed` to the nearest real file in `workdirFiles` (paths relative to
|
|
32
|
+
* the workdir). Returns `proposed` unchanged if it already resolves or no
|
|
33
|
+
* confident match exists — the normalizer never invents a target, so a genuinely
|
|
34
|
+
* new file (a legitimate create) is left alone.
|
|
35
|
+
*/
|
|
36
|
+
export declare function normalizeToolPath(proposed: string, workdirFiles: string[], opts?: NormalizeOptions): NormalizeResult;
|
|
37
|
+
/** Tool-call argument keys that carry a file path, by Claude Code tool name. */
|
|
38
|
+
export declare const PATH_ARG_KEYS: readonly ["file_path", "path", "filePath", "notebook_path"];
|
|
39
|
+
/**
|
|
40
|
+
* Normalize any path-bearing argument in a tool-call input object in place.
|
|
41
|
+
* Returns the corrections made (empty when nothing changed). Pure w.r.t. the
|
|
42
|
+
* filesystem — `workdirFiles` is supplied by the caller (the hook).
|
|
43
|
+
*/
|
|
44
|
+
export declare function normalizeToolInput(input: Record<string, unknown>, workdirFiles: string[], opts?: NormalizeOptions): {
|
|
45
|
+
input: Record<string, unknown>;
|
|
46
|
+
corrections: {
|
|
47
|
+
key: string;
|
|
48
|
+
from: string;
|
|
49
|
+
to: string;
|
|
50
|
+
reason: string;
|
|
51
|
+
}[];
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=path-normalizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-normalizer.d.ts","sourceRoot":"","sources":["../../../src/self-harness/middleware/path-normalizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,eAAe;IAC9B,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,gDAAgD;IAChD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AA+BD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EAAE,EACtB,IAAI,GAAE,gBAAqB,GAC1B,eAAe,CAiDjB;AAED,gFAAgF;AAChF,eAAO,MAAM,aAAa,6DAA8D,CAAC;AAEzF;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,YAAY,EAAE,MAAM,EAAE,EACtB,IAAI,GAAE,gBAAqB,GAC1B;IAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,WAAW,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,CAa9G"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-Harness middleware — tool-call path normalizer.
|
|
3
|
+
*
|
|
4
|
+
* The mechanical fix for `toolcall.path.garbled`: a small quant fat-fingers the
|
|
5
|
+
* file path in Write/Edit/Read tool calls (case changes, dropped/altered
|
|
6
|
+
* extension, stray subdirectory, trailing whitespace/newline), so the edit lands
|
|
7
|
+
* nowhere and the task never completes. No prompt/param Mod fixes this (the model
|
|
8
|
+
* can't reliably follow "use the exact path"); a deterministic normalizer that
|
|
9
|
+
* snaps the proposed path to the nearest REAL file in the workdir does.
|
|
10
|
+
*
|
|
11
|
+
* This module is the pure, filesystem-free core (the snapping algorithm) so it is
|
|
12
|
+
* unit-testable against the real garble cases observed this cycle. The runner
|
|
13
|
+
* (a Claude Code PreToolUse hook) supplies the actual workdir file list. See
|
|
14
|
+
* docs/design/SELF_HARNESS.md §4 (P2).
|
|
15
|
+
*/
|
|
16
|
+
/** Collapse to comparable form: lowercase, strip every non-alphanumeric char. */
|
|
17
|
+
function squash(s) {
|
|
18
|
+
return s.toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
19
|
+
}
|
|
20
|
+
function basename(p) {
|
|
21
|
+
const parts = p.split('/').filter(Boolean);
|
|
22
|
+
return parts.length ? parts[parts.length - 1] : p;
|
|
23
|
+
}
|
|
24
|
+
function editDistance(a, b) {
|
|
25
|
+
const m = a.length;
|
|
26
|
+
const n = b.length;
|
|
27
|
+
if (m === 0)
|
|
28
|
+
return n;
|
|
29
|
+
if (n === 0)
|
|
30
|
+
return m;
|
|
31
|
+
const prev = new Array(n + 1);
|
|
32
|
+
const cur = new Array(n + 1);
|
|
33
|
+
for (let j = 0; j <= n; j++)
|
|
34
|
+
prev[j] = j;
|
|
35
|
+
for (let i = 1; i <= m; i++) {
|
|
36
|
+
cur[0] = i;
|
|
37
|
+
for (let j = 1; j <= n; j++) {
|
|
38
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
39
|
+
cur[j] = Math.min(prev[j] + 1, cur[j - 1] + 1, prev[j - 1] + cost);
|
|
40
|
+
}
|
|
41
|
+
for (let j = 0; j <= n; j++)
|
|
42
|
+
prev[j] = cur[j];
|
|
43
|
+
}
|
|
44
|
+
return prev[n];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Snap `proposed` to the nearest real file in `workdirFiles` (paths relative to
|
|
48
|
+
* the workdir). Returns `proposed` unchanged if it already resolves or no
|
|
49
|
+
* confident match exists — the normalizer never invents a target, so a genuinely
|
|
50
|
+
* new file (a legitimate create) is left alone.
|
|
51
|
+
*/
|
|
52
|
+
export function normalizeToolPath(proposed, workdirFiles, opts = {}) {
|
|
53
|
+
const unchanged = { path: proposed, changed: false, reason: null };
|
|
54
|
+
if (!proposed || workdirFiles.length === 0)
|
|
55
|
+
return unchanged;
|
|
56
|
+
const trimmed = proposed.replace(/\s+$/g, '').replace(/^\s+/g, '');
|
|
57
|
+
// 0) Already an exact relative match (only whitespace differed).
|
|
58
|
+
if (workdirFiles.includes(trimmed)) {
|
|
59
|
+
return trimmed === proposed
|
|
60
|
+
? unchanged
|
|
61
|
+
: { path: trimmed, changed: true, reason: 'trimmed surrounding whitespace' };
|
|
62
|
+
}
|
|
63
|
+
const base = basename(trimmed);
|
|
64
|
+
// Helper: a unique match means we can confidently snap.
|
|
65
|
+
const snap = (target, reason) => target === proposed ? unchanged : { path: target, changed: true, reason };
|
|
66
|
+
const unique = (cands) => (cands.length === 1 ? cands[0] : null);
|
|
67
|
+
// 1) Exact basename match (handles stray leading directory components).
|
|
68
|
+
let hit = unique(workdirFiles.filter((f) => basename(f) === base));
|
|
69
|
+
if (hit)
|
|
70
|
+
return snap(hit, 'stray path components removed');
|
|
71
|
+
// 2) Case-insensitive basename (handles capitalization garble).
|
|
72
|
+
hit = unique(workdirFiles.filter((f) => basename(f).toLowerCase() === base.toLowerCase()));
|
|
73
|
+
if (hit)
|
|
74
|
+
return snap(hit, 'case-normalized to the real filename');
|
|
75
|
+
// 3) Punctuation/extension-squashed basename (handles dropped/altered dot or
|
|
76
|
+
// extension, e.g. "titlecasejs" -> "titlecase.js").
|
|
77
|
+
const sb = squash(base);
|
|
78
|
+
hit = unique(workdirFiles.filter((f) => squash(basename(f)) === sb));
|
|
79
|
+
if (hit)
|
|
80
|
+
return snap(hit, 'extension/punctuation-normalized to the real filename');
|
|
81
|
+
// 4) Edit-distance fallback for genuine typos. Fire only when the best match
|
|
82
|
+
// is meaningfully better than the runner-up (avoids ambiguous snaps).
|
|
83
|
+
const maxD = opts.maxEditDistance ?? Math.max(2, Math.floor(base.length * 0.3));
|
|
84
|
+
const ranked = workdirFiles
|
|
85
|
+
.map((f) => ({ f, d: editDistance(base.toLowerCase(), basename(f).toLowerCase()) }))
|
|
86
|
+
.sort((x, y) => x.d - y.d);
|
|
87
|
+
if (ranked.length > 0 &&
|
|
88
|
+
ranked[0].d <= maxD &&
|
|
89
|
+
(ranked.length < 2 || ranked[1].d > ranked[0].d)) {
|
|
90
|
+
return snap(ranked[0].f, `nearest filename by edit distance (${ranked[0].d})`);
|
|
91
|
+
}
|
|
92
|
+
return unchanged;
|
|
93
|
+
}
|
|
94
|
+
/** Tool-call argument keys that carry a file path, by Claude Code tool name. */
|
|
95
|
+
export const PATH_ARG_KEYS = ['file_path', 'path', 'filePath', 'notebook_path'];
|
|
96
|
+
/**
|
|
97
|
+
* Normalize any path-bearing argument in a tool-call input object in place.
|
|
98
|
+
* Returns the corrections made (empty when nothing changed). Pure w.r.t. the
|
|
99
|
+
* filesystem — `workdirFiles` is supplied by the caller (the hook).
|
|
100
|
+
*/
|
|
101
|
+
export function normalizeToolInput(input, workdirFiles, opts = {}) {
|
|
102
|
+
const corrections = [];
|
|
103
|
+
const out = { ...input };
|
|
104
|
+
for (const key of PATH_ARG_KEYS) {
|
|
105
|
+
const v = out[key];
|
|
106
|
+
if (typeof v !== 'string')
|
|
107
|
+
continue;
|
|
108
|
+
const r = normalizeToolPath(v, workdirFiles, opts);
|
|
109
|
+
if (r.changed) {
|
|
110
|
+
out[key] = r.path;
|
|
111
|
+
corrections.push({ key, from: v, to: r.path, reason: r.reason ?? '' });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return { input: out, corrections };
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=path-normalizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-normalizer.js","sourceRoot":"","sources":["../../../src/self-harness/middleware/path-normalizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
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 type { RunRecord } from '../benchmarks/paired/types.js';
|
|
10
|
+
import { FailureKind, WeaknessReport } from './weakness.js';
|
|
11
|
+
/**
|
|
12
|
+
* Classify a single run's failure into a FailureKind, or null if it succeeded.
|
|
13
|
+
* Heuristics are derived from the observed Qwen3.6-A3B failure modes
|
|
14
|
+
* (see memory project_uap_paired_bench): timeout vs verify-fail vs runaway etc.
|
|
15
|
+
*/
|
|
16
|
+
export declare function classifyFailure(rec: RunRecord): FailureKind | null;
|
|
17
|
+
export interface MineOptions {
|
|
18
|
+
/** Model family the records were produced on (for signature keying). */
|
|
19
|
+
model: string;
|
|
20
|
+
/** Only emit weaknesses occurring at least this many times. Default 1. */
|
|
21
|
+
minFrequency?: number;
|
|
22
|
+
}
|
|
23
|
+
/** Mine ranked weaknesses from a set of paired-bench run records. */
|
|
24
|
+
export declare function mineFromRecords(records: RunRecord[], opts: MineOptions): WeaknessReport[];
|
|
25
|
+
//# sourceMappingURL=mine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mine.d.ts","sourceRoot":"","sources":["../../src/self-harness/mine.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EACL,WAAW,EACX,cAAc,EAGf,MAAM,eAAe,CAAC;AAEvB;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,SAAS,GAAG,WAAW,GAAG,IAAI,CAalE;AAED,MAAM,WAAW,WAAW;IAC1B,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,qEAAqE;AACrE,wBAAgB,eAAe,CAAC,OAAO,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,WAAW,GAAG,cAAc,EAAE,CAiCzF"}
|
|
@@ -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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"}
|