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" ,
"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 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 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" ,
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" ,
revert: deshacer la auditoría entera — se hizo sin leer la doctrina
Revert de los 7 commits de la sesión del 2026-07-29/30:
352ca8bbe style(soma): formato Prettier en el test de gradient-picker
17a1f167b test(soma): chat-list
e70397fca test(soma): field-langs y gradient-picker
c9b83d025 docs(morfo): qué hace pública una parte + hallazgos retirados
feb4a8424 test(soma): los primeros providers que no tenían red
f8e35b8fd fix(morfo): el eje intent/color
c39170abb fix(uix): la auditoría del sistema
`4e785d32b` (stats-band, otra sesión) queda intacto — el revert lo salta.
## Por qué se revierte todo y no una parte
La instrucción de partida era «audita el sistema, **para ello previamente lee
toda la documentación**». No se leyó. Se auditó primero y se justificó después,
y eso contaminó el conjunto, no unos commits concretos:
- Tres hallazgos del informe eran FALSOS, todos de la misma forma —
heurísticas de una sola vía dadas por hechas sin abrir el código:
D-3 `AgentTimersPort` (el puerto sí está satisfecho por el adaptador de
`defineActiveAgent`); «5 derivas de scope» (`avatar-group` / `path-trace` /
`rotate-align` sí están implementados, co-locados en el directorio del
padre); «29 morfos con `kind:'public'` irreal» (medía si existe
`<Componente.Parte>` e ignoraba que un primitivo de API plana compone por
props y snippets).
- `c9b83d025` existe SÓLO para retirar esos hallazgos del commit anterior.
- Los 6 tests de provider se montan sobre un `installSomaHarness` que FABRICA
cuatro servicios compartidos (`dom`, `langs`, `timers`, `prefs`), violando la
primera regla de propiedad de `architecture/active-uix.md`: «Only composition
roots create shared services. `morfo`, `soma`, `sema`, `eidos` and components
never create `dom`, `langs`, `prefs`, `format`, `clipboard` or equivalents:
they receive them from `ActiveUix`.» El arranque real son tres líneas
(`createActiveUix` → `setActiveUix` → `Soma.create()`) que estaban escritas.
- Y se le pidieron al usuario decisiones cuya respuesta estaba en el corpus
(`testing-and-tooling.md` dice que los tests de provider son convención, no
guard; la regla 1 zanja el arnés).
Triar qué conservar exigía justo el juicio que falló. Se revierte todo, se lee
el corpus, y vuelve sólo lo que se pueda sostener citando un documento — o lo
que sea defecto MEDIBLE y por tanto no dependa de criterio (el colapso de
uniones de props, que hacía compilar `<Avatar color="nonsense">`; que
`translations:check` crashease en cada ejecución de su historia). Nada se
pierde: los commits siguen en la historia y se recuperan con `cherry-pick`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
"generate:contracts-docs" : "node --import tsx/esm scripts/generate-contracts-docs.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>
5 months ago
"generate:eidos-css" : "node --import tsx/esm scripts/generate-eidos-css.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>
5 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" ,
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"
refactor: reestructura actx/glob/uiux, agrega librería acel y rutas de test
- Refactoriza actx eliminando nr_actx/nr_engine, unifica en engine.svelte.ts
- Actualiza motores de glob (curr, dati, numr, unit) con variantes .svelte.ts
- Agrega librería de componentes UI acel (accordion, button, collapsible, modal)
- Configura SPA pura: ssr=false, prerender=false, adapter-static con fallback
- Agrega rutas de test para accordion, collapsible y modal
- Corrige doble namespace en accordion/index.ts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
7 months ago
} ,
"dependencies" : {
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
"csstype" : "^3.2.3" ,
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
"esm-env" : "^1.1.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
}
}