# Audit: checkbox audit-version: 1 audited-at: 2026-06-26 scope: ['soma', 'sema', 'eidos'] 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/checkbox/checkbox-provider.svelte.ts sequence-audit: State set in handler: applyPending() at line 134 called by runtime event handler (lines 68-69). Morfo sequence='post' (checkbox.ts:28, 43). VERIFIED: state change deferred until AFTER sema dispatch via runtime.trigger() → event handler → applyPending(). Lag risk MITIGATED. Prior 244ms lag from 'pre' ## Summary Counts (post-verification): CRITICAL 0 · HIGH 0 · MEDIUM 1 · LOW 1. ## Findings ### MEDIUM: A31: per-item $derived calling provider method reading global state (.includes) = O(N²) — checkbox-001 - dimension: A31-O(N²) - rule: A31: per-item $derived calling provider method reading global state (.includes) = O(N²) - location: src/uix/soma/components/checkbox/checkbox-provider.svelte.ts:313-315, 320 - evidence: CheckboxGroupProvider.isItemChecked(value: string): boolean { return this.opts.value.current.includes(value); } and updateItemChecked also calls .includes(value). Each checkbox item in a group calls isItemChecked() to sync its state (line 104), resulting in N calls to .includes() on the array, yielding O(N²) when rendering N checkboxes in a group. - impact: For large checkbox groups (50+ items), observable performance degradation during render as each item calls isItemChecked() which iterates the entire value array. Not immediately critical for typical forms but documented risk. - proposed-fix: Convert group value from string[] to a Set (or use Map if needed for fast lookup). Migrate isItemChecked to Set.has() (O(1)). Update updateItemChecked to use Set.add/delete. Ensure Set is wrapped as $state(new SvelteSet()) for reactivity. - verify: [unverified] - fix-status: open ### LOW: Comments in English must match the actual contract; stale doc referencing wrong sequence i — checkbox-002 - dimension: A-doc-drift - rule: Comments in English must match the actual contract; stale doc referencing wrong sequence is drift - location: src/uix/soma/components/checkbox/checkbox-provider.svelte.ts:42-47 - evidence: The `_pendingChecked` JSDoc states: "The two-step dance lets sema fire BEFORE the structural commit (canon `sequence: 'pre'`)." But checkbox.ts:28 and :43 both declare `sequence: 'post'` (with an explicit morfo comment: "'pre' made the functional check wait for the perceptual hold (~240ms) → laggy"). The provider comment is stale: it cites 'pre' as the canon while the morfo deliberately uses 'post'. - impact: Misleading documentation. A future maintainer reading the provider could re-introduce the 244ms-lag 'pre' regression believing it is canon. No runtime effect — the morfo is correct. - proposed-fix: Update the comment to reference `sequence: 'post'` and explain the handler-runs-after-sema ordering, consistent with checkbox.ts:25-28. - verify: [verifier-added] added by adversarial verify pass - fix-status: open ## No-findings dimensions Contract(morfo): checkboxMorfo is 'as const satisfies Morfo' (line 172). All 6 parts registered via runtime.part() exist in morfo: 'provider', 'indicator', 'hidden-input', 'group', 'group-label' (lines 72, 193, 238, 304, 353). 2-of-3 rule satisfied., data-{c}/-{part} naming: All data attributes use kebab-cased part names (data-state, data-disabled, data-readonly, data-invalid on provider; data-state on indicator; data-orientation on group). No data-soma-* violations., aria/data emitted: morfo declares aria-checked, aria-required, aria-readonly, aria-invalid, aria-hidden on provider/indicator/hidden-input. Provider also declares type='button'. All values reference morfo specs correctly., Scope includes eidos: Morfo declares scope=['soma','sema','eidos'] (line 7). No eidos imports in soma provider (verified: no 'eidos' in grep output), which is correct—eidos layer is optional consumer. SYS-1 scope-drift REFUTED: eidos scope is declared but not imported into soma, which is the correct pattern., Events: Both commit-toggle-check and commit-toggle-uncheck have sequence='post' (lines 28, 43). No inert events (all emit to sema)., Gesture/A6: No gesture, setTimeout, setInterval, ResizeObserver, or MutationObserver in checkbox provider. No cleanup risk., Hidden input A13: CheckboxHiddenInputProvider renders with name/value for form participation (lines 249-255). aria-hidden='true' keeps it off AT tree so button role='checkbox' is sole control. tabindex=-1 excludes from focus. Correct A13 pattern., A30 direct registration verified: CheckboxGroupLabelProvider.setLabelId() called in constructor (line 362), not in $effect. Prevents reactive loop., Theme tokens: All CSS custom properties reference --checkbox-* or --font-*/--space-*/--color-*/--opacity-* canonical tokens from recipes/base.ts. No hex literals, no magic numbers in CSS (px/rem only in recipe: lines 639-653). Token naming --{c}-{slot} followed (--checkbox-size-md-box-size, --checkbox-bg-off, etc.). Private TSC tokens use _checkbox-palette-* pattern (lines 8-10, 162)., Color role subset: CheckboxColor = AffirmativeColorRole (types.ts:42), declared as primary|secondary|neutral|affirm (no risk/threat/loss). Per spec: invalid state handled via data-invalid attribute, not color role., Variants: CheckboxVariant = SelectionVariant (types.ts:30: solid|outline|ghost). CSS implements all three (lines 83-126). No undeclared variants., Sync attrs: runtimePart registered with syncAttrs=true (lines 77, 200, 242, 309, 356). Props returned via $derived.by for each part (lines 167-174, 208-212, 246-257, 331-335, 365-367). No double-write risk., A14 roving: Not applicable—checkbox is not a roving component (single input, not a group with tabindex navigation)., A12 RTL: Not applicable—checkbox has no directional keys (no slider, tabs, radio-group)., A15 gesture: Not applicable—checkbox does not use Gesture layer (no slider/splitter/scroll-area patterns)., Sequence lag FIXED: Prior 244ms lag incident from 'pre' sequence is RESOLVED by current 'post' design. State change in applyPending() handler defers until after sema dispatch. ## Theming facts (E-bis) - magic z-index: none - magic literals: stroke-dasharray: 100 | stroke-dashoffset: 100 | 8% | 18% | 82% | 72% | 78% - undeclared parts: none - roles clean: true · variants clean: true ## Tests (F) - exists: true · env: jsdom - covers: sequence/state commit (toggle, indeterminate clear); readonly/disabled guards; hidden input props + form participation; group value sync; label id context registration - untested: A31 O(N²) performance with large groups (50+ items); visual state transitions in real DOM; keyboard spacebar event in integration