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/docs/process/PLAN-scene-ambient-pack.md

28 KiB

PLAN — Motor de escenas + pack Ambient + vía de promoción agéntica

Tipo: plan de ejecución por fases (process — efímero, no fuente de verdad). Fecha: 2026-07-11 · Estado: D1–D9 RESUELTAS · F0 ✅ + F1 ✅ + F2 ✅ + F3 ✅ + F4 ✅ + F4b ✅ (2026-07-12) — los 45 fondos aprobados (32 en el pack) migrados; queda F5 texto (plan separado, D9) y el visual píxel en pestaña visible. F4b: Tier B completo (16/16, D6) — galaxy · eter · hyperspeed · particles · pixel-blast · grid · prismatic · pillar · dither · blinds · balastro · iridiscence · liquid-metal · line-waves · floating-lines · letters. Mismo mecanismo que F4 (port verbatim + registro + chip); custom-pipeline reutilizado por 6 (particles gl.POINTS · dither 2-pases FBO · grid 2-pases+composite · eter fluidos 8-programas/7-FBOs half-float · pixel-blast cadena dither→liquid→noise · hyperspeed instancing+depth-FBO+bloom). Contrato completado con consumidores reales: glContext.dprCap (dither exige DPR 1 — look chunky del seed; engine toma el mín) · hooks P-5 simétricos onPointerLeave (floating-lines/galaxy/eter) y onPointerUp (hyperspeed press) · bug F1 cazado: el leave del engine recentraba nx/ny pero NO x/y (el hover de orb jamás decaía). Recortes declarados: gyro+snapBackDelay (grid, plataforma/chrome) · quality por navigator (pillar → high fijo; adaptación por dispositivo = futura opción del engine) · resolutionScale (veil, ya en F4) · mixBlendMode/paused/callbacks onSpeedUp (chrome del host/handle) · presets hyperspeed no exportados. Gates: packs:check 0/36 · engine 9/9 · scene+eidos 323/323 · check 0 propios · docs:check 0/0 · navegador: 32/32 efectos montan+compilan+linkan (prueba estructural canvas+data-scene; la escena interna de hyperspeed compila en su primer frame — cubierta por el pendiente visual). F4: Tier A completo (13/13, D6) — agénticos primero (silk · radar · threads · orb · waves · lumen) y después fog · grainient · veil · dots · beam · ray · snow-pixels. Cada efecto: port limpio a $scene/effects/{name}.ts (shader/física verbatim; iTime/iResolution→uTime/uResolution estándar; colores [0,1]→hex por P-4; booleans de interacción colapsados en hooks opt-in / mouseInfluence:0; reduce: 'static-frame' los 13) + módulo de registro en el pack + chip en el catálogo. Adaptaciones de ciudadanía declaradas: waves/dots pierden overlays de chrome del seed (cursor-dot / SVG-glow→dibujado en canvas) · dots cambia setInterval(20ms)→acumulador sobre api.time (P-3) · veil pierde resolutionScale (el buffer es del driver; si hace falta, opción de engine) · orb deriva el hover del puntero suavizado del engine (decae al salir sin hook de leave). Extensión de contrato justificada por beam (geometría 3D real, primera del tier): WebglSceneEffect.vertexShader?() + glContext.depth? + draw?() — el driver conserva contexto/loop/resize/uniforms/teardown y solo cede geometría+draw; Tier B (particles/hyperspeed/galaxy) la reutilizará. Fix F3 arrastrado: eidos.getMode() NO existía en ActiveEidos (error de check) → getThemeContext() (vía pública reactiva). Gates: packs:check 0/20 · engine 9/9 · check 0 errores en scene/packs · verificado en navegador: los 16 efectos (3 pilotos + 13 Tier A) montan/compilan/linkan y el remount en cascada no deja errores (canvas presente + data-scene correcto; un fallo de build habría hecho canvas.remove()) · README del pack lista el catálogo completo (cierre D6). El look visual píxel-a-píxel sigue pendiente de pestaña visible (limitación de entorno documentada). F3: src/packs/ambient (<Ambient effect> genérico con registro declaration-merging AmbientEffects · resolve-params.ts P-4 token→hex con drop-a-default · un engine por superficie DOM vía WeakMap para presupuesto global · re-tintado enganchado a eidos.getMode()) · módulos effects/{mesh,aurora,dot-grid} (import = opt-in) · README con el contrato P · scripts/packs-check.ts + npm packs:check (P-3 APIs crudas · S-1 sin <style> · R-1 registro+augment) 0/7 verde · alias $packs (vite+svelte+CLAUDE.md) · demo catálogo web/routes/uix/packs/ambient · encapsulación probada (0 imports de $packs fuera de web/). Verificado en navegador: SSR+hidratación limpias, host/canvas/attrs correctos; bug real cazado en la pasada: prop effect + rune $effect = store_invalid_shape (renombrado local effectName). El PINTADO no fue verificable (pane oculto suspende rAF/RO — limitación de entorno documentada; la ruta RO→draw la cubren los 9 tests del engine): pendiente un vistazo visual en pestaña visible al retomar F4. F2: resolveToken extendido a slots semánticos --color-{role}-{slot} (parser con union slot, getEidosColorRoleSlotOverride en config.ts, DEFAULT_COLOR_ROLE_SLOT_STEPS exportado — misma fuente que el CSS emitido; EXCLUIDOS contrast (pick APCA) y familia surface (translúcida); 20/20 tests, incl. equivalencia slot↔primitive y override por rol) · 3 pilotos limpios en $scene/effects (mesh webgl1 · aurora webgl2 · dot-grid canvas2d + util color local; colores = hex concretos, la resolución de tokens es del CONSUMIDOR por P-4 — la capa arts no importa uix) · re-resolución al cambiar modo: getMode() confirmado; el cableado reactivo fino va con el componente del pack (F3). F0: motion-guide §8 revertido · docs/architecture/packs.md (tier + regla + contrato P + vía Aura) · fila E1 en README + glosario · docs:check 0 err. F1: src/arts/scene/ (types con puerto SceneDom + contrato SceneEffect con reduce obligatoria · engine con pausa-fuera-de-vista/DPR/presupuesto/context-loss · drivers webgl(+2)/canvas2d · README) · alias $scene (vite+svelte+CLAUDE.md) · fila en arts/README · 9/9 tests verdes · check 0 errores en scene · arts:check 0/0 en 23 arts. Origen: estudio de web/routes/demos/animations (45 efectos: 39 fondos + 6 texto, ~16.100 líneas, auto-contenidos) + decisión de arquitectura conversada: canon = superficie de contrato · pack = hoja decorativa; el indicador de agente (futuro Aura) SÍ es canon (materializa delegate+sustain), las landings son pack. Este plan prepara la fase de dirección agéntica sin construirla.


