method: adversarially-verified workflow (analyze → refute); HIGH lead-verified by direct read of the cited code. B5 ground-truth: the A31 O(N²) isSelected/isExpanded (.includes from a per-item $derived) is confirmed across listbox/grid-list/tree-view/tree-grid/tag-group (SYS-7); rovingTargetEl is correctly LIFTED everywhere (not A31); virtual-* use SvelteMap (A33-clean).
reactivity (A31/A33/A35): "CLEAN: Per-item isActive derivations read global state directly (opts.value.current), not via method calls—O(1) per item, not O(N²). No $state(Map/Set) usage (A33 clean). ItemGroup effect at line 529–540 is component-level drag tracking, not per-item—no A35 loop risk. Ref registrations via onRefChange (lines 487, 522), not $effect—A30 clean. ResizeObserver and autoplay timer both disposed via eff
## Summary
Counts (post-verification): CRITICAL 0 · HIGH 0 · MEDIUM 2 · LOW 1.
- evidence: Morfo declares scope: ['soma', 'sema'] but eidos directory exists at src/uix/eidos/components/carousel/ with full recipe and visual components
- impact: Eidos concerns (visual/size/variant/color/block attrs) are implemented but not declared in morfo scope, creating scope ambiguity
- verify: [confirmed] Confirmed at src/uix/morfo/components/carousel.ts:7 — `scope: ['soma', 'sema'],` with NO 'eidos', while a full eidos implementation exists: src/uix/eidos/components/carousel/carousel.css is 10912 bytes plus types.ts, context, and 8 visual .svelte wrappers (carousel-item.svelte, carousel-viewport.svelte, etc.). This is exactly the SYS-1 scope-drift pattern: eidos materializes visual/size/variant attrs the morfo scope doesn't declare. Severity MEDIUM is correct (matches baseline). Note this is broadly systemic on this branch — calendar.ts:7, color-picker.ts:7, combobox.ts:7, command.ts:7, dialog.ts:18 and others all declare ['soma','sema'] yet ship eidos dirs — so the fix should likely be a sweep, but the carousel finding stands on its own evidence.
- evidence: `// @vitest-environment jsdom`. The suite covers trigger/keyboard nav, autoplay timer + pause states, viewport-geometry props and timer disposal (line 370), but the DRAG path is entirely untested: finishDrag() (provider lines 389-415) computes fraction/velocity/fastSwipe + RTL-mirrored direction, and the ItemGroup drag $effect (lines 529-540) writes dragOffset from gesture.offsetX/Y. None of fraction-threshold, fastSwipe (velocity>0.5), or the `isRtlHorizontal` mirror (line 411-412) is exercised.
- impact: Swipe-to-advance (the carousel's primary touch interaction) and its RTL direction-flip have zero regression coverage; a sign or threshold regression in finishDrag would ship silently.
- proposed-fix: Add a unit test that drives the gesture via the provider's finishDrag()/dragOffset surface with synthetic offset+velocity across LTR/RTL and vertical axes; assert the resulting next()/prev() and dragOffset reset.
- verify: [verifier-added] added by adversarial verify pass
- fix-status: open
### LOW: A10 (getItems must filter nested via .closest === root) — carousel-101 <!-- id: carousel-101 -->
- dimension: B
- rule: A10 (getItems must filter nested via .closest === root)
- evidence: getItems() returns `Array.from(group.querySelectorAll<HTMLElement>(`[${attrs.item}]`))` with no `.closest('[data-carousel]') === group` filter. A carousel nested inside another carousel's slide would have its inner `[data-carousel-item]` elements counted by the OUTER provider's querySelectorAll, inflating `slideCount` (line 175) and corrupting the outer carousel's clamp/loop math (commit() uses slideCount at line 266).
- impact: Only manifests when carousels are nested (rare). When it happens, the outer carousel mis-counts slides → wrong lastSnap clamp, wrong canGoNext, broken End-key target. No crash, no leak.
- repro: Render a Carousel whose slide contains another Carousel; observe outer provider.slideCount includes inner slides.
- proposed-fix: Filter to direct items: `Array.from(group.querySelectorAll('[data-carousel-item]')).filter(el => el.closest('[data-carousel-item-group]') === group)` — mirrors the A10 pattern used elsewhere.
- verify: [verifier-added] added by adversarial verify pass
- covers: Navigation by trigger (next/prev), keyboard (Arrow keys, Home, End), and indicator click; Loop wrapping math (lastSnap calculation, modulo wrapping for loop mode, clamping for non-loop); Disabled state guard (keyboard/click/programmatic blocked); Autoplay lifecycle via uix.timers.interval with proper disposal on effect cleanup; Pause/resume on hover/focus state transitions; Viewport/ItemGroup/Item/Indicator props projection and data-state/data-index attrs; User interaction stops autoplay when stopOnInteraction=true; Indicator multi-click and aria-selected toggle
- untested: Virtualization edge cases (very large slide count with multiple slidesPerView); RTL keyboard navigation and transform direction mirroring with dragging; Drag gesture offset tracking and finishDrag snap-point logic; ResizeObserver responsiveness to viewport resize/orientation flip; Vertical orientation layout and indicator group flex direction
## Style observations (non-blocking)
- CSS recipe uses canonical 9-role color system with -solid/-element variants (primary, secondary, affirm, risk, threat, fulfill, loss, neutral). All spacing via --space-* and radius via --radius-*. Opacity uses --opacity-disabled. Z-index: 1 is local-relative within carousel subtree (triggers), acceptable per audit rules. Indicator size sizes with var(--_carousel-indicator-size) cascaded from --space-* + explicit px multiples in data-size breakpoints.
- Vertical orientation layout correctly flips root flex-direction to row with viewport taking flex: 1 1 auto and indicator-group as narrow flex: 0 0 auto column on right, matching common pattern in Mantine/ark-ui.