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>
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>
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>
- diffuse — ecuación de fluidos discreta sobre los 3 campos dinámicos
(materia/psique/poder): cada celda intercambia con sus 4 vecinas +
entropía. Buffer de lectura separado (lee estado viejo). oro y
degradacion no difunden.
- tick — un paso completo: difusión → transiciones (agente exhausto se
fuerza a Pelear) → acciones de los agentes → envejecimiento + cosecha
(la energía del muerto vuelve como materia/fertilidad). run() corre N.
Determinista bit-exacto: aritmética f32 en orden fijo, sin HashMap ni
reducciones paralelas. Test `run_is_deterministic` verifica que mismo
input → mismo estado bit a bit.
7 tests verdes. cargo check --workspace verde. dominium ya CORRE
(core + physics = simulación funcional).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Opción B: RemoteEngine orquesta en un host remoto tunelando el wire
del daemon sobre un canal SSH direct-streamlocal hacia el sandokan.sock
remoto. El protocolo es idéntico al de DaemonEngine (postcard
length-prefixed) — sólo cambia el transporte, así que read_frame/
write_frame se reusan tal cual.
- brahman-ssh-multiplex: + SshSession::forward_unix — abre un canal
direct-streamlocal y devuelve su ChannelStream (AsyncRead+AsyncWrite).
- sandokan-daemon: protocol ahora pub, exporta read_frame/write_frame.
- sandokan-remote: RemoteEngine { SshSession + remote_socket }.
connect() o with_session(); cada operación abre un canal nuevo
(multiplexado sobre la conexión maestra).
- sandokan umbrella re-exporta RemoteEngine.
Completa Fase B: sandokan tiene Local + Daemon + Remote + auto().
cargo check --workspace verde. RemoteEngine necesita un host remoto
con `sandokan daemon` para validación runtime (sin unit test).
Opción A (text-parse del CLI por compat) queda pendiente por decisión
del usuario.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>