# Audit: time-field audit-version: 1 audited-at: 2026-06-26 scope: (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: src/uix/soma/components/time-field/time-field-provider.svelte.ts field-family (A13/A24-26/A30): { "A13_hidden_input": "Hidden input correctly carries name (from Input provider) and ISO value. Renders only when name is set. CORRECT.", "A24_readonly_without_value": "Readonly-without-value warning implemented via $effect (lines 233-247). Guards against spam with lastWarnedKey. CORRECT.", "A26_segmented_contenteditable": "onbeforeinput preventDefault present in sharedSegmentAttrs (line 334 ## Summary Counts (post-verification): CRITICAL 0 · HIGH 0 · MEDIUM 2 · LOW 1. ## Findings ### MEDIUM: A30: child->parent id registration (inputId) must be DIRECT assignment in constructor, NEV — time-field-001 - dimension: B - rule: A30: child->parent id registration (inputId) must be DIRECT assignment in constructor, NEVER $effect - location: src/uix/soma/components/time-field/time-field-provider.svelte.ts:531-535 - evidence: $effect(() => { const field = this.provider.field; if (!field) return; field.inputId.current = opts.id.current; }); - impact: $effect child->parent edge can loop when InputProvider reads from Time-field state and writes to parent Field state, causing page freeze on mount if Field's reactivity depends on inputId changes. - proposed-fix: Move the inputId assignment to the constructor, directly after line 524 (this.provider.setFieldNode). Use: if (this.provider.field) { this.provider.field.inputId.current = opts.id.current; } - verify: [downgraded] The write IS in a $effect — confirmed at time-field-provider.svelte.ts:531-535: `$effect(() => { const field = this.provider.field; if (!field) return; field.inputId.current = opts.id.current; })`. But the HIGH/page-freeze claim is NOT supported. (1) NO loop exists: grep shows `field.inputId` is ONLY written (line 534), never read by this Input provider; `opts.id.current` is a stable framework id, so the $effect cannot oscillate. The A30 freeze hazard needs a child->parent write feeding parent reactivity the child re-reads — that closed cycle is absent. (2) Systemic, not a time-field defect: date-field-provider.svelte.ts:932-936 and color-field-provider.svelte.ts:521-525 use the IDENTICAL $effect pattern. (3) Real but minor: the project's REFERENCE number-field-provider.svelte.ts:585-587 uses a plain constructor guard `if (this.provider.field) { this.provider.field.inputId.current = opts.id.current; }`, so direct constructor assignment IS the cleaner doctrine and the proposed fix is correct. Downgraded to MEDIUM — A30 doctrinal deviation (prefer direct assignment), no freeze. - fix-status: open ### MEDIUM: SYS-1: eidos recipe directory exists but morfo 'scope' omits 'eidos' SCOPE-DRIFT — time-field-002 - dimension: A - rule: SYS-1: eidos recipe directory exists but morfo 'scope' omits 'eidos' SCOPE-DRIFT - location: src/uix/morfo/components/time-field.ts:7 - evidence: scope: ['soma', 'sema'] — but src/uix/eidos/components/time-field/ directory exists with CSS and components - impact: Scope declaration is incomplete. The eidos layer provides visual recipes, but morfo declares scope without 'eidos', causing contract validators to miss eidos-layer violations. - proposed-fix: Update line 7 to: scope: ['soma', 'sema', 'eidos'], - verify: [confirmed] Confirmed. time-field.ts:7 declares `scope: ['soma', 'sema']` — omits 'eidos'. The eidos layer exists in full: Glob of src/uix/eidos/components/time-field/ returns time-field.css, time-field.svelte, time-field-input.svelte, time-field-hidden-input.svelte, time-field-segment.svelte, time-field-label.svelte, types.ts, index.ts, README.md. Classic SYS-1 scope-drift; contract validators won't reach the eidos layer. Fix: add 'eidos' to the scope array. - fix-status: fixed (212624e0) ### LOW: Morfo declares Label part defaultElement='label' but soma renders
— time-field-003 - dimension: A - rule: Morfo declares Label part defaultElement='label' but soma renders
- location: src/uix/soma/components/time-field/components/time-field-label.svelte:35 - evidence: Morfo line 152: defaultElement: 'label' | Soma line 35:
- impact: Contract element mismatch. Although functional (the div has onclick focus behavior), morfo specifies 'label' but soma deviates. The semantic