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

8.7 KiB

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.

Pendiente para mañana

P1 — Drag handle FUERA del rail sobre bloques <code> (heredado)

El grip se va fuera de la rail al hacer hover sobre un code block. Sin diagnosticar. Lugar: `eidos/components/words/words-block-handle.svelte

measureFromEl(). Pasos: comparar getBoundingClientRect().leftde

vs

; si difieren, buscar padding/margin/transform en [data-words-content] :where(pre)enwords.css`.

P1 — Heading inline level change (h1 ↔ h2 ↔ h3) (heredado)

Cambiar nivel de heading inline sin abrir drawer. Recomendación: empezar por el Block panel del drawer (verificar que el HeadingPicker se muestra cuando currentBlock === 'heading').

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.