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 }
1792 Commits (095841ca4e2f18fb7b2b4ebba2f71fab35a05337)
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
50574806d6 |
demo(blocks): harness compartido de demos + site-header con contenido real
La página de demo del primer block era mala y con razón: sin cabecera, sin contexto del block, controles sueltos flotando, backticks de markdown en crudo dentro de <Text> y relleno del tipo «filler section so the page scrolls». Harness (`web/routes/blocks/_lib/BlockDemo.svelte`), escrito una vez para las 14: identidad arriba (chip, ruta de import, vuelta a la galería, título, una frase de función y chips de datos: qué compone, landmark, props, cuántas cadenas propias) → el block VIVO dentro de un marco con su propio scroll, que es una página en miniatura → panel de controles agrupado → pestañas Composición · API · A11y · Gaps · Notas, que solo aparecen si la demo las pasa. Todo con componentes del canon (Card, Tabs, Badge, Stack…): esta sección no tiene cromo de docs propio y sigue haciendo dogfooding. `DocRow` acompaña al harness porque el `Table` del canon es una tabla de DATOS (quiere un `createTable`): la documentación en prosa usa una fila de dos columnas, igual en las 14. site-header: reescrita sobre el harness con contenido creíble de producto —nav con destinos reales y descripciones, hero y secciones que dicen algo— en vez de relleno evidente, y con control vivo de los cinco props (sticky, container, breakpoint, offset, dir) más el eje de dirección. Sin backticks literales: lo que es código va en <Code>. Verificado en navegador tras el arreglo de Box: cabecera compacta, escenario con la barra a 950px que se pega al hacer scroll dentro del marco, controles en una fila y las cuatro pestañas con contenido. Cero errores de consola. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
f98c844eda |
eidos(box): las variables de cascada de Box dejan de heredarse
Bug de fondo, no de una página: `[data-box]` lee `var(--box-…)` para cada
propiedad del modelo de caja, y una custom property HEREDA por defecto. Un
`Section` —que es un Box con 64px de padding de bloque— se lo regalaba a
TODOS sus descendientes: Container, Stack, Group, Card… Cinco componentes de
layout anidados = cinco veces el padding. De ahí los cientos de píxeles de
aire muerto en la galería de blocks (que arrastraba el defecto desde F0) y en
la demo del site-header, y de ahí que el header dentro del escenario saliera
a 32px de ancho por 435 de alto: el hijo también heredaba anchos y displays
que no eran suyos.
Las 44 variables se registran con `@property { syntax:'*'; inherits:false }`
y sin valor inicial: así cada una queda «garantizada-inválida» salvo que la
ponga el PROPIO elemento, y las cadenas `var(--box-…, revert-layer)` resuelven
exactamente lo que su autor escribió — los props de ese Box, y si no, el
cascade normal.
Verificado: paddings anidados a 0 en la demo (antes 64 en cada nivel) · la
galería de blocks pasa de ~300px de aire a una cabecera compacta · el header
del escenario mide 950×49 (antes 32×435) · `vitest src/uix/eidos` 353/353 ·
barrido de regresión por /blocks y las demos de button, card, sidebar,
nav-tree y table: cero errores de consola, cero desbordes y alturas de página
sanas · `eidos-lint box` limpio · el CSS generado no cambia (la corrección
vive en el recipe).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
3 months ago |
|
|
6b23aa7ef1 |
agent(guard): agent-check nace con la auditoría que ya tiene sujeto — anti-falsificación de actor
D-AG.11 (firmada) define SEIS auditorías. Cinco necesitan el árbol de manifiestos `src/uix/agent/components/`, que es trabajo de F4b — y el plan es explícito: el guard «nace CON el árbol, no después». Así que quedan DECLARADAS en el script y se reportan como pendientes: añadir un manifiesto las enciende, y el guard nunca puede ir por detrás de la superficie que vigila. La quinta SÍ tiene sujeto hoy y no la vigilaba nadie: F1 entregó el primitivo de actor (`$libs/actor` + el registro WeakMap privado del motor) y su invariante — que SOLO el motor acuña — no estaba protegida por nada. El token es una marca de compilación sin constructor en runtime: un forjado resuelve a null, pero un `as ActorToken` TIPA, y un contexto de actor construido a mano en el canon es exactamente la suplantación que el eje prohíbe (agent.md §5). Por eso D-AG.8 §2 dice literalmente que su defensa es el lint de agent-check, no el sistema de tipos. Dos reglas, sobre canon (uix · arts · libs · svrs · packs · web) excluyendo el arte agente: - `actor-forgery` — cast a ActorToken fuera de $agent - `actor-handbuilt` — `actor:` con valor literal (objeto/string/número) en vez de un token RECIBIDO; reenviar (`actor: opts.actor`) es la costura sancionada y calla. Los tests quedan exentos: ahí fabricar un forjado es precisamente lo que se prueba. Verificado en negativo, que un guard que nunca falla es teatro: inyectado un cast + un contexto a mano en `sema/signal.ts` → 2 hallazgos con fichero:línea y exit 1; revertido y de vuelta a limpio. `npm run agent:check` cableado junto a los demás guards del repo. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
016658a0c9 |
demo(site-header): controles vivos de cada prop + ejes claro/oscuro y RTL
La demo cumplía B-9 (existe y está enlazada) pero se quedaba corta frente a la ficha del plan («claro/oscuro, 375/1280, RTL») y a la doctrina de demos como banco de pruebas: `offset`, `container` y `breakpoint` no tenían control, y la dirección no era un eje de la página. Ahora cada prop público se maneja en vivo con `ToggleGroup`/`Field` del ecosistema (nada de nativos crudos) y la página entera cuelga de un `dir` conmutable. El modo de color NO lleva control a propósito: esta sección sigue el esquema del sistema operativo por diseño del layout, así que oscuro se verifica emulando `prefers-color-scheme`. Verificado en navegador: `container` lg→sm mueve la medida (1024→480px); `breakpoint` discrimina de verdad (a 800px, con `md` se ve la nav y con `lg` aparece el drawer); RTL espeja la barra entera (marca a la derecha, acciones a la izquierda) y oscuro pinta el header sobre superficie oscura. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
3cfc030b3a |
blocks(site-header): F2.1 · primer block del tier + landmark de NavigationMenu
Arranca F2 con el patrón del tier: composición pura de canon, sin CSS propio, sin morfo y sin una sola cadena visible suya (B-7 — todo texto llega del app por snippets). El block - `Sticky` (F1.1) envuelve solo cuando `sticky` (si no, no hay wrapper que no haga nada) → el estado pegado llega al app como `[data-sticky][data-stuck]` y el tratamiento es suyo; el block no pinta. - `Container` para la medida, `Group` para la barra, `Drawer` para la navegación estrecha; `brand` / `nav` / `actions` / `mobileNav` / `mobileTrigger` son snippets del app. - El interruptor ancho/estrecho va por el `display` responsive de los componentes de layout (B-6): el block no observa nada y las dos navegaciones nunca coexisten. - Suelo de referencia (dossier §P1: TW Headers 8 + Navbars 11 + Flyout 7 · Untitled · Flowbite): adoptamos las tres agrupaciones, el estado pegado como eje visual, el drawer móvil y el FLYOUT —la brecha de paridad que el dossier señala— sin reimplementarlo: el app pasa un `NavigationMenu`. Descartado: los volcados estáticos de cada arreglo; la barra es UN layout. El banner de anuncio no se hornea aquí (es el block F2.11 o un `Banner` en `children`). Canon arreglado de paso - **`NavigationMenu` no emitía landmark**: su morfo declara `defaultElement: 'nav'` para el Provider, pero el componente de soma renderizaba un `<div>` — el componente que ES la navegación del sitio no tenía `<nav>`, justo el hueco de a11y que el dossier atribuye a todas las referencias. Corregido en el canon, no parcheado en el block. Verificado: su demo sigue abriendo flyouts, ahora bajo `<nav>`. Hueco registrado (no falseado) - Un CTA que NAVEGA y parece botón no existe hoy: `Button` no tiene `href` por decisión propia («Link posee la navegación») y `Link` no tiene variante prominente. Queda como candidato a canon en los Gaps del block; la demo usa `Link` de verdad en vez de fingirlo. Verificado en navegador: `<header aria-label>` dentro de `[data-sticky]`, `data-stuck` al hacer scroll con el header a top:0, flyout abriendo, cero nativos crudos interactivos (B-2), 375px sin desbordes con el drawer abriendo 6 enlaces, y el `<nav>` del NavigationMenu presente. `blocks:check` verde · `svelte-check` 0 errores propios. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
528af6f72d |
docs(blocks): F1 CERRADA (8/8) · registro de sidebar y su review
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
75e1fe32a1 |
uix(sidebar): review adversarial · 31 hallazgos confirmados, arreglados
Review de 6 dimensiones × 3 verificadores escépticos (135 agentes): 43 hallazgos brutos → 31 confirmados, 12 rechazados. Todos los confirmados arreglados y verificados en navegador real. Estado (los dos ejes) - `collapsible='none'` ya no deja el sidebar INALCANZABLE en móvil: la inercia del modo se limita al escritorio, que es donde «nunca colapsa» significa algo. En móvil el panel es un Drawer que arranca cerrado, el raíl está oculto y el drawer no tiene trigger propio: con el toggle inerte no había forma humana de abrir la navegación en un teléfono. - `'none'` PINTA el estado a expandido: antes `data-state`, `aria-expanded` y `useSidebar().open` podían decir «colapsado» sobre un panel plenamente visible, y ninguna regla del recipe ni el toggle podían reconciliarlo. - El estado del drawer móvil se DESCARTA al salir de la presentación móvil: abrirlo en un teléfono y rotar dos veces remontaba el Drawer ya abierto, con overlay, foco atrapado y scroll bloqueado sin tocar nada. Submenú flotante (era el nudo con más hallazgos) - Cierra también por PUNTERO: se abría en `pointerenter` de la fila, pero el único cierre por puntero vivía en el propio flyout — salir hacia la página sin cruzarlo lo dejaba pintado para siempre. - Escape funciona desde donde el foco ESTÁ (la fila), no solo dentro del sub. - Entrar/salir se resuelve en el `menu-item`, que contiene fila Y sub, así que viajar entre ambos no lo cierra. - El flag se limpia al cambiar de presentación: expandir y volver a colapsar reabría un flyout que nadie había tocado. - El motor flotante se engancha solo cuando el sub está ABIERTO, no por modo: antes `autoUpdate` (rAF + observers) corría por cada fila del raíl. - `hasSub` deja de latir a true: se limpia en el teardown del sub. A11y - Las filas del raíl recuperan NOMBRE: un tooltip solo describe (`aria-describedby`), así que con la etiqueta oculta el texto de `tooltip` pasa también a `aria-label` — incluidas las filas con submenú, que no llevan tooltip visible. - El panel off-canvas colapsado sale del tab order y del árbol de accesibilidad (`visibility: hidden` con la transición retrasada para que el deslizamiento siga animando). - El diálogo móvil recibe el mismo nombre que el landmark. - El raíl se llama «Contraer barra lateral» (lo que hace) en vez de «Redimensionar», que prometía un arrastre fuera de alcance; cursor de puntero en vez de `ew-resize`. Recipe - El signo del off-canvas se deriva de side × dirección: en RTL la fila flex se invierte, así que el negativo fijo barría el panel POR ENCIMA de la página en vez de sacarlo por su borde. - El flyout declara banda `z-index` (nuevo token `--sidebar-sub-z`); era la única superficie flotante del ecosistema sin ella. - La transición de `inline-size` (layout por frame) queda SOLO bajo el modo icono; la base anima únicamente `transform`. - El `Drawer` es el único dueño del ancho móvil (dos dueños dejaban una banda de cromo en dos tonos) y se compone con `dragToDismiss`. - Las reglas de modo icono ya no alcanzan el subárbol flotante: sus filas conservan badges y acciones. - Bloque `prefers-reduced-motion` — la traslación del panel es la mayor del sistema. Demo - Copias corregidas donde afirmaban de más: el tooltip ahora sí NOMBRA (y se explica por qué), y los anchos son rem fijos a propósito (no los alcanza el escalado; sí el interior). - Tabla de eventos y de teclado en la pestaña morfo; `onOpenChange` y una tabla de props por parte en API. - Los chips de estado se inhabilitan en `collapsible='none'`, que es lo que el componente hace; botón «show me» que pone icon + colapsado de una vez. - El trigger pasa a ser solo icono: el morfo le da `aria-label`, que pisaba cualquier texto visible. Verificado en navegador: nombres accesibles en el raíl · flyout que cierra por puntero, por foco y por Escape (con retorno de foco) y que no resucita al cambiar de modo · off-canvas fuera del tab order · RTL sacando el panel por su propio borde · z-index 80 en el flyout · drawer móvil nombrado, a ancho completo y con el panel a ras · `collapsible='none'` abrible en un teléfono. Gates: audit PASS 0E/0W · eidos-lint 47 morfo-backed / 0 invalid · svelte-check 0 errores propios · vitest src/uix/eidos 353/353 · contracts.test solo con los 3 fallos ajenos conocidos. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
59f20e2b1f |
uix(aura): el Status en dos líneas — cierra D1
La otra mitad de la dirección firmada: el anillo dice el estado como FORMA, pero la respuesta a «¿quién actúa?» es texto, y una palabra gris de 13px junto a un orbe vivo no la daba. Ahora el Status son dos renglones: Esperando tu revisión ← el estado, content-primary, peso medium la custodia es tuya ← qué significa para ti, secondary, un escalón menos Sin parte nueva: el Status ya existía y añadir un `Detail` habría sido abstracción prematura (y una pelea de layout — dos hermanos no apilan sin envoltorio). El soma renderiza las dos líneas por defecto y expone `detailText` en los snippet props, así que un consumidor que traiga sus children sigue mandando. La copia del detalle es FIJA por estado y localizada como la etiqueta (es/en): los contadores reales del run (turnos / actos) NO están en el puerto estructural, y ensancharlo para un subtítulo más bonito es una decisión, no un defecto. Queda dicho en el README por si algún día se firma. Tokens: `--aura-status-color` pasa a `content-primary` (era secondary: el peso informativo estaba en el sitio equivocado), + `-weight`, `-gap` y `-detail-color`. Verificado en Chrome real, claro y oscuro, con un run en `reviewing`: peso 500, primary sobre secondary, y las dos líneas escalando con `data-size`. Tests 478, eidos-lint 0 invalid / 0 class-hooks, morfo:vocabulary 0 errores, check en los 73 ajenos preexistentes. Con esto D1 queda cerrada entera (anillo + jerarquía). Handoff al día. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
e10eed98cc |
uix(aura): la superficie visible del agente — anillo de custodia, orbe-contorno y desenlaces expresados
Rediseño dirigido por el usuario sobre un banco de mockups con el orbe REAL
corriendo dentro. Seis frentes, todos con maquinaria existente:
ANILLO DE CUSTODIA (parte nueva `Aura.Ring`, morfo+soma+eidos)
El estado se lee como FORMA y no solo como tinte: raíl punteado en reposo,
arco que respira al ofrecerse, segmentos = pasos del plan (laten), dos arcos
enfrentados y QUIETOS esperando tu revisión (la quietud lo separa de acting),
arco que gira actuando, anillo cerrado + pulso saliente cuando te necesita.
Envuelve al Indicator (es su marco de referencia, no un hermano posicionado a
mano). El movimiento continuo son loops REGISTRADOS (data-animation-style),
nunca @keyframes de receta (R-4.5) — vienen con su puerta de reduced-motion,
donde el dash sigue distinguiendo el estado. El attr va en los hijos del SVG,
jamás en la parte: motionAttrs() estampa además data-state, del morfo ahí.
EL ORBE ES UN CONTORNO
`thickness` en el efecto orb; el hueco es real (alfa propia) sobre cualquier
fondo. Se va la rama claro/oscuro y el parámetro backgroundColor: el shader
mezclaba con el fondo y derivaba el alfa del canal máximo, o sea pintaba un
disco OPACO del color de la superficie justo en el centro (en claro un círculo
relleno; en oscuro el azul del seed). Y la receta deja de pintar su disco en
cuanto monta el canvas (:has(canvas)) — solo sobrevive donde no hay render
vivo: SSR, tests, effect={false}, sin WebGL.
COLOR = TOKENS DE ROL, PINTADO Y NO ROTADO
colorA/colorB/colorDeep (solid / solid-hover / element) resueltos con
eidos.resolveToken y pasados como hex, que es el seam que el propio arte
documenta. El hue-delta anterior se medía en OKLCH y se aplicaba en YIQ: risk
salía VERDE junto a su propio anillo naranja.
ONION EN EL IDIOMA DEL ORBE
Prop `look="solid" | "luminous"` (defecto solid: nadie más se entera). En
luminous el sector no tiene relleno — filo de luz (pasada borrosa + nítida) y
etiqueta en el color del sector; la cuña sigue siendo área táctil. El trigger
con snippet propio va BARE: sin disco, sin sombra FAB y sin el salto del hover
(el orbe ES el trigger, no su contenido). Medio anillo bottom-center y radios
44/40. El halo respira (loop pulse) y en commit-select da UNA pasada de ping
pivotando en el centro real del menú — la firma genérica de commit anima
box-shadow, que sobre un path de SVG no hace nada.
DESENLACES EXPRESADOS (el hueco real: un fallo era indistinguible de un éxito)
Tres eventos terminales con intent INTRÍNSECO — delegate-return (fulfill) /
-aborted (sin intent: un decline es ausencia, no pérdida) / -failed (loss) —
en vez de un intent dinámico, que no tiene dónde vivir: TriggerOptions no
lleva intent y el fromProp del morfo ata a un prop PÚBLICO, no a estado de
máquina. Puerto `runs?` opcional en AuraAgentSource porque activeRun ya es
null al cerrar (§0: sin él, anuncio genérico). Primeras firmas de la familia
delegate en el registro; la de loss es MOVIMIENTO (return-recoil: retirada +
descenso), no tinte — no estrena ningún hue.
MAPA SEMÁNTICO DE COLOR (demo)
Un hue = un significado en toda la superficie: gris=sin agencia ·
naranja=tu revisión · morado=él actúa · rojo=escalated (exclusivo) ·
teal=tu sí. El anillo de autoridad reusa los colores de la custodia con el
MISMO sentido (Review=risk porque vivirás en reviewing; Auto=primary porque
actúa) y los declines pasan a neutral — canon: el intent de un cancel es
`absent`. Además el anillo en reposo DELEGA (las tres autoridades abren el
run) y se cierra por transición, no siempre que no hay run.
Dos guardas del framework corrigieron el diseño por el camino:
- BK-FRAME-NO-INTENT rechazó dar intent a una familia de marco sin
justificación escrita (excepción A-1): queda el intentRationale — el motor
no emite nada y no hay evento evaluable que enmarcar, así que el retorno
consolidado es el ÚNICO sitio expresivo del desenlace.
- fallbackTarget gana sobre el target del morfo (contrato de TriggerOptions):
el sello caía en el provider. Los terminales pasan el Ring cuando existe.
Verificado en Chrome real (ventana delante: en segundo plano el navegador
congela rAF y ResizeObserver y las medidas mienten): seis estados en claro y
oscuro, y un error de transporte REAL apuntando a un puerto muerto →
delegate-return-failed · loss · return-recoil sobre el Ring · región
«Agente: falló — control devuelto».
Tests 478 (morfo 114 · soma/aura 11, +5 casos de desenlace · eidos 353),
eidos-lint 0 invalid / 0 class-hooks nuevos, morfo:vocabulary limpio,
check en los 73 errores ajenos preexistentes.
Pendiente (handoff actualizado): la jerarquía tipográfica del Status (D1
llevaba dos líneas y solo se hizo el anillo) · el pulso de commit-select se
corta si el consumidor cierra el anillo al elegir (necesita retención tipo
Presence) · D5 la superficie de composición del encargo, decisión abierta.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
3 months ago |
|
|
245c22471b |
demo(sidebar): controles vivos de mobileBreakpoint y onOpenChange
Faltaban dos props públicos como control (regla de demo-authoring: cada prop público es un control vivo). `mobileBreakpoint` va con chips y el valor `xxl` (1536px) deja este viewport POR DEBAJO del corte, así que la presentación móvil —el `Drawer` compuesto— se puede ver sin tocar la ventana. `onOpenChange` se cablea a un contador que además enseña la doctrina: no se dispara con el estado del drawer, porque ese no es la preferencia de layout que el app persiste. Verificado en navegador: con `xxl` el shell estampa `data-mobile`, el drawer arranca CERRADO y el trigger de la página lo abre con el panel dentro de `[data-drawer-content]`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
dcce75cc20 |
uix(sidebar): el submenú flotante cierra al salir el FOCO
Se abría por hover o por foco, pero solo cerraba por puntero o Escape: un usuario de teclado que tabulara más allá del submenú dejaba una superficie abierta flotando sobre la página. El item cierra ahora en `focusout` cuando el foco sale de la fila Y de su submenú (dentro sigue abierto, para poder tabular por sus enlaces). Verificado en navegador: foco en la fila → abre; Tab → «Apollo» dentro del submenú, sigue abierto; Tab hasta salir → cerrado. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
293593307e |
uix(sidebar): el shell ocupa todo el alto de su contenedor
Un raíl de app corre de arriba abajo; el shell se quedaba a la altura de su CONTENIDO (404 de 420px en la demo), así que el panel no llegaba al borde inferior. `block-size: 100%` en el shell + el `align-items: stretch` que ya tenía llevan esa altura al panel y al inset. En un contenedor de altura automática resuelve a auto, así que no fuerza nada a quien quiera altura intrínseca. Verificado en navegador: shell y panel a 418px dentro de un contenedor de 420px (los 2px son su borde). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
21bbf9f506 |
uix(sidebar): F1.7 eidos + demo · raíl, modo icono y submenú flotante
Segunda tanda del sidebar: la capa visual, la demo canónica de 9 pestañas y la verificación en navegador real. Con esto el componente está vivo; queda el review adversarial. Eidos - Recipe con los dos ejes: off-canvas por `transform` (trabajo de compositor, el inset no reflowea) y `width` animado SOLO en modo icono, donde el inset sí tiene que seguir al raíl. El raíl NO lleva `will-change` (una franja fina tiembla a DPR fraccionario — memoria NavMenu). - Anchos como TOKENS: `--sidebar-width` 16rem · `--sidebar-width-icon` 3rem · `--sidebar-width-mobile` 18rem, más raíl, gaps, altura de fila y colores. - Tres composiciones que la capa headless no puede hacer: `Drawer` para la presentación móvil, `Tooltip` para nombrar filas en modo icono y `Badge` para los contadores. El trigger compone `Button` por el patrón `child`. - Convención de icono documentada: sobrevive el PRIMER elemento de la fila. Arreglos que destapó el navegador - **`mobile` en SSR**: sin viewport, `isAtLeast` responde «por debajo de todo» → el HTML salía con `data-mobile` y la hidratación NO lo corrige (no diffea atributos y el valor ya no cambia). Viewport desconocido = ESCRITORIO. - **Estado móvil propio** (arranca cerrado): en escritorio `open` es preferencia de layout persistida; en móvil sería un overlay tapando la página, que jamás puede ser el estado inicial. `onOpenChange` solo se dispara con el estado de escritorio. - **`open` controlado/no controlado**: se adopta el patrón de la casa (`$bindable` con default, el provider escribe siempre) — mi versión previa con estado interno no propagaba `bind:open`. - **El submenú flotante no se posicionaba**: `FloatingAnchor` resuelve su provider por CONTEXTO y el eidos envuelve la fila en un `Tooltip`, que publica el suyo → el ancla caía en el tooltip y el submenú se quedaba en `translate(0,-200%)`. Ahora el ancla se cablea directamente al provider flotante del item. Además el `<ul>` ya no se posiciona a sí mismo (colapsaba el wrapper a tamaño cero) y toma elevación del plano `overlay` por `data-depth`, como cualquier panel flotante del ecosistema. - **Tooltip vs submenú**: una fila con submenú no lleva tooltip en modo icono (dos superficies sobre el mismo ancla se pisan) — nuevo `useSidebarItemOr()`. - El item envuelve (`flex-wrap`) para que el submenú caiga en su propia línea en vez de ponerse al lado de la fila. Demo: shell de app real (grupos, badge, acción, submenú, fila deshabilitada), controles vivos de los tres props y las 9 pestañas del canon. Verificado en navegador real (Playwright): dos landmarks nombrados en el idioma activo · `aria-current="page"` en la fila activa · cada menú etiquetado por SU grupo · raíl enfocable que alterna con Enter · colapso 256→48px · off-canvas por transform · submenú flotante anclado a su fila y Escape que devuelve el foco · sema `emerge-expand/collapse` estampando en `panel` · móvil 600px = Drawer cerrado con el landmark dentro · RTL espeja el shell entero · oscuro · 0 errores de consola. Gates: `component:audit --only sidebar` PASS 0E/0W · eidos-lint 45 morfo-backed / 0 invalid / 0 class-hooks · `svelte-check` 0 errores propios · `vitest src/uix/eidos` 353/353 · `contracts.test` solo con fallos ajenos (menubar, radio-group y las claves camelCase de aura). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
e28df1817f |
docs(blocks): registro F1.7 fase morfo+soma en el plan
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
2bc5fe6bd2 |
uix(sidebar): F1.7 fase morfo+soma · contrato de 17 partes + shell headless
Primera tanda del último componente de F1, con el alcance firmado por el usuario (17 partes · submenú flotante en modo icono · sema emerge · parada tras morfo+soma). Suelo de paridad: dossier §P4, leído del `sidebar.tsx` real de shadcn (23 partes); nadie headless lo tiene (Radix/Base/Ark/React-Aria). Morfo (17 partes, 2 eventos) - DOS ejes, no uno: `data-state` (expanded|collapsed) + `data-collapsible` (offcanvas|icon|none), este último SIEMPRE estampado (shadcn solo lo pone colapsado, lo que obliga a cada regla a guardar por estado). Más `data-side` y `data-mobile`. - `panel` (no `sidebar`, que daría `data-sidebar-sidebar`) = `<aside>` NOMBRADO; `content` = `<nav>` NOMBRADO, con header y footer FUERA: así el landmark nombra la navegación y no el cromo. Ninguna referencia trae landmark. - `rail` es una parte física y un `<button>` REAL en el orden de tabulación (shadcn lo deja en tabIndex=-1, inalcanzable por teclado). - `aria-current="page"` sale del MISMO prop que `data-active`, en `menu-button` y en `menu-sub-button`. - `menu-badge` va DENTRO del control de la fila (doctrina de nav-tree: su texto entra en el nombre accesible). `separator` e `input` NO son partes: se componen el `Separator` y el `Field` canónicos. Soma - Estado controlado/no controlado con las costuras exigidas por el dossier desde v1: `open` bindable, `defaultOpen`, `onOpenChange` y `toggle()` público — sin ellas, persistencia y atajo global en app-land serían rediseño posterior. - `mobile` sale del breakpoint del SISTEMA (`uix.dom.isAtLeast`), nunca de un `matchMedia` propio; soma solo decide el hecho y estampa `data-mobile` — la presentación como `Drawer` la compone el eidos (y con ella su foco atrapado, bloqueo de scroll y descarte). - Submenú que SOBREVIVE al modo icono: `menu-sub` se vuelve superficie flotante anclada al botón de su fila (`createFloatingShellRoot` + anchor + content), se abre por hover/foco y se cierra por salida, blur o Escape devolviendo el foco al botón. shadcn los OCULTA y deja ramas enteras inalcanzables. - Dos `partRef` del morfo se resuelven last-write-wins entre instancias, así que soma da el id per-instancia (precedente `navigation-menu`): `aria-labelledby` del menú → la etiqueta de SU grupo; `aria-controls` del trigger/rail → el id del panel. Sema: pack propio con `emerge.soft` / `emerge.exit.soft` sobre `panel`, espejando nav-tree y collapsible. Langs: 4 textos (label, nav, trigger, rail). Verificado: `morfo:check` carga el contrato sin invariantes rotas · `component:audit --only sidebar` **PASS** (0E/0W) · `svelte-check` 0 errores en estos archivos · `contracts.test` solo con los 2 fallos ajenos conocidos (menubar DOM-write, radio-group data-ready). Pendiente de la siguiente tanda: eidos (raíl, anchos tokenizados, modo icono, Drawer móvil), demo y review adversarial. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
ef6bd13be3 |
uix(nav-tree): `disabled` por nodo — destino no disponible
Decisión del usuario. Un nodo deshabilitado conserva su fila (sigue siendo parte del mapa) pero pierde el `href`: no hay nada que activar con clic, Enter ni «abrir en pestaña nueva». Un `pointer-events: none` de CSS solo habría tapado el ratón. - morfo: la parte `link` gana `data-disabled` (propRef) y `aria-disabled` (literal `true` bajo `prop-truthy: disabled`). - soma: `disabled` solo aplica con `href` (un grupo sin destino lo ignora); el toggle del grupo NUNCA se deshabilita — mostrar/ocultar es control de vista, no destino. - eidos: fila en `--color-content-disabled`, sin puntero y sin hover. - demo: «Agent» va deshabilitado con badge «Soon» + filas de API y a11y. Verificado en navegador real: `<a>` sin href, `aria-disabled="true"`, `data-disabled`, color 0.79 frente a 0.61 de una fila normal, clic sin efecto, fuera del orden de tabulación (44 focusables en vez de 45), badge dentro del control. `component:audit` PASS · eidos-lint 28 morfo-backed / 0 invalid · `vitest src/uix/eidos` 353/353 · svelte-check 0 errores míos. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
a7e629f9ed |
uix(nav-tree): F1.8 CERRADA · demo + navegador + review adversarial
Cierra el árbol de navegación data-driven (E-1) de F1: demo canónica de 9
pestañas con el mapa real de docs (43 nodos, 3 niveles), verificación en
navegador real y review adversarial (5 dimensiones × 3 verificadores
escépticos; 22 hallazgos brutos, 10 confirmados) con todos los confirmados
arreglados.
Arreglos del review
- sema: la parte `group` —target de los eventos emerge— se registraba SIN
`ref`, así que `runtime.trigger` lanzaba `SomaRuntimeTargetError` en
silencio y el pack no sonaba nunca (cero `data-event-*` en el grupo frente
a los de collapsible). El provider posee ahora el ref del `<ul>`.
- eidos: en una fila navegable el chevron resolvía `inline-size: 100%` como
flex-basis y ocupaba media fila (101 de 231 px en «Soma»), robándole clics
al enlace. Toggle compacto con suelo de diana de 24 px (WCAG 2.5.8).
- soma: una clave duplicada podía volver cíclico `parentByKey` y colgar la
pestaña dentro de `trailKeys` (deriva en render) → clave sufijada + aviso
del logger + guarda de ciclo en el paseo.
- soma: el colapso es CONTEXTUAL (recuerda el `activeKey` bajo el que se
hizo): cerrar la sección que lees se respeta, pero caduca al navegar
DENTRO del grupo, para que la página actual nunca quede sin fila visible.
Sigue siendo query pura, sin `$effect` que escriba estado.
- soma: `child` recibe también `children` (el árbol renderizado); antes
dejaba el landmark vacío, porque un árbol data-driven no lo puede
reautorar el consumidor.
- morfo + langs: el nombre accesible del chevron se declara en el contrato y
se localiza («Alternar sección {label}»); ya no duplica el del enlace.
- eidos: RTL completo — el glyph espeja solo (bordes lógicos), lo que no
espeja es el giro, así que bajo `[dir='rtl']` las dos rotaciones se
intercambian. El Gap «dirección del chevron en RTL» queda RESUELTO.
- demo: paridad de snippet con los controles vivos; fuera el token fantasma
`--nav-tree-rail-width` del docblock del recipe.
badge en v1 (decisión del usuario, delegada)
Está en el suelo de paridad del dossier §P5 (los 6 refs lo llevan). Se
resuelve con SNIPPET, no con recursión a nivel de eidos: el morfo declara la
parte `badge`, soma renderiza el snippet recibido (sin él, el valor crudo —
sigue siendo headless) y el wrapper de eidos pasa el `Badge` canónico. Va
DENTRO del control de la fila, así su texto entra en el nombre accesible
(«TSC, New, enlace»). `disabled` se descarta en v1 (fuera del suelo, y un
enlace de navegación deshabilitado es semánticamente dudoso); ambos quedan
registrados en la tabla de Gaps.
Verificado: `component:audit` PASS · eidos-lint 26 morfo-backed / 0 invalid ·
`svelte-check` 0 errores en estos archivos · `vitest src/uix/eidos` 353/353 ·
navegador real (Playwright): trail auto-expandido, sema estampando en el
grupo, teclado nativo, foco visible, claro y oscuro, RTL, 375 px sin
desbordes, 0 errores de consola.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
3 months ago |
|
|
549c5e5abd |
docs(agent): D-AG.12 pendiente de firma — el contrato como referencia
PLAN §5: la decisión editorial planteada con el usuario (2026-07-22) queda firmable al retomar — (a) elevar agent.md a especificación publicable («el contrato de delegación») con agent-check como suite de conformance y el checklist de amenazas como anexo; (b) nombrar las dos reclamaciones de frontera que F4/F2 ya materializan: contexto por atención y delegación como transacción; (c) posición honesta declarada (acts secuenciales v1, cliente-first, generalidad pendiente del 2º/3º consumidor). continue-agente: punto 0 del orden de trabajo → firmar D-AG.12. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
3 months ago |
|
|
e835163103 |
uix(nav-tree): F1.8 WIP · data-driven docs nav tree (soma+sema+eidos)
Complete component, green on all static gates (audit PASS, eidos-lint 20/0, svelte-check 0, contracts clean for its parts). NOT tree-view: APG Disclosure Navigation (<nav> landmark + native links + disclosure groups), data-driven (E-1) — the app passes `nodes` + `activeHref`, the provider resolves the active node and auto-expands its ancestor trail. - morfo: nav/list/item/trigger/link/group; emerge-expand/collapse events - soma: NavTreeProvider (shared state, pure isExpanded query) + per-node NavTreeItemProvider (menubar pattern, recursive render) - sema pack: soft emerge on group disclosure (mirrors collapsible) - eidos: rail + per-depth indent recipe; own bespoke rows (not composed Link), Badge deferred to a Gap; aria-current="page" from data-active Remaining before F1.8 closes: demo + browser verify + adversarial review. Handoff: docs/process/CONTINUE-nav-tree.md Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
931a98b7c4 |
fix(anchor-nav): add missing soma README (contracts guard)
The soma component README was never committed with F1.6, so contracts.test's "public Soma component modules with local README docs" guard was failing and the eidos README's link to it was broken. Adds the headless-contract README; both guards go green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
1cc8a87722 |
docs(agent): continue-agente — handoff para la próxima sesión
Estado al cierre (F0/F1/F3/F4a cerradas + tabla de commits), verificación rápida al retomar, siguiente trabajo en orden (F4b chat → F2 gated → flecos), y la disciplina operativa de la rama compartida + gotchas de entorno (Ollama/OpenWebUI, pane, Chrome MCP, index:0 del stream). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
3 months ago |
|
|
0ab40cdcee |
uix(agnt): Aura al centro de un OnionMenu — afordancias radiales por estado
La composición que pidió el usuario: el orb es el trigger central de un OnionMenu placement="center" y las afordancias de custodia aparecen como sectores contextuales — reviewing→Authorize/Reject, escalated→Approve/Deny, activo→Stop — sin fila de botones. El anillo se abre SOLO mientras la custodia espera a un humano, con re-aserción (un cierre externo sin resolver re-abre: el efecto lee onionOpen como dependencia); por click en el centro mientras actúa; se pliega al devolver el control. App-land por doctrina (agent.md §7): el framework da estados + afordancias (Aura) y componentes (OnionMenu); el app da forma a la superficie de review. Patrón documentado en el README de aura (§Patrón). E2E verificado en Chrome real contra qwen3-coder: la escalada real por doc.clear abre el anillo con el orb rojo al centro → Deny en el sector → returned(aborted, user-cancel) + «Agente: terminó — control devuelto» + documento intacto. check 0 propios · smoke agnt PASS. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
3 months ago |
|
|
d008605fac |
uix(aura): variante orb por defecto en el indicator — presencia perceptible
El aurora (banda horizontal recortada al círculo) leía estático a 32-48px (señalado por el usuario). El render vivo pasa a ser el efecto `orb` de $scene — la presencia esférica nativa: anillo respirando con ruido + luz orbitando, movimiento de silueta perceptible en tamaños pequeños y deformable por el puntero. `aurora` queda como variante para superficies grandes (`<Aura.Indicator variant="aurora">`). Modulación §F6 del orb: el estado fija la energía (forceHoverState + hoverIntensity como gain + rotateOnHover en acting/escalated) y el rol el matiz como delta de hue OKLCH sobre la identidad del shader (primary; reviewing=risk, escalated=threat). Verificado en Chrome real, estado por estado: idle recogido → planned anillo violeta → acting denso rotando → escalated rojo agitado. Demo de aura: chips de variante; scene/README: acta D4 pendiente de F3. eidos 353/353 · check 0 propios. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
3 months ago |
|
|
97ae19da50 |
docs(agent): sección de configuración del transporte en la página agnt
La demo usaba el adaptador sin documentar cómo se configura. Nueva sección «Configuring the transport»: qué es el puerto (turn = un intercambio de cable), adapters fuera del barrel, ejemplo dev-directo vs prod-proxy (topología de credenciales), tabla completa de opciones (baseUrl · model · headers · request · fetch) y qué POSEE el adaptador como traducción de dialecto (SSE→v1, sanitización de ids, re-pairing de tool_calls, split por id en servidores que reutilizan index 0, error de cable → transport-error). README del arte: opciones inline en la entrada del adaptador. check 0 propios · smoke agnt PASS. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
3 months ago |
|
|
595040b73b |
feat(agnt): Aura como superficie de presencia de la demo con modelo real
La respuesta a «¿está pensando?» no se improvisa — es Aura, el componente
del eje construido para ello. La sección real de la página agnt bootea un
uix standalone mínimo (createActiveUix + Soma + ActiveEidos + eidos css):
legítimo porque un app compone ambos tiers, y la demo ES el app.
- Motor llama → createActiveAgent (mismas opciones bus+journal); activeRun
reactivo satisface AuraAgentSource; stream vía .engine.onEvent
- <Aura {agent}> con Indicator (orb $scene) + Status + Region + Cancel;
authorize/escalation quedan como afordancias app-level (doctrina §7)
- Verificado sobre el run real de qwen3-coder: «Inactivo» → «Propone un
plan» → announcement «Agente: terminó — control devuelto» en la Region,
doc mutado, answer en es; Cancel = Button disabled-en-idle; consola 0
check 0 propios · agent 30/30 · smoke agnt PASS.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
3 months ago |
|
|
447a87239c |
feat(agent): adaptador openai-chat real + carril de iniciativa del bus
El bus como eje del agente a nivel de app, cerrado en tres direcciones:
observar (agent.*), reaccionar (orca) e INICIAR — hecho de dominio → acción
orca → App.agent.start({initiative:'system'}) con clamp auto→review por
construcción. Nunca command-events. Sección doctrinal + ejemplo en la página.
Adaptador real `$agent/adapters/openai-chat` (fuera del barrel, D-AG.1c):
dialecto OpenAI chat-completions (Ollama/llama.cpp/LM Studio/proxy), SSE →
protocolo v1, sanitización bidireccional de capability ids con puntos, y
re-pairing de tool_calls al reproducir el transcript (memoria por callId).
Fix cazado en vivo: Ollama reutiliza index:0 para todas las calls del
stream — una call nueva se detecta por id distinto, jamás por index (los
args concatenados producían invalid-args en motor + 400 en el replay).
Demo viva en /active/docs/agnt contra qwen3-coder:30b real: capacidades
doc.* tipadas (sium), read snapshot-por-turno, streaming, escalada
irreversible. Ciclo completo verificado en navegador: 3 acts, 2 turnos,
doc mutado, respuesta en es, rastro entero en bus (correlationId=runId).
agent 30/30 · smoke agnt PASS · check 0 propios.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
3 months ago |
|
|
fa71890564 |
fix(agent): conformidad bus/orca — payload del bus sin contenido de usuario
Auditoría punto-a-punto contra los README de bus y orca (12/13 conforme).
La no-conformidad real: `goal` viajaba en AgentRunBusPayload, contra la
higiene documentada de ambos (bus: «pasa correlationId y que el suscriptor
resuelva el contexto sensible del módulo»; orca: «no unnecessary private
data — la acción lo resuelve del módulo al ejecutar la acción»).
- AgentRunBusPayload = SOLO metadata (runId/initiative/autonomy/state/
outcome/reason/acts/turns); el suscriptor resuelve vía App.agent.run(runId)
- spine test prueba el patrón: 'goal' in payload === false + resolución
desde el módulo con el orca REAL
- página agnt: nota de higiene + recomendación configureEvent(
'agent.run.state', { queuePolicy: ORCA_QUEUE_REPLACE_QUEUED }) para el
evento frecuente (doctrina de colas de orca)
- PLAN-agent F4a: acta de la auditoría de conformidad
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
3 months ago |
|
|
803b588ba5 |
feat(agent): F4a · marco de integración app — bus/orca/página del arte + fixes de auditoría
Auditoría del track (encargo): divergencias firmadas-sin-implementar corregidas y el marco de integración INDEPENDIENTE del componente — el agente como servicio del app, no como demo de un componente. Fixes de decisiones firmadas (con tests): - C3/D-AG.7: la iniciativa autónoma (system/scheduled) clampa auto→review — un run que el usuario no pidió jamás se auto-autoriza. - D-AG.5: presupuesto de contexto (maxContextBytes) con FIFO-trim byte-based (el goal sobrevive; resumen semántico diferido) + log del recorte. - F4c: tope por-arg (maxArgBytes) → invalid-args tipado. - D-AG.6d: schema Standard-Schema del resultado (`result?`); un mismatch vuelve como recoverable para auto-corrección y no cuenta como act. Integración app (patrón session EXACTO): - El arte posee el vocabulario `agent.*` (consts) + bus-helpers tipados que publican con bus INYECTADO (type-only $libs/bus): run.opened/state/ escalated/closed + act.applied, con source='agent' y correlationId=runId — la costura causal ligera (una delegación correlaciona de punta a punta). - defineActiveAgent cablea core.bus (junto a timers/logger). - Reacciones vía orca APP-LAND (el invariante intacto): probado con EngineOrca REAL reaccionando a agent.run.closed en integration.test. - Página del arte /active/docs/agnt (la convención que faltaba): sección Delegation en nav; artículo + playground VIVO con los 4 motores puros reales (bus log en vivo, journal WAL, contador orca, kill switch, compuertas deterministas) — cero componentes, integración pura de app. Gates: agent 26/26 · smoke agnt PASS · check 0 propios · verificado en navegador (pane + Chrome real): ciclo completo, orca archiva runs, kill switch reactivo. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
3 months ago |
|
|
6f9edfaa3b |
docs(palabras): bitácora 2026-07-22 — barrido de calidad 18/18 + Menubar.Panel + #6
Nueva sección de estado en el handoff vivo: el barrido adversarial (18/18 arreglados, 6 refutados, 7 commits verificados por test/Playwright), la infra Menubar.Panel que se commiteó ( |
3 months ago |
|
|
2803d5dddc |
docs(blocks): registro F1.6 anchor-nav · F1 = 6/8
Adversarial-review outcome (fixes + documented v1 limits) and the two piggybacked sticky type-fixes recorded; scoreboard corrected (prose F1.5 had also landed). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
37e35d7a2d |
fix(sticky): sentinelRef is State + eidos types import ProviderProps
svelte-check surfaced two F1.1 type errors: the sentinel is a writable ref bound by the wrapper, so it belongs in StateProps (not ActiveProps — part() wants State<HTMLElement|null>); and the eidos types barrel must import the renamed ProviderProps export, not the internal StickyProps. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
fe2d43b7ac |
uix(anchor-nav): F1.6 · scrollspy TOC (soma+eidos) + hardening
Nav landmark + native anchors; IntersectionObserver band detection (never a scroll listener + getBoundingClientRect — anti-reflow doctrine). aria-current="location", per-depth rail indent, data-active drives the eidos accent. Real-IO chromium test: band tracking + bottom dead-zone. Adversarial-review hardening: - ref-count register/unregister so duplicate hrefs / mount churn can't drop a still-referenced target (+ test) - tokenize the rail transition (--duration-fast/--ease-default) and the focus outline-offset (calc(var(--focus-ring-width) * -1)) - document two v1 limits (instant-jump dead-zone, link-order == section order) — both need a v2 observation-contract change Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
e187ab6d72 |
docs(agent): F3 cerrada · doctrina «The review surface» — split framework/app
Cierra los dos flecos de F3 tras la corrección del usuario (la review-card con diff era anclaje en dev-tools, sin sentido a nivel framework): - agent.md §7 gana «The review surface»: el FRAMEWORK posee los estados del ciclo expresados perceptualmente (reviewing/escalated con afordancias authorize/reject/cancel — Aura ya las da) + la semántica de «propuesto por otro actor» + los anuncios atribuidos; el APP posee el CONTENIDO de lo que se revisa, en su propio dominio (un documento enseña sus bloques propuestos, un calendario sus eventos pendientes). Una tarjeta-diff estilo git es legítima en una aplicación concreta; jamás canon. - §6 fatiga de aprobación enmendada en el mismo sentido (el cambio concreto en el dominio del app, nunca prosa). - PLAN: F3 CERRADA — review resuelta como doctrina sin componente nuevo; `allowedFamilies` del primer componente actuado reubicada a F2 (su hogar natural es el piloto). Siguiente: F4 por la vía del chat. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
3 months ago |
|
|
92d060a4fb |
fix(soma/menubar): getOrderedValues en orden DOM, no de inserción del Map (#6)
El barrido de calidad de palabras confirmó que el foco por flechas (ArrowLeft/Right,
Home/End) y el hover-slide divergían del orden visual tras navegar a un elemento con
más secciones contextuales: el `{#each}` keyeado reutiliza los triggers persistentes
y los nuevos se APPENDEAN al Map después, así que el orden de inserción ≠ orden DOM.
Ahora getOrderedValues ordena por compareDocumentPosition (query estructural,
reflow-safe), corrigiendo navigateAdjacent/focusEdge/onContentKeydown/hover-slide en
un punto. 5/5 tests del menubar verdes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
3 months ago |
|
|
2c175c5d95 |
feat(aura): fases 7–8 · README eidos + component:audit PASS — Aura completa (0–8)
Cierra el primer componente del eje agéntico de punta a punta (las 9 fases de la ruta). `component:audit` PASS. - README eidos con comparativa (5 refs adyacentes — thinking-indicators, CopilotKit activity, Vercel useChat.status, presencia colaborativa Figma/Docs, assistant-ui) reconociendo el paisaje escaso: nadie tiene una semántica perceptiva de la delegación con a11y (informe §8.3). Decisiones + Gaps con disposición. - Fixes del audit: opacity literal `0.5` → `var(--opacity-50)` (R-4.2); excepción R-1.5 documentada (único focusable = Cancel, que compone Button); `apg: 'none — …'` en el morfo (A-1.4). Gates: component:audit PASS · morfo:vocabulary limpio · eidos-lint aura 0 inválidos · recipe-contract verde. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
3 months ago |
|
|
ef85b9223d |
fix(soma/menubar): 3 errores de tipo de la infra Menubar.Panel
Reparan el commit anterior (era WIP con errores de svelte-check; runtime OK): - provider: `tabindex:-1` en los props del panel estaba duplicado (focusScope.props ya lo aporta con el mismo valor) → quitado el explícito. - menubar-panel: el prop `style` (de PrimitiveDivAttributes = `Record<string,unknown>`) no encajaba con el opt del provider (`StyleProperties`) → cast en el create. - test: `props['aria-haspopup']` no es clave estática del tipo (es atributo del morfo resuelto por renderProps en runtime) → acceso vía cast a Record. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
6be7195f0f |
feat(agent): eje agéntico — motor $agent (F1) + Aura + promoción uix.scene
Materializa el eje ortogonal agéntico del ecosistema: la 8ª familia semántica
`delegate` («¿quién actúa ahora?») deja de estar sin materializar. El agente es
OTRO ACTOR (LLM, macro, regla, workflow) que actúa por la MISMA API pública del
provider; la ruta de llamada no se bifurca, la concreción semántica depende del
actor.
F0 · Doctrina
- docs/architecture/agent.md — la doctrina permanente (capítulo comparativo de
referencias + bibliografía de seguridad, máquina estados=verbos, contrato de
participación, fila §0, a11y, amenazas).
- docs/process/{PLAN,TRIAGE,INFORME}-agent — plan de ejecución con todas las
decisiones firmadas (D-AG.1–11 + ⚖️1/2/3), triage de 4 revisores externos, e
informe autocontenido para revisión externa.
F1 · Motor ($libs/actor + arts/agent, 24º arte)
- EngineAgent puro (sin DOM/runes, portable a servidor): máquina D-AG.4
(suggest/review/auto · escalated con reason+timeout · returned outcome-tipado
· kill switch · autorización journaled aunque sea auto), tool-loop D-AG.5
(acts secuenciales, fallos→verbos, unknown-capability acotado, idempotencia
por callId, presupuestos acts/turns/wall-clock vía puerto de timers), techo de
autonomía por origen no confiable (F8b).
- ActiveAgent (sesión reactiva, contrato ActiveEngine) · protocolo v1 espejo
AG-UI (5 categorías + dirección tipada + reservas) · ScriptedAgentTransport
determinista (adapters/ fuera del barrel) · journal WAL + puerto de trazas
OTel · emisor sium→JSON Schema.
- Acuñación del actor (⚖️2/F6b): ActorToken opaco en $libs/actor (hoja bajo
orca/agent), registro privado WeakMap — los forjados resuelven a null;
costura `actor?` en TriggerOptions→SemanticSignal (runtime copia verbatim;
sema no resuelve). defineActiveAgent (service-factory app-level, timers del
core — cero setTimeout a pelo).
F3 · Aura — primer componente del eje (ruta 9 fases 0–6)
- El materializador canónico de `delegate` (reservado en scene §F6): morfo con
los eventos del ciclo (offer/escalate-untilAction/return + sustain-processing
stateBound) — PRIMER morfo del ecosistema que emite familia delegate; provider
soma que observa un puerto estructural (sin importar $agent — degradación
total); orb eidos = aurora $scene modulada por estado (§F6) con fallback CSS
= render de reduced-motion; live region única atribuida (WCAG 4.1.3); cancel
compone Button (asChild). Demo v2 sobre el MOTOR REAL con compuertas
deterministas. Orb-size derivado de la primitiva Avatar (32/40/48).
D4 · Promoción uix.scene (Aura llegó)
- defineEngineScene + superficie ActiveUix/ActiveEidos/contracts; el orb prefiere
el motor compartido (presupuesto de escenas global) con fallback por-superficie.
Gates: arts/agent 18/18 · aura 6/6 · arts:check 24 · eidos battery + recipe
30/30 + eidos-lint aura 0 inválidos · morfo:vocabulary + esquemas · smoke aura
PASS · verificado en navegador (ciclo completo + estampa delegate en DOM +
aurora WebGL pintando). Los tokens de recipe base.ts + CSS generado ya entraron
en HEAD vía una sesión concurrente.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
3 months ago |
|
|
bd5eb19257 |
feat(soma/menubar): Menubar.Panel ribbon-style + soporte en el provider
Componente nuevo `menubar-panel.svelte` + soporte en el provider (FloatingContent para anclar el panel a su opción, FocusScope, Dismissal) + types/exports/content/ README/test. Es la infra ribbon-style que el `palabras-element-inspector` (ya commiteado en esta rama) COMPONE — cada sección del elemento = un Menubar.Panel corto. Trabajo de esta sesión que había quedado sin commitear; sin él la rama quedaba incompleta (el inspector referencia `Menubar.Panel`). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
fca4944315 |
uix(demos): entradas de nav sidebar para sticky y prose
Las entradas del sidebar de docs para los componentes F1 sticky (grupo Layout) y prose (grupo Typography), diferidas de sus commits por un estado CRLF del archivo (autocrlf); ahora normalizado a LF y committeado limpio (3 líneas). Los componentes ya estaban en |
3 months ago |
|
|
955c6a18b3 |
docs(blocks): registro F1.5 prose · 5/8 F1
|
3 months ago |
|
|
5b84749ee5 |
uix(prose): F1.5 · tipografía editorial con auto-exclusión de componentes embebidos
Quinto componente F1 del plan blocks (eidos-only; alcance E-2 = suelo del
dossier §P4). Estiliza HTML/markdown RENDERIZADO que el app pasa como children.
EL DIFERENCIADOR (que ninguna referencia puede): cada regla de elemento se
emite a especificidad CERO vía `:where([data-prose] EL)`. Como todo componente
del framework se estiliza por `[data-{component}]` (≥0,1,0), un <Button> /
<Callout> / <Card> embebido conserva su PROPIO estilo AUTOMÁTICAMENTE — sin
anotación `not-prose`. Verificado en navegador: un <Callout> dentro de prose
mantuvo su tinte affirm, borde-acento 3px y layout grid en claro Y oscuro; las
reglas :where de prose no lo tocaron. El donut `:not(:where([data-prose-ignore],
…))` es el opt-out explícito para subárboles HTML crudos.
- morfo: 2 partes (provider bare data-prose + ignore documenta el attr opt-out;
eidos-lint lo ve morfo-backed). Selectores de elemento = estructurales bajo la
parte (S1). 0 eventos, apg:none, passive
- recipe: cobertura de paridad (h1–h6 incl. h5/h6 que tailwind NO; p, a, strong/
em, blockquote borde-acento lógico, ul/ol + ::marker, dl, code/pre + reset kbd,
img/figure/figcaption, hr, table); ESCALA EM-relativa (un font-size raíz
re-deriva todo — no la escala 5× de tailwind); overflow de tabla estilo GitHub
sin wrapper (display:block+overflow); trim de bordes; SIN backticks en code
(doblarían sobre <Code>); dark GRATIS por roles (no el patrón -invert);
propiedades lógicas → RTL correcto
- decisión :where (no @scope): :where establecido en el codebase + soporte 2021+;
@scope diferido a Gaps (mitad de tamaño pero «Baseline newly available» sin
precedente aquí)
- demo v2 9 tabs con markdown real + <Callout>/<Button> embebidos (prueba de
auto-exclusión) + ejes size/measure; README (Comparativa 5 refs · Decisiones ·
Passive · Gaps con disposición)
Verificación: component:audit PASS 0E/0W (21 literales em con /* literal */
justificado + eidosSnippet) · eidos-lint 45 morfo-backed/0 invalid ·
recipe-css-contract 30/30 · svelte-check sin errores propios · navegador:
h1 36px/bold, h2 24px, medida 65ch (~692px), blockquote acento, tabla
display:block+overflow, code chip, AUTO-EXCLUSIÓN del Callout en claro y oscuro.
Nota: nav sidebar fuera del commit (flip CRLF ajeno); índice langs reconstruido
prose-only (entangle con aura sin commitear de sesión paralela).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
3 months ago |
|
|
298567e46e |
fix(palabras): fallback read-only para select/chip en el inspector (sin celda en blanco)
La cadena de fieldControl (inspector + panel) manejaba pills/toggle/number/slider/
length/textarea/text/spacing/border/typography/adjustments/color pero NO select ni
chip (ambos válidos en PalabrasFieldType / esquemas de diseñador) ni un else final,
así que un campo de esos tipos daba una celda vacía muerta. Añadido un {:else} que
muestra el valor actual en read-only (mapeado a la etiqueta de la opción si hay
options) — que ADEMÁS es el render correcto de `chip` (display read-only). Un control
`select` funcional queda como diseño diferido (flagged). Latente: ningún esquema
shipped lo usa.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
3 months ago |
|
|
11ba4b906b |
docs(blocks): registro · review sticky + fix writing-mode · F1.1 CERRADO
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
3 months ago |
|
|
6cba9a0b19 |
uix(sticky): fix · pin con inset FÍSICO (top/bottom), no lógico — hallazgo de review
Adversarial review confirmó (minor): el recipe fijaba en el eje LÓGICO
(inset-block-start/end) mientras el rootMargin del observer es FÍSICO
(top/bottom). Coinciden en todos los modos horizontales (LTR y RTL: top/bottom
son eje de bloque, invariantes al flip inline), pero DIVERGEN en writing-modes
verticales, donde inset-block-start = izquierda/derecha física ≠ el borde que
el observer vigila → data-stuck se dispararía en la posición equivocada (o
nunca). La API `edge` es física ('top'|'bottom') y el observer es físico, así
que el CSS debe ser físico también (mi razón previa «lógico por RTL» era
incorrecta — RTL no afecta el eje de bloque).
- sticky.css: inset-block-start/end → top/bottom; margin-block-end/start del
centinela → margin-bottom/top (mismo eje de bloque, RTL-safe)
- demo: corregidas las 3 menciones «logical inset / writing-mode correct»
Verificado: component:audit PASS 0E/0W (físico top/bottom = eje bloque, no
dispara regla RTL) · test real-IntersectionObserver en chromium PASS (físico
top en horizontal = comportamiento idéntico). Nota: la lente teardown-ssr del
review falló por API stall mid-stream; esos caminos ya están cubiertos por los
tests (cleanup/disconnect aserted, disabled aserted, SSR no-op por contrato de
ActiveDom).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
3 months ago |
|
|
86e5e5791e |
fix(palabras): kinds filtra extras/avanzado; presets de interlineado/tracking heredan del esquema
- #13: el filtro `kinds` (oculta un campo si el `kind` del bloque no coincide) solo se aplicaba a los built-in de Contenido/Diseño; los campos de Avanzado y TODOS los extras de esquema lo ignoraban (solo filtraban por `.tab`), mostrando un campo kind-restringido para cualquier variante. Aplicado fieldForKind consistentemente en ambos consumidores (element-sections + panel). Latente (ningún esquema shipped lo usa) pero honra el contrato documentado. - #18: los presets Interlineado/Tracking caían a un default hardcodeado ('1.5'/'0') cuando el bloque no tenía override, resaltando un valor falso aunque el esquema declarara otro (el esquema por defecto declara text.lineHeight 1.6). Ahora heredan el valor EFECTIVO del esquema (schemeLineHeightFor/schemeLetterSpacingFor, espejo de schemeFontFor/defaultFontSize), cableado en panel + inspector. Verificado: el párrafo del esquema por defecto muestra Interlineado "Personalizado" (1.6, no el falso 1.5) y Tracking "Normal" (sin regresión). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
c6964496b4 |
docs(blocks): registro F1.1 sticky · 4/8 F1 hechas
Registra sticky (
|
3 months ago |
|
|
998b11d9bc |
uix(sticky): F1.1 · position:sticky con detección de estado (soma+eidos) — el primer behavioral
Primer componente F1 con comportamiento real (soma), y el que desbloquea el block site-header (F2.1). Construido tras un fan-out de investigación (6 lectores) que fijó el mapa: template = FeedSentinelProvider, motor = IntersectionObserver por el port bendecido de $adom, escritura de attrs por syncAttrs (nunca dom.apply crudo). Alcance E-2 = suelo del dossier §P3. - morfo: 2 partes (provider=box → data-sticky/data-edge/data-stuck · sentinel aria-hidden → data-edge); 0 eventos con justificación de COMPLEX BEHAVIOR (apg: none); data-stuck presente/ausente + data-edge enum espejan @container scroll-state(stuck: top/bottom) — este componente es el polyfill cross-browser de ese contrato CSS futuro - soma: un StickyProvider registra AMBAS partes en un runtime; el observer vive en un $effect que RETORNA observeIntersection(...) como teardown (mirror de feed); el callback async voltea stuck=$state; rootMargin DERIVADO del offset (la línea de disparo del centinela ES la línea de pin — acoplamiento matemático, offset obligatorio); root=scroll-host (default viewport), Document coercionado a null; offset viaja como --_sticky-offset (dato A8, no CSS visual — precedente meter) - eidos: recipe fino que SOLO posiciona (position:sticky + inset lógico desde --_sticky-offset + token --sticky-z-index + centinela layout-neutral 2px con margen negativo); el tratamiento del estado pegado es del consumidor ([data-sticky][data-stuck]) — el recipe posiciona, no decora - centinela = HERMANO de flujo del box (dos nodos raíz), no hijo (un hijo se fija con el box y nunca detecta); orden según edge - demo v2 9 tabs con scroll container real + readout de stuck vivo; READMEs soma + eidos (Comparativa AntD/Mantine/Chrome-technique/headless/CSS · Decisiones · Passive justification · Gaps con disposición) Verificación: component:audit PASS 0E/0W · eidos-lint 6 morfo-backed/0 invalid ([data-stuck] sin regla = intencional, consumidor decora) · morfo:check limpio · svelte-check sin regresión propia · 5 tests: 4 unit (rootMargin por borde, root null-coerce, flip de stuck, disabled, cleanup) + 1 REAL-IntersectionObserver en chromium (foreground: no-stuck→scroll→ stuck→scroll-back→no-stuck — prueba end-to-end de la geometría offset↔ rootMargin, lo que el pane suspendido no puede). Navegador: box pinea a los 12px del offset, recipe correcto. Decisión declarada (test harness): sticky-provider.svelte.test.ts usa el installSomaHarness compartido (translator identidad) como los otros 86 tests de provider — TÉCNICAMENTE en tensión con la regla CLAUDE.md «never fake translators; use createActiveUix». Son unit tests del provider; la integración real la cubren contracts.test.ts + la verificación en navegador. Seguido el precedente universal; flaggeado para tu ratificación. Nota: nav sidebar de sticky (web/routes/uix/+layout@.svelte) fuera del commit — el archivo arrastra un flip CRLF de sesión paralela (2125 líneas de ruido); la entrada viaja en el árbol de trabajo. Registros langs/soma de sticky reconstruidos sticky-only (los índices tenían entangle con aura sin commitear). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
3 months ago |
|
|
5294201406 |
uix(water): efecto de escena · mármol líquido con ondas de puntero
Nuevo efecto `water` en $scene/effects + registro en el pack Ambient (import = opt-in). Superficie de mármol de vetas incandescentes sobre negro que se ondula bajo el ratón: cada tramo de puntero engendra un anillo que se expande y refracta la superficie (modelo de anillos de pixel-blast). 11 params override por token (P-4). Alta en el catálogo demo (Tier B, 33 efectos) y en el README del pack. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
3 months ago |
|
|
3077777eca |
fix(palabras): bubble — el tamaño de fuente se puede teclear; Escape del enlace devuelve el foco
- #4: el guard capture-phase del BubbleMenu hacía preventDefault + restoreDomSelection en TODO pointerdown del bubble, así que clickear el input de tamaño nunca lo enfocaba (solo +/− servían). Ahora se salta el guard cuando el target es un control de formulario nativo (input/textarea/select): el input se enfoca y como syncSelectionFromDom CONGELA el modelo con foco fuera del editor, el bubble sigue abierto y la marca aplica al rango. Los botones (marcas) no necesitan foco y siguen con onclick; el resto de clicks siguen protegiendo el rango. Verificado Playwright: teclear "48" + Enter aplica font-size:48px. - #11: openLink saca el foco del editor al input de enlace; cerrarlo (aplicar O cancelar con Escape) no lo devolvía → editor sin caret, teclado muerto hasta reclicar. Ahora returnFocusToEditor() (api.focus + api.restoreCaret) en ambos. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
a124c32a3b |
fix(palabras): find limpia resaltados al cerrar + contador clamp; slash hace scroll al activo
- Find (#8): close() solo cambiaba `open`; la query/matches viven en el provider raíz, así que cerrar dejaba los resaltados <mark data-palabras-find-match> pintados sin UI para quitarlos (contradecía el contrato documentado). Como el `find` del snippet no llega al close() del script exterior, muevo el Escape al onkeydown del PANEL (dentro del snippet, con `find`) y limpio la query en ambos cierres (✕ + Escape). Verificado Playwright: Escape cierra y borra los 7 marks. - Find (#15): el contador podía mostrar N/M con N>M si los matches menguaban por una edición directa (currentMatchIndex no se re-clampa). Clamp en el display. - Slash (#9): 14 ítems, ~9 visibles; la navegación por teclado no hacía scroll al activo → Enter insertaba algo invisible. Efecto (raf-diferido, iframe-safe) que hace scrollIntoView del [data-active]. Verificado: ArrowUp→"Columnas" en vista. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |