You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/continue.md

296 lines
14 KiB

This file contains ambiguous Unicode characters!

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

# Continue tomorrow
Fecha de corte: **2026-05-27**. Rama: `active-uix`. Working tree con cambios
sin commitear listos para push.
## TL;DR de la sesión
Sesión maratón del Token Scope Contract — del bug del toggle (ya conocido)
hasta cobertura universal sin excepciones arquitectónicas:
1. **Diagnóstico inicial**: usuario reporta "el toggle no funciona, el
color del intent no cambia". Eager-resolution de CSS custom properties
en el cascade del toggle.
2. **TSC v1 → v2 → v2.1 → v2.2**: 4 iteraciones del Token Scope Contract.
Cada una cerrando un gap (scope explícito, álgebra de cobertura,
private tokens, multi-part + composition).
3. **Universal migration**: 18 componentes con `data-color` migrados a TSC
(15 con TSC v2.1, + 3 con extensiones v2.2 de hoy).
4. **Bug crítico post-composition**: la toggle-group composition
correctamente override `--toggle-palette-*` pero el cascade colapsaba
downstream porque los derived tokens (`--toggle-solid-on-bg` etc.)
viven en scope `[data-toggle]` (sibling, no ancestor, de
`[data-toggle-group-item]`). Fix: inlined derivations en
toggle-group.css con palette-direct refs.
5. **Bundle JIT purge** (`scripts/eidos-purge.ts`): tool standalone que
tree-shakes el `generated/base.css` por componente, var() ref,
data-attr y component import. Reduce ~50% el bundle final.
6. **Docs**: THEMING.md (~1700 líneas) como referencia canónica del
theming. CLAUDE.md con 5 hand-offs del 2026-05-27. Eidos README
actualizado.
## Tareas completadas hoy (resumen)
Total: 87 tareas TaskList. Sprint TSC ocupa #50–#87. Highlights:
- **TSC v1** (#50–#56): primera versión — `scope`/`depends` explícitos,
generator agrupando por scope.
- **TSC v2** (#57–#62): álgebra de scope (ScopeSet covers), cross-axis
collision detection, var() auto-inferred deps, color:* rename.
- **P0–P2 housekeeping** (#63–#68): rename `--{c}-color-{role}-{slot}` →
`--{c}-{role}-{slot}`, JIT purge script.
- **CONSOL + GAP** (#69–#73): consolidación de docs, universal anti-eager-
resolution guard test.
- **UNIV** (#75–#79): private tokens (`_` prefix) + migración universal
de 13 componentes.
- **EXT** (#80–#86): TSC v2.2 — multi-part `parts` + cross-recipe
`composition` + 3 componentes restantes migrados (`select`,
`toggle-group`, `avatar`) + docs.
- **EXT-FIX** (#87): bug del toggle-group color cascade tras la
composition migration.
## Patrones canon nuevos en esta sesión
### Token Scope Contract (TSC) — la fuente de verdad
Cada recipe token tiene un **scope explícito** que materializa el selector
CSS donde se emite. El generator infiere deps de los `var()` y valida
álgebra de cobertura. **Imposible introducir el bug eager-resolution si
declaras tokens en TSC** — el validator lo rechaza antes de generar CSS.
Formas:
```ts
recipes.toggle = {
'height-md': '32px', // shorthand → root
'solid-on-bg': { // single decl
value: 'var(--toggle-palette-solid)', scope: 'host'
},
'palette-solid': { // multi-decl
declarations: [
{ value: 'var(--toggle-neutral-solid)', scope: 'host' },
{ value: 'var(--toggle-affirm-solid)', scope: 'color:affirm' }
]
}
}
```
### TSC v2.2 — `parts: [...]` para multi-part scope
```ts
'_accent-track': {
parts: ['trigger', 'content'],
declarations: [
{ value: 'var(--select-primary-track)', scope: 'host' },
{ value: 'var(--select-affirm-track)', scope: 'color:affirm' }
]
}
// → emits:
// [data-select-trigger], [data-select-content] { --_select-accent-track: ... }
// [data-select-trigger][data-color='affirm'], [data-select-content][data-color='affirm'] { ... }
```
Único consumer hoy: `select` (Trigger + Content). Cualquier componente
que tenga atributos cascadeados per-part (no en root) usa este patrón.
### TSC v2.2 — `composition: { ... }` para cross-recipe override
```ts
'toggle-group': {
gap: 'var(--space-1)',
composition: {
toggle: { // foreign recipe
targetSelector: '[data-toggle-group-item]',
tokens: {
'palette-solid': {
declarations: [
{ value: 'var(--toggle-affirm-solid)', scope: 'color:affirm' },
{ value: 'var(--toggle-risk-solid)', scope: 'color:risk' }
]
}
}
}
}
}
// → emits:
// [data-toggle-group][data-color='affirm'] [data-toggle-group-item] {
// --toggle-palette-solid: var(--toggle-affirm-solid);
// }
```
Único consumer hoy: `toggle-group`. Pattern reutilizable para futuros
wrappers compositivos (button-group, nav-menu, etc.).
### Private tokens (`_` prefix)
Recipe key `_palette-solid` → CSS var `--_toggle-palette-solid` (con
underscore prefix). NO aparece en el public CSS contract. Solo accesible
desde la propia CSS recipe del componente. Convención: usar para slots
intermedios de derivation que no quieres exponer como theming knobs.
### Inline derivation cuando el ancestor scope no aplica
**Anti-pattern**: leer `var(--{foreign-component}-derived-token)` desde
un elemento que NO es descendant del scope donde se declaró ese token.
Resultado: undefined → cascade colapsa.
**Pattern correcto**: inline la derivation expression localmente. Ejemplo
en `toggle-group.css` para `[data-toggle-group-item]` — replica las
expressions de `recipes/base.ts > toggle.{solid,outline,ghost}-*`
directamente. Duplicación documentada y aceptada como trade-off.
## Trabajo acumulado SIN commitear
```
Modificados (eidos + soma touched durante TSC sprint):
M src/uix/eidos/components/avatar/avatar.css
M src/uix/eidos/components/badge/badge.css
M src/uix/eidos/components/button/button.css
M src/uix/eidos/components/card/card.css
M src/uix/eidos/components/checkbox/checkbox.css
M src/uix/eidos/components/editable/editable.css
M src/uix/eidos/components/file-upload/file-upload.css
M src/uix/eidos/components/radio-group/radio-group.css
M src/uix/eidos/components/select/select.css
M src/uix/eidos/components/stepper/stepper.css
M src/uix/eidos/components/switch/switch.css
M src/uix/eidos/components/tag-group/tag-group.css
M src/uix/eidos/components/tags-input/tags-input.css
M src/uix/eidos/components/toggle-group/toggle-group.css
M src/uix/eidos/components/toggle/toggle.css
M src/uix/eidos/README.md
M CLAUDE.md
M package.json (npm script para eidos:purge añadido)
Modificados (words component sprint en paralelo — no este chat):
M src/uix/eidos/components/words/*
M src/uix/soma/components/words/*
M src/uix/words/README.md
M web/routes/uix/components/words/*
Eliminado:
D src/docs/libro_semantica_completo.txt (reemplazado por .docx)
Untracked (TSC v2.2 + auxiliares):
?? scripts/eidos-purge.ts
?? scripts/probe-*.ts (5 probe scripts del debug session)
?? src/docs/Disenando_lo_que_ocurre_manuscrito_completo_revisado_v2.docx
?? src/uix/eidos/THEMING.md
?? src/uix/eidos/THEMING_AUDIT_2026-05-27.md
?? src/uix/eidos/components/words/* (slash menu, family menu, code lang picker)
?? src/uix/soma/components/words/components/words-slash-menu.svelte
?? src/uix/soma/components/words/engine/code-highlight.ts
?? src/uix/words/references/* (4 audit docs + 1 screenshot)
```
### Variants son canon — NO theme-extensibles
Decisión arquitectónica documentada hoy en `THEMING.md §19`. Los
variants (`solid`, `outline`, `ghost`, `soft`, `surface`, etc.) son
fijos a nivel del framework — paralelos a las 8 sema families. El
theme solo cambia palette/shadows. La fuente de verdad es la const
`EIDOS_VARIANTS` en `lib/types.ts` con 5 archetypes
(`control` / `selection` / `chip` / `marker` / `tabs`); los unions
TS se derivan de ella via `[number]` indexed access.
Variants component-specific (Banner `inline`/`overlay`/`persistent`,
Spinner `bars`/`dots`/`ring`, Button `'plain'`) viven en cada
`components/{c}/types.ts`. El lint
`recipe-css-contract.test.ts > variant CSS selectors per component
match the declared type union` valida bidireccionalmente que CSS
selectors y type unions coincidan.
## Words extension system — estado y siguiente sprint
**Hecho** (commits `1805b081` skeleton + `088d31ec` F2.3a):
- F1.1 fix evento `contact-focus` molesto (transition-only + popover scope)
- F1.2 declarar 9 `data-*` hardcoded en morfo
- F1.3 i18n keys kebab-case
- F1.4 canonizar 9 event names a forma `{family}-{verb}-{variant}`
- F1.5 toolbarLayout `grouped|inline` con ResponsiveProp
- F2.1 audit + design de `WordsExtension` interface (9 hooks)
- F2.2 skeleton: `extension-types.ts` + `extension-registry.ts` con 14 tests verdes
- F2.3a tipos de table movidos a `extensions/table/types.ts` con re-export en `engine/document.ts`
**F2.3 hecho** (sesión de hoy, 5 checkpoint commits + 143/143 tests verdes después de cada uno):
- **F2.3a** ✅ — table types → `extensions/table/types.ts` (commit `088d31ec`)
- **F2.3b** ✅ — table factories + predicates + value-set constants → `extensions/table/factories.ts` (commit `a0afa44d`)
- **F2.3d** ✅ — table markdown serializer (serialize + parse + buildTableFromMarkdownRows) → `extensions/table/serialize-markdown.ts` (commit `d6f0af48`)
- **F2.3c** ✅ — table HTML serializer (serializeTableHtml + parseTableHtml + cell helpers) → `extensions/table/serialize-html.ts` (commit `5797e69b`)
- **F2.3e** ✅ — table render (renderTable + renderTablePlainText) → `extensions/table/render.ts` (commit `d8392735`)
**F2.3 pendiente — los 4 sub-pasos restantes son el refactor difícil**:
- **F2.3f** — path.ts navigation. Las refs de table están en BRANCHES dentro de funciones grandes (`resolvePath`, `updateNode`, `inferContainerKind`), NO en helpers aislados. Extracción requiere:
- Diseñar callback adapters para recursión (engine → extension → engine)
- O bien: el engine consulta registry sólo para "is this a node my extension owns?" y el resto del walk queda en engine
- Reflexión: ¿cabe redibujar el dispatcher al estilo visitor pattern? Sería más limpio.
- **F2.3g** — normalize.ts. Mismo patrón: branches dentro de `normalizeBlock` / `normalizeNode`. Extracción requiere mismo enfoque que F2.3f.
- **F2.3h** — operations.ts (2620 LoC, ~400-500 LoC table). Las funciones `insertTable*`, `deleteTable*`, `toggle-table-*` son funciones standalone — extraíbles. Pero comparten utilities (`tableCellOptions`, `tableOptions`, `replaceAt`) que viven en el engine. Extraer requiere:
- Mover utilities a `extensions/table/utils.ts` o re-exportar desde engine
- Mover los ~20 reducers a `extensions/table/operations.ts`
- El dispatcher central (`applyWordsCommand`) consulta registry.getCommand(opType) y fallback al switch existente
- **F2.3i** — registry wire-up. Crear `tableExtension: WordsExtension` que cabledea TODOS los hooks (commands, render, serialize, etc.) al registry. El engine constructor registra `tableExtension` por defecto para backward compatibility. Después el dispatcher reescrito consulta registry.
- **F2.3j** — verify final.
**Recomendación de orden para próxima sesión** (lo que dije y se ha confirmado al hacer F2.3a-e):
1. Antes de F2.3f/g/h, hacer **F2.3i con stub vacía**: construir `tableExtension: WordsExtension` que registra sólo nodeTypes ['table','table-row','table-cell'], commandNames y events. El engine al boot lo registra. Después en h-i se mueve la lógica gradualmente hacia los hooks.
2. **F2.3h primero** (operations) usando el stub. Cada reducer extraído pasa de `case 'insertTable':` en switch a entrada en `extension.commands`. El switch del engine consulta registry.getCommand() antes del fallback.
3. **F2.3f y F2.3g** al final, donde el engine ya consulta registry para todo el resto.
**Estado del extension system** después de hoy:
- `WordsExtension` interface ✅ (F2.2)
- `WordsExtensionRegistry` con 14 tests verdes ✅ (F2.2)
- `extensions/table/` con types + factories + 2 serializers + render ✅ (F2.3a-e)
- Engine NO consulta registry aún (importa funciones directamente de extension). El cambio a "engine consulta registry para tipo X" llegará en F2.3i.
Después F2.4 (code-block, plan similar), F2.5 (docs `EXTENSIONS.md`), F2.6 (verify final).
## Cómo retomar mañana
1. **Probar toggle-group en navegador**:
- El bug del cascade fue corregido inlining derivations en
`toggle-group.css`. Pero el fix no se probó en navegador. Si el
cascade sigue roto en algún caso, revisar las inlined expressions
contra `recipes/base.ts > toggle.{solid,outline,ghost}-*`.
2. **Avatar regenerado**: la migración TSC v2.2 produce un orden de
selector ligeramente distinto al original (`[data-color][data-variant]`
en lugar de `[data-variant][data-color]`). Mismo CSS efectivo —
misma especificidad. Si algún test snapshot rompe, regenerar.
3. **Próximo trabajo natural en TSC** (NO urgent):
- Si más componentes necesitan multi-part scope o composition, ya
está todo soportado — solo añadir las recipes.
- Considerar `radius:`/`ring-color:` como AtomicScope adicionales si
el avatar `ring-color` cascade emerge como pattern recurrente.
## Comandos útiles
```bash
cd G:/dev/svelte/vicen
npm run check # svelte-check
npm run test # full vitest run
npx vitest run src/uix/eidos # eidos-only (100 tests)
npm run generate:eidos-css # regen src/uix/eidos/generated/base.css
npx tsx scripts/eidos-purge.ts <route> # JIT purge para una ruta
```
## Referencias canónicas tras la sesión
- **Theming completo**: `src/uix/eidos/THEMING.md` (1700+ líneas, §18
reescrito hoy como "Cobertura universal de TSC", §7 ampliado con
multi-part + composition).
- **Hand-offs**: `CLAUDE.md` §"Session hand-off — 2026-05-27 #5"
(TSC v2.2 + cobertura universal de theming).
- **Recipe authoring guide**: `THEMING.md` §7 (TSC) + §8 (añadir
componente nuevo).
- **Anti-eager-resolution guard**: `src/uix/eidos/recipe-css-contract.test.ts`
test "forbids palette-derived tokens at :root scope".

Powered by TurnKey Linux.