43 KiB
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) 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:
- Los 7 RFCs (1860) — la última tanda del plan original.
spec/delegation-contract.md(502) — NORMATIVO (RFC-2119, idsAG-n). Nunca estuvo en el inventario.book-map(201) ·authoring(136) ·decisions.md(88) ·building-a-component(55).theming/changelog.md(1879) — el documento sin leer más grande del corpus; es la crónica fechada detrás de las decisiones dereference.- 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 leerdecisions.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 queannounce.tslo 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
§«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
RELEERse 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 documentaprovider.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 contrasoma-architecture.mdque 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 |
⚠️ 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.mdera 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:
- «Only composition roots create shared services» —
architecture/active-uix.md§Ownership, regla 1: «morfo,soma,sema,eidosand components never createdom,langs,prefs,format,clipboardor equivalents: they receive them fromActiveUix».eidos.mdla repite («ActiveEidos creates no shared services»). Las dos puertas soncreateActiveUix/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.mdlíneas 61–63). La advertencia de RELEER que había aquí queda retirada. - Overlays:
sequence: 'post', no'pre'—sema.md(LIMPIO), nota destacada: un evento de aparición cuyo provider fijaopenen el HANDLER debe declarar'post'; con'pre'el hold de ~240 ms gatea el montaje. intentRationale—sema.md(LIMPIO),BK-FRAME-NO-INTENT: una familia estructural (contact/emerge/shift/sustain/delegate) que declare intent no neutro debe justificarlo enMorfoEventSemantic.intentRationaleovalidateMorfola rechaza.handleestá exento.- El scheduler de los holds —
sema.md(LIMPIO): los holds van poruix.timers.schedule(semaDelay,sema/timers.ts), y sólo caen asetTimeout«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)
- §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 treskind. 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. emit: 'value'es legítimo (línea 436): losdata-*no-enum van por defecto aemit: 'presence';emit: 'value'es para atributos que llevan un valor real (data-value,data-min,data-max).- ⚠️ 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 todata-_*». Más el incidente 2026-05-20 (línea 868): «A component is not done if the provider or demo emits requireddata-*that Morfo does not declare». La sesión revertida concluyó quedata-colorNO 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 leereidos.mdcompleto ytheming/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. 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)
-
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-colorNO aparece. → Esto es la mitad de la respuesta a la pregunta aparcada (nº 7): la regla demorfo.mdlí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-sizees el precedente concreto y verificable (switch.csslo usa en 4 reglas y no está en el morfo de switch). → Falta la otra mitad: sidata-colorpertenece a esa categoría. La lista de la línea 489 es ilustrativa, no exhaustiva, y no lo incluye. La respuesta está entheming/reference.md§25 («Color model: palette + roles + intents»), que el propioeidos.mdseñ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). -
--*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. -
eidos-onlyes una clasificación VÁLIDA, no un error (§«Selector-drift defense», líneas 850–858).eidos-lintclasifica cada selector en morfo-backed / eidos-only / invalid, y define eidos-only como: «the marker is there, but at least onedata-*is not declared in the morfo. Valid by convention (visual tokens likedata-variant,data-sizecome from the wrapper)». Sólo invalid (attr declarado con valor fuera del enum) es bug. -
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-colorestampado por el wrapper y ausente del morfo es legítimo (eidos-only), y que undata-colordeclarado en el morfo sólo por un eje visual es podable. Pero sigue faltandotheming/reference.md§25, queeidos.mddesigna 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.
-
PREGUNTA APARCADA (nº 7 / 9 / 12) — CERRADA:
data-colorSÍ va en el morfo. Tres evidencias independientes, ninguna autocita:architecture/active-architecture.mdlínea 565, tabla §6 «DOM attributes — the universal channel»:data-color="primary"· escribedom.apply(effect) · lee Eidos. Es la misma casilla quedata-stateydata-intent, NO la de los attrs del wrapper. Provenance comprobada congit log -L 565,566: entró con la traducción8668e117bdesde el doc castellano, y ahí lo escribiód4dfdaffa— muy anterior a cualquier sesión de agente.guides/completion-checklist.mdE-3.5: «All visual props (size,variant,color,radius) map todata-{prop}="value"on the root»; más R-3.1, R-3.3 («data-colorreflects 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 entradadatareal —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, …) perodata-colorno 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 exposingcoloras a prop → must declaredata-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 asignadata-color.valuesa 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-gradientis 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 emiteundefinedymergeProps(restProps, state.props)pisa el sello del wrapper. → Con eso la frontera queda nítida y comprobable:colorcruza la frontera de soma (los 12 morfos lo resuelven conv.propRef('color')) → va al morfo.variant/size/gradientno la cruzan → los sella el wrapper. No es una convención: es de dónde se resuelve el valor.
-
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»): «coloracepta el sistema completo — rol / intent / 33 escalas donantes / valor CSS crudo (ComponentColorProp) — en TODOS los componentes, sin excepciones», con guard estructural enrecipe-css-contract.test.ts. El tipo es abierto:ComponentColorProp = ComponentColor | (string & {})(eidos/lib/types.ts:216). Pero el morfo deswitchdeclaradata-colorcon 6 valores cerrados (['primary','secondary','neutral','affirm','risk','threat']), yscripts/morfo-check.ts:167falla cuando un attr convaluesemite algo fuera del conjunto. Esa es la contradicción que merece decisión del usuario, no la de sidata-colorva 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:
eidos/lib/component-color.ts→CANONICAL_COLOR=COLOR_ROLES∪PALETTE_SCALES= 42 nombres.resolveComponentColor('teal')devuelvedataColor: 'teal'(sólo un color CSS crudo se desvía adata-color-custom+--color-custom).eidos/components/switch/switch.svelte:42pasa esedataColoral propcolorde soma.soma/components/switch/switch-provider.svelte.ts:88–94lo devuelve verbatim (sólo intercepta el intent evaluativo y el caso custom).- El morfo declara
data-colorcon 6 valores. →<Switch color="teal">emitedata-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:checksó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.
-
provider.commitState()/provider.emitEvent()no existen en el código.grep -rn "commitState\|emitEvent"sobre todo el repo (.ts,.svelte,.js, sinnode_modules) → cero coincidencias. Los documentan dos docs, en originales verificados:architecture/overview.mdlíneas 320–334 («Three Soma scenarios») yarchitecture/soma-architecture.mdlíneas 269–293 («Three operations covering every scenario», con el cuerpoasync 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. -
El guard de tests de provider NO existe — la pregunta que quedó abierta, ahora cerrada por la puerta buena.
NO_MISSING_PROVIDER_TESTSaparece en dos ficheros y los dos son docs (soma-architecture.mdydocs/old-deprecated/fable_audit.md); no hay comprobación de existencia de*.test.tsenscripts/, no hay invariante de cobertura ensrc/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 afirmansoma-architecture.md§6 líneas 495–497 («the guard returnsNO_MISSING_PROVIDER_TESTS») ytesting-and-tooling.mdlí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. -
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) comotoClassString, import fuera.soma-architecture.md§12 línea 850 sigue diciendo «clsxis imported inprops/props.tswithout 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 desoma.md: el flattener propio, sin import.soma-architecture.mdestá stale. -
packs.mdyglossary.mddescriben un futuro que ya ocurrió.packs.mdlíneas 78–79: «WhenAuralands, the scene runtime is promoted to auix.sceneservice; until then it stays a standalone factory»;glossary.mdlínea 34: Aura «Not built yet». En el código:uix.scenees servicio (active-uix/active-uix.svelte.ts:152–178,createEngineScene+ lectura deapp.sceneen attach) y Aura existe en las tres capas (morfo/components/aura.ts,soma/components/aura,eidos/components/aura). -
CANON.mdapunta a un libro que no está. El frontmatter (líneas 7–9) declarasources.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) citaDisenando_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). -
package.jsonconserva el entrygenerate:contracts-docsy el scriptscripts/generate-contracts-docs.tsya no existe.testing-and-tooling.mdlíneas 76–77 documenta el borrado; el entry huérfano sigue. Ya estaba fichado como pendiente menor enCONTINUE-docs-corpus.md§Fósiles. -
npm run docs:checklleva 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:c39170abbarreglaba esa línea (the 8 roles→the canonical color roles, o sea aplicaba la ley «enlaza el const, no copies el número») y3097cfcb6la 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)
active-app.mdenumera 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. Engit ls-files src/arts/active-app/service-factories/hay 15: faltanagent.ts,motion.tsyscene.tsen 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.canon/tsc.mdanuncia un scope que dos docs declaran superado. Su tabla «Available scopes» listaevent:${v}→ «Motion token bound to a perceptual signal» sin nota alguna. Peroreference.md§13 se titula «Sema integration (event:*scope)» y su cuerpo entero es «⚠️ Superseded», ymotion.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.
- El inventario de este mismo fichero estaba incompleto — y faltaban dos
documentos que el corpus declara vinculantes. Censo de
git ls-filessobredocs/(sinprocess/,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 establesAG-n).theming/changelog.md(1879) — el mayor documento del corpus sin leer. → Leída yademo-authoringen esta sesión. El inventario de arriba queda corregido; el arranque en frío ya no manda leer un corpus truncado.
sema.mdse 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ó hoy6920684d0(«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.- La tabla de alias de
CLAUDE.md:96no incluye$sound. El alias existe en la fuente de verdad (vite.config.ts:35) y ensvelte.config.js:41desde el mismo commit de hoy. La tabla enumera 24 artes a mano; van 25. - Amplía el nº 22 —
active-app.mddocumenta 12 de 16 factories.git ls-files src/arts/active-app/service-factories/(sinindex.ts) da 16; faltan en la tabla §«Available services» y en el árbol §«Filesystem layout»:agent,motion,sceney —desde hoy—sound.src/arts/README.mdsí se actualizó en el mismo pase;active-app.mdno. Es el argumento de la ley del propioauthoring.md: catálogo hardcoded → puntero. - Sema tiene CUATRO canales en el código; la doctrina cuenta dos o tres.
grep "implements Channel"sobresrc/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 enengine.ts:327, exportado enexports.ts:74. Entró con53b6f629f(2026-07-08, trabajo real — procedencia comprobada). Contra eso:book-deviations.mdD.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 futuroAnnouncenecesita ser pluggable… vale convertirlo en canal formal. Hoy no.»theming/channels.md§2: «sema's runtime channels, which are 3».CLAUDE.md: «sema executessound+hapticonly». Matiz que hay que conservar: el criterio de D.8 sobrevive intacto — announce no admite modulación porintent.deltas, y la cabecera del propioannounce.tslo 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 dechannels.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.
- 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'ysignal.loss → hold: 'noticed'.holds.ts:86tienefulfill: { hold: 'settled' }yholds.ts:103loss: { 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. - 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
intentPolicyenintentRequirement+intentGuidance(D.3)» — pero ambos ejes viven ensrc/uix/sema/types.ts(yCLAUDE.mdya los doctrina como vigentes). En cambio §F.3 acierta:emissionno existe ensrc/uix/morfo/types.ts. Ynpm run morfo:vocabulary(D.4) sí existe. - El grep que
component-guide.mdmanda 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 delogger, no claves de traducción — el patrón, además de inerte, es demasiado ancho.) - Numeración rota de la checklist de
component-guide.md. El frontmatter ycomponent-audit.mdla citan como «pasos 1–40»; hay 42 entradas y la secuencia real es1…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. - Puntero roto en
component-guide.mdA36 (línea 1512): citasrc/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. Enform/sólo quedaREADME.md. - Censo hardcodeado: «≈140 morfos today» ×2 (líneas 728 y 1561 de
component-guide.md). Reales: 165 (ls src/uix/morfo/components/*.tssin tests). Tercera aparición de la misma enfermedad, tras el «8 roles» (nº 21) y la tabla de servicios (nº 22/27). channels.md§3 (línea 89) apunta a una sección deCLAUDE.mdque no existe: «The full canonical narrative lives inCLAUDE.md→ "Sema: open channel registry"».grepsobreCLAUDE.mdyAGENTS.md: cero.- 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 declarandata-color, 46 recetas eidos seleccionan por él, 82 componentes exponen propcolor. → 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)
- 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 quereference.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 declaradata-color. ✅checkbox.svelte:45→data-color={colorAttrs.dataColor}— atributo DOM crudo, junto adata-size/data-variant→ su morfo NO lo declara, y es correcto. ✅ → Los 46 componentes cuyas recetas seleccionan pordata-colorno son 46 infracciones: son la regla funcionando. La población del nº 14 son exactamente los 12 morfos que lo declaran.
- Refuerza el nº 23: un TERCER documento declara superado el scope
event:*—theming/notes.mdlíneas 151–158, «SUPERSEDED (2026-07-11, DOC-4)… never exercised and is no longer the plan». Sólocanon/tsc.mdlo 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 congrep, no citando un documento. El corpus dice lo contrario en dos sitios; quien manda es el código.«— 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.soma-architecture.mddocumenta una API fantasma queoverview.mddesmiente»
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 · RELEER2. — hechos.morfo.md completo
1. El canon + el núcleo restante · 2. —
hechos en la sesión 3.theming/reference.md entera
1. Las guías · 2. · book-deviations3. el resto de theming —
hechos en la sesión 4 (más demo-authoring, que no estaba inventariada).
- 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). - Luego
theming/changelog.md(1879) y el resto nunca inventariado (next-features·getting-started·comparison·design-text-effects, 634). - 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-connection1987 ·design-timer1540 ·design-session857 ·design-chat-block190). Si entran, el corpus crece 4.574 L más. - Actualizar este fichero al final de cada sesión de lectura: estado por documento y línea donde se paró.
- 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.
- Un analizador heurístico que no resuelve algo dice «no verificado»; no emite un hallazgo.
- 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.