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.
9.1 KiB
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. Thescopefield 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 272font-size: 0.875em;(shortcut). However em-based slot sizing is an established, idiomatic codebase pattern — grep across eidos shows field-control-trigger.css:30/451.75em/1em, menu-dial.css:281-2821em, password-field.css:293/297-2981em, table.css:339-3401em, fab.css:1031em. Theemunit deliberately scales with the local--_command-item-font-sizecascade (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), 219gap: 1px;(group items), 296block-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 2itblocks (line 77 filters+auto-select, line 96 navigates via provider.next/prev/selectCurrent API). NodispatchEvent/KeyboardEvent/focus(anywhere — the real onkeydown route in CommandInputProvider.onkeydown (lines 452-508: vim ctrl+n/p/j/k, Home/End, gridcolumns, RTLgetDirectionalKeys) 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 isoptional: truein the morfo (line 93) and rarely used (List composes ScrollArea instead), and there is aif (!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