tawasuyu

tawasuyu/brahman

Rust 582TOML 222Markdown 83JSON 198635 Definitions

feat(yahweh-meta-runtime): promover short_hash y preview_value desde nakui-explorer

Continúa la integración de apps nakui al stack yahweh. Los
helpers visuales que nakui-explorer tenía locales y son reusables
suben a yahweh-meta-runtime/format.

yahweh-meta-runtime:
- short_hash(h: &[u8; 32]) -> String: hex de los primeros 4 bytes.
- preview_value(v: &Value, max: usize) -> String: JSON one-liner
  truncado con "..." (edge case max < 3 sin panic).
- 5 tests nuevos.

nakui-explorer:
- Nueva dep yahweh-meta-runtime.
- Borrado helpers locales (short_uuid + short_hash + preview_value)
  + 4 tests duplicados.
- Imports desde yahweh-meta-runtime.

Tests: 42→47 yahweh-meta-runtime, 7→3 nakui-explorer (los 3 que
quedan son específicos del explorer: load_log, breakdown,
missing_file). Resto intacto.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

d5ef7144b5a1d2e6604505cb4dc08e7a703ecc72 · by Sergio · (5 months ago) · parent df089f058 · browse the tree at this commit

Semantic delta · 14

crates/apps/nakui-explorer/src/main.rs

5 files · +121 −60

diff --git a/CHANGELOG.md b/CHANGELOG.md
index cb44952..8ed39c1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,46 @@ ratio/diff ver `git show <sha>`.
 
 ## 2026-05-10
 
+### feat(yahweh-meta-runtime): promover `short_hash` y `preview_value` desde nakui-explorer
+Continúa la integración de las apps nakui al stack yahweh. Los
+helpers visuales que `nakui-explorer` tenía locales y son reusables
+suben a `yahweh-meta-runtime/format` para que cualquier app pueda
+consumirlos sin duplicar.
+
+Cambios en `yahweh-meta-runtime`:
+- **`pub fn short_hash(h: &[u8; 32]) -> String`**: hex de los
+  primeros 4 bytes (8 chars). Útil para mostrar bundle/schema
+  hashes en UI sin quemar pantalla.
+- **`pub fn preview_value(v: &Value, max: usize) -> String`**:
+  JSON one-liner truncado con `...` al final si excede `max`
+  chars. Edge case: `max < 3` devuelve los primeros `max` chars
+  sin sufijo.
+- Re-exports en lib.
+- 5 tests nuevos: 4 tests + 1 sanity para el caso `max < ellipsis`.
+
+Migración de `nakui-explorer`:
+- Nueva dep `yahweh-meta-runtime` en Cargo.toml.
+- Borrado helpers locales `short_uuid`, `short_hash`,
+  `preview_value` (~30 líneas).
+- `use yahweh_meta_runtime::{preview_value, short_hash, short_uuid}`.
+- Borrados 4 tests duplicados (los runtime los testea).
+
+Tests:
+- `yahweh-meta-runtime`: 42 → **47** (+5 helpers nuevos).
+- `nakui-explorer`: 7 → **3** (–4 duplicados; quedan los 3
+  específicos: load_log, breakdown, missing_file).
+- Resto del workspace intacto.
+
+Beneficio operativo: 3 helpers visuales centralizados. Cualquier
+app nueva que muestre UUIDs/hashes/JSON-previews los importa sin
+re-implementar la heurística de truncamiento.
+
+Pendiente arquitectural: el render del card timeline en
+`nakui-explorer` (border-l-4 colored + flex_col + texto en niveles)
+es un pattern reusable que también aparece en `yahweh-widget-meta-form`
+(render_list filas). Cuando aparezca un tercer consumer de ese
+pattern se extrae a un widget yahweh.
+
 ### feat(brahman-cards): templates Nickel canónicos para cada body kind
 Materializa el patrón "import + override" del brazo: hasta ahora
 `BRAHMAN_CARDS_TEMPLATES_DIR` existía como mecanismo pero el repo
diff --git a/crates/apps/nakui-explorer/Cargo.toml b/crates/apps/nakui-explorer/Cargo.toml
index 38c6249..321bd06 100644
--- a/crates/apps/nakui-explorer/Cargo.toml
+++ b/crates/apps/nakui-explorer/Cargo.toml
@@ -7,6 +7,7 @@ description = "Explorador GPUI del event log de Nakui: timeline de seeds + morph
 
 [dependencies]
 nakui-core = { path = "../../modules/nakui/core" }
+yahweh-meta-runtime = { path = "../../modules/ui_engine/libs/meta-runtime" }
 gpui = { workspace = true }
 serde_json = { workspace = true }
 uuid = { workspace = true, features = ["serde"] }
diff --git a/crates/apps/nakui-explorer/src/main.rs b/crates/apps/nakui-explorer/src/main.rs
index 1fe882c..9ff22a4 100644
--- a/crates/apps/nakui-explorer/src/main.rs
+++ b/crates/apps/nakui-explorer/src/main.rs
@@ -30,6 +30,7 @@ use gpui::{
     SharedString, Window, WindowBounds, WindowOptions,
 };
 use nakui_core::event_log::{EventLog, LogEntry};
+use yahweh_meta_runtime::{preview_value, short_hash, short_uuid};
 
 const REFRESH_INTERVAL: Duration = Duration::from_secs(2);
 
@@ -378,35 +379,8 @@ impl Render for Explorer {
     }
 }
 
-fn short_uuid(id: &uuid::Uuid) -> String {
-    let s = id.to_string();
-    if s.len() > 8 {
-        s[..8].to_string()
-    } else {
-        s
-    }
-}
-
-fn short_hash(h: &[u8; 32]) -> String {
-    let mut s = String::with_capacity(8);
-    for b in h.iter().take(4) {
-        use std::fmt::Write;
-        let _ = write!(s, "{:02x}", b);
-    }
-    s
-}
-
-/// Renderiza un `serde_json::Value` en una sola línea limitada a `max`
-/// caracteres (para preview en la timeline, no para edición).
-fn preview_value(v: &serde_json::Value, max: usize) -> String {
-    let s = v.to_string();
-    if s.chars().count() <= max {
-        s
-    } else {
-        let truncated: String = s.chars().take(max - 3).collect();
-        format!("{truncated}...")
-    }
-}
+// Helpers `short_uuid`, `short_hash`, `preview_value` viven en
+// `yahweh_meta_runtime::format`. Se usan acá via el `use` de arriba.
 
 #[cfg(test)]
 mod tests {
@@ -472,34 +446,8 @@ mod tests {
         assert!(result.is_empty());
     }
 
-    #[test]
-    fn preview_value_truncates_long_strings() {
-        let v = serde_json::json!({"a": "x".repeat(200)});
-        let p = preview_value(&v, 30);
-        assert!(p.len() <= 30);
-        assert!(p.ends_with("..."));
-    }
-
-    #[test]
-    fn preview_value_keeps_short_strings_intact() {
-        let v = serde_json::json!({"a": 1});
-        let p = preview_value(&v, 30);
-        assert_eq!(p, "{\"a\":1}");
-    }
-
-    #[test]
-    fn short_uuid_takes_first_8_chars() {
-        let id = uuid::Uuid::parse_str("a1b2c3d4-e5f6-7890-abcd-ef1234567890").unwrap();
-        assert_eq!(short_uuid(&id), "a1b2c3d4");
-    }
-
-    #[test]
-    fn short_hash_takes_first_4_bytes_hex() {
-        let mut h = [0u8; 32];
-        h[0] = 0xaa;
-        h[1] = 0xbb;
-        h[2] = 0xcc;
-        h[3] = 0xdd;
-        assert_eq!(short_hash(&h), "aabbccdd");
-    }
+    // Tests de `short_uuid` / `short_hash` / `preview_value` viven
+    // en `yahweh-meta-runtime::format` tras la migración. Si esos se
+    // vuelven a romper, los tests específicos del crate runtime los
+    // capturan; acá no duplicamos.
 }
