refactor(libs/logger): inline SILENT_LOGGER test fixture (audit SU2, partial)

libs/logger/test/diagnostics.test.ts no longer imports SILENT_LOGGER from the
consuming `$logger` art -- it uses a local no-op Logger fixture (the art exports
the identical shape). Removes one of the test-only layer inversions (SU2).

The prefs half of SU2 (libs/prefs/test importing dimension constructors from
$prefs) is left for a deliberate call: those constructors are pure (import only
$libs/prefs + $libs/locale), so the root fix is relocating them to $libs/prefs
with arts/prefs re-exporting -- an ~11-file move, disproportionate to force for a
BAJA, not-a-build-violation item.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
active-uix
dev 4 months ago
parent 0d66e5a4e7
commit 0b7757d027

@ -1,683 +0,0 @@
# Codex full audit - arquitectura y framework
Fecha: 2026-05-27
Repo: `G:\dev\svelte\vicen`
Rama observada: `active-uix`
## Veredicto ejecutivo
La arquitectura principal esta bien orientada: `ActiveApp` compone servicios,
`ActiveUix` actua como raiz UIX, `Morfo/Soma/Sema/Eidos` mantienen una
separacion reconocible, y las reglas de alias/runes estan bastante alineadas.
Hay buenas barreras: `arts` no importa `uix`, `active-uix` no importa Soma ni
Eidos, Soma no importa Eidos, y `active-app`/`active-uix` pasan sus suites
propias.
Pero el sistema no esta contractualmente sano todavia. El `npm test` global
falla por `Words`, hay drift real entre docs y codigo, Morfo importa Sema
aunque su README lo prohibe, algunos Eidos vuelven a exponer `Provider`
publicamente, y el reporte de componentes declara 34/107 componentes como
`NEEDS-WORK`. Ademas, la entrada documentada `$active-app/services` no coincide
con el alias real ni con el codigo vivo, lo que hace que la documentacion de
composicion sea peligrosa para consumidores.
## Alcance revisado
Documentacion y contratos revisados:
- `src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md`
- `src/docs/LIBRO_VARIACIONES_Y_EXTENSIONES.md`
- `src/uix/active_architecture.md`
- `src/uix/README.md`
- `src/uix/active-uix/README.md`
- `src/uix/morfo/README.md`
- `src/uix/sema/README.md`
- `src/uix/soma/README.md`
- `src/uix/soma/SOMA_ARCHITECTURE.md`
- `src/uix/soma/COMPONENT_GUIDE.md`
- `src/uix/eidos/README.md`
- `src/uix/eidos/components/README.md`
- `web/routes/uix/lib/COMPONENT_AUDIT_GUIDE.md`
- `web/routes/uix/lib/DEMO_AUTHORING_GUIDE.md`
- README de `src/arts/*`, con foco especial en `src/arts/active-app`
- README de `src/libs/*` y `src/svrs/*` relevantes
- README de `Words` en Morfo/Soma/Sema/Eidos
Tambien se revisaron configs, import graph, tests y reportes generados.
## Comandos ejecutados
- `npm run test` - falla: 1 fichero fallido, 2 tests fallidos en
`src/uix/contracts.test.ts`.
- `npx vitest run src/uix/contracts.test.ts` - falla con las mismas 2
violaciones.
- `npx vitest run src/arts/active-app/test` - pasa: 8 ficheros, 54 tests.
- `npx vitest run src/uix/active-uix/active-uix.svelte.test.ts` - pasa:
1 fichero, 25 tests.
- `npm run check` - exit 0, pero con 24 warnings Svelte y errores de carga de
configs dentro de `tmp/lexical`.
- `npm run build` - exit 0, pero conserva warnings de Svelte/Vite.
- `npm run component:audit` - exit 0, 107 componentes: 73 PASS,
34 NEEDS-WORK, 0 BROKEN.
- `npm run translations:check` - exit 0: 218 refs, 76 catalogos,
0 errors, 0 warnings.
- `npm run morfo:vocabulary` - exit 0, pero 107 warnings de vocabulario y
9 eventos con nombre no canonico.
- Escaneos estaticos de imports entre `arts`, `active-app`, `active-uix`,
`morfo`, `soma`, `sema` y `eidos`.
## Hallazgos P0
### P0-1 - La suite global falla por drift contractual de Words
Evidencia:
- `src/uix/contracts.test.ts:537` falla en
`guards hardcoded Soma component data attrs with morfo contracts`.
- `src/uix/contracts.test.ts:548` falla en
`guards component translation namespaces as kebab-case`.
- Atributos Soma no declarados en Morfo:
- `src/uix/soma/components/words/engine/render.ts`:
`data-words-find-match`, `data-words-find-active`, `data-words-indent`
- `src/uix/soma/components/words/engine/serialize-html.ts`:
`data-language`
- `src/uix/soma/components/words/words-provider.svelte.ts`:
`data-words-heading-picker`, `data-words-toolbar-family`,
`data-words-toolbar-family-panel`, `data-words-code-language-picker`,
`data-words-code-language-panel`
- Claves i18n no kebab-case:
- `components.words.bubbleMenu`
- `components.words.slashMenu`
- `components.words.linkEditor`
- `components.words.findReplace`
- Las rutas aparecen en `src/uix/morfo/components/words.ts:14-17`,
`:390`, `:413`, `:476`, `:498`, y en
`src/uix/soma/components/words/words-provider.svelte.ts:1715`,
`:1804`, `:2075`, `:2178`.
Impacto:
Morfo deja de ser la fuente de verdad para el DOM y para las rutas de texto.
Eso rompe el modelo declarado en `src/uix/README.md`: Morfo declara,
Soma transcribe, Sema proyecta, Eidos lee. Tambien bloquea CI porque
`npm run test` queda rojo.
Recomendacion:
1. Declarar esos `data-*` en `src/uix/morfo/components/words.ts` si son parte
publica estable, o retirarlos/renombrarlos en Soma si son internos.
2. Normalizar las rutas i18n a kebab-case, por ejemplo
`components.words.bubble-menu`, y sincronizar catalogos.
3. Revisar el README de Words: hoy afirma que esas claves fueron normalizadas
a camelCase, pero el contrato actual exige kebab-case.
## Hallazgos P1
### P1-1 - Morfo importa Sema aunque su contrato lo prohibe
Evidencia:
- `src/uix/morfo/README.md:824` dice que Morfo es TypeScript declarativo puro,
sin imports de `$uix/sema`, `$adom` ni `$libs/reactive`.
- Imports reales:
- `src/uix/morfo/compile.ts:48-49` importa `../sema/durations` y
`../sema/types`.
- `src/uix/morfo/types.ts:39-41` importa `../sema/types`,
`../sema/channels` y `../sema/durations`.
- `src/uix/morfo/selectors.ts:34` importa `../sema/types`.
- `src/uix/morfo/schema.ts:31-33` importa `$sium`.
Impacto:
La capa declarativa queda acoplada a la capa perceptiva. Si Sema cambia sus
tipos/canales/duraciones, Morfo cambia con ella. Eso invierte parte del flujo
arquitectonico: Morfo deberia declarar el lenguaje que Sema consume, no
depender de Sema para poder describirlo.
Recomendacion:
Mover los tipos compartidos a un contrato neutro, por ejemplo
`src/uix/contracts` o un submodulo `morfo/semantic-contracts.ts`. Sema puede
implementar esos contratos, pero Morfo no deberia importar desde Sema.
Revisar si `$sium` se acepta como validador puro o si el README debe afinar
la regla.
### P1-2 - Eidos vuelve a exponer `Provider` publicamente en 6 componentes
Evidencia:
- `src/uix/eidos/components/README.md:21-27` prohibe
`<X.Provider>` y `Provider` publico.
- `src/uix/eidos/components/README.md:40` exige asignacion explicita,
no `Object.assign`.
- Violaciones:
- `src/uix/eidos/components/announce/index.ts:12`
- `src/uix/eidos/components/clipboard/index.ts:13`
- `src/uix/eidos/components/feed/index.ts:19`
- `src/uix/eidos/components/drag-drop/index.ts:15`
- `src/uix/eidos/components/tree-grid/index.ts:53`
- `src/uix/eidos/components/tree-view/index.ts:53`
Impacto:
La API publica vuelve a tener dos formas mentales: root visual y Provider.
Eso contradice la "disciplined option C" y perpetua el split retirado
`flat vs Provider compound`.
Recomendacion:
Eliminar `.Provider` de los namespaces publicos. El root visual debe ser el
provider visual si corresponde, y las partes adjuntas deben ser solo las
partes publicas esperadas (`Trigger`, `Content`, `Item`, etc.).
### P1-3 - La entrada documentada `$active-app/services` no coincide con el codigo
Evidencia:
- `src/arts/active-app/README.md:57` documenta `$active-app/services` como
path de service factories.
- `src/arts/active-app/index.ts:8` repite esa promesa.
- `src/arts/active-app/README.md:106-107` dice que
`service-factories/` se exporta desde `$active-app/services`.
- Config real:
- `svelte.config.js:19` y `vite.config.ts:13` solo definen
`$active-app -> src/arts/active-app`.
- Por tanto `$active-app/services` resuelve a
`src/arts/active-app/services.ts`, que es el contrato de schema, no las
fabricas.
- Codigo vivo:
- `src/uix/active-uix/services.ts:24` importa desde
`$active-app/service-factories`.
- `src/arts/README.md:148` tambien usa `$active-app/service-factories`.
- Prueba directa:
- Importar `defineActiveLangs` desde `./src/arts/active-app/services.ts`
lanza `SyntaxError: ... does not provide an export named
'defineActiveLangs'`.
Impacto:
La documentacion guia al consumidor a un import path que no funciona. Es una
violacion fuerte de API publica, aunque no rompe build porque muchos ejemplos
estan dentro de strings de documentacion.
Recomendacion:
Elegir una sola direccion:
- O se corrige toda la doc a `$active-app/service-factories`.
- O se crea un alias real y estable `$active-app/services` hacia
`src/arts/active-app/service-factories`, y se mueve el contrato actual
`services.ts` a otro nombre (`schema.ts`, `contracts.ts`, etc.).
Despues, anadir un test que compile los snippets publicos o al menos valide
los import paths documentados.
### P1-4 - 34 de 107 componentes quedan en NEEDS-WORK
Evidencia:
`npm run component:audit` genero `tmp/component-audit.md`:
- Total: 107 componentes.
- PASS: 73.
- NEEDS-WORK: 34.
- BROKEN: 0.
Componentes `NEEDS-WORK`:
`alert-dialog`, `announce`, `avatar-group`, `badge`, `button`, `card`,
`clipboard`, `command`, `drag-drop`, `feed`, `format-date`, `format-number`,
`grid-list`, `image`, `link-preview`, `listbox`, `menubar`,
`navigation-menu`, `password-field`, `range-calendar`, `relative-time`,
`s-text`, `s-text-virtual-list`, `search-field`, `skeleton`, `spinner`,
`table`, `textarea`, `time-range-field`, `trans`, `tree-grid`, `tree-view`,
`virtual-grid`, `virtual-list`.
Ejemplos de errores:
- `alert-dialog`: falta selector root `[data-alert-dialog]`.
- Muchos Eidos: falta `README.md`.
- Varios interactivos: falta `:focus-visible`.
- Varias demos: falta `somaSnippet`.
- `table`, `textarea`, `tree-grid`: referencias a `--color-*` no declaradas.
- Interactivos sin URL APG declarada.
Impacto:
El framework no esta en estado de completitud auditada. La auditoria automatica
no marca `BROKEN`, pero `NEEDS-WORK` en 34 componentes es suficiente para
considerar incompleta la implementacion de la arquitectura de componentes.
Recomendacion:
Convertir el reporte en backlog cerrado por severidad: primero selectores
root/contrato DOM, luego foco/a11y, luego snippets/demo, luego READMEs. Si el
estado esperado del repo es "todo auditado", hacer que `component:audit` falle
cuando haya `NEEDS-WORK`.
### P1-5 - Drift doctrinal entre docs: 7 familias vs 8 familias Sema
Evidencia:
- `src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md:15`: "7 familias. Sin
excepciones."
- `src/uix/active_architecture.md:329`: enumera 7 familias.
- `src/docs/LIBRO_VARIACIONES_Y_EXTENSIONES.md:673`: dice 8 familias,
incluyendo `delegate`.
- `src/uix/sema/README.md:576` y `:636-638` documentan `delegate`.
Impacto:
Los autores de componentes no tienen una fuente unica para saber si
`delegate` es canonico o extension experimental. Esto afecta Morfo,
validadores, `morfo:vocabulary`, packs Sema y naming de eventos.
Recomendacion:
Consolidar la doctrina: si `delegate` es vigente, actualizar la guia base y
`active_architecture`. Si es extension, marcarlo como extension con gating y
validacion explicita.
### P1-6 - `npm run check` sale verde con ruido que deberia limpiarse
Evidencia:
`npm run check` devuelve exit 0, pero reporta:
- 24 warnings Svelte en 7 ficheros.
- Warnings a11y por elementos con handlers de puntero sin rol.
- Variables enlazadas que se actualizan sin `$state(...)`.
- `href="#"` invalido en demo de `navigation-menu`.
- `table` demo captura solo valores iniciales de `selectionMode` y
`multiSort`.
- `trans` demo tiene cierre implicito de `<span>`.
- Errores de carga de config dentro de `tmp/lexical` por dependencias no
instaladas (`svelte-preprocess`, `@sveltejs/adapter-auto`).
Impacto:
La senal de `check` queda degradada: el comando dice "0 errors", pero imprime
errores de carga externos y warnings que apuntan a bugs reales de demo.
Recomendacion:
Mover `tmp/lexical` fuera del workspace escaneado o configurar exclusion real
para svelte-check. Corregir warnings de rutas UIX y demos. Para CI, definir si
warnings Svelte deben fallar.
### P1-7 - Documentacion de estado obsoleta en `active_architecture`
Evidencia:
`src/uix/active_architecture.md` contiene un "Estado actual (2026-05-17)" que
presenta partes como pendientes o cerradas con conteos historicos, mientras
`src/docs/LIBRO_VARIACIONES_Y_EXTENSIONES.md` documenta cambios posteriores
del 2026-05-27: persistencia, `a11ySemantic`, familias permitidas y patrones
polimorficos.
Impacto:
El documento que deberia orientar la arquitectura activa mezcla estado antiguo
con reglas vigentes. Esto multiplica decisiones contradictorias en capas
sensibles como Sema y Eidos.
Recomendacion:
Separar "historial" de "contrato vigente". El contrato vigente debe decir en
una pagina corta que docs son canonicos y cuales son libro/historia.
## Hallazgos P2
### P2-1 - `morfo:vocabulary` produce demasiado warning estructural
Evidencia:
`npm run morfo:vocabulary` reporta:
- 107 warnings de enums `data-*` divergentes.
- 9 eventos de `words` que no siguen la forma `{family}-{verb}[-{variant}]`:
`words.commit-content`, `words.commit-format`, `words.commit-link`,
`words.commit-unlink`, `words.commit-slash-command`, `words.commit-check`,
`words.commit-history`, `words.commit-clear`,
`words.signal-invalid-input`.
Impacto:
El comando no distingue bien entre vocabularios legitimamente nuevos y drift
real. Al ser solo warning, se acumula ruido y el contrato pierde capacidad de
bloquear regresiones.
Recomendacion:
Promover vocabularios recurrentes a `CANONICAL_VOCABULARIES` o marcarlos como
extension aceptada con razon. Separar warnings esperados de violaciones reales.
### P2-2 - `arts` tiene excepciones de dependencia que contradicen la regla amplia
Evidencia de import graph productivo entre artes, excluyendo `active-app`:
- `src/arts/auth/client.ts -> $http`
- `src/arts/bus/engine-bus.ts -> $logger`
- `src/arts/perm/types.ts -> $http`
- `src/arts/prefs/dom-projection.ts -> $adom`
- `src/arts/session/bus-helpers.ts -> $bus`
- `src/arts/session/http-integration.ts -> $http`
- `src/arts/session/types.ts -> $storage`
- `src/arts/sium/engine-resolver.ts -> $langs`
- `src/arts/sium/engine-sium.ts -> $langs`
Muchas estan documentadas y parecen intencionales. El problema es que
`src/arts/active-app/README.md` formula una regla mas dura: los arts no deben
conocer sibling arts; ese conocimiento pertenece a `active-app`.
Impacto:
La arquitectura real ya tiene una lista de excepciones. Si no se formalizan,
las futuras dependencias cruzadas se justificaran por precedente.
Recomendacion:
Crear una matriz permitida de dependencias entre arts. Diferenciar:
- Contratos puros aceptados (`$libs/*`).
- Infraestructuras core aceptadas (`$logger`, `$bus`, `$timer`).
- Bridges opcionales aceptados (`prefs/dom-projection -> adom`).
- Dependencias prohibidas.
### P2-3 - `active-app/service-builder.ts` importa Svelte en un `.ts`
Evidencia:
`src/arts/active-app/service-builder.ts` importa `untrack` desde `svelte`.
El comentario explica que se usa para construir lazy services dentro de scopes
reactivos sin capturar mutaciones.
Impacto:
Probablemente es una decision practica correcta, pero hace que el core builder
de `active-app` tenga dependencia Svelte aunque no sea `.svelte.ts`. Si la meta
es que solo `Active*` reactivos carguen Svelte, esto debe documentarse como
excepcion.
Recomendacion:
Mantener si es necesario, pero documentarlo en `active-app` como parte del
contrato del builder. Alternativa: aislar el `untrack` en un adaptador Svelte
inyectable si se quiere preservar un builder completamente puro.
### P2-4 - `src/arts/README.md` promete `sideEffects`, pero `package.json` no lo tiene
Evidencia:
- `src/arts/README.md:267` dice que `package.json` declara
`"sideEffects": ["**/*.css", "**/*.svelte"]`.
- `package.json` no contiene `sideEffects`.
Impacto:
La politica de tree-shaking y preservacion de CSS/Svelte no esta codificada.
En un paquete privado puede no doler hoy, pero contradice el documento de
bundle policy.
Recomendacion:
Anadir el campo si la politica sigue vigente, o retirar/ajustar la regla del
README.
### P2-5 - Documentacion stale en `format/currency`
Evidencia:
`src/arts/format/currency/README.md` usa `$formats/currency` y describe
`src/arts/formats/currency/`, pero el alias real es `$format` y la ruta real
es `src/arts/format/currency`.
Impacto:
Consumidores que copien esos snippets importaran desde un alias inexistente.
Recomendacion:
Corregir el README y anadir un chequeo simple de aliases en snippets de
documentacion publica.
### P2-6 - Build pasa, pero hay senales de bundle/ruido a vigilar
Evidencia:
`npm run build` pasa, pero:
- Repite warnings de Svelte/Vite ya vistos en `check`.
- Un asset CSS de cliente aparece alrededor de 824 kB sin gzip.
- Rollup avisa que un comentario `/* @__PURE__ */` en
`src/uix/soma/components/command/command-provider.svelte.ts` esta en una
posicion que no puede interpretar y sera removido.
Impacto:
No bloquea, pero indica que el build no esta limpio y que faltan budgets o
umbrales para assets grandes.
Recomendacion:
Registrar budgets de bundle y limpiar warnings del build. Revisar el origen
del CSS grande y el comentario pure en `command-provider`.
### P2-7 - Demos UIX contienen bugs de reactividad/a11y
Evidencia:
`npm run check` y `npm run build` reportan:
- `web/routes/uix/components/navigation-menu/+page.svelte`: enlaces
`href="#"`.
- `web/routes/uix/components/table/+page.svelte:104`: `selectionMode` y
`multiSort` capturados solo al inicializar.
- `web/routes/uix/components/trans/+page.svelte:375`: cierre implicito de
`span`.
- Rutas de demo genericas en `web/routes/demos/*.svelte`: handlers de puntero
sin rol y refs no reactivas.
Impacto:
Aunque sean demos, son la superficie de validacion del framework. Bugs ahi
pueden ocultar errores del componente o ensenar patrones incorrectos.
Recomendacion:
Limpiar las demos antes de usarlas como material de contrato o referencia.
## Hallazgos P3
### P3-1 - Muchos README de Eidos faltan por componente
El reporte de componentes y el inventario indican que varios directorios
Eidos no tienen `README.md`: `announce`, `badge`, `button`, `card`,
`clipboard`, `command`, `drag-drop`, `feed`, `grid-list`, `image`,
`link-preview`, `listbox`, `menubar`, `navigation-menu`, `password-field`,
`range-calendar`, `s-text`, `s-text-virtual-list`, `skeleton`, `spinner`,
`table`, `textarea`, `time-range-field`, `tree-grid`, `tree-view`,
`virtual-grid`, `virtual-list`, entre otros.
Impacto:
Reduce trazabilidad por modulo, especialmente porque el usuario pidio auditar
README por modulo y porque la guia de componente exige documentar contrato,
comparativa y decisiones.
### P3-2 - AGENTS.md esta parcialmente viejo frente a aliases actuales
AGENTS.md menciona alias historicos (`@/ling`, `@/logr`, `@/glob`, `@/actx`)
como criticos, pero los configs actuales exponen sobre todo aliases de
`arts`, `libs`, `svrs` y `uix`. La instruccion general de mantener
`svelte.config.js` y `vite.config.ts` sincronizados si se cumple; lo viejo es
el inventario concreto.
Impacto:
Bajo para runtime, medio para agentes/humanos que usen AGENTS.md como mapa.
## Evaluacion por capas
### ActiveApp
Estado general: solido como composition root, con una deuda de API docs.
Lo que esta bien:
- Core: `logger`, `bus`, `timers`, `orca`, `prefs`.
- Servicios opt-in con schema y topological builder.
- Presets de orca separados.
- Dispose en orden razonable.
- Suite propia verde: 54 tests.
Riesgos:
- Path publico de service factories documentado como `$active-app/services`,
pero codigo real usa `$active-app/service-factories`.
- `service-builder.ts` depende de `svelte/untrack`; probablemente justificado,
pero debe declararse como excepcion de core.
- La regla "arts no conocen siblings" necesita matriz de excepciones.
### ActiveUix
Estado general: bueno y alineado con la intencion de asentarse sobre
`ActiveApp`.
Lo que esta bien:
- `createActiveUix(...)` standalone compone servicios locales.
- `attachActiveUix(app)` exige `langs` y `dom` y no compensa servicios
faltantes.
- No importa Soma ni Eidos.
- `defineUixServices(...)` crea la slice de servicios necesaria para
`ActiveApp`.
- Suite propia verde: 25 tests.
Riesgos:
- Depende del problema de naming de service factories en `active-app`.
- El contrato de `events` esta bien nombrado, pero la doctrina Sema aun esta
en drift.
### Arts
Estado general: arquitectura razonable, con excepciones de dependencia que
necesitan formalizacion.
Lo que esta bien:
- Import graph: `arts -> uix` es 0.
- Muchos modulos separan engine puro y active wrapper.
- `auth/session/perm/cache/http/storage` tienen docs de seguridad bastante
claras.
- `active-app` centraliza presets y composicion.
Riesgos:
- Algunas dependencias sibling son utiles pero no estan expresadas como matriz
permitida.
- Bundle policy de `sideEffects` no esta codificada.
- `format/currency` README tiene alias/ruta vieja.
### Morfo
Estado general: el concepto es correcto, la implementacion viola la pureza.
Lo que esta bien:
- Define contratos DOM/eventos/partes con bastante cobertura.
- `translations:check` esta verde.
- `semaSelector` existe y los packs Sema lo usan en general.
Riesgos:
- Importa tipos de Sema y `$sium`.
- `Words` tiene drift actual contra los tests de contrato.
- `morfo:vocabulary` produce demasiado ruido para ser una barrera fuerte.
### Soma
Estado general: el headless runtime mantiene buena separacion de Eidos, pero
Words se salio del contrato Morfo.
Lo que esta bien:
- No se detecto import de Eidos desde Soma.
- No se detecto import directo de `$libs/dom` desde Soma/Eidos; se usa `$adom`.
- Los tests globales pasan en casi todo salvo el contrato de Words.
Riesgos:
- Hardcoded `data-*` en Words no declarados en Morfo.
- Warnings en demos de Table apuntan a reactividad incorrecta.
### Sema
Estado general: potente, pero la doctrina no esta consolidada.
Lo que esta bien:
- Packs usan `semaSelector` en vez de selectores inventados.
- Visual/Sound/Haptic estan modelados como canales.
- `defineEngineSemantic` encaja con `ActiveUix.events`.
Riesgos:
- 7 vs 8 familias no resuelto.
- Warnings de nombres de eventos `Words`.
- Morfo depende de Sema para tipos.
### Eidos
Estado general: wrapper visual bien encaminado, pero con regresiones en API y
completitud.
Lo que esta bien:
- No se detecto `Object.assign`.
- No se detecto Eidos components importando `ActiveUix` directamente.
- `ActiveEidos` separa tema/modo/densidad de `prefs`.
Riesgos:
- 6 componentes exponen `.Provider`.
- 34 componentes NEEDS-WORK afectan Eidos/demos/contratos.
- Muchos README por componente faltan.
## Checks positivos importantes
- `svelte.config.js` y `vite.config.ts` tienen aliases sincronizados.
- Runes mode esta forzado por `dynamicCompileOptions`.
- `npm run build` pasa.
- `npm run check` no reporta errores TypeScript/Svelte fatales.
- `translations:check` pasa sin warnings.
- `active-app` y `active-uix` pasan tests focalizados.
- No hay `arts -> uix`.
- No se encontro `Soma -> Eidos`.
- No se encontro `Eidos components -> ActiveUix`.
- No se encontro `ActiveUix -> Soma/Eidos`.
- No se encontro `$libs/dom` directo desde Soma/Eidos.
## Orden recomendado de reparacion
1. Corregir `Words` hasta que `src/uix/contracts.test.ts` pase.
2. Resolver el path publico de service factories de `active-app`.
3. Sacar imports de Sema desde Morfo.
4. Eliminar `.Provider` publico en Eidos.
5. Cerrar los 34 `NEEDS-WORK` del component audit por prioridad.
6. Consolidar docs canonicas: familias Sema, estado actual, Words i18n,
`active-app` service path.
7. Limpiar `npm run check` y `npm run build` de warnings conocidos.
8. Formalizar matriz de dependencias permitidas entre `arts`.
9. Codificar `sideEffects` o retirar esa politica del README.
10. Anadir tests de snippets/import paths publicos para que la doc no pueda
prometer alias rotos.
## Cierre
La arquitectura no necesita una reescritura: necesita cerrar contratos. Las
piezas principales estan bien ubicadas, pero ahora mismo los tests y la
documentacion muestran que algunas capas estan adelantandose unas a otras.
El mayor riesgo no es que falte funcionalidad; es que el contrato escrito,
el contrato testeado y el codigo runtime no siempre son el mismo contrato.

@ -5,7 +5,18 @@ import {
type DiagnosticEvent,
type Logger
} from '../index.ts';
import { SILENT_LOGGER } from '$logger';
// Local no-op logger fixture — a `$libs/logger` test must not reach UP to the
// consuming `$logger` art for `SILENT_LOGGER` (which is exactly this shape).
const noop = (): void => {};
const SILENT_LOGGER: Logger = {
trace: noop,
debug: noop,
info: noop,
warn: noop,
error: noop,
fatal: noop
};
describe('diagnostics', () => {
it('routes framework diagnostics to the configured logger level', () => {

@ -0,0 +1,188 @@
<script>
/**
* ScrollFrames — secuencia de imágenes sincronizada con el scroll.
*
* Técnica: un contenedor alto ("track") con un hijo `position: sticky` que
* permanece fijo en pantalla mientras se recorre el track. El progreso del
* scroll dentro del track (0 → 1) se mapea a un índice de fotograma, y ese
* fotograma se dibuja en un <canvas> (sin parpadeos, fluido).
*
* Props:
* - frames: string[] URLs de los fotogramas, EN ORDEN. (obligatorio)
* - height: string Altura del track. Más alto = giro más lento. (def "300vh")
* - background: string Color de fondo del canvas. (def "transparent")
* - class: string Clases extra para el track.
*/
let {
frames,
height = '300vh',
background = 'transparent',
class: className = ''
} = $props();
// --- Estado reactivo (runas) ---
let track = $state(null); // contenedor alto (define el recorrido)
let canvas = $state(null); // lienzo donde se pinta el fotograma
let progress = $state(0); // 0..1 según el scroll dentro del track
let loaded = $state(0); // nº de imágenes ya precargadas
let size = $state({ w: 0, h: 0 }); // tamaño del canvas en píxeles de dispositivo
let images = []; // objetos Image (no necesita ser reactivo)
// Índice de fotograma derivado del progreso. round() reparte cada frame
// en una "franja" de scroll de igual tamaño.
const frameIndex = $derived(
frames.length
? Math.min(
frames.length - 1,
Math.max(0, Math.round(progress * (frames.length - 1)))
)
: 0
);
// --- 1) Precarga de todas las imágenes ---
$effect(() => {
let cancelled = false;
loaded = 0;
images = frames.map((src) => {
const img = new Image();
img.onload = () => {
if (!cancelled) loaded += 1; // dispara un redibujado al cargar
};
img.src = src;
return img;
});
return () => {
cancelled = true;
};
});
// --- 2) Cálculo del progreso al hacer scroll (throttle con rAF) ---
$effect(() => {
const el = track;
if (!el) return;
let ticking = false;
function compute() {
ticking = false;
const rect = el.getBoundingClientRect();
const vh = window.innerHeight;
const distancia = rect.height - vh; // recorrido útil mientras está sticky
const recorrido = -rect.top; // cuánto hemos avanzado dentro del track
progress =
distancia > 0
? Math.min(1, Math.max(0, recorrido / distancia))
: 0;
}
function onScroll() {
if (!ticking) {
ticking = true;
requestAnimationFrame(compute);
}
}
compute();
window.addEventListener('scroll', onScroll, { passive: true });
window.addEventListener('resize', onScroll);
return () => {
window.removeEventListener('scroll', onScroll);
window.removeEventListener('resize', onScroll);
};
});
// --- 3) Ajuste del canvas al tamaño real (nitidez en pantallas HiDPI) ---
$effect(() => {
const c = canvas;
if (!c) return;
function resize() {
const dpr = window.devicePixelRatio || 1;
const w = Math.round(c.clientWidth * dpr);
const h = Math.round(c.clientHeight * dpr);
c.width = w;
c.height = h;
size = { w, h }; // dispara redibujado
}
resize();
window.addEventListener('resize', resize);
return () => window.removeEventListener('resize', resize);
});
// --- 4) Dibujar el fotograma actual (cover) ---
$effect(() => {
// Dependencias reactivas que fuerzan el redibujado:
frameIndex;
size;
loaded;
const c = canvas;
const img = images[frameIndex];
if (!c || !img || !img.complete || !img.naturalWidth) return;
const ctx = c.getContext('2d');
const { width: cw, height: ch } = c;
const ir = img.naturalWidth / img.naturalHeight;
const cr = cw / ch;
let dw, dh, dx, dy;
if (ir > cr) {
dh = ch;
dw = ch * ir;
dx = (cw - dw) / 2;
dy = 0;
} else {
dw = cw;
dh = cw / ir;
dx = 0;
dy = (ch - dh) / 2;
}
ctx.clearRect(0, 0, cw, ch);
ctx.drawImage(img, dx, dy, dw, dh);
});
</script>
<div class="sfs-track {className}" bind:this={track} style:height>
<div class="sfs-sticky">
<canvas
class="sfs-canvas"
bind:this={canvas}
style:background
aria-hidden="true"
></canvas>
{#if frames.length && loaded < frames.length}
<div class="sfs-loader">{Math.round((loaded / frames.length) * 100)}%</div>
{/if}
</div>
</div>
<style>
.sfs-track {
position: relative;
width: 100%;
}
.sfs-sticky {
position: sticky;
top: 0;
height: 100vh;
display: grid;
place-items: center;
overflow: hidden;
}
.sfs-canvas {
width: 100%;
height: 100%;
display: block;
}
.sfs-loader {
position: absolute;
bottom: 1.5rem;
font: 0.75rem/1 system-ui, sans-serif;
letter-spacing: 0.1em;
opacity: 0.5;
}
</style>
Loading…
Cancel
Save

Powered by TurnKey Linux.