Rule handbook metadata

Rule
AI.REACT.PRIMITIVE_CONSISTENCY · lane ai
Page status
stale
page_version
a8fc1f6189cc2753343c4c952614d91f8d4c22febaf51d040bc907cf2f8c5529
generated_at
2026-05-19T19:45:00.000Z
registry_fingerprint
6773fda516344e110b5a7b1435e655e1264e773825ca8bbe62194189891c42ba

How this rule is fixed

This is an AI-enabled rule. Pass/fail requires model judgment; there is no deterministic fixer in the pilot registry.

  • Harness: invoke-ai-ruleset-harness.sh runs design-rules/ai/run-design-ai-rule.sh on the Before fixture and expects findings with matching principleId.
  • Remediation: Cursor agent plans from forge-ux-remediation.plan.md after sitewide audit — not handbook After copy.

Detection module: docs/design/ux-audit/ai-enabled-design-principles.md#ai-react-primitive-consistency. Scroll down for Before / After examples and Evidence and remediation steps.

Purpose

Kitchen Sink React primitives (data-ks-type="react-primitive", family contract Rpf) ship from react/*.tsx with shared styling in css/forge-react-primitives.css and governed roots via ksReactPrimitiveAttrs(). Deterministic gates (DET.REACT.KS_ATTRS, DET.REACT.A11Y_ROLE, DET.HASH.MARKERS) prove markers and baseline ARIA; this AI rule judges whether adjacent primitives feel like one system—aligned state vocabulary, focus treatment, spacing rhythm, and severity semantics across banners, stage bars, headers, and action strips on the same operator surface.

Plan: On showcase (forge-react-primitives.html, react-primitives-live.html) or consumer run consoles, screenshot primitives in context—not isolated Storybook tiles. Note where one control uses Bootstrap alert colors, another uses inline hex, and a third invents pill shapes. Do: Refactor to ks-fe-* classes, shared badge/banner variants, and ksReactPrimitiveAttrs on every primitive root. Check: An operator scanning a run page reads status, stage, and actions with one visual language. Adjust: When the same metaphor clash repeats (for example ad-hoc stage pills beside ForgeWorkflowStageBar), propose a deterministic DET.* candidate or extend FAM-react-primitives.md with a forbidden pattern.

Passing signals

  • Every primitive root emits data-ks-react-root="true" plus child hash / data-ks-hash (for example Frh, Fsb, Fwb, Fda) via ksReactPrimitiveAttrs()—not a mix of bare divs and one hashed widget.
  • State vocabulary is shared: severity uses ks-fe-banner--failed, ks-fe-banner--await, ks-fe-stagebar__node--active, ks-fe-badge--warning—not parallel one-off class names or inline background: red on siblings.
  • Density follows the 4px baseline from FAM-react-primitives.md: ks-fe-run-header__title at ~1.05rem, stage nodes at ~0.72rem, banner padding ~0.85rem—no adjacent controls at wildly different scales without a documented variant (ks-fe-stagebar--executive).
  • Focus is consistent: navigable stage nodes use ks-fe-stagebar--nav buttons with :focus-visible cyan outline; toolbar actions stay on Bootstrap btn inside ks-fe-actionbar__inner rather than unstyled clickable spans.
  • Severity never relies on color alone: banners pair variant class with title text; stage nodes expose title / aria-label status strings (In progress, Blocked).
  • Disabled / waiting states look intentionally muted (ks-fe-stagebar__node--pending, banner --await) with explanatory copy—not identical to active controls.
  • prefers-reduced-motion: animated stage transitions and timeline rails honor reduced motion per family contract.
  • Showcase and consumer pages load forge-react-primitives.css (or equivalent Ksc bundle)—not partial copies with drifted tokens.

Failing signals

  • Mixed metaphors on one run surface: Bootstrap alert alert-danger beside ks-fe-banner, or raw badge bg-success beside ks-fe-badge--success.
  • Invented stage UI: rainbow inline-styled pills or progress bars when ForgeWorkflowStageBar (ks-fe-stagebar) already encodes status classes.
  • Inconsistent action chrome: primary actions as oversized btn-lg in a banner while the sticky strip uses btn-xs with different border radius and no ks-fe-actionbar.
  • Missing or partial KS markers: some React mounts have data-ks-hash while neighbors use unmarked wrappers—breaks audit anchoring and suggests copy-paste integration.
  • Focus rings differ per control: one primitive shows Bootstrap focus, another removes outline, stage "tabs" are div click targets without keyboard support.
  • Traffic-light carnival: unrelated hues for the same semantic state (warning as pure yellow #ff0 on one row, amber token on the next).
  • Density chaos: run header crammed to 0.65rem while banner title floats at 1.4rem with ad-hoc style attributes bypassing CSS variables.
  • ARIA roles inconsistent with visuals: status strip uses role="alert" on a static label; toolbar missing role="toolbar" while buttons float in a generic footer.

Before example

Before (failing example)

Docs health run #8842

WAITING

Started 2026-05-19 · workspace lenses-local

Plan Execute Verify

Failing KS markup: run review panel stitches together Bootstrap alerts, ad-hoc stage pills, and unmarked wrappers—mixed severity colors, inconsistent button sizes, no ks-fe-* primitive roots.

After example

After (passing example)

Docs health run #8842

Started 2026-05-19 · workspace lenses-local

  • Awaiting review

Passing KS markup: same run context composed from governed primitives—Frh, Fsb, Fwb, Fda with ks-fe-* classes, shared severity tokens, and ksReactPrimitiveAttrs markers on each root.

Evidence and remediation

Capture: showcase URL (forge-react-primitives.html, react-primitives-live.html) or consumer run page; DOM snapshot showing adjacent primitive roots; screenshot at 1280px with at least one error/warning and one navigable stage. Record which hashes appear and whether forge-react-primitives.css loaded. Note metaphor clashes (Bootstrap alert vs ks-fe-banner, inline stage pills vs ks-fe-stagebar).

Remediate (in order):

  1. Replace ad-hoc markup with the matching primitive from react/*.tsx (ForgeRunHeader, ForgeStatusBanner, ForgeWorkflowStageBar, ForgeDecisionActionBar, etc.).
  2. Ensure each root calls ksReactPrimitiveAttrs() so DET.REACT.KS_ATTRS and hash governance pass.
  3. Map severity and stage status to documented ks-fe-* variant classes—remove inline colors and duplicate Bootstrap alert/badge patterns.
  4. Align action buttons to btn btn-sm inside ks-fe-actionbar__inner; keep density consistent with banner actions.
  5. Verify keyboard focus on interactive stage nodes (ks-fe-stagebar--nav) and toolbar role="toolbar" per DET.REACT.A11Y_ROLE.
  6. Rebuild showcase (python3 generator/build-showcase.py) and re-run AI batch with principleId: AI.REACT.PRIMITIVE_CONSISTENCY.
  7. If the same integration anti-pattern repeats across consumers, extend FAM-react-primitives.md forbidden patterns or propose a deterministic DET.* rule.