diff --git a/crates/modules/ui_engine/libs/meta-runtime/src/format.rs b/crates/modules/ui_engine/libs/meta-runtime/src/format.rs
index e827b9a..4e0c47b 100644
--- a/crates/modules/ui_engine/libs/meta-runtime/src/format.rs
+++ b/crates/modules/ui_engine/libs/meta-runtime/src/format.rs
@@ -52,6 +52,36 @@ pub fn short_uuid(id: &Uuid) -> String {
     id.to_string().chars().take(8).collect()
 }
 
+/// Hex string de los primeros 4 bytes de un hash SHA-256 (8
+/// caracteres). Útil para mostrar bundle/schema hashes en UI sin
+/// quemar pantalla con los 64 chars completos.
+pub fn short_hash(h: &[u8; 32]) -> String {
+    use std::fmt::Write;
+    let mut s = String::with_capacity(8);
+    for b in h.iter().take(4) {
+        let _ = write!(s, "{:02x}", b);
+    }
+    s
+}
+
+/// Renderea un `serde_json::Value` en una sola línea, truncado a
+/// `max` caracteres con `...` al final si excede. Para preview en
+/// timelines/cards/listas — NO para edición.
+///
+/// `max` es un upper-bound aproximado: el resultado nunca excede
+/// `max` chars, pero puede ser más corto si el value es chico.
+pub fn preview_value(v: &Value, max: usize) -> String {
+    let s = v.to_string();
+    if s.chars().count() <= max {
+        s
+    } else if max < 3 {
+        s.chars().take(max).collect()
+    } else {
+        let truncated: String = s.chars().take(max - 3).collect();
+        format!("{truncated}...")
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -105,6 +135,45 @@ mod tests {
         assert_eq!(value_to_input_text(&json!(42)), "42");
     }
 
+    #[test]
+    fn short_hash_takes_first_4_bytes_hex() {
+        let mut h = [0u8; 32];
+        h[0] = 0xaa;
+        h[1] = 0xbb;
+        h[2] = 0xcc;
+        h[3] = 0xdd;
+        assert_eq!(short_hash(&h), "aabbccdd");
+    }
+
+    #[test]
+    fn short_hash_zeros() {
+        let h = [0u8; 32];
+        assert_eq!(short_hash(&h), "00000000");
+    }
+
+    #[test]
+    fn preview_value_keeps_short_strings_intact() {
+        let v = json!({"a": 1});
+        assert_eq!(preview_value(&v, 30), "{\"a\":1}");
+    }
+
+    #[test]
+    fn preview_value_truncates_long_strings_with_ellipsis() {
+        let v = json!({"a": "x".repeat(200)});
+        let p = preview_value(&v, 30);
+        assert!(p.chars().count() <= 30);
+        assert!(p.ends_with("..."));
+    }
+
+    #[test]
+    fn preview_value_handles_max_smaller_than_ellipsis() {
+        // Edge case: max < 3 (no espacio para "..."). Devuelve
+        // los primeros `max` chars sin sufijo, sin panic.
+        let v = json!("xxxxxxxxxxxxxxxx");
+        let p = preview_value(&v, 2);
+        assert!(p.chars().count() <= 2);
+    }
+
     #[test]
     fn short_uuid_returns_first_8_chars() {
         let id = Uuid::parse_str("01ARZ3ND-EKTS-V4RR-FFQ6-9G5FAV000000").ok();
diff --git a/crates/modules/ui_engine/libs/meta-runtime/src/lib.rs b/crates/modules/ui_engine/libs/meta-runtime/src/lib.rs
index b470f5b..f179578 100644
--- a/crates/modules/ui_engine/libs/meta-runtime/src/lib.rs
+++ b/crates/modules/ui_engine/libs/meta-runtime/src/lib.rs
@@ -30,6 +30,9 @@ pub mod refs;
 
 pub use backend::{MetaBackend, WriteOutcome};
 pub use delta::{compute_clear_fields, compute_field_delta};
-pub use format::{human_label_for_record, render_value, short_uuid, value_to_input_text};
+pub use format::{
+    human_label_for_record, preview_value, render_value, short_hash, short_uuid,
+    value_to_input_text,
+};
 pub use parse::{infer_param_value, parse_field_value, resolve_param_value};
 pub use refs::validate_entity_refs;