refactor(explorer+card): independencia jerarquica enforced
Cierra el unico debt estructural detectado en el audit de independencia: nouser-explorer ya no arrastra nouser-core (que aportaba notify/walkdir/sled/blake3 al grafo de compilacion de una UI que solo habla JSON contra un socket). - Cliente movido: engine_socket::client::list_monads (~60 LOC, std + serde_json puros) emigra de nouser_core::engine_socket a nouser_card::query::client. Vive donde viven los wire types, consistente con el principio "un consumer importa el contrato, no el runtime del productor". - Drop dep: nouser-explorer deja de depender de nouser-core. Verificado con cargo tree: notify, sled, blake3 desaparecen del grafo del binario. - Fallback "falla hacia la simplicidad": nueva resolve_socket() en el explorer intenta primero broker discovery; si el broker no responde / no hay init vivo, fallback directo al default_socket_path. El explorer queda funcional contra un daemon huerfano (standalone sin init) — completa "consciente cuando hay ecosistema, soberano cuando esta solo". - socket_source gana tercer estado "default-path" para visibilidad. Audit estructural confirmo que el resto del ecosistema ya respeta el principio. Brahman es pegamento opcional, no chasis obligatorio — y ahora el grafo de Cargo lo enforcea, no solo la convencion. Tests: 4 + 10 + 27 verdes. Cliente movido ejercitado end-to-end por los 3 tests integracion de engine_socket.
This commit is contained in:
@@ -26,9 +26,9 @@ use gpui::{
|
||||
div, prelude::*, px, rgb, App, Application, Bounds, Context, IntoElement, Render, SharedString,
|
||||
Window, WindowBounds, WindowOptions,
|
||||
};
|
||||
use nouser_card::query::{ListMonadsResponse, FLOW_MONAD_LIST, FLOW_TYPE_NAME};
|
||||
use nouser_card::query::client as query_client;
|
||||
use nouser_card::query::{transport, ListMonadsResponse, FLOW_MONAD_LIST, FLOW_TYPE_NAME};
|
||||
use nouser_card::Lens;
|
||||
use nouser_core::engine_socket::client as query_client;
|
||||
|
||||
const REFRESH_INTERVAL: Duration = Duration::from_secs(2);
|
||||
const DISCOVERY_TIMEOUT: Duration = Duration::from_secs(3);
|
||||
@@ -127,14 +127,21 @@ enum TickOutcome {
|
||||
QueryFailed(String),
|
||||
}
|
||||
|
||||
/// Resuelve el socket (cache o discovery) y consulta `ListMonads`.
|
||||
/// Pensado para correr en background: no toca GPUI, sólo I/O.
|
||||
/// Resuelve el socket (cache → broker → default path) y consulta
|
||||
/// `ListMonads`. Pensado para correr en background: no toca GPUI,
|
||||
/// sólo I/O.
|
||||
///
|
||||
/// **Falla hacia la simplicidad**: si el broker brahman no está vivo
|
||||
/// (init caído / no instalado), intentamos directo el path canónico
|
||||
/// del daemon vía `transport::default_socket_path()`. El explorer
|
||||
/// sigue funcionando contra un daemon "huérfano" que no se publicó
|
||||
/// al broker — útil para correr la UI sin todo el stack.
|
||||
fn tick(prior_socket: Option<PathBuf>) -> TickOutcome {
|
||||
let (socket, source) = match prior_socket {
|
||||
Some(p) => (p, "cache"),
|
||||
None => match discover() {
|
||||
Ok(p) => (p, "discovery"),
|
||||
Err(e) => return TickOutcome::DiscoveryFailed(format!("discovery: {e}")),
|
||||
None => match resolve_socket() {
|
||||
Ok(found) => found,
|
||||
Err(e) => return TickOutcome::DiscoveryFailed(e),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -151,10 +158,35 @@ fn tick(prior_socket: Option<PathBuf>) -> TickOutcome {
|
||||
}
|
||||
}
|
||||
|
||||
/// Resuelve el socket del daemon en dos pasos:
|
||||
/// 1. **Broker**: consumer Card + `await_provider_blocking`. Path
|
||||
/// "consciente" (ecosistema brahman activo).
|
||||
/// 2. **Default path**: si el broker no responde, probamos
|
||||
/// `transport::default_socket_path()` directo. Path "soberano"
|
||||
/// (daemon corriendo solo, sin init).
|
||||
///
|
||||
/// Falla únicamente si ninguno responde.
|
||||
fn resolve_socket() -> Result<(PathBuf, &'static str), String> {
|
||||
match discover_via_broker() {
|
||||
Ok(p) => Ok((p, "broker")),
|
||||
Err(broker_err) => {
|
||||
let fallback = transport::default_socket_path();
|
||||
if fallback.exists() {
|
||||
Ok((fallback, "default-path"))
|
||||
} else {
|
||||
Err(format!(
|
||||
"broker: {broker_err}; fallback {} no existe",
|
||||
fallback.display()
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Discovery del daemon vía broker brahman. Construye un consumer
|
||||
/// Card con `flow.input = monad-list:json`, espera al primer
|
||||
/// `MatchEvent::Available`, devuelve el `producer_service_socket`.
|
||||
fn discover() -> Result<PathBuf, ConsumerError> {
|
||||
fn discover_via_broker() -> Result<PathBuf, ConsumerError> {
|
||||
let card = build_consumer_card("nouser-explorer", FLOW_MONAD_LIST, FLOW_TYPE_NAME);
|
||||
await_provider_blocking(card, DISCOVERY_TIMEOUT)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user