# Audit: date-field audit-version: 1 audited-at: 2026-06-26 scope: ['soma', 'sema'] (SCOPE-DRIFT → SYS-1) 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\date-field\date-field-provider.svelte.ts field-family (A13/A24-26/A30): A13: form-participating hidden input correctly implemented (lines 1011-1040), renders with name/value/required/disabled when name is set. A24: readonly-without-value warning implemented via soma.logger.warn (lines 355-370), guards against misconfiguration when readonlySegments set without value. A26: onbeforeinput preventDefault required for segmented contenteditable — CORRECT implementation at li ## Summary Counts (post-verification): CRITICAL 0 · HIGH 0 · MEDIUM 2 · LOW 0. ## Findings ### MEDIUM: SYS-1 (scope-drift) — date-field-001 - dimension: scope - rule: SYS-1 (scope-drift) - location: morfo line 7 + eidos dir exists - evidence: Morfo declares scope: ['soma', 'sema'] (src/uix/morfo/components/date-field.ts line 7) but eidos recipe dir src/uix/eidos/components/date-field/ and CSS src/uix/eidos/components/date-field/date-field.css both exist. Scope MUST include 'eidos' when the recipe and CSS layer are present. - impact: Contract validator may not catch visual-layer rules as part of the component's declared surface area. - proposed-fix: Update morfo scope from ['soma', 'sema'] to ['soma', 'sema', 'eidos'] - verify: [confirmed] CONFIRMED at MEDIUM. morfo `src/uix/morfo/components/date-field.ts:7` declares `scope: ['soma', 'sema']` (grep verified), while the eidos layer exists: recipe block `'date-field':` at `src/uix/eidos/lib/recipes/base.ts:1172` and CSS `src/uix/eidos/components/date-field/date-field.css` (read in full, 228 lines). This matches the documented systemic SYS-1 scope-drift (MEDIUM). NOTE: the project's stated REFERENCE component NumberField has the IDENTICAL condition — number-field.ts:7 also declares `scope: ['soma', 'sema']` yet `src/uix/eidos/components/number-field/` exists — so this is a true systemic pattern for the field family, not a date-field-specific defect. Severity stays MEDIUM per SYS-1; confidence high that the condition holds, with the caveat that whether 'eidos' is REQUIRED in scope for these components is a project-wide convention question. - fix-status: fixed (212624e0) ### MEDIUM: Test coverage gap (field-family paths) — date-field-003 - dimension: tests - rule: Test coverage gap (field-family paths) - location: date-field-provider.svelte.test.ts (275 lines) - evidence: Test suite covers: segment helpers (120-165), validation (174-198), segment commit (200-220), time-segment sync (222-240), granularity filtering (242-274). MISSING: (1) hidden-input render when name is set; (2) readonly-without-value warning fired; (3) commit-set/commit-reset event emission; (4) keyboard navigation per APG (ArrowUp/Down/Left/Right/Backspace); (5) Field parent integration (inputId wiring). - impact: High-risk field-family paths untested: form submission via hidden input, readonly misconfiguration guards, and event-driven workflows. - proposed-fix: Add test cases for: shouldRender hidden input, soma.logger.warn call when readonlySegments + undefined value, commit event firing on segment completion, keyboard segment navigation (at least one key per segment type), and Field parent inputId registration. - verify: [confirmed] CONFIRMED at MEDIUM (F dimension — high-risk field-family test gap). The test file `date-field-provider.svelte.test.ts` (read in full, 275 lines) covers ONLY: segment helpers (initSegmentStates/isAcceptableSegmentKey/getFirstSegment/handleSegmentNavigation, 120-165), validation min/max/custom (174-198), incremental segment commit (200-220), padded date+time sync (222-240), granularity filtering (242-274). UNTESTED high-risk paths that DO exist in the provider: (1) hidden-input render — `DateFieldHiddenInputProvider.shouldRender` (provider line 1022) and its A13 ISO `value`/`name`/`required` props (1027-1040) are never exercised; (2) readonly-without-value A24 warn — the `$effect` calling `soma.logger.warn` (provider 354-369) is never triggered, even though the harness already stubs `logger.warn: vi.fn()` (test line 72), so the assertion would be trivial; (3) commit event emission — `runtime.trigger('commit-set'|'commit-reset')` (provider line 785) untested; (4) keyboard segment navigation per APG (ArrowUp/Down/Backspace/number-key handlers, provider 1108-1296) untested at provider level; (5) Field parent inputId wiring (DateFieldInputProvider $effect, provider 932-936) untested. Severity MEDIUM (missing tests for high-risk paths); confidence high that these paths are real and uncovered. - fix-status: open ### MEDIUM: A30 — inputId registered via `$effect` instead of direct constructor assignment (SYSTEMIC: date/time/color-field) - dimension: B - rule: A30 (child→parent id registration MUST be a direct constructor assignment, not `$effect`) - location: date-field-provider.svelte.ts:932-936 (`$effect(() => { const field = this.provider.field; if (!field) return; field.inputId.current = opts.id.current; })`) - evidence: lead-confirmed by direct read — the DateFieldInput provider wraps the `field.inputId` registration in a `$effect`, whereas the project reference NumberField does it as a direct constructor guard (number-field-provider.svelte.ts:585-587: `if (this.provider.field) { this.provider.field.inputId.current = opts.id.current; }`). time-field (531-535) and color-field (521-525) use the identical `$effect` — SYSTEMIC. - impact: no loop today (the Input provider only WRITES `field.inputId` and never reads it back, and `opts.id` is a stable framework id), so the A30 page-freeze hazard is not live — but it is contrary to A30 doctrine and inconsistent with the NumberField reference; a future reader who makes the registration two-way (or reads inputId in the child) would reintroduce the freeze. - repro: static — compare date/time/color-field Input providers (`$effect`) vs number-field (direct). - proposed-fix: replace the `$effect` with a direct constructor assignment guarded by `if (this.provider.field)`, matching NumberField. Apply across date-field, time-field, color-field. - verify: [lead-added] the date-field agent's no-findings claim falsely listed "A30 direct id-wiring" as clean; the verify on time-field-001 + lead reads of date-field:932-936 / color-field:521-525 confirm the `$effect` pattern. Elevated to a systemic MEDIUM. - fix-status: open ## No-findings dimensions A (Contract morfo), B (keyboard, A17 focus, A33, A35, A6 cleanup, TWO-MOMENTS — note: A30 id-wiring is NOT clean, see date-field-A30), C (DOM-selector safety), D (Frontier soma→eidos), G (Redundancy) ## Theming facts (E-bis) - magic z-index: none - magic literals: 'day' | 'month' | 'year' | 'hour' | 'minute' | 'second' | 'dayPeriod' | 'literal' | 'timeZoneName' - undeclared parts: none - roles clean: true · variants clean: true - label-font (one step below input?): Label calc(1em - (var(--font-size-md) - var(--font-size-sm))) produces correct one-step scaling at md but degrades at sm input size (line 109) — see finding date-field-002. ## Tests (F) - exists: true · env: jsdom (vitest) - covers: segment state initialization; input acceptance (numeric + nav keys only); DOM segment reading (getValueFromSegmentsDOM); segment focus navigation (ActiveDom); validation (custom/min/max); segment commit on fill; time segment padding; granularity filtering (hour → no minute/second) - untested: hidden-input conditional render when name is set; readonly-without-value warning logger.warn() call; commit-set and commit-reset events firing; keyboard handling per APG (all arrow directions, backspace per segment); Field parent integration (inputId registration); readonly segment visual treatment; cross-segment cascades (month→day clamp, hour→dayPeriod flip, dayPeriod→hour AM/PM); year segment typeahead logic (pressedKeys tracking) ## Style observations (non-blocking) - Recipe tokens correctly reference --space-*, --radius-*, --font-size-*, --color-* (lines 1173-1222). No bare hex/rgb/oklch in recipe. No --opacity-* barefoot decimals (opacity-disabled token used, line 1222). Z-index not used in date-field CSS. Theming uses 9 roles (primary/secondary/neutral/affirm/fulfill/risk/threat/loss + implicit default). Label font-weight is var(--font-weight-regular), not emphasized. Segment readonly uses underline dotted var(--color-content-muted) + surface-overlay bg (consistent field family). - Invalid border color uses var(--color-risk-border) per theming rule (line 1204). - Focus ring uses outline (not box-shadow post migration, line 147 CSS). Flush offset (0) survives forced-colors.