You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/audit/components/timeline.md

4.9 KiB

Audit: timeline

audit-version: 1 audited-at: 2026-06-26 scope: soma, sema, eidos (per morfo line 39: scope: ['soma', 'sema', 'eidos']) method: adversarially-verified workflow; HIGH lead-verified. B7 ground-truth: Toolbar A35 + Form A36 incidents STAYED FIXED (untrack present); toast/clipboard/drag-drop use uix.timers (no A6 leak); button is clean (its archetype finding was inert — Spinner not runtime-registered); data-size/data-shape are eidos visual attrs (not contract violations). provider: src/uix/soma/components/timeline/timeline-provider.svelte.ts cleanup-audit (A6/A35/A36): CLEAN: Timeline provider and item provider have no timers (setTimeout/setInterval), no listeners (addEventListener, ResizeObserver, IntersectionObserver, MutationObserver, Gesture/pointer capture) to dispose. The emerge-reveal announce in TimelineItemProvider uses untrack() to avoid reactive depende

Summary

Counts (post-verification): CRITICAL 0 · HIGH 0 · MEDIUM 1 · LOW 0.

Findings

MEDIUM: High-risk paths must be tested (A35/A36 loops, live-region dispatch, gesture, timers, vali — timeline-001

  • dimension: F: Tests
  • rule: High-risk paths must be tested (A35/A36 loops, live-region dispatch, gesture, timers, validation, passive role values)
  • location: src/uix/soma/components/timeline/timeline-provider.svelte.test.ts
  • evidence: Tests cover status derivation, explicit status override, auto-indexing, and undefined status cases. Missing test for the emerge-reveal event (live feed / post-sequence announcement). The event is critical to the component's feed mode.
  • impact: The emerge-reveal event and live feed behavior are not validated by automated tests. Integration/e2e tests may cover this, but unit test for the post-render one-shot announcement when shouldEmerge=true is absent.
  • proposed-fix: Add a test case that verifies: (1) items in the initial render do NOT fire emerge-reveal (shouldEmerge=false), (2) items appended after the provider's $effect runs (ready=true) DO fire emerge-reveal one-shot, (3) the event resolves the item's intent prop correctly.
  • verify: [confirmed] CONFIRMED. timeline-provider.svelte.test.ts has 4 tests (lines 70, 114, 143, 165): status-from-active, explicit-status-override+intent, auto-index, and undefined-status. ALL construct the provider with live=false: timelineOpts default is live = false (line 44) and every call site passes false or omits it — timelineOpts(1, false, root) (79,121,148) and timelineOpts(null) (168). The emerge-reveal one-shot is gated by shouldEmerge = this.provider.live && this.provider.ready (provider line 142) and fired in the item $effect (lines 162-168): if (fired || !shouldEmerge) return; const el = opts.ref.current; if (!el) return; fired = true; untrack(() => void this.runtime.trigger('emerge-reveal', { fallbackTarget: el })). Because no test sets live=true, this entire branch — the component's ONLY semantic event and its central feed-mode behavior (morfo line 44-61, expression:'pack') — is never exercised. Maps to dimension F RISK list (live-region/feed dispatch). MEDIUM (missing test on a high-risk path), high confidence. Note on proposed fix: the untrack(trigger) correctly prevents an A35/A36 loop (refuted as a concern) and fired is a plain let not reactive state, so the test only needs to assert the trigger fires once for an appended item and stays silent for the initial batch / when live=false; intent resolution itself happens downstream in the sema cascade via the per-item runtime props.intent source (provider line 149), so assert the trigger/target rather than intent value directly.
  • fix-status: open

No-findings dimensions

A: Contract (morfo), B: Behavior (soma), C: DOM-selector, D: Frontier, E: TSC/theming, G: Redundancy

Theming facts (E-bis)

  • magic z-index: none
  • magic literals: 1em (font-size on Title/Description — inheriting from parent, acceptable pattern) | 50% / -50% (horizontal align=alternate centering — layout-specific, acceptable)
  • undeclared parts: none
  • roles clean: true · variants clean: true

Tests (F)

  • exists: true · env: jsdom / vitest
  • covers: status derivation from active index; explicit status override; auto-indexing by registration order; undefined status when active=null; intent prop projection; data-timeline and data-timeline-item marker emission; aria-current conditional on current status
  • untested: emerge-reveal event firing in live feed mode; one-shot behavior (should not re-fire); post-sequence timing (item attached before event); shouldEmerge=false in initial render; shouldEmerge=true on append after provider ready

Style observations (non-blocking)

  • The z-index:1 on [data-timeline-marker] is a local stacking context to layer the marker above the connector line — acceptable and well-commented.
  • The 50% / -50% transform centering in horizontal align=alternate is layout-specific and acceptable (not a magic value for spacing/sizing).

Powered by TurnKey Linux.