Files
brahman/CHANGELOG.md
T
Sergio f19ca723b6 feat(card): WireCard + extensions — forward-compat sin romper postcard
Restaura el campo extensions de Card que había caído al adoptar postcard
(serde_json::Value usa secuencias/maps de longitud dinámica). La
solución es separar dos formas:

- Card (la rica): para JSON/TOML. Tiene extensions: BTreeMap<String,
  serde_json::Value> con #[serde(flatten, skip_serializing_if = is_empty)].
  Los campos desconocidos del archivo sobreviven el roundtrip.
- WireCard (la slim): para postcard. Mismo schema sin extensions y con
  genesis: Vec<WireCard> recursivo. Postcard-friendly por construcción.

Conversiones From<Card> for WireCard (descarta extensions) y
From<WireCard> for Card (extensiones quedan vacías post-wire). El
contrato es explícito: extensions son anotaciones locales que sobreviven
file I/O pero NO cruzan al Init.

brahman-handshake::Hello.card cambia de Card a WireCard. Client hace
card.into() al enviar; Server hace hello.card.into() para volver a
Card antes de validar/registrar.

Tests:
- 3 nuevos en brahman-card: extensions_preserved_in_json_roundtrip,
  wire_card_roundtrip_strips_extensions, wire_card_postcard_friendly
  (verifica que postcard::to_allocvec(&wire) NO falla — caso que
  rompía con Card.extensions populadas).
- 1 ajuste en handshake/tests/handshake.rs (struct-literal de Hello
  ahora con card: sample_card(...).into()).
- brahman-card: postcard como dev-dep.

Tests acumulados: 35 (card 11, broker 11, handshake codec+transport 2 +
integ 7, card-wit 4, admin 0). 0 errores, 0 warnings (vienen del
commit anterior 9420eae).

CHANGELOG.md actualizado con esta entrada y con el commit 9420eae
("probando" del usuario, limpieza de 17 warnings dead-code).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 17:33:15 +00:00

239 lines
12 KiB
Markdown

