3.9 KiB
Audit: switch
audit-version: 1 audited-at: 2026-06-26 scope: ['soma', 'sema'] (SCOPE-DRIFT → SYS-1) 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: src/uix/soma/components/switch/switch-provider.svelte.ts sequence-audit: State set in handler (switch-provider.svelte.ts lines 103-105: opts.checked.current = next inside 'commit-toggle' event); morfo sequence='post' (morfo line 39); lagRisk=NONE (post-sequence correct for handler-set-state). Doctrine verified: Checkbox/Toggle/Switch use post (state in handler); no lag e
Summary
Counts (post-verification): CRITICAL 0 · HIGH 0 · MEDIUM 1 · LOW 0.
Findings
MEDIUM: SYS-1: morfo scope must declare all layers with recipe directories — switch-001
- dimension: Contract
- rule: SYS-1: morfo scope must declare all layers with recipe directories
- location: src/uix/morfo/components/switch.ts:24
- evidence: scope: ['soma', 'sema'] declared, but src/uix/eidos/lib/recipes/base.ts:3370+ contains 'switch:' recipe and src/uix/eidos/components/switch/ directory exists with switch.css (line 1: [data-switch])
- impact: Recipe tokens in eidos layer not declared in morfo scope; eidos wrapper (src/uix/eidos/components/switch/switch.svelte:30) adds data-size but recipe scope is undeclared
- proposed-fix: Add 'eidos' to morfo scope: scope: ['soma', 'sema', 'eidos']
- verify: [downgraded] REAL inconsistency but downgraded MEDIUM->LOW. Confirmed at src/uix/morfo/components/switch.ts:24
scope: ['soma', 'sema']while the eidos recipe exists (src/uix/eidos/lib/recipes/base.ts:3370switch: {) and the dir src/uix/eidos/components/switch/ ships switch.css (line 1[data-switch] {) + switch.svelte. The literal scope doc (types.ts:799 'Layers that implement this component') supports including 'eidos'. BUT three facts cut the severity: (1) the canonical Toggle pilot — closest sibling, with structural identity + recipe + eidos dir — ALSO omits eidos: src/uix/morfo/components/toggle.ts:25scope: ['soma', 'sema'], so this is a Toggle/Switch-family convention, not a Switch-specific drift (checkbox.ts:7 and radio-group.ts:7 DO declare 'eidos' — codebase is split); (2) no validator enforces eidos-in-scope — types.ts:835-839 only errors onevents[] + no scope:['sema']and warns on missingexpression, neither of which Switch violates (expression:'pack' present at line 27); (3) it is inert metadata with no runtime effect. SYS-1 baseline lists scope-drift as MEDIUM, but the Toggle parity + zero enforcement make this LOW. - fix-status: fixed (
212624e0)
No-findings dimensions
Behavior (sequence), Behavior (A13 hidden input), Behavior (A30 ID registration), Behavior (no A6 leaks), Behavior (no A31 O(N²)), DOM-selector, Frontier (soma doesn't import eidos), TSC (palette tokens correct), Theming (role aliases, token refs), Tests (jsdom, sequence coverage)
Theming facts (E-bis)
- magic z-index: none
- magic literals: none
- undeclared parts: none
- roles clean: true · variants clean: true
Tests (F)
- exists: true · env: jsdom
- covers: click toggle; keyboard toggle (Enter/Space); field integration (disabled/readonly/required/invalid merge); hidden input form participation
- untested: sequence lag via perceptual timing; intent/color resolution matrix
Style observations (non-blocking)
- Recipe tokens well-organized with TSC v2.1 palette pattern (_palette-solid/-solid-hover per color:primary/secondary/affirm/risk/threat)
- Color-mix() usage for disabled states follows design system
- Transition tokens reference canonical --duration-fast/--ease-default
- Token naming --switch-* follows convention (no raw hex, all refs)
- Magic literals in sizes resolved to vars (switch-size-{xs..xl}-track-width, etc.)