feat(0036d): promote kind-aware (Group → clear group_id)
NodeGroups window kind=Group ahora expone un boton SmallButton(TI_ARROW_UP) por fila que saca la entidad del grupo (group_id = NULL) y dispara reload del grafo. kind=Table mantiene el comportamiento de issue 0011. - entity_ops: nueva op `entity_clear_group_id(db, id)` idempotente. Si la columna group_id no existe (BD pre-0035a) retorna true como no-op. Falla solo si la entidad no existe o SQLite revienta. - views.cpp: extra columna "promote" en kind=Group, tooltip header diferenciado por kind, boton conectado a app.want_clear_group_id_entity. - main.cpp: handler que ejecuta entity_clear_group_id, marca windows como dirty, llama reload_after_mutation y loguea `[node_groups] promoted X out of group`. - gx-cli: flag `node update --clear-group-id` (booleano) y exposicion MCP en inputSchema + MCP_DISPATCH defaults para que el agente Echo pueda promover via tool calls. - tests: 3 nuevos CLI (clear, idempotente, combinable con --name) y 4 MCP (defaults, schema, dispatch end-to-end, idempotente). WSL: 102 passed (95 base + 7). Windows: 91 passed, 11 skipped (84 base + 7). Refs: issues/0036d-promote-kind-aware.md
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
---
|
||||
id: 0036d
|
||||
title: Promote en NodeGroups ramificado por kind (Table row vs Group child)
|
||||
status: done
|
||||
priority: high
|
||||
created: 2026-05-04
|
||||
parent: 0036
|
||||
depends_on: [0036b]
|
||||
---
|
||||
|
||||
## Objetivo
|
||||
|
||||
Boton "Promote" por fila en la NodeGroups window. La accion se
|
||||
ramifica por `kind`:
|
||||
|
||||
- **kind = Table** (DuckDB row): comportamiento actual del issue 0011
|
||||
— INSERT entity nueva apuntando a la fila DuckDB. Idempotente: si
|
||||
ya existe entidad para ese row_id, no duplica.
|
||||
- **kind = Group** (entidad hija): UPDATE clear group_id. La entidad
|
||||
sale del grupo y aparece como nodo libre en el canvas tras reload.
|
||||
|
||||
## Cambios
|
||||
|
||||
### Nueva op en `entity_ops` (Group promote)
|
||||
|
||||
```cpp
|
||||
// Saca la entidad de su grupo (group_id = NULL). No-op si ya estaba
|
||||
// fuera (group_id ya era NULL). Idempotente.
|
||||
bool entity_clear_group_id(const char* db_path, const char* entity_id);
|
||||
```
|
||||
|
||||
Tambien anyadir su pareja MCP en `gx-cli`:
|
||||
|
||||
```
|
||||
gx-cli node update <id> --clear-group-id
|
||||
```
|
||||
|
||||
(Para que el agente Echo pueda promover entidades del grupo via MCP.
|
||||
Argumento booleano que dispara la op directa, sin pasar por el flujo
|
||||
de --notes/--name.)
|
||||
|
||||
### Render del boton Promote
|
||||
|
||||
En la pintura de la window (en `views.cpp`), por cada fila visible
|
||||
mostrar un `SmallButton(TI_ARROW_UP)` con tooltip:
|
||||
|
||||
- kind = Table: `"Promote row to entity"` — comportamiento existente.
|
||||
- kind = Group: `"Promote out of group (move to canvas)"` — llama a
|
||||
la nueva op.
|
||||
|
||||
Tras la accion, marcar `g_app.want_reload = true` para que el grafo
|
||||
se refresque y la entidad reaparezca suelta.
|
||||
|
||||
### Tooltip del header
|
||||
|
||||
Cuando entras a la window, mostrar un texto suave indicando el
|
||||
comportamiento del Promote segun kind. Una sola linea, color text
|
||||
muted.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- Click promote en row de Group: la entidad pierde `group_id`
|
||||
(verificable por SQL), reload del grafo la muestra suelta
|
||||
colgando del source via la relacion existente.
|
||||
- Click promote en row de Group ya promovida (group_id ya NULL):
|
||||
no-op sin error.
|
||||
- Click promote en row de Table: comportamiento como hoy. Sin
|
||||
regresion en flow existente.
|
||||
- Tooltip diferenciado entre kinds.
|
||||
- Tests pytest:
|
||||
- `test_entity_clear_group_id_removes_membership`
|
||||
- `test_entity_clear_group_id_idempotent`
|
||||
- `test_gx_cli_node_update_clear_group_id` (CLI)
|
||||
- MCP regression: `clear_group_id` en defaults
|
||||
|
||||
## TBD
|
||||
|
||||
Branch `issue/0036d-promote-kind-aware`, merge `--no-ff` a master.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- Promote masivo (multi-select) — fase 2.
|
||||
- Re-agrupar por tipo (multi-select dentro de NodeGroups window) —
|
||||
fase 2.
|
||||
Reference in New Issue
Block a user