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

218 lines
11 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-29**. Rama: `active-uix`.
## TL;DR de la sesión
**V1 del editor Words ELIMINADO. V2 es ahora el único motor.**
La sesión arrancó con una auditoría del componente Words
(`codex-full-audit.md` en la raíz) y la pregunta del usuario: *"elimina
v1 y continua v2, ¿qué sentido tiene v1?"*. Decisión firmada y
ejecutada de cabo a rabo (F1 → F6). Ya no hay coexistencia V1/V2 ni
migrador: el modelo de documento público es `WordsDocumentV2` y punto.
### Decisiones firmadas (vinculantes)
- **D1 = "V2 puro, sin legacy"**: borrados `engine/document.ts` +
`engine/migrate-v2.ts`. **SIN** importador de retrocompatibilidad.
La API pública pasa de `WordsDocument` → `WordsDocumentV2`. Los docs
persistidos en V1 **dejan de cargar** (ruptura aceptada por el
usuario).
- **D2 = "Aceptar el drop"**: eliminados por completo los controles /
props / commands / atributos morfo de tabla `striped`, `compact` y
`cell-tone`. NO se re-mapean ni se re-portan.
## Qué se borró (V1) y a dónde se movió (V2)
**Borrado — motor V1 (`engine/*.ts`):**
`commands.ts`, `document.ts`, `dom-selection.ts`, `engine.test.ts`,
`find-replace.ts`, `history.ts`, `index.ts` (barrel V1), `input.ts`,
`migrate-v2.ts` (+test), `operations.ts`, `render.ts`,
`serialize-html.ts`, `serialize-json.ts`, `serialize-markdown.ts`,
`serialize-text.ts`.
**Borrado — árbol `extensions/` entero:** extension-registry (+test),
extension-types, `image/*`, `table/*`. El modelo V2 no usa el sistema
de extensiones; tabla/imagen/divider/callout son bloques nativos del
union `WordsBlockV2`.
**El motor V2 vive SOLO en `engine/operations-v2/`** + un puñado de
`.ts` en la raíz de `engine/` (types-v2, validate-v2, normalize,
render-v2, serialize-html-v2, serialize-markdown-v2, sema-parity,
code-highlight, path, selection, dom). Esta tanda portó al namespace
V2 lo que faltaba de V1: `commands`, `history`, `input`,
`find-replace`, `render-dom`, `serialize-text`, `extra-ops`,
`insert-block-types`, `markdown` (input-rule shortcuts), `factories`,
`dom-helpers`, `dom-selection` — además de cerrar R4A.2→R4A.8
(text / delete / marks-ops / paragraph-ops / delete-ops / block-format /
list-ops / link-ops / table-ops / selection-walkers / inline-split).
**NO existe parser HTML / Markdown / JSON-schema en V2.** Las
serializaciones HTML y Markdown son **export-only** (lossy → sin
inverso fiel). El import sólo acepta **JSON** (`JSON.parse` +
`validateWordsDocument`) y **texto plano** (`parseWordsPlainText`).
## Superficie pública V2 (lo que consume cualquier app)
- Tipos: `WordsDocumentV2`, `WordsBlockV2`, `WordsInlineV2`,
`WordsSelection`, `WordsExportFormat`, `WordsImportFormat` — todos
re-exportados desde `$soma/components/words`.
- `WORDS_DOCUMENT_VERSION_V2 = '2.0.0'` desde `engine/types-v2`.
- Provider (`words-provider.svelte.ts`): `importContent` (text + json),
`exportContent` (json / text / html / markdown), `plainText` derivado
vía `renderWordsPlainText`.
- Serializers: `serializeHtmlV2(doc)`, `serializeMarkdownV2(doc)`,
`renderWordsPlainText(doc)`, `renderWordsDocumentV2`,
`renderWordsDomHtml` / `Pretty`.
- Comando central: `applyWordsCommand(state, WordsCommandV2)` en
`operations-v2/commands.ts`.
## Forma de los contenedores V2 (recordatorio — NO hay discriminador `type` en sub-nodos)
- **Tabla**: `{ type:'table', rows, headerRow?, headerCol? }`;
fila `{ cells, visual? }`; celda `{ children, align?, verticalAlign?,
colspan?, rowspan?, visual? }`. **Celda usa `align`**, no `textAlign`.
- **Lista**: `{ type:'list', kind, items }`; item `{ children, checked?,
indent? }`. **`items`**, no `children`. Sin `type:'list-item'`.
- **Bloques con alineación**: paragraph/heading/quote llevan
`textAlign?` (a nivel bloque).
## ⚠️ Decisión consecuente NO firmada — export HTML
`serializeHtmlV2` emite **HTML semántico limpio**, no un formato
roundtrip-lossless. Como V2 no tiene parser HTML, HTML y Markdown son
export-only. Si el usuario quería export HTML roundtrip-friendly (re-
importable), es un encargo aparte. **Pendiente de confirmar con él.**
## Verificación al cierre (todo verde)
| Gate | Status | Notas |
|---|---|---|
| `npm run check` | **0 errors** / 5168 files | 26 warnings pre-existentes, ninguno en archivos tocados |
| `npx vitest run src/uix/soma/components/words` | **455/456** | el único fallo es el flake de `sema-parity` por timeout 5s bajo carga paralela |
| `sema-parity` aislado | **6/6 en 362ms** | confirma que el flake es de infra, no regresión |
| `npm run morfo:vocabulary` | **exit 0** | sólo WARN suaves (vocabularios noveles legítimos) |
| Browser smoke `/uix/components/words` | **OK** | mount limpio, 0 console errors |
**Smoke detallado**: el doc sample V2 renderiza (tabla 2×2 con
`headerRow`, 4 list-items incl. el indentado); export markdown emite
tabla GFM válida; import texto round-trip ("imported text"); import
JSON válido round-trip a través del gate ("imported json"); import
JSON inválido (versión mala) → "invalid json" y **deja el doc intacto**
(la razón de añadir el gate `validateWordsDocument`: un doc malo
asignado al `value` bindeado rompería los `$derived`).
## Consumidores re-cableados a V2
- `words-provider.svelte.ts` + `words-provider.svelte.test.ts`
- `exports.ts` + `types.ts` (superficie pública)
- `morfo/components/words.ts` (drop de atributos striped/compact/tone)
- eidos: `words.svelte`, `words-drawer.svelte`, `words-block-handle`,
`words-block-inserter`, `words-command-icon`, `words-heading-picker`,
`words-toolbar-family-menu`, `words.css`, `types.ts`
- soma `components/words.svelte`
- `test/words-content-harness.svelte` (importaba el barrel V1 borrado;
reescrito a `operations-v2` + `types-v2` + `WordsDocumentV2`)
- `web/routes/uix/components/words/+page.svelte` (último consumidor;
imports V2, importFormats → `['json','text']`, docs sample/empty/long
a forma V2, walkers `readPlainText`/`blockToPlainText`/`readInlineText`
sobre el union V2, `exportWordsDocument` + `importDraftDocument`
reescritos, prosa de la API-tab limpiada de striped/tone)
## Cerrado en la continuación (2026-05-29)
### ✅ Limpieza de huérfanos del drop D2
Borrados los selectores CSS muertos de `words.css`
(`[data-command='table-cell-tone-*']`, `table[data-words-table-striped]`,
`[data-words-table-compact]`, `[data-words-cell-tone]` + focus-within, y
los `[data-words-cell-header]` huérfanos — los headers se renderizan como
`<th>`). README actualizado a la realidad V2 (tabla lista solo formato
vivo; HTML/MD export-only; import JSON + texto). `ARCHITECTURE_PROPOSAL.md`
intacto: documenta la *decisión* de eliminarlos, no features stale.
Verificado en browser (tabla 2×2 renderiza, `<th>` conserva su tinte vía
`:where(th)`). Commit `4a0661a5`.
### ✅ R5 — POLISH-1b (image visuals)
El panel de imagen del drawer
(`eidos/components/words/words-drawer.svelte > imagePanel`) ya tenía radius
slider + shadow/border toggles. Añadido lo que faltaba: **shadow blur
slider**, **shadow color picker**, **border color picker** y **background
color picker**, vía un snippet reutilizable `imageColorField` (presets +
`<input type=color>` + clear opcional), mismo patrón que el color de texto
del panel format. Todos despachan `setBlockVisual` → `block.visual.*` →
`visualToStyle` → inline style en el `<figure>`. Verificado en browser: el
panel renderiza los 4 controles nuevos; click en swatch de Background
actualiza el figure (`background-color:#22c55e`) preservando
radius/border/shadow (shallow-merge correcto). `npm run check` 0 errors.
### ✅ P1 — Drag handle sobre `<code>` (NO reproduce)
Investigado: NO reproduce en el código actual. El "rail" al que se
refería el bug fue ELIMINADO en el rediseño de gutter (commit
`5450d5f7`, "rail out"), posterior al sprint EV donde se reportó.
`measureFromEl` (`words-block-handle.svelte`) ancla el handle a
`contentRect.left + 8` — block-type-agnostic. Verificado en browser:
sobre code y sobre paragraph el gutter cae en `left: 350.333` idéntico
(solo difiere `top`). No hay nada que arreglar; bug obsoleto.
### ✅ P1 — Heading inline level change (h1 ↔ h2 ↔ h3)
Añadido al Block panel del drawer
(`eidos/components/words/words-drawer.svelte > blockPanel`): cuando
`currentBlock === 'heading'`, un ToggleGroup H1/H2/H3 (value =
`currentHeadingLevel`) despacha `applyCommand({ type: 'setBlock',
block: 'heading', level })`. `runCommand` / `WordsCommandName` no tiene
id por-nivel (`heading-1/2/3` son ids de slash / insert-menu), por eso
se usa el comando estructurado `setBlock` con el nivel numérico (`as
const` mantiene cada `level` como literal 1|2|3). Verificado en
browser: caret en heading → el panel muestra "Heading level"; el toggle
refleja el nivel actual; el click convierte bidireccional (H1→H3→H2) y
el toggle se actualiza. `npm run check` 0 errors.
## Rework del editor Words (2026-05-29 #2 — redirect del usuario)
El usuario redirigió a un nuevo bloque de trabajo sobre el editor. Plan
en 3 pasos (acordado: overlays a eidos POR FASES, con revisión entre
cada una):
- **Paso 1 — gutter izquierdo (✅ hecho):** quitado el botón "+" del
gutter; "insertar bloque" integrado en el menú del drag handle como
"Insert below" (vía `act('insertBelow')`). Gutter convertido en banda
silver estrecha: `--_words-gutter-size` 3.5rem→2.5rem, fondo
`--words-rail-bg` #ededed (muy suave) + borde derecho 1px
`--words-rail-border` #cfcfcf (un poco más fuerte), pintado como
`linear-gradient` en `[data-words-content]` (solo background, no toca
el contenteditable). Tokens del recipe actualizados + `generate:eidos-css`.
El inserter de SEAM (`words-block-inserter.svelte`, el "+" entre
bloques) NO se tocó — es otro overlay; preguntar si también debe irse.
- **Paso 2 — props de bloque (#3, pendiente):** añadir `color` (texto)
a `BlockVisual` + per-type subsets + `visualToStyle` + validador; y
sección común (margen/espaciado/fondo/color-texto) en el block panel.
Construir esos color controls con **eidos ColorPicker** y migrar los
`<input type=color>` nativos existentes (foreground/background marks +
panel de imagen) a ColorPicker. (Cubre #3 + la parte "color pickers →
eidos" de #4-fase1.)
- **Paso 3 — menú del drag → eidos (#4-fase1 resto) + #4-fase2:**
migrar el menú del block-handle a eidos Menu/Popover; luego link
editor / find / status a Popover+Tooltip.
## Pendiente para mañana
### P2 — Heredados
- **POLISH-3**: topbar del demo (breadcrumb, Edit/Preview, Saved).
- **WORDS-DRAGDROP-SOMA**: migrar drag-drop a soma `DragDrop.Provider`
en vez de HTML5 nativo (intento previo falló — requiere reestructurar
el render del engine).
## Notas de infra
- `sema-parity.test.ts` flakea por timeout de 5s **sólo bajo carga
paralela** (full-suite). Aislado pasa 6/6 en <500ms. Si molesta,
subir el `testTimeout` de ese archivo; no es regresión.
- `.claude/scheduled_tasks.lock` es un artefacto transitorio — NO
commitear.

Powered by TurnKey Linux.