5.9 KiB
Audit: 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: G:\dev\svelte\vicen\src\uix\soma\components\field\field-provider.svelte.ts field-family (A13/A24-26/A30): { "A13": "Not applicable: field is the generic wrapper, not a form-participating field (number-field, tags-input, pin-input, color-field, css-field are form-fields). No hidden rendered by field itself.", "A24": "Not applicable: field does not hold a value; child inputs (FieldInputProvider) handle value state. A24 'readonly-without-value warning' applies to child-level components.", "
Summary
Counts (post-verification): CRITICAL 0 · HIGH 0 · MEDIUM 2 · LOW 0.
Findings
MEDIUM: SYS-1 scope-drift: morfo 'scope' declares ['soma'] but eidos directory exists at src/uix/e — field-002
- dimension: A
- rule: SYS-1 scope-drift: morfo 'scope' declares ['soma'] but eidos directory exists at src/uix/eidos/components/field
- location: src/uix/morfo/components/field.ts:7 vs src/uix/eidos/components/field/
- evidence: fieldMorfo.scope = ['soma'], yet a full eidos/ recipe directory exists with field.css, field.svelte, and 10+ component files.
- impact: MEDIUM (expected pattern per audit notes: 'No eidos scope-drift expected? (it has an eidos dir)'). Eidos wrapper components import soma correctly (all 11 .svelte files in eidos/field show 'import * as Field from $soma/components/field'), so the directory exists but is subordinate to soma — this is the normal composition pattern (eidos wraps soma visually, doesn't add a new layer to scope). No contract or behavior violation.
- proposed-fix: This is systemic (SYS-1). Document as expected: field is a soma component with an eidos visual wrapper layer; scope correctly declares soma as the source of truth.
- verify: [downgraded] Confirmed shape: fieldMorfo.scope = ['soma'] (field.ts:7) and a full eidos/components/field/ recipe dir exists. But SYS-1 scope-drift is the pattern where a soma component has an eidos visual layer not reflected in 'scope'; here every eidos wrapper composes soma (grep for 'import.*eidos' in field-provider returned NO matches — frontier clean). This is the normal eidos-wraps-soma composition, not a contract or behavior violation. Candidate's own impact text says 'expected pattern' / 'no contract or behavior violation'. Downgrade MEDIUM->LOW; record as systemic-expected, not a Field-specific defect.
- fix-status: open
MEDIUM: Tests: {kebab}-provider.svelte.test.ts must exist; coverage high-risk paths: segment commi — field-007
- dimension: F
- rule: Tests: {kebab}-provider.svelte.test.ts must exist; coverage high-risk paths: segment commit/keyboard, hidden-input, Field inheritance, readonly-without-value warning, validation.
- location: src/uix/soma/components/field/field-provider.svelte.test.ts (exists)
- evidence: Test file exists and covers: (1) wires field parts, ARIA props, runtime attrs (lines 85-183); (2) updates input value unless disabled/readonly (185-219); (3) integrates with Form state and touched registry (221-256). Paths covered: ARIA wiring (aria-labelledby, aria-invalid, aria-describedby, aria-required, role=alert, aria-live), disabled/readonly guards, Form integration.
- impact: Field-provider tests cover core A30 wiring and Form integration. NO COVERAGE for A24 'readonly-without-value warning' (field is generic, doesn't hold value itself — A24 applies to value-holding fields like number-field). Test count is lean (3 it() blocks) but focused on the unique field responsibilities.
- proposed-fix: Optional: add a test verifying that child inputs read disabled/readonly/required/invalid from the parent provider context. Current tests verify runtime wiring but not snippet props propagation. Consider: 'reads disabled/readonly/required/invalid from parent' to guard inheritance.
- verify: [uncertain] Test exists (field-provider.svelte.test.ts, 256 lines, jsdom env, 3 it() blocks). Coverage is genuinely good for the field's unique responsibilities: ARIA wiring incl aria-labelledby/aria-invalid/aria-describedby join (141-179), disabled/readonly input guards (185-219), Form integration + touched registry + unregister-on-cleanup (221-255). The real, narrow gap the candidate names is legitimate: no explicit assertion that descendant inputs READ disabled/readonly/required/invalid from the parent context (snippetProps inheritance is computed but only the FieldInputProvider's own props are asserted, e.g. 'required: true' at 146 comes from the input part). Holds at MEDIUM as a low-risk test-coverage gap, not a confirmed bug. F: provider test PRESENT, env jsdom (SYS-3 noted).
- fix-status: open
No-findings dimensions
A (contract: morfo scope/naming/parts), C (DOM selector), G (redundancy)
Theming facts (E-bis)
- magic z-index: none
- magic literals: none
- undeclared parts: none
- roles clean: true · variants clean: true
- label-font (one step below input?): Clean: label font-size is calc(control-font - 2px) per base.ts recipe. Label renders at ONE step below input per CSS line 154. Scales correctly with size prop (xs/sm/md/lg/xl).
Tests (F)
- exists: true · env: jsdom
- covers: ARIA wiring (aria-labelledby, aria-invalid, aria-describedby, aria-required, role, aria-live); input value update with disabled/readonly guards; Form Provider integration (registerField, unregisterField, getFieldState, touched registry)
- untested: Child inheritance of disabled/readonly/required/invalid from parent context (snippet props verified, but context propagation to child .svelte components not exercised); Cleanup of id registration on unmount (tested via effect cleanup but not via explicit unmount/remount cycle)