Files
brahman/CHANGELOG.md
T
Sergio b85700c538 feat: Phase B-1 — unificación ontológica de Cards (Ente ↔ Data)
La Card pasa a ser EL protocolo de presentación del ecosistema. Una
Mónada Nouser y un Ente Brahman son ambos "entidades que se presentan";
el consumidor (UI, broker, admin) discrimina por `kind` cuando importa,
pero todos hablan el mismo idioma.

brahman-card:
- CardKind { Ente (default), Data }. Backward-compat: Cards existentes
  quedan Ente.
- DataFacet { summary, keywords, centroid, member_count, dispersion,
  presentation_hint } — vista liviana para el wire. Listas grandes
  (members reales, embeddings completos) se consultan al daemon dueño
  bajo demanda.
- Card.kind y Card.data agregados. WireCard espeja, conversiones From
  propagan ambos campos.
- Default impl actualizado.

brahman-broker:
- BrokeredCard propaga kind y data desde la Card registrada. No afecta
  el matching (sigue por TypeRef + priority + pin_to); permite a
  observadores discriminar sin re-query.

nouser-card:
- Depende ahora de brahman-card.
- MonadManifest::to_brahman_card() proyecta una Mónada a Card brahman:
  - id, label, lineage directos.
  - payload Virtual, supervision Delegate, lifecycle Daemon
    (placeholder — la Mónada no se ejecuta).
  - kind = Data.
  - data = Some(DataFacet { summary, keywords, centroide,
    member_count, entropy → dispersion, presentation_hint del Lens }).
- Test nuevo projects_to_brahman_card.

brahman-status:
- Prefijo [ente] o [data] por sesión.
- Sesiones data renderean también summary, members + dispersion,
  keywords y lens hint.

Resultado: la UI ve una sola lista uniforme — no necesita saber si
mira procesos o cúmulos de datos, sólo lee el Card y se adapta por
kind. La función de presentarse es la misma para todos.

Tests: 59 (card 11, broker 15, handshake codec+tr 2 + integ 7,
card-wit 4, admin 0, nouser-card 7 +1, nouser-core 13).
cargo check --workspace: 0 errores, 0 warnings.

Próximo: Phase B-2 — bin nouser daemon que sidecarea cada Mónada como
sesión brahman, mezclándolas con los entes en brahman-status.

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

19 KiB

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: Phase B-1 — unificación ontológica de Cards (Ente ↔ Data)

La Card es el protocolo de presentación del ecosistema, no sólo de los procesos. Una Mónada Nouser y un Ente Brahman son ambos "entidades que se presentan"; el consumidor (UI, broker, admin) discrimina por kind cuando importa, pero todos hablan el mismo idioma.

Cambios:

  • brahman-card:

    • CardKind { Ente (default), Data }. Conserva back-compat: Cards existentes son Ente por default.
    • DataFacet { summary, keywords, centroid, member_count, dispersion, presentation_hint }. Liviano para el wire — listas grandes (members, embeddings completos) se consultan al daemon dueño bajo demanda.
    • Card.kind y Card.data: Option<DataFacet> agregados. WireCard espeja, conversiones From propagan.
    • Default impl actualizado.
  • brahman-broker::BrokeredCard: propaga kind y data desde la Card registrada. No afecta el matching (sigue siendo por TypeRef + priority + pin_to); permite a observadores discriminar sin re-query.

  • nouser-card: depende ahora de brahman-card. Nuevo método MonadManifest::to_brahman_card() que proyecta:

    • id, label, lineage → directos.
    • payload Virtual, supervision Delegate, lifecycle Daemon (placeholder semántico — la Mónada no se ejecuta).
    • kind = Data.
    • data = Some(DataFacet) con summary, keywords, centroide, member_count, entropy → dispersion, y un presentation_hint derivado del Lens (Code"code", Gallery"gallery", etc.).
    • Test nuevo: projects_to_brahman_card.
  • brahman-status: cada sesión muestra ahora [ente] o [data] como prefijo. Para sesiones data, render adicional con summary, members

    • dispersion, keywords y lens hint.

Resultado: la UI (yahweh, brahman-status, futuro explorer) ve una sola lista uniforme. No tiene que saber si está mirando un proceso o un cúmulo de datos — sólo lee el Card y se adapta por kind.

Tests acumulados: 59 (card 11, broker 15, handshake codec+transport 2 + integ 7, card-wit 4, admin 0, nouser-card 7, nouser-core 13). cargo check --workspace: 0 errores, 0 warnings.

Próximo: Phase B-2 — bin nouser daemon <dir> que sidecarea cada Mónada como una sesión brahman, publicándola al broker. Brahman-status las verá junto a los entes.

feat(nouser): Phase A — mecanismo determinista de Mónadas

