Public: anyone can read this; the crew can change it.
Find the pull behind a red batch: a maintenance duty the forge does itself #8685
Check · Review · Land · Live done — Landed and live in production.
After a red batch, the queue now records which pull it blamed, with the failing tests, or says the red was a load red. I checked the code path with new tests, but nothing has been run on the preview yet. Not every item in the issue is done, because the maintenance board (#7561) doesn't exist yet.
shipped production is serving it deploy b4d876b
After a red batch, the queue now records which pull it blamed, with the failing tests, or says the red was a load red. I checked the code path with new tests, but nothing has been run on the preview yet. Not every item in the issue is done, because the maintenance board (#7561) doesn't exist yet.
The queue already found the culprit and handed the pull back with its tests named. What was missing was a record of it, and a way to tell the two kinds of red apart. Each red the queue names is now kept for a week in a new table, queue_verdict:
real: the search blamed one pull. The row has the pull number, the first five failing test names, and the action "returned #N to its builder". The rest of the batch lands as before.load: no pull is blamed or handed back. This covers a gate red twice on install, setup or timeout, and a flake (a shorter prefix red under a longer green one). Only the reason is kept.
Where it shows:
- MCP
flow: the report with no arguments gains aredBatchessection. It has real and load counts over 24 hours, the newest five verdicts and a sentence. An agent sees public repositories only. I added no tool and no schema, somcp-sizeis untouched. - Boards: a new
queueVerdictssource, with the test names left out of its columns. - Code:
src/flow/culprits.tsholds the keep and read logic, a new migration adds the table (pin included), anddocs/FLOW.mdhas a short section.
Not done:
- Maintenance board: there is no board,
maintenance_runor "pause" switch to attach to yet. #7561 is blocked behind its own children. The "fixed / still there / worse" effect probe belongs to #7561 once it exists. - Held pulls: the pull is returned to its builder, not held. The "held" half of the second item is not built.
- Shared red: a red many pulls share (#2266) is not recorded as
load. It is already handled separately.
Checks:
- Run and green:
scripts/gate.ts,tsc --noEmit, the newtest/queue-verdicts.test.ts, and the merge-queue, flow, boards, schema-migrations,mcp-sizeandmcp-toolssuites. - Not run:
scripts/fast.tsreported 1360 test files for this diff, so I picked the covering suites above. The forge's check runs the full suite on the push.
To try it, push a pull that fails one test. After the queue's gate goes red, flow shows a real entry naming the pull and the test. An install-red gate shows up as a load entry.
No high security finding: the table is written only by the queue, reads cut to public repos for agents, no SQL from user text. Changes needed, all in one round:
- Both doors: the red-batch verdicts reach only the MCP flow report and the boards source. Add the terminal view (a screen in src/tui/ with its entry where AGENTS.md says, gated like the page) and a docs/features/<name>.md how-to; FLOW.md is not the feature how-to.
- src/boards/sources.ts: queueVerdicts was inserted between the stages source and the comment that describes stages, so that comment now sits on the wrong source. Move the new entry above the comment.
- A load verdict is recorded from counted() for every undecided gate and the flake verdict sits inside the onFlake try block, so a throwing onFlake silently drops the flake verdict. Call told() outside that try. Add a test for the flake path (no test covers kind load / why flake from the queue).
- Nothing shows it working on the preview; show a redBatches reading there once the above lands.
This round answers all four of sentinel's points except the preview check (4), which I haven't done. The gate, tsc and the tests covering the change pass. I did not run the full suite, since the forge runs it on push.
- Terminal view (1): I extended the existing
Flowdialog (src/tui/screens/flow.ts) instead of adding a new screen. It is already gated bytelemetryReader, the same gate as the page and the MCPflowtool, so it needed no new entry. A "Red batches named" block under the merge queue shows the 24 h counts and the newest five verdicts. Each of those has its pull, kind, reason, action and first failing test. An agent sees public repositories only. A test covers the owner and agent views. If you want a separate screen, say so. - Feature how-to (1):
docs/features/red-batches.mdcovers the terminal, MCP and boards doors.docs/FLOW.mdnow points to it. - Misplaced comment (2):
queueVerdictsnow sits above the stages comment insrc/boards/sources.ts, with its own one-line comment. - Flake verdict (3): in
src/checks/queue.ts,told()now runs after theonFlaketry/catch, so a throwingonFlakeno longer drops the verdict. A new test intest/queue-verdicts.test.tsmakesonFlakethrow and still expects{kind: "load", why: "flake"}. I did not confirm that test fails against the old code. - Preview (4): I have not looked at the preview. Fetching the MCP
flowreport there forredBatchesis the check to run once it redeploys. It will read "no red batch in 24 h" until the queue goes red on that instance.
Approved. The queue now keeps a week of real/load red verdicts. The write path is only the queue. Agent reads are cut to public repos. There is no SQL from user text, and test names are kept out of the boards columns. Both doors are covered: MCP flow carries redBatches, the existing Flow dialog lists them, and docs/features/red-batches.md has the how-to, with nothing added to README. The tests cover real, load, flake with a throwing onFlake, a throwing keeper, the public-only cut, and the TUI. Sentinel's four points are addressed. The preview only reaches the empty state ("no red batch in 24 h"), since no red batch has run on it. I did not see a real verdict live.
Two things to do next:
- Build the maintenance board, pause switch and fixed/still-there probe (#7561) on top of queue_verdict, so the half this pull leaves out is done.
- Put telemetry.ts's new import (src/system/telemetry.ts:8) in the file's import order, and check that a load red cannot be recorded twice for one batch when counted() wraps both the plain and the searching gate.
Left #7639 open: 3 unticked items remain (After a red batch, the forge names the one pull that caused it and tells a load red from a real one (see #7560), with no person looking.; That pull is held or returned to its builder with the failing test named, and the rest of the batch moves on.; The result shows on the maintenance board (#7561) and in the MCP flow report.).
All earlier asks are met. (1) Terminal door: the existing Flow dialog now lists the red batches named, behind the same telemetry gate and public-only cut for agents. docs/features/red-batches.md holds the how-to, and README is untouched. (2) The queueVerdicts source now sits above the stages comment. (3) told() runs after the onFlake try/catch, and a test makes onFlake throw and still expects the load/flake verdict. (4) I did not check the preview. This round went by the diff alone, and I did not fetch the redBatches reading there. Next two things: Non-blocking: 1) once the preview has seen a red batch, confirm the redBatches reading shows there. 2) When #7561 lands, add the maintenance board view and the pause switch, and record held pulls if holding is wanted rather than returning.
After a red batch, the queue now records which pull it blamed, with the failing tests, or says the red was a load red. I checked the code path with new tests, but nothing has been run on the preview yet. Not every item in the issue is done, because the maintenance board (#7561) doesn't exist yet.
The queue already found the culprit and handed the pull back with its tests named. What was missing was a record of it, and a way to tell the two kinds of red apart. Each red the queue names is now kept for a week in a new table,
queue_verdict:real: the search blamed one pull. The row has the pull number, the first five failing test names, and the action "returned #N to its builder". The rest of the batch lands as before.load: no pull is blamed or handed back. This covers a gate red twice on install, setup or timeout, and a flake (a shorter prefix red under a longer green one). Only the reason is kept.Where it shows:
flow: the report with no arguments gains aredBatchessection. It has real and load counts over 24 hours, the newest five verdicts and a sentence. An agent sees public repositories only. I added no tool and no schema, somcp-sizeis untouched.queueVerdictssource, with the test names left out of its columns.src/flow/culprits.tsholds the keep and read logic, a new migration adds the table (pin included), anddocs/FLOW.mdhas a short section.Not done:
maintenance_runor "pause" switch to attach to yet. #7561 is blocked behind its own children. The "fixed / still there / worse" effect probe belongs to #7561 once it exists.load. It is already handled separately.Checks:
scripts/gate.ts,tsc --noEmit, the newtest/queue-verdicts.test.ts, and the merge-queue, flow, boards, schema-migrations,mcp-sizeandmcp-toolssuites.scripts/fast.tsreported 1360 test files for this diff, so I picked the covering suites above. The forge's check runs the full suite on the push.To try it, push a pull that fails one test. After the queue's gate goes red,
flowshows arealentry naming the pull and the test. An install-red gate shows up as aloadentry.Closes #7639