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/CONTINUE-lectura-doctrina.md

702 lines
43 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# CONTINUE — lectura del corpus doctrinal
Registro de lectura. Existe porque la lectura del corpus **no cabe en una sola
ventana de contexto** (~19.000 líneas) y sin este fichero cada sesión la
reempieza o se la salta — que es exactamente cómo se auditó a ciegas el
2026-07-29/30 y hubo que revertir 7 commits (`3097cfcb6`).
No es fuente de verdad. Es un marcador de posición.
---
## Empieza aquí (arranque en frío)
**Dónde está.** 29 documentos leídos sobre el original (≈14.650 L), en cuatro
sesiones el 2026-07-30. COMPLETOS: el núcleo de arquitectura, el canon,
`theming/reference`, **las tres guías** (component-guide · component-audit ·
demo-authoring), **`book-deviations`** y **todo theming**. Ningún documento
queda contaminado.
**Lo primero que hay que saber si entras en frío.** El inventario que este
fichero traía era **incompleto**: contaba «30 documentos / 19.000 L», y el
corpus que el propio mapa ([`docs/README.md`](../README.md)) declara son
**59 ficheros / 27.348 L** (excluidos `process/`, `old-deprecated/` y los 139
dossiers de `audit/components/`). Faltaban documentos que el corpus llama
vinculantes — ver hallazgo **nº 24**. El inventario de abajo ya está corregido.
**Qué hacer ahora.** Seguir leyendo, por este orden:
1. Los 7 RFCs (1860) — la última tanda del plan original.
2. **`spec/delegation-contract.md`** (502) — **NORMATIVO** (RFC-2119, ids
`AG-n`). Nunca estuvo en el inventario.
3. `book-map` (201) · `authoring` (136) · `decisions.md` (88) ·
`building-a-component` (55).
4. **`theming/changelog.md`** (1879) — el documento sin leer más grande del
corpus; es la crónica fechada detrás de las decisiones de `reference`.
5. El resto nunca inventariado: `getting-started` (107) · `comparison` (95) ·
`next-features` (287) · `decisions/design-text-effects` (145).
Al acabar cada tanda: actualizar el inventario de abajo y los hallazgos.
**Las tres reglas que no se saltan.**
- **No escribir código ni doctrina hasta acabar la lectura.** Quedan ≈5.355 L
del corpus mapeado (más los 4 registros de diseño que indexa `decisions.md`,
4.574 L, cuyo estatuto hay que decidir al leer `decisions.md`).
- **Un hallazgo doc↔código se verifica CONTRA EL CÓDIGO.** Si sólo se sostiene
citando otro documento, no está verificado — así se fabricaron los tres
hallazgos falsos que costaron el revert.
- **Paso 0 antes de citar**: comprobar que la línea no la escribió una sesión
previa (`git log -L n,n+1:fichero`). Vale también **para el código**: el
hallazgo nº 28 se sostuvo comprobando que `announce.ts` lo escribió trabajo
real (`53b6f629f`), no una sesión de agente.
**Lo único que espera decisión tuya.** Sigue siendo el hallazgo **nº 14** (enum
cerrado del morfo vs. `color` abierto a 42), ahora con la población exacta
acotada: son **12 morfos**, no 46 — ver nº 37. Todo lo demás es deriva
doc↔código con arreglo evidente, listado en «Lo que NO se ha hecho».
**Estado del árbol**: `npm run docs:check` da **2** errores (no 1), ambos la
misma enfermedad — `says "8 roles" but COLOR_ROLES.length is 9`:
- `src/uix/eidos/components/callout/README.md:23` — daño colateral del revert
(hallazgo nº 21).
- `src/uix/blocks/banner/README.md:15` — **nuevo, y sin trackear**: trabajo en
curso del tier blocks (F2.11). No lo introdujo esta lectura y **no se toca**
(es trabajo ajeno en vuelo). Lo que sí enseña: el conteo hardcodeado no es un
fósil que se esté extinguiendo, se está **reproduciendo en obra nueva** —
cuarta aparición junto a los nº 21, 22/27 y 34.
---
## La regla que lo motiva
La instrucción del usuario fue: «audita el sistema, **para ello previamente lee
toda la documentación**». Es una **precondición bloqueante**, no contexto
opcional. Incumplirla produjo tres hallazgos falsos, un commit dedicado a
retirarlos, y preguntas al usuario cuya respuesta estaba escrita.
El orden lo fija el propio corpus en [`docs/README.md`](../README.md)
§«Reading order for a fresh start»: `overview` → `active-architecture` →
`CANON` → el capítulo de la capa que se toque.
## ⚠️ Contaminación: 7 documentos leídos en estado editado — **RESUELTA 2026-07-30**
> **Cerrada.** Los 12 documentos marcados `RELEER` se releyeron sobre el
> original. La limpieza del árbol se verificó **antes** de leer, no se supuso:
> `git diff c39170abb^ HEAD -- docs/CANON.md docs/architecture/ docs/glossary.md
> docs/guides/completion-checklist.md docs/testing-and-tooling.md docs/theming/`
> devuelve **vacío** → lo que hay en HEAD es byte a byte el estado pre-auditoría.
> Esa comprobación es el paso 0 de cualquier relectura futura.
**Lo primero que hay que saber.** El commit revertido `c39170abb` editaba 12
documentos. La lectura del 2026-07-30 se hizo sobre el árbol **con esas
ediciones dentro**, así que parte de lo que se leyó como «doctrina» era la
escritura del propio agente que luego se revirtió.
Consecuencia: **esos 7 hay que releerlos en su estado actual (original).**
~~Pendiente~~ — **hecho el 2026-07-30**; lo que sigue se conserva porque la
lección vale más que el incidente.
Dos ejemplos medidos de cómo engañó:
- `testing-and-tooling.md` — el original dice *«a guard fails when an active
provider ships without one»*. La edición lo había cambiado a *«This is a
convention, not a guard — the mechanical check does not exist»*. Se citó como
doctrina para justificar una decisión de arnés de tests. **Era autocita.**
- `overview.md` — el original documenta `provider.commitState()` /
`provider.emitEvent()` («Three Soma scenarios»). La edición lo sustituyó por
«One door: runtime.trigger» + la frase *«neither has ever existed in the
code»*. Con eso se «descubrió» una contradicción contra
`soma-architecture.md` que **la propia edición había creado**. Tras el revert
ambos documentos coinciden.
Lección para quien siga: **antes de citar un documento como doctrina, comprobar
que la línea citada no la escribió una sesión previa.** `git log -p -- <fichero>`
sobre el párrafo en cuestión.
## Inventario
Estado: `LIMPIO` = leído sobre el original · `RELEER` = leído contaminado ·
`—` = sin empezar. **Hoy no queda ninguno en `RELEER`.**
### Núcleo de arquitectura
| Doc | Líneas | Estado |
| --- | --- | --- |
| `README.md` (el mapa) | 155 | LIMPIO |
| `architecture/sema.md` | ~~1024~~ **1051** | ⚠️ LIMPIO pero **CADUCA** — ver nº 25 |
| `architecture/eidos.md` | 1055 | LIMPIO — leída completa 2026-07-30 |
| `architecture/overview.md` | 503 | LIMPIO — releída completa 2026-07-30 |
| `architecture/active-architecture.md` | 837 | LIMPIO — releída completa 2026-07-30 |
| `architecture/active-uix.md` | 115 | LIMPIO — releída completa 2026-07-30 |
| `architecture/soma.md` | 471 | LIMPIO — releída completa 2026-07-30 |
| `architecture/soma-architecture.md` | 1034 | 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 |
| `architecture/morfo.md` | 888 | LIMPIO — leída completa 2026-07-30 |
| `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 | LIMPIO — leída completa 2026-07-30 |
| **`spec/delegation-contract.md`** | 502 | — **NORMATIVO, nunca inventariado** (nº 24) |
> `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
> §Step 2 sin haberla leído nunca). Lo que salió, en «Hallazgos».
### Canon
| Doc | Líneas | Estado |
| --- | --- | --- |
| `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 | LIMPIO — leída **completa** 2026-07-30 |
| `theming/motion.md` | 791 | LIMPIO — releída completa 2026-07-30 |
| `theming/gradient-finish.md` | 475 | LIMPIO — leída completa 2026-07-30 (s.4) |
| `theming/guide.md` | 241 | LIMPIO — leída completa 2026-07-30 (s.4) |
| `theming/motion-guide.md` | 232 | LIMPIO — releída completa 2026-07-30 |
| `theming/notes.md` | 179 | LIMPIO — leída completa 2026-07-30 (s.4) |
| `theming/channels.md` | 143 | LIMPIO — leída completa 2026-07-30 (s.4) |
| **`theming/changelog.md`** | 1879 | — **nunca inventariado** (nº 24) |
**Theming queda COMPLETO salvo `changelog.md`**, que el mapa sitúa en E3 y
nadie había contado.
### Guías y decisiones
| Doc | Líneas | Estado |
| --- | --- | --- |
| `guides/component-guide.md` (pasos + reglas A1–A37) | 1568 | LIMPIO — leída completa 2026-07-30 (s.4) |
| `decisions/book-deviations.md` | 851 | LIMPIO — leída completa 2026-07-30 (s.4) |
| `guides/component-audit.md` | 369 | LIMPIO — leída completa 2026-07-30 (s.4) |
| `guides/completion-checklist.md` | 337 | LIMPIO — releída completa 2026-07-30 |
| **`guides/demo-authoring.md`** | 266 | LIMPIO — leída completa 2026-07-30 (s.4); **nunca inventariada** pese a ser LOCKED (nº 24) |
| `book-map.md` | 201 | — |
| `authoring.md` | 136 | — |
| `glossary.md` | 89 | LIMPIO — releída completa 2026-07-30 |
| `decisions.md` | 88 | — |
| `building-a-component.md` | 55 | — |
| `rfcs/*` (7 ficheros) | 1860 | — |
### Nunca inventariado (descubierto en la sesión 4 — nº 24)
| Doc | Líneas | Estrato según el mapa | Estado |
| --- | --- | --- | --- |
| `theming/changelog.md` | 1879 | E3 | — |
| `spec/delegation-contract.md` | 502 | E1 — **NORMATIVO** | — |
| `next-features.md` | 287 | E3 | — |
| `guides/demo-authoring.md` | 266 | E4 — **LOCKED** | LIMPIO (s.4) |
| `decisions/design-text-effects.md` | 145 | E3 | — |
| `getting-started.md` | 107 | puerta de entrada | — |
| `comparison.md` | 95 | «I want to…» | — |
| `audit/components/_{veredictos,naming,system,cierre}.md` | 412 | registro, pero **citados como canon** (S4/S7/S10, N1–N10) | — |
Fuera del mapa, indexados por `decisions.md`: `design-connection` (1987) ·
`design-timer` (1540) · `design-session` (857) · `design-chat-block` (190).
Su estatuto se decide al leer `decisions.md`.
**Total real del corpus: 27.348 líneas en 59 ficheros** (sin `process/`,
`old-deprecated/` ni los 139 dossiers por componente). **Leídas sobre el
original: 29 documentos (≈ 14.650 L)** — núcleo de arquitectura, canon,
`theming/reference`, theming completo salvo `changelog`, las tres guías y
`book-deviations`. Quedan ≈ 5.355 L del corpus mapeado.
## Hallazgos que SÍ se sostienen
Salen de documentos limpios y verificados como originales:
1. **«Only composition roots create shared services»** —
`architecture/active-uix.md` §Ownership, regla 1: *«`morfo`, `soma`, `sema`,
`eidos` and components never create `dom`, `langs`, `prefs`, `format`,
`clipboard` or equivalents: they receive them from `ActiveUix`»*.
`eidos.md` la repite (*«ActiveEidos creates no shared services»*). Las dos
puertas son `createActiveUix` / `attachActiveUix`; el arranque de un shell
son tres líneas (`createActiveUix` → `setActiveUix` → `Soma.create()`).
✅ **Confirmado 2026-07-30**: el fichero se releyó sobre el original y el
párrafo es literal (`active-uix.md` líneas 61–63). La advertencia de
RELEER que había aquí queda retirada.
2. **Overlays: `sequence: 'post'`, no `'pre'`** — `sema.md` (LIMPIO), nota
destacada: un evento de aparición cuyo provider fija `open` en el HANDLER
debe declarar `'post'`; con `'pre'` el hold de ~240 ms gatea el montaje.
3. **`intentRationale`** — `sema.md` (LIMPIO), `BK-FRAME-NO-INTENT`: una
familia estructural (`contact`/`emerge`/`shift`/`sustain`/`delegate`) que
declare intent no neutro debe justificarlo en
`MorfoEventSemantic.intentRationale` o `validateMorfo` la rechaza.
`handle` está exento.
4. **El scheduler de los holds** — `sema.md` (LIMPIO): los holds van por
`uix.timers.schedule` (`semaDelay`, `sema/timers.ts`), y sólo caen a
`setTimeout` *«when a channel is built without a scheduler (direct unit
tests)»*. Matiza la regla 1 para tests unitarios; no la anula.
### De `morfo.md` (leída completa, original)
5. **§Step 2 omite `'private'` — CONFIRMADO contra el original.** Las líneas
397–399 listan sólo `'public'` y `'virtual'`; la lista de referencia
(líneas 55–59) sí documenta los tres `kind`. El autor decide en §Step 2, así
que el hueco es real. ⚠️ Lo que estaba MAL era el criterio que la sesión
revertida escribió ahí como arreglo («el test es mecánico: debe existir
`<Componente.Parte>`»), que clasifica mal a todo primitivo de API plana.
El hueco sigue abierto; el arreglo no está decidido.
6. **`emit: 'value'` es legítimo** (línea 436): los `data-*` no-enum van por
defecto a `emit: 'presence'`; `emit: 'value'` es para atributos que llevan
un valor real (`data-value`, `data-min`, `data-max`).
7. ⚠️ **Y una regla que CUESTIONA la conclusión de la sesión revertida sobre
`data-color`** (línea 878, «Common pitfalls»): *«**Provider emits a data-attr
not in the morfo.** Strict mode logs a warning at runtime; morfo-check fails
in CI. Either add the attr to the morfo or rename the provider's emission to
`data-_*`»*. Más el incidente 2026-05-20 (línea 868): *«A component is not
done if the provider or demo emits required `data-*` that Morfo does not
declare»*. La sesión revertida concluyó que `data-color` NO debe ir en el
morfo porque su vocabulario es de eidos; esta regla dice que lo emitido debe
declararse. La distinción a resolver es si un attr estampado por el WRAPPER
de eidos (no por el provider de soma) entra en la regla — y eso exige leer
`eidos.md` completo y `theming/reference`. ~~NO resolver antes.~~ →
**RESUELTO en el nº 13**: el attr lo estampa el wrapper PERO su prop cruza
la frontera de soma, así que va al morfo.
8. **`data-_*`** es el prefijo reservado para attrs privados, deliberadamente
fuera del morfo; `validateMorfo()` los RECHAZA en una declaración.
### De `eidos.md` (limpia, leída hasta la 750)
9. **Existe una categoría SANCIONADA de data-attrs visuales fuera del morfo.**
§«From Soma», línea 489: *«The wrapper adds the visual token data-attrs
(`data-variant`, `data-size`, `data-block`, `data-icon-only`) and does not
reimplement state»*. Y la tabla §«From morfo» (líneas 451–460) enumera lo que
eidos consume del morfo — `parts[].kebab`, `archetype`, `states` +
`data[].values`, `data-starting-style`/`data-ending-style`, `events[].name`,
`semantic.family`/`.intent`, `prewrite[]`, `focus.trap`: **`data-color` NO
aparece**.
→ Esto es la mitad de la respuesta a la pregunta aparcada (nº 7): la regla de
`morfo.md` línea 878 («lo que el PROVIDER emite, se declara») convive con una
categoría de attrs que estampa el WRAPPER y que no van al morfo. `data-size`
es el precedente concreto y verificable (`switch.css` lo usa en 4 reglas y no
está en el morfo de switch).
→ **Falta la otra mitad**: si `data-color` pertenece a esa categoría. La
lista de la línea 489 es ilustrativa, no exhaustiva, y no lo incluye. La
respuesta está en **`theming/reference.md` §25** («Color model: palette +
roles + intents»), que el propio `eidos.md` señala como canon del color
(línea 589). ~~NO resolver antes de leer §25.~~ → **RESUELTO en el nº 13**
(§25 leída 2026-07-30; la respuesta estaba además en §1.bis y §39).
10. **`--*` es namespace de eidos** (§«The `--*` token rule»): *«The upper
layers (sema, soma, morfo) do NOT consume these tokens and do not use the
prefix»*. Es sobre custom properties, no sobre data-attrs, pero fija el
principio de propiedad.
11. **`eidos-only` es una clasificación VÁLIDA, no un error** (§«Selector-drift
defense», líneas 850–858). `eidos-lint` clasifica cada selector en
*morfo-backed* / *eidos-only* / *invalid*, y define **eidos-only** como:
*«the marker is there, but at least one `data-*` is not declared in the
morfo. **Valid by convention** (visual tokens like `data-variant`,
`data-size` come from the wrapper)»*. Sólo *invalid* (attr declarado con
valor fuera del enum) es bug.
12. **THM-4 (líneas 865–887) da la disposición para el caso inverso**: un attr
*«declared FOR a visual axis and that nothing anywhere consumes — no
recipe, no shared layer, no sibling, no behavioral reason»* es deuda, y la
disposición es *«consume it or **prune it from the morfo** (never leave
"declared for styling, styled nowhere")»*.
→ Las dos piezas juntas apuntan a que un `data-color` estampado por el
wrapper y ausente del morfo es **legítimo** (eidos-only), y que un
`data-color` declarado en el morfo sólo por un eje visual es podable. Pero
**sigue faltando `theming/reference.md` §25**, que `eidos.md` designa como
el canon del color: ~~no dar la pregunta por cerrada hasta leerla~~ →
**CERRADA en el nº 13**.
### De la relectura de los 12 contaminados (2026-07-30, sesión 2)
Todos verificados dos veces: documento + línea sobre el original, y **contra el
código**, que es la única autoridad que no puede haberla escrito un agente.
13. **PREGUNTA APARCADA (nº 7 / 9 / 12) — CERRADA: `data-color` SÍ va en el
morfo.** Tres evidencias independientes, ninguna autocita:
- `architecture/active-architecture.md` línea 565, tabla §6 «DOM attributes
— the universal channel»: `data-color="primary"` · escribe **`dom.apply`
(effect)** · lee **Eidos**. Es la misma casilla que `data-state` y
`data-intent`, NO la de los attrs del wrapper. Provenance comprobada con
`git log -L 565,566`: entró con la traducción `8668e117b` desde el doc
castellano, y ahí lo escribió `d4dfdaffa` — muy anterior a cualquier
sesión de agente.
- `guides/completion-checklist.md` **E-3.5**: *«All visual props (`size`,
`variant`, `color`, `radius`) map to `data-{prop}="value"` on the root»*;
más **R-3.1**, **R-3.3** (*«`data-color` reflects the intent»*) y
**G-1.2/G-1.3** (el subset se declara y el recipe sólo casa el declarado).
- El código: **12 morfos declaran `data-color`** (avatar, backdrop, button,
callout, card, card-group, chronos, dialog, metrics, surface, switch,
toggle), como entrada `data` real —
`attr: 'data-color', values: [...], value: v.propRef('color')`.
→ La conclusión de la sesión revertida (`f8e35b8fd`, «el morfo no puede
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`
acepta el sistema completo — rol / intent / 33 escalas donantes / valor CSS
crudo (`ComponentColorProp`) — en TODOS los componentes, sin excepciones»*,
con guard estructural en `recipe-css-contract.test.ts`. El tipo es abierto:
`ComponentColorProp = ComponentColor | (string & {})`
(`eidos/lib/types.ts:216`). Pero el morfo de `switch` declara
`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. 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
documentan dos docs, en originales verificados: `architecture/overview.md`
líneas 320–334 («Three Soma scenarios») y
`architecture/soma-architecture.md` líneas 269–293 («Three operations
covering every scenario», con el cuerpo `async commitState(change, event?)`
escrito entero). → El *desmentido* de la sesión revertida era **cierto
sobre el código**; lo inválido fue el método (lo «descubrió» citando su
propia edición). Y la retirada del hallazgo fue correcta en lo suyo: la
*contradicción entre los dos docs* sí era manufacturada — los dos dicen lo
mismo. La deriva es **doc↔código, y afecta a los dos por igual**.
16. **El guard de tests de provider NO existe** — la pregunta que quedó abierta,
ahora cerrada por la puerta buena. `NO_MISSING_PROVIDER_TESTS` aparece en
**dos ficheros y los dos son docs** (`soma-architecture.md` y
`docs/old-deprecated/fable_audit.md`); no hay comprobación de existencia de
`*.test.ts` en `scripts/`, no hay invariante de cobertura en
`src/uix/contracts.test.ts` (sus guards son VG-8, SYS-1, MOR-4, A30, A31,
THEME-SYS-1 y ~30 más, ninguno de cobertura), y no hay script npm que lo
haga. Lo afirman `soma-architecture.md` §6 líneas 495–497 (*«the guard
returns `NO_MISSING_PROVIDER_TESTS`»*) y `testing-and-tooling.md` líneas
43–46 (*«a guard fails when an active provider ships without one»*). Ambas
frases son originales y ambas son **falsas contra el código**.
17. **`clsx`: dos originales se contradicen, y el código ya resolvió.**
`architecture/soma.md` §3 líneas 103–107 dice que era fantasma y se inlineó
el 2026-07-11 (DEP-1) como `toClassString`, import fuera. `soma-architecture.md`
§12 línea 850 sigue diciendo *«`clsx` is imported in `props/props.ts`
without being declared … a debt pending decision»*, y §8.bis línea 713
*«`class` → merged with clsx»*. El código
(`src/uix/soma/props/props.ts:49–52`) confirma la versión de `soma.md`: el
flattener propio, sin import. `soma-architecture.md` está **stale**.
18. **`packs.md` y `glossary.md` describen un futuro que ya ocurrió.**
`packs.md` líneas 78–79: *«When `Aura` lands, the scene runtime is promoted
to a `uix.scene` service; until then it stays a standalone factory»*;
`glossary.md` línea 34: Aura *«Not built yet»*. En el código: `uix.scene`
**es servicio** (`active-uix/active-uix.svelte.ts:152–178`,
`createEngineScene` + lectura de `app.scene` en attach) y **Aura existe en
las tres capas** (`morfo/components/aura.ts`, `soma/components/aura`,
`eidos/components/aura`).
19. **`CANON.md` apunta a un libro que no está.** El frontmatter (líneas 7–9)
declara `sources.book: docs/Disenando_lo_que_ocurre_HOMOGENEIZADO.pdf`; ese
fichero **no existe en el repo** (`find -iname "*HOMOGENEIZADO*"` → vacío).
El §Sources del mismo documento (línea 296) cita
`Disenando_lo_que_ocurre_FINAL.pdf`, que **sí existe**. El puntero roto es
el del frontmatter, y lo escribió `53b6f629f` (commit de trabajo real, no
una sesión de auditoría).
20. **`package.json` conserva el entry `generate:contracts-docs`** y el script
`scripts/generate-contracts-docs.ts` ya no existe. `testing-and-tooling.md`
líneas 76–77 documenta el borrado; el entry huérfano sigue. Ya estaba
fichado como pendiente menor en
[`CONTINUE-docs-corpus.md`](./CONTINUE-docs-corpus.md) §Fósiles.
21. **`npm run docs:check` lleva en rojo desde el revert, y es daño colateral
del propio revert.** Salida actual en HEAD:
`ERROR [I1-count] src/uix/eidos/components/callout/README.md:23 — says "8
roles" but COLOR_ROLES.length is 9`. El diff lo explica solo:
`c39170abb` **arreglaba** esa línea (`the 8 roles` → `the canonical color
roles`, o sea aplicaba la ley «enlaza el const, no copies el número») y
`3097cfcb6` la revirtió con todo lo demás. → El revert fue correcto en su
intención pero deshizo también **arreglos buenos**; conviene revisar su
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.
### De las guías + `book-deviations` + theming (2026-07-30, sesión 4)
Todos con los dos anclajes: documento + línea sobre el original, y comando
contra el código.
24. **El inventario de este mismo fichero estaba incompleto — y faltaban dos
documentos que el corpus declara vinculantes.** Censo de `git ls-files`
sobre `docs/` (sin `process/`, `old-deprecated/` ni los 139 dossiers):
**59 ficheros, 27.348 L**, contra las «30 / 19.000» que se venían
contando. Los ausentes no eran marginales:
- **`guides/demo-authoring.md`** (266) — `component-audit.md` §0 la manda
leer *«cada vez»*, la incluye en el «paquete mínimo» de todo brief
(línea 44: *«el template LOCKED de demo, D-1.x es error-level»*) y la
cita 7 veces como fuente de las reglas de paridad.
- **`spec/delegation-contract.md`** (502) — el mapa la rotula
**NORMATIVE** (RFC-2119, ids estables `AG-n`).
- **`theming/changelog.md`** (1879) — el mayor documento del corpus sin
leer.
→ Leída ya `demo-authoring` en esta sesión. El inventario de arriba queda
corregido; el arranque en frío ya no manda leer un corpus truncado.
25. **`sema.md` se leyó en un estado que hoy no existe.** El registro lo daba
LIMPIO a 1024 L; el fichero tiene **1051** y sigue limpio en el árbol. Lo
cambió **hoy** `6920684d0` (*«extraer el motor Web Audio de sema al art
`$sound`»*), que reescribió su §SoundChannel entera —el título pasó a
*«SoundChannel — doctrine here, machine in `$sound`»*— y añadió el porqué
del corte. No es contaminación de agente (commit de trabajo real): es
**caducidad**, el otro modo en que una lectura deja de valer. Releer esa
sección antes de citar sema en materia de sonido.
26. **La tabla de alias de `CLAUDE.md:96` no incluye `$sound`.** El alias
existe en la fuente de verdad (`vite.config.ts:35`) y en
`svelte.config.js:41` desde el mismo commit de hoy. La tabla enumera 24
artes a mano; van 25.
27. **Amplía el nº 22 — `active-app.md` documenta 12 de 16 factories.**
`git ls-files src/arts/active-app/service-factories/` (sin `index.ts`) da
**16**; faltan en la tabla §«Available services» y en el árbol
§«Filesystem layout»: `agent`, `motion`, `scene` y —desde hoy— `sound`.
`src/arts/README.md` **sí** se actualizó en el mismo pase; `active-app.md`
no. Es el argumento de la ley del propio `authoring.md`: catálogo
hardcoded → puntero.
28. **Sema tiene CUATRO canales en el código; la doctrina cuenta dos o tres.**
`grep "implements Channel"` sobre `src/uix/sema/chans/`:
`VisualChannel` · `SoundChannel` · `HapticChannel` · **`AnnounceChannel`**
(`announce.ts:64`). Y no es código muerto: opción del motor
(`engine.ts:88` — `announce?: true | false | AnnounceChannelOptions |
Channel`), instanciado en `engine.ts:327`, exportado en `exports.ts:74`.
Entró con `53b6f629f` (2026-07-08, trabajo real — procedencia comprobada).
Contra eso:
- `book-deviations.md` **D.8** lista «ARIA dinámico» en *«Lo que NO es
canal»* (*«Sólo un morfo lo necesita (Announce). Hacer canal añadiría
engine surface sin caso plural»*) y cierra: *«si en el futuro `Announce`
necesita ser pluggable… vale convertirlo en canal formal. **Hoy no.**»*
- `theming/channels.md` §2: *«sema's runtime channels, which are **3**»*.
- `CLAUDE.md`: *«sema executes `sound` + `haptic` **only**»*.
**Matiz que hay que conservar**: el *criterio* de D.8 sobrevive intacto —
announce no admite modulación por `intent.deltas`, y la cabecera del
propio `announce.ts` lo reconoce citando D.8: *«a channel by registration,
not a parametric-signature channel»*. Lo stale es la **disposición** («hoy
no», «no es canal», la lista de 2) y el conteo de `channels.md`. Curiosidad
que vale como lección: **el código cita como justificación un documento que
dice lo contrario de lo que el código hizo.**
29. **La tabla de holds de D.9 quedó stale contra D.12 — en el mismo
documento.** D.9 (líneas 486–495) publica como *«tabla canónica
`SEMA_HOLDS_BY_INTENT`»*: `commit.fulfill → hold: 'noticed'` y
`signal.loss → hold: 'noticed'`. `holds.ts:86` tiene
`fulfill: { hold: 'settled' }` y `holds.ts:103` `loss: { hold: 'brief' }`,
con el comentario de la corrección del 2026-07-06 — que es exactamente lo
que D.12 decisión 2 documenta 200 líneas más abajo. Quien lea D.9 como
canon (y su rótulo invita) se lleva los valores anteriores a la corrección.
30. **D.3 figura como pendiente cuando ya está ejecutado; D.2 sigue pendiente
de verdad.** §F.4 lista *«Cambio inmediato pendiente en proyecto: split de
`intentPolicy` en `intentRequirement` + `intentGuidance` (D.3)»* — pero
ambos ejes viven en `src/uix/sema/types.ts` (y `CLAUDE.md` ya los doctrina
como vigentes). En cambio §F.3 acierta: `emission` **no** existe en
`src/uix/morfo/types.ts`. Y `npm run morfo:vocabulary` (D.4) **sí** existe.
31. **El grep que `component-guide.md` manda ejecutar dos veces no escanea
nada.** Ítem 37 de la checklist y regla A34.1 documentan:
`grep -n "['\"]soma\.[a-z-]" src --include=!*.md`. Medido:
`--include='!*.md'` no es negación en grep — la orden devuelve **0 líneas,
exit 1, sin stderr**. Con `--exclude='*.md'` salen ≥5 coincidencias
(`accordion-provider:114`, `calendar-provider:190`, `form-auto-fields:460`,
`portal.svelte:38`…). Una verificación declarada **obligatoria** que
siempre «pasa» porque no mira nada. (Aparte: las coincidencias que sí
aparecen son namespaces de `logger`, no claves de traducción — el patrón,
además de inerte, es demasiado ancho.)
32. **Numeración rota de la checklist de `component-guide.md`.** El
frontmatter y `component-audit.md` la citan como «pasos 1–40»; hay **42
entradas** y la secuencia real es `1…33, 36, 38, 39, 40, 34, 35, 37, 38,
39` — los ítems **38 y 39 están duplicados** con contenidos distintos (38:
loop A35 / auditoría de topología DOM; 39: loop asíncrono A36 / smoke). Las
citas por número que sí resuelven (A32 → «items 34–35») siguen bien; las de
38/39 son ambiguas.
33. **Puntero roto en `component-guide.md` A36** (línea 1512): cita
`src/uix/soma/components/form/BUG-onchange-onblur-hang.md` *«para el
transcript diagnóstico completo»*. El fichero lo borró `2d35f4b3e`
(**2026-05-08**), cuyo propio asunto era *«prune obsolete audits + studies,
**refresh remaining references**»*. La cita la (re)escribió `62a62075f`
(2026-07-02) al migrar la guía al libro — dos meses **después** del
borrado. En `form/` sólo queda `README.md`.
34. **Censo hardcodeado: «≈140 morfos today» ×2** (líneas 728 y 1561 de
`component-guide.md`). Reales: **165**
(`ls src/uix/morfo/components/*.ts` sin tests). Tercera aparición de la
misma enfermedad, tras el «8 roles» (nº 21) y la tabla de servicios
(nº 22/27).
35. **`channels.md` §3 (línea 89) apunta a una sección de `CLAUDE.md` que no
existe**: *«The full canonical narrative lives in `CLAUDE.md` → "Sema: open
channel registry"»*. `grep` sobre `CLAUDE.md` y `AGENTS.md`: cero.
36. **Dos documentos actuales dan listas distintas de las mismas 5 superficies
con paleta viva.** `demo-authoring.md` §6: *«button, toggle, checkbox,
radio-group, switch (5/17 data-color surfaces)»*. `notes.md` §What's next:
*«button, checkbox, switch, radio-group, toggle-group»*. Difieren en
**toggle vs toggle-group**. El denominador «17» no casa con ningún censo
medido: 12 morfos declaran `data-color`, 46 recetas eidos seleccionan por
él, 82 componentes exponen prop `color`. → **NO VERIFICADO** cuál de las
dos listas es la correcta ni qué contaba el 17; lo verificado es que
discrepan entre sí.
### Lo que esta tanda CONFIRMA (no son hallazgos nuevos)
37. **El nº 13 queda cerrado por cuarta vía, y el nº 14 acotado.**
`gradient-finish.md` §9 (**D8**, 2026-07-15, rotulado «doctrine» en el
registro de decisiones) enuncia la misma regla que `reference.md` §39, con
el mismo modo de fallo medido en vivo: *«the morfo declares an attr only
when its driving prop crosses the soma boundary»*. Y es **comprobable por
componente con una línea**:
- `switch.svelte:41` → `color={colorAttrs.dataColor}` — **prop de soma** →
su morfo declara `data-color`. ✅
- `checkbox.svelte:45` → `data-color={colorAttrs.dataColor}` — **atributo
DOM crudo**, junto a `data-size`/`data-variant` → su morfo NO lo declara,
y es correcto. ✅
→ Los 46 componentes cuyas recetas seleccionan por `data-color` **no** son
46 infracciones: son la regla funcionando. La población del nº 14 son
exactamente los **12 morfos** que lo declaran.
38. **Refuerza el nº 23**: un TERCER documento declara superado el scope
`event:*` — `theming/notes.md` líneas 151–158, *«SUPERSEDED (2026-07-11,
DOC-4)… never exercised and is no longer the plan»*. Sólo `canon/tsc.md`
lo sigue anunciando sin nota.
## Hallazgos RETIRADOS (eran autocita)
- ~~«los tests de provider son convención, no guard»~~ — era la edición
revertida. El original afirma que el guard existe. **La pregunta sobre el
arnés de tests sigue abierta y no está resuelta por el corpus.**
→ **Cerrada el 2026-07-30 por el hallazgo nº 16**, pero entrando por la
puerta buena: el guard no existe *en el código*, y eso se comprueba con
`grep`, no citando un documento. El corpus dice lo contrario en dos sitios;
quien manda es el código.
- ~~«`soma-architecture.md` documenta una API fantasma que `overview.md`
desmiente»~~ — la contradicción la creó la edición revertida.
→ **Sigue retirada tal cual**: los dos documentos coinciden, no se
desmienten. Lo que sí se sostiene, y es otra cosa, es el **nº 15**: la API
que ambos documentan no existe en el código.
**El patrón que dejan los dos.** Una sesión anterior acertó en el hecho y
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 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. El canon + el núcleo restante~~ · ~~2. `theming/reference.md` entera~~ —
hechos en la sesión 3.
~~1. Las guías~~ · ~~2. `book-deviations`~~ · ~~3. el resto de theming~~ —
hechos en la sesión 4 (más `demo-authoring`, que no estaba inventariada).
1. **Siguiente tanda**: los 7 RFCs (1860) y **`spec/delegation-contract.md`**
(502, NORMATIVO). Después los cuatro cortos (`book-map` · `authoring` ·
`decisions.md` · `building-a-component`, 480).
2. Luego `theming/changelog.md` (1879) y el resto nunca inventariado
(`next-features` · `getting-started` · `comparison` ·
`design-text-effects`, 634).
3. Al leer `decisions.md` (88), **decidir el estatuto** de los 4 registros de
diseño que indexa y que están fuera del mapa (`design-connection` 1987 ·
`design-timer` 1540 · `design-session` 857 · `design-chat-block` 190). Si
entran, el corpus crece 4.574 L más.
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
si se puede citar documento + línea, y se ha comprobado que esa línea no la
escribió una sesión anterior.
6. Un analizador heurístico que no resuelve algo dice «no verificado»; no emite
un hallazgo.
7. **Paso 0 de cualquier relectura**: comprobar que el árbol no está
contaminado (`git diff <commit-sospechoso>^ HEAD -- <ficheros>`), y para una
línea concreta, `git log -L <n>,<n+1>:<fichero>`. Cuesta un comando y es lo
que separa la doctrina de la autocita.
## Lo que NO se ha hecho (y por qué)
Nada de lo anterior está arreglado — la regla 5 lo prohíbe hasta acabar la
lectura, y quedan ≈ 5.355 L del corpus mapeado. En concreto **no se ha
tocado**: el enum de `data-color` en los morfos (nº 14, además pide decisión de
usuario), los dos 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), la línea que tiene `docs:check` en rojo (nº 21), la
tabla de servicios de `active-app.md` (nº 22/27), la nota que le falta al scope
`event:` (nº 23/38), la tabla de alias de `CLAUDE.md` sin `$sound` (nº 26), el
conteo de canales de `channels.md` §2 + D.8 + `CLAUDE.md` (nº 28), la tabla de
holds de D.9 (nº 29), el §F.4 de `book-deviations` (nº 30), el grep inerte
(nº 31), la numeración duplicada de la checklist (nº 32), el puntero al
`BUG-…md` borrado (nº 33), el «≈140 morfos» (nº 34), el puntero a la sección
inexistente de `CLAUDE.md` (nº 35) ni las dos listas de superficies que
discrepan (nº 36).
De los veintitrés, **sólo el nº 14 pide decisión de usuario** (enum cerrado del
morfo vs. `color` abierto a 42 por diseño; con `morfo:check` cazándolo sólo si
una demo elige el valor; población acotada a 12 morfos por el nº 37). Los
demás son deriva doc↔código con un único arreglo evidente cada uno — salvo
**el nº 28**, que tiene dos salidas legítimas (actualizar D.8 + `channels.md` +
`CLAUDE.md` al hecho consumado, o revisar si `AnnounceChannel` debía existir) y
conviene plantear antes de tocar nada.
**Dos hallazgos son de método, no de contenido, y afectan a cómo se sigue
leyendo**: el nº 24 (el inventario estaba truncado — ya corregido arriba) y el
nº 25 (una lectura CADUCA cuando el código se mueve debajo; `sema.md` cambió el
mismo día). Conviene comprobar `wc -l` contra el inventario al arrancar cada
sesión: cuesta un comando y detecta la caducidad antes de citar.

Powered by TurnKey Linux.