You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/audit/components/toggle.md

4.2 KiB

Audit: toggle

audit-version: 1 audited-at: 2026-06-26 scope: (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/toggle/toggle-provider.svelte.ts sequence-audit: State is set INSIDE handler (toggle-provider.svelte.ts:105-109, lines 106-107: opts.pressed.current = next). Morfo sequence='post' (morfo/components/toggle.ts:43). Runtime correctly executes 'post' sequence: handler runs first (runtime.svelte.ts:742), then await tick() (line 747), then runEmit() (li

Summary

Counts (post-verification): CRITICAL 0 · HIGH 0 · MEDIUM 1 · LOW 0.

Findings

MEDIUM: SCOPE-DRIFT (SYS-1): eidos recipe dir exists but morfo scope omits 'eidos' — toggle-001

  • dimension: Contract (morfo)
  • rule: SCOPE-DRIFT (SYS-1): eidos recipe dir exists but morfo scope omits 'eidos'
  • location: src/uix/morfo/components/toggle.ts:25
  • evidence: Morfo declares scope: ['soma', 'sema'] but eidos directory exists at src/uix/eidos/components/toggle/ with toggle.css and toggle.svelte that emit data-variant, data-size, data-block, data-icon-only. Checkbox (checkbox.ts:7) declares scope: ['soma', 'sema', 'eidos'] as comparison.
  • impact: Morfo scope does not accurately reflect the component's actual API surface. Eidos-provided visual attrs (data-variant, data-size, data-block, data-icon-only) consumed by toggle.css are outside the declared contract.
  • proposed-fix: Add 'eidos' to morfo scope: scope: ['soma', 'sema', 'eidos']
  • verify: [confirmed] CONFIRMED SYS-1 scope-drift at MEDIUM. morfo/components/toggle.ts:25 declares scope: ['soma', 'sema'], yet a full eidos surface exists: src/uix/eidos/components/toggle/ ships toggle.css + toggle.svelte + types.ts + a recipe entry (lib/recipes/base.ts:3646 toggle: {). The eidos wrapper (toggle.svelte:49-52) emits data-variant/data-size/data-block/data-icon-only consumed by toggle.css. Peer twins DO declare eidos: checkbox.ts:7, radio-group.ts:7, tabs.ts:7, and notably toggle-group.ts:10 (which reuses Toggle's recipe via structural identity) all carry scope: ['soma', 'sema', 'eidos']. NOTE on severity ceiling: this is purely a contract-accuracy/documentation gap — scope is documented (types.ts:799) as 'Layers that implement this component' but NO validator enforces 'eidos' presence (the morfo-coverage check at types.ts:835-839 only errors on events-without-sema-scope and warns on missing expression). It is also not toggle-unique: switch.ts:24 (toggle's structural twin) has the identical omission. So MEDIUM is the correct ceiling — real inconsistency vs. direct peers, zero functional/runtime impact. Does not rise to HIGH.
  • fix-status: fixed (212624e0)

No-findings dimensions

Behavior (soma), DOM-selector, Frontier (soma->eidos), TSC, Theming, Redundancy

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 via vitest
  • covers: State toggle via runtime.trigger('commit-toggle'); Morfo attrs sync (data-state, data-color, aria-pressed, aria-label) via ActiveDom; FieldProvider integration (isDisabled, isReadonly, isRequired, isInvalid OR-merge); Readonly blocks handler execution without disabling button; onPressedChange callback invocation
  • untested: Sequence timing verification (post-sequence lag risk — implicitly passing in smoke test but no explicit await measurements); Disabled button attr is set (props test at line 145 confirms, but not explicitly called out); Hidden input rendering with name+pressed condition

Style observations (non-blocking)

  • Morfo comment (lines 40-42) accurately documents the 'post' sequence rationale: 'celebrate the new state, not the gesture'
  • Provider comment (lines 39-46) clearly states this is 'runtime-direct' pilot without base class, ownership model is transparent
  • Type safety: OptsFromProps union at lines 22-36 and Managed union stay in sync via comment at lines 12-21

Powered by TurnKey Linux.