@cairn-tool/cairn 3.4.0 → 3.5.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.
Files changed (105) hide show
  1. package/README.md +6 -4
  2. package/dist/agent/manifest.d.ts +10 -0
  3. package/dist/agent/manifest.js +23 -0
  4. package/dist/agent/manifest.js.map +1 -1
  5. package/dist/agent/parser.js +1 -15
  6. package/dist/agent/parser.js.map +1 -1
  7. package/dist/agent/render.js +47 -3
  8. package/dist/agent/render.js.map +1 -1
  9. package/dist/cli.js +46 -2
  10. package/dist/cli.js.map +1 -1
  11. package/dist/commands/qa-list.d.ts +7 -0
  12. package/dist/commands/qa-list.js +69 -0
  13. package/dist/commands/qa-list.js.map +1 -0
  14. package/dist/commands/qa-run.d.ts +3 -0
  15. package/dist/commands/qa-run.js +106 -0
  16. package/dist/commands/qa-run.js.map +1 -0
  17. package/dist/commands/qa-summary.d.ts +6 -0
  18. package/dist/commands/qa-summary.js +38 -0
  19. package/dist/commands/qa-summary.js.map +1 -0
  20. package/dist/config-schema.d.ts +2 -0
  21. package/dist/config-schema.js +4 -0
  22. package/dist/config-schema.js.map +1 -1
  23. package/dist/config.d.ts +12 -2
  24. package/dist/config.js +36 -7
  25. package/dist/config.js.map +1 -1
  26. package/dist/contract/registry.js +43 -0
  27. package/dist/contract/registry.js.map +1 -1
  28. package/dist/contract/schemas/index.js +2 -0
  29. package/dist/contract/schemas/index.js.map +1 -1
  30. package/dist/contract/schemas/qa.d.ts +2 -0
  31. package/dist/contract/schemas/qa.js +111 -0
  32. package/dist/contract/schemas/qa.js.map +1 -0
  33. package/dist/qa/agent.d.ts +25 -0
  34. package/dist/qa/agent.js +142 -0
  35. package/dist/qa/agent.js.map +1 -0
  36. package/dist/qa/agents/claude-code.d.ts +2 -0
  37. package/dist/qa/agents/claude-code.js +121 -0
  38. package/dist/qa/agents/claude-code.js.map +1 -0
  39. package/dist/qa/agents/cursor.d.ts +5 -0
  40. package/dist/qa/agents/cursor.js +143 -0
  41. package/dist/qa/agents/cursor.js.map +1 -0
  42. package/dist/qa/agents/index.d.ts +32 -0
  43. package/dist/qa/agents/index.js +83 -0
  44. package/dist/qa/agents/index.js.map +1 -0
  45. package/dist/qa/agents/types.d.ts +61 -0
  46. package/dist/qa/agents/types.js +18 -0
  47. package/dist/qa/agents/types.js.map +1 -0
  48. package/dist/qa/async.d.ts +27 -0
  49. package/dist/qa/async.js +91 -0
  50. package/dist/qa/async.js.map +1 -0
  51. package/dist/qa/casefile.d.ts +35 -0
  52. package/dist/qa/casefile.js +181 -0
  53. package/dist/qa/casefile.js.map +1 -0
  54. package/dist/qa/cases.d.ts +51 -0
  55. package/dist/qa/cases.js +144 -0
  56. package/dist/qa/cases.js.map +1 -0
  57. package/dist/qa/config.d.ts +50 -0
  58. package/dist/qa/config.js +105 -0
  59. package/dist/qa/config.js.map +1 -0
  60. package/dist/qa/demo.d.ts +10 -0
  61. package/dist/qa/demo.js +194 -0
  62. package/dist/qa/demo.js.map +1 -0
  63. package/dist/qa/format.d.ts +38 -0
  64. package/dist/qa/format.js +208 -0
  65. package/dist/qa/format.js.map +1 -0
  66. package/dist/qa/harness.d.ts +68 -0
  67. package/dist/qa/harness.js +528 -0
  68. package/dist/qa/harness.js.map +1 -0
  69. package/dist/qa/keys.d.ts +12 -0
  70. package/dist/qa/keys.js +96 -0
  71. package/dist/qa/keys.js.map +1 -0
  72. package/dist/qa/layout.d.ts +102 -0
  73. package/dist/qa/layout.js +278 -0
  74. package/dist/qa/layout.js.map +1 -0
  75. package/dist/qa/lock.d.ts +5 -0
  76. package/dist/qa/lock.js +114 -0
  77. package/dist/qa/lock.js.map +1 -0
  78. package/dist/qa/options.d.ts +38 -0
  79. package/dist/qa/options.js +165 -0
  80. package/dist/qa/options.js.map +1 -0
  81. package/dist/qa/outcome.d.ts +30 -0
  82. package/dist/qa/outcome.js +162 -0
  83. package/dist/qa/outcome.js.map +1 -0
  84. package/dist/qa/reports.d.ts +51 -0
  85. package/dist/qa/reports.js +121 -0
  86. package/dist/qa/reports.js.map +1 -0
  87. package/dist/qa/schedule.d.ts +55 -0
  88. package/dist/qa/schedule.js +145 -0
  89. package/dist/qa/schedule.js.map +1 -0
  90. package/dist/qa/screen.d.ts +31 -0
  91. package/dist/qa/screen.js +146 -0
  92. package/dist/qa/screen.js.map +1 -0
  93. package/dist/qa/slot.d.ts +28 -0
  94. package/dist/qa/slot.js +126 -0
  95. package/dist/qa/slot.js.map +1 -0
  96. package/dist/qa/tracker.d.ts +36 -0
  97. package/dist/qa/tracker.js +357 -0
  98. package/dist/qa/tracker.js.map +1 -0
  99. package/dist/query/execute.js +0 -0
  100. package/dist/query/execute.js.map +1 -1
  101. package/dist/scripts/resolve.js +1 -4
  102. package/dist/scripts/resolve.js.map +1 -1
  103. package/dist/usage/providers/cursor.js +1 -1
  104. package/dist/usage/providers/cursor.js.map +1 -1
  105. package/package.json +2 -1
