La «piel» de una esfera celeste no son continentes —esos van en la
Tierra— sino las estrellas y la Vía Láctea. Y a diferencia del brillo
especular (fijo a la pantalla), esta piel gira CON la esfera, así que
delata la rotación de un vistazo.
- Campo de estrellas isótropo, decorativo (no un catálogo real),
generado con un hash determinista — no titila entre frames.
- Vía Láctea: una sobredensidad de estrellas tenues a lo largo del
plano galáctico, ubicado con el polo galáctico real (J2000, AR
192.859° / Dec +27.128°).
- Estrellas con brillo y tinte variables (azuladas / cálidas),
atenuadas por profundidad. Van detrás de la rejilla, delante del
sombreado — un fondo de planetario. Solo en tema oscuro.
36 tests verdes.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El kernel deja de colocar las ventanas a mano: las tesela. El motor es
mirada-layout — el mismo nucleo no_std que ordena el compositor Wayland
de brahman, enlazado por path cruzando la frontera de workspace. Es el
primer consumo REAL del nucleo compartido brahman <-> renaser.
- kernel/compositor.rs: enlaza mirada-layout y calcula un marco por app
con el algoritmo MasterStack, dentro del area de pantalla.
- consola::volcar_marco centra el fotograma natural de la app dentro de
su marco teselado (antes lo depositaba en region.x/y fijos).
- ContextoCapacidades lleva marco + natural_ancho/alto; sys_render_frame
valida el fotograma contra el tamaño natural.
- cargar_userspace tesela con el compositor y pinta el escenario antes
de encender las apps. Las apps NO cambian: el compositor reordena la
pantalla sin que ninguna toque una instruccion.
Verificado en QEMU (screendump): las cinco apps de genesis teseladas en
MasterStack — hola como ventana maestra, el resto apiladas a la derecha,
cada lienzo centrado en su panel.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sobre el batch 1 (eclíptica + ecuador + cuerpos):
- Horizonte local: círculo máximo perpendicular al cénit, derivado de
la latitud geográfica y el RAMC. El cénit (declinación φ, AR RAMC,
llevado al marco eclíptico) es el «punto del observador» — marcado
como tal, con su nadir y el meridiano local.
- Día/noche: los cuerpos bajo el horizonte se atenúan — de un vistazo
se ve qué planetas estaban sobre la tierra en el momento de la carta.
- Marcadores de polos: eclípticos (punto dorado) y celestes (anillo +
cruz, etiquetados PN/PS) — el ángulo entre ambos ejes ES la
oblicuidad, ahora visible.
- Relieve de la esfera: disco base + degradado radial + brillo
especular desplazado a la luz — volumen sin gradientes nativos.
- RenderModel gana `geo_latitude_deg` (#[serde(default)]); el bridge
lo puebla desde birth_data.
Verificación: 2 tests nuevos fijan la construcción del cénit — está a
la colatitud del polo celeste, y cénit/polo/MC son coplanares (el
plano del meridiano), lo que ancla el RAMC. 35 tests verdes.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Cada app tiene ahora su propia ranura de estado en el Manifiesto de
Génesis (EntradaApp.estado): guarda y recobra lo suyo, sobrevive al
reinicio, y no pisa a ninguna otra app.
- apps/memoriosa: app WASM interactiva nueva. Cuenta las teclas pulsadas
y persiste el recuento; al reiniciar despierta con su cuenta intacta.
Reemplaza la 2a instancia de hola en la genesis.
- kernel: capacidades sys_estado_cargar / sys_estado_guardar. El kernel
custodia un manifiesto VIVO (Mutex<Manifiesto>); fijar_estado lo muta,
lo re-graba en el grafo y lo re-ancla. ContextoCapacidades.indice_app
da a cada app su identidad — su ranura, jamas la de otra.
- cargar_userspace instala el manifiesto vivo antes de instanciar las
apps: el init de una app ya consulta su estado al despertar.
Verificado en QEMU (screendump + sendkey): disco virgen -> memoriosa con
0 celdas, testigo verde; 5 pulsaciones -> 5 celdas; reinicio -> 5 celdas
intactas, testigo ambar (init releyo el estado del grafo).
Cierra la Fase 7 — el userspace nace del grafo, completa.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
GPUI no es 3D y empotrar wgpu sería frágil; la esfera celeste es de
alambre —círculos máximos y puntos— y eso se proyecta a software con
trigonometría pura. Cada superficie ya sabe dibujar DrawCommand, así
que el módulo nuevo solo decide dónde cae cada trazo: una esfera real,
rotable, sin una línea de GPU.
- cosmobiologia-render/sphere3d.rs: marco eclíptico (z=0), proyección
ortográfica con yaw/pitch, eclíptica + ecuador celeste inclinado por
la oblicuidad (se cruzan en los equinoccios, como en el cielo),
rejilla de meridianos/paralelos, signos, ángulos y cuerpos natales.
Algoritmo del pintor + atenuación del hemisferio lejano. 5 tests.
- compose_sphere emite Vec<DrawCommand> — lo consumen igual el canvas
gpui y el SVG del cliente web.
- cosmobiologia-canvas: modo esfera 3D en el lienzo (tecla V o el botón
flotante «Esfera 3D»), drag para orbitar, traductor DrawCommand→GPUI.
Falta (2da capa): el horizonte local + día/noche — necesita la latitud
geográfica, que aún no viaja en el RenderModel.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El kernel deja de empotrar el userspace por completo. Ya no carga ni un
solo .wasm: es boot quien siembra el disco con el grafo poblado.
- kernel/almacen.rs y manifiesto.rs migran al nucleo compartido `formato`
(tipos, postcard, BLAKE3, trazado de registros). El kernel pierde los
include_bytes!, genesis() y sembrar_genesis().
- boot::sembrar_grafo siembra un disco virgen con el bytecode de las apps
(deduplicado) y el Manifiesto de Genesis anclado en el superbloque.
- cargar_userspace sin rama de siembra; wasm/mod.rs sin TECHO_MEMORIA.
- alias `cargo kernel` -> --manifest-path (esquiva un ICE de cargo con
formato compartido entre el kernel y boot via artifact-dep).
Verificado en QEMU (screendump): disco virgen -> boot siembra 5 objetos,
el kernel monta su grafo; segundo arranque -> boot respeta el disco, la
cronista persiste. formato: 5/5 pruebas.
Nota: el crate `formato` y los 3 Cargo.toml entraron antes en 43e6b32 por
un `git add -A` de un trabajo concurrente; este commit cierra el resto.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El corpus ya rebana la carta en tajadas vivenciales: una sola
configuración mirada plano a plano, sin promediar la contradicción.
- Colocacion / AspectoEnCarta: la posición real de un planeta en una
carta — el puente entre el motor astronómico y las claves del JOIN.
- combinaciones_de_carta: deriva todas las CombinacionId de una carta.
- rebanar_por_dominio: la tomografía — cada planeta@cN cae en el
dominio de su casa, cada planeta·signo hereda el de su casa, y un
aspecto puentea apareciendo en las dos tajadas que conecta.
- Corpus::interpretar_por_dominio: el JOIN agrupado por dominio,
entrada directa del gráfico «por tajadas».
- CombinacionId acepta el alias ASCII '/' del punto medio '·'.
- ejemplo.ron: plantilla cargable y comentada del corpus.
- GUIA.md: los pasos exactos para generar el corpus a mano.
12 tests verdes.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El corpus es la biblioteca de interpretación indexada: fragmentos de
texto de los libros (y del astrólogo) etiquetados por la combinación
astrológica que describen. NO calcula nada — las reglas las computa el
motor; el corpus sólo guarda evidencia citable y la sirve por JOIN.
Esquema TIPADO (la astrología tiene gramática — planeta=función,
signo=estilo, casa=dominio, aspecto=relación; no son vectores
intercambiables de un espacio plano):
- CombinacionId — la «etiqueta de código de barras», con variantes por
tipo de combinación; el aspecto normaliza el orden de sus extremos.
- Arquetipo / TipoArquetipo — los bloques con su PerfilSemantico
(dimensiones con nombre que define el astrólogo, no el código).
- Pasaje — texto citado + fuente + combinación.
- Dominio — el plano vivencial (Vital/Social/Psíquico) por casa.
- Corpus::interpretar — el JOIN: combinaciones de la carta → pasajes.
Cobertura total; la SÍNTESIS es de una capa superior.
6 tests verdes. La capa de composición (deducir combinaciones no
leídas) queda explícitamente sin construir — es un problema de diseño
abierto, no un producto Hadamard ingenuo.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Captura headless por el monitor de QEMU (screendump) de los dos caminos
del Manifiesto de Génesis:
- Disco virgen: sembrar_genesis() puebla el grafo y ancla el manifiesto;
consola imprime «genesis sembrada» + «5 apps nacidas del grafo».
- Disco ya sembrado: cargar() lee el manifiesto del ancla del superbloque
sin resembrar; «grafo montado :: 6 objetos :: raíz presente», la
cronista pinta su segunda celda (la cuenta de arranques perdura).
Pantalla idéntica a la Fase 6.2 en ambos casos. CHANGELOG: la sección
«Pendiente de verificación» de la 7a pasa a «Verificado».
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El rectificador deja la aproximación y pasa a la trigonometría exacta,
con precisión de segundo — el "microajuste argentino".
LA MATEMÁTICA. El rectificador ya NO usa el modelo simplificado
(directed_longitude, rotación uniforme de RA + convergencia GR). Ahora
usa `eternal_astrology::primary_direction::all_directions` — el método
Placidus-mundano: semi-arcos diurnos/nocturnos bajo el polo de cada
cuerpo, la trigonometría esférica de la escuela ascensional. No se
reimplementó nada: la matemática, ya probada, vive en eternal; el
engine sólo aporta la capa de optimización.
- error_de_carta: por cada evento, la distancia en años a la dirección
primaria que perfecciona más cerca; el error total es la suma. Es la
función de coste del microajuste — el valle es la hora real.
PRECISIÓN DE SEGUNDO. compute_natal_chart / build_eternal_inputs /
natal_cache pasan a trabajar en SEGUNDOS (compose convierte ×60). El
rectificador barre en dos pasadas: gruesa minuto a minuto sobre la
ventana (el perfil que dibuja la curva), fina segundo a segundo en
±60 s alrededor del mejor minuto.
- Rectificacion: mejor_offset_segundos; el perfil va en segundos.
- UI: panel y curva muestran «±Xm Ys · error N.NNa». Las barras siguen
siendo clicables (scrub a esa hora candidata).
Tests verdes (engine 12, render 28). Limitación conocida: all_directions
es sólo directo — converso necesita crecer en eternal (upstream).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Cada barra de la curva del barrido se vuelve clicable: un clic lleva
la carta a esa hora candidata, reusando el scrub de tiempo del
jog-dial (CanvasEvent::TimeOffsetChanged, ya cableado en el shell).
Cierra el lazo del rectificador: ahora se puede inspeccionar sobre el
wheel cualquier hora del barrido, no sólo leer la ganadora.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Tercer y último incremento: la visualización. El rectificador ya
muestra POR QUÉ una hora gana, no sólo cuál.
- cosmobiologia-canvas: CanvasState gana `rectificacion` +
`set_rectificacion`. render_rectify_profile dibuja el barrido como
un histograma en el footer — cada barra es una hora candidata, su
altura crece cuanto menor el puntaje; la barra más alta (el valle
del puntaje) es la hora rectificada, resaltada. Etiqueta los hitos
(mejor, 0, extremos).
- shell: run_rectificacion publica el Rectificacion al canvas además
del resumen textual al panel.
Con esto el rectificador automático (#67) queda completo: motor de
escaneo GR + UI de entrada + visualización del perfil.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Segundo incremento: el rectificador ya es usable de punta a punta
desde el panel, sin infraestructura de UI nueva.
- cosmobiologia-panel: Control::TextInput pasa a renderizarse desde
string_state — deja de ser un display estático y se vuelve un campo
de sólo-lectura que el shell escribe vía set_string (resultados,
etiquetas).
- cosmobiologia-modules: el módulo primary_directions gana 3 sliders
«Evento N · edad» (0 = ranura sin usar), un Action «Rectificar
hora» y un TextInput «Resultado».
- shell: run_rectificacion lee las edades de los sliders, llama a
engine::rectificar (ventana ±15 min, paso 1) y escribe la hora
rectificada + el puntaje en el campo Resultado del panel.
El rectificador queda funcional: activar GR → fijar edades de eventos
→ «Rectificar hora» → leer el resultado. Falta sólo la curva del
perfil del barrido como visualización (incremento opcional).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Primer incremento del rectificador automático (#67): dado un conjunto
de eventos conocidos de la vida del sujeto, barre las horas de
nacimiento candidatas y devuelve la que mejor los explica vía el
Sistema GR. La killer feature pro — desbloqueada al completar el GR.
- cosmobiologia-render: `convergencia_minima` — medida CONTINUA de qué
tan bien una carta explica un evento (suma de orbes del directo +
converso más cerrados sobre un punto natal). 3 tests.
- cosmobiologia-engine: módulo `rectify` — `rectificar` barre la
ventana de horas candidatas; por candidata computa la carta (una
vez, cacheada) y mide la convergencia GR a la edad de cada evento;
elige el puntaje mínimo. Devuelve el perfil completo del barrido
para que la UI lo dibuje como curva. Test end-to-end con eternal.
- bridge: `compute_natal_chart`/`body_symbol`/consts GR → pub(crate).
Falta: la UI (capturar eventos conocidos, lanzar el barrido, mostrar
la curva y la hora rectificada).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El kernel deja de empotrar las apps. Las cinco aplicaciones ya no
llegan por include_bytes! en main.rs: nacen del grafo, gobernadas por
un Manifiesto de Génesis que también vive en el grafo.
- almacen: el SuperBloque gana el ancla `manifiesto: Option<Hash>`
(gemela de `raiz`, del lado del kernel) + accesores. VERSION 1→2 —
un disco v1 se reformatea.
- manifiesto.rs: implementados `cargar` (lee el manifiesto del grafo)
y `sembrar_genesis` (puebla un disco virgen con las 5 apps de
génesis). El bytecode viaja empotrado AÚN, sólo como semilla
transitoria (la Fase 7b lo mueve al constructor de imagen `boot`).
- kernel_main: `cargar_userspace` reemplaza las 5 `encender_app`
escritas a mano; `encender_app` recupera el bytecode del grafo —
`recuperar` verifica el hash, un módulo corrupto se niega y el
arranque sigue.
- wasm: el techo de memoria pasa a ser por-app (del manifiesto).
Compila limpio. Verificación en QEMU pendiente (la corre el operador):
la pantalla debe verse idéntica a la Fase 6.2 + la línea «manifiesto».
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Abre la Fase 7 («apps que nacen del grafo»): destierra el include_bytes!
del userspace — las apps pasan a ser objetos del grafo, gobernadas por
un Manifiesto de Génesis que también vive en el grafo.
Este commit es sólo plan + andamiaje; el kernel se comporta idéntico a
la Fase 6.2.
- FASE7.md — el plan de ataque: el problema de la génesis, las
sub-fases 7a/7b/7c y los guardarraíles.
- kernel/src/manifiesto.rs — andamiaje: tipos Manifiesto/EntradaApp +
(de)serialización postcard completos; cargar/sembrar_genesis son
esbozos hasta la 7a. Declarado en main.rs, aún sin cablear a
kernel_main (#![allow(dead_code)] temporal).
CHANGELOG y DIARIO al día.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
brahman y renaser ya corren la misma versión de wasmi (1.0): el ABI
WASM del host es idéntico en Linux y en bare-metal. Desbloquea el
Paso 3 de la integración (converger el ABI Card/WASM).
El delta de la API resultó pequeño:
- `Linker::instantiate` + `InstancePre::start` → `instantiate_and_start`
(wasmi 1.0 fusiona instanciación y arranque).
- Motor configurado en `CompilationMode::Eager` — traducción completa
del módulo por adelantado, comportamiento predecible, paridad con el
motor wasmi del kernel de renaser.
Primer test de arje-wasm: `demo_corre_en_wasmi_1` ejecuta el módulo
demo de punta a punta (WAT→wasm, instanciación, host imports
log/exit). arje-zero (PID 1, consumidor) compila sin cambios.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Endurece y documenta la integración renaser↔brahman tras el piloto
mirada-layout.
- scripts/check-shared-cores.sh: compila cada núcleo compartido
registrado para x86_64-unknown-none. Si un núcleo recobra `std` en
silencio (dep descuidada), falla aquí y no semanas después en
renaser. Hoy cubre mirada-layout.
- docs/renaser-integracion.md: por qué renaser es un workspace aparte,
el modelo núcleos-duales/superficies-por-plataforma, cómo se hace
no_std un núcleo, y el estado del plan por etapas.
Paso 2 (converger el CAS) DESCARTADO tras leer el código: arje-cas
(blobs SHA256 sobre FS), renaser/almacen (DAG blake3+postcard sobre
virtio-blk) y minga-core (Merkle-AST con hash estructural) son tres
capas distintas, no una duplicación — converger impondría una
abstracción equivocada. Razonado en el doc.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
renaser —kernel asíncrono de espacio de direcciones único, no-POSIX,
`no_std` x86_64— entra al monorepo como su PROPIO workspace de Cargo,
no fusionado: usa toolchain nightly, target `x86_64-unknown-none` y
`panic = "abort"`, incompatibles con los perfiles globales de brahman.
- `renaser/` — copia del proyecto (sin su `.git`; el repo original
conserva su historia standalone). Workspace propio con su
`rust-toolchain.toml` y `.cargo/`.
- `exclude = ["renaser"]` en el workspace de brahman: Cargo lo trata
como ajeno.
- El kernel de renaser path-depende `mirada-layout` cruzando la
frontera de workspace — primer núcleo compartido. Semilla de la
Fase 8 (compositor): geometría de teselado compartida, framebuffer
nativo de renaser; smithay se queda en el lado Linux.
Verificado: `cargo build -p boot` compila kernel + imagen UEFI con
mirada-layout enlazado para bare-metal.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
mirada-layout (el motor de teselado del compositor) pasa a `no_std +
alloc` para poder compilarse también en bare-metal — es el primer
crate-núcleo que brahman y renaser compartirán.
- `#![cfg_attr(not(test), no_std)]` + `extern crate alloc`: usa
`alloc::{vec, collections::BTreeMap}` en vez de `std`.
- Matemática de punto flotante vía `libm` (`sqrt`/`ceil`/`round` viven
en `std`, no en `core`).
- `serde` pasa a feature opcional: los consumidores Linux
(mirada-protocol/brain) la activan; un consumidor bare-metal no
necesita (de)serializar el layout.
- Deps declaradas directas (no `workspace = true`): un núcleo que
cruzará fronteras de workspace se mantiene autocontenido.
Verificado: `cargo build --target x86_64-unknown-none` compila;
32 tests verdes; mirada-protocol/brain sin regresión.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El módulo Uranian sólo listaba las fórmulas como texto; ahora también
las muestra geométricamente.
- cosmobiologia-canvas: render_uranian_dial pinta un eje horizontal
0-90° con cada cuerpo natal proyectado en su longitud mod 90. Ticks
en las divisiones duras (0/22½/45/67½/90°); los cuerpos que forman
una fórmula uraniana van resaltados, y los clusters densos se
escalonan en filas para legibilidad. La sección del footer combina
el dial geométrico con la lista de pills de fórmulas.
- El dial aparece siempre que el módulo Uranian está activo (antes la
sección sólo salía si había grupos detectados).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Completa la feature de armónicos: además de la carta armónica, ahora
hay un espectro que guía qué armónico mirar.
- cosmobiologia-render: harmonic_spectrum computa la fuerza de cada
armónica 1-32 (suma de cercanía a conjunción exacta de los pares de
cuerpos en esa armónica). apply_harmonic lo puebla + expone el
armónico activo. Campos RenderModel.harmonic / .harmonic_spectrum.
2 tests nuevos (el pico cae en la armónica resonante).
- cosmobiologia-canvas: render_harmonic_spectrum pinta el histograma
en el footer; cada barra es clicable y emite HarmonicSelected — un
clic salta a esa armónica. La barra activa va resaltada.
- shell: select_harmonic fija el slider del módulo natal y recompone.
- modules: el slider de armónico pasa de 1-20 a 1-32 (rango del
espectro).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El slider "Armónico" del NatalModule existía pero no hacía nada.
Ahora re-renderiza la carta en el armónico de orden N.
- cosmobiologia-render: módulo `harmonic` agnóstico — apply_harmonic
transforma los cuerpos natales a (longitud·N) mod 360 y recomputa
los aspectos sobre las posiciones armónicas (conjunción, oposición,
trígono, cuadratura, sextil). Las casas se conservan como marco.
6 tests (incluye: quintil natal → conjunción en H5).
- cosmobiologia-engine: NatalOptions.harmonic; compose lo aplica tras
la pasada natal, antes de los overlays. Test end-to-end.
- shell: build_natal_options lee el slider del módulo natal.
El título anota "· HN". Falta: histograma de fuerza por armónico.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Tercer y último incremento del Sistema GR: en modo GR (direcciones
primarias activas) el jog-dial deja de rotar el wheel y pasa a
scrubear la edad en vivo.
- canvas: CanvasState::gr_active() detecta el modo; on_jog_move emite
CanvasEvent::GrAgeDelta (años por grado de jog, sensibilidad 0.1)
en vez de rotar; on_jog_up no aplica snap de tiempo.
- shell: scrub_gr_age acumula el delta sobre target_age_years del
módulo primary_directions, clampa a [0,120], sincroniza el slider
del panel y recompone — los glifos dirigidos y el HUD se mueven en
vivo bajo el cursor.
Con esto el Sistema GR queda completo: cómputo de triggers, resaltado
de convergencias, HUD de rectificación y scrubbing live.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Segundo incremento del Sistema GR: el canvas ahora hace visible la
rectificación.
- Resaltado de convergencias: por cada punto natal donde un directo y
un converso coinciden dentro del micro-orbe, un eje brillante cruza
la zona del dual-ring hasta el cinturón natal, con marcador glow.
- HUD lateral: columna a la derecha del wheel cuando GR está activo,
con los triggers ordenados por orbe. Color rojo→gris según orbe; las
convergencias llevan ✦ y fondo resaltado.
paint_wheel recibe los gr_triggers; render_wheel monta el body como
fila wheel+HUD sólo en modo GR.
Falta: scrubbing live del jog-dial mapeado a la edad.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Primer incremento del Sistema GR (García Rosas): la engine, además del
dual-ring directo/converso, ahora computa los triggers de rectificación
y detecta las convergencias directo+converso sobre un mismo punto natal.
- cosmobiologia-render: módulo `gr` agnóstico — tipos GrTrigger/GrDirection
+ compute_gr_triggers (emparejamiento puro, 7 tests). Campo gr_triggers
en RenderModel (serde-default, back-compat).
- cosmobiologia-engine: build_primary_directions_overlay computa los
triggers contra cuerpos natales + 4 ángulos; orbe HUD 2°, micro-orbe
de evento 5'. Test end-to-end con eternal.
Falta: resaltado del evento en el canvas, HUD lateral, scrubbing live.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
minga-vfs deja de ser un stub: monta el repositorio direccionado por
contenido como un filesystem FUSE de sólo lectura. roots/<hash> da el
código fuente reconstruido (formato normalizado) de cada raíz del MST;
cas/<hash> resuelve cualquier hash bajo demanda como S-expression.
Capas separadas: render (SemanticNode→texto, puro) + source (contrato
NodeSource, backends sled/memoria) + fs (único módulo con fuser).
Nuevo subcomando `minga mount <punto>`. Dep fuser 0.15 sin libfuse-dev
(default-features = false). 14 tests nuevos, sin regresión en minga-cli.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Nuevo crate `crates/init/arje-absorb`: lee la configuración de un init
clásico y la traduce a una Tarjeta Semilla (Card JSON) con cada
servicio como hija genesis de arje-zero. El paso «absorber» de la
migración a arje — para no perder los servicios al cambiar de init.
- Absorbers: sysvinit (/etc/inittab), runit (runsvdir o /etc/sv),
dinit (/etc/dinit.d), openrc (/etc/runlevels). Autodetección.
- Modelo intermedio ForeignService → Card vía brahman-card (validado).
- `--with-carmen`: agrega carmen-dm (gestor de login gráfico).
- CLI: --from/--root/--output/--label/--with-carmen. 24 tests, clippy
limpio.
`scripts/migrate-to-arje.sh`: orquesta absorber → validar → (carmen:
compila+instala mirada dinámico) → install-arje-as-init.sh. El init
viejo queda intacto; arje se elige en GRUB. --dry-run no toca nada.
systemd no se absorbe (units no son texto trivial) — para systemd
sigue la capa de shims + seeds/arje-host.card.json.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El rename ente→arje dejó referencias stale al binario PID 1 y a los
shims. Los nombres reales (verificados con cargo metadata) son todos
arje-*: arje-zero, los 14 arje-*-compat, arje-echo, arje-policy-provider,
arje-bus, arje-brain.
- build-arje-initrd.sh, install-arje-as-init.sh, uninstall-arje.sh,
run-arje-qemu.sh: `-p ente-*` → `-p arje-*`, paths /sbin/arje-zero y
/usr/sbin/arje-*, RUST_LOG arje_zero=info.
- seeds/arje-prod y arje-host: los exec `/usr/sbin/ente-*-compat`
apuntaban a binarios que no existirían tras instalar — corregidos a
`/usr/sbin/arje-*`. (validate.sh no chequea exec, por eso «validaban»
igual; al boot real habrían fallado.)
Intactos a propósito: `/ente/` (directorio canónico de la Semilla) y
`ente.slice/*` (jerarquía cgroup). Las 3 seeds validan.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Pieza 2 del DM: declara `mirada-compositor --greeter` como hijo genesis
de arje-zero en `seeds/arje-host.card.json`, reemplazando el agetty de
tty1. Con `supervision: Restart { 2000, 60000 }`, arje-zero lo
respawnea si panica — la resiliencia «PID 2 supervisado» (sshd queda
como rescate remoto). Va en arje-host (boot de hardware real con rootfs
y mesa), NO en arje-prod (seed del initrd, sin GPU).
Además: `seeds/validate.sh` tenía referencias `ente-zero` stale del
rename ente→arje — corregidas a `arje-zero` (paquete + binario). Las
tres seeds validan. Tabla de seeds actualizada en docs/arje-boot.md.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`mirada-compositor --greeter` arranca como gestor de login: lanza
mirada-greeter como proceso hijo, lee su stdout y, al recibir el
SessionTicket, muta de BodyMode::Greeter a BodyMode::Session sin
reiniciar el servidor Wayland — la «mutación atómica» del DM.
- BodyMode { Greeter, Session }: eje ortogonal a Brain (Embedded/Linked).
- modo greeter: sin atajos registrados, rechaza Spawn, sin autoarranque.
- traspaso (complete_greeter_handoff): registra los atajos y arranca la
sesión — el comando del tiquet, o el autoarranque del usuario.
- privilegios: el compositor corre como root; spawn_command baja a
setuid/setgid + grupos suplementarios del usuario autenticado.
- bandera ortogonal al backend (--greeter [--drm|--winit]); el tiquet
llega por un canal calloop en DRM y por mpsc en winit.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El formateo de informes de COBOL: supresión de ceros a la izquierda,
coma de millares e inserción del punto decimal. Rebanada vertical.
- charka-lexer: el punto separador exige un espacio detrás; un punto
pegado a un carácter (ZZ9.99) ya no es terminador, sino símbolo —
el parser lo reensambla dentro de la cláusula PICTURE.
- charka-runtime: format_edited(valor, pic) — 9, Z, coma, punto, B.
- charka-ir: Field::edit guarda la PICTURE; el campo es texto.
- charka-codegen / charka-shadow: MOVE a un campo de edición pasa por
format_edited antes de almacenar.
- Corpus: 19-reporte. Sombra y crate compilado dan la misma salida.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El gran hueco que faltaba para el COBOL real: el procesamiento de
ficheros secuenciales. Una rebanada vertical por los seis crates.
- charka-parser: la ENVIRONMENT division ya no se ignora — se parsea
FILE-CONTROL (SELECT name ASSIGN TO "ruta"); del FILE SECTION se
asocia cada FD con su registro 01. Program::files.
- charka-runtime: tipo CobFile — un fichero «line sequential» (cada
registro una línea). Lectura: carga a memoria. Escritura: acumula y
vuelca al cerrar.
- charka-ir: Ir::files y los statements Open/Close/Read/Write. READ
lleva sus bloques AT END / NOT AT END.
- charka-codegen: un campo CobFile por fichero en el struct Program;
los verbos emiten llamadas al runtime.
- charka-shadow: el intérprete hace E/S de ficheros real.
- Corpus: programa nuevo 18-fichero — escribe tres líneas, las relee
con READ ... AT END y las muestra. Verificado: el intérprete sombra
y el crate compilado por scaffold dan la misma salida.
Alcance v1: organización line sequential; sin ficheros indexados ni
relativos, sin FILE STATUS.
Tests: charka-parser 17, charka-runtime 19, charka-ir 30,
charka-codegen 25, charka-shadow 23. fmt + clippy limpios.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
PERFORM A THRU C ejecuta A, B y C; antes el transpilador sólo
ejecutaba A (lo marcaba como aproximado).
- charka-codegen: Symbols registra ahora los párrafos en orden con su
nombre de método; Symbols::build toma el Ir completo.
paragraph_range(name, thru) da los métodos del rango; emit_perform
emite la llamada a cada uno.
- charka-shadow: run_paragraph_range ejecuta los párrafos de name a
thru inclusive.
- Corpus: programa nuevo 17-rangopar (PERFORM PASO-A THRU PASO-C sobre
tres párrafos). Verificado: el intérprete sombra y el crate
compilado por scaffold dan la misma salida.
Tests: charka-codegen 24, charka-shadow 22. fmt + clippy limpios.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
La cara de escritura de los nombres de condición de COBOL: si
IF ES-VALIDO los lee, SET ES-VALIDO TO TRUE los escribe.
- IR: Stmt::SetTrue { conditions }.
- Parser: SET cond-1 cond-2 ... TO TRUE. Otras formas de SET
(índices, TO FALSE) caen a Stmt::Unknown.
- Codegen y shadow: SET cond TO TRUE asigna a su dato padre el valor
del 88 (un MOVE del valor a la variable).
- Corpus: programa nuevo 16-bandera (cambia banderas de texto y de
número con SET). Verificado: el intérprete sombra y el crate
compilado por scaffold dan la misma salida.
Tests: charka-ir 29, charka-codegen 23, charka-shadow 21. fmt +
clippy limpios.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El verbo de COBOL para volver un dato (o un registro entero) a su
valor por defecto.
- IR: Stmt::Initialize { targets }. El model de charka-ir registra
ahora los grupos y sus datos elementales (DataModel::groups,
GroupInfo { name, members }).
- Parser: INITIALIZE name-1 name-2 ...
- Codegen y shadow: cada destino, si es un grupo, se expande a sus
miembros; cada dato elemental se pone a 0 (numérico) o a espacios
(alfanumérico); una tabla OCCURS resetea todos sus elementos.
- Corpus: programa nuevo 15-resetear (resetea un grupo y un escalar).
Verificado: el intérprete sombra y el crate compilado por scaffold
dan la misma salida.
Tests: charka-ir 28, charka-codegen 22, charka-shadow 20. fmt +
clippy limpios.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Completa el EVALUATE con sus dos formas que faltaban.
- IR: la rama WhenBranch pasa de values: Vec<Operand> a
tests: Vec<WhenTest>, donde WhenTest es Value (igualdad), Range
(WHEN lo THRU hi) o Cond (EVALUATE TRUE WHEN cond).
- Parser: detecta EVALUATE TRUE y entonces cada WHEN parsea una
condición; en modo valor reconoce WHEN lo THRU hi.
- Codegen y shadow: una prueba Range se traduce a lo <= s <= hi; una
Cond, a la condición directa.
- Corpus: programa nuevo 14-clasifica (clasifica notas con rangos THRU
y un EVALUATE TRUE). Verificado: intérprete sombra y crate compilado
dan la misma salida.
Tests: charka-ir 27, charka-codegen 21, charka-shadow 19. fmt +
clippy limpios.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El verbo de COBOL para analizar y limpiar campos de texto.
- IR: Stmt::Inspect { target, op } con InspectOp::TallyingForAll
(cuenta apariciones y las suma a un contador) y
InspectOp::ReplacingAll (reemplaza apariciones).
- Parser: INSPECT t TALLYING n FOR ALL lit y
INSPECT t REPLACING ALL a BY b. Una forma no soportada cae a
Stmt::Unknown.
- Codegen: TALLYING -> str::matches(..).count(); REPLACING ->
str::replace.
- Shadow: el intérprete cuenta / reemplaza el texto.
- Corpus: programa nuevo 13-inspeccion. Verificado: el intérprete
sombra y el crate compilado por scaffold dan la misma salida.
Alcance v1: TALLYING FOR ALL y REPLACING ALL; sin LEADING, FIRST,
CHARACTERS, BEFORE/AFTER.
Tests: charka-ir 26, charka-codegen 20, charka-shadow 18. fmt +
clippy limpios.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Dos verbos comunes de COBOL para construir y partir cadenas.
- IR: Stmt::StringConcat { sources, into } y
Stmt::Unstring { source, delimiter, into }.
- Parser: STRING a b DELIMITED BY SIZE INTO t END-STRING y
UNSTRING s DELIMITED BY d INTO a b c END-UNSTRING.
- Codegen: STRING -> format! concatenado; UNSTRING -> un bloque que
parte con str::split y reparte los trozos a los destinos.
- Shadow: el intérprete concatena / parte el texto y lo reparte.
- Corpus: programa nuevo 12-cadenas. Verificado: el intérprete sombra
y el crate compilado por scaffold dan la misma salida.
Alcance v1: STRING con DELIMITED BY SIZE (otros delimitadores se
ignoran); sin WITH POINTER ni ON OVERFLOW.
Tests: charka-ir 25, charka-codegen 19, charka-shadow 17. fmt +
clippy limpios.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Los arrays de COBOL, que antes el transpilador descartaba en silencio.
Una rebanada vertical amplia que atraviesa el pipeline entero.
- Parser: la cláusula OCCURS n [TIMES] se captura en DataItem.
- IR: Operand::Indexed { name, index } — una referencia ELEM(I), con
subíndice 1-based. Los destinos de los statements pasan de
Vec<String> a Vec<Operand>, así que se puede escribir a un elemento
de tabla (MOVE x TO ELEM(I), COMPUTE ELEM(I) = ...). model::Field
gana occurs: Option<u32>.
- Codegen: un campo OCCURS se emite como Vec<Num>/Vec<Text>,
inicializado con vec![..; n]; una referencia con subíndice indexa el
vector (1-based -> 0-based).
- Shadow: en el intérprete todo campo es un vector — un escalar es de
longitud 1, una tabla de n; las referencias se resuelven a
(nombre, índice).
- Corpus: programa nuevo 11-tabla (llena una tabla con cuadrados y los
suma). Verificado: el intérprete sombra y el crate compilado por
scaffold dan ambos SUMA DE CUADRADOS = 000055.
Alcance v1: OCCURS elemental, una dimensión, subíndice de un operando.
Fuera: OCCURS de grupo, multidimensional, DEPENDING ON.
Tests: charka-parser 16, charka-ir 24, charka-codegen 18,
charka-shadow 16. fmt + clippy limpios.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Los nombres de condición de COBOL (IF ES-VALIDO), que antes el
transpilador evaluaba siempre como false. Y, de paso, se elimina la
duplicación de la resolución del modelo de datos.
- charka-ir gana un módulo `model`: resolve_data(&[DataItem]) ->
DataModel aplana el árbol de datos a campos elementales (Field con
FieldKind) y a nombres de condición (ConditionName). El Ir lleva
ahora un campo `model` — la fuente única de verdad sobre la
clasificación de PICTURE.
- charka-codegen y charka-shadow consumen ir.model en vez de
reimplementar cada uno la clasificación, el ancho de PICTURE y la
normalización de VALUE. charka-codegen ya no depende de charka-bcd.
- Cond::Named (un nivel 88) se resuelve a `padre = valor`: el codegen
emite la comparación, el intérprete sombra la evalúa.
- Corregido: un dato con hijos de nivel 88 antes se perdía como si
fuera un grupo; ahora se reconoce como campo elemental.
- Corpus: programa nuevo 10-condicion (semáforo con 88 de texto y de
número). Verificado: intérprete y crate compilado dan igual salida.
Tests: charka-ir 23, charka-codegen 17, charka-shadow 15. fmt +
clippy limpios.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
EVALUATE atraviesa el pipeline entero — antes el parser lo guardaba
crudo como Stmt::Unknown.
- IR: Stmt::Evaluate { subject, whens, other } con
WhenBranch { values, body }. Varios WHEN apilados comparten cuerpo;
WHEN OTHER es el caso por defecto.
- Parser: EVALUATE subject WHEN v1 WHEN v2 ... [WHEN OTHER ...]
END-EVALUATE.
- Codegen: lo baja a una cadena if / else if / else — una rama se
elige si el sujeto es igual a alguno de sus valores, sin caída.
- Shadow: el intérprete evalúa el sujeto y ejecuta la primera rama
cuyos valores casen, o el WHEN OTHER.
- Corpus: programa nuevo 09-evaluar (EVALUATE por valor anidado en un
PERFORM VARYING, con WHEN apilados y WHEN OTHER). Verificado: el
intérprete sombra y el crate compilado por scaffold dan la misma
salida.
Alcance v1: EVALUATE por igualdad de valor; no la forma EVALUATE TRUE
con condiciones ni los rangos THRU.
Tests: charka-ir 19, charka-codegen 16, charka-shadow 14. fmt +
clippy limpios.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El bucle más usado de COBOL, que antes el parser degradaba a un
PERFORM vacío (un hueco de corrección real). Ahora atraviesa el
pipeline entero como una rebanada vertical.
- IR: PerformControl::Varying { var, from, by, until }.
- Parser: reconoce PERFORM VARYING var FROM x BY y UNTIL cond en
línea (END-PERFORM) y fuera de línea (PERFORM párrafo VARYING ...).
- Codegen: emite var = from; while !(until) { cuerpo; var += by; }.
- Shadow: el intérprete inicializa la variable, evalúa la condición
antes de cada vuelta e incrementa al final.
- Corpus: programa nuevo 08-varying (suma 1..10). Verificado: el
intérprete sombra y el crate compilado por scaffold dan ambos
SUMA 1 A 10 = 00055 — las dos rutas concuerdan.
Tests: charka-ir 18, charka-codegen 15, charka-shadow 13. fmt +
clippy limpios.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
App nueva crates/apps/charka — el binario `charka`, que vuelve usable
el pipeline COBOL->Rust desde la terminal.
- transpile <in.cob> [-o out.rs] — emite el código Rust.
- scaffold <in.cob> -o <dir> — genera un crate Rust completo
(Cargo.toml + src/main.rs) que depende de charka-runtime y compila.
- run <in.cob> — ejecuta el programa con el intérprete sombra, sin
compilar nada, y muestra su salida.
- check <in.cob> -e <esperado> — ejecuta y diferencia contra una
salida esperada; reporta las líneas que difieren.
Avisa de los verbos COBOL que aún no se transpilan. Verificado de
punta a punta contra el corpus: scaffold de 06-nomina genera un crate
que compila y produce la misma salida que el intérprete sombra — las
dos rutas de ejecución concuerdan.
4 tests; fmt + clippy limpios.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El pipeline COBOL->Rust queda completo (7 crates) y validado de punta
a punta.
charka-shadow certifica que el transpilador preserva la semántica del
COBOL original con una ejecución sombra: un intérprete que corre el Ir
directamente sobre charka-runtime, sin compilar nada. Es una segunda
ruta de ejecución, independiente del código que emite charka-codegen
— si la sombra y el transpilado divergieran, sería un bug.
- interpret(&Ir) -> Outcome ejecuta el IR y captura las líneas de
DISPLAY; run_source(&str) corre el pipeline completo.
- Tope de pasos (Halt::StepLimit): un bucle que no termina se corta
en vez de colgarse.
- Módulos: field (datos -> campos vivos) / interp (el motor).
Corpus nuevo crates/modules/charka/corpus/ — 7 programas COBOL de
complejidad graduada (01-hola .. 07-clasificar) con sus salidas
esperadas verificadas a mano: DISPLAY, aritmética con GIVING,
IF/ELSE, PERFORM TIMES/UNTIL, grupos, COMPUTE con paréntesis,
ROUNDED, IF anidado con AND. Material de prueba del pipeline entero.
11 tests (los 7 del corpus + fuente vacío, STOP RUN, tope de pasos,
error de léxico); fmt + clippy limpios.
No hay GnuCOBOL en la máquina: la referencia v1 es el corpus; un modo
futuro diferenciará contra el compilador real.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
La etapa final del transpilador. generate(&Ir) -> String produce un
fuente Rust (un main.rs) que, compilado contra charka-runtime, ejecuta
la lógica del programa COBOL.
- struct Program con un campo Num/Text por dato elemental; new() lo
inicializa desde las cláusulas VALUE.
- Un método p_<párrafo> por párrafo del PROCEDURE; run() los encadena
en orden (el «caer» de COBOL); main() construye y corre.
- Cada Stmt -> código Rust: MOVE->.store/.fill, DISPLAY->println!,
COMPUTE y aritmética -> expresiones Decimal, IF->if/else,
PERFORM-> llamada / for / while, STOP RUN->process::exit.
- Tolerante: lo no transpilable (Stmt::Unknown, dato sin resolver, **)
se emite como comentario // charka: — el código generado compila.
- Saneado de identificadores COBOL->Rust (choques con keywords).
- Verificado de punta a punta: un programa COBOL demo transpila a Rust
que compila contra charka-runtime y produce la salida esperada.
- Módulos: emit / sym / expr / stmt. 14 tests; fmt + clippy limpios.
El pipeline COBOL->Rust corre de punta a punta. Falta sólo
charka-shadow (validador en sombra).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>