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/command.md

9.1 KiB

Audit: command

audit-version: 1 audited-at: 2026-06-26 scope: (SCOPE-DRIFT → SYS-1) method: adversarially-verified workflow (analyze → refute); HIGH/CRITICAL personally re-verified against cited code by the lead. provider: src/uix/soma/components/command/command-provider.svelte.ts

Summary

Counts (post-verification): CRITICAL 0 · HIGH 0 · MEDIUM 1 · LOW 5. systemic hits: SYS-1 (scope-drift); SYS-3 (jsdom-only, keyboard untested).

Findings

MEDIUM: SYS-1 scope-drift — command-001

  • dimension: E-bis
  • rule: SYS-1 scope-drift
  • location: src/uix/morfo/components/command.ts:7
  • evidence: scope: ['soma', 'sema'], — but eidos/components/command/ directory exists with CSS and components. Morfo declares scope omitting 'eidos'
  • impact: Component has eidos visuals and recipes but scope doesn't declare it; scope drift breaks the four-layer contract and may cause issues with validation or tooling that expect declared scopes
  • proposed-fix: Add 'eidos' to the scope array: scope: ['soma', 'sema', 'eidos']
  • verify: [downgraded] morfo line 7 reads scope: ['soma', 'sema'], and an eidos/components/command/ dir with CSS exists. But this is NOT command-specific drift: I counted 63 stateful morfos (combobox, calendar, date-picker, color-picker, dialog, select, popover, listbox, etc.) that ALL omit 'eidos' from scope while shipping an eidos recipe dir. The scope field semantics in src/uix/morfo/types.ts:770-839 govern SEMA/event coherence ('If a morfo declares events[] AND scope:['sema']...'), not eidos-recipe presence — the visual layer is not gated by the scope array. No contract test asserts scope must include 'eidos' when CSS exists. Treating this as a HIGH per-component contract violation contradicts the framework's own baseline (63/64 components do it). At most a systemic LOW doc/convention observation; the stated HIGH severity and 'breaks the four-layer contract' impact are not supportable.
  • fix-status: fixed (212624e0)

LOW: Magic literal — em font sizes — command-003

  • dimension: E-bis
  • rule: Magic literal — em font sizes
  • location: src/uix/eidos/components/command/command.css:260-261,272
  • evidence: inline-size: 1.125em (line 260-261) and font-size: 0.875em (line 272) are bare em values without canonical token references
  • impact: Icon and shortcut sizing use hard-coded em multipliers instead of --icon-size-* or --font-size-* tokens; inconsistent with theming system
  • proposed-fix: Replace 1.125em with a canonical icon size scale reference (e.g., --icon-size-md or create --command-item-icon-size). Replace 0.875em with a font-size scale reference or scale modifier
  • verify: [downgraded] Confirmed the literals: command.css:260-261 inline-size: 1.125em; block-size: 1.125em; (icon box) and 272 font-size: 0.875em; (shortcut). However em-based slot sizing is an established, idiomatic codebase pattern — grep across eidos shows field-control-trigger.css:30/45 1.75em/1em, menu-dial.css:281-282 1em, password-field.css:293/297-298 1em, table.css:339-340 1em, fab.css:103 1em. The em unit deliberately scales with the local --_command-item-font-size cascade (which IS token-driven), so these are RELATIVE sizing, not fixed px/rem drift the E-bis rule targets. At most a LOW consistency nit; MEDIUM overstates it given the framework-wide convention.
  • fix-status: open

LOW: Magic literal — pixel heights — command-004

  • dimension: E-bis
  • rule: Magic literal — pixel heights
  • location: src/uix/eidos/components/command/command.css:153,219,296
  • evidence: block-size: 2px (loading bar), gap: 1px (group items), block-size: 1px (separator) — bare pixel literals
  • impact: Three structural heights use magic pixels instead of token references; brittle to design changes
  • proposed-fix: Create or reference --border-width for 1px lines (already canonical for most components). For 2px loading bar, create --command-loading-height or use a custom CSS variable scoped to command
  • verify: [downgraded] Confirmed: command.css:153 block-size: 2px; (loading bar), 219 gap: 1px; (group items), 296 block-size: 1px; (separator). The 1px values are hairline-divider widths idiomatic across the codebase (separator/border lines); 2px is an off-scale loading-bar height. These are genuine bare-pixel literals but they are structural hairlines, not tokens that carry theming intent — LOW severity at most, not MEDIUM. No user-visible or behavioral impact.
  • fix-status: open

