autor3search-typescript 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +210 -0
- package/dist/benchproto/types.d.ts +32 -0
- package/dist/benchproto/types.js +28 -0
- package/dist/benchproto/types.js.map +1 -0
- package/dist/benchrun/child.d.ts +1 -0
- package/dist/benchrun/child.js +222 -0
- package/dist/benchrun/child.js.map +1 -0
- package/dist/benchrun/invoke.d.ts +61 -0
- package/dist/benchrun/invoke.js +152 -0
- package/dist/benchrun/invoke.js.map +1 -0
- package/dist/cli/cmd-baseline.d.ts +15 -0
- package/dist/cli/cmd-baseline.js +292 -0
- package/dist/cli/cmd-baseline.js.map +1 -0
- package/dist/cli/cmd-doctor.d.ts +11 -0
- package/dist/cli/cmd-doctor.js +26 -0
- package/dist/cli/cmd-doctor.js.map +1 -0
- package/dist/cli/cmd-eval.d.ts +30 -0
- package/dist/cli/cmd-eval.js +173 -0
- package/dist/cli/cmd-eval.js.map +1 -0
- package/dist/cli/cmd-init.d.ts +16 -0
- package/dist/cli/cmd-init.js +343 -0
- package/dist/cli/cmd-init.js.map +1 -0
- package/dist/cli/cmd-profile.d.ts +11 -0
- package/dist/cli/cmd-profile.js +140 -0
- package/dist/cli/cmd-profile.js.map +1 -0
- package/dist/cli/cmd-report.d.ts +15 -0
- package/dist/cli/cmd-report.js +70 -0
- package/dist/cli/cmd-report.js.map +1 -0
- package/dist/cli/cmd-status.d.ts +11 -0
- package/dist/cli/cmd-status.js +143 -0
- package/dist/cli/cmd-status.js.map +1 -0
- package/dist/cli/cmd-stop.d.ts +15 -0
- package/dist/cli/cmd-stop.js +143 -0
- package/dist/cli/cmd-stop.js.map +1 -0
- package/dist/cli/main.d.ts +31 -0
- package/dist/cli/main.js +133 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/runctx.d.ts +29 -0
- package/dist/cli/runctx.js +49 -0
- package/dist/cli/runctx.js.map +1 -0
- package/dist/cli/speedup.d.ts +14 -0
- package/dist/cli/speedup.js +25 -0
- package/dist/cli/speedup.js.map +1 -0
- package/dist/config/load.d.ts +6 -0
- package/dist/config/load.js +172 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/schema.d.ts +42 -0
- package/dist/config/schema.js +25 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/discover/benchmarks.d.ts +26 -0
- package/dist/discover/benchmarks.js +88 -0
- package/dist/discover/benchmarks.js.map +1 -0
- package/dist/discover/files.d.ts +23 -0
- package/dist/discover/files.js +82 -0
- package/dist/discover/files.js.map +1 -0
- package/dist/doctor/doctor.d.ts +56 -0
- package/dist/doctor/doctor.js +255 -0
- package/dist/doctor/doctor.js.map +1 -0
- package/dist/freeze/freeze.d.ts +23 -0
- package/dist/freeze/freeze.js +107 -0
- package/dist/freeze/freeze.js.map +1 -0
- package/dist/freeze/manifest.d.ts +6 -0
- package/dist/freeze/manifest.js +9 -0
- package/dist/freeze/manifest.js.map +1 -0
- package/dist/freeze/safepath.d.ts +8 -0
- package/dist/freeze/safepath.js +22 -0
- package/dist/freeze/safepath.js.map +1 -0
- package/dist/gitx/git.d.ts +87 -0
- package/dist/gitx/git.js +235 -0
- package/dist/gitx/git.js.map +1 -0
- package/dist/measure/interleave.d.ts +32 -0
- package/dist/measure/interleave.js +42 -0
- package/dist/measure/interleave.js.map +1 -0
- package/dist/pipeline/eval.d.ts +67 -0
- package/dist/pipeline/eval.js +495 -0
- package/dist/pipeline/eval.js.map +1 -0
- package/dist/pm/detect.d.ts +17 -0
- package/dist/pm/detect.js +131 -0
- package/dist/pm/detect.js.map +1 -0
- package/dist/profile/profile.d.ts +53 -0
- package/dist/profile/profile.js +105 -0
- package/dist/profile/profile.js.map +1 -0
- package/dist/results/results.d.ts +65 -0
- package/dist/results/results.js +214 -0
- package/dist/results/results.js.map +1 -0
- package/dist/runner/exec.d.ts +69 -0
- package/dist/runner/exec.js +185 -0
- package/dist/runner/exec.js.map +1 -0
- package/dist/scope/scope.d.ts +20 -0
- package/dist/scope/scope.js +70 -0
- package/dist/scope/scope.js.map +1 -0
- package/dist/state/baseline.d.ts +35 -0
- package/dist/state/baseline.js +38 -0
- package/dist/state/baseline.js.map +1 -0
- package/dist/state/home.d.ts +9 -0
- package/dist/state/home.js +72 -0
- package/dist/state/home.js.map +1 -0
- package/dist/state/lock.d.ts +11 -0
- package/dist/state/lock.js +89 -0
- package/dist/state/lock.js.map +1 -0
- package/dist/state/runnaming.d.ts +27 -0
- package/dist/state/runnaming.js +47 -0
- package/dist/state/runnaming.js.map +1 -0
- package/dist/state/stop.d.ts +28 -0
- package/dist/state/stop.js +59 -0
- package/dist/state/stop.js.map +1 -0
- package/dist/stats/delta.d.ts +29 -0
- package/dist/stats/delta.js +41 -0
- package/dist/stats/delta.js.map +1 -0
- package/dist/stats/geomean.d.ts +4 -0
- package/dist/stats/geomean.js +21 -0
- package/dist/stats/geomean.js.map +1 -0
- package/dist/stats/mannwhitney.d.ts +27 -0
- package/dist/stats/mannwhitney.js +158 -0
- package/dist/stats/mannwhitney.js.map +1 -0
- package/dist/verdict/verdict.d.ts +46 -0
- package/dist/verdict/verdict.js +102 -0
- package/dist/verdict/verdict.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/package.json +35 -0
- package/templates/program.md +131 -0
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The gate chain: everything one `eval` invocation does between "the agent
|
|
3
|
+
* made a commit" and "here is a verdict." Gate order is the design, not an
|
|
4
|
+
* implementation detail -- each gate must reject before anything past it
|
|
5
|
+
* runs, and in particular before any benchmark child is ever spawned.
|
|
6
|
+
*
|
|
7
|
+
* The eleven checks, in the order the brief specifies:
|
|
8
|
+
*
|
|
9
|
+
* 1. scope -- every changed file is in `config.scope` (or immutable
|
|
10
|
+
* -> unconditional reject regardless of scope)
|
|
11
|
+
* 2. config integrity -- `.autor3search/config.yaml` hashes to what baseline
|
|
12
|
+
* recorded; the agent cannot loosen its own rules
|
|
13
|
+
* 3. restore -- frozen tests/benchmarks are put back exactly as they
|
|
14
|
+
* were at baseline, whether or not they were "in scope"
|
|
15
|
+
* 4. unmanifested -- no new test/bench/runner-config file has appeared
|
|
16
|
+
* that baseline never froze ("add an easier benchmark")
|
|
17
|
+
* 5. typecheck -- `config.typecheckCommand`, skipped when empty
|
|
18
|
+
* 6. build -- `config.buildCommand`, skipped when empty
|
|
19
|
+
* 7. test -- `config.testCommand` (never empty)
|
|
20
|
+
* 8. worktree integrity -- the candidate's own working tree is clean and HEAD
|
|
21
|
+
* has moved past `baseline.measureCommit` (measuring
|
|
22
|
+
* an uncommitted edit and crediting it to a commit
|
|
23
|
+
* that never contained it would let one uncommitted
|
|
24
|
+
* optimization be scored forever); the pinned
|
|
25
|
+
* baseline worktree still exists and its lockfile
|
|
26
|
+
* is untouched -- if it is merely at the wrong
|
|
27
|
+
* commit (an interrupted step 11 advance), it is
|
|
28
|
+
* repointed and restored automatically here
|
|
29
|
+
* rather than refused
|
|
30
|
+
* 9. measure -- interleaved benchmark measurement, base vs. candidate
|
|
31
|
+
* 10. score -- `compareAll` + `decide`
|
|
32
|
+
* 11. on KEEP -- advance `measureCommit` (never `frozenCommit`)
|
|
33
|
+
*
|
|
34
|
+
* A `results.tsv` row is appended for every outcome this function actually
|
|
35
|
+
* returns from -- FAIL and CRASH included -- because "an eval ran and was
|
|
36
|
+
* refused" is itself part of the experiment record.
|
|
37
|
+
*/
|
|
38
|
+
import { access, readFile } from 'node:fs/promises';
|
|
39
|
+
import path from 'node:path';
|
|
40
|
+
import { runChild } from '../benchrun/invoke.js';
|
|
41
|
+
import { loadConfig, parseDuration } from '../config/load.js';
|
|
42
|
+
import { freezableFiles } from '../discover/files.js';
|
|
43
|
+
import { findUnmanifested, restore } from '../freeze/freeze.js';
|
|
44
|
+
import { hashString } from '../freeze/manifest.js';
|
|
45
|
+
import { changedFiles, headCommit, repointWorktree } from '../gitx/git.js';
|
|
46
|
+
import { interleave } from '../measure/interleave.js';
|
|
47
|
+
import { appendRow, loadRows } from '../results/results.js';
|
|
48
|
+
import { checkScope } from '../scope/scope.js';
|
|
49
|
+
import { ALPHA, compareAll } from '../stats/delta.js';
|
|
50
|
+
import { readBaseline, writeBaseline } from '../state/baseline.js';
|
|
51
|
+
import { acquireEvalLock } from '../state/lock.js';
|
|
52
|
+
import { runDir } from '../state/home.js';
|
|
53
|
+
import { readStop } from '../state/stop.js';
|
|
54
|
+
import { FROZEN_DIRNAME, WORKTREE_DIRNAME } from '../state/runnaming.js';
|
|
55
|
+
import { ok, runShell, tail } from '../runner/exec.js';
|
|
56
|
+
import { decide } from '../verdict/verdict.js';
|
|
57
|
+
function messageOf(e) {
|
|
58
|
+
return e instanceof Error ? e.message : String(e);
|
|
59
|
+
}
|
|
60
|
+
async function exists(p) {
|
|
61
|
+
try {
|
|
62
|
+
await access(p);
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/** `<file>:<fn>` -> `{ id, file, fn }`. The inverse of how `discoverBenchmarks` builds an id. */
|
|
70
|
+
function parseBenchmarkId(id) {
|
|
71
|
+
const idx = id.lastIndexOf(':');
|
|
72
|
+
if (idx === -1) {
|
|
73
|
+
throw new Error(`malformed benchmark id in baseline record: ${JSON.stringify(id)}`);
|
|
74
|
+
}
|
|
75
|
+
return { id, file: id.slice(0, idx), fn: id.slice(idx + 1) };
|
|
76
|
+
}
|
|
77
|
+
function noVerdict(status) {
|
|
78
|
+
// fail/crash never reach decide() -- nothing was scored, so score,
|
|
79
|
+
// correctedAlpha and regressions are all placeholders, not measurements.
|
|
80
|
+
// ALPHA (uncorrected) is used rather than a computed correction because no
|
|
81
|
+
// benchmark count is known at this point.
|
|
82
|
+
return { status, score: 1, regressions: [], correctedAlpha: ALPHA, warnings: [] };
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Runs one experiment end to end: the full gate chain, and -- for whatever
|
|
86
|
+
* outcome it ends in -- one `results.tsv` row.
|
|
87
|
+
*
|
|
88
|
+
* The eval lock is held for the whole chain and released in a `finally`, so
|
|
89
|
+
* a crash mid-chain (this function throwing something genuinely
|
|
90
|
+
* unanticipated) never leaves a future eval permanently blocked.
|
|
91
|
+
*/
|
|
92
|
+
export async function runEval(opts) {
|
|
93
|
+
const dir = runDir(opts.ctx.repoRoot, opts.tag);
|
|
94
|
+
const release = await acquireEvalLock(dir);
|
|
95
|
+
try {
|
|
96
|
+
return await evaluate(opts, dir);
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
await release();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
async function evaluate(opts, dir) {
|
|
103
|
+
const log = opts.log ?? (() => { });
|
|
104
|
+
const worktreeDir = path.join(dir, WORKTREE_DIRNAME);
|
|
105
|
+
const frozenDir = path.join(dir, FROZEN_DIRNAME);
|
|
106
|
+
const stopRequested = (await readStop(dir)) !== null;
|
|
107
|
+
let candidateCommit = 'unknown';
|
|
108
|
+
try {
|
|
109
|
+
candidateCommit = await headCommit(opts.ctx.repoRoot);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
// Best effort only -- a row still needs *some* commit string, and a
|
|
113
|
+
// git failure this early will also fail loudly below anyway.
|
|
114
|
+
}
|
|
115
|
+
const warnings = [];
|
|
116
|
+
const restoredFiles = [];
|
|
117
|
+
let baseline;
|
|
118
|
+
let config;
|
|
119
|
+
/**
|
|
120
|
+
* Builds the final outcome for any terminal state (fail, crash, discard or
|
|
121
|
+
* keep), appends its results.tsv row, and returns. The row is appended
|
|
122
|
+
* for every path through this function -- a rejected or crashed
|
|
123
|
+
* experiment is still part of the record.
|
|
124
|
+
*/
|
|
125
|
+
async function finish(verdict, deltas, failedGate, message) {
|
|
126
|
+
const frozenCommit = baseline?.frozenCommit ?? 'unknown';
|
|
127
|
+
const measureCommit = baseline?.measureCommit ?? 'unknown';
|
|
128
|
+
const allWarnings = [...warnings, ...verdict.warnings];
|
|
129
|
+
const priorRows = await loadRows(opts.ctx.resultsPath);
|
|
130
|
+
const experiment = priorRows.length + 1;
|
|
131
|
+
const bestBenchDelta = deltas.length > 0 ? Math.min(...deltas.map((d) => d.pctChange)) : 0;
|
|
132
|
+
const pMin = deltas.length > 0 ? Math.min(...deltas.map((d) => d.p)) : 1;
|
|
133
|
+
// results.tsv's `reason` column only ever holds a `DiscardReason` or ''
|
|
134
|
+
// (loadRows rejects anything else) -- a FAIL/CRASH's free-text `message`
|
|
135
|
+
// cannot go there. Folding it into `description` instead is the only
|
|
136
|
+
// place in the fixed 7-column row that can carry it, so a FAIL/CRASH row
|
|
137
|
+
// is not left with an empty reason AND an empty description, the way a
|
|
138
|
+
// plain `opts.description` passthrough would leave it whenever the agent
|
|
139
|
+
// did not also pass `-desc`.
|
|
140
|
+
const isFailure = verdict.status === 'fail' || verdict.status === 'crash';
|
|
141
|
+
const description = isFailure
|
|
142
|
+
? opts.description.length > 0
|
|
143
|
+
? `${opts.description}: ${message}`
|
|
144
|
+
: message
|
|
145
|
+
: opts.description;
|
|
146
|
+
const row = {
|
|
147
|
+
commit: candidateCommit,
|
|
148
|
+
score: verdict.score,
|
|
149
|
+
bestBenchDelta,
|
|
150
|
+
pMin,
|
|
151
|
+
status: verdict.status,
|
|
152
|
+
reason: verdict.reason ?? '',
|
|
153
|
+
description,
|
|
154
|
+
};
|
|
155
|
+
await appendRow(opts.ctx.resultsPath, row);
|
|
156
|
+
return {
|
|
157
|
+
verdict,
|
|
158
|
+
deltas,
|
|
159
|
+
stopRequested,
|
|
160
|
+
...(failedGate !== undefined ? { failedGate } : {}),
|
|
161
|
+
message,
|
|
162
|
+
warnings: allWarnings,
|
|
163
|
+
restoredFiles,
|
|
164
|
+
candidateCommit,
|
|
165
|
+
frozenCommit,
|
|
166
|
+
measureCommit,
|
|
167
|
+
experiment,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
// --- Load baseline and config. Either failing is a harness/environment
|
|
171
|
+
// problem, not a policy decision about the agent's change (there is no
|
|
172
|
+
// change to have a policy about yet) -- CRASH, not FAIL. Reporting FAIL
|
|
173
|
+
// here would tell an unattended agent "your change was rejected, try
|
|
174
|
+
// another," which for "no baseline exists yet" is actively false and
|
|
175
|
+
// would loop it forever discarding otherwise-good work.
|
|
176
|
+
try {
|
|
177
|
+
baseline = await readBaseline(dir);
|
|
178
|
+
}
|
|
179
|
+
catch (e) {
|
|
180
|
+
return finish(noVerdict('crash'), [], 'setup', messageOf(e));
|
|
181
|
+
}
|
|
182
|
+
try {
|
|
183
|
+
config = await loadConfig(opts.ctx.configPath);
|
|
184
|
+
}
|
|
185
|
+
catch (e) {
|
|
186
|
+
return finish(noVerdict('crash'), [], 'setup', messageOf(e));
|
|
187
|
+
}
|
|
188
|
+
// --- Gate 1: scope. Immutable files reject unconditionally, regardless of
|
|
189
|
+
// `config.scope` -- see `checkScope`. A failure to even COMPUTE the
|
|
190
|
+
// changed-file list (git itself failing) is a harness problem, not a
|
|
191
|
+
// scope verdict about the change -- CRASH.
|
|
192
|
+
let changed;
|
|
193
|
+
try {
|
|
194
|
+
changed = await changedFiles(opts.ctx.repoRoot, baseline.frozenCommit);
|
|
195
|
+
}
|
|
196
|
+
catch (e) {
|
|
197
|
+
return finish(noVerdict('crash'), [], 'scope', `could not compute changed files: ${messageOf(e)}`);
|
|
198
|
+
}
|
|
199
|
+
const violations = checkScope(changed, config.scope);
|
|
200
|
+
if (violations.length > 0) {
|
|
201
|
+
const list = violations.map((v) => `${v.file} (${v.reason})`).join(', ');
|
|
202
|
+
return finish(noVerdict('fail'), [], 'scope', `scope violation: ${list}`);
|
|
203
|
+
}
|
|
204
|
+
// --- Gate 2: config integrity. The config that produced `baseline` must
|
|
205
|
+
// still be exactly what is on disk -- this is what stops the agent
|
|
206
|
+
// loosening its own rules mid-run.
|
|
207
|
+
let configText;
|
|
208
|
+
try {
|
|
209
|
+
configText = await readFile(opts.ctx.configPath, 'utf8');
|
|
210
|
+
}
|
|
211
|
+
catch (e) {
|
|
212
|
+
return finish(noVerdict('crash'), [], 'config-integrity', `could not read config: ${messageOf(e)}`);
|
|
213
|
+
}
|
|
214
|
+
if (hashString(configText) !== baseline.configHash) {
|
|
215
|
+
return finish(noVerdict('fail'), [], 'config-integrity', `${path.basename(opts.ctx.configPath)} has changed since baseline: the run configuration is frozen`);
|
|
216
|
+
}
|
|
217
|
+
// Captured HERE, before gate 3 ever touches the working tree: gate 3's own
|
|
218
|
+
// restore intentionally leaves tracked frozen files differing from HEAD
|
|
219
|
+
// (that is the whole point -- the measured content must be the frozen
|
|
220
|
+
// bytes, not whatever the agent committed), which makes the tree dirty on
|
|
221
|
+
// its own. Checking cleanliness after that would misreport every
|
|
222
|
+
// legitimate restore as an uncommitted-change violation. What gate 8 must
|
|
223
|
+
// police is whether the AGENT's own commit left the tree clean, which is
|
|
224
|
+
// exactly what this snapshot -- taken before any harness mutation -- answers.
|
|
225
|
+
//
|
|
226
|
+
// Deliberately `changedFiles(repoRoot, candidateCommit)` (HEAD), NOT
|
|
227
|
+
// `isClean` (`git status --porcelain`): `isClean` respects whatever
|
|
228
|
+
// `.gitignore` is on disk, including one the agent just wrote --
|
|
229
|
+
// `printf '*\n' > src/lib/.gitignore` hides an uncommitted, IN-SCOPE file
|
|
230
|
+
// from `git status` entirely, so `isClean` would report a clean tree
|
|
231
|
+
// while the working tree still differs from HEAD. That is the exact C1
|
|
232
|
+
// attack (measure an uncommitted edit, credit it to a commit that never
|
|
233
|
+
// contained it) surviving Priority 2's scope-gate fix by hiding from THIS
|
|
234
|
+
// gate instead: the scope gate happily lets an in-scope file through, and
|
|
235
|
+
// a gitignore-trusting clean check never sees it was never committed.
|
|
236
|
+
// `changedFiles` is already immune to this (see its own doc comment) --
|
|
237
|
+
// reusing it here means gate 8 inherits that immunity by construction,
|
|
238
|
+
// not by remembering to reimplement it a second time.
|
|
239
|
+
let treeWasCleanBeforeRestore = true;
|
|
240
|
+
try {
|
|
241
|
+
treeWasCleanBeforeRestore = (await changedFiles(opts.ctx.repoRoot, candidateCommit)).length === 0;
|
|
242
|
+
}
|
|
243
|
+
catch (e) {
|
|
244
|
+
return finish(noVerdict('crash'), [], 'worktree-integrity', `could not check working tree cleanliness: ${messageOf(e)}`);
|
|
245
|
+
}
|
|
246
|
+
// --- Gate 3: restore. Frozen files are put back exactly as they were,
|
|
247
|
+
// whether or not the agent's edit to them was "in scope" -- a test file
|
|
248
|
+
// edit is legal to make, but its content is not legal to keep. A failure
|
|
249
|
+
// here (e.g. the frozen snapshot itself is missing or unreadable) is a
|
|
250
|
+
// harness-state problem, not something the agent's change did -- CRASH.
|
|
251
|
+
try {
|
|
252
|
+
const changedByRestore = await restore(opts.ctx.repoRoot, frozenDir, baseline.manifest);
|
|
253
|
+
restoredFiles.push(...changedByRestore);
|
|
254
|
+
if (changedByRestore.length > 0) {
|
|
255
|
+
warnings.push(`restored ${changedByRestore.length} frozen file(s) modified since baseline: ${changedByRestore.join(', ')}`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
catch (e) {
|
|
259
|
+
return finish(noVerdict('crash'), [], 'restore', `could not restore frozen files: ${messageOf(e)}`);
|
|
260
|
+
}
|
|
261
|
+
// --- Gate 4: unmanifested. A new test/bench/runner-config file absent
|
|
262
|
+
// from the frozen manifest is rejected outright -- this is what closes
|
|
263
|
+
// "add an easier benchmark." A failure to even list the candidate files
|
|
264
|
+
// (a filesystem walk failing) is a harness problem -- CRASH.
|
|
265
|
+
let candidates;
|
|
266
|
+
try {
|
|
267
|
+
candidates = await freezableFiles(opts.ctx.repoRoot);
|
|
268
|
+
}
|
|
269
|
+
catch (e) {
|
|
270
|
+
return finish(noVerdict('crash'), [], 'unmanifested', `could not list freezable files: ${messageOf(e)}`);
|
|
271
|
+
}
|
|
272
|
+
const extra = findUnmanifested(candidates, baseline.manifest, config.unfreeze);
|
|
273
|
+
if (extra.length > 0) {
|
|
274
|
+
return finish(noVerdict('fail'), [], 'unmanifested', `new test/bench/runner-config file(s) not present at baseline: ${extra.join(', ')}`);
|
|
275
|
+
}
|
|
276
|
+
const timeoutMs = parseDuration(config.timeout);
|
|
277
|
+
// --- Gate 5: typecheck (skipped when empty).
|
|
278
|
+
if (config.typecheckCommand.trim() !== '') {
|
|
279
|
+
const r = await runShell(config.typecheckCommand, { cwd: opts.ctx.repoRoot, timeoutMs, log });
|
|
280
|
+
if (!ok(r)) {
|
|
281
|
+
return finish(noVerdict('fail'), [], 'typecheck', `typecheck command failed (${config.typecheckCommand}, exit ${r.exitCode}): ${tail(r.stderr || r.stdout, 40)}`);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
// --- Gate 6: build (skipped when empty).
|
|
285
|
+
if (config.buildCommand.trim() !== '') {
|
|
286
|
+
const r = await runShell(config.buildCommand, { cwd: opts.ctx.repoRoot, timeoutMs, log });
|
|
287
|
+
if (!ok(r)) {
|
|
288
|
+
return finish(noVerdict('fail'), [], 'build', `build command failed (${config.buildCommand}, exit ${r.exitCode}): ${tail(r.stderr || r.stdout, 40)}`);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
// --- Gate 7: test (never empty -- enforced by config validation).
|
|
292
|
+
{
|
|
293
|
+
const r = await runShell(config.testCommand, { cwd: opts.ctx.repoRoot, timeoutMs, log });
|
|
294
|
+
if (!ok(r)) {
|
|
295
|
+
return finish(noVerdict('fail'), [], 'test', `test command failed (${config.testCommand}, exit ${r.exitCode}): ${tail(r.stderr || r.stdout, 40)}`);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
// --- Gate 8: worktree integrity.
|
|
299
|
+
//
|
|
300
|
+
// The candidate is measured from `opts.ctx.repoRoot` -- the live working
|
|
301
|
+
// tree, not a checkout of `candidateCommit` -- so nothing upstream of this
|
|
302
|
+
// gate stops an agent from applying a real optimization and never
|
|
303
|
+
// committing it: the working tree keeps the win, `candidateCommit` (and
|
|
304
|
+
// `measureCommit` after a KEEP) stays wherever HEAD already was, and the
|
|
305
|
+
// same uncommitted edit can be measured and credited indefinitely. Both
|
|
306
|
+
// checks below are FAIL, not CRASH: they describe the agent's own change
|
|
307
|
+
// (or lack of one), not a harness malfunction.
|
|
308
|
+
if (!treeWasCleanBeforeRestore) {
|
|
309
|
+
return finish(noVerdict('fail'), [], 'worktree-integrity', 'the working tree is not clean (uncommitted changes or untracked files): the candidate is ' +
|
|
310
|
+
'measured from this working tree, and crediting an uncommitted edit to a commit that never ' +
|
|
311
|
+
'contained it would let the same edit be measured and kept forever without ever landing. ' +
|
|
312
|
+
'Commit your change, then run eval.');
|
|
313
|
+
}
|
|
314
|
+
if (candidateCommit === baseline.measureCommit) {
|
|
315
|
+
return finish(noVerdict('fail'), [], 'worktree-integrity', `HEAD (${candidateCommit}) is the same commit already recorded as measureCommit: there is ` +
|
|
316
|
+
'nothing new to evaluate. Commit your change, then run eval.');
|
|
317
|
+
}
|
|
318
|
+
const worktreeResult = await checkWorktreeIntegrity(worktreeDir, frozenDir, baseline);
|
|
319
|
+
if (worktreeResult.warning !== null)
|
|
320
|
+
warnings.push(worktreeResult.warning);
|
|
321
|
+
if (worktreeResult.error !== null) {
|
|
322
|
+
return finish(noVerdict('fail'), [], 'worktree-integrity', worktreeResult.error);
|
|
323
|
+
}
|
|
324
|
+
// --- Gate 9: measure.
|
|
325
|
+
const benchmarks = baseline.benchmarks.map(parseBenchmarkId);
|
|
326
|
+
const benchtimeMs = parseDuration(config.benchtime);
|
|
327
|
+
const warmupMs = parseDuration(config.warmup);
|
|
328
|
+
const defaultMeasureOne = async (measureDir, b) => {
|
|
329
|
+
const result = await runChild({
|
|
330
|
+
cwd: measureDir,
|
|
331
|
+
benchFileAbs: path.join(measureDir, b.file),
|
|
332
|
+
fn: b.fn,
|
|
333
|
+
id: b.id,
|
|
334
|
+
benchtimeMs,
|
|
335
|
+
warmupMs,
|
|
336
|
+
timeoutMs,
|
|
337
|
+
nodeArgs: config.nodeArgs,
|
|
338
|
+
log,
|
|
339
|
+
});
|
|
340
|
+
if (!result.ok) {
|
|
341
|
+
throw new Error(`benchmark ${b.id} crashed in ${measureDir}: ${result.error}`);
|
|
342
|
+
}
|
|
343
|
+
return result.nsPerOp;
|
|
344
|
+
};
|
|
345
|
+
const measureOne = opts.measureOne ?? defaultMeasureOne;
|
|
346
|
+
let base;
|
|
347
|
+
let cand;
|
|
348
|
+
try {
|
|
349
|
+
;
|
|
350
|
+
({ base, cand } = await interleave({
|
|
351
|
+
rounds: config.count,
|
|
352
|
+
benchmarks,
|
|
353
|
+
baseDir: worktreeDir,
|
|
354
|
+
candDir: opts.ctx.repoRoot,
|
|
355
|
+
measureOne,
|
|
356
|
+
}));
|
|
357
|
+
}
|
|
358
|
+
catch (e) {
|
|
359
|
+
return finish(noVerdict('crash'), [], 'measure', messageOf(e));
|
|
360
|
+
}
|
|
361
|
+
// --- Gate 10: score.
|
|
362
|
+
let deltas;
|
|
363
|
+
try {
|
|
364
|
+
deltas = compareAll(base, cand);
|
|
365
|
+
}
|
|
366
|
+
catch (e) {
|
|
367
|
+
return finish(noVerdict('crash'), [], 'measure', messageOf(e));
|
|
368
|
+
}
|
|
369
|
+
const verdict = decide({
|
|
370
|
+
deltas,
|
|
371
|
+
minEffectPct: config.minEffectPct,
|
|
372
|
+
maxRegressPct: config.maxRegressPct,
|
|
373
|
+
rounds: config.count,
|
|
374
|
+
});
|
|
375
|
+
// --- Step 11: on KEEP, advance measureCommit. frozenCommit and the
|
|
376
|
+
// manifest are never touched -- moving the measurement point must never
|
|
377
|
+
// move the success criteria.
|
|
378
|
+
//
|
|
379
|
+
// `writeBaseline` runs FIRST, before either worktree operation --
|
|
380
|
+
// deliberately, so the sequence is recoverable rather than merely
|
|
381
|
+
// atomic-looking. A KEEP is a real, already-decided fact the moment
|
|
382
|
+
// `decide()` returns it; `measureCommit` recording that fact must not
|
|
383
|
+
// depend on two more subprocess calls (`repointWorktree`, `restore`)
|
|
384
|
+
// succeeding first. If either fails or the process dies here, the NEXT
|
|
385
|
+
// eval's gate 8 sees a worktree merely behind the now-already-recorded
|
|
386
|
+
// `measureCommit` -- a state it repairs itself (see
|
|
387
|
+
// `checkWorktreeIntegrity`) instead of demanding `baseline -force`, which
|
|
388
|
+
// would silently re-freeze from whatever is at HEAD by then.
|
|
389
|
+
//
|
|
390
|
+
// `repointWorktree` checks out the candidate commit's OWN tree into the
|
|
391
|
+
// base worktree -- tampered bench/test content included, since freezing
|
|
392
|
+
// only pins byte content in the manifest and the frozen snapshot, not
|
|
393
|
+
// what a later commit is allowed to contain. Gate 3 already restored
|
|
394
|
+
// `repoRoot`'s WORKING TREE for this experiment's own measurement, but
|
|
395
|
+
// that restoration never touches the commit itself, so without also
|
|
396
|
+
// restoring the worktree here, a candidate commit that both fixes the
|
|
397
|
+
// source AND slows the benchmark body would earn a legitimate KEEP now
|
|
398
|
+
// and then permanently inflate every future baseline measurement -- "add
|
|
399
|
+
// an easier benchmark," routed around gate 4 (which only checks the
|
|
400
|
+
// manifest, not commit content) via the one place gate 3's fix never
|
|
401
|
+
// reaches. Restoring the worktree's frozen files immediately after the
|
|
402
|
+
// repoint closes that gap: both sides always measure the SAME frozen
|
|
403
|
+
// benchmark bytes, regardless of what any given commit holds.
|
|
404
|
+
if (verdict.status === 'keep') {
|
|
405
|
+
try {
|
|
406
|
+
const advanced = { ...baseline, measureCommit: candidateCommit };
|
|
407
|
+
await writeBaseline(dir, advanced);
|
|
408
|
+
baseline = advanced;
|
|
409
|
+
await repointWorktree(worktreeDir, candidateCommit);
|
|
410
|
+
await restore(worktreeDir, frozenDir, baseline.manifest);
|
|
411
|
+
}
|
|
412
|
+
catch (e) {
|
|
413
|
+
// A genuine KEEP was already decided -- this is a harness failure
|
|
414
|
+
// advancing the measurement point, not a verdict about the change,
|
|
415
|
+
// so it must not read as FAIL ("your change was rejected"). CRASH is
|
|
416
|
+
// also why this experiment still gets a results.tsv row here, rather
|
|
417
|
+
// than an exception escaping with nothing recorded at all.
|
|
418
|
+
return finish(noVerdict('crash'), deltas, 'advance', messageOf(e));
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
return finish(verdict, deltas, undefined, `${verdict.status}${verdict.reason ? `: ${verdict.reason}` : ''}`);
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* The `"baseline -force" to recreate it` advice this function used to give
|
|
425
|
+
* for EVERY problem was actively harmful for the one case (below) that is
|
|
426
|
+
* cheaply self-healing: `-force` re-derives the freeze manifest from
|
|
427
|
+
* whatever is at HEAD when it runs, silently adopting the agent's own
|
|
428
|
+
* commits as the new correctness contract -- exactly the "grade its own
|
|
429
|
+
* homework" failure mode this whole tool exists to prevent. It is still the
|
|
430
|
+
* right advice for the two cases that genuinely have no cheaper fix
|
|
431
|
+
* (the worktree is gone; the lockfile itself changed), so those messages
|
|
432
|
+
* now say so explicitly rather than presenting `-force` as a free action.
|
|
433
|
+
*/
|
|
434
|
+
async function checkWorktreeIntegrity(worktreeDir, frozenDir, baseline) {
|
|
435
|
+
if (!(await exists(worktreeDir))) {
|
|
436
|
+
return {
|
|
437
|
+
error: `no worktree at ${worktreeDir}: it is missing and must be re-created. "baseline -force" ` +
|
|
438
|
+
'will do that, but it also re-freezes tests/benchmarks from the CURRENT HEAD, adopting ' +
|
|
439
|
+
'whatever is committed there as the new frozen contract -- review what has changed since ' +
|
|
440
|
+
'the original baseline before running it.',
|
|
441
|
+
warning: null,
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
let atCommit;
|
|
445
|
+
try {
|
|
446
|
+
atCommit = await headCommit(worktreeDir);
|
|
447
|
+
}
|
|
448
|
+
catch (e) {
|
|
449
|
+
return { error: `could not read the worktree's HEAD: ${messageOf(e)}`, warning: null };
|
|
450
|
+
}
|
|
451
|
+
let warning = null;
|
|
452
|
+
if (atCommit !== baseline.measureCommit) {
|
|
453
|
+
// Merely being at the wrong commit is cheaply recoverable WITHOUT
|
|
454
|
+
// re-freezing anything: `baseline.measureCommit` is already the
|
|
455
|
+
// authoritative value by the time this ever runs (step 11 writes it
|
|
456
|
+
// before touching the worktree at all), so this is exactly the state a
|
|
457
|
+
// crash between that write and the repoint/restore that follows it
|
|
458
|
+
// would leave behind -- self-healed here instead of demanded of the
|
|
459
|
+
// human via `-force`. `frozenCommit` and `baseline.manifest` are never
|
|
460
|
+
// touched by this: only the MEASUREMENT point is being caught up.
|
|
461
|
+
try {
|
|
462
|
+
await repointWorktree(worktreeDir, baseline.measureCommit);
|
|
463
|
+
await restore(worktreeDir, frozenDir, baseline.manifest);
|
|
464
|
+
}
|
|
465
|
+
catch (e) {
|
|
466
|
+
return {
|
|
467
|
+
error: `the worktree is at ${atCommit} but baseline.measureCommit is ${baseline.measureCommit}, ` +
|
|
468
|
+
`and repairing it automatically failed: ${messageOf(e)}`,
|
|
469
|
+
warning: null,
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
warning =
|
|
473
|
+
`the baseline worktree was at ${atCommit}, behind baseline.measureCommit ` +
|
|
474
|
+
`(${baseline.measureCommit}) -- likely left over from an interrupted measureCommit advance -- ` +
|
|
475
|
+
'and was repointed and restored automatically';
|
|
476
|
+
}
|
|
477
|
+
let lockfileText;
|
|
478
|
+
try {
|
|
479
|
+
lockfileText = await readFile(path.join(worktreeDir, baseline.lockfileName), 'utf8');
|
|
480
|
+
}
|
|
481
|
+
catch (e) {
|
|
482
|
+
return { error: `could not read the worktree's lockfile (${baseline.lockfileName}): ${messageOf(e)}`, warning };
|
|
483
|
+
}
|
|
484
|
+
if (hashString(lockfileText) !== baseline.lockfileHash) {
|
|
485
|
+
return {
|
|
486
|
+
error: `the worktree's lockfile (${baseline.lockfileName}) no longer matches baseline.lockfileHash: ` +
|
|
487
|
+
'dependencies must be reinstalled. "baseline -force" will do that, but it also re-freezes ' +
|
|
488
|
+
'tests/benchmarks from the CURRENT HEAD, adopting whatever is committed there as the new ' +
|
|
489
|
+
'frozen contract -- review what has changed since the original baseline before running it.',
|
|
490
|
+
warning,
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
return { error: null, warning };
|
|
494
|
+
}
|
|
495
|
+
//# sourceMappingURL=eval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eval.js","sourceRoot":"","sources":["../../src/pipeline/eval.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun';
|
|
2
|
+
export interface Detected {
|
|
3
|
+
pm: PackageManager;
|
|
4
|
+
lockfile: string;
|
|
5
|
+
/** A frozen-lockfile install: reproducible, and it fails rather than drifting. */
|
|
6
|
+
installCommand: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Refuses a workspace root.
|
|
10
|
+
*
|
|
11
|
+
* v0.1 supports single-package repositories only. Saying so plainly is much
|
|
12
|
+
* better than half-working: in a workspace the scope gate, the freeze set and
|
|
13
|
+
* the install layout all mean something different, and getting any of them
|
|
14
|
+
* subtly wrong weakens a guarantee the user believes they have.
|
|
15
|
+
*/
|
|
16
|
+
export declare function assertSinglePackage(pkgJsonText: string, root: string): Promise<void>;
|
|
17
|
+
export declare function detect(root: string): Promise<Detected>;
|