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>
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>
Envuelve mirada-brain::Desktop y lo pinta: barra con escritorios + modo
+ foco, lienzo teselado con marco por ventana. Con MIRADA_SOCKET sondea
un Cuerpo por mirada-link; sin él, simulación con ventanas sintéticas y
teclado (n/w/j/k/tab/1-9). cargo build -p mirada limpio.
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>
matilda deja de ser sólo un ejecutable aparte: el shell lo incorpora
como herramienta. Meta-comando `:matilda plan|script|apply
<inventario.json>` — reconcilia contra el estado real de la máquina
(matilda-discover) y vuelca el resultado al feed del shell:
- `plan`/`script` → una tarjeta sintética con el plan o el script.
- `apply` → ejecuta el script de verdad; su salida fluye en una
tarjeta como cualquier comando (streaming, captura acotada, kill).
El panel [RUN] gana una sección [tools] con «⚙ matilda» que precarga
el comando. Reusa todo lo del shell —feed, ejecución, sesión— sin
panel nuevo ni peso extra: la herramienta es no invasiva.
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>
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>
El shell ahora ejecuta de verdad. Adiós a los cuadros verdes de
ejemplo: el panel central muestra los comandos ejecutados, cada uno
con su salida llegando en streaming (shuma-exec lanza el proceso,
un bucle de fondo drena stdout/stderr ~9 veces/s).
El shell vive dentro de una WorkSession (shuma-session): la barra de
estado muestra el directorio actual y su identificador de aislamiento
(hash estable del cwd — cd lo cambia). `cd` se maneja internamente.
El panel [RUN] lista los grupos de comandos reutilizables; un clic
ejecuta el grupo entero (lines unidas por &&).
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>
CLI que recorre el caso canónico de extremo a extremo: Venezuela
atestigua la nacionalidad de Yumaira, otras identidades corroboran,
una firma manipulada se rechaza, y tres políticas negociadas dan
veredictos distintos sobre la misma evidencia. cargo run -p agorapura.
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>
fana-editor-gpui: EdgesElement pinta los conectores de dependencia
como paths; editor_view compone bloques de átomo (divs absolutos
coloreados por coherencia) + osciloscopio del sidepane. RenderPlan
ahora lleva su LayoutConfig para que el backend sea autosuficiente.
app fana: ventana con un relato de ejemplo (rama principal + alterna),
botón «Mutar raíz» que dispara la onda de choque lógica
(propagate_mutation), «Re-validar todo», leyenda y estadísticas.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
build_plan(NarrativeGraph) → RenderPlan: AtomBlocks apilados por
profundidad topológica (una columna por rama), Edges de dependencia
(borde inferior → superior) y osciloscopio de coherencia en el
sidepane (tono + intensidad semántica normalizada). Determinista:
orden desempata por (profundidad, columna, id). 10 tests.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Daemon que carga un Provider una vez y lo sirve sobre socket Unix;
DaemonClient lo consume desde otro proceso implementando el trait
Provider (indistinguible de un backend local). Multi-instancia: un
daemon por modelo, cada uno en su socket. Frames postcard con
prefijo de largo. 8 tests (wire + integración real sobre socket).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
dominium-canvas-gpui: Element que pinta un RenderPlan como quads,
centrado en sus bounds (rgba→hsla, único crate que toca gpui).
app dominium: compone core→physics→iso→render-plan→canvas en una
ventana GPUI con bucle de simulación de fondo (~11 tps), panel de
estadísticas, controles play/pausa + re-sembrar, y re-siembra
automática al colapso poblacional.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
build_plan(World, IsoProjector, ZWeights, PlanConfig) → RenderPlan:
un quad por celda (color = mezcla pesada de las 5 capas, relieve =
Z compuesto) + un quad-marca por Lemming posado sobre el terreno.
Quads ordenados por profundidad de pintor (depth = x+y) + caja
envolvente para centrado. Cero deps gráficas. 10 tests.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Proyección calculada en CPU antes de emitir quads 2D (GPUI no maneja
matrices 3D ni mallas).
- ZWeights — pesos del Z compuesto, uno por capa; z_of() calcula el
relieve como Σ wᵢ·capaᵢ (los 5 sliders del panel).
- IsoProjector — matriz iso fija: x=(x-y)·cos30, y=(x+y)·sin30 − Z·zf.
cos/sin de 30° vía libm → proyección bit-exacta cross-platform.
- project() + shadow() (Lambert plano: la sombra cae en z=0 desplazada
por la dirección de luz, larga en proporción a la altura).
6 tests verdes (origen, eje del rombo, Z eleva, Z compuesto lineal,
determinismo, sombra de punto en el suelo). cargo check verde.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
apps/shuma-shell deja de ser el dashboard legacy de la era shipote y
pasa a ser el shell de la spec: layout fijo de 3 zonas.
- status (arriba) — estado de sandokan + versión.
- [RUN] (izquierda) — barra de macros desde MacroBook (F1/F2/F3).
- Lienzo de Contexto (centro) — grafo de intenciones: cada %cN es una
caja posicionada por shuma-shell-render::layout, borde coloreado por
estado (ámbar Running / verde Ok / rojo Failed).
- [SENS] (derecha) — telemetría (CPU/MEM, placeholders).
- prompt fijo (abajo) — la línea de intención.
v1: renderiza la estructura con datos de ejemplo. Cableado interactivo
(typing, F-keys ejecutando vía sandokan, telemetría viva) es el paso
siguiente. cargo check --workspace verde.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Layout agnóstico del grafo de intenciones del shell:
- layout(SessionGraph) → CanvasPlan: cada comando %cN es un NodeBox
ubicado en una columna por su profundidad de dependencia
(longest-path); cada ref %pN/%cN que consume genera una Edge hacia
el comando que la produjo. Nodos colapsados se dibujan retraídos.
- paint(plan, canvas) → render directo contra pineal-render: aristas
al fondo, cajas con borde coloreado por estado (ámbar/verde/rojo).
4 tests verdes (columnas por dependencia, aristas de buffer, comandos
independientes en col 0, paint emite draw calls). cargo check verde.
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>
Desbloqueado por verbo. fana-semantic embebe los átomos y mide su
afinidad a un conjunto de conceptos.
- ConceptSet — embebe el texto de referencia de cada concepto como su
vector ancla (vía cualquier verbo Provider).
- SemanticScorer — embebe el contenido de un NarrativeAtom y llena
atom.semantic_vectors con la similitud coseno concepto→intensidad.
Limpia el scoring previo en cada pasada.
Agnóstico del backend (verbo_core::Provider). 3 tests verdes con
verbo-mock — incluye: texto idéntico al ancla puntúa coseno ≈ 1.
cargo check --workspace verde.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Backend sin modelo real: FNV-1a del texto siembra un LCG que genera el
vector. Mismo texto → mismo vector siempre; textos distintos → vectores
distintos. Dimensión configurable (default 384d, típica de modelos
ligeros).
Desbloquea desarrollar y testear los consumidores de verbo
(fana-semantic, badu, chasqui) sin descargar modelos ONNX ni pegarle a
Cohere. Los backends reales (cohere/bge/fastembed) son swaps de config.
4 tests verdes (determinismo, distinción, dimensión, batch).
cargo check --workspace verde.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Primer crate de verbo (provider de embeddings compartido; desbloquea
fana-semantic, badu y la búsqueda de chasqui).
- ModelId — identidad de modelo (nombre + dimensión). Vectores de
distinto ModelId no son comparables.
- EmbeddingVector — vector + su ModelId; new() valida la dimensión,
cosine() rechaza comparar modelos distintos (error tipado, no
sinsentido silencioso), norm() euclidiana.
- EmbedError — ModelMismatch / BadDimension / Backend.
- trait Provider — model_id + embed + embed_batch (default secuencial).
Lo cumplen los backends concretos (cohere / bge / fastembed).
5 tests verdes (cosine idéntico/ortogonal/cross-model/zero, validación
de dimensión). cargo check --workspace verde.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
shuma-intent: el corazón agnóstico del shell shuma.
- parse — Intention: una línea del prompt parseada en etapas separadas
por pipe. Ref (%cN comando / %pN buffer) + Stage (Exec | Inject).
Parsea el ejemplo de la spec: `ssh nodo 'cat data.json' | %p1 | sort`.
- graph — SessionGraph: el grafo de contexto de la sesión. record()
registra una intención (%cN), complete() le asigna buffer de salida
(%pN) + estado, resolve() resuelve referencias, dangling_refs()
valida una intención antes de ejecutar (la validación previa del
prompt), collapse_succeeded() retrae nodos OK (quietud visual).
Todo puro y serializable (sesiones exportables). El front-end GPUI
(zonas RUN/SENS + lienzo central) lo rehidrata; la ejecución la hace
sandokan. 8 tests verdes. cargo check --workspace verde.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- fana-core: NarrativeAtom + CoherenceState ahora Serialize/Deserialize
(serde con feature rc para el Arc<String>; uuid con feature serde).
- fana-graph: + atoms() iterator + from_atoms() constructor.
- fana-store: GraphStore sobre sled. put/get/remove_atom por Uuid,
serialización bincode. save_graph persiste átomo por átomo;
load_graph reconstruye el grafo (la adjacency se re-cablea desde las
dependencies de cada átomo).
7 tests verdes (roundtrip put/get/remove + save/load_graph preserva
estructura). cargo check --workspace verde.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Primer paso de fana (prioridad alta entre las apps Fase C).
- fana-core — NarrativeAtom: id + content_hash SHA-256 + content
Arc<String> (structural sharing: ramificar es O(1)) + semantic_vectors
+ dependencies + branch_id + CoherenceState (Valid/InConflict/
PendingEvaluation). Invariante hash↔content verificable; set_content
re-hashea y marca PendingEvaluation.
- fana-graph — NarrativeGraph: DAG de átomos + adjacency
dependencia→dependientes. propagate_mutation: BFS que marca
PendingEvaluation en cascada a todo descendiente (la "onda de choque
lógica" de la spec), agnóstico de UI — devuelve los ids afectados.
topological_order con detección de ciclo.
10 tests verdes. cargo check --workspace verde.
Pendiente fana: semantic (cliente verbo), store (sled), llm, render-plan,
editor-gpui.
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>
Envuelve russh 0.54 con una API mínima: una SshSession mantiene el
Handle maestro; cada exec() concurrente abre su propio canal en
paralelo sobre la misma conexión TCP (SSH multiplexa canales por
diseño del protocolo).
- SshConfig (host/port/user/auth/keepalive) + SshAuth (Password | Key).
- SshSession::connect — config russh + keepalive + auth password o
clave privada en disco; verificación de host key TOFU por default.
- SshSession::exec — corre un comando en un canal nuevo, junta
stdout/stderr/exit_code.
- SshSession es Clone barato (comparte el Handle).
Base de sandokan RemoteEngine y del Linker SSH de matilda.
Compila contra russh 0.54. El test de conexión real requiere un
servidor SSH (fuera del unit test).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- index — CardIndex: índice en memoria con filtros (by_label
case-insensitive substring, by_kind, providing por Capability, by_id).
- registry — scan_dir: carga toda Card *.json de un directorio,
saltando ruido y archivos rotos.
- discovery — CardDiscovery: une el índice local con la malla P2P;
announce_all publica las Cards locales al DHT, find_remote busca
proveedores. Modo local-only sin DHT también soportado.
Lo consumen el card-browser de nahual-shell y agorapura.
7 tests verdes. cargo check --workspace verde.
settings.local.json: defaultMode bypassPermissions (sesión desatendida).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
brahman-net corre un único Kademlia para todo el ecosistema.
brahman-dht le pone arriba un esquema de claves namespaced para que
distintos dominios coexistan sin colisión en la misma malla.
- key — RecordKind (Code/Card/Persona/Service/Custom) + DhtKey.
Wire: [kind_tag] ++ blake3(id) = 33 bytes longitud fija. Custom(n)
usa 0x80|n: nunca choca con los kinds estándar.
- Dht — wrapper sobre BrahmanNet: announce/withdraw/find (modelo de
provider records).
Consumidores: minga (Code), brahman-card-discovery (Card), agorapura
(Persona). 5 tests verdes (incl. smoke async sobre un nodo libp2p real).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
apps/sandokan (binario `sandokan`): CLI para probar el orquestador.
Subcomandos: daemon, run <exec> [args], list, status, telemetry, stop.
Fix: Intent serializaba Card directo, pero Card tiene un campo
`#[serde(flatten)] extensions` incompatible con postcard ("sequence
length must be known"). Intent::card ahora usa #[serde(with)] que
proyecta Card↔WireCard en el límite de serialización (las extensions
locales se descartan al cruzar el wire — comportamiento correcto).
Smoke test verificado end-to-end: daemon + run /bin/sleep + list +
status Running + telemetry + stop + status Killed.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>