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/package.json

73 lines
3.1 KiB

{
"name": "vicen",
"private": true,
"version": "0.0.1",
"type": "module",
feat(apps): apps/base — la primera app que consume UIX como fuente desde un workspace, y su check entra en el gate (F3 del cierre) Hasta hoy ninguna app consumía el framework fuera de su propio árbol de demos, y por eso la receta del boot pudo estar rota en producción sin que nadie lo supiera. apps/base es un esqueleto SvelteKit con adapter-static estricto y prerender, que sigue docs/consuming.md al pie de la letra: alias por resolveUixAliases, runas por config, raíz standalone (createActiveUix + setActiveUix + Soma + ActiveEidos con applyDom), boot compilado con SU esquema (es/en/ar), CSP por hash con el artefacto propio, fuentes y sonidos copiados al static/ de la app (assets:sync, con --check). La página es un AppShell con un Toggle de modo, un Select de idioma y un Dialog. Raíz: workspaces ["apps/*"] (una sola copia de svelte 5.55.0, vite 7.3.1, kit 2.55.0 y esbuild 0.27.4; lock +23 líneas); apps:check = check + build + smoke de la app, dentro del gate justo antes de la suite; .gitignore y .prettierignore para lo generado y lo copiado. El smoke sirve build/ por HTTP y pasa tres visitantes (es-ES, ar-EG, es-ES con modo oscuro y movimiento reducido), cada uno con los módulos abortados (sellos del boot) y con carga completa (0 pageerror, 0 console.error, 0 violaciones CSP, delta 0 entre boot e hidratación). Comprueba además que el tag del boot va DESPUÉS del <meta> CSP: encima, corre sin política y Kit no lo avisa. Constructor, adversarial y dos rondas de cierre (Opus). El adversarial escribió una segunda app solo con el contrato y la hizo arrancar en Chromium, Firefox y WebKit; midió la CSP en siete variantes y tres motores, y mutó la app para ver si el smoke muerde. Defectos cerrados: - D1: el smoke prometía contar traducciones ausentes y en una build de producción no hay señal (engine-langs las emite solo en DEV). Ya no lo promete; README y consuming §8 dicen dónde se ve cada cosa. - D2: el smoke nunca abría modo oscuro. Tercer visitante con el valor afirmado; un pin 'light' olvidado en la raíz ahora da exit 1. - D3: sin reset de documento el Dialog medía 409 px en un móvil de 375. La app lleva su reset de tres reglas (doctrina vigente: el reset es de la app); que la fundación lo traiga es fila del ledger. - D5: los textos del esqueleto seguían en castellano bajo lang=ar. Salen de src/lib/strings.ts por langs.ts(record), tipados. - D6: esa garantía de tipo la sostenía una unión de idiomas escrita a mano. Ahora hay UNA tupla (APP_LANGUAGES en prefs-schema.ts) que leen el esquema, los textos y el Select. Visto fallar: con 'fr' en la tupla, check exit 1 con 8 errores que nombran fr; restaurado byte a byte. - C1-C3: el contrato gana el tsconfig mínimo medido (rewriteRelativeImportExtensions, sin él 578 errores), las rutas de import de Soma/ActiveEidos/createThemeBaseEidosConfig y adapter-static + prerender. Cero cambios en src/**. Huecos del framework que la app destapa, al ledger: el Dialog modal no devuelve el foco al trigger (queda en BODY en los 3 motores: FocusScope enfoca mientras HideOthers aún tiene el inert), Select.Value muestra el value crudo hasta abrir el popup, los catálogos de componentes no tienen 'ar', la foundation se carga dos veces (482 KB enlazados + 426 KB inyectados por applyDom, 5 153 tokens duplicados), guide.md llama eidos.listThemes() dentro del hook, la regla 6 de active-uix.md está caducada, y uix.langs no lleva el tipo del catálogo de la app. Verificación: apps:check exit 0 (1391 ficheros 0 errores · build · smoke `boot 27/27 · unguarded 0 · pageerror 0 · console.error 0 · csp 0 · delta 0 · flips 0`) · boot de la app 15 365 B, byte-idéntico en dos compilaciones, su hash en el <meta> de build/index.html · docs:check 0/0 en 820 docs. Sobre el lote antes de D6 (D6 no toca src/, scripts/ ni la suite): gate entero exit 0 en 357 s, check:gate 89 dentro del ledger, suite 464/464 ficheros · 5442/5442 tests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
3 weeks ago
"workspaces": [
"apps/*"
],
"scripts": {
feat(audit): component re-audit + fixes P0–P5 (P4 complete, P5 in progress) Re-audit of the whole component catalog at pilot depth (91 fichas + the checkpoint verdicts in docs/audit/components/) and the executed fix packages. - P0–P3: doctrine (sema participation, CANON §3 intent, component-guide §5 + API naming, §32 outline), guards (morfo-vocabulary-check S10/S11d, component-audit A-3.1/A-1.4/S9, eidos-lint classHooks), morfo contracts (role=application removed ×4, aria-selected off the Day, drp translationRef, field data-state prune, pin-input commit-set, media-player renames), 13 new sema packs + 12 morfos family-default → pack. - P4 (N1–N10) COMPLETE: selectionMode (select/combobox/toggle-group/calendar); onValueCommit terminal-callback norm (pin-input/search/password/textarea + date/time/color-field add); typed validation reason + onInvalid (tags-input, css-field); index/onIndexChange (carousel); deselectable; openDelay/ groupSkipDelay; allowCustomValue; defaultValue prune. - P5 (in progress): S1 class-hooks codemod (22 hooks → data-attrs across cropper/button/image-picker/toggle/image-adjustments); S5 outline remnant in field.css; depth pass (data-depth=overlay on tooltip/toast/float-panel); touch-rows (--touch-target token, decoupled ::before hit-slop, area-not-visual, 44 AAA). S6 (Field composition) + S8 (calendar-surface) pending. Verification: errors-outside-(alpha|words|palabras|chronos) == 59 (baseline); morfo-vocabulary-check exit 0; eidos-lint class-hooks/invalid 0 on touched components; per-component vitest suites green. Handoff + remaining plan: docs/process/continue-audit-fixes-2026-07.md Excluded (broken by the N1 rename, left broken per user decision, not staged): words/**, palabras/**, chronos, web/routes/alpha/**. Reconciliation pending: the touch-rows ::before for checkbox/switch reverses changelog §37's earlier pseudo-element rejection (WCAG-overlap) that had routed markers to a labeled-row/Field task — flagged for the user in the handoff. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
3 months ago
"dev": "vite dev --force",
"build": "vite build",
"preview": "vite preview",
morfo: cross-layer contract + 14 new WAI-ARIA components + Dialog wired Morfo (src/uix/morfo/): machine-readable contract of a component's public DOM surface, shared between soma/sema/eidos. Shape v5 consolidated across three independent AI reviews (Gemini, Grok, ChatGPT) plus Sema alignment. Types, sium-based validator with cross-field invariants, dialog.ts as the first canonical morfo with data-last-action for Sema-causal exits, 7 passing unit tests. createAttrs(morfo) and registerContract(morfo) now consume a Morfo — legacy inline signature removed. Dialog provider refactored to derive parts + data contract from dialogMorfo. The other 65 soma components need porting (svelte-check lists them) — tracked work. Tooling: scripts/smoke-check.mjs — Playwright smoke over 65 soma demo routes scripts/morfo-check.ts — validates emitted DOM vs morfo scripts/morfo-vocabulary-check.ts — canonical vocabulary consistency npm run smoke / morfo:check / morfo:vocabulary WAI-ARIA APG components added (100% APG coverage now): Announce, Avatar, Clipboard, DragDrop, Feed, GridList, Meter, Progress, SearchField, TagGroup, TreeGrid + Table.RowDetail/Trigger (detail panel pattern; hierarchical Table rows deprecated — use TreeGrid instead). air: Link, Banner. Sema prep: src/uix/sema/sema_pre.md documents the semantic layer's DOM requirements. Morfo already provides everything Sema needs (data-last-action patterns, transition markers, enumerable state values, cross-component consistency). Sema implementation deferred. COMPONENT_GUIDE updated: items 37-39 (translation namespace grep, DOM topology vs .require() audit, npm run smoke is part of done) + A34 rule with incident log. WAI-ARIA pattern listed as soma membership criterion. Pagination translation bug fixed (soma.pagination.page -> idlangref PAGINATION_LANGS.PAGE). Table demo namespace fix (soma.table.* -> components.table.*). Avatar demo now offline-safe (SVG data URL). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
"worker": "node worker.js",
"worker:daemon": "node worker.js --daemon",
"prepare": "svelte-kit sync || echo ''",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
feat(gate): fase B de P0 — la puerta existe y sabe fallar El hallazgo mayor confirmado de la auditoría 2026-08-26: ~16 validadores y 429 ficheros de test que nada ejecutaba (sin CI en ninguna rama de la historia, hooks .sample, eidos-lint sin script npm). Esta fase los cablea: - `check:gate` (scripts/check-gate.ts): svelte-check con política — src/ debe cero; web/ se mide contra el ledger menguante scripts/check-debt.ts (34 ficheros, 71 errores congelados; sólo puede bajar, la disciplina de theming-census-debt). Guard anti-vacío: sin marcador COMPLETED o con conteo que no cuadra, falla — un gate que no inspeccionó nada no pasa. - `eidos:lint` deja de ser invocación cruda (exit 1 real en invalid/dead). - `gate`: check:gate → validadores rápidos → vitest al final. `lint` queda deliberadamente FUERA: hay ~2.300 ficheros de deuda de formato preexistente (nunca se formateó el repo entero; el one-shot pendiente es `npm run format` en árbol quieto y re-añadirlo — documentado en el hook). - scripts/hooks/pre-push: la fuente del hook, SIN armar. Se armó en caliente, bloqueó el push legítimo del eje theming (secuencia mal: verde primero, puerta después) y se desarmó — de paso la puerta demostró que sabe fallar, que era el requisito de verificación de la fase. - .prettierrc endOfLine:auto — neutraliza la clase CRLF/autocrlf de Windows (~350 falsos rojos), sin cambiar formato real. Verificación: check:gate exit 0 sobre HEAD (71 dentro del ledger, src/ a cero tras 9d6533cb7 del eje navigation-menu) · sondeo individual del resto de miembros del gate: verdes salvo los adjudicados en fase A. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 month ago
"check:gate": "node --import tsx/esm scripts/check-gate.ts",
"gate": "npm run lint && npm run check:gate && npm run morfo:vocabulary && npm run docs:check && npm run arts:check && npm run blocks:check && npm run packs:check && npm run rtl:check && npm run translations:check && npm run agent:check && npm run eidos:lint && npm run apps:check && npm run test",
"lint": "prettier --check .",
"format": "prettier --write .",
"test:unit": "vitest",
"test": "npm run test:unit -- --run",
morfo: cross-layer contract + 14 new WAI-ARIA components + Dialog wired Morfo (src/uix/morfo/): machine-readable contract of a component's public DOM surface, shared between soma/sema/eidos. Shape v5 consolidated across three independent AI reviews (Gemini, Grok, ChatGPT) plus Sema alignment. Types, sium-based validator with cross-field invariants, dialog.ts as the first canonical morfo with data-last-action for Sema-causal exits, 7 passing unit tests. createAttrs(morfo) and registerContract(morfo) now consume a Morfo — legacy inline signature removed. Dialog provider refactored to derive parts + data contract from dialogMorfo. The other 65 soma components need porting (svelte-check lists them) — tracked work. Tooling: scripts/smoke-check.mjs — Playwright smoke over 65 soma demo routes scripts/morfo-check.ts — validates emitted DOM vs morfo scripts/morfo-vocabulary-check.ts — canonical vocabulary consistency npm run smoke / morfo:check / morfo:vocabulary WAI-ARIA APG components added (100% APG coverage now): Announce, Avatar, Clipboard, DragDrop, Feed, GridList, Meter, Progress, SearchField, TagGroup, TreeGrid + Table.RowDetail/Trigger (detail panel pattern; hierarchical Table rows deprecated — use TreeGrid instead). air: Link, Banner. Sema prep: src/uix/sema/sema_pre.md documents the semantic layer's DOM requirements. Morfo already provides everything Sema needs (data-last-action patterns, transition markers, enumerable state values, cross-component consistency). Sema implementation deferred. COMPONENT_GUIDE updated: items 37-39 (translation namespace grep, DOM topology vs .require() audit, npm run smoke is part of done) + A34 rule with incident log. WAI-ARIA pattern listed as soma membership criterion. Pagination translation bug fixed (soma.pagination.page -> idlangref PAGINATION_LANGS.PAGE). Table demo namespace fix (soma.table.* -> components.table.*). Avatar demo now offline-safe (SVG data URL). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
"smoke": "node scripts/smoke-check.mjs",
feat(apps): apps/base — la primera app que consume UIX como fuente desde un workspace, y su check entra en el gate (F3 del cierre) Hasta hoy ninguna app consumía el framework fuera de su propio árbol de demos, y por eso la receta del boot pudo estar rota en producción sin que nadie lo supiera. apps/base es un esqueleto SvelteKit con adapter-static estricto y prerender, que sigue docs/consuming.md al pie de la letra: alias por resolveUixAliases, runas por config, raíz standalone (createActiveUix + setActiveUix + Soma + ActiveEidos con applyDom), boot compilado con SU esquema (es/en/ar), CSP por hash con el artefacto propio, fuentes y sonidos copiados al static/ de la app (assets:sync, con --check). La página es un AppShell con un Toggle de modo, un Select de idioma y un Dialog. Raíz: workspaces ["apps/*"] (una sola copia de svelte 5.55.0, vite 7.3.1, kit 2.55.0 y esbuild 0.27.4; lock +23 líneas); apps:check = check + build + smoke de la app, dentro del gate justo antes de la suite; .gitignore y .prettierignore para lo generado y lo copiado. El smoke sirve build/ por HTTP y pasa tres visitantes (es-ES, ar-EG, es-ES con modo oscuro y movimiento reducido), cada uno con los módulos abortados (sellos del boot) y con carga completa (0 pageerror, 0 console.error, 0 violaciones CSP, delta 0 entre boot e hidratación). Comprueba además que el tag del boot va DESPUÉS del <meta> CSP: encima, corre sin política y Kit no lo avisa. Constructor, adversarial y dos rondas de cierre (Opus). El adversarial escribió una segunda app solo con el contrato y la hizo arrancar en Chromium, Firefox y WebKit; midió la CSP en siete variantes y tres motores, y mutó la app para ver si el smoke muerde. Defectos cerrados: - D1: el smoke prometía contar traducciones ausentes y en una build de producción no hay señal (engine-langs las emite solo en DEV). Ya no lo promete; README y consuming §8 dicen dónde se ve cada cosa. - D2: el smoke nunca abría modo oscuro. Tercer visitante con el valor afirmado; un pin 'light' olvidado en la raíz ahora da exit 1. - D3: sin reset de documento el Dialog medía 409 px en un móvil de 375. La app lleva su reset de tres reglas (doctrina vigente: el reset es de la app); que la fundación lo traiga es fila del ledger. - D5: los textos del esqueleto seguían en castellano bajo lang=ar. Salen de src/lib/strings.ts por langs.ts(record), tipados. - D6: esa garantía de tipo la sostenía una unión de idiomas escrita a mano. Ahora hay UNA tupla (APP_LANGUAGES en prefs-schema.ts) que leen el esquema, los textos y el Select. Visto fallar: con 'fr' en la tupla, check exit 1 con 8 errores que nombran fr; restaurado byte a byte. - C1-C3: el contrato gana el tsconfig mínimo medido (rewriteRelativeImportExtensions, sin él 578 errores), las rutas de import de Soma/ActiveEidos/createThemeBaseEidosConfig y adapter-static + prerender. Cero cambios en src/**. Huecos del framework que la app destapa, al ledger: el Dialog modal no devuelve el foco al trigger (queda en BODY en los 3 motores: FocusScope enfoca mientras HideOthers aún tiene el inert), Select.Value muestra el value crudo hasta abrir el popup, los catálogos de componentes no tienen 'ar', la foundation se carga dos veces (482 KB enlazados + 426 KB inyectados por applyDom, 5 153 tokens duplicados), guide.md llama eidos.listThemes() dentro del hook, la regla 6 de active-uix.md está caducada, y uix.langs no lleva el tipo del catálogo de la app. Verificación: apps:check exit 0 (1391 ficheros 0 errores · build · smoke `boot 27/27 · unguarded 0 · pageerror 0 · console.error 0 · csp 0 · delta 0 · flips 0`) · boot de la app 15 365 B, byte-idéntico en dos compilaciones, su hash en el <meta> de build/index.html · docs:check 0/0 en 820 docs. Sobre el lote antes de D6 (D6 no toca src/, scripts/ ni la suite): gate entero exit 0 en 357 s, check:gate 89 dentro del ledger, suite 464/464 ficheros · 5442/5442 tests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
3 weeks ago
"apps:check": "npm run check -w apps/base && npm run build -w apps/base && npm run smoke -w apps/base",
uix: date-picker + date-range-picker components + component audit infra Two new Eidos components shipped end-to-end (wrapper + recipe + demo + Soma provider hardening) plus a checklist-driven audit pipeline that scores all 67 morfo components against doctrinal completion criteria. New components: - date-picker: full popover-anchored picker over date-field + calendar, with calendar/content/trigger parts and demo route. - date-range-picker: standalone wrapper with own calendar/grid/segment surface, demo route, and recipe CSS. - Both wrappers follow Option C disciplined (root + parts attached via explicit assignment, no Object.assign). Supporting Soma changes: - range-calendar provider tightened (211 LOC of behavior, 167 LOC of tests), README brought up to component doctrine. - date-field, date-picker, date-range-field, date-range-picker Soma providers + READMEs updated for new wrappers. - popover provider/close gain props needed by the picker wrappers. Morfo updates: - date-picker / date-range-picker / range-calendar morfos refined for the new APIs (parts, events, ARIA). Audit infrastructure (new): - src/uix/COMPONENT_COMPLETION_CHECKLIST.md — 81 doctrinal rules across morfo / eidos wrapper / recipe CSS / demo / README / cross-layer scripts. Each rule keyed to active_architecture.md, GUIA_IMPLEMENTACION and DEMO_AUTHORING_GUIDE. - scripts/component-audit.ts + `npm run component:audit` — regex parser over all 67 components, emits tmp/component-audit.md with summary scoreboard + per-component findings. Validates against canonical SEMA_FAMILIES / SEMA_VERBS / ARCHETYPE_VOCABULARY / INTENTS. - Initial baseline: 1 PASS, 64 NEEDS-WORK, 2 BROKEN (tooltip, date-range-picker). Top systemic gaps: translations.label (49), README Gaps/Comparativa/Baseline sections (87 combined), keyboard /event ratio under-declaration (15), apg URL absent (19). Misc: - src/uix/kimi-audit-eidos.md — supplementary audit notes. - .gitignore: ignore .codex-* agent scratch artifacts at repo root. - continue.md + READMEs updated through the migration. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
"component:audit": "node --import tsx/esm scripts/component-audit.ts",
uix(theming): revisión adversarial de F2-A — 8 hallazgos de 34, y nace R-5.4 Pase escéptico del bloque (§7.7, molde Sidebar) con medición propia: worktree con SOLO el CSS revertido a la base del bloque (DOM de demo constante — prueba más dura que la del autor), sonda x2 por componente para fijar el suelo de ruido. 34 hipótesis · 26 refutadas · 8 reales. Lo que NO se pudo romper: el «default idéntico» aguanta en los ocho (0 diffs; command 8.091 · table 13.050 · media-player 3.277 · gradient-picker 609 · listbox 2.813 · carousel 2.842; los 3 de tree-grid y los 5 de feed salen idénticos corriendo DOS veces el mismo código → instrumento); 0 tokens huérfanos de 336; el bundle ES 1:1 con los primitivos; el «verificado a mano» de gradient-picker era verdad (15/16 alcanzan al montar); sin doble animación; eidos-lint 0 invalid. Los 4 de código, arreglados con diff de computed VACÍO (re-medido: command 8.091 y carousel 2.842 valores, 0 diffs): 1. command: el re-point de `--command-radius` dentro del Dialog era una declaración muerta con comentario falso — la misma regla pone el radio a 0 y el input lee `--command-input-radius`, nunca este token (medido: `--dialog-content-radius: 9999px` no movía NADA; `--command-radius: 77px` movía la paleta inline y no la del dialog). Retirado; comentarios y README reescritos con lo medido. 2. carousel: la regla vertical del indicador activo llevaba el `2.25` a pelo mientras la horizontal leía `active-indicator-scale` — el token alcanzaba media superficie (scale:6 → horizontal 18→48px, vertical 18→18px). Ahora lo leen las dos. 3. carousel: el trío `item-gap*` no podía ganar NUNCA — soma estampa `gap` INLINE desde la prop (lo necesita para el flex-basis; reglas casadas por CDP: la de la receta y encima INLINE gap:0rem). Retirados los 3 tokens y las 2 declaraciones muertas (la base y el gap:0 de ghost): 0 diffs, que es la prueba. Canal de valor de soma, como --gp-current-gradient. Censo carousel 35 knobs · 23 públicos · 77 % · 27 claves; global 43 % intacto (5.190 · 2.102). 4. table: `striped-row-bg` no alcanza NADA en la demo publicada — `:nth-of-type(even)` cuenta los <tr> de RowDetail y las filas de datos quedan impares (medido tr a tr: diez inmunes). Arreglarlo mueve píxel → PENDIENTE DE FIRMA (candidato `:nth-child(even of [data-table-row])`); adjudicado en el ledger mientras tanto. El instrumento cargaba 22 falsos negativos de 26 «no effect», con tres causas medidas, y la cuarta era de la sonda: - el paso de abrir hacía CLIC en el input, y un clic de ratón sobre un input de texto SÍ casa `:focus-visible` — la regla de foco pintaba el borde y el token de reposo leía muerto (era el «falso negativo sin causa» de §13); - el override se escribía solo en `[data-{c}]`, y las partes que cuelgan de `{c}-root` no lo recibían; - `::before`/`::after` eran invisibles (el aro de buffering, el spinner); - la no-determinación de feed no era una animación sin localizar: era la demo aún CARGANDO — el auto load-more mantiene [data-busy] ~3 s y la firma `commit-settle` anima box-shadow sobre el nodo medido. Con la espera de asentado: 0 diffs y 0 nodos ausentes sobre 6.264 valores, dos corridas. Con eso NACE EL GUARD R-5.4 (la deuda que §13 pedía desde gradient-picker, y que carousel convirtió en patrón — un estilo inline de otra capa es invisible para todo análisis estático): `npm run theming:sentinel -- <c> <url>` (scripts/theming-sentinel.ts, promovido de `__`; blur tras abrir, override en todos los nodos del componente, pseudos, pase de hover, settle) + ledger scripts/theming-sentinel-exceptions.ts con UNA razón medida por token — muerto sin adjudicar = exit 1, excepción STALE = aviso. Los ocho componentes en verde: command 50/57 · table 41/45 · media-player 46/61 · tree-grid 45/47 · gradient-picker 9/25 · listbox 20/21 · carousel 26/27 · feed 43/50, con 46 excepciones adjudicadas. El guard ya me corrigió a mí: cinco entradas mías salieron STALE (los control-height-* de media-player SÍ alcanzan) y las borró; y dos muertos nuevos los produjeron los propios arreglos (el blur apaga focus-input-border; el settle desmonta el spinner de feed) — adjudicados con su porqué. Doctrina en recipe-contract §4. También: tres cifras de especificidad de next-features §12 recontadas (la banda de tree-grid es (0,8,0); la tinta seleccionada del arquetipo es (0,4,0); y el `item` de table vive en la fila Y EN LA CELDA — elementsFromPoint pone el velo en la celda), el comentario de listbox que mandaba pisar el privado `--_listbox-max-height` apunta ahora al público, y quedan registrados en §13 los dos `header-z` con literal '2' y el spinner de media-player a 720ms mientras el gemelo de feed lleva tokens. Guards: censo global 43 % intacto · audit --only command+carousel PASS · eidos-lint 0 invalid (command 16/12, carousel 29/9, listbox 12/7) · vitest eidos 434/435 (el rojo es el conocido skin-media-player) · rtl 0/180 · docs 0/813 · check 0 errores en tocados (72 globales de otras sesiones) · prettier limpio en lo nuevo (los desvíos de command.css/carousel.css ya estaban en HEAD y no se tocan). Pendiente de firma (CONTINUE §«PENDIENTE DE FIRMA»): el striped inerte, el arquetipo en fila+celda, y que soma lea el gap de un token. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
"theming:sentinel": "node scripts/theming-sentinel.ts",
morfo: cross-layer contract + 14 new WAI-ARIA components + Dialog wired Morfo (src/uix/morfo/): machine-readable contract of a component's public DOM surface, shared between soma/sema/eidos. Shape v5 consolidated across three independent AI reviews (Gemini, Grok, ChatGPT) plus Sema alignment. Types, sium-based validator with cross-field invariants, dialog.ts as the first canonical morfo with data-last-action for Sema-causal exits, 7 passing unit tests. createAttrs(morfo) and registerContract(morfo) now consume a Morfo — legacy inline signature removed. Dialog provider refactored to derive parts + data contract from dialogMorfo. The other 65 soma components need porting (svelte-check lists them) — tracked work. Tooling: scripts/smoke-check.mjs — Playwright smoke over 65 soma demo routes scripts/morfo-check.ts — validates emitted DOM vs morfo scripts/morfo-vocabulary-check.ts — canonical vocabulary consistency npm run smoke / morfo:check / morfo:vocabulary WAI-ARIA APG components added (100% APG coverage now): Announce, Avatar, Clipboard, DragDrop, Feed, GridList, Meter, Progress, SearchField, TagGroup, TreeGrid + Table.RowDetail/Trigger (detail panel pattern; hierarchical Table rows deprecated — use TreeGrid instead). air: Link, Banner. Sema prep: src/uix/sema/sema_pre.md documents the semantic layer's DOM requirements. Morfo already provides everything Sema needs (data-last-action patterns, transition markers, enumerable state values, cross-component consistency). Sema implementation deferred. COMPONENT_GUIDE updated: items 37-39 (translation namespace grep, DOM topology vs .require() audit, npm run smoke is part of done) + A34 rule with incident log. WAI-ARIA pattern listed as soma membership criterion. Pagination translation bug fixed (soma.pagination.page -> idlangref PAGINATION_LANGS.PAGE). Table demo namespace fix (soma.table.* -> components.table.*). Avatar demo now offline-safe (SVG data URL). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
"morfo:check": "node --import tsx/esm scripts/morfo-check.ts",
"morfo:vocabulary": "node --import tsx/esm scripts/morfo-vocabulary-check.ts",
morfo: add permutation runner (A37) — third validation layer for state transitions ## Why `morfo:check` validates single-state DOM at page load; `smoke` catches hydration-time errors. Neither ejercices state TRANSITIONS — and that is where every reactivity bug we caught this week actually lived: - toolbar A35 loop (mount-time, not caught by either) - form A36 microtask loop (mount-time with onChange) - slider RTL transform (static value, off-by-thumb-width) All passed the existing CI. All would have failed a "click, re-validate" pass. ## What - **`scripts/permutation-check.ts`** — Playwright runner. For each demo, collects `data-perm-step="N"` elements, executes them in ascending order (re-discovering after each step so portal-gated controls get counted), and re-validates the component's morfo + captures any `pageerror` / `console.error` between steps. - **`data-perm-*` authoring convention** — step index, human label, mode (click / focus / type / key), settle delay, skip-validate flag. Demos opt in incrementally; the runner SKIPs annotation-less pages without failing. - **`src/uix/morfo/PERMUTATION_RUNNER.md`** — full design doc covering what it validates, the annotation convention, example, failure format, and v2–v4 roadmap (URL-driven states → morfo-inferred cycles → MutationObserver ordering for Sema). - **COMPONENT_GUIDE A37 + checklist item 40** — instrumentation is now a ship-gate rule; doc lists coverage targets (overlays / toggleables / composite roving / forms / RTL) and explicit skips (alerts, file pickers). - **`npm run perm:check`** — pipeline entry, exit codes 0/1/2 parallelling `morfo:check`. ## Instrumented demos (v1 seed) - dialog — 2 steps: open via trigger → close via Close button. Step 1 is inside `{#if open}` + Portal; runner's dynamic re-discovery handles it. - tabs — 3 steps: initial tab 1 → switch to tab 2 → switch to tab 3. - toolbar — 3 steps: toggle bold / italic / underline GroupItems (exercises the A35 pattern that previously looped). Result: 8/8 permutations pass; 63 demos SKIPPED pending instrumentation. ## Verification - `npm run check`: 0 errors in soma/morfo/scripts scope. - `npm run smoke`: 65/65 routes. - `npm run morfo:check`: 66/66 morfos. - `npm run perm:check`: 3/3 instrumented demos, 8/8 permutations. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
"perm:check": "node --import tsx/esm scripts/permutation-check.ts",
uix: rename morfo.translations → morfo.texts (idlangref discipline) Morfo now declares text slots as absolute idlangrefs in `texts: Record<string, LangRef>`, not literal multilingual records. Multilingual content moves out of morfo entirely into per-component catalogs under `src/uix/langs/components/{kebab}.ts`, merged globally by `ActiveUix` via the new `componentLangs` barrel. Morfo stays a pure abstract surface; localization lives in its own layer. - Type: `translations?: LangNode` → `texts?: Record<string, LangRef>` in `src/uix/morfo/types.ts`. Doc and test fixtures updated. - Catalog: new `src/uix/langs/` directory with `common.ts` (was `langs.ts`), `components/` (one file per migrated morfo, plus a barrel), and an aggregate `uixLangs`. `ActiveUix` registers both namespaces at boot. - Registry: `registerMorfo` no longer carries a translations fingerprint and no longer extends `ActiveLangs` dynamically. `connectMorfoTranslations` and `MorfoTranslationTarget` deleted from the public morfo barrel. - Validation: schema.ts drops the relative-translationRef-in-morfo.translations check; catalog presence is enforced by the new `scripts/translations-check.ts` (wired as `npm run translations:check`). - Audit: `scripts/component-audit.ts` rule A-1.3 now validates `texts.label` idlangref shape (`#?components.{kebab}.label|Fallback`) and explicitly errors on any surviving legacy `translations:` field. - Migration: `scripts/migrate-translations-to-texts.ts` is the one-off Node script that produced the 42 morfo rewrites and 42 catalog files. - Tests: `morfo/registry.test.ts` rewritten around the simpler contract; `active-uix.svelte.test.ts` reflects boot-time catalog availability instead of lazy per-morfo extension. Verification: `npm run check` (0 errors), `npm run translations:check` (0/0), `npm run morfo:check` (36/36 routed). The 4 pre-existing failures in `test` are unrelated (date-picker types, css regen, range-calendar clear, color contract). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
"translations:check": "node --import tsx/esm scripts/translations-check.ts",
feat(docs): docs:check guard — copyable-invariant lint for the doc corpus Phase 3 of PLAN-docs-reconciliation (fable_audit D5: the 'link, don't copy' law had no mechanical guard). New scripts/docs-check.ts + npm run docs:check with six invariants, each born from a verified drift: - I1 vocabulary counts vs SEMA_FAMILIES/INTENTS/ARCHETYPE_VOCABULARY (context-gated: font/shape families, variant archetypes and evaluative subsets don't false-positive; section numbers and quoted historical mentions skipped). - I2 phantom fields: translations: in morfo/soma docs, defaultSemantic outside LIBRO_VARIACIONES (rename/rejection mentions allowed). - I3 dependency claims: soma dep lists must cite real package.json dependencies; corpus-wide @floating-ui mentions need their devDep-only context. - I4 SHARED_VARIANT_VOCAB (component-audit) == EIDOS_VARIANTS (textual mirror comparison). - I5 checklist<->audit: every Enforcement:audit rule exists in the script, every script rule ID is declared. - I6 relative links resolve (WARN until the known dangling targets get their user decision: THEMING_AUDIT deleted in worktree, PENDIENTES.md deleted 2026-06-07, MOTION_SERVICE_RFC demo routes). Chronicle docs (process/, changelogs, audits, CONTINUEs, status: historical frontmatter, the book) are exempt from truth-tracking. Also: THEMING s2 per-layer table realigned to the real entrypoint (the fragile rule-count column dropped); stale adom link in SOMA_ARCHITECTURE fixed; validator documented in docs/testing-and-tooling.md. Current output: 1 error (building-a-component known-traps row — cleared in the closing pass) + 13 warns. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
3 months ago
"docs:check": "node --import tsx/esm scripts/docs-check.ts",
"arts:check": "node --import tsx/esm scripts/arts-check.ts",
agent(guard): agent-check nace con la auditoría que ya tiene sujeto — anti-falsificación de actor D-AG.11 (firmada) define SEIS auditorías. Cinco necesitan el árbol de manifiestos `src/uix/agent/components/`, que es trabajo de F4b — y el plan es explícito: el guard «nace CON el árbol, no después». Así que quedan DECLARADAS en el script y se reportan como pendientes: añadir un manifiesto las enciende, y el guard nunca puede ir por detrás de la superficie que vigila. La quinta SÍ tiene sujeto hoy y no la vigilaba nadie: F1 entregó el primitivo de actor (`$libs/actor` + el registro WeakMap privado del motor) y su invariante — que SOLO el motor acuña — no estaba protegida por nada. El token es una marca de compilación sin constructor en runtime: un forjado resuelve a null, pero un `as ActorToken` TIPA, y un contexto de actor construido a mano en el canon es exactamente la suplantación que el eje prohíbe (agent.md §5). Por eso D-AG.8 §2 dice literalmente que su defensa es el lint de agent-check, no el sistema de tipos. Dos reglas, sobre canon (uix · arts · libs · svrs · packs · web) excluyendo el arte agente: - `actor-forgery` — cast a ActorToken fuera de $agent - `actor-handbuilt` — `actor:` con valor literal (objeto/string/número) en vez de un token RECIBIDO; reenviar (`actor: opts.actor`) es la costura sancionada y calla. Los tests quedan exentos: ahí fabricar un forjado es precisamente lo que se prueba. Verificado en negativo, que un guard que nunca falla es teatro: inyectado un cast + un contexto a mano en `sema/signal.ts` → 2 hallazgos con fichero:línea y exit 1; revertido y de vuelta a limpio. `npm run agent:check` cableado junto a los demás guards del repo. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3 months ago
"agent:check": "node --import tsx/esm scripts/agent-check.ts",
fix(cleanroom): F2+F3+F4-C+SEM-4s1 — lote mecánico, censos con guard, corpus documental y el close polimórfico de los pickers VIVO F2 — lote mecánico (13 ítems): - DEP-2 ogl eliminado (0 imports) · DEP-1 clsx inlineado como toClassString propio + suite de contrato (props.test.ts; soma.md §12 cerrado). - THM-7: los 5 selectores manuales de sema.md reescritos con semaSelector (los ejemplos [data-toast-root] apuntaban a un part INEXISTENTE — la deriva que el builder previene, demostrada en el propio doc). - MOR-1 escape isomorfo + validación de attr-names en semaSelector + 9 tests (selectors.test.ts, matches() real con comillas/corchetes) · MOR-2 partMarkerAttr = única fuente compilador↔builder + test de paridad · MOR-3 _resetCompileCache borrado (0 usos). - SOM-2 keydown continue en match sin handler + keyboardFixtureMorfo · SOM-1 no-await de handlers (censo async = 0; contrato V1 cumplido) + pin. - SEM-2 trigger pre-attacha catch con logger (void trigger sin unhandled rejection; throw intacto para awaiters) + pin · SEM-3 fallback muerto de applyDominance → skip defensivo + timer tope de awaitExpression cancelado · SEC-1 adjudicado YA implementado (assertCssVariableValue desde 2026-05-11) + pin del path de VALOR. - accordion → outline (§32; su outline:none dejaba CERO anillo en HCM) — verificado en vivo · THM-6 radius-full 9999px · EID-4 recuentos 33. F3 — censos con guard: - SOM-3 cerrado: announcer + image-provider migrados a scheduler-preferred (consumidores cableados: date/time-field vía soma.uix.timers; avatar/image vía eidos.timers — verificado en vivo); guard de timers ENSANCHADO de soma/components a TODO soma y pasado a EVIDENCIA (setTimeout exige .schedule( en el fichero — layers/ y datetime/ escapaban del ámbito viejo). - THM-5: R-4.7 nueva (válvula same-line /* important: <razón> */, escaneo comment-blanked) + las 15 declaraciones anotadas con su razón + canon recipe-contract §3/§4. - SOM-4 adjudicado: el censo/guard YA existían (49 pins); knob/mask-field/ timeline pinneados (overrides documentados en call-site); media-player Batch-4 (35 hits, cero renderProps) = único batch restante, registrado. - THM-4 doctrinado en eidos.md §unused (comportamiento/composición = legítimo; deuda = eje visual sin consumidor; hotspots por lotes). F4-C — corpus documental (decisiones de usuario aplicadas): - DOC-3: los 15 enlaces muertos resueltos (repoint a la edición FINAL trackeada / des-link históricos) · docs:check I6-links WARN→ERROR. - DOC-1: tabla «Build contract» MIGRADA a component-guide con estados modernizados (A3–A5 → LIVE + guards de hoy); banners reapuntados; citas de CANON/sema.md historificadas; lápida-redirect en el §13 del fósil. - DOC-4: hold chain → holds.ts · FAQ event:* SUPERSEDED por signatures · gradient añadido a los DOS capstones (sextet real) · nota de paleta de demo-authoring corregida (universalPaletteDecls + decisión THM-2 = mecanismo universal como sucesor del tracker borrado). - DOC-5/6: recuentos anti-frágiles datados · §4.11 dup → §4.12 · Known gaps historificado · N-6/N-7 recuperadas de git (d68d2c45^) y canonizadas en eidos.md §pickers · authoring E2 → canon/tsc.md · air-old des-linkado · EID-3 (placement) en la fila RTL · AUX-2 disabledDom documentado. SEM-4 sesión 1 — el close polimórfico de los pickers, VIVO (D.11): - Reconciliación: los morfos ya no declaran close (delegated al Popover, de-dialoged 06-27); el agujero real era el cierre programático bypaseando dismissWith → save/cancel/select eran perceptualmente SILENCIOSOS. - Fix: PickerShellHandle.setPopoverDismiss + closeWith(cause) en los 5 providers (14 sitios; select/commit → 'save' = commit.save+fulfill, cancel → 'cancel' = emerge; fallback raw para headless) + UN inyector en el eidos PickerShell root (norma N-8). Picker genérico fuera a propósito (ya suena commit-set/cancel por diseño S9). - Verificado en vivo (date-picker): Done → close·commit·fulfill·active · Cancel → close·emerge · cierre real. Gates: matriz 141/141 (los 6 morfos nuevos de la pista de texto paralela también PASS) · contracts 38/38 · eidos 314 · sema 178 · morfo 94 · docs:check 0/0 con I6 en error · baseline propio 57. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
3 months ago
"packs:check": "node --import tsx/esm scripts/packs-check.ts",
feat(direction): un guard para el eje logico-fisico, y el <main> que congelaba las 51 demos Cierra la §2.1 del handoff. El guard nacio en rojo con 24 hallazgos y al arreglarlos aparecieron dos defectos mas grandes que el que buscaba. 1) EL GUARD RTL-1. Nada cruzaba un ancla LOGICA con un desplazamiento FISICO en la misma regla CSS: eidos-lint clasifica SELECTORES, no declaraciones, y la fila RTL del contrato de construccion decia "rule (LIVE)" — revision humana. Por eso el defecto del slider llego a produccion y lo cazo el ojo del usuario. Ahora `npm run rtl:check`, con la logica en src/uix/eidos/rtl-lint.ts (14 tests) para que sea testeable, calcando el par lint.ts / scripts/eidos-lint.ts. El test ancla el caso historico: slider.css ANTES de 013ceac57 sale rojo y el arreglo que se commiteo sale verde. Dos desviaciones del enunciado, deliberadas. AMPLIA a la propiedad independiente `translate:`, que se usa MAS que `transform: translate*` (87 frente a 36) y tiene el mismo defecto — ocho de los 24 hallazgos eran de esa forma. RECORTA `padding-inline*`: no mueve la caja contra su ancla, asi que no puede pelear con un translate; solo anadia ruido. 2) LA COSECHA, 24 -> 1. El unico que queda es palabras, auditado y no tocado. Los 23 caen en tres familias: CENTRADO (10) donde el resultado deseado es simetrico y basta dejar de descentrar; DIRECCIONAL (6) donde el signo debe voltear; y FISICO (7) donde lo que sobraba era el ancla logica — handles de brujula del cropper sobre una imagen que no se voltea, y el arco polar del menu-dial. Medido en Chrome el switch: el thumb salia a +24px en un carril de 38px, colgando fuera. Verificados tambien carousel, avatar, cropper, menu-dial y chat-log. 3) :dir() ES LA DOCTRINA, [dir='rtl'] QUEDA PROHIBIDO. Los 12 selectores que habia en eidos estaban TODOS rotos, en los dos sentidos opuestos del mismo error, y ambos medidos en Chrome. Los 5 descendientes se aplican DE MAS: el sidebar tenia direction:ltr de verdad y aun asi matcheaba, porque el selector capta cualquier ancestro RTL e ignora un dir mas cercano que redeclare. Los 7 de mismo-elemento NO se aplican NUNCA: el tree-view era rtl de verdad y no matcheaba, porque desde 013ceac57 el atributo solo se estampa si alguien lo afirmo. :dir() acierta los tres casos porque mira la direccion RESUELTA. Baseline desde 2023. 4) EL PIN DEL <main>. 5469e05df hizo dos cosas que se anulan: puso las demos en `auto` —sin prop dir, o sea el componente no estampa atributo y HEREDA del DOM— y a la vez clavo <main data-uix-canvas dir="ltr"> sobre ellas. Ese <main> era la herencia, asi que el toggle del topbar y el arabe llegaban a <html> y morian ahi: las 51 demos congeladas en LTR. Su comentario afirmaba que "los componentes siguen las prefs, este contenedor no les afecta" — cierto para la LOGICA, falso para el CSS, que lee el direction COMPUTADO. Medido: html dir="rtl" con el panel del sidebar todavia a la izquierda, y quitar ese atributo y nada mas lo movia. Se queda el lang="en". Coste aceptado por el usuario: vuelve la puntuacion desplazada en la prosa inglesa al elegir RTL, que es cosmetico y solo en un modo de inspeccion; demos que no pueden demostrar, no. Si hay que fijar la prosa otra vez, el pin va alrededor de la PROSA. Verificado: check 74 = linea base exacta en las tres pasadas. rtl-lint 14/14. Suite de eidos 375 pasan; el fallo de lint.test.ts por audio-player es PREEXISTENTE, comprobado con stash, y es del hilo del sonido. Los 9 CSS tocados ya fallaban prettier antes de tocarlos, asi que no se formatean. SIN VERIFICAR EN NAVEGADOR, anotado en el handoff: archetypes y proof-of-human (sus reglas viven en @media (pointer: coarse), invisible en escritorio) y sliding-indicator (la demo del radio-group segmented no llegaba a medir). QUEDA: hay wrappers estampando dir="" vacio en vez de omitir el atributo — visto en sidebar y tree-view; no rompe porque un valor invalido hereda, pero contradice la letra del contrato. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
"rtl:check": "node --import tsx/esm scripts/rtl-check.ts",
"blocks:check": "node --import tsx/esm scripts/blocks-check.ts",
test(eidos): la capa compartida deja de no tener guard — uno de texto y uno de valor computado La auditoria encontro que `affix` no tenia NINGUNA cobertura automatica: nueve zonas, el remapeo RTL, la regla de stretch y el empate de `position` con `[data-button]` estaban verificados solo a mano. Con dos consumidores y un tercero planificado, eso era el hallazgo estructural. Van dos guards, y la division del trabajo entre ellos es medida, no supuesta. `shared-layer-contract.test.ts` (texto, proyecto node) — nueve zonas cubiertas, `stretch` solo en bordes de bloque, ningun eje leido sin la ranura de override, ninguna regla de geometria enganchada en `data-affix` (la identidad), y el contrato de consumidor: importa la capa, estampa el gancho, no acuna tokens propios, y reafirma `position` si el primitivo que compone ya declara uno. Existe por UNA razon que el navegador no puede cubrir: `getComputedStyle` de `--_affix-safe-inline-start` devuelve `"0px"` en escritorio — medido. La sustitucion ya ocurrio, asi que que `env(safe-area-inset-*)` alimento la ranura se perdio. Un remapeo con una sola mitad volteada se lee igual que uno correcto en toda maquina donde corre CI, y solo aparece en un movil con muesca, apaisado y en RTL. El texto es el unico sitio donde ese emparejamiento se ve. `scripts/layer-check.ts` (navegador, `npm run layer:check`) — para todo elemento con el gancho: `position` es el que la capa promete, la z resuelve, los tokens publicos resuelven, y ninguna ranura declarada inline computa a vacio (la firma exacta de un ciclo de custom property). La lista de consumidores es DERIVADA de quien importa la capa, asi que MenuDial entrara el dia que migre sin tocar nada. Lo que NO comprueba, y esta escrito en su cabecera en vez de tapado: la geometria. La asercion obvia —"el inset anclado no es `auto`"— es INUTIL: `getComputedStyle` da el valor usado, asi que un `auto` se lee como pixeles (medido: `-1976.7px` en una sonda, `324px` en el fallo real del ciclo). No hay forma a nivel de propiedad de distinguir "324px porque el calc murio" de "324px porque lo pidio el autor". Eso exige comparar contra el bloque contenedor, que exige caminar ancestros. Diferido al tercer consumidor. Ambos guards se verificaron POR MUTACION, porque un test en verde no prueba nada hasta que falla sobre el defecto que dice atrapar: texto M1 media mitad del remapeo RTL -> falla M2 zona borrada -> falla M3 vuelta a un solo nivel de token -> falla M4 puente sin `position` -> falla M5 fab reacuna --fab-z -> falla navegador M6 la capa pierde el position de veras -> falla M7 token de z renombrado -> falla M8 la demo deja de ejercitar la capa -> falla M8 no es teorico: la PRIMERA corrida de `layer:check` dio verde habiendo mirado CERO elementos, porque la demo de fab arrancaba en `placement="static"`, que no estampa gancho. Un guard que aprueba porque no habia nada que mirar es peor que no tenerlo, asi que ese caso es ahora un fallo y el default de la demo pasa a `bottom-end` — "floating" es el nombre del componente y su demo deberia ejercitarlo (la caja del stage tiene `contain: layout`, no se escapa). Y una comprobacion mas que dejo dicha: quitar `position: fixed` del puente de fab NO rompe nada en el orden de carga actual — la capa gana el empate igual. Esa linea es un seguro contra un orden que puede cambiar entre builds, no el arreglo de un estado roto; por eso la cubre el guard de texto y no el de navegador. check 69 = base intacta · smoke fab PASS · layer:check 0 violaciones sobre 2 consumidores · suite 120/120. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
"layer:check": "node --import tsx/esm scripts/layer-check.ts",
feat(docs): S1 — generated canonical-vocabulary appendix (STUMBLES #1) An agent building a component from the docs-book alone could not assign archetypes / holds / haptic kinds: the closed sets live only in code consts and the corpus (correctly) forbids copying them into prose, so they were invisible from the docs. STUMBLES #1, the top stumble. Fix: docs/canon/vocabularies.md is GENERATED from the consts by 'npm run docs:vocabularies' — the ONE sanctioned place the lists are spelled out (generated = no drift objection), which every other doc links to. It covers part archetypes (with a one-line role each), sema families with their default hold/persistence + per-intent overrides, verbs by family, intents, the perceptual-duration scale, haptic kinds, the 33 palette scales, sizes, variant archetypes, and the shared common.* strings. - scripts/docs-vocabularies.ts imports the consts (robust — no fragile JSDoc/regex parsing) and formats them; the generation is an exported function so docs-check can compare. - Added ARCHETYPE_DESCRIPTIONS to morfo/types.ts (co-located with ARCHETYPE_VOCABULARY, satisfies Record<MorfoArchetype,string>) as the authoritative one-liners the appendix reads — descriptions become first-class data instead of inline union JSDoc a tool would have to parse. - docs-check gains I7: it regenerates in-memory and fails if the committed file drifts from the consts (negative-tested: corrupt -> error, regen -> green). The appendix's own counts pass I1, so I1 doubles as a second guard. - Linked from README (E2 canon row + two 'I want to' shortcuts), CANON.md (doctrine here, enumerated lists there), architecture/morfo.md (pick a part's archetype), and the component-audit minimum-package list (STUMBLES #8). docs:check 0 errors; npm run check unchanged in my files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
3 months ago
"docs:vocabularies": "node --import tsx/esm scripts/docs-vocabularies.ts",
feat(eidos): TSC v2.2 (parts + composition) + universal theming coverage Token Scope Contract universal — no más excepciones arquitectónicas. Los 3 componentes que vivían fuera de TSC v2.1 (select, avatar, toggle-group) ahora están dentro del contrato via dos extensiones nuevas. TSC v2.2 extensiones (lib/config-types.ts + render-css.ts + config.ts): - `parts: readonly string[]` en RecipeTokenMultiDeclaration — emite selectores comma-separados (`[data-{c}-x], [data-{c}-y]`) para componentes con data-color cascadeado per-part. Consumer: select. - `composition: { foreignRecipe: { targetSelector, tokens } }` sibling key — overrides cross-recipe scoped a la cascade del host. Consumer: toggle-group modifica `--toggle-palette-*` en sus items. Migraciones: - select: 3 private `_accent-{track,border,text}` con parts: ['trigger', 'content'] + 7 cascades color:X each. Removed orphan `_accent-solid` (CSS no consumía). - avatar: 6 tokens via composite scopes `['variant:X', 'color:Y']` con matrix helper inline. Badge usa parts: ['badge']. Reemplaza 24 bloques CSS × 2 partes. - toggle-group: composition block con 8 palette tokens × 4 colors. Reemplaza 4 bloques CSS per-color. Bug toggle-group post-composition (encontrado y arreglado): Tras la composition migration, el cascade del toggle-group seguía roto porque los tokens derivados (`--toggle-solid-on-bg`, `--toggle-outline-fg`, etc.) viven en scope `[data-toggle]`. El `[data-toggle-group-item]` es sibling (no descendant), así que `var(--toggle-solid-on-bg)` resolvía undefined. Fix: inlined derivation expressions directamente en `[data-toggle-group-item]` y sus variant cascades (solid/outline/ghost), referenciando palette tokens en su propio scope local. Validador + emisor + contract: - `validateRecipeComposition` valida el shape `{ targetSelector, tokens }` y rechaza composition entries con scope='root'. - `stripCompositionKey` + `emitComposition` separan el pipeline. - `appendRecipeContractTokens` skip-list para `composition` (no aparece como fake `--{c}-composition` knob). - `tokenKeys`/`tokenEntries` helpers en recipe-css-contract.test.ts filtran composition en todos los iteradores. Documentación: - THEMING.md §18 reescrito como "Cobertura universal de TSC". §7 extendido con subsecciones "Multi-part scope" y "Cross-recipe composition" + ejemplos completos. TOC actualizado. - eidos/README.md tabla de referencia ampliada con TSC v2.2 + §18. - CLAUDE.md gana hand-off "2026-05-27 #5" (TSC v2.2 + cobertura universal). - CONTINUE.md reescrito al estado actual de la sesión. Working tree también incluye sprint Words en paralelo (multiple authors): slash menu, find/replace regex, code language picker, table audit, toolbar family menu, code highlight engine. Tests: 786/786 pass en src/uix/{eidos,morfo,soma,sema}. `npm run check`: 6 errores pre-existentes (lib/_demo, soma/components/internal, web/routes/active) no relacionados. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 months ago
"generate:eidos-css": "node --import tsx/esm scripts/generate-eidos-css.ts",
feat(prefs)!: un motor, un sobre, un codigo — mode/theme/density/scaling son prefs, sobre canonico y boot compilado Auditoria P2 #2: los attrs de preferencias se estampaban solo en cliente tras hidratar (app.html sin script, build estatico sin servidor) — flash claro para todo usuario dark — y no podia existir un script de arranque porque no habia contrato de persistencia (PrefsIntentStorage lo aporta cada app) y eidos llevaba un SEGUNDO motor de preferencias (theme / modeSource / densitySource / scalingSource por opciones, sin persistir), por doctrina escrita en arts/prefs/README.md («UIX does not turn it into prefs.theme»). El autor REVOCA esa doctrina. UN MOTOR. `mode` es una dimension de prefs junto a `motion` (mismo patron, `resolveTheme` de $libs/theme, que ya existia como gemelo de `resolveMotion`); `theme` (id de familia), `density` y `scaling` las declara la RAIZ en un modulo PURO (src/uix/active-uix/prefs-schema.ts) — arts/prefs no importa src/uix. Eidos lee `uix.prefs` por su puerto `ActiveEidosPreferenceSource` (src/uix/eidos/prefs-source.ts), como ya consume uix.langs / uix.dom / uix.motion. El resolver de tema baja a una funcion pura `resolveThemeId(theme, mode, isRegistered)` (src/uix/eidos/lib/theme-id.ts); los cuatro nombres de attr de eidos a src/uix/eidos/lib/attrs.ts y los de la proyeccion a src/arts/prefs/dom-attrs.ts: modulos sin Svelte, porque el boot los comparte. UN SOBRE. src/libs/prefs/document.ts: `uix.prefs-intent` v1 bajo la clave `uix.prefs`, espejo del documento de eidos (kind + version estrictos, version desconocida se RECHAZA). Solo intencion — nunca efectivo ni entorno. Adaptador localStorage canonico creado en la raiz standalone (`prefs.storage`: propio gana, `false` desactiva). HIDRATACION SINCRONA: el bridge awaitea `load()` aunque sea sincrono y produciria una primera resolucion con defaults y un salto un tick despues — el flash movido de sitio; la raiz lee el sobre ANTES de crear el motor y lo pasa como `intent`; el bridge queda solo para persistir (skipHydrate). UN CODIGO. El boot no se escribe: se COMPILA con esbuild desde los mismos modulos puros (src/uix/active-uix/boot/boot.ts → generated/boot.js, 15.009 bytes / 5.625 gzip, IIFE sin globales, cero Svelte; test de sincronia, precedente generated/base.css). `renderUixBootScript(params)` (boot/render.ts) es Kit-agnostico: el framework entrega el string; el hook de Kit son tres lineas de la app (receta en docs/theming/guide.md, NO cableada: el layout congelado lleva persistencia propia). Estampa los NUEVE attrs (dir lang data-motion data-sound data-haptic data-theme data-mode data-density data-scaling) → DELTA CERO al hidratar, probado por integracion con la raiz REAL (boot/boot-delta.test.ts, tres casos) y por tres mutaciones (sin hidratacion sincrona → rojo; constante de attr cambiada en un solo lado → rojo; boot compilado con `data-modo` → los tres casos rojos). Hallazgo del test de delta cero: la raiz no aplicaba el entorno del navegador (esperaba que el app llamara detectBrowserEnvironment en onMount) — ahora lo siembra ella (guardado por `document`) y observa sus cambios (watchBrowserEnvironment → patchEnvironment), sustituyendo el listener que eidos tenia en createSystemColorSchemeSource. Cifras: vitest prefs+libs/prefs+active-uix+eidos+value-channels 57/593 · suite completa 453/5306 · check 73 (src/ a cero; ledger intacto) · check:gate OK · eidos:lint 0 · docs:check 0/0 · morfo:vocabulary, arts/blocks/packs/rtl/translations/agent:check OK. ESTADO INTERINO, firmado para manana (acta en CONTINUE-audit-p0.md): `resolvePreferences` LANZA con `uix` + escalar/source (forma firmada originalmente); medido despues, `ActiveEidos.create()` inyecta `uix` SIEMPRE y todas las demos pasan escalares o sources (>=12 sitios, incluido web/routes/uix/+layout@.svelte:511) → el sitio de demos lanza al arrancar hasta la forma (c'): pines si (escalar explicito gana, precedente `options.dom ?? options.uix?.dom`), sources reactivas por eje FUERA, sin throw, pines en el boot. Pendientes anotados: contracts.test.ts:1270-1276 codifica la doctrina revocada; esbuild no es dependencia declarada (transitiva de vite) — decision del autor con servidores parados. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
3 weeks ago
"generate:boot": "node --import tsx/esm scripts/generate-boot.ts",
uix(chat): v2 · emoji-picker (picker completo) + escaparate rico del bloque Nuevo componente emoji-picker y rediseño del escaparate de mensajeria. emoji-picker (ruta 9 fases): - Compone Popover (open/close/foco/portal) + Command (busqueda + grid + nav de teclado + a11y combobox/listbox, su "grid mode" documentado) + dos ToggleGroup (categorias + tono de piel). Delegated: sin eventos propios (D.1); el grid y las celdas doble-registran Command.List/Item, conservando la a11y pero con contrato visual propio (gana especificidad con selectores de 2 niveles, sin tocar attrs [data-command-*] ajenos — eidos-lint limpio). - Datos: $libs/emoji, dataset vendorizado de emojibase (MIT) horneado por scripts/generate-emoji-data.ts (precedente lucide: JSON crudo en static/ + script generador). ~1906 emoji con nombre CLDR + keywords, 316 con tono de piel single-person. Grid acotado (categoria activa o resultados de busqueda), sin virtualizacion (refinamiento v2). Helpers puros + test (12/12). - morfo delegated (7 partes + header/footer de layout); soma (root + trigger + content + grid + option + preview, provider-test 4/4); eidos (panel empaquetado, receta con tokens --emoji-picker-*); langs es/en; demo 5 tabs (excepcion delegated documentada); READMEs dobles. Escaparate del bloque (web/routes/uix/demos/chat) — rehecho rico y correcto: - Avatares por-autor con color solido (Avatar del ecosistema): antes gris neutro indefinido, ahora teal/ambar/verde/indigo/primary bien contrastados. - Dos columnas: chat-list (sidebar con badges + typing-en-lista) + sala. - Conversacion rica: separador de dia, run agrupado, reaccion, reply citado, recibos de lectura, typing con avatar, y el emoji-picker integrado en el composer (inserta en el draft). - Solape de burbujas (transitorio, estimateSize=48 con mensajes ~90-126px) mitigado subiendo el estimate a 76. Auditoria de tamanos/espacios: recipes del bloque limpios (todo con tokens --space-*/--size-*/--color-*); unico literal (punto tono-capable) tokenizado. Verificacion: check baseline 76 (0 nuevos) · component:audit emoji-picker PASS · eidos-lint invalid=0 · recipe-contract 30/30 · morfo:vocabulary 0 · emoji lib 12/12 · provider-test 4/4 · Playwright PASS (busqueda 'rocket'->rocket+ astronautas, click->onSelect+cierra, teclado, tono oscuro 👋->👋🏿, picker abre en el composer). Capturas claro miradas. next-features §7 marca emoji-picker SHIPPED. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3 months ago
"generate:emoji-data": "node --import tsx/esm scripts/generate-emoji-data.ts",
feat(gate): fase B de P0 — la puerta existe y sabe fallar El hallazgo mayor confirmado de la auditoría 2026-08-26: ~16 validadores y 429 ficheros de test que nada ejecutaba (sin CI en ninguna rama de la historia, hooks .sample, eidos-lint sin script npm). Esta fase los cablea: - `check:gate` (scripts/check-gate.ts): svelte-check con política — src/ debe cero; web/ se mide contra el ledger menguante scripts/check-debt.ts (34 ficheros, 71 errores congelados; sólo puede bajar, la disciplina de theming-census-debt). Guard anti-vacío: sin marcador COMPLETED o con conteo que no cuadra, falla — un gate que no inspeccionó nada no pasa. - `eidos:lint` deja de ser invocación cruda (exit 1 real en invalid/dead). - `gate`: check:gate → validadores rápidos → vitest al final. `lint` queda deliberadamente FUERA: hay ~2.300 ficheros de deuda de formato preexistente (nunca se formateó el repo entero; el one-shot pendiente es `npm run format` en árbol quieto y re-añadirlo — documentado en el hook). - scripts/hooks/pre-push: la fuente del hook, SIN armar. Se armó en caliente, bloqueó el push legítimo del eje theming (secuencia mal: verde primero, puerta después) y se desarmó — de paso la puerta demostró que sabe fallar, que era el requisito de verificación de la fase. - .prettierrc endOfLine:auto — neutraliza la clase CRLF/autocrlf de Windows (~350 falsos rojos), sin cambiar formato real. Verificación: check:gate exit 0 sobre HEAD (71 dentro del ledger, src/ a cero tras 9d6533cb7 del eje navigation-menu) · sondeo individual del resto de miembros del gate: verdes salvo los adjudicados en fase A. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 month ago
"eidos:lint": "node --import tsx/esm scripts/eidos-lint-all.ts",
feat(eidos): TSC v2.2 (parts + composition) + universal theming coverage Token Scope Contract universal — no más excepciones arquitectónicas. Los 3 componentes que vivían fuera de TSC v2.1 (select, avatar, toggle-group) ahora están dentro del contrato via dos extensiones nuevas. TSC v2.2 extensiones (lib/config-types.ts + render-css.ts + config.ts): - `parts: readonly string[]` en RecipeTokenMultiDeclaration — emite selectores comma-separados (`[data-{c}-x], [data-{c}-y]`) para componentes con data-color cascadeado per-part. Consumer: select. - `composition: { foreignRecipe: { targetSelector, tokens } }` sibling key — overrides cross-recipe scoped a la cascade del host. Consumer: toggle-group modifica `--toggle-palette-*` en sus items. Migraciones: - select: 3 private `_accent-{track,border,text}` con parts: ['trigger', 'content'] + 7 cascades color:X each. Removed orphan `_accent-solid` (CSS no consumía). - avatar: 6 tokens via composite scopes `['variant:X', 'color:Y']` con matrix helper inline. Badge usa parts: ['badge']. Reemplaza 24 bloques CSS × 2 partes. - toggle-group: composition block con 8 palette tokens × 4 colors. Reemplaza 4 bloques CSS per-color. Bug toggle-group post-composition (encontrado y arreglado): Tras la composition migration, el cascade del toggle-group seguía roto porque los tokens derivados (`--toggle-solid-on-bg`, `--toggle-outline-fg`, etc.) viven en scope `[data-toggle]`. El `[data-toggle-group-item]` es sibling (no descendant), así que `var(--toggle-solid-on-bg)` resolvía undefined. Fix: inlined derivation expressions directamente en `[data-toggle-group-item]` y sus variant cascades (solid/outline/ghost), referenciando palette tokens en su propio scope local. Validador + emisor + contract: - `validateRecipeComposition` valida el shape `{ targetSelector, tokens }` y rechaza composition entries con scope='root'. - `stripCompositionKey` + `emitComposition` separan el pipeline. - `appendRecipeContractTokens` skip-list para `composition` (no aparece como fake `--{c}-composition` knob). - `tokenKeys`/`tokenEntries` helpers en recipe-css-contract.test.ts filtran composition en todos los iteradores. Documentación: - THEMING.md §18 reescrito como "Cobertura universal de TSC". §7 extendido con subsecciones "Multi-part scope" y "Cross-recipe composition" + ejemplos completos. TOC actualizado. - eidos/README.md tabla de referencia ampliada con TSC v2.2 + §18. - CLAUDE.md gana hand-off "2026-05-27 #5" (TSC v2.2 + cobertura universal). - CONTINUE.md reescrito al estado actual de la sesión. Working tree también incluye sprint Words en paralelo (multiple authors): slash menu, find/replace regex, code language picker, table audit, toolbar family menu, code highlight engine. Tests: 786/786 pass en src/uix/{eidos,morfo,soma,sema}. `npm run check`: 6 errores pre-existentes (lib/_demo, soma/components/internal, web/routes/active) no relacionados. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 months ago
"eidos:purge": "node --import tsx/esm scripts/eidos-purge.ts"
},
"devDependencies": {
feat(ethereal): finalize — own engine is the runtime + dual-engine native path Two parts: the cutover (own JS engine replaces @floating-ui as the runtime, dep out of the library) and the native CSS Anchor Positioning path layered on top. Cutover (P4, reconciled): - Flip USE_OWN_ENGINE -> true, then delete it (flag.ts removed). Collapse the A/B in use-floating + floating.svelte to own-only (drop the fui imports, the factory shim, the `as unknown as` casts). useFloating's `dom` is now required. - @floating-ui moved dependencies -> devDependencies: the LIBRARY (src/arts/ethereal + src/uix/soma) imports it NOWHERE; it stays only for the visual demo + the parity oracle. Zero-dep doctrine met for consumers. Dual engine (P2 — built + proven end-to-end): - `selectPositioningStrategy` ($ethereal/strategy.ts, 5 tests) picks native vs JS per instance on discriminators (arrow / shift / virtual-anchor / explicit-boundary; sticky is subsumed by shift). The behavioural twin of supportsCssAnchor. - eidos `renderFloatingNativeBlock`: @supports (anchor-name) and (position-area) with position-area from data-side/align (logical axes — validated against the spec), per-side gap margin, position-try-fallbacks for flip. base.css regenerated. - soma wrapper: when native, stamps data-floating-native + an inline anchor-name<-> position-anchor link and PAUSES the JS positioner (no computePosition, no autoUpdate). - New `avoidCollisions: 'flip'` (flip-only, no slide) decouples flip from shift so an overlay can flip natively. Popover demo: avoidCollisions = full / flip / off. - Proven in a real browser: a flip-only arrowless popover routes to native, positions via position-area, and flips natively (flip-block) at an edge — zero JS transform. Honest scope: shift has no native primitive, so native lights up only for non-shift overlays; the JS engine stays the default for collision-avoiding ones. data-side doesn't track a native flip, so native is gated to the arrowless case. Verified: 537 tests green (ethereal + 7 overlays + floating + generated-css), 0 new check errors. Docs: CONTINUE.md, PERF.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3 months ago
"@floating-ui/core": "^1.7.1",
"@floating-ui/dom": "^1.7.1",
"@sveltejs/adapter-static": "^3.0.10",
"@sveltejs/kit": "^2.50.2",
"@sveltejs/vite-plugin-svelte": "^6.2.4",
"@tailwindcss/typography": "^0.5.19",
"@tailwindcss/vite": "^4.1.18",
"@types/node": "^25.5.0",
"@vitest/browser-playwright": "^4.1.0",
feat(active-uix)!: el boot lo compila el build del SITIO con su propio esquema, y lo que UIX escribe en <html dir> lleva marca de propiedad (fila 2 del boot, F1 del cierre) F1 del plan de cierre del framework. Cierra el último trabajo del eje boot. EL DEFECTO. El boot por defecto compilaba un catálogo de preferencias de UN solo idioma (createDefaultUixPrefsSchema), y la raíz sembraba su entorno leyendo el <html dir> que el boot acababa de escribir: un usuario árabe de una app multiidioma no veía un parpadeo, se quedaba en LTR TODA la sesión, porque el runtime tomaba la salida del boot como si la hubiera declarado la página. EL COMPILADOR POR SITIO. Una sola fusión, composeUixPrefsSchema, la consumen createActiveUix y el boot: no puede derivar. El generador acepta --schema y --out (el especificador boot/boot-schema.ts apunta al esquema del sitio o a boot/default-schema.ts); los guards (sin runas, techo de tamaño, ASCII, sin </script, valores string por atributo) son errores del COMPILADOR con mensajes para el consumidor, porque ahora el artefacto lo produce el sitio. Un esquema que importa el barrel $prefs se rechaza nombrándolo. scripts/uix-boot-check.ts es el guard de rancidez: plugin de Vite que tumba el build con un artefacto viejo (probado con vite build real) y función para CI. Delta cero por esquema: por defecto, multiidioma con árabe, ejes redefinidos y esquema parcial. LA MARCA DE PROPIEDAD, diseño firmado por el autor. El canon de dirección dice que <html dir> es una proyección y nunca una fuente, con una sola excepción: el dir del AUTOR en la plantilla o el servidor. El boot rompió la premisa de esa excepción. Todo lo que UIX escribe en <html dir> lleva ahora PREFS_DIR_PROJECTED_ATTR (el boot con valor «boot», cada proyección del runtime con un token de instancia); la semilla solo adopta un dir SIN marca. Un dir escrito por script no es una fuente: en ejecución la dirección se afirma con prefs.setIntent('direction') o options.prefs.environment, que ganan a la semilla. Se descartaron, midiendo, la marca con valor (cierra el script y congela la dirección al navegar entre layouts) y la inferencia por valor. dispose solo retira lo que todavía es SUYO: SvelteKit crea la raíz del layout nuevo ANTES de destruir la vieja (medido), y un retiro a ciegas dejaba el <html> de la raíz nueva sin dir, lang ni data-motion/sound/haptic (medido hoy: los nueve atributos a null). Mismo principio que el unstamp de sema, que comprueba data-event-id. esbuild se declara como devDependency EXACTA 0.27.4: los bytes del boot y su hash dependen del minificador, y una subida dentro de un rango rompería la sincronía. Boot 15 198 B, sha256-hsqdGYcrRu3oEc0Q3G/A67ApQT3q9c/vT9zMDgxROg8= (el hash se mueve: firmado por el autor). VERIFICACIÓN. Constructor Opus en cuatro rondas y adversarial Opus en dos pasadas independientes, con sus reproducciones repetidas tras cada cierre: en Chromium, entrar en árabe y pasar a inglés y a español sigue al idioma, y al revés también; el dir de plantilla gana antes y después de hidratar y en una raíz recreada; una raíz recreada sobre una viva sigue al idioma con y sin boot; tras create b → destroy a, <html> conserva lo que proyectó b. Diez defectos declarados por el adversarial, cerrados (D1–D10): marca de propiedad, esquema parcial que estampaba "undefined", vigilante de dev mudo, plugin sin test, receta de CI que no cargaba en jsdom, cifras y prosa, y un vite build real que se cae cuando el boot no compila. Mutaciones en rojo, restauradas byte a byte: la proyección no marca · dispose sin guard de dueño (también repetida por el coordinador: 3 rojos) · la semilla compara valor en vez de presencia · marcar el dir del autor. Suite entera 463 ficheros / 5 437 tests, exit 0 · check 0 errores en src/ y en scripts/ (89 en web/, ledger intacto) · docs:check 0/0 · generate:boot dos veces byte-idéntico. LO QUE NO CIERRA (al ledger de cierre): (1) PREEXISTENTE — en la misma navegación entre layouts, el ActiveEidos.dispose de la raíz vieja sigue retirando data-theme/mode/density/scaling de la raíz nueva; exige cambiar el dispose de eidos, otra capa. (2) La propiedad de los atributos proyectados cuelga de la marca de dir: si la plantilla declara la dirección, dispose deja lang y data-motion puestos cuando la raíz se desmonta sin sustituta (benigno). (3) Sin boot, un script que escribe dir antes de la primera raíz es indistinguible de la plantilla y se adopta. (4) El vigilante de dev no reacciona a ficheros nuevos ni a inputs fuera del root. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
3 weeks ago
"esbuild": "0.27.4",
"jsdom": "^29.0.2",
"playwright": "^1.58.2",
"prettier": "^3.8.1",
"prettier-plugin-svelte": "^3.4.1",
"prettier-plugin-tailwindcss": "^0.7.2",
"svelte": "^5.51.0",
"svelte-check": "^4.4.2",
"tailwindcss": "^4.1.18",
"tailwindcss-animate": "^1.0.7",
"tsx": "^4.21.0",
"typescript": "^5.9.3",
"vite": "^7.3.1",
"vitest": "^4.1.0",
"vitest-browser-svelte": "^2.0.2"
}
}

Powered by TurnKey Linux.