docs(process): canon + theming completos — el corpus ya tenía escrita la respuesta

Tercera sesión de lectura: el canon entero (tsc · vocabularies ·
recipe-contract), lo que faltaba del núcleo (active-app · agent · blocks) y
`theming/reference.md` COMPLETA. 21 de 30 documentos leídos sobre el original
(≈10.400 L de 19.000).

## La pregunta del color: el corpus la tenía respondida, dos veces y mejor

`reference.md` §1.bis se titula «Theming lives in Eidos, not in Morfo (by
design)» y se abre con «This is the most frequent architectural question».
Existe literalmente para impedir el error que cometió la sesión revertida. Su
apartado «What SHOULD enter morfo regarding theming» es inequívoco: un
componente que expone `color` como prop DEBE declarar `data-color.values` en
su morfo; los attrs puramente visuales (`data-variant`, `data-size`) NO.

Y §39 (2026-07-15, la doctrina más reciente) da el criterio mecánico y el
porqué: «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` pisa el
sello del wrapper. La frontera deja de ser convención: es de dónde se resuelve
el valor.

## Y el agujero real, ahora seguido extremo a extremo

`resolveComponentColor` (`eidos/lib/component-color.ts`) considera canónicos
los 9 roles MÁS las 33 escalas donantes = 42 nombres; sólo un color CSS crudo
se desvía a `data-color-custom`. El wrapper de switch pasa ese `dataColor` a
soma, y el provider lo devuelve verbatim. El morfo declara 6 valores.
`<Switch color="teal">` emite `data-color="teal"`, fuera del enum — y no es
un caso aislado: avatar 8 · button 8 · card 8 · switch 6 · toggle 6 ·
dialog 3, contra 42 posibles.

NO verificado si salta hoy en CI: `morfo:check` sólo ve lo que las demos
renderizan de hecho, y no lo he ejecutado. Ese es justamente el agujero — el
guard de «lo declarado se cumple» depende de que una demo elija el valor
infractor, en el eje que la decisión de 2026-07-18 abrió a 42. Es el único
hallazgo que pide decisión de usuario.

## Dos derivas más

- `active-app.md` enumera a mano 12 service factories; hay 15 (faltan
  `agent`, `motion`, `scene`, en la tabla y en el árbol). Misma enfermedad que
  el «8 roles» y contra la ley que el propio corpus escribió: catálogo
  hardcoded → puntero.
- `canon/tsc.md` anuncia el scope `event:` sin nota, mientras `reference.md`
  §13 lo marca «Superseded» y `motion.md` «descartado». El tipo existe, cero
  recetas lo consumen: las tres frases son ciertas, pero quien construya desde
  el canon lo leerá como disponible.

Nada arreglado (regla 5). Quedan ≈6.200 líneas: las guías, `decisions/` y los
RFCs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
alpha-0.1-sec-dom
dev 2 months ago
parent d8ff647d7c
commit 37061a7371

@ -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 | | `testing-and-tooling.md` | 110 | LIMPIO — releída completa 2026-07-30 |
| `CANON.md` | 305 | 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/morfo.md` | 888 | LIMPIO — leída completa 2026-07-30 |
| `architecture/active-app.md` | 351 | — | | `architecture/active-app.md` | 351 | LIMPIO — leída completa 2026-07-30 |
| `architecture/agent.md` | 472 | — | | `architecture/agent.md` | 472 | LIMPIO — leída completa 2026-07-30 |
| `architecture/packs.md` | 86 | LIMPIO — releí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 > `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 > 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 | | Doc | Líneas | Estado |
| --- | --- | --- | | --- | --- | --- |
| `canon/tsc.md` (Token Scope Contract) | 329 | — | | `canon/tsc.md` (Token Scope Contract) | 329 | LIMPIO — leída completa 2026-07-30 |
| `canon/vocabularies.md` (conjuntos cerrados, generados) | 153 | — | | `canon/vocabularies.md` (conjuntos cerrados, generados) | 153 | LIMPIO — leída completa 2026-07-30 |
| `canon/recipe-contract.md` | 184 | — | | `canon/recipe-contract.md` | 184 | LIMPIO — leída completa 2026-07-30 |
### Theming y motion ### Theming y motion
| Doc | Líneas | Estado | | 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/motion.md` | 791 | LIMPIO — releída completa 2026-07-30 |
| `theming/gradient-finish.md` | 475 | — | | `theming/gradient-finish.md` | 475 | — |
| `theming/guide.md` | 241 | — | | `theming/guide.md` | 241 | — |
@ -115,9 +115,11 @@ Estado: `LIMPIO` = leído sobre el original · `RELEER` = leído contaminado ·
| `building-a-component.md` | 55 | — | | `building-a-component.md` | 55 | — |
| `rfcs/*` (7 ficheros) | 1860 | — | | `rfcs/*` (7 ficheros) | 1860 | — |
Total ≈ 19.000 líneas. **Leídas sobre el original: 15 documentos** (≈ 7.100 L) — Total ≈ 19.000 líneas. **Leídas sobre el original: 21 documentos (≈ 10.400 L)** —
todo el núcleo de arquitectura menos `active-app`, `agent` y `blocks`. Sin el núcleo de arquitectura COMPLETO, el canon COMPLETO, y `theming/reference`
empezar: canon (3), theming (5 y media), guías y decisiones (9). 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 ## 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 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 hallazgo nº 9 existe (`data-variant`, `data-size`, …) pero `data-color` no
pertenece a ella: viene del prop y viaja por el morfo. 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 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 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` (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** `data-color` con **6 valores cerrados**
(`['primary','secondary','neutral','affirm','risk','threat']`), y (`['primary','secondary','neutral','affirm','risk','threat']`), y
`scripts/morfo-check.ts:167` falla cuando un attr con `values` emite algo `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 fuera del conjunto. Esa es la contradicción que merece decisión del
un valor que el morfo no declara. **NO verificado** si hoy salta: haría usuario, no la de si `data-color` va en el morfo.
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 **CADENA COMPLETA, verificada extremo a extremo (misma sesión).** No es
merece decisión del usuario, no la de si `data-color` va en el morfo. 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 15. **`provider.commitState()` / `provider.emitEvent()` no existen en el
código.** `grep -rn "commitState\|emitEvent"` sobre todo el repo (`.ts`, código.** `grep -rn "commitState\|emitEvent"` sobre todo el repo (`.ts`,
`.svelte`, `.js`, sin `node_modules`) → **cero coincidencias**. Los `.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: diff buscando más casos antes de dar por saneado el árbol. Fix pendiente:
una línea, sin decidir (no lo toco: regla 5). 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) ## Hallazgos RETIRADOS (eran autocita)
- ~~«los tests de provider son convención, no guard»~~ — era la edición - ~~«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 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 «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á 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 ## Cómo continuar
~~1. Releer los 7 marcados `RELEER`~~ · ~~2. `morfo.md` completo~~ — hechos. ~~1. Releer los 7 marcados `RELEER`~~ · ~~2. `morfo.md` completo~~ — hechos.
1. **Siguiente tanda**: el canon sin empezar (`canon/tsc.md` 329 · ~~1. El canon + el núcleo restante~~ · ~~2. `theming/reference.md` entera~~ —
`canon/vocabularies.md` 153 · `canon/recipe-contract.md` 184) y lo que hechos en la sesión 3.
queda del núcleo (`architecture/active-app.md` 351 ·
`architecture/agent.md` 472 · `architecture/blocks.md` 113). ≈ 1.600 L. 1. **Siguiente tanda**: las guías —`guides/component-guide.md` (1568, los
2. Después `theming/reference.md` **entera** (sólo van §20–§28) — es el pasos 1–40 + reglas A1–A37) y `guides/component-audit.md` (369). Es donde
documento vivo más citado y el que ancló la pregunta del color. vive el criterio de autoría, y lo que más se cita al construir.
3. Luego guías y decisiones: `guides/component-guide.md` (1568, las reglas 2. Después `decisions/book-deviations.md` (851) — la bitácora de dónde el
A1–A37) y `decisions/book-deviations.md` (851) son los dos gordos. 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 4. Actualizar este fichero al final de cada sesión de lectura: estado por
documento y línea donde se paró. documento y línea donde se paró.
5. **No escribir código ni doctrina hasta acabar.** Un hallazgo sólo se reporta 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 docs que documentan `commitState`/`emitEvent` (nº 15), las dos frases sobre el
guard inexistente (nº 16), `soma-architecture.md` §12/§8.bis sobre `clsx` 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 (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) 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). 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 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 De los once, **sólo el nº 14 pide decisión de usuario** (enum cerrado del
con un único arreglo evidente cada uno. 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.

Loading…
Cancel
Save

Powered by TurnKey Linux.