From 2b4f89b5bc7bd1894d0321a88c4f4ce6ff13577f Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Mon, 5 Oct 2026 16:02:47 +0000 Subject: [PATCH] build-job.mjs: the watcher reads the SUMMARY wherever it sits in the report (the closing report starts with the app header; two finished builds showed as still running on 5 October 2026) Co-Authored-By: Claude Fable 5.1 --- tools/build-job.mjs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/tools/build-job.mjs b/tools/build-job.mjs index 1995994d9..ebe71a67e 100755 --- a/tools/build-job.mjs +++ b/tools/build-job.mjs @@ -54,13 +54,24 @@ function db() { return j.rows; }; } -const summaryOf = lines => { const l = (lines || '').split('\n')[0]; if (!l.startsWith('SUMMARY ')) return null; try { return JSON.parse(l.slice(8)); } catch { return null; } }; +// the closing SUMMARY line wherever it sits in the report (5 October 2026: it was read from line 0 only, so a report whose +// first line is a STAGE or RESULT line hid a finished job and the watcher said "still running" past two done builds) +const summaryOf = lines => { for (const l of (lines || '').split('\n')) { if (!l.startsWith('SUMMARY ')) continue; try { return JSON.parse(l.slice(8)); } catch { return null; } } return null; }; const FINAL = new Set(['done', 'failed', 'timeout', 'aborted']); /// The newest report per machine for the job: { machine, summary, lines[] }. async function reports(sql, id) { - const rows = await sql(`SELECT DISTINCT ON (run_id) run_id, machine, received_at, lines FROM miner_logs WHERE run_id LIKE $1 AND label LIKE 'job-%' ORDER BY run_id, received_at DESC`, [`job-${id}-%`]); - return rows.map(r => ({ run_id: r.run_id, machine: r.machine, received_at: r.received_at, summary: summaryOf(r.lines), lines: (r.lines || '').split('\n') })); + // every report of the job, newest first; per run the newest row that carries a SUMMARY wins (a progress upload can + // land after the closing report), else the newest row + const rows = await sql(`SELECT run_id, machine, received_at, lines FROM miner_logs WHERE run_id LIKE $1 AND label LIKE 'job-%' ORDER BY run_id, received_at DESC`, [`job-${id}-%`]); + const byRun = new Map(); + for (const r of rows) { + const cur = byRun.get(r.run_id); + const sum = summaryOf(r.lines); + if (!cur) { byRun.set(r.run_id, { ...r, summary: sum }); continue; } + if (!cur.summary && sum) byRun.set(r.run_id, { ...r, summary: sum }); + } + return [...byRun.values()].map(r => ({ run_id: r.run_id, machine: r.machine, received_at: r.received_at, summary: r.summary, lines: (r.lines || '').split('\n') })); } async function watch(id, quiet = false) {