From f5987d9cfc47146e2a8b32a670cd38ccf9e89ed8 Mon Sep 17 00:00:00 2001 From: Sergio Date: Sat, 9 May 2026 23:38:25 +0000 Subject: [PATCH] =?UTF-8?q?refactor(yahweh):=20Fase=201=20=E2=80=94=20naku?= =?UTF-8?q?i-ui-schema=20=E2=86=92=20yahweh-meta-schema?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Primer paso del refactor yahweh. El schema de UI declarativa no tiene acoplamiento real con Nakui (sólo dep en serde/thiserror) — movemos a yahweh para que cualquier app metadata-driven lo use sin pasar por nakui. Mecánico: - git mv crates/modules/nakui/ui-schema → crates/modules/ui_engine/libs/meta-schema. - Crate name: nakui-ui-schema → yahweh-meta-schema. - Workspace members[] actualizado (sección yahweh, no nakui). - Consumers actualizados: brahman-cards (Cargo.toml + lib.rs + readers.rs), nakui-ui (Cargo.toml + main.rs). - Self-test (example_modules.rs): import + path rebase (5 niveles arriba ahora). Documental: - Doc del crate ahora dice "metainterfaz (yahweh meta-schema)" + "backend-agnostic" en filosofía. - Module.nakui_module_dir documentado como "path opaco al backend"; se conserva el nombre por compat con módulos ya escritos + serde alias "backend_module_dir" para futuro rename suave. Tests: 13 yahweh-meta-schema + 26 brahman-cards + 48 nakui-ui verdes. Workspace build verde. NO hace Fase 1: mover widgets a yahweh (Fase 2), trait MetaBackend (Fase 3), renombrar nakui_module_dir. Co-Authored-By: Claude Opus 4.7 (1M context) --- CHANGELOG.md | 73 +++++++++++++++++++ Cargo.lock | 24 +++--- Cargo.toml | 2 +- crates/apps/nakui-ui/Cargo.toml | 2 +- crates/apps/nakui-ui/src/main.rs | 2 +- crates/core/brahman-cards/Cargo.toml | 2 +- crates/core/brahman-cards/src/lib.rs | 4 +- crates/core/brahman-cards/src/readers.rs | 6 +- crates/modules/nakui/ui-schema/Cargo.toml | 14 ---- .../ui_engine/libs/meta-schema/Cargo.toml | 14 ++++ .../libs/meta-schema}/src/lib.rs | 60 ++++++++------- .../meta-schema}/tests/example_modules.rs | 11 ++- 12 files changed, 149 insertions(+), 65 deletions(-) delete mode 100644 crates/modules/nakui/ui-schema/Cargo.toml create mode 100644 crates/modules/ui_engine/libs/meta-schema/Cargo.toml rename crates/modules/{nakui/ui-schema => ui_engine/libs/meta-schema}/src/lib.rs (91%) rename crates/modules/{nakui/ui-schema => ui_engine/libs/meta-schema}/tests/example_modules.rs (89%) diff --git a/CHANGELOG.md b/CHANGELOG.md index af9ddca..c24edfd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,79 @@ ratio/diff ver `git show `. ## 2026-05-09 +### refactor(yahweh): Fase 1 — `nakui-ui-schema` → `yahweh-meta-schema` +Primer paso del refactor yahweh. El schema de UI declarativa +(entities, menús, listas, formularios, acciones) vivía bajo +`crates/modules/nakui/ui-schema/` y se llamaba `nakui-ui-schema` — +un nombre que sugería acoplamiento con Nakui que en realidad no +existe (el crate sólo depende de `serde`/`serde_json`/`thiserror`). +Lo movemos a yahweh para que sea consumible por cualquier app de UI +metadata-driven sin hacer pasar la dep "rara" por nakui. + +Cambios mecánicos: +- **`git mv`**: `crates/modules/nakui/ui-schema/` → + `crates/modules/ui_engine/libs/meta-schema/`. +- **Cargo.toml del crate movido**: + - `name = "nakui-ui-schema"` → `name = "yahweh-meta-schema"`. + - Description actualizada: "Yahweh — meta-schema: descriptores + declarativos de UI ... independiente del backend". +- **Workspace `Cargo.toml`**: la entry del members[] pasa de + `crates/modules/nakui/ui-schema` a + `crates/modules/ui_engine/libs/meta-schema` (en su sección + yahweh, no en la sección nakui). +- **`brahman-cards`**: + - Cargo.toml: dep path/name a `yahweh-meta-schema`. + - lib.rs: `pub use nakui_ui_schema::Module` → + `pub use yahweh_meta_schema::Module`. + - readers.rs: comment + doc-link al nuevo nombre. +- **`nakui-ui`**: + - Cargo.toml: dep path/name a `yahweh-meta-schema`. + - main.rs: `use nakui_ui_schema::{...}` → + `use yahweh_meta_schema::{...}`. +- **Self-test del crate movido** + (`tests/example_modules.rs`): `nakui_ui_schema` → `yahweh_meta_schema`, + y se rebasa el path del repo root (5 niveles arriba ahora, era 4). + +Cambios documentales: +- **Doc de crate** (`lib.rs`): "Schema declarativo de la metainterfaz + Nakui" → "Schema declarativo de la metainterfaz (yahweh + meta-schema)" + "backend-agnostic" en la filosofía. La sección + Persistencia universal pasa de "el runtime conecta cada vista al + `nakui_core::store::Store`" a un wording neutro: "el runtime que + consume este schema conecta vistas a su backend". +- **Doc del field `Module.nakui_module_dir`**: ahora marcado como + "path opaco al backend, lo interpreta el runtime concreto". Se + describe la convención actual de Nakui (nsmc.json + KCL + Rhai) + como ejemplo, no como contrato del schema. El nombre del campo + se mantiene por compat con módulos ya escritos; agregado + `#[serde(alias = "backend_module_dir")]` para que un futuro + rename no rompa los actuales. + +Tests: +- yahweh-meta-schema (crate movido): 13 tests propios siguen + verdes tras el path rebase. +- brahman-cards: 26/26 verdes (17 integration + 9 nickel). +- nakui-ui: 48/48 verdes. +- Workspace build verde. + +Lo que NO hace Fase 1: +- No mueve los widgets de UI (form/list/modal/EntityRef selector) + a yahweh — eso es Fase 2. +- No introduce un trait `MetaBackend` para desacoplar la lógica + de runtime de Nakui — eso es Fase 3. +- No renombra el field `nakui_module_dir`. Se hará cuando aparezca + un segundo backend que también lo necesite. + +**Pendientes** (orden): +1. **Fase 2**: extraer widgets render (form/list/modal/EntityRef + selector + helpers parse_field_value/render_value/etc.) a un + nuevo crate `yahweh-widget-meta-form` (o nombre similar). +2. **Fase 3**: trait `MetaBackend` + thin shell — `nakui-ui` queda + reducido a una impl de backend wireada a `nakui-core`. +3. **KCL → Nickel**: kcl_wrapper reemplazado por evaluación de + Nickel contracts. +4. **card.k eliminado** (REFERENCE ONLY). + ### feat(nakui-ui): migrar consumer al brazo unificado `brahman_cards::load_cards_from_dir` Primera consumer migration del brazo. `nakui-ui` ya no llama a `nakui_ui_schema::load_modules_from_dir` directamente — pasa por diff --git a/Cargo.lock b/Cargo.lock index d322400..542cb0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1238,13 +1238,13 @@ name = "brahman-cards" version = "0.1.0" dependencies = [ "brahman-card", - "nakui-ui-schema", "nickel-lang", "nouser-card", "serde", "serde_json", "thiserror 2.0.18", "ulid", + "yahweh-meta-schema", ] [[package]] @@ -6396,24 +6396,14 @@ dependencies = [ "brahman-cards", "gpui", "nakui-core", - "nakui-ui-schema", "serde_json", "tempfile", "uuid", + "yahweh-meta-schema", "yahweh-theme", "yahweh-widget-text-input", ] -[[package]] -name = "nakui-ui-schema" -version = "0.1.0" -dependencies = [ - "serde", - "serde_json", - "tempfile", - "thiserror 2.0.18", -] - [[package]] name = "nanorand" version = "0.7.0" @@ -12840,6 +12830,16 @@ dependencies = [ "yahweh-theme", ] +[[package]] +name = "yahweh-meta-schema" +version = "0.1.0" +dependencies = [ + "serde", + "serde_json", + "tempfile", + "thiserror 2.0.18", +] + [[package]] name = "yahweh-provider-fs" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index b0892c7..a4e8e12 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,6 +52,7 @@ members = [ "crates/modules/ui_engine/libs/core", "crates/modules/ui_engine/libs/theme", "crates/modules/ui_engine/libs/bus", + "crates/modules/ui_engine/libs/meta-schema", "crates/modules/ui_engine/libs/providers/fs", "crates/modules/ui_engine/libs/providers/sqlite", "crates/modules/ui_engine/widgets/tree", @@ -65,7 +66,6 @@ members = [ # modules/nakui/ — ERP matemático (nakui absorbido) # ============================================================ "crates/modules/nakui/core", - "crates/modules/nakui/ui-schema", # ============================================================ # modules/nouser/ — explorador de Mónadas (nuevo) diff --git a/crates/apps/nakui-ui/Cargo.toml b/crates/apps/nakui-ui/Cargo.toml index a0922d4..3a0c684 100644 --- a/crates/apps/nakui-ui/Cargo.toml +++ b/crates/apps/nakui-ui/Cargo.toml @@ -7,7 +7,7 @@ description = "Nakui — runtime GPUI de la metainterfaz: carga module.json desd [dependencies] nakui-core = { path = "../../modules/nakui/core" } -nakui-ui-schema = { path = "../../modules/nakui/ui-schema" } +yahweh-meta-schema = { path = "../../modules/ui_engine/libs/meta-schema" } brahman-cards = { path = "../../core/brahman-cards" } yahweh-widget-text-input = { path = "../../modules/ui_engine/widgets/text_input" } yahweh-theme = { path = "../../modules/ui_engine/libs/theme" } diff --git a/crates/apps/nakui-ui/src/main.rs b/crates/apps/nakui-ui/src/main.rs index 5ab9d27..3f6b979 100644 --- a/crates/apps/nakui-ui/src/main.rs +++ b/crates/apps/nakui-ui/src/main.rs @@ -37,7 +37,7 @@ use nakui_core::event_log::{ use brahman_cards::CardBody; use nakui_core::executor::Executor; use nakui_core::store::{MemoryStore, Store}; -use nakui_ui_schema::{ +use yahweh_meta_schema::{ Action, FieldKind, FieldSpec, FormView, ListView, Module, View, }; use serde_json::{json, Value}; diff --git a/crates/core/brahman-cards/Cargo.toml b/crates/core/brahman-cards/Cargo.toml index bc47950..ac16228 100644 --- a/crates/core/brahman-cards/Cargo.toml +++ b/crates/core/brahman-cards/Cargo.toml @@ -15,7 +15,7 @@ thiserror = { workspace = true } ulid = { workspace = true } brahman-card = { path = "../brahman-card" } nouser-card = { path = "../../modules/nouser/card" } -nakui-ui-schema = { path = "../../modules/nakui/ui-schema" } +yahweh-meta-schema = { path = "../../modules/ui_engine/libs/meta-schema" } nickel-lang = "2.0.0" [dev-dependencies] diff --git a/crates/core/brahman-cards/src/lib.rs b/crates/core/brahman-cards/src/lib.rs index bf65906..1a6a529 100644 --- a/crates/core/brahman-cards/src/lib.rs +++ b/crates/core/brahman-cards/src/lib.rs @@ -48,8 +48,8 @@ use serde_json::Value; use thiserror::Error; pub use brahman_card::Card as EnteCard; -pub use nakui_ui_schema::Module as UiModuleSpec; pub use nouser_card::MonadManifest; +pub use yahweh_meta_schema::Module as UiModuleSpec; /// Estructura canónica única que consumen los downstream del sistema /// (UI runtime, storage, DHT, wire). Cada formato input se proyecta @@ -59,7 +59,7 @@ pub use nouser_card::MonadManifest; /// (identidad legible + extensiones forward-compat); el body preserva /// el typing rico de cada dominio sin colapsarlos. // PartialEq se omite porque algunos body variants vienen de crates -// que no lo implementan (MonadManifest, nakui_ui_schema::Module). +// que no lo implementan (MonadManifest, yahweh_meta_schema::Module). // Si downstream necesita igualdad, comparar via JSON round-trip o // agregar PartialEq en los crates origen. #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/crates/core/brahman-cards/src/readers.rs b/crates/core/brahman-cards/src/readers.rs index 44b99cc..fbac969 100644 --- a/crates/core/brahman-cards/src/readers.rs +++ b/crates/core/brahman-cards/src/readers.rs @@ -114,11 +114,11 @@ impl CardReader for MonadJsonReader { } // ============================================================================ -// UiModule (nakui-ui-schema) +// UiModule (yahweh-meta-schema) // ============================================================================ -/// Reader para el shape JSON de los `module.json` de la UI Nakui -/// ([`nakui_ui_schema::Module`]). +/// Reader para el shape JSON de los `module.json` de la metainterfaz +/// ([`yahweh_meta_schema::Module`]). /// /// Heurística: tiene `entities` Y `views` Y `menu`. Es el shape más /// específico del repo, así que va primero en el orden default — si diff --git a/crates/modules/nakui/ui-schema/Cargo.toml b/crates/modules/nakui/ui-schema/Cargo.toml deleted file mode 100644 index e6627d2..0000000 --- a/crates/modules/nakui/ui-schema/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "nakui-ui-schema" -version.workspace = true -edition.workspace = true -license.workspace = true -description = "Nakui UI metainterface schema: módulos declaran menús, listas y formularios como datos (JSON); el runtime los carga y renderiza sin código compilado por módulo." - -[dependencies] -serde = { workspace = true } -serde_json = { workspace = true } -thiserror = { workspace = true } - -[dev-dependencies] -tempfile = { workspace = true } diff --git a/crates/modules/ui_engine/libs/meta-schema/Cargo.toml b/crates/modules/ui_engine/libs/meta-schema/Cargo.toml new file mode 100644 index 0000000..6fffb20 --- /dev/null +++ b/crates/modules/ui_engine/libs/meta-schema/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "yahweh-meta-schema" +version.workspace = true +edition.workspace = true +license.workspace = true +description = "Yahweh — meta-schema: descriptores declarativos de UI (entities, menús, listas, formularios, acciones) consumidos por widgets metainterfaz reusables. Independiente del backend: cualquier app que monte una UI dirigida por datos puede usarlo." + +[dependencies] +serde = { workspace = true } +serde_json = { workspace = true } +thiserror = { workspace = true } + +[dev-dependencies] +tempfile = { workspace = true } diff --git a/crates/modules/nakui/ui-schema/src/lib.rs b/crates/modules/ui_engine/libs/meta-schema/src/lib.rs similarity index 91% rename from crates/modules/nakui/ui-schema/src/lib.rs rename to crates/modules/ui_engine/libs/meta-schema/src/lib.rs index 82dfd29..2af599c 100644 --- a/crates/modules/nakui/ui-schema/src/lib.rs +++ b/crates/modules/ui_engine/libs/meta-schema/src/lib.rs @@ -1,22 +1,22 @@ -//! Schema declarativo de la metainterfaz Nakui. +//! Schema declarativo de la metainterfaz (yahweh meta-schema). //! -//! Cada **módulo** Nakui (customers, products, sales, ...) declara -//! aquí qué menús, vistas, listas y formularios expone, sin escribir -//! código GPUI ni Rust. El runtime ([`nakui-ui` crate]) lee estos -//! `module.json` desde un directorio y monta automáticamente la UI -//! correspondiente. +//! Cada **módulo** declara aquí qué menús, vistas, listas y +//! formularios expone, sin escribir código GPUI ni Rust. Cualquier +//! runtime de UI dirigida por datos (Nakui hoy, otros mañana) lo +//! carga y monta la UI correspondiente. //! //! ## Filosofía //! -//! - **UI como datos**: agregar un módulo = escribir un JSON. Ningún -//! recompile, ningún acoplamiento con el binario del runtime. -//! - **Persistencia universal**: el runtime conecta cada vista al -//! `nakui_core::store::Store` actual; los formularios escriben -//! ops por la pipeline normal de Nakui (executor + event log). -//! - **Schema primero, semántica después**: este crate sólo define -//! la *forma* de los manifests. Validación semántica -//! (referencias rotas a entities, campos faltantes, etc.) vive en -//! el runtime que lo carga, no acá. +//! - **UI como datos**: agregar un módulo = escribir un JSON o un +//! `.ncl`. Ningún recompile, ningún acoplamiento con el binario +//! del runtime. +//! - **Backend-agnostic**: este crate sólo describe la *forma* de +//! la UI. La conexión a un store/log/executor concretos vive en +//! el runtime que lo consume (ej: el meta-runtime de Nakui que +//! wirea esto a `nakui_core` + KCL post-checks). +//! - **Schema primero, semántica después**: validación semántica +//! (referencias rotas a entities, campos faltantes, etc.) vive +//! en el runtime que lo carga, no acá. //! //! ## Anatomía de un módulo //! @@ -47,7 +47,7 @@ use std::path::{Path, PathBuf}; use serde::{Deserialize, Serialize}; use thiserror::Error; -/// Manifiesto de un módulo de la metainterfaz Nakui. +/// Manifiesto de un módulo declarativo de UI. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Module { /// Identificador estable. Único dentro del directorio cargado. @@ -66,20 +66,28 @@ pub struct Module { #[serde(default)] pub entities: Vec, - /// Path a un módulo nakui-core (directorio con `nsmc.json` + - /// schemas KCL + scripts Rhai). Cuando está set, el runtime - /// carga un `Executor` para ese path y permite que las acciones - /// `Morphism { name }` despachen al pipeline real - /// (compute → log → apply). + /// Path opaco al backend que va a manejar este módulo. Lo + /// interpreta el runtime concreto (no este schema). + /// + /// Convención actual de Nakui: directorio con `nsmc.json` + + /// schemas KCL + scripts Rhai. Cuando está set, el runtime + /// Nakui carga un `Executor` para ese path y permite que las + /// acciones `Morphism { name }` despachen al pipeline real + /// (compute → log → apply). Otro backend puede ignorar este + /// campo o darle un significado distinto. /// /// Path resuelto relativo al directorio del `module.json` /// o absoluto. /// - /// Si es `None`, las acciones `Morphism` quedan deshabilitadas - /// (toast informativo al usuario). Las acciones `SeedEntity` - /// siguen funcionando sin esto — son altas administrativas que - /// no necesitan validación de manifest. - #[serde(default)] + /// Si es `None`, los backends que requieren manifest deberían + /// degradar (toast informativo, deshabilitar morphisms, etc.); + /// los `SeedEntity` siguen funcionando — son altas + /// administrativas que no necesitan validación de manifest. + /// + /// Nombre conservado por compat con módulos ya escritos. + /// Renombrar a `backend_module_dir` o similar si emerge un + /// segundo backend que también lo use. + #[serde(default, alias = "backend_module_dir")] pub nakui_module_dir: Option, /// Items del menú. Cada uno apunta a una key de `views`. Orden diff --git a/crates/modules/nakui/ui-schema/tests/example_modules.rs b/crates/modules/ui_engine/libs/meta-schema/tests/example_modules.rs similarity index 89% rename from crates/modules/nakui/ui-schema/tests/example_modules.rs rename to crates/modules/ui_engine/libs/meta-schema/tests/example_modules.rs index 1e552c1..230b10c 100644 --- a/crates/modules/nakui/ui-schema/tests/example_modules.rs +++ b/crates/modules/ui_engine/libs/meta-schema/tests/example_modules.rs @@ -4,13 +4,16 @@ //! corra `NAKUI_MODULES_DIR=examples/nakui-modules cargo run -p nakui-ui` //! va a obtener los 6 módulos cargados sin tocar nada. -use nakui_ui_schema::{load_modules_from_dir, FieldKind, View}; +use yahweh_meta_schema::{load_modules_from_dir, FieldKind, View}; fn examples_dir() -> std::path::PathBuf { // Tests corren desde el dir del crate; el repo root está dos // niveles arriba: crates/modules/nakui/ui-schema → repo. + // Tras el lift a yahweh, el crate vive en + // `crates/modules/ui_engine/libs/meta-schema`, así que el repo + // root queda 5 niveles arriba. let here = std::path::Path::new(env!("CARGO_MANIFEST_DIR")); - here.join("../../../..").join("examples/nakui-modules") + here.join("../../../../..").join("examples/nakui-modules") } #[test] @@ -50,8 +53,8 @@ fn sales_engine_declares_nakui_module_dir_and_morphism() { "sales_engine debería declarar nakui_module_dir" ); let has_morphism_view = sales.views.values().any(|v| match v { - nakui_ui_schema::View::Form(form) => { - matches!(form.on_submit, nakui_ui_schema::Action::Morphism { .. }) + yahweh_meta_schema::View::Form(form) => { + matches!(form.on_submit, yahweh_meta_schema::Action::Morphism { .. }) } _ => false, });