Reglas de gobierno de este plan (cumplimiento total)

Las cinco del usuario (2026-07-11), literales:

  1. NO INVENTES.
  2. Ante duda o falta de datos, re-analiza el problema desde todos los ángulos.
  3. Toda pregunta al usuario llega con todas las opciones analizadas en profundidad.
  4. Ninguna decisión que viole o cree inconsistencia en el ecosistema.
  5. Buscar siempre la solución que suponga un upgrade del ecosistema respetando su filosofía.

Y las del propio ecosistema que aplican aquí:

  • Docs-first: una decisión que contradiga doctrina vigente actualiza el doc canónico ANTES del código (aplica a motion-guide §8).
  • Guard con cada sistema nuevo: el contrato de pack nace con guard mecánico el día uno.
  • Nunca borrar sin instrucción explícita ("borra/elimina"): los borrados de F0 quedan gateados en D5.
  • Verificación por fase: cada fase declara su criterio verify y no se cierra sin él.
  • Pista independiente: este plan NO se entrelaza con la cola clean-room-fixes (F1+ de continue-cleanroom-fixes-2026-07.md); prioridad relativa la decide el usuario.

Datos verificados que anclan el plan (no inventados)

Dato Evidencia
45 efectos auto-contenidos (0 imports externos; solo svelte + relativos) grep de imports 2026-07-11
Sustratos: 11 WebGL2 · 16 WebGL1 standalone · 8 sobre base WebGLBackground · 4 canvas-2D (dot-grid, dots, letters, waves) · 6 texto DOM/CSS/WAAPI grep getContext por fichero
Ciudadanía: reduced-motion 9/45 · pausa-fuera-de-vista 26/45 · context-loss 0/45 · APIs crudas (rAF/RO/IO/matchMedia) 45/45 censo grep 2026-07-11
Las 4 copias de la base (fog≡glass-blocks≡glass-window≡liquid-image≡mesh; nebula/plasma/lumen divergidas) comparten firma idéntica (fragmentShader/setupUniforms/updateUniforms(t,dt)/onPointerMove/loc/uploadTexture, mismas líneas 158–186) → consolidación de bajo riesgo diff + grep de firmas
Contrato por-efecto embrionario ya existe background/mesh/Mesh.ts (params tipados + 3 métodos)
El mejor ciudadano actual (patrón a heredar) aurora.svelte: reduce (frame estático), IO-pause, RO, DPR cap 2, teardown con loseContext
ActiveDom ya expone todo lo que el motor necesita: requestFrame/cancelFrame, observeResize, observeIntersection, prefersReducedMotion, listen superficie confirmada (stub disabledDom en active-uix.svelte.ts:242-329 refleja la interfaz)
⚠️ eidos.resolveToken HOY solo resuelve --scale-{n}-{step} y --primitive-{role}-{step}; devuelve null para slots semánticos (--color-primary-solid) active-eidos.svelte.ts:485-517
Alias: const único aliases en vite.config.ts:11 (espejado a svelte.config.js); $scene libre grep
Precedente de factory: service-factories/motion.ts (defineEngineMotion) ls
ogl en package.json:60 con 0 imports en src+web auditoría 2026-07-10
Restos: bends copy.svelte + 4 test-*.html inventario
Doctrina a revertir conscientemente: motion-guide §8 declara los fondos WebGL no-goal ("a separate axis") docs/theming/motion-guide.md §8

