Skip to content

Navigation Menu

Sign in
Sign up

Night Watch Component Auditor

Cindy Zhang edited this page Sep 6, 2026 · 27 revisions

Night Watch — Component Auditor

Assigned to: Cindy's Navi (cixzhang)

Goal: Ensure all components follow Astryx conventions — theming compatibility, API consistency, accessibility contracts, and export hygiene.

Authority and process: Product behavior is governed only by committed repository records whose front matter says authority: current. Start with the component spec, then follow its applicable module, family, design, architecture, theme, and AST relationships. The wiki owns audit procedure, practical guidance, scoring, and the ledger lifecycle; it does not replace those product records.

⚠️ Keep in sync. When a durable product requirement changes, update its canonical repository owner first, then update the rubric procedure or examples when needed. Do not add a reusable product rule only to the wiki.


Why This Role Exists

Component quality regresses silently. A hardcoded color, a missing themeProps, a boolean prop without is prefix, a missing displayName — these don't break tests or CI but they break the developer and theming contracts. This role catches the drift across all dimensions in a single pass per component.


Scope

Activation status: Draft spec:AST-029 proposes observational backfill and fail-closed auto-merge, but it is not authoritative yet. Until it becomes current together with a versioned component template/schema and active-record migration, a missing contract is only draft review material and every audit PR remains manual-review-only.

Each night this role takes one component and runs a full audit of it against the Component Audit Rubric — every section, including the rendered-design half, which means driving a real browser and capturing screenshots. Then it fixes what it can, re-audits to prove the fixes worked, and records the result.

One component done properly, rather than five skimmed. A pass that only runs the mechanical checks finds the drift a linter could have found; the expensive half — does this state actually render, is this reachable by keyboard, does the hover do anything — is where the real defects are, and it is worth a night.

The checks themselves are not restated here. The rubric is the single source for what is checked, how it is verified, and how it is scored. This page owns only the nightly mechanics: how the component is chosen, how fixes are made and proven, and how the result is recorded.

The score ledger — component-scores.json in this wiki — is the only record of progress. There is no separate state file, no queue kept on the side, no list of completed components. What has been audited, when, under which rubric version, and what is still open — all of it lives in the ledger, and the ledger is what the next night reads. If it is not in the ledger, it did not happen.


The nightly run

1. Pick the component

Read the ledger—component-scores.json in this wiki—and pick against the live roster generated from every component-bearing package registered in scripts/component-packages.cjs (currently Core, Lab, Charts, Rich Text, and Vega). The order is never-audited first, then oldest-audited, then lowest-scoring, so coverage grows before anything gets re-audited and the weakest components come back around soonest. Take the first one.

node scripts/score-ledger.mjs --queue --limit 1

Already audited today? The ledger's lastAudited says so. Stop; do not run twice.

2. Establish the observational component contract

Read the component's colocated <Name>.spec.md. If it is missing or incomplete, continue the audit from current repository authority and checkable evidence. You may optionally prepare a draft observational worksheet for owner review with the repository's component-specification guide. Until spec:AST-029 is current and its schema migration has landed, this worksheet cannot settle policy or make the PR auto-merge eligible. Record only verified shipped behavior; do not add or improve behavior. Use the proposed closed evidence matrix to make gaps visible for owner review.

Implementation defines component-local facts. Applicable current shared records and objective standards override conflicting implementation; those conflicts are audit findings to fix. A completed backfill becomes current only after exact-head owner approval. Any unresolved public API, compatibility, ownership, or subjective design decision makes the audit manual-review-only.

3. Audit it—the full rubric

Work Component Audit Rubric end to end, as a full component grading rather than a mechanical sweep. That means the automated checks and the judgement ones, and the screenshots: build Storybook, drive real Chromium, and capture every state the component has in light and dark. The rendered-design half is graded from pixels or it is reported not measured — never guessed, never scored zero.

Write the scorecard before changing a single line. It is the before half of the night's evidence, and you cannot prove a fix worked without it.

RTL applicability is mandatory

Run pnpm rtl:audit -- --filter <Name> for every component, new or existing. Do not call 0 pass / 0 fail / all N-A clean. Read the component source and every story for directional icons, contextual separators or connectors, positioned affordances, control order, scrolling or dragging, overlays, and horizontal keyboard behavior. Then leave the component in exactly one state:

  • measured: an applicable automatic or curated dimension ran;
  • verified N-A: add a specific core/Name or lab/Name reason to apps/storybook/rtl-audit/verified-not-applicable.json;
  • coverage gap: the harness has no dimension for behavior you found.

A coverage gap is a system-level finding. Link #5364 rather than filing one issue per component, add or extend the reusable detector/target, and re-run the component. Never invent a target that measures unrelated behavior just to turn N-A into pass. A verified-N/A entry is not an allowlist: remove it if later behavior makes an RTL dimension applicable.

