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:
@@ -230,6 +230,12 @@ def cmd_node_update(args) -> None:
|
||||
_die(f"bad tags: {e}")
|
||||
sets.append("tags = ?")
|
||||
params.append(json.dumps(tags))
|
||||
# Issue 0036d: --clear-group-id saca la entidad de su grupo
|
||||
# (UPDATE entities SET group_id = NULL). Booleano sin value param;
|
||||
# combinable con otros sets.
|
||||
if getattr(args, "clear_group_id", False):
|
||||
sets.append("group_id = NULL")
|
||||
_log("node_update", f"clear_group_id=true id={args.id}")
|
||||
if not sets:
|
||||
_die("no fields to update")
|
||||
|
||||
@@ -829,7 +835,9 @@ MCP_TOOLS = [
|
||||
"notes": {"type": "string", "description": "Texto del panel Note. Reemplaza el contenido salvo que append_notes=true."},
|
||||
"append_notes": {"type": "boolean", "default": False,
|
||||
"description": "Si true, anyade `notes` al final con doble newline en vez de reemplazar."},
|
||||
"tags": {"type": "string", "description": "JSON array literal o CSV 'a,b,c'"}},
|
||||
"tags": {"type": "string", "description": "JSON array literal o CSV 'a,b,c'"},
|
||||
"clear_group_id": {"type": "boolean", "default": False,
|
||||
"description": "saca la entidad del grupo (group_id = NULL)"}},
|
||||
"required": ["id"]}},
|
||||
{"name": "node_delete",
|
||||
"description": "Borra la entidad y todas sus relaciones. Irreversible. Confirmar con el usuario antes.",
|
||||
@@ -931,7 +939,8 @@ MCP_DISPATCH = {
|
||||
"node_update": (cmd_node_update, {"name": None, "type": None,
|
||||
"status": None, "description": None,
|
||||
"notes": None, "append_notes": False,
|
||||
"tags": None}),
|
||||
"tags": None,
|
||||
"clear_group_id": False}),
|
||||
"node_delete": (cmd_node_delete, {}),
|
||||
"rel_create": (cmd_rel_create, {"name": None}),
|
||||
"rel_delete": (cmd_rel_delete, {}),
|
||||
@@ -1086,6 +1095,11 @@ def main() -> None:
|
||||
"en vez de reemplazarlas (separador: doble newline).")
|
||||
sp.add_argument("--tags",
|
||||
help='JSON array o "tag1,tag2" CSV')
|
||||
sp.add_argument("--clear-group-id", dest="clear_group_id",
|
||||
action="store_true",
|
||||
help="saca la entidad del grupo (UPDATE group_id = NULL). "
|
||||
"Idempotente; combinable con otros campos. "
|
||||
"Issue 0036d.")
|
||||
sp.set_defaults(fn=cmd_node_update)
|
||||
sp = n.add_parser("list")
|
||||
sp.add_argument("--type")
|
||||
|
||||
Reference in New Issue
Block a user