Primer componente F1 con comportamiento real (soma), y el que desbloquea el
block site-header (F2.1). Construido tras un fan-out de investigación (6
lectores) que fijó el mapa: template = FeedSentinelProvider, motor =
IntersectionObserver por el port bendecido de $adom, escritura de attrs por
syncAttrs (nunca dom.apply crudo). Alcance E-2 = suelo del dossier §P3.
- morfo: 2 partes (provider=box → data-sticky/data-edge/data-stuck ·
sentinel aria-hidden → data-edge); 0 eventos con justificación de COMPLEX
BEHAVIOR (apg: none); data-stuck presente/ausente + data-edge enum
espejan @container scroll-state(stuck: top/bottom) — este componente es el
polyfill cross-browser de ese contrato CSS futuro
- soma: un StickyProvider registra AMBAS partes en un runtime; el observer
vive en un $effect que RETORNA observeIntersection(...) como teardown
(mirror de feed); el callback async voltea stuck=$state; rootMargin
DERIVADO del offset (la línea de disparo del centinela ES la línea de pin
— acoplamiento matemático, offset obligatorio); root=scroll-host
(default viewport), Document coercionado a null; offset viaja como
--_sticky-offset (dato A8, no CSS visual — precedente meter)
- eidos: recipe fino que SOLO posiciona (position:sticky + inset lógico
desde --_sticky-offset + token --sticky-z-index + centinela layout-neutral
2px con margen negativo); el tratamiento del estado pegado es del
consumidor ([data-sticky][data-stuck]) — el recipe posiciona, no decora
- centinela = HERMANO de flujo del box (dos nodos raíz), no hijo (un hijo se
fija con el box y nunca detecta); orden según edge
- demo v2 9 tabs con scroll container real + readout de stuck vivo; READMEs
soma + eidos (Comparativa AntD/Mantine/Chrome-technique/headless/CSS ·
Decisiones · Passive justification · Gaps con disposición)
Verificación: component:audit PASS 0E/0W · eidos-lint 6 morfo-backed/0
invalid ([data-stuck] sin regla = intencional, consumidor decora) ·
morfo:check limpio · svelte-check sin regresión propia · 5 tests: 4 unit
(rootMargin por borde, root null-coerce, flip de stuck, disabled, cleanup) +
1 REAL-IntersectionObserver en chromium (foreground: no-stuck→scroll→
stuck→scroll-back→no-stuck — prueba end-to-end de la geometría offset↔
rootMargin, lo que el pane suspendido no puede). Navegador: box pinea a los
12px del offset, recipe correcto.
Decisión declarada (test harness): sticky-provider.svelte.test.ts usa el
installSomaHarness compartido (translator identidad) como los otros 86 tests
de provider — TÉCNICAMENTE en tensión con la regla CLAUDE.md «never fake
translators; use createActiveUix». Son unit tests del provider; la
integración real la cubren contracts.test.ts + la verificación en navegador.
Seguido el precedente universal; flaggeado para tu ratificación.
Nota: nav sidebar de sticky (web/routes/uix/+layout@.svelte) fuera del commit
— el archivo arrastra un flip CRLF de sesión paralela (2125 líneas de ruido);
la entrada viaja en el árbol de trabajo. Registros langs/soma de sticky
reconstruidos sticky-only (los índices tenían entangle con aura sin commitear).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>