For text decorations, context decides applicability. A slash in prose is neutral; an aria-hidden slash between repeated breadcrumb items communicates progression and D6 measures it. Unicode-mirrored angle quotes must not also receive a CSS flip; arrows and contextual slashes require one mirror or a glyph swap.

Chrome's CDP accessibility tree does not reliably expose aria-current. Verify the DOM attribute and the element's computed or implicit role separately; absence from the AX tree alone is unverified, not a failure.

4. Fix what you can

Fix the findings that have a clear right answer—a raw value that should be a token, missing behavior coverage, a missing stable visual-regression snapshot, consumer-doc drift, an unguarded hover, or an implementation bug against a current shared contract or objective standard. The same audit PR may contain the draft observational worksheet and these objective fixes. Work in one branch: night-watch-component-audit/<Component>/YYYY-MM-DD.

Leave alone anything that needs a decision rather than a correction: a naming dispute, a new prop, a changed API shape, a visual judgement call, a system-level design question. Those are not yours to settle in a fix pass — carry them in the scorecard and say so in the PR's Needs Review section. The Component Lifecycle routing rules say where each kind goes.

If a finding is real but you cannot fix it safely, that is fine. Leave it in the ledger as an open blocking finding with a one-line explanation. An honest open finding is worth more than a rushed fix.

5. Re-audit, and prove it

Run the audit again on the fixed component. This is the point of the whole exercise: the second score is what tells you the fixes worked, and it is what goes in the ledger.

  • Capture the screenshots again, so you have a genuine before/after pair for anything visual.
  • The score must move. If you fixed something blocking and the score is unchanged, then either the fix does not do what you think or the first audit was wrong. Find out which — do not record a number you cannot explain.
  • If a fix made something else worse, revert it. A nightly pass must never leave a component worse than it found it.

6. Record it

Record the post-fix score, per Recording an audit:

git clone https://github.com/facebook/astryx.wiki.git /tmp/astryx-wiki
<your scorecard JSON> | node scripts/score-ledger.mjs --record <Component> \
 --from - --ledger /tmp/astryx-wiki/component-scores.json --push

--push commits and pushes the wiki for you and prints the commit URL. Pipe the scorecard in rather than writing it to a file — the ledger is the only stored form, and a scorecard on disk is a second copy that goes stale within the hour. Use --dry-run first if you want to see the diff.

Your result appears on the Component Scores page without a rebuild — it fetches the ledger at runtime.

Only record what you actually measured. A section you could not verify is not_measured — never a guess, never a zero. Note the before score in the PR so the improvement is legible, but the ledger holds the current truth, which is the score after your fixes.

Do not file issues. Findings you did not fix live in the ledger row against the component, where the next audit will find them. A finding does not need a ticket to be tracked, and a nightly pass that files a dozen issues a week buries the ones that matter. The only exception is a system-level problem — something affecting many components that no single component's PR can fix. That gets one issue, and every affected ledger row links it.

7. Open the PR, drive it green, and keep it manual until activation

Publish it ready for review, not as a draft. The description carries:

  • the component package and exact repository/spec heads;
  • the before and after scores, and what moved;
  • the optional draft worksheet and its known evidence gaps, when one was prepared;
  • before/after screenshots for anything visual;
  • the findings you fixed, each citing its rubric rule id;
  • a Needs Review section for everything you deliberately did not fix, and why.

Then drive CI to green yourself: run pnpm test, pnpm build and pnpm lint:strict locally before pushing—CI is not your test runner. On failure, check the branch HEAD is still the SHA you pushed; if it changed, stop. Fix and push again. Three attempts, then stop and leave it for a human.

Do not enable auto-merge while spec:AST-029 is draft. Leave every audit PR open for human review. After an approved activation lands the current system spec, versioned component template/schema, active-record migration, and matching prompt and procedure together, the proposed gate additionally requires all of these on the exact head:

  • the component spec backfill describes only verified shipped or remediated behavior and has spec-owner approval;
  • every public concept and reachable state has a complete evidence-matrix row;
  • the PR changes no public API or compatibility/migration promise;
  • no ownership conflict or conflict between current records remains;
  • it makes no subjective representation, proportion, density, or interaction-feel decision;
  • every remediation is an objective test, stable visual snapshot, doc-drift fix, or bug fix with before/after evidence;
  • no unrelated cleanup is present; and
  • all required CI and review signals are green.

If any condition is not met after activation, do not auto-merge. Leave the PR open for human review.


Does not do

  • File hardening issues. Unfixed findings live in the ledger row, not in a ticket queue. Only a genuinely system-level problem gets an issue.
  • Keep its own state. The ledger is the record of progress — there is no state file to update.
  • Settle judgement calls. Public API, compatibility, ownership conflicts, and subjective visual direction route to the canonical repository owner and make the PR manual-review-only.
  • Batch components. One a night, audited properly.
  • Review other people's PRs — that is Night Watch Reviewer.

Clone this wiki locally

AltStyle によって変換されたページ (->オリジナル) /