Decisiones de usuario (gate de F0) — cada una con recomendación analizada

ID Decisión Opciones analizadas Recomendación
D1 Nombre del art del motor scene (genérico, sirve a fondos/agente/charts futuros) · scenic · ambient (se confunde con el pack) arts/scene, EngineScene/createEngineScene, alias $scene — espejo exacto del precedente motion
D2 Ubicación del tier pack (a) src/packs/ambient/ (estrato nuevo, sobre uix, documentado) · (b) src/uix/packs/ (dentro de uix — mancha la pureza de capas: el pack consume uix, no es capa) · (c) dentro de web (no es site-code) (a) src/packs/ + fila nueva en el mapa de estratos (docs/README.md) y en authoring.md
D3 Nombres de componentes Pack: <Ambient effect="…">. Futuro canónico: Aura (evita colisión con la capa soma Presence) Ambient / Aura — Aura queda solo como nombre RESERVADO documentado; no se construye en este plan
D4 Acceso al motor (a) uix.scene ya (toca superficie ActiveUix + contracts.ts + docs — invasivo antes de tener consumidor canónico) · (b) factory standalone ahora, promoción a uix.scene cuando llegue Aura (b) — mínima invasión = coherencia; la promoción queda declarada en la vía Aura
D5 Borrados F0 (requieren tu "borra" explícito) bends copy.svelte · 4 test-*.html · dep ogl de package.json Borrar los 3 grupos (la dep muerta contradice zero-dependence; los restos contaminan greps)
D6 Alcance Tier A del pack v1 (tras pilotos) Lista propuesta (sobrios/marca/agénticos): silk · fog · grainient · veil · threads · waves · dots · beam · ray · snow-pixels · radar · orb · lumen Aprobar lista o recortarla; Tier B (galaxy, hyperspeed, eter, pixel-blast, grid, particles, pillar, prismatic, balastro, blinds, dither, floating-lines, iridiscence, line-waves, liquid-metal, letters) queda para F4b sin fecha
D7 Destino de web/routes/demos/animations (a) conservar hasta paridad del pack y decidir entonces · (b) migrar la ruta a catálogo del pack ya (a) — nada se borra; la demo nueva del pack nace aparte y la vieja se retira cuando tú lo digas
D8 Efectos de imagen (distorsion, liquid-image, glass-blocks, glass-window) Son tratamientos de imagen (reciben src), no fondos FUERA de este plan — familia futura de efectos de Image, decisión aparte
D9 Los 6 de texto (a) fase F5 de este plan · (b) plan separado (b) plan separado — destinos heterogéneos (count→compone format; blur→dominio content de motion; gradient→eidos CSS+tokens; circular/focus/scrambled→eidos decorativos con endurecimiento SR). Mezclarlos aquí infla el alcance

Resoluciones del usuario (2026-07-12)

  • D1–D4 — ACEPTADAS las cuatro (arts/scene · src/packs/ambient · Ambient/Aura · factory standalone). Aclaración pedida y respondida: las animaciones de texto NO entran al pack Ambient — el pack es solo fondos decorativos (aria-hidden, sin contenido); las de texto envuelven contenido real (superficie a11y = superficie de contrato) y van a su plan separado (D9).
  • D5 — CAMBIADA: NO se borra nada. Literal del usuario: "debes de crearlos sano, lo que hay no debe de contaminar lo nuevo, de hecho se queda a modo presencial y comparativo, nada más". Consecuencias: la colección original (web/routes/demos/animations, incl. bends copy y test-*.html) queda intacta como referencia presencial/comparativa; la dependencia ogl también se queda por ahora; lo nuevo se construye LIMPIO en arts/scene + src/packs/ambient sin heredar los patrones contaminados (APIs crudas, base duplicada, hex sueltos). El punto F0.4 (higiene) queda anulado.
  • D6 — Tier A APROBADA tal cual (13 efectos; agénticos primero).
  • D7–D9 — CONFIRMADOS (demos intactas hasta paridad · imagen fuera · texto en plan separado).