# Changelog
Registro cronológico de cambios sustantivos en el monorepo Brahman. Cada
entrada lista las acciones concretas tras un commit; para detalles de
ratio/diff ver `git show <sha>`.
## 2026-05-08
### feat(card): WireCard + extensions — forward-compat sin romper postcard
- `Card.extensions: BTreeMap<String, serde_json::Value>` restaurado con
`#[serde(flatten, default, skip_serializing_if = is_empty)]`. Los
campos JSON/TOML desconocidos sobreviven el roundtrip de archivos.
- Nuevo `WireCard`: proyección postcard-friendly (sin `extensions`,
`genesis: Vec<WireCard>` recursivo). Conversiones `From<Card>` y
`From<WireCard>` con descarte/recreación de extensions.
- `brahman-handshake::Hello.card` pasa de `Card` a `WireCard`. Client
hace `card.into()` antes de enviar; Server hace `hello.card.into()`
para volver a Card antes de validar/registrar.
- 3 tests nuevos en brahman-card:
`extensions_preserved_in_json_roundtrip`,
`wire_card_roundtrip_strips_extensions`,
`wire_card_postcard_friendly` (postcard encode/decode efectivo).
- brahman-card gana `postcard` como dev-dep para el último test.
- Contrato documentado: extensions = anotaciones locales que NO cruzan
al Init; sólo viven en archivos.
### `9420eae` chore: limpia warnings dead-code en arje (commit del usuario)
- `ente-zero/src/events.rs`: `#![allow(dead_code)]` a nivel módulo —
es vocabulario de eventos con variantes/campos reservados para flujos
no cableados aún (CapabilityRequested, ShutdownReason::Signal,
CapabilityGrant::{Granted, Denied, QuotaExceeded}, ExitStatus
fields).
- `ente-zero/src/graph/mod.rs`: comentado el re-export ahora innecesario
de `SHUTDOWN_GRACE`. `DEFAULT_GRANT_TTL` con `#[allow(dead_code)]`
+ nota "reservado para capability granting".
- `ente-zero/src/graph/capabilities.rs`: `renew_grant` con
`#[allow(dead_code)]` (capability renewal pendiente).
- `ente-kernel/src/surface.rs`: drop de `use anyhow::Context` (no se
usaba).
- `ente-hostnamed-compat/src/main.rs`: drop de `Connection` (no se
usaba).
- `ente-polkit-compat/src/main.rs`: `PolicyDecision.source` con
`#[allow(dead_code)]` (sólo aparece en `Debug` para logging).
- `cargo check --workspace`: 17 warnings → 0.
### feat(sidecar): WIT al sidecar — módulos conscientes vivos
- `brahman-card::WitInterface` deriva `Serialize`, `Deserialize`,
`PartialEq`, `Eq` para cruzar el wire postcard.
- `brahman-handshake::Hello` lleva `wit: Option<WitInterface>`. Server
usa `ResolvedCard::from_conscious` cuando viene presente, `from_agnostic`
cuando no.
- `brahman-handshake::Client::connect` queda como wrapper agnóstico de
`connect_with(path, card, wit: Option<WitInterface>)`.
- `brahman-broker::Broker::register` ahora toma `Option<WitInterface>`
como tercer arg. `BrokeredCard` guarda el wit. 25 sitios de tests
actualizados con `, None`.
- `brahman-sidecar::SidecarConfig` con campo `wit`. Helpers nuevos:
`SidecarConfig::new(card).with_wit(wit)` y `spawn_conscious(card, wit)`.
El log `attached` reporta `conscious=true|false`.
- `brahman-status` muestra marker 🧠 + sección `wit:` (package/world,
imports, exports) por sesión consciente.
- Example nuevo `crates/shared/brahman-sidecar/examples/presence-conscious.rs`:
toma label + path .wit (default `shared_wit/protocol.wit`), parsea
con brahman-card-wit, spawna sidecar consciente.
- Validado end-to-end:
```
$ presence-conscious demo.conscious shared_wit/protocol.wit &
$ brahman-status
Sessions (1):
01K... demo.conscious 🧠 lifecycle=Daemon
wit: brahman:protocol@0.1.0 / module
imports: types, handshake, lifecycle
exports: run
```
### feat(core): brahman-card-wit — extractor opcional de contratos WIT
- Crate nuevo `crates/core/brahman-card-wit` con `wit-parser = "0.230"`.
- API: `parse_wit(source)` y `parse_wit_file(path)` devuelven
`Vec<WitInterface>` (uno por `world` declarado).
- Interfaces importadas/exportadas (no sólo funciones) se resuelven
por nombre via `resolve.interfaces[id].name`.
- Example `crates/core/brahman-card-wit/examples/brahman-wit-info.rs`
CLI: `brahman-wit-info shared_wit/protocol.wit` → lista paquete,
worlds, imports y exports.
- 4 tests: inline, archivo real (`shared_wit/protocol.wit`), parse
error, world vacío.
- Validado contra `protocol.wit`: detecta worlds `module` y
`admin-host` con sus imports/exports correctos.
### `7b589b8` chore: agrega CHANGELOG.md retroactivo
- `CHANGELOG.md` en la raíz con los 11 commits previos documentados
acción por acción. A partir de este punto, cada cambio sustantivo
actualiza también este archivo en el mismo commit.
### `8a83a26` feat(handshake): notificación push de matches
- Frame `MatchEvent { kind: Available | Lost, ... }` añadido al protocolo.
- `Session::run_post_handshake` usa `tokio::select!` para multiplexar
reads del cliente y un canal `mpsc` push del server.
- Server: `SessionTxTable` (Arc<Mutex<HashMap<SessionId, Sender<Frame>>>>)
y `LastMatches` para diff por sesión. `broadcast_match_diffs` corre
tras cada `register` y `unregister`, emite sólo los cambios.
- Capacity del canal push: 32 (ephemeral, `try_send` non-blocking).
- Client: `VecDeque<MatchEvent>` interno, `take_event()` (non-blocking)
y `await_event(timeout)`. `ping()` ahora drena MatchEvents intermedios
hasta encontrar el Pong.
- Example `crates/core/brahman-handshake/examples/subscriber.rs`.
- Test `match_event_pushed_on_producer_arrival` (handshake integ 6→7).
### `70a7a0d` feat: segundo módulo (nakui) + admin API + brahman-status
- Crate nuevo `crates/shared/brahman-sidecar` (DRY del thread + tokio +
ping loop). API: `spawn(card)` / `spawn_with_handle(config)`.
- `nakui` cmd_run llama `brahman_sidecar::spawn` antes de `run_server`.
Card: lifecycle Daemon, supervision Restart, flow `command` (json) /
`report` (json).
- Crate nuevo `crates/core/brahman-admin` con `StatusSnapshot` JSON
line-delim, `AdminServer` y `client::query`.
- ente-zero levanta también el AdminServer en `primordial_loop`.
- Example `crates/shared/brahman-sidecar/examples/presence.rs`
(módulo dummy long-lived parametrizable por label).
- Example `crates/core/brahman-admin/examples/brahman-status.rs`
(CLI que pretty-printa el snapshot).
- `brahman-broker`: `BrokeredCard` ahora incluye `lifecycle`. `Endpoint`
y `Match` derivan `Serialize`/`Deserialize`. Nuevo `Broker::cards()`
iterador.
- `brahman-card`: `pub use ::ulid` para que módulos no dependan de ulid.
- yahweh-shell migrado al sidecar compartido (96→53 LOC).
### `595f68e` feat(yahweh-shell): primer módulo brahman vivo
- yahweh-shell spawnea sidecar antes de `Application::new()`.
- Card declarada: label `brahman.ui_engine`, lifecycle Widget,
supervision Delegate, payload Virtual, flow input `render-data`
(json) / output `user-intent` (json).
- Sidecar en thread aparte con tokio current_thread runtime,
desacoplado del runtime GPUI.
### `df9d10c` feat(ente-zero): enchufa el handshake server al Init real
- ente-zero levanta `brahman_handshake::server::Server::bind` en
`primordial_loop` después del ente-bus, con degradación grácil
si bind falla (mismo patrón que uevents).
- Nuevo módulo `brahman-handshake/src/transport.rs`: helper
`default_socket_path()` con resolución `BRAHMAN_INIT_SOCKET` →
`XDG_RUNTIME_DIR` → `TMPDIR`.
- Example `crates/core/brahman-handshake/examples/probe.rs`.
- Validación end-to-end manual: probe contra ente-zero vivo
imprime `HelloAck: session=... init_attached=true`.
### `07d77a3` feat(handshake): integra el broker con el ciclo de sesiones
- `ServerConfig` acepta `Option<Arc<Mutex<Broker>>>`.
- `register_session` indexa la Card en el broker y la `SessionRegistry`
antes de emitir HelloAck.
- `Session::handle` refactor a `do_handshake → run_post_handshake →
cleanup` con cleanup unificado (broker + sessions).
- Tests integ nuevos: `broker_registers_and_unregisters_with_session`
y `broker_matches_two_live_modules`.
- Fix colateral: `brahman-card::TypeRef` pasa de internally-tagged
(`#[serde(tag = "kind")]`) a externally-tagged. Postcard no soporta
internally-tagged en formatos no self-describing. JSON cambia de
`{"kind":"primitive","name":"x"}` a `{"primitive":{"name":"x"}}`.
### `5091106` feat(core): brahman-broker — matching híbrido
- Crate nuevo `crates/core/brahman-broker`.
- 3 estrategias de matching: `Exact`, `Structural`, `ExactThenStructural`
(default). Devuelven `Match::via` con la estrategia que ganó.
- Override `pin_to`: el consumer pide un productor por label; si la
pista no resuelve, cae en type-search.
- Tiebreak por `Card.priority` desc, luego `label` asc (estable y
determinista).
- API: `register`, `unregister`, `find_producer_for`, `all_matches`,
`cards`, `sessions`, `len`, `is_empty`.
- 11 tests (matching, pin_to, priority, no-self-loops, all-matches).
### `814390f` feat(core): brahman-handshake — protocolo runtime
- Crate nuevo `crates/core/brahman-handshake` con server y client
Rust↔Rust sobre Unix socket.
- Frames length-prefixed (4 bytes LE) + cuerpo postcard.
- Mensajes: `Hello`, `HelloAck`, `Ping`, `Pong`, `Farewell`, `Error`.
- `MAX_FRAME_BYTES = 4 MiB` para evitar reservas absurdas.
- Tradeoff: drop `extensions`/`extra` de Card por incompat
postcard ↔ `serde_json::Value`. Forward-compat queda en
`schema_version` + `protocol_version` negotiation.
- 4 tests integ + 1 unit en codec.
### `ed0e973` refactor(arje): migra ente-card a re-export de brahman-card
- `ente-card/src/lib.rs` reescrito como crate-shim de re-export
(327 LOC → 25 LOC).
- `EntityCard` ≡ `brahman_card::Card` por type alias.
- `ente-card/Cargo.toml`: deps reducidas a `brahman-card`.
- `Card` impl `Default` (Ulid::nil(), label vacío) para que
`..Default::default()` funcione en struct-literals.
- 4 sitios en `ente-zero/src/seed.rs` actualizados con
`..Default::default()` para los campos aditivos.
- Los 21 consumidores arje compilan sin tocar fuente.
### `0feba74` feat(core): brahman-card — Tarjeta canónica híbrida
- Crate nuevo `crates/core/brahman-card`.
- Hereda de arje: `id: Ulid`, `lineage`, `Capability` tipado,
`Payload::{Wasm, Native, Virtual, Legacy}`, `SomaSpec`
(namespaces, cgroups, rlimits, cpu_affinity), `Supervision`
(Restart con backoff, OneShot, Delegate), `genesis` recursivo.
- Aditivo brahman: `Permissions` enumerados (`NetworkingPolicy`,
`FsPolicy`, `IpcPolicy`), `Lifecycle` ortogonal a Supervision,
`Priority` de scheduling, `Flows` con `TypeRef` discriminado
(Primitive | Wit), `pin_to` opcional.
- `TrustLevel` derivado de `Permissions` (no declarado).
- `ResolvedCard { card, wit: Option<WitInterface>, trust }`.
- Soporta JSON (canónico) + TOML (auto-detectado por extensión).
- 8 tests incluido `arje_seed_format_compatible` que valida que
el JSON de arje sigue parseando con defaults para los aditivos.
### `4d50bfc` chore: absorbe nakui (ERP matemático) en modules/nakui
- `~/nakui` → `crates/modules/nakui/{core,modules}`.
- `core/`: el crate `nakui-core` con 4 bins (nakui, demo,
inventory_demo, sales_demo) y tests.
- `modules/{inventory,sales,treasury}/`: data declarativa
(`nsmc.json`, `schema.k`, `morphisms/`) que el crate consume.
No son crates Cargo.
- Deps directas (no `workspace = true`): thiserror v1, surrealdb,
rhai, petgraph. No conflicto con el resto del workspace.
### `53dbdf0` chore: monorepo inicial con arje + minga + yahweh absorbidos
- 45 crates absorbidos en 4 ejes:
- `crates/core/`: 24 crates de arje (Init systemd-compatible:
`ente-card`, `ente-zero`, `ente-kernel`, `ente-bus`, `ente-cas`,
`ente-soma`, `ente-wasm`, `ente-snapshot`, `ente-brain`,
`ente-echo`, `ente-policy-provider`, + 12 `*-compat`).
- `crates/modules/semantic_dht/`: 5 crates de minga (`minga-core`
con AST/CAS/MST, `minga-p2p` con libp2p Kad, `minga-store`,
`minga-vfs`, `minga-cli`).
- `crates/modules/ui_engine/`: 11 crates de yahweh (libs/{core,
theme, bus, providers}, widgets/{tree, splitter, tabs, tiled,
container_core, text_input}).
- `crates/apps/`: 5 crates de yahweh (file_explorer,
database_explorer, text_viewer, image_viewer, yahweh-shell).
- `shared_wit/protocol.wit` con handshake/lifecycle inicial.
- `Cargo.toml` unificado: thiserror bumped a 2 (transparente para
arje), tokio "full", paths intra-workspace de yahweh redirigidos.
- `cargo check --workspace`: 0 errores (sólo dead-code warnings
preexistentes en ente-zero).