Carry next_design's split on the human-queue design lane, so the dashboard can show the inbox apart from the defect - #243
Conversation
The dashboard's design box and /ndd disagreed about how much design work waits on a human: the snapshot's lanes cell carried the raw ai:design label total (6 on 2026-08-09) while next_design presented 0, withholding every row as 'no trusted comment raises a design question'. A count that cannot be driven to zero by doing the work it names is not measuring the work. human-queue --json now attaches next_design's own partition to the vetter-verdicts.ai:design cell: a breakdown object beside count (presentable / noQuestion / draft / unaddressable / fetchErrors, zeros included) and a bucket annotation on each prs entry, spelled identically so breakdown.<key> counts exactly the entries annotated <key>. The split routes through next_design's own classifier stages (nd_hit_class, then nd_outcome over the same gh pr view read) — one enumeration, one classifier; both matches are exhaustive so a new arm in either stage refuses to compile until the split gives it a bucket. count stays the raw label total for every existing consumer. counts.designPresentable / counts.designNoQuestion mirror the two headline buckets off the cell's own breakdown, so the history rollup — which copies counts verbatim — carries the series the dashboard draws: the human inbox (what /ndd serves) and the defect bucket (rows no command serves). counts.design keeps its raw meaning and its continuity. The producer-PR search now also returns isDraft, carried through QueuePr, so the draft withholding classifies fetch-free exactly as next_design's own search-stage does. Refs #240 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 50 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
WalkthroughThe PR tracks draft state through PR inventory records and adds JSON-only design-lane buckets. It annotates design records, emits zero-inclusive breakdowns, and adds presentable and no-question counts while retaining the raw design count. ChangesDesign lane inventory
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant HumanQueueJson
participant DesignSplitPipeline
participant DesignClassifier
participant GitHubDetailReads
HumanQueueJson->>DesignSplitPipeline: request design breakdown
DesignSplitPipeline->>DesignClassifier: classify design PR
DesignSplitPipeline->>GitHubDetailReads: fetch bounded PR details
GitHubDetailReads-->>DesignSplitPipeline: return detail results
DesignSplitPipeline-->>HumanQueueJson: return bucket annotations and breakdown
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@pr-review-report-rs/src/main.rs`:
- Around line 17443-17465: Update DesignBucket::ALL to be generated through an
exhaustive match over every DesignBucket variant, rather than maintaining an
independent literal array. Preserve the existing ordering and ensure adding a
new variant causes compilation to require updating this enumeration, keeping
breakdown zero-inclusive.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 4c117b30-b22f-4429-9204-852abc16c68a
📒 Files selected for processing (1)
pr-review-report-rs/src/main.rs
CodeRabbit on #243: a new variant makes key() fail to compile, but ALL compiled unchanged — so design_bucket would classify into the new bucket and annotate an entry with it while breakdown omitted its key, which is exactly the zero-inclusive contract the enum exists to state, broken quietly. ALL is now declared at length COUNT and checked against an exhaustive const fn ordinal() by a const block asserting every ordinal is listed exactly once. Four ways to get it wrong, four build failures, each verified: variant added, nothing else -> E0004 non-exhaustive ordinal() variant + ordinal + key + COUNT -> E0308 array length 5 != 6 COUNT raised alone -> E0308 array length 5 != 6 a variant listed twice in ALL -> E0080 'listed twice in ALL' Refs #240 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Reviewed a23b8e5: pass — members are selected by the same |
|
Reviewed a23b8e5: pass Rulings-conformance: checked the artifact against CLAUDE.md's rulings section and against every ruling the human stated for this work.
Merging with |
Closes #240
Pairs with rainlanguage/rain-org-health#168 — the renderer half. The two land together: this PR emits the split, that one draws it. Neither is harmful alone (an old dashboard ignores the new fields; the new dashboard falls back on a snapshot without them), but the number on the panel is only fixed when both are in.
What the mismatch was
Measured 2026-08-09T08:44Z, same moment, both tools: the dashboard said 6 design PRs waiting on a human;
/nddsaidpresentable0,noQuestion6. The snapshot'slanes["vetter-verdicts"]["ai:design"]carried the raw label total, andnext_designwithheld all six as "no trusted comment raises a design question". Draining the wholeai:designqueue that day did not move the box, because the number it drew was never the number of rulable rows.The schema
human-queue --jsonnow attachesnext_design's own partition to the design cell:plus two
countskeys mirroring the headline buckets off that samebreakdown:counts.designkeeps its exact meaning (the raw cell size, per #228), so the existing series is continuous. The rollup copiescountsverbatim, soqueue-history-linecarries the two new series with no change to the appender or torefresh-human-queue.sh.One enumeration, one classifier. The split does not re-implement "does a trusted comment raise a question". It routes each cell member through
next_design's own stages —nd_hit_classfirst (so a draft is withheld fetch-free, exactly as the live queue does it), thennd_outcomeover the samegh pr viewread. Both matches are exhaustive on purpose: a new arm in either stage refuses to compile until the split gives it a bucket. The members are selected by the sameclassify_lanecalllanes_docbuckets with, never by a label read, so the split describes exactly the list it is emitted beside (a PR wearingai:designunderai:close-candidateis in neither).breakdown.<key>is COUNTED OFF the annotated entries rather than copied from the split, so it equals the number ofprsrows carrying that bucket by construction.Cost: one
gh pr viewper design-lane member,--jsononly — the daily review prints the cell whole and pays nothing.Out of scope, per the issue: the search-index lag on a fresh ruling. No retry loop, and no log line either —
refresh-human-queue.shhas no non-trivial place to put one that says more than the existing stamped lines already do.QA
design_split_tests::{the_members_are_the_cells_own_prs, a_member_lands_where_ndd_would_put_it, the_breakdown_partitions_the_cell_it_is_attached_to, a_draft_member_is_filed_apart_without_a_read, an_empty_design_lane_emits_zeroes_not_a_cell, the_counts_mirror_the_breakdown_and_the_raw_series_survives}— all six name functions that do not exist on base, so they cannot compile against it; their discrimination is established by the mutation pass below rather than by a base run.state_descriptor_tests::every_descriptor_occupancy_source_resolves_in_the_emitted_document(pre-existing, extended here) fails on base-plus-emitter-removed — verified as mutant M8, which it names in its own words: "counts.designPresentable must emit even over an empty design lane".design_lane_membersreads the label instead of callingclassify_lane→ killed bythe_members_are_the_cells_own_prs(the dominatedai:close-candidate/ai:blocked-onmembers enter the split but not the cell)design_bucketswapsPresentable/NoQuestion→ killed bya_member_lands_where_ndd_would_put_itdesign_member_hithardcodesisDraft: false→ killed bya_draft_member_is_filed_apart_without_a_read(its fetch seam asserts the draft is never read)attach_design_breakdowncounts but never annotates the entries → killed bythe_breakdown_partitions_the_cell_it_is_attached_todesign_breakdown_countreads the cell'scountinstead of itsbreakdown→ killed bythe_counts_mirror_the_breakdown_and_the_raw_series_survivescountskeys are wired to each other's bucket → killed by the same test (the fixture is deliberately asymmetric, 1 presentable vs 2 noQuestion, so a swap cannot pass)attach_design_breakdowndrops the zero-valued keys → killed bythe_breakdown_partitions_the_cell_it_is_attached_to(key set derived fromDesignBucket::ALL, not typed twice)countsmirror loop is deleted → killed byan_empty_design_lane_emits_zeroes_not_a_cell,the_counts_mirror_the_breakdown_and_the_raw_series_survives, and the extendedevery_descriptor_occupancy_source_resolves_in_the_emitted_documentnext_design's own stated invariant,aiDesign == draft + unaddressable + presentable + noQuestion + fetchErrors + archivedRepo(theDesignQueueCountsdoc comment), and the live 2026-08-09 measurement in the issue (6 labelled / 0 presentable / 6 noQuestion) reproduced as the fixture shape. Fixture comment bodies are built by the REAL writers (state_comment,verdict_comment), so they cannot drift from what the pipeline actually posts.archivedRepohas no twin here and the reason is structural, not an omission:producer_pr_inventorywithholds archived-repo PRs before any lane is built, so this cell can never hold one.next_designcomputes, through the same classifier — done, viand_hit_class/nd_outcome; (b)countkept for backward compat with the split beside it — done; (c) theprslist split the same way — done, as a per-entrybucketannotation, which is what lets a consumer filter one list rather than reconcile several; (d)queue-history-linecarrying the new keys so the time-series can draw them — done, and it needed no change at all, since it copiescountsverbatim; (e) the dashboard rendering — the paired rain-org-health PR.Summary by CodeRabbit
New Features
Bug Fixes