Files
brahman/crates/core/brahman-admin/examples/brahman-status.rs
T
Sergio 5edc912ed8 feat: Phase D-3 + D-4 — service_socket en Card, providers coexisten
Cierra el ciclo del swap automático Nous mock↔real:

- brahman-card: Card.service_socket: Option<PathBuf> y espejo en
  WireCard. Path del data plane (distinto al Init). Cualquier
  consumer que matchee con esta Card conecta directo, sin discovery
  extra.
- brahman-broker: BrokeredCard propaga service_socket. Sin
  participación en matching — sólo metadata.
- brahman-handshake::MatchEvent: nuevo campo
  producer_service_socket. Server lo busca en BrokeredCard al emitir
  Available.
- nouser-nous::transport: provider_socket_path(provider: &str)
  devuelve nouser-nous-{provider}.sock por default. Mock y real
  coexisten en sockets distintos (Phase D-4). default_socket_path()
  conserva el comportamiento single-provider.
- Mock declara nouser-nous-mock.sock; real declara
  nouser-nous-real.sock. La Card se construye DESPUÉS del bind.
- brahman-status imprime "socket:" por sesión cuando está presente.

Validación end-to-end:
  $ ente-zero & nouser-nous-mock & nouser-nous-real &
  $ ls /run/user/1001/nouser-nous-*.sock
    nouser-nous-mock.sock
    nouser-nous-real.sock
  $ brahman-status
  Sessions (2):
    [ente]  nouser.nous_real
        socket: /run/user/1001/nouser-nous-real.sock
    [ente]  nouser.nous_mock
        socket: /run/user/1001/nouser-nous-mock.sock

Pendiente (no crítico): nouser-core attract --remote usa todavía
NOUSER_NOUS_SOCKET hardcoded. Siguiente paso: subscribirse al
MatchEvent del broker y usar producer_service_socket directo, así
BRAHMAN_BROKER_CONTEXT=test/prod swapea provider sin tocar al
consumer.

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

93 lines
3.3 KiB
Rust

//! `brahman-status` — CLI para inspeccionar el estado del Init.
//!
//! Conecta al socket admin (default `$XDG_RUNTIME_DIR/brahman-admin.sock`,
//! override con `$BRAHMAN_ADMIN_SOCKET`), recibe el snapshot, y lo imprime.
use brahman_admin::{client, transport};
#[tokio::main(flavor = "current_thread")]
async fn main() -> anyhow::Result<()> {
let path = transport::default_socket_path();
let snap = client::query(&path).await?;
println!(
"Init: server={} protocol={} attached={}",
snap.server_version, snap.protocol_version, snap.init_attached
);
if let Some(ctx) = &snap.current_context {
println!("Context: {}", ctx);
}
println!();
println!("Sessions ({}):", snap.sessions.len());
if snap.sessions.is_empty() {
println!(" (ninguna)");
} else {
for s in &snap.sessions {
let conscious_marker = if s.wit.is_some() { " 🧠" } else { "" };
let kind_marker = match s.kind {
brahman_card::CardKind::Ente => "ente",
brahman_card::CardKind::Data => "data",
};
println!(
" [{}] {} {}{} lifecycle={:?} priority={:?}",
kind_marker, s.session, s.label, conscious_marker, s.lifecycle, s.priority
);
if let Some(sock) = &s.service_socket {
println!(" socket: {}", sock.display());
}
if let Some(data) = &s.data {
if !data.summary.is_empty() {
println!(" summary: {}", data.summary);
}
if data.member_count > 0 {
println!(
" members: {} (dispersion={:.2})",
data.member_count, data.dispersion
);
}
if !data.keywords.is_empty() {
println!(" keywords: {}", data.keywords.join(", "));
}
if !data.presentation_hint.is_empty() {
println!(" lens hint: {}", data.presentation_hint);
}
}
if let Some(wit) = &s.wit {
println!(" wit: {} / {}", wit.package, wit.world);
if !wit.imports.is_empty() {
println!(" imports: {}", wit.imports.join(", "));
}
if !wit.exports.is_empty() {
println!(" exports: {}", wit.exports.join(", "));
}
}
for f in &s.inputs {
println!(" in {}: {:?}", f.name, f.ty);
}
for f in &s.outputs {
println!(" out {}: {:?}", f.name, f.ty);
}
}
}
println!();
println!("Matches ({}):", snap.matches.len());
if snap.matches.is_empty() {
println!(" (ninguno)");
} else {
for m in &snap.matches {
let pin_marker = if m.pinned { "📌" } else { " " };
println!(
" {} {}.{}{}.{} via {:?}",
pin_marker,
m.consumer_label,
m.consumer.flow_name,
m.producer_label,
m.producer.flow_name,
m.via
);
}
}
Ok(())
}