Primer trozo del módulo Nouser (Kairos): explorador de Mónadas como "imanes semánticos" sobre el filesystem. Phase A cubre el 90% de los casos sin tocar IA — sólo metadatos y heurísticas.

Crates nuevos:

  • crates/modules/nouser/card: MonadManifest (la Tarjeta de Presentación de una Mónada — espejo conceptual de brahman::Card pero para datos, no para procesos runtime). Campos: id (Ulid), label, summary, centroid (vacío en Phase A), keywords, cardinality, entropy [0,1], dominant_lens, pins, members, timestamps, extensions (forward-compat). 6 tests de validación + JSON roundtrip.
  • crates/modules/nouser/core: pipeline determinista.
    • scanner: walkdir → Vec<FileEntry> con metadatos (path, size, mtime, extension). Skipea hidden por default. Configurable max depth y follow_links.
    • cluster::by_directory: agrupa por parent dir, mínimo 3 archivos para promover a Mónada (configurable). Calcula keywords (top-N extensiones por frecuencia + alfabético), elige Lens dominante (Code/Gallery/Markdown/Database/Grid) según extensión más frecuente, computa entropía de Shannon normalizada [0,1].
    • db: MonadDb en memoria con índices BTreeMap files/monads y resolve_members(monad_id) que filtra IDs huérfanos. Phase B traerá persistencia.
    • bin nouser: subcomandos scan <dir>, show <dir> <prefix>, json <dir>. Env var NOUSER_MIN_FILES para tunear el threshold.
    • 13 tests (4 scanner + 6 cluster + 3 db).

Demo end-to-end:

$ nouser scan crates scan: 255 archivos en crates, 19 mónadas (min_files=3) [01KR4C13] src card=12 ent=0.00 lens=Code keywords: rs [01KR4C13] tests card=14 ent=0.00 lens=Code keywords: rs [01KR4C13] fixtures card=5 ent=0.00 lens=Grid keywords: rhai ...

$ nouser show crates 01KR4C Monad 01KR4C1370DVF6NMTW6SECNXAF label: src summary: 4 archivos en crates/modules/nouser/core/src (ext: rs) cardinality: 4 entropy: 0.0000 lens: Code members (4): 4132 bytes crates/modules/nouser/core/src/db.rs ...

Pendientes para próximas fases (anotados, no urgentes):

  • Phase B: bin nouser daemon que sidecarea a brahman-init declarando flows (scan-request:jsonmonad-update:json).
  • Phase C: pseudo-embeddings deterministas (hash de path/ext/size a 32-d) + atracción por centroide via cosine similarity. Implementa el "imán" sin LLM.
  • Phase D: módulo nouser-nous aparte para el LLM real (Llama/ONNX). En priority_contexts.test el Init pinea a mock-nous (embeddings determinísticos); en prod a real-nous.
  • Polish: labels de Mónada incluir 2-3 componentes del path para desambiguar src/ repetidos en monorepo.

Workspace: 0 errores, 0 warnings. Tests acumulados: 58 (card 11, broker 15, handshake codec+transport 2 + integ 7, card-wit 4, admin 0, nouser-card 6, nouser-core 13).

feat(broker): priority contexts — biases per-contexto operativo

  • brahman-card::ContextBias { pin_to: Option<String>, priority_offset: i8 } declara un override per-contexto.
  • Card.priority_contexts: BTreeMap<String, ContextBias> y mismo en WireCard (cruza el wire). Las conversiones From lo propagan.
  • BrokerConfig.current_context: Option<String>. Cuando el broker corre bajo un contexto y una Card declara biases para ese nombre, se aplican:
    • Como consumidor: pin_to sobreescribe el Flow.pin_to estático.
    • Como productor: priority_offset se suma a la priority base (clamp en [Low=0, Critical=3]) para el ranking.
  • BrokeredCard propaga priority_contexts. find_producer_for usa effective_priority(card) y effective_pin(card, input) antes de los tiebreaks.
  • brahman-admin::AdminConfig.current_context + StatusSnapshot.current_context espejan el contexto activo. brahman-status lo imprime como Context: <nombre> justo debajo de Init: ....
  • ente-zero lee BRAHMAN_BROKER_CONTEXT env var y la propaga al broker y al admin. Sin var, biases per-contexto inactivos.
  • 4 tests nuevos en brahman-broker: context_priority_offset_lifts_producer_above_alphabetic_winner, context_pin_to_overrides_static_pin, unknown_context_no_op, priority_offset_clamps_to_critical.
  • Validación end-to-end: BRAHMAN_BROKER_CONTEXT=test ente-zerobrahman-status muestra Context: test.

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>>>) 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_SOCKETXDG_RUNTIME_DIRTMPDIR.
  • 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).
  • EntityCardbrahman_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

  • ~/nakuicrates/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).