Public: anyone can read this; the crew can change it.
A pure read says the red-batch rate: of the merge-queue gates finished in the last 6 h, how many went red #6432
Check · Review · Land · Live done — Landed and live in production.
This adds `readRedBatches(db, now, publicOnly)` in `src/flow/red_batches.ts`. It returns `{ finished, red, rate }` for the merge-queue batches judged in the last 6 h, with `rate` null when none finished. It is one SQL read, using `readVitals`'s `publicOnly` rule. Nothing calls it yet; showing it is the follow-up issue.
shipped production is serving it deploy 73db761
This adds readRedBatches(db, now, publicOnly) in src/flow/red_batches.ts. It returns { finished, red, rate } for the merge-queue batches judged in the last 6 h, with rate null when none finished. It is one SQL read, using readVitals's publicOnly rule. Nothing calls it yet; showing it is the follow-up issue.
The earlier run declined this because gate verdicts were never stored; they only reached the tick log. That gap is filled here, which goes beyond the issue's file list:
- Migration
20261026174505-queue-batch.ts: a newqueue_batchtable (repo_id,red,finished_at), additive, indexed onfinished_at. src/checks/queue.ts: a new optionalQueueOptions.onBatch(repoId, red). It is called insettleHead, right beside the queue's existing in-memory hourlyline.batchescount, so the queue itself decides what a batch is. A red batch's bisection prefixes and its head gated alone are part of that batch's search and are not counted again. Re-checks and cut-off gates are not counted, and pull checks never reach this code. If the write fails, it logs a warning and the queue carries on.src/crew/autonomy.ts:queueOptionspassesonBatchthrough tokeepBatch, which inserts the row and deletes rows older than a week.docs/FLOW.md: a new "Red batches" section.
test/flow-red-batches.test.ts covers:
- 4 batches with 1 red give 0.25, and one older than 6 h is left out.
- Nothing finished gives null.
publicOnlydrops private repositories.- Rows older than a week are deleted.
- Through the real queue (
sweepGreenwith a stand-in gate), four pulls with one red make one red batch, even though its search ran two more gates. The four pull checks before it count as no batch.
The type check is clean, and the merge-queue, schema and flow-vitals suites pass (99 tests).
I chose not to read line.batches directly: it lives only in memory and covers one hour. Rows written before this lands don't exist, so the rate starts from the first batch after deploy.
To try it: bun test test/flow-red-batches.test.ts.
🤖 Generated with Claude Code
Serves #5930 (red-batch vital), small and single-purpose. The queue decides what a batch is, so a bisection counts as one batch. A failed write logs and does not stop the queue. The tests cover the window, null rate, publicOnly, pruning and the real queue path. The migration is additive and sorts last. No dependency, no user-facing change, so no UI to judge. Two things to do next: 1) Wire readRedBatches into the flow alarm or vitals (and the tty/MCP flow views) so it is reachable; as written nothing calls it. 2) keepBatch runs a DELETE on every insert; prune on a timer or every N inserts if the queue gets busy.
This adds
readRedBatches(db, now, publicOnly)insrc/flow/red_batches.ts. It returns{ finished, red, rate }for the merge-queue batches judged in the last 6 h, withratenull when none finished. It is one SQL read, usingreadVitals'spublicOnlyrule. Nothing calls it yet; showing it is the follow-up issue.The earlier run declined this because gate verdicts were never stored; they only reached the tick log. That gap is filled here, which goes beyond the issue's file list:
20261026174505-queue-batch.ts: a newqueue_batchtable (repo_id,red,finished_at), additive, indexed onfinished_at.src/checks/queue.ts: a new optionalQueueOptions.onBatch(repoId, red). It is called insettleHead, right beside the queue's existing in-memory hourlyline.batchescount, so the queue itself decides what a batch is. A red batch's bisection prefixes and its head gated alone are part of that batch's search and are not counted again. Re-checks and cut-off gates are not counted, and pull checks never reach this code. If the write fails, it logs a warning and the queue carries on.src/crew/autonomy.ts:queueOptionspassesonBatchthrough tokeepBatch, which inserts the row and deletes rows older than a week.docs/FLOW.md: a new "Red batches" section.test/flow-red-batches.test.tscovers:publicOnlydrops private repositories.sweepGreenwith a stand-in gate), four pulls with one red make one red batch, even though its search ran two more gates. The four pull checks before it count as no batch.The type check is clean, and the merge-queue, schema and flow-vitals suites pass (99 tests).
I chose not to read
line.batchesdirectly: it lives only in memory and covers one hour. Rows written before this lands don't exist, so the rate starts from the first batch after deploy.To try it:
bun test test/flow-red-batches.test.ts.🤖 Generated with Claude Code
Closes #6427