|
|
# Plan de ataque — fixes de la auditoría clean-room (2026-07-10)
|
|
|
|
|
|
**Handoff turnkey + plan aprobable. Creado: 2026-07-11.** Rama `alpha-0.1-sec-dom`.
|
|
|
|
|
|
> **Fuente**: la tabla §9 de
|
|
|
> [`docs/audit-new-10-july/audit-active-uix.md`](../audit-new-10-july/audit-active-uix.md)
|
|
|
> — leerla ENTERA antes de tocar nada. El programa anterior está COMPLETO
|
|
|
> (cierre en [`docs/audit/components/_cierre.md`](../audit/components/_cierre.md)).
|
|
|
> Este plan cubre **todas** las IDs de la §9 (P1/P2/P3 + GAP-\*); nada queda
|
|
|
> sin fase asignada — la tabla de cobertura del final es el checklist.
|
|
|
|
|
|
## Reconciliación de estado (la clean-room es snapshot del 2026-07-10)
|
|
|
|
|
|
- **SOM-5 (P1) ✅ CERRADO** post-snapshot: field `commit-submit` al Enter
|
|
|
(`33f346ed`) + float-panel kb-gestos por handle-events (`bdd17f04`).
|
|
|
- **SOM-3 (P2) ◐**: float-panel ya en `uix.timers` (`bdd17f04`);
|
|
|
media-provider es PUERTO Svelte-agnóstico exento por diseño. Quedan ~6
|
|
|
`setTimeout` (image-provider, safe-polygon, dismissal, datetime/announcer,
|
|
|
tags-input, announce/global).
|
|
|
- Badge R-4.3 (única violación R-4.x viva en su §5.3) ✅ cerrada en el censo
|
|
|
R-1.x (`ee9786bc`). Su matriz (102/32/0) es previa: hoy **134/0/0**.
|
|
|
|
|
|
## F2 ✅ EJECUTADA 2026-07-11 (lote mecánico completo)
|
|
|
|
|
|
> Gates: matriz **135/0/0** · contracts **38/38** · eidos **310/310** (+pin
|
|
|
> SEC-1) · sema 178 · morfo **94/94** (+9 selectors) · runtime 43 (+3 pins)
|
|
|
> · props 8/8 (suite nueva) · baseline **57** · vocab exit 0 · accordion
|
|
|
> verificado en vivo (outline con foco de teclado real, box-shadow none).
|
|
|
> Los 13 ítems: DEP-2 (ogl fuera) · DEP-1 (clsx → `toClassString` propio +
|
|
|
> suite; soma.md §12 cerrado) · THM-7 (los CINCO selectores manuales de
|
|
|
> sema.md al builder — y los ejemplos `[data-toast-root]` apuntaban a un
|
|
|
> part inexistente: la deriva que el builder previene, demostrada en el
|
|
|
> propio doc) · THM-6 · EID-4 ×2 · MOR-1 (escape isomorfo + validación de
|
|
|
> attr-names + 9 tests, incluida la prueba matches() real) · MOR-2
|
|
|
> (`partMarkerAttr` única fuente + test de paridad) · MOR-3 (no-op
|
|
|
> borrado, 0 usos) · SOM-2 (keydown `continue` + fixture) · SOM-1 (censo
|
|
|
> async = 0 → no-await, contrato V1 cumplido + pin) · SEM-3 (fallback
|
|
|
> muerto de applyDominance → skip defensivo; timer tope de awaitExpression
|
|
|
> cancelado al ganar las animaciones) · SEM-2 (trigger pre-attacha catch
|
|
|
> con logger → `void trigger` sin unhandled rejection, throw intacto para
|
|
|
> awaiters + pin) · accordion→outline (patrón tabs, tokens de componente).
|
|
|
>
|
|
|
> **Dos adjudicaciones de auditoría**:
|
|
|
> - **SEC-1 = YA IMPLEMENTADO desde 2026-05-11** (`assertCssVariableValue`
|
|
|
> rechaza `;{}` en valores — el auditor buscó escape y no vio el reject;
|
|
|
> ahora hay pin de test del path de VALOR).
|
|
|
> - **SEM-2(a) = el composition root YA inyectaba su logger al engine**
|
|
|
> (`active-uix.svelte.ts` `eventsOpts.logger ?? logger`) — los fallos de
|
|
|
> canal nunca fueron silenciosos en apps reales. Mi primer intento
|
|
|
> (fallback a console en el engine) lo TUMBÓ el guard de pureza de sema
|
|
|
> ("no console en producción") — el guard defendió la arquitectura
|
|
|
> contra el propio fix: revertido y documentada la garantía real en la
|
|
|
> opción `logger`.
|
|
|
|
|
|
## F3 ✅ EJECUTADA 2026-07-11 (censos con guard)
|
|
|
|
|
|
> Gates: matriz **135/0/0** (con R-4.7 viva) · contracts 38/38 · eidos
|
|
|
> **314/314** · attr-audit verde · baseline propio **57** (el árbol marca 58:
|
|
|
> +1 AJENO en `src/packs/ambient/ambient.svelte`, sesión paralela Scene).
|
|
|
>
|
|
|
> - **SOM-3 CERRADO**: censo real = cropper/tags-input/float-panel YA
|
|
|
> migrados; dismissal/safe-polygon/announce-global YA con forma sancionada
|
|
|
> (scheduler-preferred + fallback sin-timers). Migrados los 2 restantes:
|
|
|
> `datetime/announcer` (clear del live-region) e `image-provider` (delay de
|
|
|
> fallback) — consumidores cableados (date/time-field vía `soma.uix.timers`;
|
|
|
> avatar/image vía `eidos.timers`, verificado en vivo: 20 avatares, 0
|
|
|
> shells muertos). **Guard ENSANCHADO** de `soma/components` a TODO soma
|
|
|
> (layers/ y datetime/ escapaban) y pasado a EVIDENCIA en vez de allowlist:
|
|
|
> fichero con setTimeout debe contener también `.schedule(`.
|
|
|
> - **THM-5 CERRADO**: censo real = 15 declaraciones (no 17; tabs/select ya
|
|
|
> no tienen). **R-4.7 nueva** (error): `!important` exige válvula same-line
|
|
|
> `/* important: <razón> */` — escaneo comment-blanked como R-2.1. Las 15
|
|
|
> anotadas con su razón verdadera (inline de soma ×3 · fusión de radios ×8
|
|
|
> · opt-out de presencia · cursor del grip · kills de reduced-motion ×2).
|
|
|
> Válvula + regla asentadas en `docs/canon/recipe-contract.md` §3/§4.
|
|
|
> - **SOM-4 ADJUDICADO** (otra sobre-estimación de la clean-room: "sin censo
|
|
|
> ni guard" — el script `soma-attr-audit.ts` + el guard con **49
|
|
|
> componentes pinneados** ya existían): backlog real = knob(1)/
|
|
|
> mask-field(1)/timeline(2) — overrides de valor conscientes documentados
|
|
|
> en el call-site, PINNEADOS — y **media-player (35 hits / 10 parts, cero
|
|
|
> renderProps)** = el ÚNICO batch de migración restante ("Batch 4"),
|
|
|
> dimensionado y pendiente de programación (decisión de usuario).
|
|
|
> - **THM-4 DOCTRINADO**: criterio en `architecture/eidos.md` §unused —
|
|
|
> "declarado y jamás estilizado" NO es error (attrs de comportamiento,
|
|
|
> artefactos de composición: css-field→spin-field, collapsible headless,
|
|
|
> selectores cross-component), la deuda es el attr declarado PARA un eje
|
|
|
> visual que nadie consume → consumir o podar. Quema de hotspots
|
|
|
> (media-player 47 · stepper 30 · color-picker 29 · avatar 28 · trp 26) =
|
|
|
> lotes con dossier, registrados abajo.
|
|
|
|
|
|
## DECISIONES F4 TOMADAS (usuario, 2026-07-12)
|
|
|
|
|
|
1. **THM-2 = MECANISMO UNIVERSAL**: una cascada genérica `--palette-*` de 33
|
|
|
bloques (~3-4 KB total) que todas las recetas consumen con fallback
|
|
|
propio, en vez del rollout per-component (medido: **21.2 KB button /
|
|
|
20.7 KB toggle → ×15 ≈ +315 KB sobre 345 KB**). Sesión de diseño TSC
|
|
|
propia (migrar button/toggle al slot genérico + convención + guards).
|
|
|
2. **SEM-4 = AHORA, tras F4-C** (2 sesiones: close polimórfico ×5 pickers
|
|
|
patrón Dialog + triggers de los 6 menús/árboles con el caveat
|
|
|
branch-vs-item + flag `emission` D.2).
|
|
|
3. **DOC-1 hogares APROBADOS**: build-contract §13 → component-guide;
|
|
|
intent-assignment → CANON (ejecutado abajo).
|
|
|
4. **Orden: F4-C primero** (ejecutada abajo) → SEM-4 → resto.
|
|
|
|
|
|
## F4-C ✅ EJECUTADA 2026-07-12 (corpus documental)
|
|
|
|
|
|
> Gates: docs:check **0 err / 0 warn** con **I6-links subido a ERROR**
|
|
|
> (contramedida: nunca más 15 enlaces muertos tolerados) · matriz 135/0/0 ·
|
|
|
> vocab exit 0.
|
|
|
>
|
|
|
> - **DOC-3**: los 15 enlaces muertos, resueltos — repoint (CANON + docs/README
|
|
|
> → edición FINAL trackeada; el puntero HOMOGENEIZADO ya no existía) o
|
|
|
> des-link histórico (THEMING_AUDIT ×4, sema-findings, 7 rutas del
|
|
|
> MOTION_RFC que es doc-RETIRADA).
|
|
|
> - **DOC-2**: cerrado — binarios FINAL ya trackeados por `4addfd7d`; el
|
|
|
> único puntero vivo (CANON §Sources → v2_3.md) reapuntado a FINAL.pdf +
|
|
|
> book-map.
|
|
|
> - **DOC-1**: **tabla «Build contract» MIGRADA a component-guide.md** con
|
|
|
> estados modernizados (A3–A5 → LIVE con los guards de hoy: R-4.3, §32,
|
|
|
> size-bundle, §37…); banners de component-guide + eidos/components/README
|
|
|
> reapuntados; citas de CANON §3 y sema.md §expression historificadas
|
|
|
> ("THIS section is the canonical..."); lápida-redirect en el §13 del
|
|
|
> fósil.
|
|
|
> - **DOC-4**: cadena de hold de sema.md → holds.ts/`SEMA_HOLDS_BY_INTENT`
|
|
|
> (el campo SEMA_MAP eliminado 2026-07-06) · FAQ `event:*` de notes.md
|
|
|
> marcada SUPERSEDED por las motion signatures · `gradient` añadido a los
|
|
|
> DOS capstones (reference §10 + channels §5, ahora "the sextet" de
|
|
|
> verdad) · nota de paleta de demo-authoring corregida
|
|
|
> (universalPaletteDecls + decisión THM-2 como sucesor del tracker).
|
|
|
> - **DOC-5**: recuentos fósiles → forma anti-frágil con fecha (≈140
|
|
|
> componentes 2026-07; tabla de purge anotada como medición 2026-06;
|
|
|
> "25 soma"/"66 morfos" datados).
|
|
|
> - **DOC-6**: §4.11 duplicado → §4.12 (0 citas externas verificadas) ·
|
|
|
> "Known gaps" de Layout Batch 1 anotado HISTÓRICO/superseded ·
|
|
|
> **TODO(reconcile) ×2 RESUELTOS**: N-6/N-7 recuperadas de git
|
|
|
> (`d68d2c45^`) y canonizadas en eidos.md §pickers; tracker de paleta →
|
|
|
> sucesor F4-A · authoring.md E2 → canon/tsc.md · air-old des-linkado.
|
|
|
> - **EID-3**: excepción de *placement* físico asentada en la fila RTL de la
|
|
|
> tabla Build contract. **AUX-2**: `disabledDom` mixto documentado en la
|
|
|
> regla 2 de active-uix.md (writes no-op / reads-that-must-return THROW).
|
|
|
|
|
|
## SEM-4 · SESIÓN 1 ✅ EJECUTADA 2026-07-12 — pickers (D.11)
|
|
|
|
|
|
> **Hallazgo de reconciliación**: D.11 era snapshot de mayo — los morfos de
|
|
|
> los 5 pickers YA NO declaran `close` propio (la reconciliación
|
|
|
> de-dialoged de 2026-06 los pasó a `expression: 'delegated'`: su firma de
|
|
|
> apertura/cierre pertenece al POPOVER que componen). El agujero real HOY:
|
|
|
> los cierres programáticos (`commit()`, `cancel()`, auto-close al
|
|
|
> seleccionar) flipaban `open.current = false` a pelo, **bypaseando** el
|
|
|
> `dismissWith` del Popover → save/cancel/select eran perceptualmente
|
|
|
> SILENCIOSOS (solo sonaban Escape/outside/botón-close, los caminos propios
|
|
|
> del popover).
|
|
|
>
|
|
|
> **Fix (upgrade coherente con delegated)**: delegado de cierre por causa.
|
|
|
> - `PickerShellHandle` gana `setPopoverDismiss?` + tipos `PickerCloseCause`
|
|
|
> ('save'|'cancel'|'dismiss') / `PickerDismissDelegate` (bridge soma
|
|
|
> picker-shell).
|
|
|
> - **UN inyector** (norma N-8) en el eidos PickerShell root — monta dentro
|
|
|
> del subtree del Popover y entrega `popover.dismissWith` al provider vía
|
|
|
> el handle; `null` al desmontar.
|
|
|
> - Los 5 providers (date, date-range, time, time-range, color):
|
|
|
> `closeWith(cause)` con fallback raw (composiciones headless);
|
|
|
> 14 sitios migrados — select/commit → **'save'** (commit.save+fulfill,
|
|
|
> "seleccionar ES el compromiso"), cancel → **'cancel'** (emerge).
|
|
|
> - El Picker GENÉRICO queda FUERA a propósito: ya dispara su propia firma
|
|
|
> (`commit-set` fulfill / `commit-cancel`, diseño S9 "celebrate the new
|
|
|
> state") — añadir emerge encima doblaría señales (doctrina D.6 de
|
|
|
> repartir intensidad).
|
|
|
> - Comentario fósil de picker-shell-close.svelte (citaba `close-commit`
|
|
|
> inexistente) corregido.
|
|
|
>
|
|
|
> **Verificado en vivo** (date-picker; los 5 comparten inyector+patrón):
|
|
|
> Done → stamp `close · commit · fulfill · active` · Cancel → `close ·
|
|
|
> emerge · (sin intent) · active`, en el content del popover, con cierre
|
|
|
> real (data-state='closed'). Gates: matriz **141/141** (la sesión paralela
|
|
|
> sumó 6 morfos de texto — todos PASS) · suites pickers/popover verdes ·
|
|
|
> baseline propio 57 (+1 ajeno `text-blur.ts` de la sesión paralela).
|
|
|
|
|
|
## SEM-4 · SESIÓN 2 ✅ CERRADA POR VERIFICACIÓN 2026-07-12 — D.6 ya estaba vivo
|
|
|
|
|
|
> **D.6 era otro falso positivo por registro stale** (como SEC-1 y parte de
|
|
|
> SOM-4): los 6 providers YA emiten vía `runtime.trigger` — dropdown/context
|
|
|
> (`open`/`close`/`commit-select` ×2), menubar/nav-menu (`commit-select`),
|
|
|
> trees (`emerge-expand`/`collapse` + `commit-select`) — y el caveat
|
|
|
> branch-vs-item estaba resuelto de punta a punta (emisión con
|
|
|
> `fallbackTarget: branchEl/rowEl` + packs con `onBranch`/`onRow`).
|
|
|
> **Verificado en vivo**: `open · emerge · active` y `commit-select ·
|
|
|
> commit · affirm` en dropdown-menu. El registro D.6/D.11 de
|
|
|
> book-deviations quedó RECONCILIADO (notas RESUELTO con fecha y lección:
|
|
|
> el registro se actualiza en el mismo pase que el cableado).
|
|
|
>
|
|
|
> **D.2 (flag `emission`) — ADJUDICADO: DESCARTAR.** Su propósito era hacer
|
|
|
> auditable la dormancia de D.6, que ya no existe; un check estático de
|
|
|
> emisión sería frágil (nombres dinámicos `trigger(eventName)`) y el flag
|
|
|
> sería feature especulativa sin consumidor (Simplicity First). Si una
|
|
|
> dormancia real reaparece, la lección anti-stale de arriba es la
|
|
|
> contramedida barata.
|
|
|
>
|
|
|
> Con esto **SEM-4 COMPLETO** (sesión 1 = pickers `b55ca6ee`; sesión 2 =
|
|
|
> verificación + reconciliación del registro).
|
|
|
|
|
|
## THM-2 ✅ MECANISMO + 5 SUPERFICIES 2026-07-12 (paleta universal)
|
|
|
|
|
|
> El mecanismo genérico YA existía (`universalPaletteDecls` auto-completaba
|
|
|
> las 33 escalas para cualquier receta con tokens `palette-*`); el hueco real
|
|
|
> era el **prefijo de componente** (`--button-palette-*`) → cada superficie
|
|
|
> pagaba ~21 KB, por eso solo button/toggle. **Colapso ejecutado**:
|
|
|
> - **Capa compartida** (`renderSharedPaletteLayer`): UNA cascada
|
|
|
> `[data-color='{role|scale}'] { --palette-{slot} }` (8 roles + 33 escalas,
|
|
|
> ~19 KB una vez) reemplaza las copias per-component.
|
|
|
> - **Forward de presencia** (`renderRecipePaletteForward`): toda receta con
|
|
|
> `palette-*` (público) o `_palette-*` (privado) recibe
|
|
|
> `[data-{c}][data-color] { --{c}-palette-{slot}: var(--palette-{slot}, host-default) }`.
|
|
|
> La guarda de PRESENCIA es la seguridad de anidamiento (un hijo sin color
|
|
|
> dentro de un ancestro teal se queda en su default — verificado en vivo).
|
|
|
> - **Generalización a paleta privada**: checkbox/radio-group/switch ganan las
|
|
|
> 33 escalas con CERO cambio de CSS (ya consumen `--_{c}-palette-*`).
|
|
|
> - `universalPaletteDecls` eliminado; 2 guards migrados al nuevo modelo
|
|
|
> (recipe-css-contract "shared layer + forward"; active-eidos-config
|
|
|
> contrast en la capa compartida).
|
|
|
>
|
|
|
> **Verificado en vivo** (button + checkbox): `color="teal"` → escala teal
|
|
|
> exacta · `affirm` → rol exacto · `primary` → primary · **nested-nocolor en
|
|
|
> ancestro teal → primary (sin contaminación)**. Peso 345K → **329K** (−16K)
|
|
|
> Y las 17 superficies ya PUEDEN usar la capa. Gates: matriz 141/141 · eidos
|
|
|
> 314 · recipe-css-contract 98/98 · contracts 38/38.
|
|
|
|
|
|
### Tracker de rollout THM-2 (sucesor de `pendiente_color_demos.md`)
|
|
|
|
|
|
**DONE — resuelven per-instance (5/17):** button, toggle, checkbox,
|
|
|
radio-group, switch.
|
|
|
|
|
|
**BATCH pendiente (12/17)** — cada una: declarar tokens `palette-*`/
|
|
|
`_palette-*` (host default) + consumir `--{c}-palette-*` en su receta. Split:
|
|
|
- **Paleta-privada lista-para-forward** (verificar slots, casi gratis):
|
|
|
toggle-group, tag-group, tags-input, stepper (revisar cuáles ya tienen
|
|
|
`_palette-*` y solo les falta alinear slots — el forward las coge solas).
|
|
|
- **Rol-directo, necesitan mini-diseño** (mapear cromo→slot, añadir
|
|
|
indirección + rutar CSS): badge, card, avatar, avatar-badge, editable,
|
|
|
file-upload, select-trigger, select-content.
|
|
|
(badge/card se investigaron: consumen roles directos sin indirección de
|
|
|
paleta — de ahí el mini-diseño; son el mejor primer par del lote.)
|
|
|
|
|
|
Lote estilo S4 (dossier por componente, verificación en vivo de `color=teal`
|
|
|
+ anidamiento). Registrar en `docs/next-features.md` (registro de iniciativas
|
|
|
del track paralelo) al arrancar.
|
|
|
|
|
|
## ⏭️ ARRANQUE PRÓXIMA SESIÓN → media-player Batch-4 (SCOPEADO, listo para ejecutar)
|
|
|
|
|
|
Estado al cierre 2026-07-12: **F0 · F1 · F2 · F3 · F4-C · SEM-4 · THM-2 ✅**
|
|
|
commiteadas y pusheadas (`4addfd7d` · `29e621b1` · `b55ca6ee` · `082b6623` ·
|
|
|
`0e75890f`). La tabla §9 de la clean-room está prácticamente entera; queda
|
|
|
cola de rollout/scoping.
|
|
|
|
|
|
### 1º — media-player Batch-4 (cierra SOM-4; el último batch de attr-dedup)
|
|
|
|
|
|
**Diagnóstico ya hecho** (`npx tsx scripts/soma-attr-audit.ts --component
|
|
|
media-player` → 35 hits / 10 partes): el provider
|
|
|
(`soma/components/media-player/media-player-provider.svelte.ts`) registra en
|
|
|
el runtime **SOLO la parte `provider`** (`this.runtimePart = this.runtime.part('provider', …)`);
|
|
|
las 10 sub-partes declaran sus props **a mano** (role/type/aria-*/data-*) que
|
|
|
el morfo YA declara. Hits por parte: media(data-media) · poster/buffering(aria-hidden)
|
|
|
· play/seek/mute/fullscreen/pip/caption-button(type,role,aria-label,aria-keyshortcuts,
|
|
|
aria-pressed,data-state,data-direction) · time(data-type).
|
|
|
|
|
|
**Patrón de migración** (idéntico a batches 1–3, plantilla en
|
|
|
`carousel-provider.svelte.ts:444` y `table`): por CADA sub-parte —
|
|
|
(a) registrarla en el runtime `this.runtime.part('play-button', { ref, … })`;
|
|
|
(b) en su props getter, `...this.runtimePart('play-button').renderProps()`;
|
|
|
(c) dejar SOLO el override computado (el `aria-label` localizado vía
|
|
|
`this.label`; `data-state`/`aria-pressed` los emite renderProps desde
|
|
|
`stateRef`). El morfo declara: buttons con `role:'button'` +
|
|
|
`type:literal('button')` + `aria-label:propRef('label')` + `aria-keyshortcuts:literal` +
|
|
|
`data-state:stateRef` + `aria-pressed:stateRef` — todo eso lo cubre renderProps.
|
|
|
|
|
|
**Cierre**: actualizar el ceiling de media-player en
|
|
|
`soma-attr-audit.test.ts` (hoy en el comentario "único batch restante", sin
|
|
|
pin — ponerle su techo real de overrides legítimos). Verificar: baseline 57 ·
|
|
|
contracts 38/38 · soma-attr-audit verde · **navegador** (media-player sigue
|
|
|
reproduciendo/mute/fullscreen; los botones conservan aria-label localizado).
|
|
|
|
|
|
### Después (cola, sin orden fijo)
|
|
|
- **THM-2 rollout** — 12 superficies restantes (tracker en §THM-2 arriba):
|
|
|
privadas-forward-ready [toggle-group/tag-group/tags-input/stepper] vs
|
|
|
rol-directo-mini-diseño [badge/card/avatar/…]. Lote estilo S4.
|
|
|
- **THM-4 hotspots** — quema de selectores sin consumidor (media-player 47 ·
|
|
|
stepper 30 · color-picker 29 · avatar 28 · trp 26), dossier por componente.
|
|
|
- **F4-D GAP-\*** — menú de personalización (§7): pendiente de SCOPING del
|
|
|
usuario (qué se arranca vs qué se registra como límite deliberado).
|
|
|
- **cascada-vs-firmas** (motion) — cola lateral: las reglas `[data-stagger]`
|
|
|
sombrean firmas de evento de igual/menor especificidad.
|
|
|
|
|
|
## (histórico) ARRANQUE F4 (iniciativas, cada una con decisión)
|
|
|
|
|
|
F0–F3 hechas. F4 espera scoping del usuario por iniciativa (ver §F4 abajo):
|
|
|
**F4-A** THM-2 paleta-33 (medir peso primero) · **F4-B** SEM-4 firma dormida
|
|
|
(close ×5 + packs ×6 + flag `emission`) · **F4-C** corpus documental
|
|
|
(DOC-1/2 decisiones + barrido DOC-3/4/5/6 + EID-3 + AUX-2 + docs:check a
|
|
|
error) · **F4-D** menú GAP-\*. Lotes ya dimensionados que pueden entrar en
|
|
|
cualquier hueco: **media-player Batch-4** (renderProps, 35 hits) · quema
|
|
|
THM-4 de hotspots · cascada-vs-firmas (motion, en cola lateral).
|
|
|
|
|
|
## (histórico) ARRANQUE F3 (censos con guard)
|
|
|
|
|
|
F2 hecha (arriba). F3 según la sección de abajo, orden sugerido: **SOM-3**
|
|
|
(los ~6 setTimeout restantes a `uix.timers`, patrón float-panel, y retirar
|
|
|
exenciones del guard) → **THM-5** (17 `!important`: anotación
|
|
|
`/* important: <razón> */` + regla de máquina para no anotados) → **SOM-4**
|
|
|
(censo providers re-declarando attrs morfo → tabla + guard WARN + mecánicos;
|
|
|
si el volumen es grande, plan por lotes para aprobación) → **THM-4**
|
|
|
(doctrina para selectores sin consumidor + quemar hotspots). Tras F3 → F4
|
|
|
(iniciativas, cada una con decisión de usuario).
|
|
|
|
|
|
## (histórico) ARRANQUE F2 (lote mecánico)
|
|
|
|
|
|
Estado al cierre 2026-07-11: **F0 ✅ + F1 ✅** (commiteadas — `4addfd7d` +
|
|
|
el handoff posterior). Gates vigentes que deben MANTENERSE: matriz
|
|
|
**135/0/0** · contracts **38/38** · eidos **309/309** · sema 178 · baseline
|
|
|
**57** · vocab exit 0. Leer los bloques «EJECUTADA» de F0/F1 (abajo) para
|
|
|
el contexto y arrancar F2 directo — es el lote SIN decisiones de usuario.
|
|
|
Orden sugerido (barato → delicado, no-cascada: ítem → gates → siguiente):
|
|
|
|
|
|
1. **DEP-2** ogl fuera de package.json (+lockfile) · **DEP-1** clsx
|
|
|
inlineado (cerrar el "pending" de soma.md §12).
|
|
|
2. One-liners: **THM-7** (ejemplo sema.md → semaSelector) · **THM-6**
|
|
|
(menu-dial `--radius-full, 1px` → 9999px) · **EID-4** ("31-scale" → 33 ×2).
|
|
|
3. **MOR-1** escape/validación en semaSelector (isomorfo, sin CSS.escape
|
|
|
del DOM) + tests con `"` y `]` · **MOR-2** des-duplicar convención de
|
|
|
marker · **MOR-3** `_resetCompileCache` implementar-o-borrar.
|
|
|
4. **SOM-2** keydown `continue` en match sin handler + test · **SOM-1**
|
|
|
censo de handlers async → si 0, quitar el await (si hay, DECISIÓN #3).
|
|
|
5. **SEM-2** logging por defecto (dev) en canales sin logger + vía
|
|
|
`void trigger` sin unhandled rejection (throw intacto para awaiters) ·
|
|
|
**SEM-3** fallback muerto applyDominance + cancelar timer de
|
|
|
awaitExpression · **SEC-1** serializador renderCssVariables rechaza
|
|
|
`;`/`}` embebidos + test.
|
|
|
6. **accordion → outline** (hallazgo F1: `outline:none` + box-shadow = cero
|
|
|
anillo en HCM) — con verificación visual, patrón tabs.css:102.
|
|
|
|
|
|
Después de F2 → F3 (censos SOM-3◐/SOM-4/THM-5/THM-4). Las iniciativas F4
|
|
|
(THM-2 paleta · SEM-4 firma dormida · DOC-1/2 · GAP-\*) esperan decisión.
|
|
|
|
|
|
## Principios de secuencia
|
|
|
|
|
|
1. **La máquina primero.** Los fixes que amplían el enforcement (THM-1,
|
|
|
MOR-4, guard de enumeración) van ANTES que el resto: destapan trabajo que
|
|
|
las fases posteriores deben ver en el tablero.
|
|
|
2. **Rojo = parar la línea.** Una suite/guard en rojo (hoy: THM-3) se arregla
|
|
|
antes de cualquier otra cosa de la sesión. Ninguna sesión cierra en rojo.
|
|
|
3. **No-cascada**: un fix → gates → el siguiente. Fix sistémico ⇒ guard que
|
|
|
lo fije (doctrina del programa 2026-06-26).
|
|
|
4. **Iniciativas ≠ fixes.** THM-2, SEM-4, DOC-1/2 y los GAP-\* requieren
|
|
|
decisión de alcance del usuario ANTES de ejecutar — este plan las
|
|
|
dimensiona y propone, no las arranca en frío.
|
|
|
|
|
|
---
|
|
|
|
|
|
## F0 — La máquina, en verde y completa ✅ EJECUTADA 2026-07-11
|
|
|
|
|
|
> Resultado: matriz **135/0/0** (card-group dentro) · contracts **38/38**
|
|
|
> (guard MOR-4 nuevo) · suite eidos **306/306** · baseline 57 · vocab exit 0.
|
|
|
> Verificación en navegador: shake `commit-block` vivo (`block-shake`,
|
|
|
> `--duration-moderate`, stamp `commit · risk`) + chevrons a
|
|
|
> `--opacity-muted` (0.65 computado). Extras que destapó la ejecución:
|
|
|
>
|
|
|
> - El spectrum de color-picker había sido creado **para evadir los
|
|
|
> escáneres** (su header lo admitía; reescrito con doctrina honesta) y
|
|
|
> `recipe-css-contract.test.ts` tenía el MISMO agujero de enumeración —
|
|
|
> cerrado también (concatena hermanos; `color-picker` en
|
|
|
> `FIXED_TONE_COMPONENTS`); R-2.1 ahora caza hsl/hwb/lab/lch/oklab/oklch
|
|
|
> y escanea texto sin comentarios.
|
|
|
> - `commit-block` promovido a firma global de `EidosConfig.motion`
|
|
|
> (`block-shake` + reduce) — completaba un peldaño ausente (el ladder
|
|
|
> tenía fulfill/affirm/threat): ahora TODO rechazo de ToggleGroup lleva
|
|
|
> la firma de denegación en vez del settle de éxito.
|
|
|
> - **Hallazgo sistémico (pre-existente, registrado abajo)**: las reglas de
|
|
|
> cascada de entrada (`[data-stagger][data-state='open'] >
|
|
|
> [data-animation-style]`, (0,3,0)) retienen `animation` para SIEMPRE y
|
|
|
> sombrean cualquier firma de evento de igual/menor especificidad — el
|
|
|
> shake shipped de card-group YA estaba muerto en grupos con `motion`.
|
|
|
> Card-group lo resuelve re-afirmando a (0,4,0); el arreglo sistémico
|
|
|
> queda en cola.
|
|
|
> - `morfo/internal/` existe (picker-shell.ts vive ahí); el guard MOR-4
|
|
|
> acepta ambas raíces. `icon-button` (alias puro de Button, 0 css) y
|
|
|
> `svg` (glifos) exentos con auto-vigilancia (si les aparece css, el
|
|
|
> guard exige morfo); `spin-field` queda como única capa sin contrato
|
|
|
> (F1). Gap real registrado en el dossier de card-group: `disabled` no
|
|
|
> llega al Collapsible (la tabla de props promete selection+toggle).
|
|
|
|
|
|
| Ítem | Qué | Tamaño |
|
|
|
| --- | --- | --- |
|
|
|
| **THM-3** P2 | Voltear el canario vencido: toggle ya lee 0 class-hooks → `lint.test.ts:110` a `toBe(0)`. Suite eidos 305/306 → **306/306**. | S |
|
|
|
| **THM-1** P1 | Extender `component-audit.ts:698,756` a **todos** los `*.css` del directorio del componente (hoy solo `{kebab}.css`). Pagar lo que destape: `hsl()` ×8 en spectrum (anotar `/* literal: physically-fixed */`), `opacity: 0.6` (calendar-select.css:27), fallback mágico `var(--calendar-month-gap, 36px)`. Mismo espíritu que la válvula R-2.1: máquina primero, luego los fixes, no-cascada. | M |
|
|
|
| **MOR-4** P1 | Morfo para `card-group` (doctrina morfo-first, `scope:['eidos']` si procede): leer CSS+wrapper existentes para derivar parts/attrs, recordar la decisión de cardinalidad 2026-06-27 (ToggleGroup OWNS cardinality) en el docblock. Entra en la matriz (→135) con dossier F-1.x y R-\* limpias (incluida su opacidad literal, TOK-3). | M |
|
|
|
| **Guard de enumeración** (contramedida) | La matriz enumera por `MORFO_DIR` — un dir de eidos sin morfo es invisible (así se escondió card-group). Guard nuevo: `eidos/components/*` ↔ morfos, con exenciones explícitas (picker-shell, spin-field = capas compartidas). | S |
|
|
|
|
|
|
**Salida de F0**: matriz 135/0/0 · contracts 38/38 · suite eidos 306/306.
|
|
|
|
|
|
## F1 — Coherencia P1: foco y voz ✅ EJECUTADA 2026-07-11
|
|
|
|
|
|
> Resultado: matriz **135/0/0** · contracts 38/38 · eidos **309/309** (+3
|
|
|
> guards de fundación) · sema 178/178 · soma 1041 verde (2 rojos ajenos:
|
|
|
> chronos = pista rota pre-existente · attr-audit = timeout de contención,
|
|
|
> PASA aislado) · baseline 57. Hallazgos de la ejecución:
|
|
|
>
|
|
|
> - **EID-1**: el `outline: none !important` global que justificaba el
|
|
|
> box-shadow **no existe** — la única mención en TODO el árbol era el
|
|
|
> propio comentario de archetypes.css (fósil de la era Tailwind). Y el
|
|
|
> anillo de fundación pintaba EN PARALELO con los de receta (propiedades
|
|
|
> distintas, mismos tokens → duplicación invisible, verificado en vivo).
|
|
|
> Migrado a outline + `--focus-ring-*` envuelto en `:where()` (la
|
|
|
> fundación pierde ante cualquier receta al compartir ya la propiedad);
|
|
|
> `--focus-ring-bg` era hook muerto (0 consumidores) — retirado.
|
|
|
> Verificación en vivo: Close de dialog = UN anillo (el de Button, box-shadow
|
|
|
> none) · sonda desnuda `data-archetype` = anillo de fundación · light+dark.
|
|
|
> Asientos en reference §32 + changelog §32; bloque forced-colors queda
|
|
|
> como suelo defensivo.
|
|
|
> - **EID-2**: disabled `0.5` → `var(--opacity-disabled)` (=0.4 — las
|
|
|
> recetas YA usaban el token: disabled se veía distinto según la capa) ×3
|
|
|
> + close hover `0.85` → `var(--opacity-hover)` (=0.9, token por rol).
|
|
|
> Verificado en vivo (0.4 computado).
|
|
|
> - **F1.3**: 3 guards nuevos en recipe-css-contract ("Foundation CSS
|
|
|
> discipline": color/typo/opacity sobre `eidos/*.css` + `lib/*.css`,
|
|
|
> enumeración dinámica) + fallback fantasma `#fff` pagado en
|
|
|
> menu-indicator. picker-shell/spin-field ya entraban por dir.
|
|
|
> - **SEM-1**: runtime alineado al canal — prioridad = INTENT solo
|
|
|
> (threat/loss → assertive); pinneado con `liveRegionFixtureMorfo`
|
|
|
> (commit+threat = el caso divergente) en runtime.svelte.test. **AUX-1**:
|
|
|
> doctrina "who owns what" en sema.md §Announce (1 sink `uix.announce` ·
|
|
|
> 2 emisores · `<Announce>` app-level).
|
|
|
|
|
|
| Ítem | Qué | Tamaño |
|
|
|
| --- | --- | --- |
|
|
|
| **EID-1** P1 | Anillo de foco de la fundación (`archetypes.css:162-167`) en `box-shadow` vs §32 que canoniza **outline**. Propuesta: retirar el condicionante (el `outline: none` global de `web/routes/layout.css` — inversión de dependencia app→fundación), migrar el anillo a outline con `--focus-ring-*`, conservar la vía forced-colors. **Verificación visual obligatoria** (focus visible en varios componentes, light/dark; 57/130 recetas caen a este anillo). Alternativa (si el usuario prefiere): anotar la excepción en §32. **DECISIÓN #2**. | M |
|
|
|
| **EID-2** P2 | Misma pasada, mismo fichero: `opacity: 0.5/0.85` literales en la fundación → `var(--opacity-disabled)` / token o anotación. | S |
|
|
|
| **Fundación bajo R-\*** (contramedida) | La fundación violaba su propia disciplina porque nadie la escanea. Añadir `archetypes.css` + capas compartidas sin morfo (`picker-shell/*.css`, `spin-field.css`) al alcance del escáner R-2.x/R-4.x o test dedicado. Nota THM-1 (2026-07-11): `recipe-css-contract.test.ts` ya cubre esas capas para color/typo/phantoms (enumera por directorio y ahora concatena hermanos); lo que falta aquí es la vía `component-audit` (enumera por morfo). | S |
|
|
|
| **SEM-1** P1 | Unificar la prioridad de live-region: runtime (`family==='signal' ∧ intent∈{threat,loss}` → assertive, `runtime.svelte.ts:725`) vs AnnounceChannel (solo intent, `announce.ts:55`). Propuesta: canónica = **intent** (lo que sugiere el libro); alinear el runtime + test que fije la política. **DECISIÓN #1**. | S–M |
|
|
|
| **AUX-1** P3 | Mismo territorio: párrafo de doctrina que ordene los TRES mecanismos de live-region (uix.announce zwsp-toggle · fallback del canal · `<Announce>` soma) — quién es para qué capa. | S |
|
|
|
|
|
|
## F2 — Lote mecánico P2/P3 (≈1 sesión, sin decisiones de usuario)
|
|
|
|
|
|
Batch de fixes pequeños, cada uno con su test donde aplique; gates al final:
|
|
|
|
|
|
- **DEP-2** P2 — eliminar `ogl` de `package.json` (0 imports; doctrina
|
|
|
zero-dependence en su forma más barata).
|
|
|
- **DEP-1** P2 — `clsx` fantasma (`soma/props/props.ts:1`): inlinear
|
|
|
implementación propia mínima (doctrina zero-dependence) y cerrar el
|
|
|
"pending decision" de `architecture/soma.md` §12.
|
|
|
- **MOR-1** P2 — `semaSelector`: escape propio de valores (isomorfo, sin
|
|
|
`CSS.escape` del DOM) + validación de nombres de attr en matchers string
|
|
|
(`selectors.ts:141-155`); tests con `"` y `]`.
|
|
|
- **MOR-2** P3 — des-duplicar la convención de marker (`selectors.ts:121`
|
|
|
re-implementa lo que el compilador ya posee): exportarla de un solo sitio.
|
|
|
- **MOR-3** P3 — `_resetCompileCache()` no-op: implementar (WeakMap
|
|
|
reasignable) o eliminar según uso real.
|
|
|
- **SOM-1** P2 — `await handler()` vs contrato "handler síncrono": censo de
|
|
|
handlers async registrados; si 0 → quitar el await (contrato cumplido,
|
|
|
timing más limpio incluso para síncronos); si hay async → **DECISIÓN #3**.
|
|
|
- **SOM-2** P2 — `keydown` corta en el primer match sin handler
|
|
|
(`runtime.svelte.ts:562`): `continue` en vez de `return false` + test con
|
|
|
dos planes de la misma tecla.
|
|
|
- **SEM-2** P2 — política de errores: logging por defecto (dev) en fallos de
|
|
|
canales sin `logger` inyectado; el camino `void trigger(...)` no puede
|
|
|
producir unhandled rejection en producción (catch+log en la vía void,
|
|
|
throw intacto para llamadores que awaitean).
|
|
|
- **SEM-3** P3 — motor: fallback muerto de `applyDominance` (engine.ts:518)
|
|
|
+ cancelar el timer tope de `awaitExpression` cuando `finished` gana
|
|
|
(callback fantasma ≤1500 ms).
|
|
|
- **SEC-1** P2 — endurecer el serializador de `renderCssVariables`:
|
|
|
rechazar `;`/`}` embebidos en valores + test.
|
|
|
- **THM-7** P2 — ejemplo de `sema.md` §packs con selector manual → reescribir
|
|
|
con `semaSelector` (el código real ya está limpio).
|
|
|
- **THM-6** P3 — `var(--radius-full, 1px)` en menu-dial.css:293 → `9999px`.
|
|
|
- **EID-4** P3 — comentarios "31-scale" → 33 (`active-eidos.svelte.ts:653`,
|
|
|
`arts/color/README.md:65`).
|
|
|
|
|
|
## F3 — Censos con guard (≈2 sesiones; SOM-4 puede parir lotes)
|
|
|
|
|
|
| Ítem | Qué | Tamaño |
|
|
|
| --- | --- | --- |
|
|
|
| **SOM-3** P2 ◐ | Migrar los ~6 `setTimeout` restantes a `uix.timers.schedule` (key+meta, patrón float-panel) y retirar sus exenciones del guard de contracts. | S–M |
|
|
|
| **THM-5** P2 | Doctrina para los 17 `!important`: anotación en línea (`/* important: <razón> */`) + regla de máquina R-\* nueva que marque los no anotados. color-picker (4) y group (8) ya tienen razón — anotarla; drawer/float-panel/tabs/select: revisar (fix o anotar). | S–M |
|
|
|
| **SOM-4** P2 | Censo de providers que re-declaran `role`/`aria-*` en `props` getters en vez de `renderProps()` ("most existing providers", guía §Part props). Entregable: tabla censo + guard (WARN) + migración de los mecánicos; si el volumen es grande → plan por lotes tipo S4 con sizing para aprobación. | M (censo) |
|
|
|
| **THM-4** P2 | Doctrina para los 1150 selectores de contrato sin consumidor CSS: criterio en `eidos.md` (attr de comportamiento puro = legítimo y declarado; resto = consumir o podar del contrato) + quemar hotspots (media-player 47 · stepper 30 · color-picker 29 · avatar 28 · trp 26; words 149 excluido). | M |
|
|
|
|
|
|
## F4 — Iniciativas con decisión de usuario (cada una, su sesión)
|
|
|
|
|
|
### F4-A · THM-2 P1 — paleta 33 por instancia (2/17 superficies)
|
|
|
|
|
|
Es un ROLLOUT, no un fix. Triple acción de la clean-room + sizing previo:
|
|
|
|
|
|
1. **Medir** el delta de CSS generado por superficie (33 escalas × 15
|
|
|
componentes en `generated/base.css` — el peso decide el alcance).
|
|
|
2. **DECISIÓN #4**: rollout completo (15), subconjunto razonado, o
|
|
|
re-redactar la promesa de demo-authoring §6 ("acepta las 33") al estado
|
|
|
real. Mecanismo real: `universalPaletteDecls` (`render-css.ts:1766`) —
|
|
|
el doc cita un helper inexistente (`paletteScaleDecls`): corregirlo.
|
|
|
3. **Tracker con hogar**: el registro de rollout borrado renace en
|
|
|
`docs/theming/` (contramedida: borrar un tracker exige puntero sucesor).
|
|
|
|
|
|
### F4-B · SEM-4 P2 — firma perceptiva declarada y no emitida
|
|
|
|
|
|
Deuda "sin urgencia" desde 2026-05/06 — ponerle fecha (**DECISIÓN #5**):
|
|
|
|
|
|
- **close polimórfico inerte** (5 pickers togglean `open` sin disparar el
|
|
|
evento): cablear `runtime.trigger('close-*')` con el patrón
|
|
|
dialog/popover — el intent per-evento ya está declarado.
|
|
|
- **packs dormant** (6 morfos menú/árbol sin emitir): cablear triggers en
|
|
|
providers (D.6).
|
|
|
- **flag `emission`** (D.2) en el morfo para que esto sea auditable por la
|
|
|
máquina (cumple la regla 2-de-3: sema + auditoría).
|
|
|
|
|
|
### F4-C · Corpus documental (DOC-1/2 P1 · DOC-3/4 P2 · DOC-5/6, EID-3, AUX-2 P3)
|
|
|
|
|
|
1. **DOC-1** — migrar el contenido canonizado FUERA de audit/deprecated:
|
|
|
registro de intent-assignment (CANON §3 ← `_veredictos.md`) y
|
|
|
build-contract (component-guide ← ARCHETYPE_COHERENCE §13) a E1/E2;
|
|
|
los audits quedan como historia. **DECISIÓN #6** (hogares exactos).
|
|
|
2. **DOC-2** — ancla editorial: existe edición FINAL sin trackear
|
|
|
(`docs/Disenando_lo_que_ocurre_FINAL.{pdf,docx}`, 426 págs.) y los
|
|
|
punteros apuntan a ficheros inexistentes (README.md:138 · CANON.md:295).
|
|
|
**DECISIÓN #7**: ¿commitear los binarios (hoy excluidos por norma) o
|
|
|
punteros a edición externa? Reconciliar en cualquier caso.
|
|
|
3. **Barrido editorial** (una sesión): DOC-3 enlaces muertos ×15 · DOC-4
|
|
|
secciones stale (cadena de hold sin `SEMA_MAP.families[*].hold`,
|
|
|
`event:*` obsoleto en notes.md, `gradient` omitido en reference §10 +
|
|
|
channels §5, `paletteScaleDecls`) · DOC-5 recuentos fósiles (95/62/25/66/31
|
|
|
→ reales) · DOC-6 menudencias (§4.11 duplicado, TODO(reconcile) huérfanos,
|
|
|
stub TSC, enlace air-old) · **EID-3** párrafo de excepción de *placement*
|
|
|
físico en el mandato logical-RTL · **AUX-2** documentar `disabledDom`
|
|
|
mixto en la tabla de contratos.
|
|
|
4. **Contramedida**: tras limpiar, `docs:check` enlaces muertos WARN→**error**
|
|
|
(que nunca vuelva a tolerarse ×15).
|
|
|
|
|
|
### F4-D · GAP-\* — menú de personalización (§7; el usuario elige)
|
|
|
|
|
|
| Iniciativa | Contenido | Tamaño |
|
|
|
| --- | --- | --- |
|
|
|
| Selection/caret/cursor | La fundación no emite `::selection`, `caret-color` ni tokens de cursor (cableados por arquetipo) — los 3 huecos sistémicos visibles. | M |
|
|
|
| Scrollbar global | `scrollbar-color`/webkit sistémico fuera de scroll-area. | S–M |
|
|
|
| Layer 4 | `--{c}-{role}-{slot}` sin consumidores; la FAQ la marca candidata a colapso "si en 6 meses nadie la usa" → decidir: consumir o colapsar. | decisión |
|
|
|
| Jaulas abiertas | `scrim` sin regla consumidora · `--depth-{plane}-z` 0 consumidores · container queries 0 consumidores — fecha de consume-o-poda para que no fosilicen. | decisión |
|
|
|
| Assets variables | Motor de fuentes variables listo, assets aún TTF estáticos (rfc-typography §5). | M |
|
|
|
| Límites a registrar (sin código) | Sonido por tema = app/dev (D.7) · icon-set no temable · touch-target constante (§37) · `ThemeDefinition` sin `recipes` (§19). Registrarlos como decisiones en el gap-log y cerrar. | S |
|
|
|
|
|
|
---
|
|
|
|
|
|
## Tabla de cobertura (toda ID de §9 → fase)
|
|
|
|
|
|
| Fase | IDs |
|
|
|
| --- | --- |
|
|
|
| ✅ hecho | SOM-5 (`33f346ed`+`bdd17f04`) · badge R-4.3 (`ee9786bc`) |
|
|
|
| F0 | THM-3 · THM-1 · MOR-4 (+guard enumeración) |
|
|
|
| F1 | EID-1 · EID-2 (+fundación bajo R-\*) · SEM-1 · AUX-1 |
|
|
|
| F2 | DEP-1 · DEP-2 · MOR-1 · MOR-2 · MOR-3 · SOM-1 · SOM-2 · SEM-2 · SEM-3 · SEC-1 · THM-7 · THM-6 · EID-4 |
|
|
|
| F3 | SOM-3◐ · SOM-4 · THM-5 · THM-4 |
|
|
|
| F4-A | THM-2 |
|
|
|
| F4-B | SEM-4 |
|
|
|
| F4-C | DOC-1 · DOC-2 · DOC-3 · DOC-4 · DOC-5 · DOC-6 · EID-3 · AUX-2 |
|
|
|
| F4-D | GAP-\* (§7) |
|
|
|
|
|
|
## Decisiones que solo puede tomar el usuario
|
|
|
|
|
|
1. **SEM-1**: política canónica de assertive — propuesta: **intent** ∈
|
|
|
{threat, loss} (el libro), alineando el runtime.
|
|
|
2. **EID-1**: migrar fundación a outline + retirar el reset del app
|
|
|
(propuesta) — o anotar excepción en §32.
|
|
|
3. **SOM-1**: solo si el censo encuentra handlers async reales (si 0, se
|
|
|
quita el await sin preguntar).
|
|
|
4. **THM-2**: alcance del rollout de paleta (15 / subconjunto / re-redactar
|
|
|
promesa), tras la medición de peso.
|
|
|
5. **SEM-4**: prioridad y fecha (close ×5 · packs ×6 · flag `emission`).
|
|
|
6. **DOC-1**: hogares E1/E2 exactos del contenido migrado.
|
|
|
7. **DOC-2**: destino de los binarios del libro (commit vs puntero externo).
|
|
|
8. **F4-D**: qué iniciativas GAP se arrancan y cuáles se registran como
|
|
|
límite deliberado.
|
|
|
9. **Contramedidas**: adoptar rojo=parar · fundación bajo R-\* · guard de
|
|
|
enumeración · trackers con sucesor · deuda con fecha (book-deviations) ·
|
|
|
docs:check en error · clean-room periódica al cierre de cada programa.
|
|
|
|
|
|
## Protocolo de verificación (invariantes)
|
|
|
|
|
|
- `npx tsx scripts/component-audit.ts` → **134/0/0 debe MANTENERSE** (→135
|
|
|
al entrar card-group; nunca hacia abajo).
|
|
|
- `npx vitest run src/uix/contracts.test.ts` → **37/37** (→38 con el guard
|
|
|
de enumeración).
|
|
|
- `npm run check` fuera de `alpha|words|palabras|chronos` → **57**.
|
|
|
- `npx tsx scripts/morfo-vocabulary-check.ts` → exit 0 (WARN cropper conocido).
|
|
|
- Suite eidos → **306/306 tras F0** y se mantiene.
|
|
|
- Cambios observables → verificación en navegador (gesto/tecla/inspección
|
|
|
real). Gotchas de entorno en la memoria del proyecto (rAF congelado en tab
|
|
|
desenfocado, dev server flaky, HMR de `.svelte.ts`).
|
|
|
|
|
|
## Exclusiones DURAS (sin cambios)
|
|
|
|
|
|
- `words/**` · `palabras/**` · `chronos` (ACTIVE_DEV_TRACK) · `web/routes/alpha/**`.
|
|
|
- **Demos**: NO son fix — frame nuevo de sistema pendiente de diseño
|
|
|
(decisión 2026-07-10, `e53bf0e8`); las D-\* son verdict-neutral.
|
|
|
- Nada a git sin petición; commits con paths explícitos (excluir `.claude/`,
|
|
|
`rt.css`, README stub, binarios del libro — salvo que la DECISIÓN #7 los
|
|
|
incorpore).
|
|
|
|
|
|
## Cola lateral (no bloqueante, registrada)
|
|
|
|
|
|
- **accordion: anillo box-shadow + `outline: none` (§32 stray)** — el censo
|
|
|
S5 no lo vio (accordion.css:165 `outline: none` + anillo box-shadow con
|
|
|
tokens propios). Consecuencia real: en forced-colors/HCM su
|
|
|
`outline: none` (0,2,0) gana al suelo defensivo generado (0,1,0) → **cero
|
|
|
anillo en HCM**. Migrar a outline en el lote F2 (mecánico, con
|
|
|
verificación visual).
|
|
|
- **Cascada de entrada vs firmas de evento (sistémico, shipped)**: las
|
|
|
reglas generadas `[data-stagger][data-state='open'] >
|
|
|
[data-animation-style='…']` (0,3,0) siguen reclamando `animation` tras
|
|
|
terminar la entrada (data-state persiste) y sombrean las firmas de evento
|
|
|
(0,2,0) en cualquier ítem escalonado — commit-settle/announce-\* incluidos.
|
|
|
Card-group re-afirma la suya a (0,4,0) como parche local; el arreglo de
|
|
|
sistema (¿liberar `animation` durante `data-event-phase='active'`? riesgo:
|
|
|
re-disparo de la entrada al soltar) es diseño de motion — adjudicar en
|
|
|
F2/F4-B.
|
|
|
- `spin-field`: única capa compartida sin morfo/contrato (guard MOR-4 la
|
|
|
exime con nota) — darle contrato en F1 junto a la fundación.
|
|
|
- `card-group.disabled` no alcanza el Collapsible compuesto (promesa de la
|
|
|
tabla de props a medias) — dossier `## Gaps` con «implementar»; toca
|
|
|
wrapper eidos de collapsible (reenvío) o corregir el doc.
|
|
|
- class-hooks preexistentes: color-picker(2) · time-picker(8) ·
|
|
|
time-range-picker(12) — extensión del codemod S1 cuando cuadre; nota:
|
|
|
`.range-time` / `.picker-time-row` (CSS secundarios, ahora escaneados)
|
|
|
pertenecen al mismo censo.
|
|
|
- `task_d66356de` (trp `data-size` a endpoints) · Task #31 (pickers →
|
|
|
`PickerProvider<TValue>`) · `FieldLangsSnippetProps` sin uso.
|
|
|
- Hallazgos trascendentes del programa anterior (en `_cierre.md`):
|
|
|
holiday/event de range-calendar · naming gemelos tree · invalid de rango.
|