test(rtl): close applicability gaps with fail-closed evidence - #5885
test(rtl): close applicability gaps with fail-closed evidence#5885freddymeta wants to merge 17 commits into
Conversation
…ured targets #5365 added the applicability rule — every component in the live Core+Lab roster is measured, verified N-A, or a coverage gap — and shipped verified-not-applicable.json empty. 223 of 246 components were therefore gaps, so pr-rtl was red on nearly every PR. It is soft-gated and blocks nothing; the cost is that a permanent red buries real RTL findings. Full library at 501e975, same command before and after: before COV : 22 measured / 1 verified N-A / 223 gap / 0 stale after COV : 26 measured / 101 verified N-A / 119 gap / 0 stale D1/D5/D6 verdicts are identical across the two runs (13 pass / 1 fail / 158 N-A, 19 PM pass, 14 DEC pass) — this change only adds registry rows and curated targets. 100 verified-N/A declarations, each written after reading that component's source and its stories, with a reason naming what it actually renders. Cross-checked afterwards: every proposed entry re-scanned for directional glyph names, rtlStyles.mirror, physical CSS, Left/Right keys, direction-reading JS, and positioned-plus-translate pairs. Twenty were then rendered LTR and RTL in Chromium — every element's RTL centre was the exact mirror of its LTR centre (max delta 2.7px) with nothing pinned to a physical side. `0 stale` is the load-bearing number: no declaration masks a dimension that actually fires. Four curated targets, all passing: TabList D3 core-tablist--overflow LTR +318, RTL -318 Drawer D4 lab-drawer--showcase LTR 0.82, RTL 0.18 Stepper D2 core-stepper--default-horizontal 85<647, 1015>453 TransferList D2 lab-transferlist--default 360<741, 740>360 TabList is the one that earns its keep: it exercises scrollByPage's isRtlElement sign flip, which no dimension reached before. Deliberately left as gaps: Table and its story groups, SideNav, TreeList, Toolbar, Slider, Tokenizer, the placement-driven overlays, MobileNav, TopNav, Selector, ListInput, Tour, LogStream, Markdown — all genuinely direction-sensitive and owed real measurement rather than a stamp. Every lab/Chart* entry too: whether a chart's category or time axis should mirror under RTL is a design decision, not a code fact.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Scoped runs, i.e. what Table and SideNav stay red on purpose — they are two of the components this PR refuses to stamp.
|
PR Analysis Report
No new or modified components detected. Bundle Size SummaryNo component packages changed. Accessibility AuditStatus: No accessibility violations detected. Generated by PR Enrichment workflow | View full report |
cixzhang
left a comment
There was a problem hiding this comment.
Thanks for doing the full applicability pass. Main now measures CheckboxList’s start/end relationship in core-checkboxlist--rich-descriptions, but this head still declares core/CheckboxList verified N/A. I replayed this registry against current main: D2 passes, then coverage exits with 1 stale. Please merge main, keep its CheckboxList target, and remove this verified-N/A row so the RTL signal goes green for the right reason.
[Reviewed by Robohands]
|
Addressed in
Verification:
— Puck, on behalf of Freddy |
# Conflicts: # apps/storybook/rtl-audit/targets.json
|
Follow-up: Reverified on the merged tree:
— Puck, on behalf of Freddy |
cixzhang
left a comment
There was a problem hiding this comment.
Thanks, the CheckboxList stale row is fixed, and this head’s full audit confirms every added target plus 0 stale.
Main moved again after your merge: #5648 added the Chat D2 target in the same targets.json block, so GitHub now reports this head as conflicting. Please merge main once more and retain both Chat and this PR’s Drawer/Stepper/TabList/TransferList targets; dropping either side would hide an RTL relationship from future PR checks.
[Reviewed by Robohands]
# Conflicts: # apps/storybook/rtl-audit/targets.json
cixzhang
left a comment
There was a problem hiding this comment.
Thanks, the two earlier asks—removing CheckboxList's stale declaration and retaining Chat's target—are fixed. The registry at apps/storybook/rtl-audit/verified-not-applicable.json:3 keeps every verified N-A row valid after its component or stories change, so a later RTL relationship outside the automatic detectors can stay hidden while PR CI reports it verified. Please tie each declaration to the source/story evidence it reviewed and fail closed when that evidence changes. Can we add a regression showing a changed declared component returns to a coverage gap until it is re-verified?
[Reviewed by Robohands]
# Conflicts: # apps/storybook/rtl-audit/targets.json # apps/storybook/rtl-audit/verified-not-applicable.json
# Conflicts: # apps/storybook/rtl-audit/targets.json
|
Addressed the evidence-invalidation request in
I also merged current main, removed landed duplicate coverage, reviewed and refreshed Validation on the pushed head: build pass, Storybook build + 101-row evidence check pass, strict lint pass, Storybook typecheck pass, 21/21 focused regressions pass, and scoped real audit |
# Conflicts: # apps/storybook/rtl-audit/targets.json # apps/storybook/rtl-audit/verified-not-applicable.json
# Conflicts: # apps/storybook/rtl-audit/verified-not-applicable.json
Cause
The RTL applicability contract requires every Core/Lab surface to be
measured,verified N-A, or a coverage gap. The registry originally had almost no reviewed N/A declarations, so the soft-gated audit was permanently red and hid new RTL findings.The remaining correctness hole was that a verified-N/A row survived later source or story changes. A declaration could therefore keep masking a newly introduced relationship outside the automatic detectors.
What changed
Fail-closed N/A evidence
Every verified-N/A declaration now stores SHA-256 evidence for:
A changed, added, removed, or renamed evidence file returns the component to
coverage-gapuntil that one declaration is manually re-reviewed and refreshed. Missing, empty, malformed, duplicate, or undiscoverable declarations also fail closed.pnpm rtl:audit:verify-na -- --component core/Text --writerefreshes exactly one reviewed declaration. Bulk refresh is refused.Storybook's existing required
buildcommand runs the evidence check after producingdist/index.json, so component-, story-, and registry-only PRs cannot bypass it even thoughpr-rtlremains soft-gated.Current-main coverage delta
Against current
main, this PR adds 96 reviewed N/A declarations and four curated targets:lab-drawer--showcasecore-tokenizer--logical-orderlab-transferlist--defaultcore-typeahead--logical-orderThe Stepper D2 target moved to #5495, which landed and now owns the component and regression on
main.Regression coverage
The focused suite proves:
verified-na;coverage-gap;verified-na;Real mutation controls also changed
Text.tsxandText.stories.tsxindependently: both failed with the exact changed path, and restoring the file made the checker pass again.Current validation
On pushed head
540b8cc694abecd78136500b1a9c5ba3a69594c4:7 measured / 3 verified N-A / 0 gap / 0 stale;Gates
pnpm rtl:audit:verify-na— pass:101 verified-N/A evidence declarations are currentpnpm lint:strict— 0 errors, 85 existing warnings7 measured / 3 verified N-A / 0 gap / 0 stale, exit 00 measured / 4 verified N-A / 0 gap / 0 stale, exit 0No changeset: this is internal audit infrastructure and checked-in audit data; no public package API changes.