lastlight-evals 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/README.md +187 -0
- package/datasets/code-fix/instances.json +26 -0
- package/datasets/code-fix/repos/codefix__date-range-off-by-one/README.md +8 -0
- package/datasets/code-fix/repos/codefix__date-range-off-by-one/package.json +9 -0
- package/datasets/code-fix/repos/codefix__date-range-off-by-one/src/date-range.ts +25 -0
- package/datasets/code-fix/tests/codefix__date-range-off-by-one/date-range.test.ts +18 -0
- package/datasets/code-fix/tier.json +5 -0
- package/datasets/triage/instances.json +62 -0
- package/datasets/triage/tier.json +5 -0
- package/dist/bootstrap.js +46 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/discovery.js +100 -0
- package/dist/discovery.js.map +1 -0
- package/dist/env.js +109 -0
- package/dist/env.js.map +1 -0
- package/dist/fake-github.js +249 -0
- package/dist/fake-github.js.map +1 -0
- package/dist/grade.js +134 -0
- package/dist/grade.js.map +1 -0
- package/dist/html-report.js +325 -0
- package/dist/html-report.js.map +1 -0
- package/dist/init.js +122 -0
- package/dist/init.js.map +1 -0
- package/dist/mechanism.test.js +108 -0
- package/dist/mechanism.test.js.map +1 -0
- package/dist/metrics.js +86 -0
- package/dist/metrics.js.map +1 -0
- package/dist/paths.js +33 -0
- package/dist/paths.js.map +1 -0
- package/dist/report.js +137 -0
- package/dist/report.js.map +1 -0
- package/dist/run-instance.js +203 -0
- package/dist/run-instance.js.map +1 -0
- package/dist/run.js +476 -0
- package/dist/run.js.map +1 -0
- package/dist/schema.js +15 -0
- package/dist/schema.js.map +1 -0
- package/dist/seed.js +49 -0
- package/dist/seed.js.map +1 -0
- package/models.json +17 -0
- package/package.json +50 -0
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-contained HTML scorecard, styled to match the Last Light site
|
|
3
|
+
* (~/work/lastlight-www): dark navy theme, gold/orange/teal accents,
|
|
4
|
+
* Inter + JetBrains Mono. No build step, no external assets beyond Google
|
|
5
|
+
* Fonts — written straight to `evals/results/<tiers>/index.html`.
|
|
6
|
+
*
|
|
7
|
+
* One report, one tier per tab (radio-driven CSS, no JS). Each tab leads with
|
|
8
|
+
* a model-comparison table — models as rows, sorted by the tier's primary
|
|
9
|
+
* metric, with inline bar charts and best-in-column highlighting — followed by
|
|
10
|
+
* the per-instance detail rows.
|
|
11
|
+
*/
|
|
12
|
+
import { writeFileSync, mkdirSync, renameSync } from "node:fs";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
import { summarizeModels } from "./report.js";
|
|
15
|
+
const esc = (s) => String(s ?? "")
|
|
16
|
+
.replace(/&/g, "&")
|
|
17
|
+
.replace(/</g, "<")
|
|
18
|
+
.replace(/>/g, ">")
|
|
19
|
+
.replace(/"/g, """);
|
|
20
|
+
function pill(kind, label) {
|
|
21
|
+
return `<span class="pill ${kind}">${esc(label)}</span>`;
|
|
22
|
+
}
|
|
23
|
+
function fmtMs(ms) {
|
|
24
|
+
if (!ms)
|
|
25
|
+
return "—";
|
|
26
|
+
if (ms < 1000)
|
|
27
|
+
return `${ms}ms`;
|
|
28
|
+
const s = Math.round(ms / 1000);
|
|
29
|
+
return s < 60 ? `${s}s` : `${Math.floor(s / 60)}m${String(s % 60).padStart(2, "0")}`;
|
|
30
|
+
}
|
|
31
|
+
function tierMetric(tier) {
|
|
32
|
+
if (tier === "code-fix") {
|
|
33
|
+
return {
|
|
34
|
+
label: "resolved",
|
|
35
|
+
rate: (m) => (m.codeFixTotal ? m.codeFixResolved / m.codeFixTotal : 0),
|
|
36
|
+
frac: (m) => (m.codeFixTotal ? `${m.codeFixResolved}/${m.codeFixTotal}` : "—"),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
label: "behavioral",
|
|
41
|
+
rate: (m) => (m.behavioralTotal ? m.behavioralOk / m.behavioralTotal : 0),
|
|
42
|
+
frac: (m) => (m.behavioralTotal ? `${m.behavioralOk}/${m.behavioralTotal}` : "—"),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/** A horizontal bar (0..1 fill) with a value label beside it. */
|
|
46
|
+
function bar(frac, value, klass, best) {
|
|
47
|
+
const pct = Math.max(0, Math.min(1, frac)) * 100;
|
|
48
|
+
return `<div class="bar${best ? " best" : ""}"><span class="bar-track"><span class="bar-fill ${klass}" style="width:${pct.toFixed(1)}%"></span></span><span class="bar-val">${esc(value)}</span></div>`;
|
|
49
|
+
}
|
|
50
|
+
function compareTable(models, tier, labels) {
|
|
51
|
+
const metric = tierMetric(tier);
|
|
52
|
+
const ranked = [...models].sort((a, b) => metric.rate(b) - metric.rate(a) || a.totalCostUsd - b.totalCostUsd);
|
|
53
|
+
// Best-in-column references. Cost/latency only consider models that actually
|
|
54
|
+
// produced a run (cost > 0) so an errored 0-cost row isn't crowned "cheapest".
|
|
55
|
+
const bestRate = Math.max(0, ...ranked.map(metric.rate));
|
|
56
|
+
const costs = ranked.filter((m) => m.totalCostUsd > 0).map((m) => m.totalCostUsd);
|
|
57
|
+
const lats = ranked.filter((m) => m.p50DurationMs > 0).map((m) => m.p50DurationMs);
|
|
58
|
+
const minCost = costs.length ? Math.min(...costs) : Infinity;
|
|
59
|
+
const minLat = lats.length ? Math.min(...lats) : Infinity;
|
|
60
|
+
const maxCost = costs.length ? Math.max(...costs) : 1;
|
|
61
|
+
const maxLat = lats.length ? Math.max(...lats) : 1;
|
|
62
|
+
const rows = ranked
|
|
63
|
+
.map((m, i) => {
|
|
64
|
+
const rate = metric.rate(m);
|
|
65
|
+
const isBestRate = metric.frac(m) !== "—" && rate >= bestRate && bestRate > 0;
|
|
66
|
+
const isBestCost = m.totalCostUsd > 0 && m.totalCostUsd === minCost;
|
|
67
|
+
const isBestLat = m.p50DurationMs > 0 && m.p50DurationMs === minLat;
|
|
68
|
+
return `
|
|
69
|
+
<tr>
|
|
70
|
+
<td class="rank">${i + 1}</td>
|
|
71
|
+
<td class="mono model">${esc(labels[m.model] ?? m.model)}</td>
|
|
72
|
+
<td class="barcell">${bar(rate, metric.frac(m), "fill-gold", isBestRate)}</td>
|
|
73
|
+
<td class="barcell">${bar(maxCost ? m.totalCostUsd / maxCost : 0, `$${m.totalCostUsd.toFixed(3)}`, "fill-teal", isBestCost)}</td>
|
|
74
|
+
<td class="barcell">${bar(maxLat ? m.p50DurationMs / maxLat : 0, fmtMs(m.p50DurationMs), "fill-orange", isBestLat)}</td>
|
|
75
|
+
<td class="mono num">${Math.round(m.avgInputTokens)}<span class="muted">/</span>${Math.round(m.avgOutputTokens)}</td>
|
|
76
|
+
<td class="mono num ${m.errors ? "fail-fg" : "muted"}">${m.errors}</td>
|
|
77
|
+
</tr>`;
|
|
78
|
+
})
|
|
79
|
+
.join("\n");
|
|
80
|
+
return `
|
|
81
|
+
<table class="cmp">
|
|
82
|
+
<thead>
|
|
83
|
+
<tr>
|
|
84
|
+
<th class="rank">#</th><th>model</th>
|
|
85
|
+
<th>${esc(metric.label)} →</th><th>total cost ↓</th><th>p50 latency ↓</th>
|
|
86
|
+
<th class="num">avg in/out tok</th><th class="num">err</th>
|
|
87
|
+
</tr>
|
|
88
|
+
</thead>
|
|
89
|
+
<tbody>${rows}</tbody>
|
|
90
|
+
</table>`;
|
|
91
|
+
}
|
|
92
|
+
function checksHtml(r) {
|
|
93
|
+
const checks = r.behavioral?.checks ?? [];
|
|
94
|
+
if (!checks.length && r.resolved === undefined)
|
|
95
|
+
return '<span class="muted">—</span>';
|
|
96
|
+
const chips = checks
|
|
97
|
+
.map((c) => `<span class="chip ${c.ok ? "ok" : "no"}" title="${esc(c.detail ?? "")}">${esc(c.name)}</span>`)
|
|
98
|
+
.join("");
|
|
99
|
+
return chips || '<span class="muted">—</span>';
|
|
100
|
+
}
|
|
101
|
+
function detailRows(results, tier, labels) {
|
|
102
|
+
const showCodeFix = tier === "code-fix";
|
|
103
|
+
// "2/3" pass-count when a case aggregates multiple trials (worst-case verdict).
|
|
104
|
+
const frac = (pass, n) => pass !== undefined && n && n > 1 ? ` <span class="frac">${pass}/${n}</span>` : "";
|
|
105
|
+
return results
|
|
106
|
+
.map((r) => {
|
|
107
|
+
const resolved = (r.resolved === undefined ? pill("na", "—") : r.resolved ? pill("pass", "resolved") : pill("fail", "unresolved")) +
|
|
108
|
+
frac(r.resolvedPass, r.trials);
|
|
109
|
+
const beh = (r.error
|
|
110
|
+
? pill("fail", "error")
|
|
111
|
+
: r.behavioral
|
|
112
|
+
? r.behavioral.ok
|
|
113
|
+
? pill("pass", "ok")
|
|
114
|
+
: pill("fail", "miss")
|
|
115
|
+
: pill("na", "—")) + (r.error ? "" : frac(r.behavioralPass, r.trials));
|
|
116
|
+
return `
|
|
117
|
+
<tr>
|
|
118
|
+
<td class="mono">${esc(r.instance_id)}</td>
|
|
119
|
+
<td class="mono muted">${esc(labels[r.model] ?? r.model)}</td>
|
|
120
|
+
${showCodeFix ? `<td>${resolved}</td>` : ""}
|
|
121
|
+
<td>${beh}</td>
|
|
122
|
+
<td class="checks">${checksHtml(r)}</td>
|
|
123
|
+
<td class="mono num">$${r.costUsd.toFixed(4)}</td>
|
|
124
|
+
<td class="mono num">${fmtMs(r.durationMs)}</td>
|
|
125
|
+
</tr>${r.error ? `<tr class="errrow"><td colspan="${showCodeFix ? 7 : 6}" class="mono err">${esc(r.error)}</td></tr>` : ""}`;
|
|
126
|
+
})
|
|
127
|
+
.join("\n");
|
|
128
|
+
}
|
|
129
|
+
/** Rows for cases still running / queued (live runs only). */
|
|
130
|
+
function pendingRows(pending, tier, labels) {
|
|
131
|
+
const showCodeFix = tier === "code-fix";
|
|
132
|
+
// running before queued so the in-flight ones sit nearest the finished rows.
|
|
133
|
+
const ordered = [...pending].sort((a, b) => (a.status === b.status ? 0 : a.status === "running" ? -1 : 1));
|
|
134
|
+
return ordered
|
|
135
|
+
.map((pn) => {
|
|
136
|
+
const cell = pn.status === "running"
|
|
137
|
+
? '<span class="pill run">running…</span>'
|
|
138
|
+
: '<span class="pill wait">queued</span>';
|
|
139
|
+
const dash = '<span class="muted">—</span>';
|
|
140
|
+
return `
|
|
141
|
+
<tr class="pendingrow">
|
|
142
|
+
<td class="mono muted">${esc(pn.instance_id)}</td>
|
|
143
|
+
<td class="mono muted">${esc(labels[pn.model] ?? pn.model)}</td>
|
|
144
|
+
${showCodeFix ? `<td>${cell}</td><td>${dash}</td>` : `<td>${cell}</td>`}
|
|
145
|
+
<td>${dash}</td>
|
|
146
|
+
<td class="mono num muted">—</td>
|
|
147
|
+
<td class="mono num muted">—</td>
|
|
148
|
+
</tr>`;
|
|
149
|
+
})
|
|
150
|
+
.join("\n");
|
|
151
|
+
}
|
|
152
|
+
function tierPane(tier, results, pending, labels) {
|
|
153
|
+
const models = summarizeModels(results);
|
|
154
|
+
const showCodeFix = tier === "code-fix";
|
|
155
|
+
const detailHead = showCodeFix
|
|
156
|
+
? "<th>instance</th><th>model</th><th>code-fix</th><th>behavioral</th><th>checks</th><th>cost</th><th>latency</th>"
|
|
157
|
+
: "<th>instance</th><th>model</th><th>behavioral</th><th>checks</th><th>cost</th><th>latency</th>";
|
|
158
|
+
return `
|
|
159
|
+
<h2>Model comparison <span class="muted">— ${esc(tier)}</span></h2>
|
|
160
|
+
${compareTable(models, tier, labels)}
|
|
161
|
+
<h2>Per-instance results</h2>
|
|
162
|
+
<table>
|
|
163
|
+
<thead><tr>${detailHead}</tr></thead>
|
|
164
|
+
<tbody>${detailRows(results, tier, labels)}${pending.length ? pendingRows(pending, tier, labels) : ""}</tbody>
|
|
165
|
+
</table>`;
|
|
166
|
+
}
|
|
167
|
+
export function renderHtml(card, meta) {
|
|
168
|
+
const labels = meta.labels ?? {};
|
|
169
|
+
const pending = meta.pending ?? [];
|
|
170
|
+
// Preserve the requested tier order; keep tiers that have results OR pending
|
|
171
|
+
// work (so a tier's tab shows up before its first case finishes).
|
|
172
|
+
const tiers = meta.tiers.filter((t) => card.results.some((r) => (r.tier ?? meta.tiers[0]) === t) || pending.some((pn) => pn.tier === t));
|
|
173
|
+
const useTiers = tiers.length ? tiers : meta.tiers.slice(0, 1);
|
|
174
|
+
const radios = useTiers.map((_, i) => `<input type="radio" name="tier" id="t${i}"${i === 0 ? " checked" : ""}>`).join("\n ");
|
|
175
|
+
const tabs = useTiers.map((t, i) => `<label for="t${i}">${esc(t)}</label>`).join("\n ");
|
|
176
|
+
const panes = useTiers
|
|
177
|
+
.map((t, i) => {
|
|
178
|
+
const rs = card.results.filter((r) => (r.tier ?? useTiers[0]) === t);
|
|
179
|
+
const pn = pending.filter((x) => x.tier === t);
|
|
180
|
+
return `<section class="pane pane-${i}">${tierPane(t, rs, pn, labels)}</section>`;
|
|
181
|
+
})
|
|
182
|
+
.join("\n ");
|
|
183
|
+
// Per-index CSS so the checked radio reveals its pane + lights its tab.
|
|
184
|
+
const tabCss = useTiers
|
|
185
|
+
.map((_, i) => `#t${i}:checked ~ .pane-${i}{display:block;} #t${i}:checked ~ .tabs label[for=t${i}]{background:var(--gold);color:var(--navy);border-color:var(--gold);}`)
|
|
186
|
+
.join("\n ");
|
|
187
|
+
return `<!doctype html>
|
|
188
|
+
<html lang="en">
|
|
189
|
+
<head>
|
|
190
|
+
<meta charset="utf-8" />
|
|
191
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
192
|
+
${meta.live ? '<meta http-equiv="refresh" content="3" />' : ""}
|
|
193
|
+
<title>Last Light — Eval Scorecard</title>
|
|
194
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
195
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
196
|
+
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;600&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
|
197
|
+
<style>
|
|
198
|
+
:root {
|
|
199
|
+
--gold:#F0B429; --orange:#E8752A; --teal:#1A7A8A; --teal-dark:#135E6B;
|
|
200
|
+
--navy:#1B2735; --bg:#0C1117; --bg-card:#141B24; --bg-card-hover:#1A2332;
|
|
201
|
+
--border:#1E2A38; --text:#C9D1D9; --text-muted:#7D8694; --text-bright:#ECEFF4;
|
|
202
|
+
--pass:#3FB950; --fail:#E5534B;
|
|
203
|
+
--mono:'JetBrains Mono',monospace; --sans:'Inter',-apple-system,sans-serif;
|
|
204
|
+
}
|
|
205
|
+
* { box-sizing:border-box; }
|
|
206
|
+
body { margin:0; background:var(--bg); color:var(--text); font-family:var(--sans); line-height:1.55; }
|
|
207
|
+
.wrap { max-width:1100px; margin:0 auto; padding:48px 24px 80px; }
|
|
208
|
+
header { border-bottom:1px solid var(--border); padding-bottom:24px; margin-bottom:24px; }
|
|
209
|
+
h1 { color:var(--text-bright); font-size:30px; margin:0 0 6px; letter-spacing:-0.02em; }
|
|
210
|
+
h1 .accent { color:var(--gold); }
|
|
211
|
+
h2 { color:var(--text-bright); font-size:18px; margin:32px 0 14px; }
|
|
212
|
+
h2 .muted { font-weight:400; }
|
|
213
|
+
.meta { color:var(--text-muted); font-size:13px; font-family:var(--mono); }
|
|
214
|
+
.meta b { color:var(--text); font-weight:600; }
|
|
215
|
+
|
|
216
|
+
/* radio-driven tabs (no JS) */
|
|
217
|
+
input[name=tier] { position:absolute; opacity:0; pointer-events:none; }
|
|
218
|
+
.tabs { display:flex; gap:8px; margin-bottom:8px; flex-wrap:wrap; }
|
|
219
|
+
.tabs label { cursor:pointer; font-family:var(--mono); font-size:13px; font-weight:600;
|
|
220
|
+
padding:8px 16px; border-radius:8px; border:1px solid var(--border); color:var(--text-muted);
|
|
221
|
+
background:var(--bg-card); user-select:none; }
|
|
222
|
+
.tabs label:hover { color:var(--text-bright); border-color:var(--teal); }
|
|
223
|
+
.pane { display:none; }
|
|
224
|
+
${tabCss}
|
|
225
|
+
|
|
226
|
+
table { width:100%; border-collapse:collapse; background:var(--bg-card); border:1px solid var(--border); border-radius:12px; overflow:hidden; }
|
|
227
|
+
th { text-align:left; color:var(--text-muted); font-size:11px; text-transform:uppercase; letter-spacing:0.05em; font-weight:600; padding:11px 14px; border-bottom:1px solid var(--border); background:var(--navy); }
|
|
228
|
+
td { padding:10px 14px; border-bottom:1px solid var(--border); font-size:13px; vertical-align:middle; }
|
|
229
|
+
tr:last-child td { border-bottom:none; }
|
|
230
|
+
.mono { font-family:var(--mono); }
|
|
231
|
+
.num { text-align:right; white-space:nowrap; }
|
|
232
|
+
.muted { color:var(--text-muted); }
|
|
233
|
+
.fail-fg { color:var(--fail); }
|
|
234
|
+
|
|
235
|
+
/* comparison table */
|
|
236
|
+
table.cmp td { vertical-align:middle; }
|
|
237
|
+
.cmp .rank { width:30px; color:var(--text-muted); font-family:var(--mono); text-align:center; }
|
|
238
|
+
.cmp .model { color:var(--gold); font-weight:600; white-space:nowrap; }
|
|
239
|
+
.cmp .barcell { width:22%; min-width:140px; }
|
|
240
|
+
.bar { display:flex; align-items:center; gap:8px; }
|
|
241
|
+
.bar-track { flex:1; height:8px; background:var(--navy); border-radius:999px; overflow:hidden; }
|
|
242
|
+
.bar-fill { display:block; height:100%; border-radius:999px; }
|
|
243
|
+
.fill-gold { background:var(--gold); } .fill-teal { background:var(--teal); } .fill-orange { background:var(--orange); }
|
|
244
|
+
.bar-val { font-family:var(--mono); font-size:12px; min-width:48px; text-align:right; color:var(--text); }
|
|
245
|
+
.bar.best .bar-val { color:var(--pass); font-weight:600; }
|
|
246
|
+
.bar.best .bar-val::after { content:" ★"; color:var(--gold); font-size:10px; }
|
|
247
|
+
|
|
248
|
+
.pill { display:inline-block; font-family:var(--mono); font-size:11px; font-weight:600; padding:3px 9px; border-radius:999px; }
|
|
249
|
+
.pill.pass { background:rgba(63,185,80,0.14); color:var(--pass); }
|
|
250
|
+
.pill.fail { background:rgba(229,83,75,0.14); color:var(--fail); }
|
|
251
|
+
.pill.na { background:var(--navy); color:var(--text-muted); }
|
|
252
|
+
.pill.run { background:rgba(240,180,41,0.14); color:var(--gold); animation:pulse 1.4s ease-in-out infinite; }
|
|
253
|
+
.pill.wait { background:var(--navy); color:var(--text-muted); }
|
|
254
|
+
.pendingrow td { opacity:0.72; }
|
|
255
|
+
.frac { font-family:var(--mono); font-size:11px; color:var(--text-muted); }
|
|
256
|
+
.checks { line-height:2; }
|
|
257
|
+
.chip { display:inline-block; font-family:var(--mono); font-size:10.5px; padding:2px 7px; border-radius:5px; margin:0 4px 4px 0; border:1px solid var(--border); }
|
|
258
|
+
.chip.ok { color:var(--pass); border-color:rgba(63,185,80,0.4); }
|
|
259
|
+
.chip.no { color:var(--fail); border-color:rgba(229,83,75,0.4); }
|
|
260
|
+
.errrow td { color:var(--fail); background:rgba(229,83,75,0.06); }
|
|
261
|
+
.err { white-space:pre-wrap; }
|
|
262
|
+
footer { margin-top:40px; color:var(--text-muted); font-size:12px; font-family:var(--mono); }
|
|
263
|
+
a { color:var(--gold); }
|
|
264
|
+
.live { font-family:var(--mono); font-size:13px; color:var(--gold); font-weight:600; letter-spacing:0; vertical-align:middle; margin-left:10px; animation:pulse 1.4s ease-in-out infinite; }
|
|
265
|
+
@keyframes pulse { 0%,100%{opacity:1;} 50%{opacity:0.35;} }
|
|
266
|
+
</style>
|
|
267
|
+
</head>
|
|
268
|
+
<body>
|
|
269
|
+
<div class="wrap">
|
|
270
|
+
<header>
|
|
271
|
+
<h1>Last Light <span class="accent">·</span> Eval Scorecard${meta.live ? ` <span class="live">● live${meta.progress ? ` ${esc(meta.progress)}` : ""}</span>` : ""}</h1>
|
|
272
|
+
<div class="meta">
|
|
273
|
+
<b>${esc(useTiers.join(" + "))}</b> ·
|
|
274
|
+
models: <b>${esc(meta.models.join(", "))}</b> ·
|
|
275
|
+
${esc(card.results.length)}${pending.length ? ` / ${esc(card.results.length + pending.length)}` : ""} cases${meta.runs && meta.runs > 1
|
|
276
|
+
? ` · <b>${esc(meta.runs)}×</b> per case <span class="muted">(worst-case verdict · mean cost)</span>`
|
|
277
|
+
: ""} ·
|
|
278
|
+
${esc(meta.generatedAt)}
|
|
279
|
+
</div>
|
|
280
|
+
</header>
|
|
281
|
+
|
|
282
|
+
<div class="tabwrap">
|
|
283
|
+
${radios}
|
|
284
|
+
<nav class="tabs">
|
|
285
|
+
${tabs}
|
|
286
|
+
</nav>
|
|
287
|
+
${panes}
|
|
288
|
+
</div>
|
|
289
|
+
|
|
290
|
+
<footer>
|
|
291
|
+
Real production workflows · mocked GitHub · deterministic grading. ★ = best in column.
|
|
292
|
+
Generated by <span class="mono">npm run eval</span>. Also: scorecard.json · predictions.jsonl.
|
|
293
|
+
</footer>
|
|
294
|
+
</div>
|
|
295
|
+
<script>
|
|
296
|
+
// Preserve the active tab + scroll position across the live auto-refresh.
|
|
297
|
+
(function () {
|
|
298
|
+
try {
|
|
299
|
+
var K = "ll-eval-tab", S = "ll-eval-scroll";
|
|
300
|
+
var saved = sessionStorage.getItem(K);
|
|
301
|
+
if (saved) { var r = document.getElementById(saved); if (r) r.checked = true; }
|
|
302
|
+
document.querySelectorAll('input[name=tier]').forEach(function (radio) {
|
|
303
|
+
radio.addEventListener("change", function () { sessionStorage.setItem(K, radio.id); });
|
|
304
|
+
});
|
|
305
|
+
var y = sessionStorage.getItem(S);
|
|
306
|
+
if (y) window.scrollTo(0, parseInt(y, 10) || 0);
|
|
307
|
+
window.addEventListener("scroll", function () { sessionStorage.setItem(S, String(window.scrollY)); }, { passive: true });
|
|
308
|
+
} catch (e) {}
|
|
309
|
+
})();
|
|
310
|
+
</script>
|
|
311
|
+
</body>
|
|
312
|
+
</html>
|
|
313
|
+
`;
|
|
314
|
+
}
|
|
315
|
+
export function writeHtml(dir, card, meta) {
|
|
316
|
+
mkdirSync(dir, { recursive: true });
|
|
317
|
+
const file = join(dir, "index.html");
|
|
318
|
+
// Write-then-rename so a browser auto-refreshing during a live run never
|
|
319
|
+
// reads a half-written file (rename is atomic on the same filesystem).
|
|
320
|
+
const tmp = join(dir, ".index.html.tmp");
|
|
321
|
+
writeFileSync(tmp, renderHtml(card, meta));
|
|
322
|
+
renameSync(tmp, file);
|
|
323
|
+
return file;
|
|
324
|
+
}
|
|
325
|
+
//# sourceMappingURL=html-report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html-report.js","sourceRoot":"","sources":["../src/html-report.ts"],"names":[],"mappings":"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"}
|
package/dist/init.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `lastlight-evals init [dir]` — scaffold a fresh overlay + evals repo, seeded
|
|
3
|
+
* from the shipped defaults, then optionally version it as a private GitHub repo.
|
|
4
|
+
*
|
|
5
|
+
* The result is a self-contained deployment overlay: it carries its own
|
|
6
|
+
* `workflows/` / `skills/` / `agent-context/` (which shadow the built-ins by
|
|
7
|
+
* logical name) AND its own `evals/datasets/` + `evals/models.json`. Point the
|
|
8
|
+
* runner at it with `lastlight-evals run --overlay <dir>` (or run from inside
|
|
9
|
+
* it with `--overlay .`). It's pure data/config — no node deps; the globally
|
|
10
|
+
* installed CLI supplies the runtime.
|
|
11
|
+
*
|
|
12
|
+
* Git/GitHub bootstrap reuses core's `detectGh` + `bootstrapOverlayRepo` (the
|
|
13
|
+
* same flow behind `lastlight server setup`) via the `lastlight/evals` barrel —
|
|
14
|
+
* git init + initial commit + an offered `gh repo create --private`.
|
|
15
|
+
*/
|
|
16
|
+
import { existsSync, mkdirSync, writeFileSync, cpSync } from "node:fs";
|
|
17
|
+
import { join, resolve, basename } from "node:path";
|
|
18
|
+
import * as p from "@clack/prompts";
|
|
19
|
+
import chalk from "chalk";
|
|
20
|
+
import { detectGh, bootstrapOverlayRepo } from "lastlight/evals";
|
|
21
|
+
import { builtinDatasetsRoot, builtinModelsPath } from "./paths.js";
|
|
22
|
+
const CONFIG_YAML = `# Last Light — eval/overlay config (merged over the core config/default.yaml).
|
|
23
|
+
# Arrays replace, maps deep-merge, env vars override. See the lastlight docs.
|
|
24
|
+
#
|
|
25
|
+
# managedRepos:
|
|
26
|
+
# - your-org/your-repo
|
|
27
|
+
#
|
|
28
|
+
# models:
|
|
29
|
+
# default: openai/gpt-5.5
|
|
30
|
+
`;
|
|
31
|
+
const GITIGNORE = `# Eval run output (scorecards, predictions) — regenerated, never commit.
|
|
32
|
+
eval-results/
|
|
33
|
+
|
|
34
|
+
# Local secrets / env.
|
|
35
|
+
.env
|
|
36
|
+
secrets/*
|
|
37
|
+
!secrets/.env.example
|
|
38
|
+
*.pem
|
|
39
|
+
`;
|
|
40
|
+
function readmeFor(name) {
|
|
41
|
+
return `# ${name}
|
|
42
|
+
|
|
43
|
+
A Last Light **eval + overlay** workspace, created by \`lastlight-evals init\`.
|
|
44
|
+
|
|
45
|
+
## Layout
|
|
46
|
+
|
|
47
|
+
- \`workflows/\`, \`skills/\`, \`agent-context/\` — overlay assets. Files here
|
|
48
|
+
**shadow** the built-in Last Light assets by name, or add new ones.
|
|
49
|
+
- \`evals/datasets/<tier>/\` — your eval datasets (\`instances.json\` +
|
|
50
|
+
\`tier.json\`, plus \`repos/\` + \`tests/\` for code-fix tiers). Seeded with the
|
|
51
|
+
shipped \`triage\` / \`code-fix\` samples — edit or replace them.
|
|
52
|
+
- \`evals/models.json\` — the model registry these evals run against.
|
|
53
|
+
- \`config.yaml\` — overlay config (managed repos, models, …).
|
|
54
|
+
|
|
55
|
+
## Run
|
|
56
|
+
|
|
57
|
+
\`\`\`bash
|
|
58
|
+
# from inside this repo
|
|
59
|
+
lastlight-evals run --overlay .
|
|
60
|
+
# or a specific tier
|
|
61
|
+
lastlight-evals run code-fix --overlay .
|
|
62
|
+
\`\`\`
|
|
63
|
+
|
|
64
|
+
Override which core build the evals test with \`LASTLIGHT_CORE_DIR=/path/to/lastlight\`.
|
|
65
|
+
`;
|
|
66
|
+
}
|
|
67
|
+
/** Write the default files/dirs into `dir`, never overwriting what exists. */
|
|
68
|
+
function scaffoldEvalRepo(dir) {
|
|
69
|
+
const created = [];
|
|
70
|
+
const writeIfMissing = (rel, content) => {
|
|
71
|
+
const abs = join(dir, rel);
|
|
72
|
+
if (existsSync(abs))
|
|
73
|
+
return;
|
|
74
|
+
mkdirSync(resolve(abs, ".."), { recursive: true });
|
|
75
|
+
writeFileSync(abs, content, "utf8");
|
|
76
|
+
created.push(rel);
|
|
77
|
+
};
|
|
78
|
+
// Overlay asset dirs (empty placeholders the user fills in).
|
|
79
|
+
for (const d of ["workflows", "skills", "agent-context"]) {
|
|
80
|
+
const keep = join(d, ".gitkeep");
|
|
81
|
+
writeIfMissing(keep, "");
|
|
82
|
+
}
|
|
83
|
+
// Seed datasets + models from the shipped defaults (a starting point to edit).
|
|
84
|
+
const datasetsDst = join(dir, "evals", "datasets");
|
|
85
|
+
if (!existsSync(datasetsDst)) {
|
|
86
|
+
mkdirSync(datasetsDst, { recursive: true });
|
|
87
|
+
cpSync(builtinDatasetsRoot(), datasetsDst, { recursive: true });
|
|
88
|
+
created.push("evals/datasets/ (seeded triage + code-fix)");
|
|
89
|
+
}
|
|
90
|
+
const modelsDst = join(dir, "evals", "models.json");
|
|
91
|
+
if (!existsSync(modelsDst)) {
|
|
92
|
+
cpSync(builtinModelsPath(), modelsDst);
|
|
93
|
+
created.push("evals/models.json");
|
|
94
|
+
}
|
|
95
|
+
writeIfMissing("config.yaml", CONFIG_YAML);
|
|
96
|
+
writeIfMissing(".gitignore", GITIGNORE);
|
|
97
|
+
writeIfMissing("README.md", readmeFor(basename(dir)));
|
|
98
|
+
return created;
|
|
99
|
+
}
|
|
100
|
+
export async function runInit(dirArg) {
|
|
101
|
+
p.intro(chalk.bold(`Last Light ${chalk.yellow("·")} eval init`));
|
|
102
|
+
const dir = resolve(dirArg ?? "lastlight-evals-workspace");
|
|
103
|
+
p.log.step(`Scaffolding ${chalk.cyan(dir)}`);
|
|
104
|
+
const created = scaffoldEvalRepo(dir);
|
|
105
|
+
if (created.length) {
|
|
106
|
+
p.log.success(`Created:\n ${created.join("\n ")}`);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
p.log.info("Nothing to scaffold — every default file already existed.");
|
|
110
|
+
}
|
|
111
|
+
// Offer to version it + create a private GitHub repo (reuses core's flow).
|
|
112
|
+
try {
|
|
113
|
+
const gh = await detectGh();
|
|
114
|
+
await bootstrapOverlayRepo(dir, { gh });
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
p.log.warn(`Skipped git/GitHub bootstrap: ${err.message}`);
|
|
118
|
+
}
|
|
119
|
+
p.outro(chalk.green(`done — run it with: ${chalk.bold(`lastlight-evals run --overlay ${dir === process.cwd() ? "." : dir}`)}`));
|
|
120
|
+
return 0;
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=init.js.map
|
package/dist/init.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACvE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAEpD,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEjE,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpE,MAAM,WAAW,GAAG;;;;;;;;CAQnB,CAAC;AAEF,MAAM,SAAS,GAAG;;;;;;;;CAQjB,CAAC;AAEF,SAAS,SAAS,CAAC,IAAY;IAC7B,OAAO,KAAK,IAAI;;;;;;;;;;;;;;;;;;;;;;;;CAwBjB,CAAC;AACF,CAAC;AAED,8EAA8E;AAC9E,SAAS,gBAAgB,CAAC,GAAW;IACnC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,cAAc,GAAG,CAAC,GAAW,EAAE,OAAe,EAAQ,EAAE;QAC5D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAC3B,IAAI,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO;QAC5B,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QACpC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACpB,CAAC,CAAC;IAEF,6DAA6D;IAC7D,KAAK,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,eAAe,CAAC,EAAE,CAAC;QACzD,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;QACjC,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC3B,CAAC;IAED,+EAA+E;IAC/E,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;IACnD,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7B,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,MAAM,CAAC,mBAAmB,EAAE,EAAE,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChE,OAAO,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;IAC7D,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;IACpD,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,MAAM,CAAC,iBAAiB,EAAE,EAAE,SAAS,CAAC,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IACpC,CAAC;IAED,cAAc,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IAC3C,cAAc,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;IACxC,cAAc,CAAC,WAAW,EAAE,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACtD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,MAAe;IAC3C,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC;IAEjE,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,2BAA2B,CAAC,CAAC;IAC3D,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,eAAe,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACvD,CAAC;SAAM,CAAC;QACN,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;IAC1E,CAAC;IAED,2EAA2E;IAC3E,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC5B,MAAM,oBAAoB,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,iCAAkC,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,CAAC,CAAC,KAAK,CACL,KAAK,CAAC,KAAK,CACT,uBAAuB,KAAK,CAAC,IAAI,CAAC,iCAAiC,GAAG,KAAK,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,CAC1G,CACF,CAAC;IACF,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic, AI-free tests for the eval harness mechanism. These run in the
|
|
3
|
+
* DEFAULT `npm test` suite (not the paid `*.eval.test.ts` suite) so the mock
|
|
4
|
+
* plumbing is regression-guarded for free:
|
|
5
|
+
*
|
|
6
|
+
* - the fake GitHub speaks enough REST for the real github_* tools;
|
|
7
|
+
* - agentic-pi's `githubApiBaseUrl` seam actually routes Octokit at it;
|
|
8
|
+
* - workspace seeding + execution grading flip red→green correctly.
|
|
9
|
+
*/
|
|
10
|
+
import { describe, it, expect } from "vitest";
|
|
11
|
+
import { GitHubClient } from "agentic-pi/dist/extensions/github/client.js";
|
|
12
|
+
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
import { tmpdir } from "node:os";
|
|
15
|
+
import { startFakeGitHub } from "./fake-github.js";
|
|
16
|
+
import { seedWorkspace } from "./seed.js";
|
|
17
|
+
import { gradeExecution, gradeBehavioral, gradeTriage } from "./grade.js";
|
|
18
|
+
const staticAuth = { getToken: async () => "fake-token", expiresAt: null };
|
|
19
|
+
describe("fake GitHub + agentic-pi github tools (baseUrl seam)", () => {
|
|
20
|
+
it("serves seeded issues and records mutations made through the real GitHubClient", async () => {
|
|
21
|
+
const fake = await startFakeGitHub({
|
|
22
|
+
owner: "acme",
|
|
23
|
+
repo: "widget",
|
|
24
|
+
issues: [{ number: 101, title: "Crash on empty config", body: "boom", labels: [] }],
|
|
25
|
+
});
|
|
26
|
+
try {
|
|
27
|
+
// The REAL agentic-pi client, pointed at the fake via the released seam.
|
|
28
|
+
const gh = new GitHubClient(staticAuth, { baseUrl: fake.url });
|
|
29
|
+
const issue = (await gh.getIssue("acme", "widget", 101));
|
|
30
|
+
expect(issue.number).toBe(101);
|
|
31
|
+
expect(issue.title).toBe("Crash on empty config");
|
|
32
|
+
await gh.createLabel("acme", "widget", "bug", "d73a4a");
|
|
33
|
+
await gh.addLabels("acme", "widget", 101, ["bug", "ready-for-agent"]);
|
|
34
|
+
await gh.addIssueComment("acme", "widget", 101, "Triaged — needs a repro first.");
|
|
35
|
+
expect(fake.labelsOn(101)).toEqual(expect.arrayContaining(["bug", "ready-for-agent"]));
|
|
36
|
+
expect(fake.commentsOn(101).some((c) => /repro/i.test(c))).toBe(true);
|
|
37
|
+
expect(fake.calls.some((c) => c.method === "POST" && c.path.endsWith("/labels"))).toBe(true);
|
|
38
|
+
}
|
|
39
|
+
finally {
|
|
40
|
+
await fake.close();
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
it("behavioral + triage grades read the recorded GitHub state", async () => {
|
|
44
|
+
const fake = await startFakeGitHub({
|
|
45
|
+
owner: "acme",
|
|
46
|
+
repo: "widget",
|
|
47
|
+
issues: [{ number: 7, title: "Q", body: "how?", labels: [] }],
|
|
48
|
+
});
|
|
49
|
+
try {
|
|
50
|
+
const gh = new GitHubClient(staticAuth, { baseUrl: fake.url });
|
|
51
|
+
await gh.addLabels("acme", "widget", 7, ["question"]);
|
|
52
|
+
const beh = gradeBehavioral({ labels_added: ["question"], labels_absent: ["ready-for-agent"] }, fake, { issueNumber: 7, branch: "main" });
|
|
53
|
+
expect(beh.ok).toBe(true);
|
|
54
|
+
const tri = gradeTriage({ category: "question" }, fake, 7);
|
|
55
|
+
expect(tri.ok).toBe(true);
|
|
56
|
+
const miss = gradeTriage({ state: "ready-for-agent" }, fake, 7);
|
|
57
|
+
expect(miss.ok).toBe(false);
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
await fake.close();
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
describe("workspace seed + execution grade (SWE-bench resolved)", () => {
|
|
65
|
+
it("flips red→green when the bug is fixed, and detects PASS_TO_PASS regressions", () => {
|
|
66
|
+
const stateDir = mkdtempSync(join(tmpdir(), "ll-eval-mech-"));
|
|
67
|
+
try {
|
|
68
|
+
const fixtureDir = join(stateDir, "fixture");
|
|
69
|
+
mkdirSync(join(fixtureDir, "src"), { recursive: true });
|
|
70
|
+
// Buggy: off-by-one (returns n + 2).
|
|
71
|
+
writeFileSync(join(fixtureDir, "src", "counter.ts"), "export const next = (n: number): number => n + 2;\n");
|
|
72
|
+
const seeded = seedWorkspace({ stateDir, taskId: "mech-task", fixtureDir });
|
|
73
|
+
expect(seeded.baseCommit).toHaveLength(40);
|
|
74
|
+
// Held-out test the agent never saw.
|
|
75
|
+
const heldOutDir = join(stateDir, "held");
|
|
76
|
+
mkdirSync(heldOutDir, { recursive: true });
|
|
77
|
+
writeFileSync(join(heldOutDir, "counter.test.ts"), [
|
|
78
|
+
'import { test } from "node:test";',
|
|
79
|
+
'import assert from "node:assert/strict";',
|
|
80
|
+
'import { next } from "./src/counter.ts";',
|
|
81
|
+
'test("increments by one", () => { assert.equal(next(1), 2); });',
|
|
82
|
+
'test("stays numeric", () => { assert.equal(typeof next(3), "number"); });',
|
|
83
|
+
].join("\n") + "\n");
|
|
84
|
+
// Before the fix → FAIL_TO_PASS test is red → not resolved.
|
|
85
|
+
const before = gradeExecution({
|
|
86
|
+
workDir: seeded.workDir,
|
|
87
|
+
heldOutDir,
|
|
88
|
+
failToPass: ["increments by one"],
|
|
89
|
+
passToPass: ["stays numeric"],
|
|
90
|
+
});
|
|
91
|
+
expect(before.resolved).toBe(false);
|
|
92
|
+
expect(before.failToPass.find((t) => t.id === "increments by one")?.pass).toBe(false);
|
|
93
|
+
expect(before.passToPass.find((t) => t.id === "stays numeric")?.pass).toBe(true);
|
|
94
|
+
// Apply the fix → both green → resolved.
|
|
95
|
+
writeFileSync(join(seeded.workDir, "src", "counter.ts"), "export const next = (n: number): number => n + 1;\n");
|
|
96
|
+
const after = gradeExecution({
|
|
97
|
+
workDir: seeded.workDir,
|
|
98
|
+
failToPass: ["increments by one"],
|
|
99
|
+
passToPass: ["stays numeric"],
|
|
100
|
+
});
|
|
101
|
+
expect(after.resolved).toBe(true);
|
|
102
|
+
}
|
|
103
|
+
finally {
|
|
104
|
+
rmSync(stateDir, { recursive: true, force: true });
|
|
105
|
+
}
|
|
106
|
+
}, 60_000);
|
|
107
|
+
});
|
|
108
|
+
//# sourceMappingURL=mechanism.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mechanism.test.js","sourceRoot":"","sources":["../src/mechanism.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,6CAA6C,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE1E,MAAM,UAAU,GAAG,EAAE,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,YAAY,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AAE3E,QAAQ,CAAC,sDAAsD,EAAE,GAAG,EAAE;IACpE,EAAE,CAAC,+EAA+E,EAAE,KAAK,IAAI,EAAE;QAC7F,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC;YACjC,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,uBAAuB,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;SACpF,CAAC,CAAC;QACH,IAAI,CAAC;YACH,yEAAyE;YACzE,MAAM,EAAE,GAAG,IAAI,YAAY,CAAC,UAAU,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;YAE/D,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAsC,CAAC;YAC9F,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC/B,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;YAElD,MAAM,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;YACxD,MAAM,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC;YACtE,MAAM,EAAE,CAAC,eAAe,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,gCAAgC,CAAC,CAAC;YAElF,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;YACvF,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/F,CAAC;gBAAS,CAAC;YACT,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QACrB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC;YACjC,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;SAC9D,CAAC,CAAC;QACH,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,IAAI,YAAY,CAAC,UAAU,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;YAC/D,MAAM,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;YAEtD,MAAM,GAAG,GAAG,eAAe,CAAC,EAAE,YAAY,EAAE,CAAC,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC,iBAAiB,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1I,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAE1B,MAAM,GAAG,GAAG,WAAW,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAC3D,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAE1B,MAAM,IAAI,GAAG,WAAW,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAChE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;gBAAS,CAAC;YACT,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QACrB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,uDAAuD,EAAE,GAAG,EAAE;IACrE,EAAE,CAAC,6EAA6E,EAAE,GAAG,EAAE;QACrF,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;QAC9D,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;YAC7C,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACxD,qCAAqC;YACrC,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,YAAY,CAAC,EAAE,qDAAqD,CAAC,CAAC;YAE5G,MAAM,MAAM,GAAG,aAAa,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC;YAC5E,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YAE3C,qCAAqC;YACrC,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC1C,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3C,aAAa,CACX,IAAI,CAAC,UAAU,EAAE,iBAAiB,CAAC,EACnC;gBACE,mCAAmC;gBACnC,0CAA0C;gBAC1C,0CAA0C;gBAC1C,iEAAiE;gBACjE,2EAA2E;aAC5E,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CACpB,CAAC;YAEF,4DAA4D;YAC5D,MAAM,MAAM,GAAG,cAAc,CAAC;gBAC5B,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,UAAU;gBACV,UAAU,EAAE,CAAC,mBAAmB,CAAC;gBACjC,UAAU,EAAE,CAAC,eAAe,CAAC;aAC9B,CAAC,CAAC;YACH,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACpC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,mBAAmB,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACtF,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,eAAe,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEjF,yCAAyC;YACzC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,YAAY,CAAC,EAAE,qDAAqD,CAAC,CAAC;YAChH,MAAM,KAAK,GAAG,cAAc,CAAC;gBAC3B,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,UAAU,EAAE,CAAC,mBAAmB,CAAC;gBACjC,UAAU,EAAE,CAAC,eAAe,CAAC;aAC9B,CAAC,CAAC;YACH,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,CAAC;IACH,CAAC,EAAE,MAAM,CAAC,CAAC;AACb,CAAC,CAAC,CAAC"}
|