astra
alpha-0.1-background
alpha-0.1-dir-prefs
alpha-0.1-sec-dom
menubar-v4-safe
active-uix
morfo-runtime
morfo-driven-soma
semantuix
glm-5
main
sium-v1.0
${ noResults }
4 Commits (468a9d1134d697546f1b36231d6773d6324a5faa)
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
9254bcc15e |
refactor(build): un solo mapa de alias — uix.aliases.js lo importan vite.config.ts, svelte.config.js, el compilador del boot y docs-check; muere la copia a mano (F2 del cierre)
La tabla de alias (38 entradas) estaba escrita dos veces, en vite.config.ts y a mano en svelte.config.js, y dos scripts la sacaban de vuelta de la config de Vite con una regex (generate-boot.ts y el invariante 8 de docs-check.ts). Una app del workspace habría sido el cuarto sitio. Ahora vive UNA vez en uix.aliases.js (raíz, .js con JSDoc porque Node carga svelte.config.js sin bundler): UIX_ALIASES con rutas relativas y resolveUixAliases(root) con las absolutas, en el mismo orden. Las dos tablas eran idénticas en claves, valores y orden (comprobado antes de sustituirlas). El orden es contrato: Vite y esbuild casan un alias de cadena por prefijo y SvelteKit se los pasa en orden de inserción (leído en @sveltejs/kit/src/exports/vite/utils.js), así que $svrs/auth/testing y $svrs/auth van antes que $svrs. src/uix/aliases.test.ts lo guarda junto a lo demás: cada destino existe (anti-vacío ≥ 38), resolveUixAliases conserva orden y rutas, ninguna config vuelve a llevar una copia, y el tsconfig generado por SvelteKit tiene paths para cada entrada. Visto fallar: con $svrs delante de $svrs/auth, 1 rojo (restaurado byte a byte). svelte.config.js gana kit.typescript.config para que svelte-check incluya el módulo. readViteAliases muere sin shim; pack.test.ts importa el módulo. CLAUDE.md y AGENTS.md dicen dónde vive la tabla (la sección de AGENTS.md listaba alias que ya no existen). Verificación: aliases.test + pack.test 6/6 · generate:boot byte-idéntico (esbuild recibe el mismo mapa) · docs:check 0/0 · check:gate OK (src/ a cero; 89 en web/, dentro del ledger) · suite entera 464 ficheros / 5 442 tests, exit 0 · npm run build de la raíz exit 0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
3 weeks ago |
|
|
29e581c721 |
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 |
|
|
9ae58c2365 |
feat(active-uix)!: el boot viaja como CUERPO CONSTANTE con los parámetros en un atributo — un hash de CSP fijo, sin node:fs, y la delta deja de confirmarse a sí misma (fila 1)
La receta documentada del boot pre-hidratación no funcionaba en ningún despliegue
real, y el panel de diseño de nueve agentes que el autor pidió lo confirmó
midiendo: con el `render.ts` anterior, un build REAL de SvelteKit con
adapter-static revienta el prerender con `ENOENT …/output/server/generated/boot.js`
y devuelve un 500. La causa: `renderUixBootScript` leía el bundle DEL DISCO junto
a su propio módulo, y una vez empaquetado ese fichero no está ahí.
FORMA NUEVA. El generador compila una entrada propia (`boot/entry.ts`), sin
`globalName`, y emite el MISMO fichero de siempre (`generated/boot.js`, sin
borrar nada) como módulo con dos constantes: el texto exacto del script y su
`sha256-…`. `renderUixBootScript` pierde `node:fs`, `node:path`, `node:url`, la
caché y el envoltorio que estaba ESCRITO A MANO: al no haber `globalName`, la
llamada la hace la propia entrada compilada. «Compilado, no escrito» sale
reforzado, no rebajado.
LOS PARÁMETROS VIAJAN EN UN ATRIBUTO del mismo `<script>`, no dentro del cuerpo.
Consecuencia, que es el punto entero de la fila: el cuerpo es CONSTANTE, así que
su hash es constante por versión del framework, igual para todos los sitios y
todos los `themeIds`. La guía pasa a tener UNA sola receta, por hash, que cubre
prerender, SSR y hasta `mode: 'nonce'`; el nonce baja a salida de emergencia. Un
bloque `application/json` hermano se descartó con razón medida: rompería la
invariante de que el tag parsea a exactamente un `<script>` y un minificador de
HTML podría borrarlo sin que nadie se entere.
TRES MENTIRAS DE LA GUÍA, CORREGIDAS. `event.locals.nonce` no existe en Kit
2.55.0 (cero ocurrencias en su código; `respond.js:168` es `locals: {}`), así que
la receta anterior pasaba `undefined`, el navegador bloqueaba el script y volvía
el flash sin un solo error. El placeholder estaba ENCIMA de `%sveltekit.head%`,
donde la política de prerender de Kit no lo alcanza: eso es evadir la CSP, no
cumplirla, y no vale cuando la política llega por cabecera. Y el `html.replace`
con cadena interpreta `$'`, así que ahora la receta usa reemplazo FUNCIÓN. Se
añade el aviso que puede tumbarle la página al consumidor: añadir un hash a un
`script-src` que lleva `'unsafe-inline'` hace que el navegador IGNORE
`unsafe-inline` y bloquee los demás scripts inline del sitio, incluido el
arranque de Kit.
EL CRITERIO SE CORRIGE. `boot-delta.test.ts` gana un tercer snapshot contra un
documento LIMPIO. El anterior arrancaba el runtime sobre el documento ya sellado,
y como `directionDimension.derive` devuelve `env.direction` antes de derivar del
idioma y el entorno se siembra leyendo el `<html dir>` que el boot acaba de
escribir, la columna `dir` se confirmaba a sí misma. Medido con el boot clavado a
`rtl`: los cinco rojos caen todos en la lectura nueva y ninguno en la anterior.
AUDIT DEV. La raíz compara en desarrollo su primera proyección con lo que ya hay
en `<html>` y NOMBRA los ejes que discrepan. Convierte en ruidosos cinco fallos
que hoy son idénticos y mudos: pin olvidado, `themeIds` incompleto, `storageKey`
distinto, artefacto rancio y script bloqueado por la CSP.
Artefacto 14 666 B, `sha256-5fulJ/2Q6DttR258KqIhWSwfm5g7973BEzzzq14fapY=`,
generación determinista. Verificación: suite entera 461 ficheros / 5404 tests, exit 0 · check con
0 errores bajo `src/` y bajo `scripts/` (89 en `web/`, ledger intacto) ·
docs:check 0/0/819 · `npx vitest run src/uix/active-uix` 9 ficheros / 97 tests.
El test nuevo `boot/pack.test.ts` empaqueta `render.ts` y lo ejecuta: sale ROJO
contra el código anterior con el ENOENT literal, y es lo único que impide que
esta clase vuelva.
Adversarial Opus independiente (árbol byte-idéntico al terminar, 14 mutaciones
revertidas): midió el hash bajo CSP real contra un servidor HTTP en Chromium 145,
Firefox 146 y WebKit 26, con control negativo bloqueado; montó una app SvelteKit
real siguiendo la guía al pie de la letra y la vio construir, prerenderizar y
arrancar sin violaciones; y probó el ENOENT con un build real. Declaró 5 defectos
del lote, ninguno bloqueante, cerrados en una segunda ronda y re-verificados uno
a uno con su reproducción original: un universal falso en un comentario, la
puerta del artefacto sin validar el cuerpo (ahora con guard propio importable),
la constante del hash sin comillas para quien escriba su propia cabecera, el
audit que SÍ viaja al bundle de producción (1 428 B medidos, no un supuesto; no
CORRE, gracias a un ternario que el bundler no pliega) y el eje que se nombraba a
profundidad 2 y ahora va en el mensaje. La redacción del guard del artefacto,
último defecto de la segunda pasada, la corregí yo: corre en cada render, 76 us
con artefacto frente a 1,49 us sin él, medido.
Filas que deja para el autor: los 1 428 B del audit en producción, si se gatean
con una bandera que el bundler pliegue · el audit queda mudo si el runtime se
desecha en el mismo turno · la fila 2 debe decidir si la puerta verifica que el
hash describa al cuerpo.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
3 weeks ago |
|
|
e3c0899dd8 |
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> |
4 weeks ago |