Hub Quality & Risk banded dials — epic #500 child 1 (#525) - #528
Conversation
Each 0-100 score now renders as a banded arc beside its number. The band is the SERVER's (state.qualityRisk) — the client never re-derives one; the arc uses pathLength="100" so the dash IS the score, which also means the morph patching that one attribute on a stable node is the draw-in animation (--motion-draw tier, frozen by the global reduced-motion guard). Honest nulls hold and stay distinguishable: an unknown score draws the empty track only — no zero-length arc may imply a measured zero — while a real 0 (contracts present, nothing flagged) draws its empty arc and reads "0", per the #453 contract. Band colors are one token set (--band-*) read by BOTH the tile border and the arc stroke, so the two palettes cannot drift. The dial is role=img with a "<label> <score> of 100, band <band>" aria-label; the readable number it augments stays in the DOM. New canonical fixture: fixtureScoredRun. Every existing fixture leaves quality/risk null (no builder.json anywhere), so the first draft of the browser tests passed VACUOUSLY through the unknown branch — proving nothing. The scored fixture makes the tests demand real arcs that equal the projection's own numbers. Live verification of those dials then surfaced #527 (filed, out of scope here): the rollup index does not persist builder objects, so an index-served run scores 15/low where a full parse scores 50/high — the card silently understates risk for most runs. The dials render the projection faithfully either way; the fixture docstring records the trap. Closes #525. Part of epic #500. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Strix is installed on this repository, but we couldn't run this PR security review because this workspace's trial has ended. Add a card to resume code reviews here. |
|
Warning Review limit reached
Next review available in: 14 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. 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: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
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 |
PR Summary by QodoRender banded Quality & Risk dial arcs from server-provided scores/bands
AI Description
Diagram
High-Level Assessment
Files changed (5)
|
Code Review by Qodo
Context used✅ Compliance rules (platform):
300 rules✅ Skills:
|
Qodo bug 1 (real): qrDialHtml trusted the score's shape — esc() only HTML-escapes, so a non-finite score emitted stroke-dasharray="NaN NaN" and an out-of-range one a negative remainder. qrNumericScore is now the single guard for BOTH the arc and the number: non-numeric renders the honest unknown (no arc, em-dash) and out-of-range clamps the arc. The text path had the same pre-existing weakness (it would have printed "NaN/100") — fixed by sharing the guard rather than patching one caller. Qodo bug 2: the browser test dereferenced card.projection and riskTile before asserting they exist, so a regression would surface as a TypeError instead of a diagnosis. Both asserted first now. Refs #525 (PR #528 review follow-up). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Both Qodo findings addressed — both were real:
Suite note: one full-suite run showed 7/7 dial pins, 26/26 browser, lint/typecheck clean. — Claude Main |
Closes #525 · first implementation child of epic #500 (data-viz).
What
Each 0-100 score renders as a banded arc beside its number:
state.qualityRiskand never re-derives a band.pathLength="100"makes the dash units the score itself (stroke-dasharray="62 38"for 62) — which also means the Hub client: full-DOM live repaints destroy node identity — swallowed clicks, dropped focus, broken selection #495 morph patching that one attribute on a stable node is the draw-in animation, at the--motion-drawtier, frozen by the pinned reduced-motion guard.0— contracts present, nothing flagged — draws its empty arc and reads0, per the Quality & Risk Index: Aggregated Risk Score + Complexity Index from the 15 stages #453 contract.--band-*tokens are read by both the tile border and the arc stroke, so the two can't drift.role="img"with"<label> <score> of 100, band <band>"; the arc isaria-hidden; the readable number the dial augments stays in the DOM.The test that almost lied
The first draft of the browser tests passed on unfixed code — every canonical fixture leaves quality/risk null (no
builder.jsonanywhere), so each assertion sailed through an honest-unknown branch and proved nothing. Fixed by adding the canonicalfixtureScoredRun(real builder contracts, mixed severities incl. one mitigated, a guardrail block, files touched, a container-verified execution) and rewriting the tests to demand real arcs whose lengths equal the projection's own numbers. Only then did they go red.What live verification then found — #527
Looking at the rendered card (screenshot captured via playwright-core), the chips read "0 files touched · 0 builder tasks" against a fixture authoring two contracts and five files. Probing full-parse vs index-served on one root:
The same run flips high → low purely because of a cache tier, while
risk_count: [2,2]sits in the same snapshot. That is a false score with a reassuring green band — filed as #527 (out of scope here; the dials render the projection faithfully either way, and the fixture docstring records the trap).Verification
Core 1899/1899 · browser 26/26 · lint 0 · typecheck 0 · validate 196 · security green · whitespace clean. Live-verified: dials match the projection exactly (arc
"15 85"for score 15, band classlow).Merging after green checks + reviewer bodies read, per the current working protocol.
🤖 Generated with Claude Code