@@ -0,0 +1,528 @@
1
+ import { existsSync, rmSync } from "node:fs";
2
+ import { join, relative } from "node:path";
3
+ import { DONE_FAIL, DONE_OK, RENDER_HZ } from "./config.js";
4
+ import { RED, RESET, flatten, fmtDuration } from "./format.js";
5
+ import { Cleanup, Gate, sleep } from "./async.js";
6
+ import { commandFor, stillEligible } from "./cases.js";
7
+ import { Scheduler } from "./schedule.js";
8
+ import { Slot } from "./slot.js";
9
+ import { agentCaps, asEventList, resolveAgent } from "./agents/index.js";
10
+ import { FAIL_OUTCOME, classify, outcomeLabel, readVerdict, usageCells, usageFragment, usageTotal, } from "./outcome.js";
11
+ import { BLANK_METRICS, frame } from "./layout.js";
12
+ import { Screen } from "./screen.js";
13
+ import { killGroup, runAgent } from "./agent.js";
14
+ import { acquireLock } from "./lock.js";
15
+ import { consoleSummary, writeSessionLog, writeSummaryJson } from "./reports.js";
16
+ import { writeCaseTracker } from "./tracker.js";
17
+ const pad2 = (n) => String(n).padStart(2, "0");
18
+ /** datetime.now(timezone.utc).strftime("%Y%m%d-%H%M%S") */
19
+ export function runId(d = new Date()) {
20
+ return (`${d.getUTCFullYear()}${pad2(d.getUTCMonth() + 1)}${pad2(d.getUTCDate())}` +
21
+ `-${pad2(d.getUTCHours())}${pad2(d.getUTCMinutes())}${pad2(d.getUTCSeconds())}`);
22
+ }
23
+ /** datetime.now().strftime("%H:%M:%S") — local, for line-log timestamps. */
24
+ function stamp(d = new Date()) {
25
+ return `${pad2(d.getHours())}:${pad2(d.getMinutes())}:${pad2(d.getSeconds())}`;
26
+ }
27
+ export class Harness {
28
+ options;
29
+ cases;
30
+ allCases;
31
+ prior;
32
+ byName;
33
+ sched;
34
+ slots;
35
+ live = new Map();
36
+ records = [];
37
+ gate = new Gate(true);
38
+ cleanup = new Cleanup();
39
+ screen;
40
+ startedMs = performance.now();
41
+ runId;
42
+ pid = process.pid;
43
+ logRoot;
44
+ sessionLog;
45
+ trackerPath = null;
46
+ lock = null;
47
+ paused = false;
48
+ draining = false;
49
+ stopLevel = 0;
50
+ constructor(options, cases, allCases) {
51
+ this.options = options;
52
+ this.cases = cases;
53
+ this.allCases = allCases.length > 0 ? allCases : [...cases];
54
+ this.prior = new Set(this.allCases.filter((c) => existsSync(c.outDir)).map((c) => c.name));
55
+ this.byName = new Map(this.allCases.map((c) => [c.name, c]));
56
+ this.sched = new Scheduler(this.cases, agentCaps(options.parallel));
57
+ this.slots = Array.from({ length: options.parallel }, (_, i) => new Slot(i));
58
+ this.runId = runId();
59
+ this.logRoot = join(options.runsDir, "_logs", this.runId);
60
+ this.sessionLog = join(options.runsDir, "_runs", `${this.runId}-${this.pid}.md`);
61
+ this.screen = new Screen(!options.noTui);
62
+ }
63
+ get info() {
64
+ return {
65
+ runId: this.runId,
66
+ pid: this.pid,
67
+ defaultModel: this.options.model,
68
+ parallel: this.options.parallel,
69
+ repo: this.options.repo,
70
+ runsDir: this.options.runsDir,
71
+ sessionLog: this.sessionLog,
72
+ logRoot: this.logRoot,
73
+ };
74
+ }
75
+ // ---------------------------------------------------------------- view model
76
+ progress() {
77
+ const running = this.slots.filter((s) => s.status === "run").length;
78
+ const finished = new Set(this.records.filter((r) => r.status !== "skipped").map((r) => r.name));
79
+ const completed = new Set([...this.prior, ...finished]).size;
80
+ return [running, completed, this.allCases.length];
81
+ }
82
+ finishedRecords() {
83
+ return this.records.filter((r) => r.status !== "skipped");
84
+ }
85
+ sessionStats() {
86
+ const recs = this.finishedRecords();
87
+ return {
88
+ ok: this.records.filter((r) => r.status === DONE_OK).length,
89
+ fail: this.records.filter((r) => DONE_FAIL.has(r.status)).length,
90
+ skipped: this.records.filter((r) => r.status === "skipped").length,
91
+ durationS: recs.reduce((sum, r) => sum + r.durationS, 0),
92
+ tools: recs.reduce((sum, r) => sum + r.tools, 0),
93
+ usage: usageTotal(recs.map((r) => r.usage)),
94
+ wallS: (performance.now() - this.startedMs) / 1000,
95
+ };
96
+ }
97
+ tableRows() {
98
+ const latest = new Map();
99
+ for (const rec of this.records)
100
+ latest.set(rec.name, rec);
101
+ const running = new Map();
102
+ for (const slot of this.slots) {
103
+ if (slot.case !== null && slot.status === "run")
104
+ running.set(slot.case.name, slot);
105
+ }
106
+ const now = performance.now();
107
+ return this.allCases.map((kase) => {
108
+ const rec = latest.get(kase.name);
109
+ const live = running.get(kase.name);
110
+ if (live) {
111
+ return {
112
+ name: kase.name,
113
+ status: "Running",
114
+ outcome: "—",
115
+ duration: fmtDuration(live.elapsedSeconds(now)),
116
+ tools: String(live.tools),
117
+ ...usageCells(null),
118
+ };
119
+ }
120
+ if (rec !== undefined && rec.status !== "skipped") {
121
+ let status;
122
+ let outcome;
123
+ if (rec.status === DONE_OK) {
124
+ status = "Done";
125
+ outcome = outcomeLabel(readVerdict(kase.outDir));
126
+ }
127
+ else {
128
+ status = "Failed";
129
+ const verdict = readVerdict(kase.outDir);
130
+ outcome =
131
+ verdict !== "—" ? outcomeLabel(verdict) : (FAIL_OUTCOME[rec.status] ?? rec.status);
132
+ }
133
+ return {
134
+ name: kase.name,
135
+ status,
136
+ outcome,
137
+ duration: fmtDuration(rec.durationS),
138
+ tools: String(rec.tools),
139
+ ...usageCells(rec.usage),
140
+ };
141
+ }
142
+ if (this.prior.has(kase.name) || (rec !== undefined && rec.status === "skipped")) {
143
+ return {
144
+ name: kase.name,
145
+ status: "Prior",
146
+ outcome: outcomeLabel(readVerdict(kase.outDir)),
147
+ ...BLANK_METRICS,
148
+ };
149
+ }
150
+ return { name: kase.name, status: "Pending", outcome: "—", ...BLANK_METRICS };
151
+ });
152
+ }
153
+ tableTotals() {
154
+ const recs = this.finishedRecords();
155
+ if (recs.length === 0) {
156
+ return { name: "Total", status: "—", outcome: "—", ...BLANK_METRICS };
157
+ }
158
+ const stats = this.sessionStats();
159
+ return {
160
+ name: "Total",
161
+ status: "—",
162
+ outcome: "—",
163
+ duration: fmtDuration(stats.durationS),
164
+ tools: String(stats.tools),
165
+ ...usageCells(stats.usage),
166
+ };
167
+ }
168
+ recordOutcome = (rec) => {
169
+ const kase = this.byName.get(rec.name);
170
+ const folder = kase !== undefined ? kase.outDir : join(this.options.runsDir, rec.name);
171
+ if (rec.status === DONE_OK)
172
+ return outcomeLabel(readVerdict(folder));
173
+ if (rec.status === "skipped")
174
+ return "—";
175
+ const verdict = readVerdict(folder);
176
+ if (verdict !== "—")
177
+ return outcomeLabel(verdict);
178
+ return FAIL_OUTCOME[rec.status] ?? rec.status;
179
+ };
180
+ statusLeft() {
181
+ const [run, done, total] = this.progress();
182
+ const elapsed = fmtDuration((performance.now() - this.startedMs) / 1000);
183
+ const summed = usageTotal(this.records.filter((r) => r.status !== "skipped").map((r) => r.usage));
184
+ const tok = summed ? usageFragment(summed) : "tokens —";
185
+ const flags = [];
186
+ if (this.paused)
187
+ flags.push("PAUSED");
188
+ if (this.draining)
189
+ flags.push("DRAINING");
190
+ const extra = flags.length > 0 ? ` ${flags.join(" ")}` : "";
191
+ return ` ${run}+${done}/${total} ${elapsed} ${tok}${extra}`;
192
+ }
193
+ paneView(slot, now) {
194
+ return {
195
+ slot: slot.index,
196
+ name: slot.case?.name ?? null,
197
+ model: slot.case?.model ?? "",
198
+ status: slot.status,
199
+ elapsedSeconds: slot.elapsedSeconds(now),
200
+ tools: slot.tools,
201
+ streamedBytes: slot.streamedBytes,
202
+ usage: slot.usage,
203
+ note: slot.note,
204
+ transcript: slot.transcript,
205
+ thinking: slot.thinking,
206
+ };
207
+ }
208
+ /**
209
+ * The slots worth a pane: the ones actually running. With nothing running and nothing left to
210
+ * dispatch — the end of a session — the finished slots stand in so the final frame still shows
211
+ * every result. With work still queued, the region stays empty and says why instead, since a
212
+ * queue held up by a barrier or a tag is exactly the state worth seeing.
213
+ */
214
+ visibleSlots() {
215
+ const running = this.slots.filter((s) => s.status === "run");
216
+ if (running.length > 0 || this.sched.size > 0)
217
+ return running;
218
+ return this.slots
219
+ .filter((s) => s.case !== null && s.endedMs !== null)
220
+ .sort((a, b) => (a.endedMs ?? 0) - (b.endedMs ?? 0));
221
+ }
222
+ viewModel() {
223
+ const now = performance.now();
224
+ const visible = this.visibleSlots();
225
+ this.screen.visibleSlots = visible.map((s) => s.index);
226
+ return {
227
+ mode: this.screen.mode,
228
+ zoom: this.screen.zoom,
229
+ scroll: this.screen.scroll,
230
+ running: this.sched.inFlight,
231
+ parallel: this.options.parallel,
232
+ queued: this.sched.size,
233
+ paused: this.paused,
234
+ draining: this.draining,
235
+ panes: visible.map((s) => this.paneView(s, now)),
236
+ panesNote: this.panesNote(),
237
+ table: this.screen.mode === "table" ? this.tableRows() : [],
238
+ totals: this.tableTotals(),
239
+ statusLeft: this.statusLeft(),
240
+ };
241
+ }
242
+ /** Why the pane region is empty — without this a tag-blocked queue looks like a hang. */
243
+ panesNote() {
244
+ if (this.paused)
245
+ return "paused — press p to resume";
246
+ if (this.draining)
247
+ return "draining — waiting for the running agents";
248
+ if (this.stopLevel > 0)
249
+ return "stopping";
250
+ return this.sched.blockedReason() ?? "no agents running";
251
+ }
252
+ renderOnce() {
253
+ const [rows, cols] = this.screen.size();
254
+ if (rows < 1)
255
+ return;
256
+ const vm = this.viewModel();
257
+ // A zoomed case that finished drops out of the pane list; unzoom rather than silently
258
+ // falling back to showing everything.
259
+ if (vm.zoom !== null && !vm.panes.some((p) => p.slot === vm.zoom)) {
260
+ this.screen.zoom = null;
261
+ vm.zoom = null;
262
+ }
263
+ const laid = frame(vm, rows, cols);
264
+ if (vm.mode === "table") {
265
+ this.screen.scroll = laid.scroll;
266
+ this.screen.page = laid.page;
267
+ }
268
+ this.screen.render(laid.lines, rows, cols);
269
+ }
270
+ // ---------------------------------------------------------------- controls
271
+ togglePause() {
272
+ this.paused = !this.paused;
273
+ this.gate.set(!this.paused);
274
+ }
275
+ requestDrain() {
276
+ this.draining = true;
277
+ this.gate.set(true); // wake paused workers so they can observe the drain and exit
278
+ this.sched.wake(); // and workers parked on a tag, which the gate does not reach
279
+ this.logPlain("draining — no new cases; waiting for running agents");
280
+ }
281
+ requestStop() {
282
+ this.stopLevel += 1;
283
+ this.paused = true;
284
+ this.gate.set(true); // CRITICAL: a paused worker must be woken to see stopLevel
285
+ this.sched.wake(); // likewise for a worker parked waiting on a tag
286
+ const sig = this.stopLevel >= 2 ? "SIGKILL" : "SIGINT";
287
+ for (const child of [...this.live.values()])
288
+ killGroup(child, sig);
289
+ }
290
+ logPlain(msg) {
291
+ if (this.screen.enabled || this.options.json)
292
+ return;
293
+ process.stdout.write(`${stamp()} ${msg}\n`);
294
+ }
295
+ // ---------------------------------------------------------------- reporting
296
+ writeSummary() {
297
+ writeSummaryJson(this.info, this.records, this.recordOutcome);
298
+ writeSessionLog(this.info, this.records, this.sessionStats(), this.recordOutcome);
299
+ }
300
+ writeTracker() {
301
+ try {
302
+ const { path } = writeCaseTracker(this.options.runsDir);
303
+ this.trackerPath = path;
304
+ }
305
+ catch {
306
+ this.trackerPath = null;
307
+ }
308
+ }
309
+ exitCode() {
310
+ if (this.records.length === 0)
311
+ return 1;
312
+ return this.records.every((r) => r.status === DONE_OK || r.status === "skipped") ? 0 : 1;
313
+ }
314
+ // ---------------------------------------------------------------- execution
315
+ async runCase(slot, kase) {
316
+ const logDir = join(this.logRoot, kase.name);
317
+ slot.reset(kase, logDir);
318
+ rmSync(kase.tempDir, { recursive: true, force: true });
319
+ const argv = commandFor(kase, this.options.agent);
320
+ this.logPlain(`slot${slot.index + 1} ${kase.name} start`);
321
+ let exitCode = null;
322
+ let timedOut;
323
+ const profile = resolveAgent(kase.agentName);
324
+ try {
325
+ const result = await runAgent({
326
+ argv,
327
+ cwd: this.options.repo,
328
+ logDir,
329
+ timeoutMs: this.options.timeoutMs,
330
+ onBytes: (n) => {
331
+ slot.streamedBytes += n;
332
+ },
333
+ onEvent: (event) => {
334
+ for (const qa of asEventList(profile.normalize(event)))
335
+ slot.applyEvent(qa);
336
+ },
337
+ onRawLine: (line) => slot.add(line),
338
+ onSpawn: (child) => {
339
+ this.live.set(slot.index, child);
340
+ },
341
+ });
342
+ exitCode = result.exitCode;
343
+ timedOut = result.timedOut;
344
+ }
345
+ finally {
346
+ this.live.delete(slot.index);
347
+ slot.endedMs = performance.now();
348
+ slot.exitCode = exitCode;
349
+ slot.closeTranscript();
350
+ }
351
+ const [status, note] = classify(kase, exitCode, timedOut === true);
352
+ slot.status = status;
353
+ if (note && !slot.note)
354
+ slot.note = note;
355
+ const durationS = slot.elapsedSeconds(performance.now());
356
+ this.records.push({
357
+ name: kase.name,
358
+ model: kase.model,
359
+ status: slot.status,
360
+ exitCode,
361
+ startedS: ((slot.startedMs ?? this.startedMs) - this.startedMs) / 1000,
362
+ durationS,
363
+ durationIsInt: false,
364
+ usage: slot.usage,
365
+ note: slot.note,
366
+ sessionId: slot.sessionId,
367
+ logDir: relative(this.options.runsDir, logDir),
368
+ tools: slot.tools,
369
+ });
370
+ this.writeSummary();
371
+ this.logPlain(`slot${slot.index + 1} ${kase.name} ${slot.status} ` +
372
+ `exit=${exitCode === null ? "None" : exitCode} ${fmtDuration(durationS)}`);
373
+ }
374
+ recordSkipped(slot, kase) {
375
+ slot.reset(kase);
376
+ slot.status = "skipped";
377
+ slot.endedMs = performance.now();
378
+ slot.note = "folder already exists";
379
+ this.records.push({
380
+ name: kase.name,
381
+ model: kase.model,
382
+ status: "skipped",
383
+ exitCode: null,
384
+ startedS: ((slot.startedMs ?? this.startedMs) - this.startedMs) / 1000,
385
+ durationS: 0,
386
+ durationIsInt: true,
387
+ usage: null,
388
+ note: slot.note,
389
+ sessionId: "",
390
+ logDir: "",
391
+ tools: 0,
392
+ });
393
+ this.writeSummary();
394
+ this.logPlain(`slot${slot.index + 1} ${kase.name} skipped`);
395
+ }
396
+ recordHarnessError(slot, kase, err) {
397
+ slot.status = "error";
398
+ slot.endedMs = performance.now();
399
+ slot.note = flatten(err instanceof Error ? err.message : String(err)).slice(0, 160);
400
+ slot.add(`${RED}x harness: ${slot.note}${RESET}`);
401
+ this.records.push({
402
+ name: kase.name,
403
+ model: kase.model,
404
+ status: "error",
405
+ exitCode: null,
406
+ startedS: ((slot.startedMs ?? this.startedMs) - this.startedMs) / 1000,
407
+ durationS: slot.elapsedSeconds(performance.now()),
408
+ durationIsInt: false,
409
+ usage: null,
410
+ note: slot.note,
411
+ sessionId: slot.sessionId,
412
+ logDir: slot.logDir ? relative(this.options.runsDir, slot.logDir) : "",
413
+ tools: slot.tools,
414
+ });
415
+ this.writeSummary();
416
+ this.logPlain(`slot${slot.index + 1} ${kase.name} error ${slot.note}`);
417
+ }
418
+ async worker(slot) {
419
+ for (;;) {
420
+ if (this.stopLevel || this.draining)
421
+ return;
422
+ await this.gate.wait();
423
+ if (this.stopLevel || this.draining)
424
+ return;
425
+ // Sampled before the take and handed to changed() below, so a release landing between the
426
+ // two cannot be slept through. Nothing may `await` between here and changed().
427
+ const generation = this.sched.generationId;
428
+ const kase = this.sched.take();
429
+ if (kase === null) {
430
+ if (this.sched.size === 0)
431
+ return; // nothing left for anyone — this worker is done
432
+ await this.sched.changed(generation); // park until a case finishes, or we are shut down
433
+ continue;
434
+ }
435
+ try {
436
+ if (stillEligible(kase))
437
+ await this.runCase(slot, kase);
438
+ else
439
+ this.recordSkipped(slot, kase);
440
+ }
441
+ catch (err) {
442
+ this.recordHarnessError(slot, kase, err);
443
+ }
444
+ finally {
445
+ // Both paths: a skipped case still reserved its tags in take().
446
+ this.sched.release(kase);
447
+ }
448
+ }
449
+ }
450
+ async renderLoop(signal) {
451
+ const interval = 1000 / RENDER_HZ;
452
+ while (!signal.aborted) {
453
+ this.renderOnce();
454
+ if (this.stopLevel && this.live.size === 0) {
455
+ await sleep(200, signal);
456
+ this.renderOnce();
457
+ return;
458
+ }
459
+ await sleep(interval, signal);
460
+ }
461
+ }
462
+ async run() {
463
+ this.sched = new Scheduler(this.cases, agentCaps(this.options.parallel));
464
+ this.writeSummary();
465
+ const onSignal = () => this.requestStop();
466
+ process.on("SIGINT", onSignal);
467
+ process.on("SIGTERM", onSignal);
468
+ const loops = new AbortController();
469
+ this.screen.listen(this, () => {
470
+ if (this.screen.enabled)
471
+ this.renderOnce();
472
+ });
473
+ const rendering = this.screen.enabled ? this.renderLoop(loops.signal) : Promise.resolve();
474
+ const onResize = () => this.renderOnce();
475
+ if (this.screen.enabled)
476
+ process.stdout.on("resize", onResize);
477
+ try {
478
+ await Promise.all(this.slots.map((slot) => this.worker(slot)));
479
+ if (this.screen.enabled) {
480
+ this.renderOnce();
481
+ await sleep(500);
482
+ }
483
+ }
484
+ finally {
485
+ this.stopLevel = Math.max(this.stopLevel, 1);
486
+ loops.abort();
487
+ await rendering.catch(() => undefined);
488
+ if (this.screen.enabled)
489
+ process.stdout.off("resize", onResize);
490
+ process.off("SIGINT", onSignal);
491
+ process.off("SIGTERM", onSignal);
492
+ for (const slot of this.slots)
493
+ slot.closeTranscript();
494
+ this.writeSummary();
495
+ this.writeTracker();
496
+ }
497
+ return this.exitCode();
498
+ }
499
+ /** Acquire the lock, run inside the alt screen, print the summary, always clean up. */
500
+ async main() {
501
+ this.lock = acquireLock(this.options.runsDir);
502
+ this.cleanup.add(() => this.lock?.release());
503
+ this.cleanup.add(() => this.screen.restore());
504
+ this.cleanup.install((err) => {
505
+ process.stderr.write(`${err instanceof Error ? (err.stack ?? err.message) : String(err)}\n`);
506
+ });
507
+ this.screen.enter();
508
+ let code;
509
+ try {
510
+ code = await this.run();
511
+ }
512
+ finally {
513
+ this.screen.restore();
514
+ }
515
+ if (!this.options.json) {
516
+ process.stdout.write(`${consoleSummary(this.info, this.sessionStats(), this.trackerPath)}\n`);
517
+ }
518
+ this.lock.release();
519
+ return code;
520
+ }
521
+ get sessionRecords() {
522
+ return this.records;
523
+ }
524
+ get sessionInfo() {
525
+ return this.info;
526
+ }
527
+ }
528
+ //# sourceMappingURL=harness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness.js","sourceRoot":"","sources":["../../src/qa/harness.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /** Turn raw stdin bytes into named keys, including CSI/SS3 arrows and paging. */
2
+ export declare class KeyDecoder {
3
+ private buf;
4
+ get pending(): boolean;
5
+ push(data: string): string[];
6
+ /**
7
+ * Called on the 250 ms read timeout: a buffer holding exactly ESC is a real Escape keypress
8
+ * rather than the start of a sequence that has not arrived yet.
9
+ */
10
+ flush(): string[];
11
+ private match;
12
+ }
@@ -0,0 +1,96 @@
1
+ const SS3 = {
2
+ A: "up",
3
+ B: "down",
4
+ C: "right",
5
+ D: "left",
6
+ H: "home",
7
+ F: "end",
8
+ };
9
+ const CSI_SEQ = {
10
+ "[A": "up",
11
+ "[B": "down",
12
+ "[C": "right",
13
+ "[D": "left",
14
+ "[H": "home",
15
+ "[F": "end",
16
+ "[5~": "pgup",
17
+ "[6~": "pgdn",
18
+ "[1~": "home",
19
+ "[4~": "end",
20
+ "[7~": "home",
21
+ "[8~": "end",
22
+ };
23
+ const TILDE_CODES = {
24
+ "5": "pgup",
25
+ "6": "pgdn",
26
+ "1": "home",
27
+ "4": "end",
28
+ "7": "home",
29
+ "8": "end",
30
+ };
31
+ /** Turn raw stdin bytes into named keys, including CSI/SS3 arrows and paging. */
32
+ export class KeyDecoder {
33
+ buf = "";
34
+ get pending() {
35
+ return this.buf.length > 0;
36
+ }
37
+ push(data) {
38
+ this.buf += data;
39
+ const keys = [];
40
+ while (this.buf.length > 0) {
41
+ const [key, n] = this.match(this.buf);
42
+ if (n === 0)
43
+ break;
44
+ if (key)
45
+ keys.push(key);
46
+ this.buf = this.buf.slice(n);
47
+ }
48
+ return keys;
49
+ }
50
+ /**
51
+ * Called on the 250 ms read timeout: a buffer holding exactly ESC is a real Escape keypress
52
+ * rather than the start of a sequence that has not arrived yet.
53
+ */
54
+ flush() {
55
+ if (this.buf === "\x1b") {
56
+ this.buf = "";
57
+ return ["esc"];
58
+ }
59
+ return [];
60
+ }
61
+ match(s) {
62
+ if (s[0] !== "\x1b") {
63
+ // Python yields a whole code point here; JS indexing would split an astral pair
64
+ // (a pasted emoji) into two lone surrogates.
65
+ const ch = String.fromCodePoint(s.codePointAt(0));
66
+ return [ch, ch.length];
67
+ }
68
+ if (s.length === 1)
69
+ return ["", 0];
70
+ if (s[1] === "O") {
71
+ if (s.length < 3)
72
+ return ["", 0];
73
+ return [SS3[s[2]] ?? "", 3];
74
+ }
75
+ if (s[1] !== "[")
76
+ return ["esc", 1];
77
+ let i = 2;
78
+ while (i < s.length && (/[0-9]/.test(s[i]) || s[i] === ";"))
79
+ i += 1;
80
+ if (i >= s.length)
81
+ return ["", 0];
82
+ const seq = s.slice(1, i + 1);
83
+ const mapped = CSI_SEQ[seq];
84
+ if (mapped)
85
+ return [mapped, i + 1];
86
+ const final = s[i];
87
+ if (final in SS3)
88
+ return [SS3[final], i + 1];
89
+ if (final === "~") {
90
+ const code = seq.slice(1).replace(/~+$/, "").split(";")[0] ?? "";
91
+ return [TILDE_CODES[code] ?? "", i + 1];
92
+ }
93
+ return ["", i + 1];
94
+ }
95
+ }
96
+ //# sourceMappingURL=keys.js.map