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 no
shippeaba ningún template.

3 templates basic bajo crates/core/brahman-cards/templates/:
- ente_basic.ncl: Card runtime mínima (Virtual + OneShot).
- monad_basic.ncl: Mónada con metadata vacía.
- ui_module_basic.ncl: descriptor UI con entities/menu/views vacíos.

Cada field override-able marcada `| default` (sin eso Nickel rebota
merge de strings/numbers no-iguales).

Nuevo `pub fn canonical_templates_dir() -> PathBuf` resuelve el dir
via CARGO_MANIFEST_DIR. Para distribución del binary standalone
queda como pending (include_dir! o convención de install path).

5 tests E2E que cubren los 3 templates con import+override, sanity
del default sin override, y existencia física del dir.

Tests brahman-cards: 26 → 31 (+5). Workspace intacto.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sergio
2026-05-10 09:30:16 +00:00
parent b05de24c24
commit df089f0585
6 changed files with 420 additions and 1 deletions
+73
View File
@@ -6,6 +6,79 @@ ratio/diff ver `git show <sha>`.
## 2026-05-10
### 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
no shippeaba ningún template. Ahora hay 3 templates basic (uno
por body kind del CardBody) bajo
`crates/core/brahman-cards/templates/`:
- **`ente_basic.ncl`** — Card runtime mínima: `payload="Virtual"`,
`supervision="OneShot"`, `schema_version=1`. Override típico:
`id` + `label`.
- **`monad_basic.ncl`** — agrupación semántica de archivos
(Mónada Nouser): metadata vacía, `dominant_lens="grid"` (lowercase
por convención serde rename_all). Override típico: `id`, `label`,
`members`, `cardinality`.
- **`ui_module_basic.ncl`** — descriptor UI con `entities=[]`,
`menu=[]`, `views={}`. Override típico: `id`, `label` y los
3 payloads.
Cada field override-able marcada `| default` (sin eso Nickel
rebota merge de strings/numbers no-iguales).
API nueva en `lib.rs`:
- **`pub fn canonical_templates_dir() -> PathBuf`**: devuelve el
directorio de templates del crate (resuelto via
`CARGO_MANIFEST_DIR`). Útil para apuntar el env
`BRAHMAN_CARDS_TEMPLATES_DIR` en runtime/tests sin hardcoding
del path.
- Doc explica que para distribución del binary standalone (cuando
emerja), incluir templates como recursos via `include_dir!` o
instalar el directorio junto al ejecutable.
5 tests E2E (`tests/templates.rs`) que cubren:
- `ente_basic` import + override `id`+`label` → Card body Ente
con `payload=Virtual` (default preserved).
- `monad_basic` import + override `id`+`label`+`cardinality`
Card body Monad con members=[] y summary="" (defaults).
- `ui_module_basic` import + override de `id`+`label`+menu+views
→ Card body UiModule con entities=[] (default).
- Sanity: import sin override → defaults `"TEMPLATE_ID"` /
`"TEMPLATE_LABEL"` pasan al wrapper sin error.
- Sanity: el path de `canonical_templates_dir()` apunta a un
directorio existente con los 3 archivos esperados.
Helper de test `with_canonical_templates(F)` setea/restaura el
env localmente; cada test single-thread-safe.
Tests suite brahman-cards: 26 → **31** verdes (+5). El resto del
workspace intacto.
Beneficio operativo:
- Un usuario que quiera declarar un Card nuevo puede empezar con
un override de 2 líneas (`id` + `label`) en lugar de copiar el
shape full desde cero.
- Templates auto-documentan la convención `| default` para que
copiar uno y agregar fields propios "just works" en merge.
- El brazo sigue siendo agnostic — los templates son sólo
archivos `.ncl` resueltos via el import resolver Nickel; nada
hardcoded en código Rust.
Limitaciones:
- No hay templates "ricos" tipo `crud_basic.ncl` que parametricen
por entity name. Nickel no expone funciones-templates de la
forma típica de templating engines; lo más cercano sería un
template con un field `entity_name | String` y references
internas via `me.entity_name`. Cuando aparezca el caso de uso
real (e.g., un módulo donde el patrón list+form es repetitivo),
se diseña el template paramétrico.
- `canonical_templates_dir()` resuelve via `CARGO_MANIFEST_DIR`
funciona en `cargo` (test/run/build) pero no para un binary
instalado fuera del workspace. Para release distribution la API
necesitará un fallback (resources embedded o convención de
install path).
### refactor(nakui-core): KCL → Nickel — `kcl_wrapper` reemplazado por evaluación in-process
Cierra el ciclo: el motor de validación de entities deja de
shellear el binario externo `kcl` y pasa a evaluar **Nickel