# Changelog — misc Entradas que no encajan en otro proyecto (chore, ci, gitignore, etc.). ### chore(.gitignore): excluir .claude/ (state local de Claude Code) Iter 18. Side cleanup tras debugging: `.claude/` aparecía en `git status` cada sesión (contenía `scheduled_tasks.lock` y `settings.local.json`, ambos local-only). Excluido para que no se commitee accidentalmente y para que `git status` quede limpio. Investigación previa que motivó el cleanup: persiguiendo un supuesto deadlock en `drift_check_surfaces_expected_per_record_diffs` con eprintlns/macro de log a archivo en `drift.rs` y `run.rs`. Conclusión: no hay deadlock — pasa cleanly aislado, en suite nakui-core, y en `cargo test --workspace`. El "hang" original venía de procesos cargo y test-binaries huérfanos de sesiones anteriores compitiendo por el build lock. Source restaurado, ningún cambio funcional. Memoria `project_drift_hang.md` reescrita con el playbook correcto. ### feat(explorer+daemon): discovery dinámico vía broker + query socket La UI deja de hardcodear el socket admin: ahora descubre al daemon nouser vía `MatchEvent::Available` del broker brahman y le consulta sus Mónadas directo, sin pasar por brahman-admin. Cierra el "explorer encuentra al daemon de forma totalmente dinámica" del meta-plan. Pipeline end-to-end: - Daemon publica engine Card con `service_socket = $XDG_RUNTIME_DIR/nouser-engine.sock` y `flow.output = monad-list:json`. - Daemon binda un Unix socket en ese path y monta un listener blocking que sirve `nouser_card::query::QueryRequest::ListMonads`, responde `ListMonadsResponse { engine, monads: Vec }`. - Explorer construye un consumer Card con `flow.input = monad-list:json` vía `brahman_sidecar::build_consumer_card`, llama `await_provider_blocking(card, 3s)` y recibe el socket descubierto. - Cachea ese socket; cada poll (2s) llama `nouser_core::engine_socket::client::list_monads(socket, 2s)`. Fallo de query → invalida cache → próximo tick re-descubre. Wire types nuevos en `nouser_card::query`: - `QueryRequest::ListMonads` (single variant por ahora). - `ListMonadsResponse { engine: EngineInfo, monads: Vec }`. - `MonadView`: proyección slim de `MonadManifest` SIN `centroid` ni `members` — la UI no los necesita y eran KB por Mónada que no tenían por qué viajar cada poll. - `transport::default_socket_path()` con env override `NOUSER_ENGINE_SOCKET`. - Const `FLOW_MONAD_LIST = "monad-list"`, `FLOW_TYPE_NAME = "json"`. Listener en `nouser_core::engine_socket`: - `spawn_listener(config, db)` arma std::os::unix::net::UnixListener en thread blocking dedicado. Frecuencia esperada (UI cada 2s) no amerita tokio. - `client::list_monads(socket, timeout)` — cliente blocking con `QueryError` tipado (Connect / Io / Serde / Daemon / Timeout / Empty). - 3 tests integración: roundtrip vacío, Mónadas reales, request inválido devuelve ErrorResponse. Refactor explorer: - Drop dep `brahman-admin`, add deps `brahman-sidecar`, `nouser-card`, `nouser-core`. - State: `socket: Option` cache + `snapshot: Option` + `socket_source: "discovery"|"cache"` (sólo informativo). - Tick: `tick(prior_socket)` separado del UI, devuelve un enum `TickOutcome::{Ok, DiscoveryFailed, QueryFailed}`. Cualquier fallo invalida la cache → re-discovery automática. - Header reformulado: `Engine 'nouser_engine' · N mónada(s) · socket: /... (cache|discovery) · watching: /tmp/x`. - Render pintado de un engine card + Mónadas, sin ya iterar `BrokeredCard` del admin. Trade-offs aceptados: - Polling 2s (no streaming). El broker no empuja cambios de Data cards hoy; agregar streaming requiere extender el protocolo handshake. Para snapshot UI, polling 2s es suficiente. - Re-descubrimiento full en cada error de query (en lugar de retry con backoff). Discovery es barato (~ms vs broker), no vale la pena la complejidad. Tests: 10 (nouser-card, +3 query) + 27 (nouser-core, +3 engine_socket) + 4 (sidecar) verdes. Explorer compila clean.