Fases

F0 — Doctrina + higiene (gate: D1–D9 respondidas)

  1. Revertir el no-goal: editar docs/theming/motion-guide.md §8 — los fondos ambient dejan de ser no-goal y pasan a "pack Ambient sobre arts/scene" (docs-first).
  2. Escribir el tier pack donde corresponde: fila "packs" en la tabla de estratos de docs/README.md + docs/authoring.md; la regla de admisión queda escrita: canon = superficie de contrato consumida por otros (eventos/ARIA/comportamiento/tokens); pack = hoja decorativa parametrizada; dependencia SOLO pack→framework; borrar el pack no rompe nada.
  3. Declarar la vía de promoción agéntica (una sección en el mismo doc del tier): los efectos son recursos compartidos en $scene/effects; el consumo semántico llegará con la familia delegate+sustain (componente reservado Aura); mapeo orientativo estados→efectos (idle: mesh/fog/grainient · listening: orb/lumen · thinking: aurora/silk · acting/streaming: threads/waves · searching: radar · error puntual: ray como firma de evento).
  4. Higiene — ANULADO por D5 (2026-07-12): nada se borra; la colección original queda como referencia presencial/comparativa y ogl permanece en package.json. El mandato es construir lo nuevo limpio, no sanear lo viejo.
  • Verify: docs editados enlazan y npm run docs:check sin errores nuevos; npm run check intacto; git status solo con lo previsto.
  • No se hace: ningún código del motor; ningún borrado sin D5.

F1 — arts/scene (el motor)

  1. Crear src/arts/scene/ con:
    • types.ts — puerto estructural SceneDom (subconjunto: requestFrame/cancelFrame, observeResize, observeIntersection, prefersReducedMotion, listen; adom lo satisface — mismo patrón MotionDom) + contrato SceneEffect derivado del de Mesh.ts y del patrón aurora: { name, driver: 'webgl' | 'webgl2' | 'canvas2d', params tipados, reduce: 'static-frame' | 'hide' (OBLIGATORIA, sin default silencioso), pointer?: opt-in }; para webgl: fragmentShader/setupUniforms/updateUniforms(t,dt); para canvas2d: setup/draw(t,dt).
    • engine-scene.ts — createEngineScene({ dom, logger? }): mount(node, effect, params) → SceneHandle { setParams, pause, resume, dispose }. Responsabilidades únicas: bucle en dom.requestFrame con delta capado; pausa por observeIntersection + pestaña oculta; resize por observeResize + DPR cap configurable (default 2); reduced-motion vía dom.prefersReducedMotion aplicando la policy del efecto (frame estático = dibujar 1 vez, como aurora); webglcontextlost/restored (0/45 lo manejan hoy — upgrade real); presupuesto de escenas concurrentes con logger.warn al superarlo (los navegadores capan contextos GL); teardown completo (programa, buffers, observers, loseContext).
    • drivers/webgl.ts — consolidación de la base: partir de la copia idéntica ×5 (fog/WebGLBackground.ts), diff completo contra nebula/plasma/lumen para incorporar lo que sus variantes corrigieron (firmas idénticas ya verificadas; la divergencia es interna) + el patrón WebGL2 de aurora como capacidad del driver (el efecto declara driver).
    • drivers/canvas2d.ts — extraído de dot-grid/dots/letters/waves (mismo ciclo de vida, sin GL).
    • index.ts barrel + README.md (contrato, policy reduce, presupuesto, la vía Aura).
  2. Alias $scene en el const de vite.config.ts:11 + espejo en svelte.config.js.
  3. Fila en el mapa de src/arts/README.md.
  4. Tests (proyecto server): ciclo de vida con dom fake (mount→pause por IO→resume→dispose), policy reduce, context-loss, presupuesto.
  5. NO se crea defineEngineScene en service-factories todavía (D4b) — se anota en el README como parte de la promoción Aura.
  • Verify: npm run check 0 nuevos + npx vitest run src/arts/scene verde + npm run arts:check verde. Ningún efecto portado aún.