LOW: Morfo contract — archetype declaration — command-006

  • dimension: A
  • rule: Morfo contract — archetype declaration
  • location: src/uix/morfo/components/command.ts:98-124
  • evidence: Item part declares archetype: 'item' but does not declare Icon or Shortcut as sub-parts in the morfo
  • impact: Eidos defines Item.Icon and Item.Shortcut sub-parts (in eidos/components/command/index.ts) with their own data-* selectors, but they are not declared in the morfo. They are eidos-only sub-parts and properly documented in types.ts, so this is intentional (not an error)
  • proposed-fix: N/A — this is a documented eidos extension pattern
  • verify: [confirmed] Confirmed non-finding by the candidate's own admission. morfo declares Item (lines 97-124) with archetype 'item' and data-value/data-selected/data-disabled, but Icon/Shortcut are eidos-only sub-parts (index.ts:49-62 attaches ItemIcon/ItemShortcut; command.css:255/265 selectors documented as 'eidos-only' sub-part). This is the documented eidos-extension pattern, explicitly proposedFix 'N/A'. Correctly emitted as LOW with no action.
  • fix-status: open

LOW: Test environment — jsdom only — command-007

  • dimension: F
  • rule: Test environment — jsdom only
  • location: src/uix/soma/components/command/command-provider.svelte.test.ts:1
  • evidence: // @vitest-environment jsdom — test suite uses jsdom, which cannot test keyboard input, focus, or DOM pointer events accurately
  • impact: Keyboard navigation (ArrowDown/Up/Home/End/Enter/vim bindings) is complex behavioral code but only tested in jsdom (which doesn't fire real keyboard/mouse events). Focus logic untested.
  • proposed-fix: Add a client/Playwright test suite for keyboard navigation (arrow keys, grid columns, loop wrapping, Home/End), pointer selection, and focus sync. See SYS-3 pattern.
  • verify: [confirmed] Confirmed and arguably under-severed. test file line 1 // @vitest-environment jsdom; whole file is 122 lines with only 2 it blocks (line 77 filters+auto-select, line 96 navigates via provider.next/prev/selectCurrent API). No dispatchEvent/KeyboardEvent/focus( anywhere — the real onkeydown route in CommandInputProvider.onkeydown (lines 452-508: vim ctrl+n/p/j/k, Home/End, grid columns, RTL getDirectionalKeys) is NEVER exercised through a key event, only the underlying API methods are. This is a clean SYS-3 hit (interaction-heavy + jsdom-only + keyboard route untested). LOW is defensible but MEDIUM would be equally justified per the SYS-3 rubric.
  • fix-status: open

LOW: Viewport structure assumption — command-008

  • dimension: C
  • rule: Viewport structure assumption
  • location: src/uix/soma/components/command/command-provider.svelte.ts:598
  • evidence: const child = el.firstElementChild as HTMLElement | null; — assumes the viewport ref's first child is the measurable element
  • impact: If a consumer passes a custom child to Viewport (via the child snippet), firstElementChild may fail or measure the wrong element
  • proposed-fix: Add a fallback measurement: measure the viewport itself if firstElementChild is not present, or document this as a contract requirement (viewport must wrap content in a single element)
  • verify: [confirmed] Confirmed at LOW. provider line 598 const child = el.firstElementChild as HTMLElement | null; then observes it for resize. command-viewport.svelte renders {@render children?.()} with NO wrapper element, so firstElementChild measures whatever the consumer passes — fragile if the consumer renders text or multiple top-level nodes. Real robustness nit, but Viewport is optional: true in the morfo (line 93) and rarely used (List composes ScrollArea instead), and there is a if (!child) return; guard so it fails safe (no crash, just no height var). Correctly LOW; not behavioral/a11y.
  • fix-status: open

No-findings dimensions

B, D, G

Theming facts (E-bis)

  • magic z-index: none
  • magic literals: command-003 (em sizes) | command-004 (px heights)
  • undeclared parts: none
  • roles clean: true · variants clean: true

Tests (F)

  • exists: true · env: jsdom
  • covers: filter/visibility; navigation (basic); disabled items; group registration
  • untested: keyboard input (Arrow/Home/End/vim); pointer events; focus state; grid columns; loop wrapping edge cases; RTL keyboard inversion; two-moments ordering

Style observations (non-blocking)

  • Command CSS is well-structured with good comments explaining concentric radius + shape-nest pattern
  • Dialog integration (lines 71-99) cleanly separates panel chrome from palette chrome
  • Input styling mirrors Select trigger (consistent archetype treatment)
  • Item sub-parts (Icon/Shortcut) leverage inherited flex layout smartly

Powered by TurnKey Linux.