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

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:

  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 §«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)

  1. §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.
  2. 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).
  3. ⚠️ 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.
  4. 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)

  1. 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).

  2. --* 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.

  3. 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.

  4. 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.

  1. 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.
  2. 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.
  3. 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.

  4. 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.

  5. 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.

  6. 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).

  7. 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).

  8. 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 §Fósiles.

  9. 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)

  1. 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.
  2. 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.

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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.
  7. 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.
  8. 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.)
  9. 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.
  10. 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.
  11. 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).
  12. 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.
  13. 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)

  1. 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.
  2. 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.