F2 — Recursos piloto + costura de tokens

  1. Extender eidos.resolveToken a slots semánticos (--color-{role}-{slot}): resolver rol+slot→step vía la misma fuente que el generador (DEFAULT_COLOR_ROLE_SLOT_STEPS, render-css.ts) respetando overrides de applyColorScheme (precedencia ya implementada para primitives). Es un upgrade coherente con su diseño (config + $color, cero DOM) y cierra la limitación verificada. Test en active-eidos.test.ts.
  2. Helper de color del motor: los params de color aceptan token CSS custom-property | color CSS crudo; resolución vía eidos.resolveToken cuando hay contexto eidos, passthrough si no (el pack funciona sin eidos, degradando a hex — encapsulación real).
  3. Re-resolución al cambiar modo/tema: verificar la superficie reactiva de ActiveEidos (el mecanismo con que applyColorScheme "sigue light/dark") y engancharse al MISMO; si no hay superficie pública, exponerla como parte de este trabajo (decisión técnica documentada en el momento, no inventada ahora).
  4. Portar los 3 pilotos que cubren los 3 sustratos, a src/arts/scene/effects/: mesh (webgl base, params ya tipados), aurora (webgl2, hereda su propia ciudadanía), dot-grid (canvas2d interactivo con pointer opt-in). Colores por defecto derivados de roles del tema (mesh: primary/secondary/tertiary/neutral).
  • Verify: test de resolveToken semántico; los 3 efectos montan/desmontan en un harness de test; reduce policy ejercitada; npm run check + suite eidos verdes (306/306 — el canario THM-3 ya volteado según memoria F0 clean-room).

F3 — Pack Ambient v1

  1. src/packs/ambient/ (D2): componente de montaje <Ambient effect="…" params={…}> — registro tipado por declaration-merging (interface AmbientEffects, patrón exacto EidosMotionPresets), tree-shaking por import de efecto; canvas aria-hidden="true"; pointer-events: none salvo efectos pointer opt-in; sin <style> scoped — clase/estilo passthrough estándar.
  2. Instancia el motor con el dom del contexto (ActiveEidos.require().dom cuando existe; puerto explícito por prop para uso fuera del árbol uix).
  3. Contrato P de una página (README del pack): reduce obligatoria · teardown por handle · DOM solo por puerto · colores token-aware · aria-hidden · presupuesto. Mini-guard scripts/packs-check.ts (+ npm script packs:check): efecto registrado sin reduce = error; grep de rAF/RO/IO crudos en src/packs/ = error.
  4. Demo catálogo única (una ruta nueva bajo web/routes, selector de efecto + params en vivo + toggle reduce/modo) — las demos viejas intactas (D7a).
  • Verify: packs:check verde; demo carga los 3 pilotos; cambio de modo re-tinta un efecto token-aware en vivo (verificación en navegador); borrar src/packs/ deja npm run check verde (prueba de encapsulación — en working tree, sin commitear).

F4 — Migración Tier A (D6)

Por cada efecto aprobado: extraer shader/lógica al contrato SceneEffect (queda ~⅓ del fichero original), declarar reduce, params color token-aware donde tenga sentido, registrar en AmbientEffects, añadir al catálogo demo. Orden sugerido: los agénticos primero (orb, lumen, radar, silk, threads, waves) — son los recursos que la fase Aura consumirá.

  • Verify por efecto: monta/pausa/reduce/teardown en el catálogo + packs:check verde. Cierre de fase: Tier A completo listado en el README del pack.

F4b — Tier B (sin fecha, mismo mecanismo). F5 — texto (plan separado, D9).

F6 — Cierre

  1. Actualizar memoria de proyecto + docs/process/ con el estado real.
  2. Verificación global: npm run check · npx vitest run src/arts/scene src/uix/eidos · packs:check · docs:check.
  3. Dejar escrito el arranque de la fase agéntica: Aura = componente canónico por la ruta de 9 fases, morfo con estados de ciclo de agente + eventos delegate/sustain + intent, pack sema con modulación por intent (velocidad/amplitud/hue = el análogo visual de pitch/gain/contour), consumo de $scene/effects, promoción del motor a uix.scene (D4). Nada de esto se construye en este plan.

Qué NO hace este plan (anti-scope-creep)

  • No construye Aura ni toca sema/morfo/soma.
  • No toca la cola clean-room-fixes ni la matriz de componentes (el pack no entra en component:audit).
  • No borra las demos actuales ni ningún fichero sin D5/D7.
  • No añade uix.scene a ActiveUix (D4).
  • No porta efectos de imagen (D8) ni texto (D9).

Powered by TurnKey Linux.