Initial commit: SvelteKit application with modular libraries
Add comprehensive library system for internationalization, logging,
formatting, and UI state management:
- ling: i18n library with translation keys, plural rules, and JSON serialization
- logr: logging system with levels, filters, history, and transports
- glob: number (numr), date (dati), currency (curr), and unit (unit) formatters
- actx: application context integrating all modules with Svelte 5 reactivity
- uiux: reactive UI state for theme, toasts, modals, menus, and breakpoints
Features:
- 247 passing tests across 4 test suites
- Svelte 5 runes ($state) for reactive context
- Lazy initialization for optional modules
- Type-safe configuration with TypeScript
- Locale-aware formatting using Intl APIs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7 months ago
{
"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/*"
] ,
Initial commit: SvelteKit application with modular libraries
Add comprehensive library system for internationalization, logging,
formatting, and UI state management:
- ling: i18n library with translation keys, plural rules, and JSON serialization
- logr: logging system with levels, filters, history, and transports
- glob: number (numr), date (dati), currency (curr), and unit (unit) formatters
- actx: application context integrating all modules with Svelte 5 reactivity
- uiux: reactive UI state for theme, toasts, modals, menus, and breakpoints
Features:
- 247 passing tests across 4 test suites
- Svelte 5 runes ($state) for reactive context
- Lazy initialization for optional modules
- Type-safe configuration with TypeScript
- Locale-aware formatting using Intl APIs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7 months ago
"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" ,
Initial commit: SvelteKit application with modular libraries
Add comprehensive library system for internationalization, logging,
formatting, and UI state management:
- ling: i18n library with translation keys, plural rules, and JSON serialization
- logr: logging system with levels, filters, history, and transports
- glob: number (numr), date (dati), currency (curr), and unit (unit) formatters
- actx: application context integrating all modules with Svelte 5 reactivity
- uiux: reactive UI state for theme, toasts, modals, menus, and breakpoints
Features:
- 247 passing tests across 4 test suites
- Svelte 5 runes ($state) for reactive context
- Lazy initialization for optional modules
- Type-safe configuration with TypeScript
- Locale-aware formatting using Intl APIs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7 months ago
"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" ,
Initial commit: SvelteKit application with modular libraries
Add comprehensive library system for internationalization, logging,
formatting, and UI state management:
- ling: i18n library with translation keys, plural rules, and JSON serialization
- logr: logging system with levels, filters, history, and transports
- glob: number (numr), date (dati), currency (curr), and unit (unit) formatters
- actx: application context integrating all modules with Svelte 5 reactivity
- uiux: reactive UI state for theme, toasts, modals, menus, and breakpoints
Features:
- 247 passing tests across 4 test suites
- Svelte 5 runes ($state) for reactive context
- Lazy initialization for optional modules
- Type-safe configuration with TypeScript
- Locale-aware formatting using Intl APIs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7 months ago
"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" ,
Initial commit: SvelteKit application with modular libraries
Add comprehensive library system for internationalization, logging,
formatting, and UI state management:
- ling: i18n library with translation keys, plural rules, and JSON serialization
- logr: logging system with levels, filters, history, and transports
- glob: number (numr), date (dati), currency (curr), and unit (unit) formatters
- actx: application context integrating all modules with Svelte 5 reactivity
- uiux: reactive UI state for theme, toasts, modals, menus, and breakpoints
Features:
- 247 passing tests across 4 test suites
- Svelte 5 runes ($state) for reactive context
- Lazy initialization for optional modules
- Type-safe configuration with TypeScript
- Locale-aware formatting using Intl APIs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7 months ago
"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: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"
Initial commit: SvelteKit application with modular libraries
Add comprehensive library system for internationalization, logging,
formatting, and UI state management:
- ling: i18n library with translation keys, plural rules, and JSON serialization
- logr: logging system with levels, filters, history, and transports
- glob: number (numr), date (dati), currency (curr), and unit (unit) formatters
- actx: application context integrating all modules with Svelte 5 reactivity
- uiux: reactive UI state for theme, toasts, modals, menus, and breakpoints
Features:
- 247 passing tests across 4 test suites
- Svelte 5 runes ($state) for reactive context
- Lazy initialization for optional modules
- Type-safe configuration with TypeScript
- Locale-aware formatting using Intl APIs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7 months ago
} ,
"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" ,
Initial commit: SvelteKit application with modular libraries
Add comprehensive library system for internationalization, logging,
formatting, and UI state management:
- ling: i18n library with translation keys, plural rules, and JSON serialization
- logr: logging system with levels, filters, history, and transports
- glob: number (numr), date (dati), currency (curr), and unit (unit) formatters
- actx: application context integrating all modules with Svelte 5 reactivity
- uiux: reactive UI state for theme, toasts, modals, menus, and breakpoints
Features:
- 247 passing tests across 4 test suites
- Svelte 5 runes ($state) for reactive context
- Lazy initialization for optional modules
- Type-safe configuration with TypeScript
- Locale-aware formatting using Intl APIs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7 months ago
"@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" ,
soma: tier 1/2 components, Field/NumberField integration, codex_audit fixes
New components: context-menu, field, file-upload, link-preview, menubar.
Codex audit fixes (2026-04-17):
- Wrappers thinned: table, scroll-area scrollbar, calendar, range-calendar
- Toast Root → Item refactor (data-toast-item, resolves part collision)
- TreeView tab-stop fallback, Table right-pinned offset, Toolbar O(N) registry
- Combobox label registry, Pagination count=0, Splitter feasible-range clamp
- TagsInput relatedTarget, Toast compound hotkey, RadioGroup closest filter
- Accessible-name props (aria-label/-labelledby) tipados en RadioGroup/Slider/
Switch/Toolbar; Slider thumbLabels per-index
- NumberField startValue saneado, Table getIsSomeSelected filtra visibles
- Docs: DropdownMenu CheckboxGroup, NumberField terra-free, Pagination
First/Last snippet
Supporting changes:
- App layer + ling/logr/glob/util consolidation, tests updates
- Terra/scripts mechanical reformat (quotes, imports)
- Test pages updated to match new APIs
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
"jsdom" : "^29.0.2" ,
Initial commit: SvelteKit application with modular libraries
Add comprehensive library system for internationalization, logging,
formatting, and UI state management:
- ling: i18n library with translation keys, plural rules, and JSON serialization
- logr: logging system with levels, filters, history, and transports
- glob: number (numr), date (dati), currency (curr), and unit (unit) formatters
- actx: application context integrating all modules with Svelte 5 reactivity
- uiux: reactive UI state for theme, toasts, modals, menus, and breakpoints
Features:
- 247 passing tests across 4 test suites
- Svelte 5 runes ($state) for reactive context
- Lazy initialization for optional modules
- Type-safe configuration with TypeScript
- Locale-aware formatting using Intl APIs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7 months ago
"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" ,
feat: port Dialog to acel, refactor alert-dialog, fix TS errors, add test pages
- Port Dialog component from uisv to acel (dialog.svelte.ts state machine)
- Rewrite alert-dialog as thin wrapper over acel Dialog
- Remove 4 redundant alert-dialog components (Trigger, Overlay, Title, Description)
now re-exported directly from dialog/components/
- Add Dialog export to acel/index.ts
- Fix double-namespace in button/index.ts
- Fix SPA config: ssr=false, prerender=false, adapter-static fallback
- Fix Snippet<[DialogContentSnippetProps]> children call with snippetProps
- Fix glob/lib/date TS errors: import type for verbatimModuleSyntax (×45)
- Fix TS7053 in manipulation.ts invertDuration and DateFormatter.ts
- Fix TS2322 hourCycle type in comn_utils.ts and DateFormatter.ts
- Recreate test pages: accordion, collapsible, alert-dialog, dialog (new), button (new)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
7 months ago
"tailwindcss-animate" : "^1.0.7" ,
"tsx" : "^4.21.0" ,
Initial commit: SvelteKit application with modular libraries
Add comprehensive library system for internationalization, logging,
formatting, and UI state management:
- ling: i18n library with translation keys, plural rules, and JSON serialization
- logr: logging system with levels, filters, history, and transports
- glob: number (numr), date (dati), currency (curr), and unit (unit) formatters
- actx: application context integrating all modules with Svelte 5 reactivity
- uiux: reactive UI state for theme, toasts, modals, menus, and breakpoints
Features:
- 247 passing tests across 4 test suites
- Svelte 5 runes ($state) for reactive context
- Lazy initialization for optional modules
- Type-safe configuration with TypeScript
- Locale-aware formatting using Intl APIs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7 months ago
"typescript" : "^5.9.3" ,
"vite" : "^7.3.1" ,
"vitest" : "^4.1.0" ,
"vitest-browser-svelte" : "^2.0.2"
}
}