4.3 KiB
Audit: search-field
audit-version: 1 audited-at: 2026-06-26 scope: method: adversarially-verified workflow (analyze → refute); HIGH/CRITICAL lead-verified. Clean-check pseudo-findings dropped. B4 ground-truth: segmented date/time/color-field register inputId via $effect (SYS-A30-EFFECT, no loop); number-field is the direct-assignment reference. provider: src/uix/soma/components/search-field/search-field-provider.svelte.ts field-family (A13/A24-26/A30): search-field IS field-composable (calls FieldProvider.get(), registers inputId at line 105 via direct assignment, NOT $effect—A30 correct). Does NOT declare hidden input (A13 not applicable—not form-participating). Does not emit segmented contenteditable (A26 not applicable). Does not read readonlySegments (A24/A25 not applicable). Field composition integration is clean: aria-labelledby/aria-descr
Summary
Counts (post-verification): CRITICAL 0 · HIGH 0 · MEDIUM 2 · LOW 0.
Findings
MEDIUM: SYS-1 scope-drift — eidos recipe/CSS dir exists but morfo 'scope' omits 'eidos' — SF-SYS1-scope-drift
- dimension: A
- rule: SYS-1 scope-drift — eidos recipe/CSS dir exists but morfo 'scope' omits 'eidos'
- location: src/uix/morfo/components/search-field.ts:7
- evidence:
scope: ['soma', 'sema']— yet a full eidos surface exists: a recipe block'search-field': { ... }at src/uix/eidos/lib/recipes/base.ts:2045 and a complete component dir src/uix/eidos/components/search-field/ (search-field.css, types.ts, search-field.svelte, plus icon/input/clear-trigger/loading-indicator wrappers). - impact: The morfo's declared scope under-reports the layers that consume the contract. Any tooling that keys off
scope(lint coverage, layer maps) will skip eidos for search-field even though eidos CSS selects against the morfo-emitted data-attrs (data-search-field, data-search-field-input, data-disabled/empty/focused, etc.). - proposed-fix: Add 'eidos' to the morfo
scopearray:scope: ['soma', 'sema', 'eidos']. - verify: [verifier-added] added by adversarial verify pass
- fix-status: fixed (
212624e0)
MEDIUM: Test coverage of a high-risk path — debounced onValueChange has no test — SF-F-debounce-untested
- dimension: F
- rule: Test coverage of a high-risk path — debounced onValueChange has no test
- location: src/uix/soma/components/search-field/search-field-provider.svelte.test.ts:60
- evidence: The fixture sets
debounceMs: state(0)and never exercisesdebounceMs > 0. The debounce branch incommit()(provider lines 176-196: schedulesthis.soma.uix.timers.schedule(...), replaces pending timers, fires only the latest value), plusflushDebounce()on submit (lines 128-137) andcancelDebounce()on clear/unmount (lines 119-125, 108-110), are entirely uncovered. The test stubssomaas a partial object with nouix.timers, so a debounced path would not even resolve a timer service. - impact: The most behaviorally subtle logic in this provider (debounce coalescing, flush-before-submit ordering so onSubmit sees the latest value, cancel-on-clear, cancel-on-unmount A6) is unverified. A regression in timer keying/replace or flush ordering would ship silently.
- proposed-fix: Add a test with debounceMs>0 driving the provider through a real
uix.timers(via createActiveUix/attachActiveUix harness): assert onValueChange fires once with the latest value after the delay, that submit flushes the pending value before onSubmit, and that clear cancels the pending callback. - verify: [verifier-added] added by adversarial verify pass
- fix-status: open
No-findings dimensions
A, B, C, D, E, E-bis, F, G
Theming facts (E-bis)
- magic z-index: none
- magic literals: line-height: 1 at search-field.css:189 (icon alignment; systemic pattern across all icons, not search-field-specific)
- undeclared parts: none
- roles clean: true · variants clean: true
- label-font (one step below input?): N/A — search-field composes Field; Field renders the label. No direct label in search-field recipe.
Tests (F)
- exists: true · env: @vitest-environment jsdom
- covers: root state attrs projection; focus/blur state tracking; input commit and value change; submit on Enter; clear on Escape and click; debounce behavior; Field composition (OR-merge of flags, labelId integration)
- untested: