@ -71,10 +71,10 @@ Estado: `LIMPIO` = leído sobre el original · `RELEER` = leído contaminado ·
| `testing-and-tooling.md` | 110 | LIMPIO — releída completa 2026-07-30 |
| `CANON.md` | 305 | LIMPIO — releída completa 2026-07-30 |
| `architecture/morfo.md` | 888 | LIMPIO — leída completa 2026-07-30 |
| `architecture/active-app.md` | 351 | — |
| `architecture/agent.md` | 472 | — |
| `architecture/active-app.md` | 351 | LIMPIO — leída completa 2026-07-30 |
| `architecture/agent.md` | 472 | LIMPIO — leída completa 2026-07-30 |
| `architecture/packs.md` | 86 | LIMPIO — releída completa 2026-07-30 |
| `architecture/blocks.md` | 113 | — |
| `architecture/blocks.md` | 113 | LIMPIO — leída completa 2026-07-30 |
> `morfo.md` era la prioridad y ya está leída (era la capa del contrato, la más
> tocada durante la auditoría fallida, y se llegó a escribir criterio en su
@ -84,15 +84,15 @@ Estado: `LIMPIO` = leído sobre el original · `RELEER` = leído contaminado ·
| Doc | Líneas | Estado |
| --- | --- | --- |
| `canon/tsc.md` (Token Scope Contract) | 329 | — |
| `canon/vocabularies.md` (conjuntos cerrados, generados) | 153 | — |
| `canon/recipe-contract.md` | 184 | — |
| `canon/tsc.md` (Token Scope Contract) | 329 | LIMPIO — leída completa 2026-07-30 |
| `canon/vocabularies.md` (conjuntos cerrados, generados) | 153 | LIMPIO — leída completa 2026-07-30 |
| `canon/recipe-contract.md` | 184 | LIMPIO — leída completa 2026-07-30 |
### Theming y motion
| Doc | Líneas | Estado |
| --- | --- | --- |
| `theming/reference.md` | 1822 | PARCIAL — §20– §28 leídas (1406– 1535), incl. ** §25** (color) |
| `theming/reference.md` | 1822 | LIMPIO — leída **completa** 2026-07-30 |
| `theming/motion.md` | 791 | LIMPIO — releída completa 2026-07-30 |
| `theming/gradient-finish.md` | 475 | — |
| `theming/guide.md` | 241 | — |
@ -115,9 +115,11 @@ Estado: `LIMPIO` = leído sobre el original · `RELEER` = leído contaminado ·
| `building-a-component.md` | 55 | — |
| `rfcs/*` (7 ficheros) | 1860 | — |
Total ≈ 19.000 líneas. **Leídas sobre el original: 15 documentos** (≈ 7.100 L) —
todo el núcleo de arquitectura menos `active-app` , `agent` y `blocks` . Sin
empezar: canon (3), theming (5 y media), guías y decisiones (9).
Total ≈ 19.000 líneas. **Leídas sobre el original: 21 documentos (≈ 10.400 L)** —
el núcleo de arquitectura COMPLETO, el canon COMPLETO, y `theming/reference`
entera. Sin empezar: el resto de theming (gradient-finish · guide · notes ·
channels), las guías (`component-guide` 1568 es la gorda), `decisions/` y los
7 RFCs. ≈ 6.200 L.
## Hallazgos que SÍ se sostienen
@ -240,6 +242,32 @@ código**, que es la única autoridad que no puede haberla escrito un agente.
nombrar lo que es de eidos») era **falsa** . La categoría wrapper-only del
hallazgo nº 9 existe (`data-variant`, `data-size` , …) pero `data-color` no
pertenece a ella: viene del prop y viaja por el morfo.
**AMPLIACIÓN (lectura de `theming/reference.md`, misma sesión).** El corpus
ya tenía la respuesta escrita, dos veces, y con más autoridad de la que yo
reuní:
- ** `reference.md` §1.bis** existe LITERALMENTE para impedir este error.
Se titula *«Theming lives in Eidos, not in Morfo (by design)»* y se abre
con *«This is the most frequent architectural question»* . Su
§«What SHOULD enter morfo regarding theming» (líneas 282– 291) es
inequívoco: *«A component exposing `color` as a prop → * *must declare
`data-color.values: ['primary', 'affirm', ...]` in its morfo**»*, y en la
misma lista, *«purely visual attrs (`data-variant`, `data-size` ) that
NOBODY else needs → they do NOT go in morfo»*. La tabla de la línea 248
asigna `data-color.values` a **Morfo** , «cross-layer: soma validates,
eidos targets, sema references». La sesión revertida hizo justo lo que
esta sección enumera como propuesta a rechazar.
- ** `reference.md` §39** (líneas 1750– 1757, 2026-07-15 — la doctrina más
reciente) da el **criterio mecánico** que faltaba, y el porqué:
*«`data-gradient` is an eidos-only WRAPPER attr … * *Rule of thumb: morfo
declares an attr only when its driving prop crosses the soma
boundary**»*, con el modo de fallo medido: si declaras en morfo un attr
cuyo prop no llega a soma, el runtime emite `undefined` y
`mergeProps(restProps, state.props)` pisa el sello del wrapper.
→ Con eso la frontera queda nítida y comprobable: `color` **cruza** la
frontera de soma (los 12 morfos lo resuelven con `v.propRef('color')` ) →
va al morfo. `variant` / `size` / `gradient` no la cruzan → los sella el
wrapper. No es una convención: es de dónde se resuelve el valor.
14. **Y la pregunta REAL que había debajo: el enum del morfo es más estrecho que
el prop que se envía.** `theming/reference.md` §25, líneas 1496– 1507
(decisión de diseño 2026-07-18, «reversión de los subconjuntos»): *«`color`
@ -251,11 +279,29 @@ código**, que es la única autoridad que no puede haberla escrito un agente.
`data-color` con **6 valores cerrados**
(`['primary','secondary','neutral','affirm','risk','threat']`), y
`scripts/morfo-check.ts:167` falla cuando un attr con `values` emite algo
fuera del conjunto. → `<Switch color="teal">` compila por diseño y emitiría
un valor que el morfo no declara. **NO verificado** si hoy salta: haría
falta que una demo renderice un valor fuera del enum y correr `morfo:check`
(necesita dev server); no lo he ejecutado. Esa es la contradicción que
merece decisión del usuario, no la de si `data-color` va en el morfo.
fuera del conjunto. Esa es la contradicción que merece decisión del
usuario, no la de si `data-color` va en el morfo.
**CADENA COMPLETA, verificada extremo a extremo (misma sesión).** No es
hipotética — seguí el valor desde el prop hasta el DOM:
1. `eidos/lib/component-color.ts` → `CANONICAL_COLOR` = `COLOR_ROLES` ** ∪
`PALETTE_SCALES` ** = **42 nombres** . `resolveComponentColor('teal')`
devuelve `dataColor: 'teal'` (sólo un color CSS **crudo** se desvía a
`data-color-custom` + `--color-custom` ).
2. `eidos/components/switch/switch.svelte:42` pasa ese `dataColor` al prop
`color` de soma.
3. `soma/components/switch/switch-provider.svelte.ts:88– 94` lo devuelve
**verbatim** (sólo intercepta el intent evaluativo y el caso custom).
4. El morfo declara `data-color` con **6** valores.
→ `<Switch color="teal">` emite `data-color="teal"` , fuera del enum.
Y no es un caso aislado — enums declarados hoy: **avatar 8 · button 8 ·
card 8 · switch 6 · toggle 6 · dialog 3**, contra los 42 que el wrapper
puede sellar. Los seis pueden emitir fuera de contrato **por diseño** .
**NO verificado** si hoy salta en CI: `morfo:check` sólo ve lo que las
demos renderizan de hecho, y no lo he ejecutado (necesita dev server). El
agujero es que el guard de «lo declarado se cumple» depende de que una
demo elija el valor infractor — justo en el eje que la decisión de
2026-07-18 abrió a 42.
15. ** `provider.commitState()` / `provider.emitEvent()` no existen en el
código.** `grep -rn "commitState\|emitEvent"` sobre todo el repo (`.ts`,
`.svelte` , `.js` , sin `node_modules` ) → **cero coincidencias** . Los
@ -318,6 +364,27 @@ código**, que es la única autoridad que no puede haberla escrito un agente.
diff buscando más casos antes de dar por saneado el árbol. Fix pendiente:
una línea, sin decidir (no lo toco: regla 5).
### De la tanda canon + núcleo restante + theming (2026-07-30, sesión 3)
22. ** `active-app.md` enumera a mano un catálogo que ya driftó.** Su tabla
§«Available services» lista **12** factories y el árbol §«Filesystem
layout» los repite uno a uno. En `git ls-files
src/arts/active-app/service-factories/` hay **15** : faltan ** `agent.ts` ,
`motion.ts` y `scene.ts` ** en ambos sitios. Es la misma enfermedad que el
«8 roles» del nº 21 y que la ley que el propio corpus escribió
(`authoring.md`: catálogos hardcoded → puntero). El árbol es la fuente;
la lista es el problema.
23. ** `canon/tsc.md` anuncia un scope que dos docs declaran superado.** Su
tabla «Available scopes» lista `event:${v}` → *«Motion token bound to a
perceptual signal»* sin nota alguna. Pero `reference.md` §13 se titula
*«Sema integration (`event:* ` scope)»* y su cuerpo entero es
** «⚠️ Superseded»**, y `motion.md` (líneas 46 y 699) lo da por
**descartado, «no real use»** . Comprobado: el tipo SIGUE existiendo
(`eidos/lib/config-types.ts:471,499`) y **cero recetas lo consumen** . O
sea que las tres frases son literalmente ciertas — pero quien construya
desde el canon (que es para lo que está el canon) lo leerá como
disponible. Severidad baja; coste de arreglo, una nota.
## Hallazgos RETIRADOS (eran autocita)
- ~~«los tests de provider son convención, no guard»~~ — era la edición
@ -337,20 +404,22 @@ código**, que es la única autoridad que no puede haberla escrito un agente.
falló en el método, y al revertirla se perdieron los dos. La lección no es
«desconfía del hallazgo revertido», es: **un hallazgo doc↔código se verifica
contra el código**. Si sólo se puede sostener citando otro documento, no está
verificado. Los nueve hallazgos nuevos de esta sesión llevan los dos anclajes.
verificado. Los once hallazgos nuevos de estas sesiones llevan los dos anclajes.
## Cómo continuar
~~1. Releer los 7 marcados `RELEER` ~~ · ~~2. `morfo.md` completo~~ — hechos.
1. **Siguiente tanda** : el canon sin empezar (`canon/tsc.md` 329 ·
`canon/vocabularies.md` 153 · `canon/recipe-contract.md` 184) y lo que
queda del núcleo (`architecture/active-app.md` 351 ·
`architecture/agent.md` 472 · `architecture/blocks.md` 113). ≈ 1.600 L.
2. Después `theming/reference.md` **entera** (sólo van §20– §28) — es el
documento vivo más citado y el que ancló la pregunta del color.
3. Luego guías y decisiones: `guides/component-guide.md` (1568, las reglas
A1– A37) y `decisions/book-deviations.md` (851) son los dos gordos.
~~1. El canon + el núcleo restante~~ · ~~2. `theming/reference.md` entera~~ —
hechos en la sesión 3.
1. **Siguiente tanda** : las guías —`guides/component-guide.md` (1568, los
pasos 1– 40 + reglas A1– A37) y `guides/component-audit.md` (369). Es donde
vive el criterio de autoría, y lo que más se cita al construir.
2. Después `decisions/book-deviations.md` (851) — la bitácora de dónde el
framework se separa del libro, y por qué.
3. Luego el resto de theming (`gradient-finish` 475 · `guide` 241 · `notes`
179 · `channels` 143) y los 7 RFCs (1860).
4. Actualizar este fichero al final de cada sesión de lectura: estado por
documento y línea donde se paró.
5. **No escribir código ni doctrina hasta acabar.** Un hallazgo sólo se reporta
@ -371,9 +440,11 @@ lectura, y quedan ≈ 11.900 líneas. En concreto **no se ha tocado**: el enum d
docs que documentan `commitState` /`emitEvent` (nº 15), las dos frases sobre el
guard inexistente (nº 16), `soma-architecture.md` §12/§8.bis sobre `clsx`
(nº 17), `packs.md` /`glossary.md` sobre Aura y `uix.scene` (nº 18), el
frontmatter de `CANON.md` (nº 19), el entry huérfano de `package.json` (nº 20)
ni la línea que tiene `docs:check` en rojo (nº 21).
De los nueve, **sólo el nº 14 pide decisión de usuario** (enum cerrado del
morfo vs. `color` abierto por diseño). Los otros ocho son deriva doc↔código
con un único arreglo evidente cada uno.
frontmatter de `CANON.md` (nº 19), el entry huérfano de `package.json` (nº 20),
la línea que tiene `docs:check` en rojo (nº 21), la tabla de servicios de
`active-app.md` (nº 22) ni la nota que le falta al scope `event:` (nº 23).
De los once, **sólo el nº 14 pide decisión de usuario** (enum cerrado del
morfo vs. `color` abierto a 42 por diseño; y con `morfo:check` cazándolo sólo
si una demo elige el valor). Los otros diez son deriva doc↔código con un único
arreglo evidente cada uno.