# Audit: radio-group audit-version: 1 audited-at: 2026-06-26 scope: method: adversarially-verified workflow; HIGH lead-verified. B6 ground-truth: checkbox/toggle/switch commit-toggle = sequence post (lag-fixed); radio-group/tabs/accordion/stepper set state at call-site (pre OK); toggle-group + checkbox-group carry the A31 .includes pattern (SYS-7); slider has no gesture-layer A6 leak. provider: G:\dev\svelte\vicen\src\uix\soma\components\radio-group\radio-group-provider.svelte.ts sequence-audit: state set at CALL-SITE (selectItem line 127: this.opts.value.current = value) BEFORE runtime.trigger (line 131). Morfo sequence: 'pre' (line 24). DOCTRINE: radio-group is call-site + pre, no lag risk. Prior batch verified 47ms acceptable for held-key nav. MATCH ✓ ## Summary Counts (post-verification): CRITICAL 0 · HIGH 0 · MEDIUM 1 · LOW 0. ## Findings ### MEDIUM: MAGIC-LITERALS: invalid-focus-ring shadow uses hardcoded px instead of canonical tokens — radio-group-001 - dimension: E: Theming - rule: MAGIC-LITERALS: invalid-focus-ring shadow uses hardcoded px instead of canonical tokens - location: src/uix/eidos/components/radio-group/radio-group.css:177 - evidence: box-shadow: 0 0 0 2px var(--color-surface-default), 0 0 0 4px var(--color-threat-element); - impact: The invalid state focus ring uses hardcoded 2px and 4px values instead of the canonical --focus-ring-offset and --focus-ring-width tokens. This breaks theming consistency and diverges from the pattern established in calendar (line 1712) and other components. If --focus-ring-width changes, this focus ring won't update. - repro: View a radio-group in invalid state with focus; compare the focus ring thickness to other components. Check base.ts focus-ring token definitions. - proposed-fix: Replace with: box-shadow: 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--color-threat-element); (matching the canonical pattern from calendar.css and input.css) - verify: [confirmed] Confirmed at radio-group.css:177 — `box-shadow: 0 0 0 2px var(--color-surface-default), 0 0 0 4px var(--color-threat-element);`. Canonical token-driven double-ring pattern exists in archetypes.css:123-124, recipes/base.ts:1693/1712/2835 and accordion.css:160-162 using `var(--focus-ring-offset)` + `calc(var(--focus-ring-offset) + var(--focus-ring-width))`. Tokens resolve to offset 1px / width 2px (generated/base.css:178-179), so canonical rings are 1px/3px while this hardcode renders 2px/4px — a real visual divergence, not just naming. No radio-group focus token override in the recipe; normal focus (line 122-124) is already tokenized. MEDIUM correct, confidence high. - fix-status: open ## No-findings dimensions A: Contract (morfo) — as const satisfies Morfo ✓, all 5 parts registered (provider/item/indicator/hidden-input/label), 2-of-3 data-{c}-{part} naming ✓, A: Contract — aria-hidden correctly set on indicator (line 132) and hidden-input (line 147), B: Behavior — Sequence audit: state set at CALL-SITE (selectItem line 127) before runtime.trigger, morfo sequence='pre' ✓ (matches doctrine for radio-group: call-site state + pre tolerates no lag per prior work, 47ms test), B: Behavior — A14 roving tabindex: exactly one tabindex=0 when selected or fallback ✓ (lines 222-226 and test 218-224), B: Behavior — A12 RTL: getDirectionalKeys(dir, orientation) called ✓ (line 242), no transform bug, B: Behavior — A13 hidden input: rendered, type=radio, name propagates ✓ (lines 344-355, test 226-233), B: Behavior — A30 id registration: direct assignment in constructor ✓ (line 382, not in $effect), A31 isChecked derivation: O(1) simple equality ✓ (line 220, no .includes loop), B: Behavior — No A6 gesture/observer/timer leaks (no setTimeout/setInterval/Gesture/ResizeObserver/MutationObserver used), C: DOM-selector — CSS.escape used on consumer value (line 93) ✓, D: Frontier — soma does not import eidos ✓, E: TSC composition — no cross-recipe TSC (TSC v2.1 palette local to radio-group, not shared), E: Theming — only 9 roles used ✓, no raw hex ✓, token references for font-size/icon-size/spacing ✓ (exceptions: focus ring magic 2px/4px found), F: Tests — test env jsdom ✓, covers roving (239-276), keyboard (261-269), state (197-237), hidden input (226-233), readonly/disabled guards (278-312) ## Theming facts (E-bis) - magic z-index: none - magic literals: 2px and 4px in invalid focus-ring shadow (line 177) - undeclared parts: none - roles clean: true · variants clean: true ## Tests (F) - exists: true · env: jsdom - covers: roving tabindex fallback (239-276: navigation, auto-select); keyboard navigation with loop/directional keys (237-268); state selection sync (197-237: onclick, isChecked derivation); hidden input name/value/checked form participation (226-233); readonly and disabled guards across group/item (278-312) - untested: RTL directional keys (dir='rtl' orientation swap verified in type but no jsdom RTL test); A30 label id registration edge case (id.current mutations) ## Style observations (non-blocking) - Focus ring pattern divergence: invalid state uses 2px/4px shadow offsets (hardcoded) vs canonical --focus-ring-offset/--focus-ring-width across other components - Data-attribute naming clean: data-radio-group provider, data-radio-group-{item|indicator|hidden-input|label} parts follow the kebab pattern correctly - Theming palette: _palette-solid TSC v2.1 correctly declared on host [data-radio-group], inherited by items — no double-declaration or cross-recipe contamination - No color role violations: only primary/secondary/neutral/affirm used (never risk/threat/loss)