The mismatch
The dashboard and /ndd disagree about how much design work is waiting on a human, and the dashboard is the one that is wrong.
Measured 2026-08-09T08:44Z, same moment, both tools:
|
says |
dashboard (human-queue --json → lanes["vetter-verdicts"]["ai:design"]) |
6 PRs |
/ndd (next_design) |
presentable 0, noQuestion 6 |
site/pipeline.html:864 files that box under { owner: "human", … act: "rule on design Q" }. So the dashboard is telling a human there are six design questions to rule on, and the command built to rule on them has nothing to present — it withholds every one of the six, each with "why": "no trusted comment raises a design question".
The six: cyclo.site#412, rain.erc4626.words#233, rain.erc4626.words#166, raindex#2778, raindex#2721, raindex#2720.
Why it matters beyond a wrong number
The whole ai:design queue was drained on 2026-08-09 — six rows, all ruled. The dashboard did not move, because the number it draws was never the number of rulable rows; it is the raw label count. A panel whose count cannot be driven to zero by doing the work it names is not measuring the work.
It also hides the real defect. Those six rows are stranded: labelled into a lane whose command cannot present them, and picked up by no other actor's queue. Folding them into the same number as genuine questions is what makes them invisible. #241 covers routing them out; this issue is about not counting them as human inbox in the first place.
What to change
human-queue --json already has the split — next_design computes exactly aiDesign == draft + unaddressable + presentable + noQuestion + fetchErrors (pr-review-report-rs/src/main.rs:27138). The snapshot should carry the same breakdown for the design lane, and the dashboard should render:
presentable as the human inbox — the count /ndd will actually serve, and the one that goes to zero when a human drains the queue
noQuestion as a separate defect bucket, not as human work — same treatment the leak bucket gets, which the panel already models as "should trend to zero" rather than as an inbox
draft / unaddressable / fetchErrors wherever they belong, but not silently inside the human's number
The invariant to hold: every count the dashboard files under owner: "human" is a count some human command will present. If no command serves it, it is not an inbox, and displaying it as one manufactures work that cannot be done.
Secondary: the snapshot lags label writes
Separate and much smaller. cyclo.site#386 was ruled ai:needs-work at ~08:35Z; the refresh-human-queue run that pushed 4d12035 at 08:41Z still listed it under ai:design with counts.design: 7. A direct pr-review-report human-queue --json at 08:44Z returned 6 without it. So the snapshot inherits GitHub's search-index lag, and a refresh fired shortly after a ruling publishes a count that is already wrong.
Not worth a retry loop, but worth knowing when reading the panel: the hourly refresh can be up to one cycle behind a just-made ruling. If anything, the fix is for the refresh to log the lag rather than to fight it.
Related: #238, #239.
The mismatch
The dashboard and
/ndddisagree about how much design work is waiting on a human, and the dashboard is the one that is wrong.Measured 2026-08-09T08:44Z, same moment, both tools:
human-queue --json→lanes["vetter-verdicts"]["ai:design"])/ndd(next_design)presentable0,noQuestion6site/pipeline.html:864files that box under{ owner: "human", … act: "rule on design Q" }. So the dashboard is telling a human there are six design questions to rule on, and the command built to rule on them has nothing to present — it withholds every one of the six, each with"why": "no trusted comment raises a design question".The six: cyclo.site#412, rain.erc4626.words#233, rain.erc4626.words#166, raindex#2778, raindex#2721, raindex#2720.
Why it matters beyond a wrong number
The whole
ai:designqueue was drained on 2026-08-09 — six rows, all ruled. The dashboard did not move, because the number it draws was never the number of rulable rows; it is the raw label count. A panel whose count cannot be driven to zero by doing the work it names is not measuring the work.It also hides the real defect. Those six rows are stranded: labelled into a lane whose command cannot present them, and picked up by no other actor's queue. Folding them into the same number as genuine questions is what makes them invisible. #241 covers routing them out; this issue is about not counting them as human inbox in the first place.
What to change
human-queue --jsonalready has the split —next_designcomputes exactlyaiDesign == draft + unaddressable + presentable + noQuestion + fetchErrors(pr-review-report-rs/src/main.rs:27138). The snapshot should carry the same breakdown for the design lane, and the dashboard should render:presentableas the human inbox — the count/nddwill actually serve, and the one that goes to zero when a human drains the queuenoQuestionas a separate defect bucket, not as human work — same treatment the leak bucket gets, which the panel already models as "should trend to zero" rather than as an inboxdraft/unaddressable/fetchErrorswherever they belong, but not silently inside the human's numberThe invariant to hold: every count the dashboard files under
owner: "human"is a count some human command will present. If no command serves it, it is not an inbox, and displaying it as one manufactures work that cannot be done.Secondary: the snapshot lags label writes
Separate and much smaller. cyclo.site#386 was ruled
ai:needs-workat ~08:35Z; therefresh-human-queuerun that pushed4d12035at 08:41Z still listed it underai:designwithcounts.design: 7. A directpr-review-report human-queue --jsonat 08:44Z returned 6 without it. So the snapshot inherits GitHub's search-index lag, and a refresh fired shortly after a ruling publishes a count that is already wrong.Not worth a retry loop, but worth knowing when reading the panel: the hourly refresh can be up to one cycle behind a just-made ruling. If anything, the fix is for the refresh to log the lag rather than to fight it.
Related: #238, #239.