El cursor dejaba de ser un cuadrado fijo. Ahora honra
`wl_pointer.set_cursor`: sobre el texto de una terminal sale la «I»,
sobre un enlace la mano, etc. — la forma la dibuja el cliente en una
superficie y el compositor la compone.
- `App` guarda un `cursor_status: CursorImageStatus`; el handler
`SeatHandler::cursor_image` lo actualiza.
- `render()` lo interpreta: `Surface` → compone el árbol de la
superficie del cursor en `pointer_loc - hotspot` (helper
`cursor_hotspot`, vía `CursorImageSurfaceData`); `Named` o sin tema →
el cuadrado de siempre; `Hidden` → nada.
- Sobre el escritorio pelado (sin cliente debajo) el cursor vuelve al
de por defecto, para que no se quede con la «I» de la última ventana.
- La superficie del cursor también recibe frame-callbacks (cursores
animados).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sin decoración, las ventanas se confundían entre sí. Ahora el backend
DRM dibuja un marco fino alrededor de cada ventana: azul la que tiene
el foco del teclado, gris las demás.
- `ManagedWindow` gana `focused: bool` (lo fija `exec_op` al atender
`BodyOp::Focus`/`Unfocus`) y `borders: [SolidColorBuffer; 4]` — un
búfer por lado, cada uno con su `Id` estable para el seguimiento de
daño; `SolidColorBuffer` sube su contador sólo si tamaño o color
cambian, así un marco quieto no fuerza recomposición.
- El enum `Frame` pasa de `Cursor` a `Solid`: una variante de color
sólido que sirve para el cursor y para los marcos (dos variantes con
el mismo tipo chocarían en el `From` que genera `render_elements!`).
- `render()` en dos pasos: refresca los búferes (tamaño = contenido,
color = foco) y luego arma los elementos. El marco va metido hacia
adentro, sobre el borde de la superficie, así no pisa al vecino.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Un escritorio sin forma de abrir una terminal no es usable. Ahora el
keymap puede lanzar programas:
- `mirada-protocol`: nuevo `BrainCommand::Spawn(String)`.
- `mirada-brain`: `DesktopAction::Spawn(String)` con forma textual
`spawn:<comando>` (`Display`/`FromStr`); `Desktop::apply` la traduce
a `BrainCommand::Spawn`. El keymap por defecto trae
`Super+Shift+Return` → `spawn:foot`. `DesktopAction` deja de ser
`Copy` (lleva el comando) — `Keymap::lookup` clona en vez de copiar.
- `mirada-body`: `BodyOp::Spawn(String)`.
- `mirada-compositor`: `exec_op` ejecuta el spawn con un helper
`spawn_command` (`sh -c`, hereda `WAYLAND_DISPLAY`), que también
recoge el lanzamiento de `MIRADA_STARTUP` — antes duplicado.
`spawn:foot --title x` también funciona desde `mirada-ctl`. Tests
nuevos del round-trip textual y del flujo atajo→comando.
Nota: un keymap.ron ya existente no recibe el atajo nuevo; hay que
añadir la línea a mano o borrar el archivo para regenerarlo.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`Super`+arrastre interactivo en el backend DRM: botón izquierdo mueve
la ventana, botón derecho la redimensiona. Al arrastrarla, la ventana
pasa a flotar — comportamiento estilo dwm.
La verdad geométrica vive en el Cerebro, así que el arrastre viaja
hasta él:
- `mirada-protocol`: nuevo `BodyEvent::WindowFloatTo { id, rect }`.
- `mirada-brain`: `Desktop::on_event` lo atiende — busca el escritorio
de la ventana y la hace flotar en ese rectángulo
(`Workspace::set_floating`). Dos tests nuevos.
- `mirada-compositor`: `DragGrab`/`DragMode` en `App`; `handle_input`
arranca el arrastre con `Super`+botón sobre una ventana
(`keyboard.modifier_state().logo`), traga los botones mientras dura y
lo cierra al soltar. `drag_update` recalcula el rectángulo (mover =
esquina sigue al puntero; redimensionar = esquina inferior-derecha,
con un mínimo de 120 px) y emite `WindowFloatTo`. Durante el arrastre
el puntero no llega al cliente.
De paso, arregla un test de `mirada-link` que construía un
`WindowPlacement` sin los campos `floating`/`fullscreen`.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Un escritorio teselante no quiere barras de título de cliente. El
compositor anuncia ahora `xdg-decoration` y a todo toplevel le impone
`Mode::ServerSide`; como el servidor no dibuja decoración alguna, las
ventanas quedan sin marco.
Sin esto, clientes como `foot` se dibujan su propia barra (CSD) con
botones de minimizar/maximizar/cerrar — ruido en un WM teselante.
- `XdgDecorationHandler` para `App`: `new_decoration`, `request_mode`
y `unset_mode` fijan siempre `ServerSide` y reenvían el configure.
- `delegate_xdg_decoration!(App)`; el global se anuncia en `build_app`.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El backend DRM del Cuerpo deja de ser sólo-teclado: `libinput` ahora
mueve un cursor de software y reenvía clics y rueda a los clientes.
- Enum `Frame` (vía `render_elements!`) que mezcla superficies de
cliente y un `SolidColorRenderElement` para el cursor, marcado
`Kind::Cursor` y compuesto encima de todo.
- `handle_input` atiende `PointerMotion`/`PointerMotionAbsolute`/
`PointerButton`/`PointerAxis`; el puntero se acota a la salida.
- Foco-sigue-ratón: `window_at` hace el test de impacto (flotantes
sobre teseladas, contra el rectángulo real de la superficie) y, al
cambiar de ventana, emite `BodyEvent::PointerEntered`.
- `surface_px_size` en main.rs — tamaño presentado de una superficie,
reusado por el test de impacto.
Compila + clippy limpio; pendiente de verificar en hardware.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
mirada-compositor tiene dos backends: winit (anidado) y drm (nativo
sobre TTY, verificado en hardware). README con la selección de backend,
los requisitos de cada uno y MIRADA_STARTUP/MIRADA_DRM_TIMEOUT; SDD con
la estructura del backend DRM. Pendiente: puntero en DRM, VT switch,
hotplug.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Dos remates de la tanda WM.
Fullscreen del cliente:
- BodyEvent::FullscreenRequest { id, fullscreen }. mirada-compositor
implementa XdgShellHandler::fullscreen_request / unfullscreen_request
y avisa al Cerebro; Desktop::on_event fija el fullscreen en el
escritorio que tiene la ventana. Así un reproductor o un juego que
llama a xdg set_fullscreen entra a pantalla completa solo.
HUD multi-salida (app mirada):
- El lienzo dibuja todas las salidas a escala (encaja su caja
envolvente en el lienzo fijo; con una salida, 1:1), cada una con su
marco y su número/escritorio. En simulación, Shift+n añade un monitor.
mirada-brain 63->65 tests.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Una ventana se puede guardar en el scratchpad (oculta, en ningún
escritorio) e invocar a voluntad como overlay flotante — el patrón de
la terminal desplegable.
- Desktop.scratchpad: Vec<WindowId>. SendToScratchpad saca la ventana
enfocada del teselado y la guarda; ToggleScratchpad (Super+`) la
invoca flotando y centrada en el escritorio activo, o la oculta.
- Invocarla desde otro escritorio la trae consigo (sale de donde
estuviera). WindowClosed la quita del scratchpad.
- window_lines marca las guardadas como workspace 0; mirada-ctl windows
las lista como «esc scratch».
Sin cambios de protocolo — una ventana del scratchpad invocada no es
más que una flotante. Verificado end-to-end con headless-ctl.
mirada-brain 58->63 tests.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El Desktop deja de teselar sólo la salida primaria. Cada Output muestra
un escritorio virtual distinto y relayout() las tesela todas en un solo
Place que cubre todas las pantallas.
- Output { id, rect, workspace }; focused_output reemplaza al índice
global active. active_index() = el escritorio de la salida enfocada.
- OutputAdded asigna el primer escritorio libre; OutputRemoved deja sus
ventanas en su escritorio y reajusta el foco. reflow_outputs() las
recoloca en fila.
- SwitchWorkspace actúa sobre la salida enfocada; si el escritorio
pedido ya lo muestra otra salida, las intercambia (invariante: un
escritorio se ve en una salida como mucho).
- DesktopAction::FocusOutputNext (Super+o) mueve el foco entre
monitores. El foco del teclado es único — relayout() lo unifica a la
ventana enfocada de la salida enfocada.
Verificado end-to-end con headless-ctl (ahora 2 salidas).
mirada-brain 52->58 tests.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
ToggleFullscreen (Super+Shift+f) lleva la ventana enfocada a pantalla
completa: cubre toda la salida sin gap, oculta al resto y se lleva el
foco. Distinto del modo Monocle (un modo de teselado): es un estado
por ventana que ignora el layout.
- Workspace.fullscreen: Option<WindowId>; set_fullscreen / fullscreen();
remove() lo limpia si se cierra esa ventana.
- placements() da a la fullscreen el rect completo y marca al resto
visible: false. WindowPlacement y BodyOp::Configure llevan
fullscreen: bool.
- mirada-compositor fija el estado xdg_toplevel::Fullscreen en la
superficie, para que el cliente lo sepa.
- Cableado en keymap, HUD de mirada y mirada-ctl.
Verificado end-to-end con headless-ctl. mirada-protocol 10->11,
mirada-brain 51->52.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
mirada-brain::rules — config declarativa que decide qué hacer con una
ventana al abrirse, mismo patrón que el keymap.
- Rule casa por subcadena de app_id y/o title (sin distinguir
mayúsculas; vacío = cualquiera) y aplica un destino: workspace (1..9)
y/o floating. Gana la primera regla que case.
- Rules en RON (~/.config/mirada/rules.ron); la primera vez se escribe
una plantilla con ejemplos comentados, si está corrupta se ignora.
- Desktop consulta Rules::resolve en cada WindowOpened — el evento ya
trae app_id/title — y abre la ventana en su escritorio, flotando si
toca. set_rules en Desktop; las apps cargan rules.ron al arrancar.
mirada-brain 42->51 tests.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Una ventana puede salir del teselado y flotar: conserva su propio
rectángulo y se compone por encima de las teseladas.
- Workspace guarda las flotantes en un mapa aparte; layout() tesela
sólo las no-flotantes y añade las flotantes al final (orden de
pintado). set_floating / is_floating.
- WindowPlacement y BodyOp::Configure llevan floating: bool. BodyState
detecta el cambio de floating como cualquier otro reconfigure.
- DesktopAction::ToggleFloat (Super+f): saca la enfocada a un
rectángulo centrado al 60 % de la pantalla, o la devuelve al teselado.
En Monocle, una flotante sigue visible.
- mirada-compositor ordena las flotantes al frente de la lista
front-to-back de elementos → se pintan encima.
- HUD de mirada marca las flotantes; mirada-ctl toggle-float.
Verificado end-to-end con headless-ctl. mirada-layout 30->32,
mirada-protocol 9->10, mirada-body 13->14, mirada-brain 41->42.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Tanda de funciones de tiling WM, toda pura (mirada-layout/brain), sin
tocar el protocolo:
- nmaster: LayoutParams.master_count — cuántas ventanas van en el área
maestra. MasterStack y CenteredMaster apilan N maestras; sin pila, las
maestras llenan la pantalla. Acciones inc-master/dec-master (Super+,
Super+.), acotadas 1..9.
- Promover a maestra: Workspace::promote_focused lleva la ventana
enfocada al puesto 0. Acción promote-to-master (Super+Return).
- Smart gaps: una sola ventana se tesela a sangre, sin margen.
combo_string del compositor canoniza ahora teclas con nombre (Return,
Tab, F5, flechas…) vía xkb::keysym_get_name, no sólo caracteres
imprimibles — sin eso Super+Return no sería un atajo expresable.
Cableado en keymap por defecto, HUD de mirada y mirada-ctl. Verificado
end-to-end con headless-ctl. mirada-layout 26->30, mirada-brain 39->41.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
mirada-layout pasa de 4 a 7 modos de teselado, todos intercambiables
por el API (SetLayout / CycleLayout / mirada-ctl layout <modo>):
- Rows: filas horizontales de igual alto (complemento de Columns).
- Spiral: espiral de Fibonacci — cada ventana parte por la mitad el
espacio restante, alternando el sentido del corte.
- CenteredMaster: maestra centrada + pila a ambos lados (monitores
anchos).
LayoutMode::ALL + next() definen el ciclo. Añade dos acciones,
GrowMaster/ShrinkMaster (Super+l / Super+h), que ajustan master_ratio
en caliente — ese parámetro existía pero no había forma de tocarlo.
Cableado completo: tile(), cycle, slugs Display/FromStr, keymap por
defecto (Super+r/d/s), HUD de mirada, mirada-ctl actions. El ejemplo
headless-ctl ahora imprime la geometría para verificar los layouts.
mirada-layout 22->26 tests, mirada-brain 37->39.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Toda acción de escritorio converge en Desktop::apply(DesktopAction); el
keymap era sólo un front-end. Esta tanda añade los otros tres.
- DesktopAction::FocusWindow(WindowId): direccionamiento directo de una
ventana (no sólo ciclar); si está en otro escritorio, salta a él.
DesktopAction pasa a ser Serialize/Deserialize (postcard) además de
Display/FromStr.
- mirada-brain::ctl: el API de control externo. CtlRequest/CtlReply
(marco postcard), CtlServer/CtlConn no bloqueantes y send_request.
El Cerebro abre el socket y atiende en su bucle: la app mirada
siempre, mirada-compositor sólo con el Cerebro embebido.
- mirada-ctl: CLI de control estilo swaymsg/hyprctl —
`mirada-ctl focus-next | focus-window 5 | workspace 3 | windows`.
Parsea la acción de los argumentos vía FromStr.
- HUD interactivo en la app mirada: pips de escritorio y ventanas del
lienzo clicables (SwitchWorkspace / FocusWindow).
- Ejemplo headless-ctl: un Cerebro sin gráficos para probar mirada-ctl
en modo desatendido. Verificado end-to-end.
mirada-brain: 29 -> 37 tests.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Los atajos de teclado dejan de estar cableados: ahora son un Keymap
configurable que vive sólo en el Cerebro. El Cuerpo nunca lo ve — sólo
recibe la lista de cadenas a interceptar (GrabKeys) y devuelve la
pulsada; es Desktop quien la traduce. Esa separación (qué interceptar
vs. qué significa) hace innecesario cualquier candado o Arc.
mirada-brain:
- keymap.rs — Keymap: from_ron/to_ron, load/save, load_or_init (escribe
un archivo por defecto documentado si falta; default sin pisar si está
corrupto), default_path (~/.config/mirada/keymap.ron), y watch sobre
notify para la recarga en caliente (KeymapWatch).
- DesktopAction: Display + FromStr — vocabulario textual estable
("focus-next", "layout:grid", "workspace:3"); evita los guiones que
romperían el RON de un enum.
- Desktop: with_keymap, set_keymap (cambio en caliente -> nuevo GrabKeys).
- Ejemplo keymap-default: imprime el archivo por defecto en RON.
Apps: mirada y mirada-compositor (modo embebido) cargan el keymap del
usuario al arrancar y lo recargan en caliente cuando el archivo cambia.
Disco RON, cable postcard (sólo la lista de cadenas), sin ejecutable
configurador. mirada-brain: 17 -> 29 tests.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Compositor Wayland teselante real sobre smithay, backend winit (corre
anidado como ventana dentro de la sesión X11/Wayland actual). Habla
wl_compositor/xdg_shell/wl_shm/wl_seat/wl_data_device y compone las
superficies de los clientes con GlesRenderer.
Dos modos: autónomo (Cerebro Desktop embebido, un solo proceso) o
enlazado (MIRADA_SOCKET → la app mirada decide la geometría). Reusa
mirada-body para la contabilidad y mirada-link para el cable.
Actualiza el SDD: el Cuerpo deja de ser pendiente. Añade README.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
BodyState agnóstico de smithay: lleva salidas + superficies, traduce
BrainCommand a BodyOp (sólo lo que cambia) y emite BodyEvent desde los
mutadores del backend. Ejemplo headless: Cuerpo sin gráficos guiado por
stdin para ejercitar el bucle Cerebro↔Cuerpo. 13 tests.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Link<Out,In> sobre socket Unix: hilo lector de fondo + canal mpsc para
sondeo no bloqueante. BrainLink/BodyLink, connected_pair (socketpair),
connect/listen por ruta; Drop cierra el socket y propaga EOF. 7 tests.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Desktop agnóstico de GPUI/smithay: salidas, 9 escritorios virtuales,
registro de ventanas y foco. on_event(BodyEvent) -> Vec<BrainCommand>;
DesktopAction + mapa de teclas estilo tiling WM (Super). 17 tests.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
BrainCommand/BodyEvent + WindowPlacement, marco postcard con prefijo u32
LE (write_frame/read_frame, guard MAX_FRAME) y el puente placements()
desde un Workspace de mirada-layout. 9 tests.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
matilda-discover gana discover_inventory(): corre docker inspect en
cada contenedor y compara contra el spec deseado — imagen, puertos,
env y volúmenes declarados. Si el contenedor que corre se desvió, el
plan emite un Update; si está al día, no hay acción. La comparación es
por satisfacción (lo extra que trae la imagen se ignora).
El CLI (--discover) y el shell (:matilda) ahora usan discover_inventory
en vez del descubrimiento por nombre: detectan no sólo qué crear y
eliminar, sino la deriva de configuración de lo que ya existe.
container_drift es puro — 6 tests nuevos con JSON de docker inspect.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Observa qué contenedores y vhosts existen (docker ps + sitios de
nginx) y reconstruye un Inventory "actual" que matilda-plan diferencia
contra el deseado: detecta correctamente qué crear y qué eliminar
(huérfanos). Parseo puro y testeable; sólo discover_local toca el
sistema. 6 tests.
La CLI gana el flag --discover en plan/script/apply: reconcilia
contra el estado real de la máquina en vez de partir de vacío.
matilda: 7 crates + CLI, ~48 tests. Pendiente: matilda-app (GPUI) y
la inspección detallada (docker inspect) para detectar drift de
configuración, no sólo presencia.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
matilda-ghost: el agente que ejecuta los ApplySteps en la máquina
destino — escribe archivos, corre comandos, reporta paso a paso;
semántica set -e (se detiene en el primer error). dry_run previsualiza
sin tocar nada. 5 tests.
matilda-linker: aplica los pasos en un host remoto por SSH sobre
brahman-ssh-multiplex; produce el mismo ApplyReport que el ghost local.
apps/matilda: deja de ser una demo hardcoded — ahora es una CLI real:
matilda example | plan | script | apply (local · --dry-run · --host)
Carga el inventario de un JSON, reconcilia y aplica.
matilda: 6 crates + CLI, ~42 tests. La cadena va de la declaración
a la aplicación local/remota.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Traduce un Plan de reconciliación a ApplySteps concretos: por cada
acción, los archivos a escribir en el servidor y los comandos a
correr. Contenedores → docker rm/run; vhosts → archivo nginx +
reload; hosts → sin pasos (son destino de conexión, no algo a
aplicar). steps_to_script() emite un script bash único con heredocs.
Sigue agnóstico de transporte — ejecutar los pasos (local, SSH o vía
matilda-ghost) es la capa de I/O. La demo CLI ahora imprime el script.
6 tests; matilda llega de la declaración al script ejecutable.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El volcado de la salida excedente ya no copia por espacio de usuario:
pasado el tope, el lector escribe la línea que cruzó + lo bufereado y
luego mueve el resto del pipe al archivo con splice(2) —kernel a
kernel, sin copia—. Se aplica a stdout (el contenido principal).
shuma-shell limpia sus archivos de volcado al cerrar la sesión
(Drop). Los spills llevan el pid en el nombre para no chocar entre
instancias.
shuma-exec: 11 tests verdes (el de spill ahora verifica el camino
splice).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
bash deja de ser el ejecutor. shuma-exec ahora tiene dos modos:
- Exec::Direct — brahman lanza y conecta cada etapa del pipe con
descriptores reales; control total del árbol de procesos.
- Exec::Shell — fallback a `bash -c` para sintaxis que el modo directo
aún no absorbe (globs, $VAR, redirecciones, &&). bash = un parser
de sintaxis, no el ejecutor por defecto.
El shell elige: pipe simple (sólo comandos/args/`|`) → directo; algo
más → shell. La WorkSession lleva su CapturePolicy (límite + spill),
configurable con `:limit <MB>` y `:spill on|off`; la barra de estado
la muestra. Si spill está activo, la salida excedente se vuelca a un
archivo en vez de descartarse (RunEvent::Spilled).
shuma-exec: 11 tests (directo, pipes, spill, kill de pipeline).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
shuma-exec: cota dura de memoria. CommandSpec.capture_limit (bytes):
pasado el tope se emite RunEvent::Truncated una vez y el resto se
descarta —pero el pipe se sigue drenando, así el proceso no se
bloquea y termina normal. CommandSpec.stdin_data alimenta un texto
por la entrada estándar (escrito en su propio hilo).
shuma-session: CommandRun.truncated.
shuma-shell: tope de captura de 8 MiB por comando. Cada card con
salida muestra «⤳ reprocesar» — al pulsarlo, el próximo comando
filtra esa salida capturada (vía stdin) sin re-ejecutar el original;
un banner marca el modo. Las cards truncadas avisan «⚠ truncado».
shuma-exec: 12 tests (incluye truncado y reproceso por stdin).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
shuma-infer: el directorio de una ocurrencia es ahora el cwd de su
último comando (el dir donde realmente operó el patrón, ya hechos los
cd). predict_next devuelve también el índice del patrón.
shuma-shell: la predicción se filtra por marcadores de proyecto
(.git, Cargo.toml, package.json, go.mod…). El shell deriva la
condición de disparo de un patrón —los marcadores comunes a sus
directorios— y sólo lo anticipa en un cwd que comparta esa estructura.
Así el ghost no sugiere `cargo build` en un directorio sin Cargo.toml.
Cierra la visión: del scripting a la intención, con precisión.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
shuma-line: ghost_suggestion(line, corpus) — el resto de la línea que
el shell predice, a partir de un corpus priorizado.
shuma-infer: predict_next(recent, patterns) — si los últimos comandos
coinciden con el prefijo de un patrón, devuelve los pasos que faltan.
shuma-shell: mientras se escribe, el prompt pinta en gris tenue la
continuación predicha — historial reciente o, con prioridad, la
secuencia que el motor de inferencia anticipa (cd a un proyecto →
fantasma «git pull && cargo build»). La flecha → al final de la
línea, o Ctrl+Space, aceptan el fantasma.
13 tests shuma-infer, 37 shuma-line.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Detecta patrones de comandos repetidos en el historial: ventana
deslizante sobre las firmas de binarios (sólo ventanas 100%
exitosas), abstracción de argumentos variables (cd /a vs cd /b →
cd <…>), patrones maximales, puntaje por largo × frecuencia.
10 tests, agnóstico y determinista.
El shell lo corre tras cada comando terminado y promueve el patrón
más fuerte a un grupo «✨ ...» en el panel [RUN] — la rehidratación
que convierte la repetición orgánica en una receta de un clic.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
shuma-exec: RunHandle::kill() — el proceso se comparte con su hilo
coordinador (Arc<Mutex<Child>>) para poder terminarlo; los lectores
cierran al cerrarse los pipes. 8 tests (incluye kill de un sleep).
shuma-shell:
- Cada tarjeta de comando en curso (▷) muestra un botón «✕ matar».
- Meta-comando `:save <nombre>` guarda como grupo los comandos
ejecutados desde el último guardado. El botón «+» del panel [RUN]
precarga «:save » en el input para nombrarlo.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- shuma-session: la salida de un comando ahora distingue el flujo
(OutputLine { stream, text }); CommandRun expone lines_of/count_of/
has_stderr.
- Las tarjetas del feed se acordeonan (clic en la cabecera). El filtro
de la cabecera muestra stdout por defecto; si hubo stderr aparece el
switch «⚠ N» para verlo.
- Orden de terminal: los comandos nuevos se acolan abajo, los viejos
suben y se autocolapsan — salvo que el usuario haya tocado el
acordeón a mano (user_touched).
- El feed sigue al comando más reciente (ScrollHandle::scroll_to_bottom).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
shuma-session: el shell trabaja dentro de una WorkSession — directorio
actual (que es el identificador de aislamiento, hash estable del cwd),
historial de comandos ejecutados (CommandRun con salida y estado) y
grupos de comandos guardados y reutilizables (CommandGroup).
shuma-exec: ejecutor con salida en streaming — lanza bash -c en un
directorio y entrega stdout/stderr línea a línea por un canal, sin
esperar al final. Es la capa que sandokan (poll-based, orquesta Cards)
deliberadamente no cubre.
15 tests. Agnósticos de UI, #![forbid(unsafe_code)].
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El input de abajo ahora está vivo sobre shuma-line: se escribe de
verdad (teclado completo, motions, Ctrl+a/e/u, UTF-8), con resaltado
por token en tiempo real (comando, flag, string, variable, pipe,
redirección…) y autocompletado posicional con popup navegable
(↑↓ Tab) — comandos del PATH, flags por comando, rutas del disco.
Enter registra la línea en el lienzo de intenciones; las etapas de
pipe se cuentan en la barra de estado.
Panel derecho [SENS]: monitores de CPU y memoria con curva en vivo
(shuma-sysmon, refresco ~1s). Paneles laterales colapsables.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Lee /proc/stat y /proc/meminfo; calcula uso de CPU (delta entre
muestras) y de memoria; mantiene un History circular para la curva
del monitor. Parseo puro (parse_cpu_stat/parse_meminfo) separado de
la lectura de archivos → testeable sin tocar el sistema.
8 tests. #![forbid(unsafe_code)], cero deps de UI.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Análisis de la línea de comandos bash, listo para GUI o TUI:
- lexer: tokeniza + clasifica (comando vs argumento por etapa),
reconoce comillas, variables, tuberías, redirecciones, operadores.
- pipeline: descompone la línea en etapas separadas por |.
- complete: autocompletado posicional (comando / flag / ruta) con
CompletionSource inyectable; diccionario de flags por comando.
- LineState: input editable UTF-8-safe (cursor, motions, completado).
- Dialect conmutable (bash hoy; zsh/fish/python a futuro).
32 tests. #![forbid(unsafe_code)], cero deps de UI.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Rect + split (reparto exacto de píxeles), 4 modos de layout
(MasterStack, Monocle, Grid, Columns) con tile(), y Workspace:
ventanas en orden de teselado, foco cíclico, reordenado y
resolución de geometría. Determinista, agnóstico de Wayland/smithay.
22 tests. #![forbid(unsafe_code)].
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Cimiento numérico del transpilador. Picture parsea la cláusula
PICTURE (9, V, S, 9(n)); Decimal es punto fijo exacto (mantissa i128
+ scale) con suma/resta/producto exactos, división con escala de
resultado fija, redondeo Truncate/HalfUp y coerce a un Picture con
detección de desbordamiento (ON SIZE ERROR).
22 tests. Determinista, sin deps de plataforma — base de Fase D.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
yachay-core: notebook como secuencia de celdas (orden de lectura) +
DAG de dependencias (orden de ejecución). Celdas markdown/código/embed
con content_hash BLAKE3; editar una propaga staleness a descendientes;
digest Merkle por celda (content_hash ‖ digests upstream) y
notebook_digest que certifica reproducibilidad. Demo CLI en apps/yachay.
14 tests. Sin kernel ni UI, #![forbid(unsafe_code)].
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
matilda-core: modelo declarativo (Host, Container, VHost, Inventory).
matilda-config: renderiza Container→docker-compose/docker run y
VHost→bloque server nginx (con TLS + redirección :80→:443).
matilda-plan: reconciliación pura actual→deseado con acciones
ordenadas por dependencia (contenedores antes que vhosts, removes
en orden inverso). Demo CLI en apps/matilda.
29 tests. Funciones puras, cero Docker/SSH/disco.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Pitch MIDI (clase/octava/frecuencia ET A4=440), Scale (raíz + patrón
de semitonos: mayor, menor natural, pentatónica), Chord (7 cualidades,
voicing, nombres) y un Score multipista con tempo: ScoreNote en
pulsos, Track con inserción ordenada y transposición atómica.
24 tests. Agnóstico de síntesis y UI, #![forbid(unsafe_code)].
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
CLI que siembra un cuaderno (cocina/jardín/oficina), imprime el grafo
de wiki-links (forward/backlinks, huérfanas, colgantes) y los
clústeres por gravedad semántica + vecinos + layout 2D.
cargo run -p badu.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
badu-core: modelo Note + NoteStore (etiquetas, búsqueda) + grafo de
wiki-links [[...]] derivado del cuerpo (forward/backlinks, huérfanas,
enlaces colgantes; resolución case-insensitive).
badu-gravity: SemanticField sobre vectores semánticos — afinidad
coseno, vecinos más cercanos, clústeres por umbral (union-find) y
layout 2D dirigido por fuerzas (notas afines se atraen, todas se
repelen; determinista, sin RNG).
29 tests. Cero red, #![forbid(unsafe_code)].
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
agorapura-core: identidades fractales (persona/comunidad/alianza/
institución) sobre claves ed25519, Claims sujeto-predicado-valor y
Attestations firmadas y autoverificables (la prueba viaja con el
dato). agorapura-graph: TrustGraph guarda sólo atestaciones con firma
válida; corroboration() devuelve evidencia cruda y TrustPolicy —un
umbral negociado, no una verdad del sistema— la traduce a sí/no.
22 tests. Cero red, cero estado global, #![forbid(unsafe_code)].
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>