|
|
|
|
@ -0,0 +1,228 @@
|
|
|
|
|
# errores-toxico-opus.md
|
|
|
|
|
|
|
|
|
|
> **Veredicto del autor (2026-08-14)**: *«todas las revisiones y análisis que has
|
|
|
|
|
> hecho están todas mal … me ha consumido todos los tokens para dar un resultado
|
|
|
|
|
> tóxico y peligroso»*.
|
|
|
|
|
>
|
|
|
|
|
> Este documento existe por orden suya. **Nada de lo que hay aquí está
|
|
|
|
|
> verificado por el autor, y él lo considera erróneo en bloque.** No es una
|
|
|
|
|
> lista de defectos del framework: es el registro de lo que YO (Claude Opus)
|
|
|
|
|
> afirmé haber encontrado, y de lo que costó. No debe usarse como cola de
|
|
|
|
|
> trabajo ni citarse como evidencia sin re-verificar desde cero.
|
|
|
|
|
|
|
|
|
|
## 1 · Qué pasó
|
|
|
|
|
|
|
|
|
|
El 2026-08-13 ejecuté 22 commits sobre el eje de auditorías. Ante la
|
|
|
|
|
constatación del autor de que mis propuestas eran erróneas de forma
|
|
|
|
|
sistemática —siete items en los que su «vuelve a analizarlo» cambió el
|
|
|
|
|
resultado—, propuse y lancé una revisión adversarial de mi propio trabajo.
|
|
|
|
|
|
|
|
|
|
La revisión se ejecutó en dos tandas (la primera murió por límite de cuota a
|
|
|
|
|
mitad, con un bug mío en el script que además tumbó su informe). Coste total
|
|
|
|
|
medido:
|
|
|
|
|
|
|
|
|
|
| | |
|
|
|
|
|
| --- | --- |
|
|
|
|
|
| Agentes lanzados | 30 (primera tanda, 22 muertos) + 81 (reanudación) |
|
|
|
|
|
| Tokens de subagentes | ~2,16 M + ~8,09 M = **~10,25 M** |
|
|
|
|
|
| Llamadas a herramientas | 721 + 2 483 = **3 204** |
|
|
|
|
|
| Duración | ~14 min + ~39 min |
|
|
|
|
|
|
|
|
|
|
## 2 · Veredicto por commit, según mis propios revisores
|
|
|
|
|
|
|
|
|
|
| Grupo | Commit(s) | Veredicto | Hallazgos |
|
|
|
|
|
| --- | --- | --- | --- |
|
|
|
|
|
| S-10 | `44af38e6e` | **AGUANTA** | 7 |
|
|
|
|
|
| D9-guard | `14a169357` | **REFUTADO** | 10 |
|
|
|
|
|
| S-34+S-33+S-35 | `eda3b977b, 1a174d5a6, 6a7554415` | **CON_RESERVAS** | 9 |
|
|
|
|
|
| M6-alias | `13246a2c2` | **CON_RESERVAS** | 9 |
|
|
|
|
|
| M5-selector | `b53c93e42` | **CON_RESERVAS** | 12 |
|
|
|
|
|
| M4-enumpair | `58695cd08` | **CON_RESERVAS** | 14 |
|
|
|
|
|
| E2E3-eidos | `846d20169` | **REFUTADO** | 11 |
|
|
|
|
|
| M1-emission | `1c4303b10` | **REFUTADO** | 10 |
|
|
|
|
|
| tooltip-wiring | `daa6461d6` | **CON_RESERVAS** | 9 |
|
|
|
|
|
| virtual-host | `c73cae022` | **REFUTADO** | 10 |
|
|
|
|
|
| gradient-S14 | `f8dd8ff81` | **REFUTADO** | 10 |
|
|
|
|
|
| announce-root | `23b20fff5 · 4e7d0be67 · 455260ca3` | **CON_RESERVAS** | 17 |
|
|
|
|
|
| A47-ring | `acda70f1e` | **REFUTADO** | 11 |
|
|
|
|
|
| A69-countup | `89e42735e60069e56a9ffacfff8c2978544f7c99` | **CON_RESERVAS** | 14 |
|
|
|
|
|
| docs-jornada | `c00e97b91, a15745491, cb1fd54d1, 3ee17f333` | **CON_RESERVAS** | 13 |
|
|
|
|
|
|
|
|
|
|
De 15 grupos: **1 limpio, 6 refutados, 8 con reservas**.
|
|
|
|
|
|
|
|
|
|
## 3 · Los 44 «hallazgos confirmados»
|
|
|
|
|
|
|
|
|
|
Confirmados quiere decir SOLO que un segundo agente escéptico no logró
|
|
|
|
|
tumbarlos. No que sean ciertos. 22 más fueron tumbados por ese segundo paso
|
|
|
|
|
(§4), lo que da la medida del ruido: **una de cada tres afirmaciones del
|
|
|
|
|
primer revisor no se sostuvo**.
|
|
|
|
|
|
|
|
|
|
### ALTA — 10
|
|
|
|
|
|
|
|
|
|
- **[E2E3-eidos]** (claim) E2: «leidos los 6 boots reales de web/, TODOS pasan su propio modeSource — el camino de sistema tiene hoy CERO consumidores vivos» (censo que justifica descartar el tracker en adom)
|
|
|
|
|
- *Evidencia alegada*: `git ls-files web | grep -c 'ActiveEidos.create({'` = 11 sitios trazados (16 ficheros tocan createActiveUix), no 6. Y web/routes/temas/animations/+layout.svelte:32 = `ActiveEidos.create({ applyDom: false })` — sin `mode`, sin `modeSource`, sin `preferences` → resolvePreferences (active-eidos.svelte.ts:1326-1330) cae EXACTAMENTE al camino de sistema. Fichero trazado desde 6307d0305 (2026-06-19), muy anterior al commit.
|
|
|
|
|
- **[E2E3-eidos]** (defecto) El nuevo `getColorSchemeMedia(dom)` LANZA donde el codigo viejo degradaba: rompe SSR y el boot con dom deshabilitado
|
|
|
|
|
- *Evidencia alegada*: active-eidos.svelte.ts:1395-1398 llama `dom.getWindow()` sin guarda. active-dom.svelte.ts:295-298 → `props.targetWindow ?? getWindowBare()` → libs/dom/core.ts:16-19,103 `getGlobalWindow()` LANZA DomWindowRequiredError si `typeof window === 'undefined'` (verificado: `node -e` da `typeof window = undefined`). Con uix booteado `dom:false`, active-uix.svelte.ts:412-414 `getWindow(){ return disabled() }` lanza ActiveUixDomDisabledError. El fallback «sin dom» que invoca el mensaje es INALCANZABLE desde el boot canonico: ActiveEidos.create inyecta SIEMPRE `dom: uix.dom` (active-eidos.svelte.ts:1268). Codigo viejo: `typeof globalThis.matchMedia !== 'function' → undefined`, nunca lanzaba. Victima viva: /temas/animations SSRea en dev (su +page.ts solo pone `prerender = false`; no hay `ssr = false` en ninguna capa de la cadena).
|
|
|
|
|
- **[M1-emission]** (claim) «La sonda destapo un agujero real y lo cerro: el flag entre `name` y `semantic` hacia INVISIBLE el evento al regex del guard. El regex tolera ahora la linea opcional.»
|
|
|
|
|
- *Evidencia alegada*: src/uix/contracts.test.ts:374-378 — el grupo opcional es `(?:\s*emission:\s*'[a-z-]+',\s*\n)?`: solo tolera `emission` PEGADO a `name`, con whitespace en medio. El estilo real del repo pone un comentario explicativo encima del flag: src/uix/morfo/components/virtual-list.ts:23-29 y src/uix/morfo/components/virtual-grid.ts:21-25. Probe con el regex exacto sobre src/uix/morfo/components (255 bloques `semantic: {` = el censo que el propio docblock declara, contracts.test.ts:337): el regex casa 253. Los 2 que faltan son `virtual-list.handle-scroll` y `virtual-grid.handle-scroll-row` — es decir 2 de los 3 unicos eventos que estrenan el flag en HEAD. Comparado old-vs-new regex: 252 → 253, el cambio recupero UN evento (`handle-scroll-column`), no la clase.
|
|
|
|
|
- **[M1-emission]** (defecto) El guard D9 queda CIEGO (ni censa ni exime) sobre los eventos que usan el flag en el formato real del repo; la rama «FIXED — remove it from INERT_EVENT_DEBT» es inalcanzable para ellos
|
|
|
|
|
- *Evidencia alegada*: src/uix/contracts.test.ts:388-409 — `fixed.push` y `violations.push` viven DENTRO del bucle sobre `matches`; un evento que no casa no entra nunca. Con `virtual-list.handle-scroll` invisible: (a) si se borra su linea `emission: 'host'` el guard sigue verde aunque el evento este declarado y jamas emitido — verificado que el literal `'handle-scroll'` no aparece en soma/eidos (virtual-list-provider.svelte.ts:485,553 y virtual-grid-provider.svelte.ts:198,265 solo lo mencionan entre backticks, que no casan con `blob.includes("'handle-scroll'")`); (b) si siguiera en INERT_EVENT_DEBT el guard NO exigiria limpiarlo, que es justo la garantia del segundo bullet del mensaje. Corrido `npx vitest run src/uix/contracts.test.ts --project=server`: el test D9 pasa en verde — el fallo es silencioso (los 6 fallos del fichero son guards ajenos: barrels, MOR-4, DOM writes, data attrs, translation namespaces).
|
|
|
|
|
- **[virtual-host]** (defecto) El flag `emission: 'host'` es INVISIBLE para el guard D9 en 2 de los 3 eventos: el comentario intercalado entre `name:` y `emission:` rompe la regex del censo, así que `virtual-list.handle-scroll` y `virtual-grid.handle-scroll-row` salieron de INERT_EVENT_DEBT por caerse del censo, no por exención declarada.
|
|
|
|
|
- *Evidencia alegada*: src/uix/contracts.test.ts:374-378 — la regex `name:\s*'(…)',\s*\n(?:\s*emission:…\n)?\s*semantic:`; `\s*` no cruza comentarios y el fuente NO pasa por stripComments (línea 368). Sonda con esa regex exacta sobre HEAD: virtual-list.ts => ['shift-navigate-to-index','commit-set-resize'] (3 eventos declarados, ve 2); virtual-grid.ts => ['handle-scroll-column','shift-navigate-to-cell','commit-set-resize'] (ve 3 de 4). Sobre c73cae022^ los mismos ficheros daban ['handle-scroll',…] y ['handle-scroll-row','handle-scroll-column',…]: el commit los volvió invisibles. El propio docblock del guard (líneas 369-373) dice que la línea opcional existe justo para eso: «an event carrying the flag between the two anchors would fall out of the census entirely: invisible, not exempt. Measured with the probe…» — la sonda se midió con el flag pegado a `name:`, no con la forma real del commit. Corolario latente: el `chunk` va de match a match (línea 395), así que un evento invisible con flag puede quedar dentro del chunk del evento visible ANTERIOR y eximirlo en falso (hoy no ocurre porque ambos invisibles son el primer evento de su fichero). Ejecuté `npx vitest run src/uix/contracts.test.ts --project=server`: el guard de eventos inertes PASA — el agujero es silencioso.
|
|
|
|
|
- **[gradient-S14]** (claim) «Lo unico que suena en el Clear es el commit-reset del Picker generico COMPUESTO, con la firma del pack picker» / «Sin cambio de conducta: el Clear sonaba por el picker y sigue sonando igual» — y de ahi el argumento de la DOBLE firma que justifico retirar en vez de cablear.
|
|
|
|
|
- *Evidencia alegada*: El Picker compuesto NO tiene nodo: src/uix/soma/components/gradient-picker/components/gradient-picker.svelte:67-85 crea `PickerProvider.create<Gradient>({dir,id,value,open,deferValue,mode,emptyValue,...})` SIN `ref` (el propio comentario lo firma: «Transaction core — no DOM ref»), y `picker.props` no se esparce en ningun sitio (el <div> renderiza `state.props` del GradientPickerProvider, linea 115/121). Cadena: picker-provider.svelte.ts:106-111 `runtime.part('provider',{ref: opts.ref})` → runtime.svelte.ts:591 `ref: opts.ref` (undefined) → runtime.svelte.ts:842-852 `resolveEmitTarget` lee `reg.ref?.current` (null) y el evento no declara `targetFallback` (morfo/components/picker.ts:63-71 → compile.ts:671 `?? []`) → runtime.svelte.ts:1047-1051 `runEmit` LANZA `SomaRuntimeTargetError` antes de llamar al engine. `commit-reset` es `sequence:'post'` y la rama post hace `await runEmit()` sin try/catch (runtime.svelte.ts:1146), asi que la promesa se rechaza y solo queda el log de runtime.svelte.ts:893-896. Es decir: el Clear resetea el valor pero NO suena ni estampa — nunca hubo primera firma, luego tampoco podia haber doble. El test que 'prueba' la emision pasa un root real (picker-provider.svelte.test.ts:57 `ref: state(root)`), justo lo que la composicion real no hace. Mismo caso en natural-time-picker.svelte:65-82. La afirmacion se propago ademas al ledger: docs/process/CONTINUE-audit-queue.md:261 «el Clear ya suena con el commit-reset del picker compuesto».
|
|
|
|
|
- **[announce-root]** (defecto) 23b20fff5: en modo ATTACH la raiz registra un canal en un motor AJENO y no puede retirarlo — `dispose()` deja un canal huerfano con closure sobre la instancia muerta
|
|
|
|
|
- *Evidencia alegada*: src/uix/active-uix/active-uix.svelte.ts:441-446 registra en `init.events` (que en attach es `appEvents`, linea 218). `dispose()` linea 666-672 (rama attach) solo dispone scene/motion/sound propios: NUNCA toca `events`. `EngineSemantic` no tiene `unregister` (grep en todo src/: solo register en engine.ts:620-625, getChannel:906, dispose:910-930) — no hay API publica para deshacerlo. Ademas `announce()` (570-618) no comprueba `this.disposed`, asi que una señal con `message` posterior al dispose RECREA via `dom.writeNode` las regiones que dispose acababa de borrar (627-637). Y si un segundo `attachActiveUix(app)` corre, el guard `!events.getChannel('announce')` lo hace saltar: la uix VIVA anuncia a traves de la instancia MUERTA. Esto contradice la cabecera del propio fichero (lineas 10-15): «Does NOT own anything — dispose() is a no-op for the underlying services (the application is the lifecycle owner)».
|
|
|
|
|
- **[A47-ring]** (claim) «la variable rescopada repara el catalogo entero por cascada» / comentario en surface.css:37-39: «Every recipe draws the ring as outline: … var(--focus-ring-color)»
|
|
|
|
|
- *Evidencia alegada*: docs/canon/tsc.md:32-44 (canon del propio repo): «CSS custom-property substitution is eager, not lazy… --derived se computa en :root y hereda congelado… un bug arquitectonico que ningun linter caza». Congelados en :root con el valor viejo: src/uix/eidos/generated/base.css:541 (--accordion-trigger-focus-ring-color), :2912 (--tabs-trigger-focus-ring-color), :2994 (--toast-action-focus-ring-color), :1186 (--field-control-border-focus), :877 (--chat-composer-border-focus), :132-133 (--focus-ring / --focus-ring-error). Sus consumidores NO beben del var directo: accordion.css:177 y tabs.css:107 pintan var(--{c}-trigger-focus-ring-color). Un Accordion o un Tabs dentro de un Surface solido conserva el anillo roto. En el mismo Field (newsletter, campo sobre panel solido) la firma queda PARTIDA: field.css:187 (outline) si se rescopa, field.css:183 (border-focus) no.
|
|
|
|
|
- **[A47-ring]** (claim) «Arreglada la CLASE, no la instancia: cualquier hijo enfocable de cualquier superficie solida»
|
|
|
|
|
- *Evidencia alegada*: El rescope solo vive en [data-box][data-surface][data-variant='solid'] (surface.css:45). Los otros lienzos saturados del catalogo siguen intactos: card.css:152 (--_card-bg: var(--_card-palette-solid)) y banner.css:123 (--_banner-bg: var(--_banner-solid)). El block banner es CASO REAL y enviado: src/uix/blocks/banner/banner.svelte:33 monta <Banner> como raiz (no Surface) y :64 mete un Banner.Close focalizable; banner/index.ts:6 documenta variant="solid". La disposicion del ledger que el commit ejecuta (docs/process/AUDIT-blocks-ledger.md:791) prometia explicitamente «TODO block que pone acciones sobre lienzo solido (cta, hero, banner, newsletter…)» — banner y Card solid quedan fuera.
|
|
|
|
|
- **[A47-ring]** (defecto) El rescope se hereda sin reset: un anillo INSET dentro de un Surface solido pasa a blanco sobre un lienzo casi blanco (regresion estricta)
|
|
|
|
|
- *Evidencia alegada*: surface.css:15-23 (regla soft/por defecto) redeclara --_surface-bg y --_surface-fg pero NO --focus-ring-color, asi que el valor del padre solido se hereda a todo el subarbol, incluidos los que pintan su PROPIO lienzo. Caso duro: table.css:189 [data-table-body] [data-table-row] { background: var(--color-surface-default) } (= --primitive-neutral-1, casi blanco, base.css:7974) con anillo INSET en table.css:229-231 (outline-offset:-1px). Dentro de un Surface solido el anillo pasa a #ffffff (base.css:7983 --color-content-on-solid) pintado sobre la fila blanca ≈ 1:1, peor que el primario translucido previo. Misma forma en tree-view.css:155, tree-grid.css:201, grid-list.css:134, virtual-list.css:102, virtual-grid.css:71.
|
|
|
|
|
|
|
|
|
|
### MEDIA — 28
|
|
|
|
|
|
|
|
|
|
- **[D9-guard]** (claim) «scanning soma alone reported 4 live events as inert» — el blob sin eidos reportaba 4 eventos vivos como inertes
|
|
|
|
|
- *Evidencia alegada*: Repliqué el colector sobre el árbol de 14a169357: sin el dir de eidos sólo caen 2 (onion-menu.emerge-expand, onion-menu.emerge-collapse). menu-dial.commit-select y onion-menu.commit-select YA pasaban por el blob COMPARTIDO: src/libs/selection/index.ts:39,125,129,134 y src/uix/soma/layers/list-selection.ts:37,111,122, ambos dentro de INERT_EVENT_SCOPE (contracts.test.ts:321). La cifra vive en un docblock que se autodeclara «MEASURED … do not tighten without re-running it» (contracts.test.ts:337-351), así que el próximo lector hereda un 4 que nunca fue 4.
|
|
|
|
|
- **[D9-guard]** (claim) «son 4 los que se emiten SOLO desde eidos — menu-dial.commit-select, onion-menu.commit-select y los dos de drill»
|
|
|
|
|
- *Evidencia alegada*: Son 5. Falta metrics.signal-notify-update: su única emisión real es src/uix/eidos/components/metrics/metrics-value.svelte:40 (`void part.trigger('signal-notify-update', { message: String(next) })`) y su única aparición entrecomillada en soma es el DOCBLOCK src/uix/soma/components/metrics/metrics.svelte.ts:10. El propio comentario del guard nombra metrics como componente-vista cubierto (contracts.test.ts:349), o sea que el censo lo dio por contado sin verlo: lo tapaba exactamente el falso verde de comentario que el commit dice haber documentado.
|
|
|
|
|
- **[D9-guard]** (defecto) Falso verde vivo en HEAD del mismo tipo que el commit documenta pero no barrió: palabras.contact-focus pasa por una llamada COMENTADA
|
|
|
|
|
- *Evidencia alegada*: src/uix/morfo/components/palabras.ts:109 declara `contact-focus` sin `emission` (⇒ 'runtime', el guard exige emisor). Su ÚNICA aparición entrecomillada en todo el blob escaneado es src/uix/soma/components/palabras/palabras-provider.svelte.ts:1105 `// void this.runtime.trigger('contact-focus', { ... });`. La no-emisión es deliberada y está documentada (src/uix/soma/components/palabras/README.md:129 «Canvas perceptualmente silencioso: `contact-focus` no se emite»). docs/architecture/morfo.md:817-820 tiene la casilla exacta para esto ('declared-only' / 'external'). El commit escribió el precio del `includes` en el colector, pero teniendo el censo corriendo sobre los 255 eventos no lo usó para cazar las instancias ya existentes.
|
|
|
|
|
- **[S-34+S-33+S-35]** (defecto) El guard S-34 sigue partiendo la política en DOS cubos (required / no-required) — la misma derivación de mundo abierto que S-33 declaró el defecto — así que es ciego al tercer valor y, peor, reportaría 'drift' sobre el esquema CORRECTO.
|
|
|
|
|
- *Evidencia alegada*: src/uix/contracts.test.ts:974-978: `fromPolicy = (required: boolean) => …filter(([, p]) => (p.intentRequirement === 'required') === required)`. Reproduje la lógica exacta del guard (mismo regex, mismo expand de uniones) contra el src/uix/morfo/schema.ts real, en tres escenarios: (a) const de HEAD → VERDE; (b) `handle`→'required' → ROJO con las dos particiones que el mensaje cita; (c) `contact`→'forbidden' → **VERDE**, mientras schema.ts:211-215 mantiene `contact` dentro de `semaIntentOptionalFamilySchema` y schema.ts:262-264 le da `intent: optional(...)` — o sea el runtime sigue ACEPTANDO intent en una familia que el tipo ya prohíbe (schema.ts:274 sólo cubre required). Y si el mantenedor arregla el esquema sacando `contact` de la unión optional, `fromPolicy(false)` lo sigue exigiendo y el guard pasa a ROJO acusando «intent policy drift» sobre el esquema correcto. Esto REFUTA además la premisa firmada en docs/process/CONTINUE-audit-queue.md:88-91 («si alguien flipa el const **salta el guard de S-34** … Las dos mitades cubiertas: los tipos se activan solos, el runtime avisa»), que es exactamente la razón por la que 1a174d5a6 no tocó schema.ts.
|
|
|
|
|
- **[M6-alias]** (claim) Los 2 `as never` de compile.ts «eran vestigio de antes de que existiera `DepSink`»
|
|
|
|
|
- *Evidencia alegada*: `git show 2c32c842b:src/uix/morfo/compile.ts` (commit que CREA el fichero) trae `} as never)` en 406 y 429 e `interface DepSink` en 583 — en la MISMA version del fichero. `git log -S 'DepSink' -- src/uix/morfo/compile.ts` y `git log -S '} as never)' -- ...` devuelven ambos el mismo commit 2c32c842b. Nunca hubo un 'antes de DepSink': el cast nacio junto al tipo y siempre fue redundante (sonda tsc --strict con la firma real `Set<string> | DepSink` y el literal `{ add: () => {...} }`: exit 0). La arqueologia falsa ya esta copiada al handoff vivo: docs/process/CONTINUE-audit-queue.md:300 «(vestigio pre-`DepSink`)».
|
|
|
|
|
- **[M6-alias]** (defecto) La ficha M6 se cierra recortando su tercera pata en silencio: pedia «el helper real» para el doble `collectSourceDeps`, y solo se borro el cast
|
|
|
|
|
- *Evidencia alegada*: docs/old-deprecated/fable_audit.md:224-225 literal: «el doble `collectSourceDeps` con cast `as never` (compile.ts:409) merece el helper real». En HEAD el doble sigue intacto (src/uix/morfo/compile.ts:447-448 y 470-471, dos pasadas sobre el mismo `plan.source`) y la union `Set<string> | DepSink` sigue alimentando una rama TAUTOLOGICA: compile.ts:716-720 hace `if (translationsOrSink instanceof Set) { translationsOrSink.add(source.key) } else { translationsOrSink.add(source.key) }` — las dos ramas son el mismo codigo. Aun asi docs/process/CONTINUE-audit-queue.md:295 tacha `~~M6~~ EJECUTADO` y el mensaje enumera la ficha como aliases + as never + `_resetCompileCache`, sin nombrar el helper. Item cerrado con su peticion mas sustantiva viva (regla dura: nunca recortar alcance en silencio).
|
|
|
|
|
- **[M5-selector]** (defecto) La doctrina del libro sigue diciendo lo contrario del código: `state` documentado como string suelto y `undeclaredState` inexistente en los capítulos.
|
|
|
|
|
- *Evidencia alegada*: docs/architecture/morfo.md:1047-1051 «### What it accepts loose … **`state` / `aria`** — the data-attr vocabulary … not yet derived from the morfo's data contract. A future iteration will tighten these too.» y docs/architecture/sema.md:365-366 «`state` / `aria` / `pseudo` accept plain strings … not yet typed-derived». El commit borró exactamente esa promesa del docblock de selectors.ts pero no tocó ninguno de los dos capítulos (diff sólo toca docs/process/CONTINUE-audit-queue.md), y `undeclaredState` no se menciona en morfo.md, sema.md ni eidos.md. El mensaje canta «docs 0/624» — el censo no ve prosa, y en este proyecto los docs mandan sobre el código.
|
|
|
|
|
- **[M5-selector]** (defecto) `DataPairOf` deja abierta la clase de deriva MAYORITARIA: los presence flags. Su único valor legal es `''`, y el tipo les da `value: string`; el docblock afirma lo contrario del contrato.
|
|
|
|
|
- *Evidencia alegada*: types.ts:238 «presence: truthy source writes `data-x=""`» y compile.ts:632 `if (!hasEnum) return data.emit === 'value' ? 'string' : 'html-presence'` + compile.ts:763 `case 'html-presence': return raw ? '' : undefined`; el proveedor real estampa `''` (soma/components/dialog/dialog-provider.svelte.ts:454-455). Sólo 47 entradas en los 166 morfos declaran `emit: 'value'`. Sin embargo selectors.ts:96-97 escribe «presence flags and `emit: 'value'` attrs carry arbitrary values» y selectors.ts:111-112 les da `value: string`. Consecuencia concreta: `state: { attr: 'data-nested', value: 'true' }` sobre dialog/content compila Y pasa el gate runtime (no hay `values`), y emite `[data-dialog-content][data-nested="true"]`, un selector que no puede casar jamás. El morfo YA codifica la respuesta (`pickDataMode`), así que aquí el tipo podía hablar y no habla.
|
|
|
|
|
- **[M4-enumpair]** (defecto) El gemelo NO compilado del mismo defecto sigue vivo y exportado: `resolveMorfoDataValue` repite `values.find(v => v !== source.state)` sin arreglo, asi que ahora los dos caminos de evaluacion DISCREPAN sobre la misma entrada (el compilado lanza, el crudo adivina).
|
|
|
|
|
- *Evidencia alegada*: src/uix/morfo/resolver.ts:89-91 intacto (`if (source.kind === 'stateRef' && typeof raw === 'boolean') { if (raw) return source.state; return data.values.find((value) => value !== source.state); }`). Exportado como API publica en src/uix/morfo/index.ts:40,42 bajo el docblock 'Used by the runtime and by anything that needs to derive attrs from a morfo' (index.ts:35-37). Ejecutado con tsx sobre la declaracion REAL de checkbox (G:/tmp/m4-twin.ts): resolveMorfoDataValue(data-state, {states:{checked:true}}) -> 'checked', {checked:false} -> 'unchecked', y resolvePartAttrs devuelve lo mismo; el plan compilado del MISMO attr lanza MorfoInvariantError. Antes del commit ambos caminos coincidian; compile.ts:10 presenta el compilador como la version memoizada de resolvePartAttrs.
|
|
|
|
|
- **[M4-enumpair]** (claim) «El arreglo hace imposible EN SILENCIO el emparejamiento booleano<->enum-no-binario»
|
|
|
|
|
- *Evidencia alegada*: Solo cierto para el camino compilado (compile.ts:767-783). Por el camino exportado sin compilar el emparejamiento sigue ocurriendo y sigue siendo silencioso: resolver.ts:89-91, verificado por ejecucion sobre checkboxMorfo (boolean false -> 'unchecked', sin aviso ni error). M4 queda cerrado a medias.
|
|
|
|
|
- **[M4-enumpair]** (claim) «‘Hoy no muerde porque los stateRef booleanos usan enums binarios’ — falso de premisa: hay 12 declaraciones con 3+»
|
|
|
|
|
- *Evidencia alegada*: La ficha (docs/old-deprecated/fable_audit.md:209-214) predica sobre los stateRef BOOLEANOS; las 12 declaraciones de 3+ son de estado STRING, como el propio commit concede dos lineas despues. Censo propio compilando los 166 ficheros de morfo (G:/tmp/m4-census.ts) + lectura de los 11 bindings reales: TODO stateRef ligado a booleano usa enum binario, luego la premisa de la ficha es VERDADERA. El acierto real del commit es otro (su arreglo habria proscrito 12 declaraciones legitimas). CONTINUE-audit-queue.md:271-273 deja registrado en el ledger vivo que 'la premisa de la ficha era falsa'.
|
|
|
|
|
- **[M4-enumpair]** (defecto) `enumValues.length === 2` no es la invariante correcta: en un enum binario cuya etiqueta-true NO es miembro del enum, la pareja se sigue infiriendo por ORDEN de declaracion y estampa un valor fuera del contrato — la clase M4 viva dentro de la rama que el commit declara «exacta por construccion».
|
|
|
|
|
- *Evidencia alegada*: compile.ts:556-560 solo comprueba la aridad. El esquema exige `stateRef.state ∈ part.states` (schema.ts:557-560), no `∈ data.values`. Reproducido (G:/tmp/m4-hole.ts): part con states ['on','off','busy'] y data {values:['on','off'], value:v.stateRef('busy')} PASA validateMorfo; enumPair = ['busy','on']; boolean true -> 'busy' (fuera del set cerrado), false -> 'on' por orden. Censo: 0 casos hoy entre los 67 binarios, luego es latente — la misma latencia por la que el commit justifica su throw. Arreglo: `enumValues.length === 2 && enumValues.includes(source.state)`.
|
|
|
|
|
- **[E2E3-eidos]** (defecto) El error atrapado va a `context`, no a la ranura `error` del logger: el aviso pierde mensaje y stack en todo transporte
|
|
|
|
|
- *Evidencia alegada*: active-eidos.svelte.ts:1100 `{ context: { error } }`. engine-logger.ts:269 solo pasa por `extractError` lo que llegue en `input.error`; `entry.error` queda undefined. Cada transporte/adaptador lee `entry.error`: transports.ts:59 y :89, sentry.ts:123, datadog.ts:88, logtail.ts:57, loki.ts:79, otel.ts:80. Un Error crudo dentro de `context` serializa a `{}` en JSON. Ademas refuta el encuadre del mensaje («la superficie que ya usa sema»): sema escribe `{ error: err, context: {...} }` en sema/engine.ts:734-737.
|
|
|
|
|
- **[E2E3-eidos]** (defecto) El «keep» es incondicional: un re-spec EXPLICITO que falla pinta ahora un esquema OBSOLETO sobre un tema nuevo
|
|
|
|
|
- *Evidencia alegada*: applyTheme fija los specs (active-eidos.svelte.ts:863-876), llama `apply()` (:892) que sirve `#lastSchemeCss` — el bloque del tema ANTERIOR y con el selector ANTERIOR — y luego lanza en :895. Queda type/depth/shape/space del tema B con los `--primitive-*` del tema A. Igual en applyColorScheme: `#schemeSpec` se asigna en :728 ANTES del build eager que lanza en :729, asi que cada apply() posterior re-sirve el bloque de la semilla vieja para siempre. La justificacion de E3 («un cambio de MODO con semilla que no deriva») cubre solo el re-derive con el mismo spec; el codigo no distingue.
|
|
|
|
|
- **[M1-emission]** (claim) «'host' NO cuenta como muerto: el anfitrion dispara por el runtime y la regla casa normal» (y la tabla de morfo.md:818 «'host' → pack rules stay LIVE (the stamp happens)»)
|
|
|
|
|
- *Evidencia alegada*: El chequeo preexistente del censo de packs no sabe nada de `emission`: src/uix/sema/pack-census.test.ts:539-573 («tunes only events some provider actually emits») busca el LITERAL del nombre en el arbol soma+eidos con comentarios stripeados. Replicado ese codigo exacto sobre los tres eventos `emission: 'host'` de HEAD: `virtual-list:handle-scroll` false, `virtual-grid:handle-scroll-row` false, `virtual-grid:handle-scroll-column` false. Una regla de pack que alcance solo esos eventos se reporta MUERTA y exige un waiver en `EMISSION_EXCEPTIONS` (pack-census.test.ts:342) — exactamente la lista de excepciones que D.2 venia a retirar. Latente hoy solo porque virtual-list/virtual-grid no tienen pack (grep en src/uix/sema/components: 0 ficheros).
|
|
|
|
|
- **[M1-emission]** (defecto) La lectura de `emission` por CHUNK atribuye el flag al evento equivocado cuando el evento marcado es invisible al regex
|
|
|
|
|
- *Evidencia alegada*: src/uix/contracts.test.ts:395-397 — `chunk = source.slice(match.index, matches[i+1]?.index)`: el limite es el siguiente MATCH, no el siguiente evento. Ejecutada la logica literal del guard sobre un fichero sintetico en el estilo del propio repo (un evento runtime seguido de otro con comentario + `emission: 'host'`): resultado `[['commit-set-resize','host']]` — el evento runtime queda EXIMIDO por el flag del vecino, y el vecino desaparece. Hoy no muerde solo porque en virtual-list/grid el evento marcado es el PRIMERO del array; reordenar el array lo activa. Ademas la lectura no stripea comentarios, al reves que el censo de packs (pack-census.test.ts:359-364, que los stripea precisamente porque la prosa ya engaño a una busqueda literal): una mencion `emission: 'host'` en un comentario dentro del chunk exime en silencio.
|
|
|
|
|
- **[tooltip-wiring]** (claim) «SIN su `commits` (fijaba 'delayed-open' y PISARIA el 'instant-open' del camino focus)» — el commit justifica borrar el `commits` del present con un mecanismo de escritura DOM.
|
|
|
|
|
- *Evidencia alegada*: docs/architecture/morfo.md:115-121 — tabla «Runtime executor»: `events[].commits` → «**Nobody executes**; smoke validates» + «`commits` es DESCRIPTIVO, no prescriptivo. La cadena causal real es handler -> state -> effect -> dom.apply». En codigo: src/uix/morfo/compile.ts:681 solo lo copia (`commit: event.commits`) y NADIE lee `.commit` (grep en src/uix/soma/runtime.svelte.ts = 0 hits; unicos consumidores: schema.ts:765-777 validando y dialog.test.ts). Un `commits` no puede pisar nada. La DECISION de quitarlo es defendible por otra razon (un valor unico no puede describir un tri-estado), pero el mecanismo citado no existe — y el falso mecanismo queda escrito en el fichero de contrato: src/uix/morfo/components/tooltip.ts:40-42 «a fixed committed value would overwrite the focus path's 'instant-open'».
|
|
|
|
|
- **[tooltip-wiring]** (defecto) El ledger VIVO del eje docs↔codigo sigue afirmando lo contrario de HEAD y su precondicion explicita quedo sin responder; el commit solo actualizo CONTINUE-audit-queue.md.
|
|
|
|
|
- *Evidencia alegada*: docs/process/AUDIT-docs-code-ledger.md:531 («Contrato muerto … `tooltip` ×3 | libre; es el que queda accionable aqui») y :538-543 («El accionable: `tooltip`, 3 de 3. **Cero llamadas a `trigger(` en todo `soma/components/tooltip`**» — falso desde este commit; y «La pregunta previa es cual de las dos, porque el tooltip **compone Popover** y podria ser otro `expression: 'delegated'` … eso hay que medirlo antes de tocar, no suponerlo»). Esa premisa es ademas FALSA: TooltipProvider compone `createFloatingShellRoot` (tooltip-provider.svelte.ts:161-169), no PopoverProvider (grep 'popover' en soma/eidos/components/tooltip = solo comentarios de receta). La decision acierta; el ledger no se corrigio ni se respondio.
|
|
|
|
|
- **[virtual-host]** (defecto) En el modo `WindowViewport` — variante de primera clase del mismo componente — la superficie prometida al host NO puede aterrizar: el trigger rechaza con SomaRuntimeTargetError.
|
|
|
|
|
- *Evidencia alegada*: `handle-scroll` declara `target: v.partRef('viewport')` y ningún `targetFallback` (virtual-list.ts:29-34). `VirtualListWindowViewportProvider` registra solo la parte `window-viewport` (virtual-list-provider.svelte.ts:625) y escucha `win` scroll (línea 662); su docblock (línea 610) dice «Cannot be combined with a regular Viewport under the same Provider — pick one or the other», así que `viewport` no tiene instancia viva. runtime.svelte.ts:841-853 `resolveEmitTarget` devuelve null y runEmit lanza `SomaRuntimeTargetError` (líneas 1049-1052; el evento es `sequence:'post'`, así que falla en el emit). `targetFallback` es exactamente el mecanismo declarado para el estado de montaje (morfo/types.ts:503-516) y no se usó al convertir el evento en promesa al host.
|
|
|
|
|
- **[virtual-host]** (defecto) La cita desfasada que el commit dice haber corregido «al tocarlo» sigue viva en los README públicos de los dos componentes, y sus tablas de eventos siguen sin registrar `emission: 'host'` — justo lo que la doctrina citada dice que el flag existe para arreglar.
|
|
|
|
|
- *Evidencia alegada*: src/uix/soma/components/virtual-list/README.md:153 sigue diciendo «family.handle activates only the haptic channel» cuando sema-map.ts:483-499 declara `activeChannels: ['sound','haptic']` (+ `sounds: { default: 'step' }`, haptic `kind:'tick'`); la tabla (README.md:149) mantiene «Emitted? NO» sin mención del flag, y virtual-grid/README.md:104-105 hereda la razón («Same buzz reasoning as virtual-list»). La doctrina que el commit invoca, docs/architecture/morfo.md:822-828, dice literalmente que el flag existe «so the README event tables stop promising perception that never occurs». Se arreglaron los dos comentarios de provider y se dejó el documento público.
|
|
|
|
|
- **[gradient-S14]** (claim) «Retirada completa» — el evento fuera del morfo, la regla muerta fuera del pack.
|
|
|
|
|
- *Evidencia alegada*: Los DOS ficheros que el commit edito siguen documentando el evento retirado. src/uix/sema/components/gradient-picker.ts:15 mantiene «• commit-reset — cleared back to the initial value: a neutral reset» y :17 «El `fulfill` / `loss` / `neutral` intents…» cuando ya no queda ninguna regla `neutral` (solo commit-save fulfill / commit-remove loss). src/uix/morfo/components/gradient-picker.ts:6-7 sigue diciendo que el morfo declara «the content shell + the clear value-semantic» y :23 «Own commit events (reset / save / remove) tuned by the pack». Un grep de `commit-reset` en src/ sigue devolviendo sema/components/gradient-picker.ts.
|
|
|
|
|
- **[gradient-S14]** (defecto) El README de soma queda con una tabla «Sema events» de solo cabecera (cero filas), y omite los dos eventos que su provider SI emite.
|
|
|
|
|
- *Evidencia alegada*: src/uix/soma/components/gradient-picker/README.md:61-64: la seccion `## Sema events` conserva cabecera y separador sin ninguna fila tras borrar la unica que habia. Mientras tanto el provider de esa misma carpeta emite dos eventos: gradient-picker-provider.svelte.ts:135 `void this.runtime.trigger('commit-save')` y :143 `void this.runtime.trigger('commit-remove')`. El README pasa de documentar 1 evento equivocado a documentar 0 de 2 reales.
|
|
|
|
|
- **[gradient-S14]** (defecto) Un consumidor rastreado quedo mintiendo: la demo declara como contrato el evento retirado.
|
|
|
|
|
- *Evidencia alegada*: web/routes/uix/components/gradient-picker/+page.svelte:335 (fichero versionado, `git ls-files` lo confirma), pestaña sema: «The picker declares one value event — <code>commit-reset</code> (the Clear action)». Tras el commit el morfo no declara `commit-reset` y declara DOS eventos (commit-save / commit-remove). El panel en si se auto-cura (linea 127: `actions = [...compiled.actions.byName.values()]`), pero la prosa —y el conteo narrativo «one value event»— es falsa. Ni el commit ni el ledger mencionan este consumidor.
|
|
|
|
|
- **[announce-root]** (claim) 23b20fff5: «announce es SUSTITUCION (sema.md §channels — "the one that substitutes")»
|
|
|
|
|
- *Evidencia alegada*: La frase «the one that substitutes» y la taxonomia ornamento/sustituto viven en docs/theming/channels.md:56 y :61, NO en sema.md. La seccion §«Channels and signatures» de sema.md (linea 590-597) es una tabla de 4 filas que ni siquiera LISTA `announce` ni menciona sustitucion. La cita erronea quedo fijada tambien en el comentario permanente del codigo (src/uix/active-uix/active-uix.svelte.ts:434 «sema.md §channels») y en la propia doc (docs/architecture/sema.md:963 «(§channels)», que ahora auto-referencia esa tabla que no dice nada de eso).
|
|
|
|
|
- **[announce-root]** (defecto) 455260ca3: el docblock de `CHANNEL_EXCEPTIONS` quedo mintiendo — sigue describiendo una decision PENDIENTE y cinco waivers que el commit borro
|
|
|
|
|
- *Evidencia alegada*: src/uix/sema/pack-census.test.ts:313-322 en HEAD: «PENDING AUTHOR DECISION (S-30/S-38, audited 2026-08-05, waived 2026-08-06): five rules write a haptic signature their family never activates — inert since birth… These waivers record the finding; they do not bless it», seguido de `const CHANNEL_EXCEPTIONS = {}` (linea 323). La decision se firmo en este mismo commit. El autor SI actualizo el bloque hermano `EMISSION_EXCEPTIONS` (338-342: «EMPTY since 2026-08-13…»), lo que confirma que la omision es del commit y no un estilo.
|
|
|
|
|
- **[announce-root]** (defecto) 23b20fff5: la §announce de sema.md se contradice consigo misma tras el «reescrito» — titulo y entradilla siguen diciendo opt-in
|
|
|
|
|
- *Evidencia alegada*: docs/architecture/sema.md:919 «### Announce channel — `engine.announce` (opt-in)» y :922-923 «first-class channel (AnnounceChannel, id announce), opt-in like sound / haptic», frente a :960-968 (añadido por el commit) «Both roots wire it by DEFAULT … Default ON because announce is SUBSTITUTION, not ornament». Misma deriva sin tocar en src/uix/sema/chans/announce.ts:13 («first-class, opt-in channel like sound / haptic»), src/uix/sema/engine.ts:89-95 («Opt-in like sound / haptic») y docs/theming/channels.md:58 («joined on 2026-07-04 as a built-in opt-in channel») — precisamente el doc que sostiene la doctrina en la que el commit se apoya.
|
|
|
|
|
- **[A47-ring]** (claim) «medido en la demo real del cta, 1,02:1 (peor aun que el 1,43:1 del ledger; misma pareja, panel rgb(142,78,198))» + «sonda de composicion (canvas getImageData)»
|
|
|
|
|
- *Evidencia alegada*: No es la misma pareja. Convirtiendo el panel que el ledger registro (AUDIT-blocks-ledger.md:775: background-color oklch(0.5556 0.1829 305.86)) da rgb(141,78,198) = el color PLANO, sin el linear-gradient que el ledger midio compuesto en rgb(102,55,144). Y 1,02 solo sale con el pigmento del anillo OSCURO (color(srgb 0.5175 0.3412 0.6666)/0.52 sobre rgb(142,78,198) = 1,021), mientras el 1,43 del ledger es la fila CLARO gradient=false (ledger:773); sus cifras oscuras son 1,25/1,26. Ademas ambos numeros del commit (1,02 y 5,18) reproducen EXACTO desde el color plano, no desde el pixel compuesto — con el compuesto rgb(102,55,144) el «despues» daria 8,35:1 — asi que la «sonda de composicion» midio el background-color nominal, justo lo que dice haber evitado.
|
|
|
|
|
- **[A69-countup]** (claim) «una banda de contadores aterriza JUNTA por construccion» (count-up.svelte:200-201) y types.ts:21 «Seconds the count takes to settle — TRUE for any magnitude».
|
|
|
|
|
- *Evidencia alegada*: El invariante esta anclado a `restThreshold = 0.5*10^-decimals` (count-up.svelte:175), derivado de los LITERALES `from`/`to` — no de la resolucion real del formatter, que `notation` / `maximumFractionDigits` / `minimumFractionDigits` / `formatStyle` cambian (count-up.svelte:67-78). Simulacion con el Intl real y las mismas opciones que construye formatValue: el ejemplo del PROPIO README (README.md:19, `to={1200000} currency compact`) hace su ULTIMO cambio visible a 250 ms y dispara `onEnd` a 2017 ms — 1,77 s DESPUES de que la cifra parase (el mismo defecto de A-69, invertido). README.md:22 (`to={2048} compact`): 333 ms vs 2017. El preset del propio demo (web/routes/uix/components/count-up/+page.svelte:47, compact + maxFrac 1, duration 2,4): 533 ms vs 2417. `maximumFractionDigits={0}` sobre 99.9: 1467 vs 2000. Y `src/uix/blocks/stats-band/types.ts:42-44` anuncia `notation` en `countOptions`, o sea una banda PUEDE mezclar compact y plano: 250 ms vs 2000 ms = 1,75 s de dispersion, no 0. README.md:66 sigue afirmando literalmente la premisa falsa: «el muelle para en cuanto el display ya no puede cambiar».
|
|
|
|
|
|
|
|
|
|
### BAJA — 6
|
|
|
|
|
|
|
|
|
|
- **[S-34+S-33+S-35]** (claim) S-33: «el probe de tipos … (tres `@ts-expect-error`, uno de ellos el que ayer se quedaba sin consumir)» y «sema+morfo 537 ✓ (532 + 5 nuevos)».
|
|
|
|
|
- *Evidencia alegada*: git show 1a174d5a6:src/uix/sema/intent-policy.test.ts — hay DOS directivas reales (líneas 65 y 68); la tercera aparición (línea 34) es prosa dentro de un comentario («un `@ts-expect-error` sin consumir es error de compilación»), y TS no la parsea como directiva porque el texto empieza por backtick. Y el fichero añade TRES bloques `it(` (líneas 64, 76, 100), no cinco: 532+5=537 no cuadra con su propio diff (sería 534→537). Cross-check: S-35 sí cuadra — añade 2 `it` y declara 537→539.
|
|
|
|
|
- **[M4-enumpair]** (claim) «Mi primera propuesta invocaba un ‘guard de contratos’ que NO existe»
|
|
|
|
|
- *Evidencia alegada*: Existe: `assertContract` (src/uix/morfo/contracts.ts:59-85), alimentado por registerCompiledContract desde el morfo compilado y llamado por el runtime en runtime.svelte.ts:716; avisa cuando un data-attr toma un valor fuera del `values` declarado — exactamente esta clase. No habria cazado M4 (el valor adivinado SI esta en el enum) ni ve los attrs escritos por el efecto syncAttrs, pero «NO existe» es falso tal como queda escrito en el ledger (CONTINUE-audit-queue.md:278). Salvedad: no puedo leer la propuesta original, asi que juzgo la frase tal como queda registrada.
|
|
|
|
|
- **[E2E3-eidos]** (claim) E2: «la suscripcion va por `dom.listen` (ciclo de vida gestionado)»
|
|
|
|
|
- *Evidencia alegada*: active-dom.svelte.ts:300-315: `listen` es un `addEventListener` pelado que devuelve el removedor; no hay registro, y `dispose()` (:601-610) solo cancela measureQueues y los trackers — no retira listeners. El ciclo de vida es IDENTICO al camino crudo que sustituye: sigue dependiendo de ActiveEidos.dispose() → `#unsubscribe` (:406 y :1160) → detachers de createComposedPreferenceSource (:1350-1357). La regla de la casa (enrutar por ActiveDom) si se cumple; «gestionado» no aporta nada.
|
|
|
|
|
- **[tooltip-wiring]** (claim) «la entrada por data-state es el workaround de la emision ausente (el comentario del provider lo dice literal)».
|
|
|
|
|
- *Evidencia alegada*: El comentario pre-commit (git show daa6461d6^:src/uix/soma/components/tooltip/tooltip-provider.svelte.ts, lineas 229-235) dice literalmente: «Stay 'delayed-open' (NOT 'instant-open') as the content MOUNTS, so the eidos entrance animation keyed on [data-state='delayed-open'] actually plays … 'instant-open' stays reserved for focus / skip-delay». Documenta una eleccion de MAQUINA DE ESTADOS y su acoplamiento con la receta; no menciona emision, firma ni evento en ningun punto (grep -i 'emission|emit|workaround' en el fichero pre-commit = 0 hits). La cita esta inflada.
|
|
|
|
|
- **[docs-jornada]** (claim) a15745491: «los otros cuatro son rejillas en popover, otro problema» (usado para desactivar la evidencia de asimetria de familia).
|
|
|
|
|
- *Evidencia alegada*: Solo 2 de los 4 lo son. src/uix/soma/components/date-picker/README.md:3 «Combined date input and calendar popover» ✓ popover; date-range-picker igual. Pero src/uix/soma/components/calendar/README.md:1-3 y src/uix/soma/components/range-calendar/README.md:1-3 describen rejillas inline standalone («A date-range picker grid... fully headless»), sin popover (calendar-provider.svelte.ts:153 solo menciona «no nested popover» para MonthView/YearView). Sus defaults false (calendar.svelte:31, range-calendar.svelte:33) NO se explican por «vivir en un popover». La conclusion de la revocacion no depende de esto, pero el argumento escrito es falso para la mitad del conjunto.
|
|
|
|
|
- **[docs-jornada]** (claim) cb1fd54d1 §1: «CLAUDE.md §Eidos drift defense dice que cuando una capa PUEDE expresar la restriccion en TypeScript, hacerlo con un test es una violacion de arquitectura».
|
|
|
|
|
- *Evidencia alegada*: CLAUDE.md:332-340 y docs/architecture/eidos.md:858-895 acotan la doctrina a los SELECTORES que apuntan al morfo: «hand-written morfo-targeting selector strings in TS are an architecture violation, not a lint warning», con el remedio semaSelector. La misma seccion BENDICE explicitamente el lint donde el tipo no llega: «Plain .css recipes have no builder yet — for those, scripts/eidos-lint.ts is the opt-in safety net». No hay ninguna frase que convierta un test/guard en violacion de arquitectura fuera del eje de selectores. La conclusion (derivar los tres cubos en positivo) es correcta por otros motivos, pero la doctrina citada no dice eso — y el commit hermano eda3b977b/S-34 metio precisamente un guard de runtime sobre el mismo const.
|
|
|
|
|
|
|
|
|
|
## 4 · Los 22 que el segundo escéptico tumbó
|
|
|
|
|
|
|
|
|
|
Se listan porque son la prueba de que el primer paso produce falsos
|
|
|
|
|
positivos con soltura.
|
|
|
|
|
|
|
|
|
|
- **[D9-guard]** (ALTA) El fix amplía el BLOB a eidos pero NO la puerta: un componente sin dir de soma sigue sin auditarse, y hay una instancia D9 viva e invisible (card.commit-select)
|
|
|
|
|
- *Por qué no se sostiene*: La puerta existe (reproducida en src/uix/contracts.test.ts:380-381) y el censo confirma la aritmética del primero: al árbol de 14a169357 el regex casa 256 eventos, 255 entran al bucle y el único que la puerta salta es exactamente card.commit-select. Pero la puerta NO es lo que lo
|
|
|
|
|
- **[D9-guard]** (MEDIA) «Endurecerlo convierte 27 emisiones REALES en violaciones — checkbox, accordion, calendar, select, combobox, listbox, grid-list, tag-group, range-calendar, chronos, aura, palabras»
|
|
|
|
|
- *Por qué no se sostiene*: FALSADO: la cifra 27 SÍ es reproducible; el primero no probó la lectura obvia — restringir el conteo a los componentes que la propia frase enumera. Instrumento: repliqué `collectInertEventViolations` byte a byte (src/uix/contracts.test.ts:362-404 @14a169357) sobre el árbol del c
|
|
|
|
|
- **[M6-alias]** (MEDIA) El barrel pierde el concepto entero: `IntentExpectedFamily` se borra de exports.ts y NO se anade `IntentRequiredFamily`
|
|
|
|
|
- *Por qué no se sostiene*: El hecho literal se reproduce (src/uix/sema/exports.ts:5 lista `IntentOptionalFamily` y en todo el fichero no hay `IntentRequiredFamily`), pero las tres patas del razonamiento caen: 1) «cero nombres públicos para ese concepto» es FALSO. El nombre canónico vive en src/uix/sema/ty
|
|
|
|
|
- **[M5-selector]** (MEDIA) Las dos puertas no son disyuntas «respecto al contrato del morfo» como promete el docblock: el gate de `undeclaredState` mira sólo la parte SELECCIONADA, y por ahí se esquiva un en
|
|
|
|
|
- *Por qué no se sostiene*: La conducta se reproduce (probe con tsx: `semaSelector(dialogMorfo,'trigger',{undeclaredState:{attr:'data-last-action',value:'x'}})` → `[data-dialog-trigger][data-last-action="x"]`, sin lanzar), pero NO es un defecto: hay neutralizador y la caracterización del daño es falsa. 1)
|
|
|
|
|
- **[M5-selector]** (MEDIA) «El gate de disyuncion vive en el BUILDER, no en el censo (desviacion declarada del punto 4 firmado, a mas fuerte)» — la desviación declarada es incompleta: se calló la rebaja de g
|
|
|
|
|
- *Por qué no se sostiene*: NO se sostiene: el eje que el primero dice «callado» está escrito, en el MISMO commit, en las líneas que él mismo cita como prueba. 1) Autodestrucción de la evidencia. `src/uix/morfo/selectors.ts:100-106` (añadidas por b53c93e42, y `selectors.ts` NO ha cambiado desde entonces: `
|
|
|
|
|
- **[M5-selector]** (BAJA) «la union atraviesa intacta el idioma … de los 67 packs».
|
|
|
|
|
- *Por qué no se sostiene*: El «67» no es una cifra arrastrada: es EXACTA para el referente que la propia frase nombra. La frase del commit es «la union atraviesa intacta **el idioma `Parameters<typeof semaSelector<M>>[2]`** de los 67 packs», y el sujeto contado son los packs que LLEVAN ese idioma, no los p
|
|
|
|
|
- **[M4-enumpair]** (MEDIA) Primer throw de MorfoInvariantError en el camino de EVALUACION (no de declaracion), sin puerta de dev: revienta dentro del $effect de syncAttrs y en la API publica `resolveProps`,
|
|
|
|
|
- *Por qué no se sostiene*: Las citas literales se reproducen (compile.ts:775-780 lanza sin puerta; contracts.ts:65 sí la tiene), pero la premisa que sostiene el hallazgo —«la convención de la capa para una violación de contrato en runtime es avisar sólo en dev»— es falsa, y el remedio propuesto invoca un c
|
|
|
|
|
- **[tooltip-wiring]** (MEDIA) `openAndPresent` NO cubre todos los caminos de apertura: la prop `open` (bindable, publica y demostrada con un switch) abre sin emitir `emerge-present`, pero su cierre SI emite `em
|
|
|
|
|
- *Por qué no se sostiene*: La mecánica se reproduce (abrir por prop + leave/blur ⇒ `emerge-dismiss` sin `emerge-present`), pero NO es defecto: (1) El invariante citado no dice lo que el primero le atribuye. `tooltip-provider.svelte.ts:277-280` contrapone el caso del TIMER CANCELADO — «a cancelled open-time
|
|
|
|
|
- **[virtual-host]** (MEDIA) «La promesa del host es viable, verificado: `provider.runtime` es campo publico — un app puede emitir con su propia politica» (mensaje + docblock del morfo + CONTINUE-audit-queue).
|
|
|
|
|
- *Por qué no se sostiene*: Los HECHOS del primero se reproducen (barriles sin provider: virtual-list/exports.ts y virtual-grid/exports.ts sólo 4 `.svelte` + tipos; snippetProps en virtual-list-provider.svelte.ts:494-501 y types.ts:18-30 no exponen runtime), pero su INFERENCIA cae por tres neutralizadores.
|
|
|
|
|
- **[gradient-S14]** (BAJA) «date-picker cableado el 2026-08-11» (y en el ledger «cableados 2026-08-11»).
|
|
|
|
|
- *Por qué no se sostiene*: NO SE SOSTIENE. La evidencia del primero se reproduce (f4e414e2e es el unico commit que introduce el trigger en los tres providers, author=commit=2026-08-12 01:30:22 +0200), pero su INTERPRETACION —«el 11 es la adjudicacion, no el cableado»— queda refutada por tres neutralizadore
|
|
|
|
|
- **[announce-root]** (MEDIA) 23b20fff5: `AnnounceChannel` no consulta `effective.activeChannels`, asi que la puerta por regla/evento (`channels`) NO puede cerrarlo — y ahora esta encendido por defecto
|
|
|
|
|
- *Por qué no se sostiene*: Los hechos crudos se reproducen (announce.ts:86-99 no consulta activeChannels; ninguna familia declara 'announce' en sema-map.ts:423-512), pero la INFERENCIA de defecto cae: el hallazgo asume que la puerta `channels` gobierna todo canal registrado, y la doctrina firmada dice lo c
|
|
|
|
|
- **[announce-root]** (BAJA) 4e7d0be67: «el sumidero recibia un OBJETO donde lee una prioridad, liveRegionIds[obj] es undefined, y TODO aterrizaba en la region polite»
|
|
|
|
|
- *Por qué no se sostiene*: NO se sostiene: hay neutralizador, y esta en la MISMA linea que el primero cita. La mitad DOM de su evidencia si reproduce (active-uix.svelte.ts:583 `liveRegionElements.get(obj)` falla porque el Map tiene claves string; :585 `liveRegionIds[obj]` es undefined; :589 `id: undefined`
|
|
|
|
|
- **[A47-ring]** (MEDIA) «Los DOS unicos elementos interactivos del block quedaban sin indicador, contra el minimo 3:1 de WCAG 1.4.11» (repetido en surface.css:36-37)
|
|
|
|
|
- *Por qué no se sostiene*: TUMBADO: la frase que el ledger declara falsa NO es la que viaja en acda70f1e, y el neutralizador esta en el mismo comentario. 1) La cita no coincide. `AUDIT-blocks-ledger.md:759` marca como «literalmente falso» el sintagma «quedan sin indicador de foco **por teclado**», y lo fu
|
|
|
|
|
- **[A47-ring]** (ALTA) Viola D12 (contexto de tinta de subarbol MINIMO y con opt-in explicito) y contradice el comentario que hay dos lineas encima de la insercion
|
|
|
|
|
- *Por qué no se sostiene*: Las citas reproducen literalmente (gradient-finish.md:366-371 y :409-422; surface.css:30-31; inserción en surface.css:34-45), pero NO prohíben lo que el commit hace. Tres neutralizadores: (1) CATEGORÍA. El límite de D12 es «nested components that read their OWN color/surface tok
|
|
|
|
|
- **[A47-ring]** (MEDIA) TextArea dentro de un Surface solido pierde el borde de foco: blanco sobre blanco
|
|
|
|
|
- *Por qué no se sostiene*: La evidencia se reproduce al pie de la letra, pero el daño que deduce no existe: el borde y el outline BEBEN DE LA MISMA VARIABLE y van pegados, así que no pueden ser «blanco sobre blanco» entre sí. 1) UNA banda, no dos señales. textarea.css:17 (`--_textarea-border-focus: var(--
|
|
|
|
|
- **[A47-ring]** (MEDIA) Ninguna guarda vigila que una receta de componente escriba un token propiedad de la fundacion
|
|
|
|
|
- *Por qué no se sostiene*: La evidencia empírica del primero SÍ se reproduce (corrido `npx vitest run src/uix/eidos/recipe-css-contract.test.ts --project=server` en HEAD: 31/31 pasan), pero hay neutralizador doctrinal: la forma que denuncia no está prohibida por ninguna regla, así que la ausencia de guarda
|
|
|
|
|
- **[A69-countup]** (MEDIA) El cambio AGRAVA, sin declararlo, el item abierto A-68 (CONFIRMADO, MEDIA) — «cada cifra se hace visible con su muelle ya avanzado» — pese a que el mensaje lo lista como «NO tocado
|
|
|
|
|
- *Por qué no se sostiene*: La ARITMÉTICA del primero se reproduce (la verifiqué aparte: λ_new 5,080/3,278/2,299; consumo en el instante de revelado 5,8→18,1 % para 340 y 20,6→35,4 % para 48; 12.500 pasa de 0,0 a 0,4 %). Es incluso más fuerte de lo que dice: con duration=2 la ζ vieja es 2√2 EXACTA, así que
|
|
|
|
|
- **[docs-jornada]** (MEDIA) 3ee17f333 anade §4.1 «Hallazgos del 2026-08-13 — RESUELTOS» al handoff pero deja el mismo fichero declarando esos hallazgos ABIERTOS 140 lineas mas arriba, y el arranque del docume
|
|
|
|
|
- *Por qué no se sostiene*: La contradicción textual existe, pero está LEGITIMADA por doctrina escrita y la atribución falla en un tercio de la evidencia. 1) Doctrina que lo legitima (el neutralizador). `docs/README.md:151-154`: «[docs/process/] holds session hand-offs… They record *what happened*, not *wh
|
|
|
|
|
- **[docs-jornada]** (MEDIA) 3ee17f333 (docblock de SemaActionEvent): «this is the public surface an app driving EngineSemantic WITHOUT soma uses to name an occurrence».
|
|
|
|
|
- *Por qué no se sostiene*: La evidencia bruta del primero SI se reproduce (engine.ts:642 `async emit(signal: SemanticSignal)` es la unica entrada de ocurrencia; ninguna funcion del motor acepta ni devuelve `SemaActionEvent`; `SemaEventKey` no tiene hits fuera de types/event/exports + tests), pero refuta un
|
|
|
|
|
- **[docs-jornada]** (MEDIA) 3ee17f333 (docblock de validateSemaEvent) cierra con «If the predicate ever stops enforcing policy, this branch is already here and correct», pero la funcion solo posee la MITAD de
|
|
|
|
|
- *Por qué no se sostiene*: El hecho bruto se reproduce (validation.ts:57-63 sólo mira `=== 'required'`), pero la lectura que lo convierte en defecto no sobrevive. 1) El docblock NUNCA reclama la política entera; su sujeto está acotado EN EL CÓDIGO. `src/uix/sema/validation.ts:31` dice «The policy branch b
|
|
|
|
|
- **[docs-jornada]** (BAJA) a15745491: «chronos es el UNICO que escribio su decision» sobre fixedWeeks.
|
|
|
|
|
- *Por qué no se sostiene*: NO SE SOSTIENE. Las dos citas del primero se reproducen literalmente en HEAD, pero ninguna es lo que la frase afirma, y hay neutralizador verificado. 1) La frase está acotada por sus PROPIAS citas. `docs/process/CONTINUE-perceptual-surface.md:1072-1073` dice «chronos es **el úni
|
|
|
|
|
- **[docs-jornada]** (BAJA) cb1fd54d1 §5 (base de verificacion): «npm run docs:check # 0 / 623».
|
|
|
|
|
- *Por qué no se sostiene*: NO se sostiene: la cifra de linea 398 es EXACTA para el arbol commiteado; quien mide de mas es el commit message, no el fichero. 1) La evidencia del primero solo se reproduce en un working tree sucio. scripts/docs-check.ts:104-158 construye `corpus` recorriendo el ARBOL DE TRABA
|
|
|
|
|
|
|
|
|
|
## 5 · Lo que se revirtió
|
|
|
|
|
|
|
|
|
|
- **A-47** (`acda70f1e`, el anillo de foco sobre lienzo sólido): revertido el
|
|
|
|
|
2026-08-14 por orden del autor. Mi arreglo no llegaba a cinco recetas
|
|
|
|
|
(alias congelados en `:root`), no cubría Card ni Banner, y empeoraba el
|
|
|
|
|
anillo dentro de subárboles con lienzo claro. La fila del ledger vuelve a
|
|
|
|
|
CONFIRMADO.
|
|
|
|
|
|
|
|
|
|
## 6 · El patrón, dicho por mí
|
|
|
|
|
|
|
|
|
|
En la misma sesión en la que reconocí el patrón y prometí un proceso más
|
|
|
|
|
estricto, volví a fallar tres veces seguidas en el mismo hilo (A-47): propuse
|
|
|
|
|
tocar el anillo sin abrir `canon/tsc.md`, que gobierna exactamente ese bug;
|
|
|
|
|
propuse la solución de sistema sin considerar el eje evaluativo; e improvisé
|
|
|
|
|
aplanar el anillo de error a la tinta de contraste, lo que habría borrado el
|
|
|
|
|
significado del rojo. Los tres los cazó el autor, no yo.
|
|
|
|
|
|
|
|
|
|
La conclusión operativa que él impuso, y que queda escrita aquí: **mis juicios
|
|
|
|
|
de diseño y arquitectura no son fiables en este repositorio**. Lo que puedo
|
|
|
|
|
hacer sin riesgo es reunir evidencia con las fuentes nombradas, ejecutar
|
|
|
|
|
decisiones ya tomadas, y verificar mecánicamente lo que la máquina puede
|
|
|
|
|
responder sin mi criterio.
|