// #775: real incident identities; list-window/order variants below are synthetic // witnesses, not a claim about GitHub's unsaved historical API responses. import test from 'node:test'; import assert from 'node:assert/strict'; import { decideReconciliation, pendingEvidenceError, processRuns } from '../scripts/process-reconcile.mjs'; import { decideResume, resume } from '../scripts/process-resume.mjs'; const LABEL = 'S7-code-review'; const incidents = [ [740, 'stairs-floor-switch', 36877086418, 36877204584, 'f23cca8f65a9641f9cc409b749347ba167cf9c65', '14:32:05', 'success'], [748, 'canon-reconcile', 36883983363, 36884081445, '395210117e242b5b16118cdfd1985f9a3d620cef', '15:24:18', 'success'], [744, 'floor-geometry-key', 36875649994, 36875756451, '62bd32538132462d4f5222a36db3bdf1e660b80b', '14:21:07', 'failure'], ]; function fixture(row = incidents[0]) { const [issue, slug, id, validateId, sha, time, conclusion] = row; const branch = `issue/${issue}-${slug}`; const createdAt = `2026-10-01T${time}Z`; const run = { id, attempt: 1, issue, label: LABEL, stage: 'code', status: 'completed', conclusion: 'success', createdAt }; const request = { id: 'request-1', label: LABEL, at: createdAt }; const pending = { schema: 1, issue: String(issue), run_id: String(id), run_attempt: '1', stage: 'code', branch, material_sha: sha, validate_run_id: String(validateId) }; return { issue, branch, sha, headSha: sha, request, labels: [LABEL], run, pending, runs: [run], validateRun: { id: validateId, event: 'workflow_dispatch', status: 'completed', headSha: sha, conclusion }, pendingOf: (candidate) => candidate.id === id ? pending : null }; } const raw = (run, extra = {}) => ({ ...run, event: 'issues', display_title: `process #${run.issue} · ${run.label} · fixture`, created_at: run.createdAt, ...extra }); test('#775 all three incident markers resume, including red Validate (ordinary prepare owns S6/comment)', () => { for (const row of incidents) assert.equal(decideResume(fixture(row)).action, 'resume', `#${row[0]}`); }); test('#775 history is paged to the request, not capped at 200 or filtered-search 1000 runs', () => { for (const row of incidents) { const f = fixture(row); const unrelated = Array.from({ length: 1100 }, (_, n) => raw({ ...f.run, id: n + 1, issue: 999, createdAt: '2026-10-01T16:00:00Z' }, { display_title: 'process #999 · P2 · unrelated label' })); const rows = [...unrelated, raw(f.run), raw({ ...f.run, id: 2, createdAt: '2026-09-30T00:00:00Z' })]; const calls = []; const runs = processRuns('o/r', [{ number: f.issue }], { since: f.request.at, getJson: (args) => { const url = args[1]; calls.push(url); assert.ok(!url.includes('event='), 'unfiltered endpoint avoids the search-result cap'); const page = Number(new URL(`https://api.test/${url}`).searchParams.get('page')); return { workflow_runs: rows.slice((page - 1) * 100, page * 100) }; } }); assert.equal(calls.length, 12); assert.equal(decideResume({ ...f, runs }).action, 'resume', `#${f.issue}`); } }); test('#775 history errors/repeated pages are not silently interpreted as a lost request', () => { const f = fixture(); const page = Array.from({ length: 100 }, (_, n) => raw({ ...f.run, id: n + 1 })); let calls = 0; assert.throws(() => processRuns('o/r', [], { since: f.request.at, getJson: () => { if (++calls === 2) throw new Error('API unavailable'); return { workflow_runs: page }; } }), /API unavailable/); assert.throws(() => processRuns('o/r', [], { since: f.request.at, getJson: () => ({ workflow_runs: page }) }), /pagination/); }); test('#775 stop at the request time, deduplicate overlapping pages, ignore non-issue workflow events', () => { const f = fixture(); const first = Array.from({ length: 100 }, (_, n) => raw({ ...f.run, id: n + 1, createdAt: '2026-10-01T16:00:00Z' })); const second = [first[99], raw(f.run), raw({ ...f.run, id: 3, createdAt: '2026-09-30T00:00:00Z' }), raw({ ...f.run, id: 200 }, { event: 'workflow_dispatch' })]; let count = 0; const runs = processRuns('o/r', [], { since: f.request.at, getJson: () => ({ workflow_runs: [first, second][count++] }) }); assert.equal(count, 2); assert.equal(runs.length, 101); assert.equal(new Set(runs.map((run) => run.id)).size, runs.length); }); test('#775 skipped noise can be ignored but newer attempted reviews are barriers', () => { const f = fixture(); const newer = { ...f.run, id: f.run.id + 1, createdAt: '2026-10-01T16:00:00Z' }; assert.equal(decideResume({ ...f, runs: [{ ...newer, conclusion: 'skipped' }, f.run] }).action, 'resume'); for (const conclusion of ['failure', 'cancelled', 'success']) { assert.equal(decideResume({ ...f, runs: [{ ...newer, conclusion }, f.run] }).action, 'noop', conclusion); } assert.equal(decideResume({ ...f, runs: [{ ...newer, status: 'in_progress' }, f.run] }).action, 'noop'); }); test('#775 a new request, branch head, different dispatch or damaged identity never wakes the old round', () => { const f = fixture(); for (const overrides of [ { request: null }, { request: { ...f.request, at: '2026-10-01T16:00:00Z' } }, { headSha: 'b'.repeat(40) }, { issue: 999 }, { branch: 'issue/740-other-branch' }, { validateRun: { ...f.validateRun, id: f.validateRun.id + 1 } }, { labels: [LABEL, 'S4-spec-review'] }, ]) assert.equal(decideResume({ ...f, ...overrides }).action, 'noop', JSON.stringify(overrides)); for (const overrides of [{ schema: 2 }, { issue: '999' }, { run_id: '1' }, { run_attempt: '2' }, { stage: 'spec' }, { branch: 'other' }, { validate_run_id: '' }]) { assert.equal(decideResume({ ...f, pendingOf: () => ({ ...f.pending, ...overrides }) }).action, 'noop', JSON.stringify(overrides)); } }); test('#775 write path rechecks current request, stop labels, head and runs; duplicates cannot relabel twice', async () => { const f = fixture(); for (const changed of [{ labels: [] }, { labels: [LABEL, 'blocked'] }, { headSha: 'b'.repeat(40) }, { request: { ...f.request, id: 'request-2' } }]) { let reads = 0; let writes = 0; const ops = { state: () => ++reads === 1 ? f : { ...f, ...changed }, runs: () => f.runs, pendingOf: f.pendingOf, relabel: () => writes++ }; const result = await resume({ ...f, repo: 'o/r', ops, sleep: async () => {} }); assert.equal(result.applied, false); assert.equal(writes, 0); } let reads = 0; let writes = 0; let state = f; const ops = { state: () => state, runs: () => { reads++; return f.runs; }, pendingOf: f.pendingOf, relabel: () => { writes++; state = { ...f, request: { ...f.request, id: 'request-2', at: '2026-10-01T17:00:00Z' } }; } }; assert.equal((await resume({ ...f, repo: 'o/r', ops, sleep: async () => {} })).applied, true); assert.equal((await resume({ ...f, repo: 'o/r', ops, sleep: async () => {} })).applied, false); assert.equal(writes, 1); assert.ok(reads >= 2); }); test('#775 transient missing/old/no-marker snapshots recover without waiting for the schedule', async () => { for (const row of incidents) { const f = fixture(row); let reads = 0; let writes = 0; const waits = []; const ops = { state: () => f, runs: () => ++reads === 1 ? (f.issue === 744 ? [] : [{ ...f.run, id: 1, createdAt: f.issue === 748 ? '2026-09-30T00:00:00Z' : f.run.createdAt }]) : f.runs, pendingOf: f.pendingOf, relabel: () => writes++ }; const result = await resume({ ...f, repo: 'o/r', ops, sleep: async (ms) => waits.push(ms) }); assert.equal(result.applied, true, `#${f.issue}`); assert.equal(writes, 1); assert.deepEqual(waits, [5000]); } }); test('#775 absent evidence gets a bounded grace, never a guessed relabel', async () => { const f = fixture(); let reads = 0; const waits = []; const result = await resume({ ...f, repo: 'o/r', sleep: async (ms) => waits.push(ms), ops: { state: () => f, runs: () => { reads++; return []; }, pendingOf: f.pendingOf, relabel: () => assert.fail('no evidence') } }); assert.equal(result.action, 'noop'); assert.equal(result.applied, false); assert.equal(reads, 3); assert.deepEqual(waits, [5000, 5000]); }); test('#775 reconciler uses the same request boundary, skipped-run handling and sealed identity', () => { const f = fixture(); const now = Date.parse('2026-10-01T17:00:00Z'); const base = { issue: { number: f.issue, labels: [LABEL] }, request: f.request, now }; const ready = { ...f.run, pending: f.pending, pendingValidate: 'completed' }; const skipped = { ...f.run, id: 999, createdAt: '2026-10-01T16:00:00Z', conclusion: 'skipped' }; assert.equal(decideReconciliation({ ...base, runs: [skipped, ready] }).action, 'retry'); assert.equal(decideReconciliation({ ...base, runs: [{ ...ready, resultArtifact: true }] }).action, 'escalate'); const justReapplied = { ...f.request, at: '2026-10-01T14:32:06Z' }; assert.equal(decideReconciliation({ ...base, request: justReapplied, now: Date.parse(justReapplied.at), runs: [ready] }).action, 'wait', 'previous run one second before the new label cannot be recovered as the new request'); assert.equal(pendingEvidenceError(f.pending, { issue: f.issue, run: f.run }), null); assert.match(pendingEvidenceError({ ...f.pending, run_attempt: '2' }, { issue: f.issue, run: f.run }), /attempt/); }); test('#775 a run starting between snapshots prevents the write', async () => { const f = fixture(); let reads = 0; const ops = { state: () => f, runs: () => ++reads === 1 ? f.runs : [{ ...f.run, id: f.run.id + 1, status: 'in_progress', createdAt: '2026-10-01T16:00:00Z' }, f.run], pendingOf: f.pendingOf, relabel: () => assert.fail('new process already running') }; assert.equal((await resume({ ...f, repo: 'o/r', ops })).applied, false); });