"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 <!-- id: time-field-001 -->
- dimension: B
- rule: A30: child->parent id registration (inputId) must be DIRECT assignment in constructor, NEVER $effect
- 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.
- 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.
- evidence: Morfo line 152: defaultElement: 'label' | Soma line 35: <div{...mergedProps}>
- impact: Contract element mismatch. Although functional (the div has onclick focus behavior), morfo specifies 'label' but soma deviates. The semantic <label> element is not used despite being declared.
- proposed-fix: Either: (1) Change morfo defaultElement to 'div' (since segmented input can't use <labelfor>) or (2) render <label> in soma and provide proper for/aria-labelledby wiring.
- verify: [downgraded] Element mismatch is real but lower impact than MEDIUM. Confirmed: morfo time-field.ts:152 declares Label `defaultElement: 'label'`; time-field-label.svelte:35 renders `<div {...mergedProps}>`. Systemic — date-field is identical (date-field.ts:136 `defaultElement: 'label'` vs date-field-label.svelte:35 `<div>`), and color-field is the consistent counter-example (color-field.ts:69 'label' + color-field-label.svelte:35 `<label>`). `defaultElement` is advisory and the part archetype is 'label'; a real `<label for>` cannot target a composite spinbutton group, so the `<div>` is an intentional a11y choice (it carries onclick focus). Downgraded to LOW — element naming/contract drift, not a behavioral or a11y break. The candidate's two proposed options are both valid.
- fix-status: open
## No-findings dimensions
C, D, E, E-bis, F, G
## 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?): Label font-size correctly one typographic step below input. CSS line 101: calc(1em - (var(--font-size-md) - var(--font-size-sm))) resolves to sm when input is md. CORRECT.
## Tests (F)
- exists: true · env: jsdom
- covers: validation (custom, min, max constraints); segment-fill commit logic (all segments required before value commits); 12-hour display sync (hour padding, dayPeriod conversion)
- untested: keyboard routes (ArrowUp/Down, Backspace, ArrowLeft/Right segment nav); readonly-without-value warning emit (A24 warning spam guard); Field composition inputId registration (A30); onbeforeinput preventDefault behavior (A26); hidden input form submission with name propagation (A13)