From 520b7e7bd929d880d48d6cb43be8379dd17e13db Mon Sep 17 00:00:00 2001 From: OpenCodeMCP-BetaTest Date: Wed, 8 Apr 2026 01:44:43 +0200 Subject: [PATCH] =?UTF-8?q?fix(QA-018):=20prohibir=20m=C3=BAltiples=20wire?= =?UTF-8?q?s=20al=20mismo=20puerto=20de=20entrada?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - model.red: wire-exists-to-port? verifica si ya existe wire al puerto destino - model.red: add-wire wraps append+guard — reemplaza append directo en canvas - canvas.red: 5 puntos de add-wire usan add-wire en lugar de append directo - tests/test-model.red: 5 tests de regresión QA-018 QA-024 y QA-029 ya estaban corregidos en el código (verificado). Co-Authored-By: Claude Sonnet 4.6 --- src/graph/model.red | 36 ++++++++++++++++++++++++++++++++++ src/ui/diagram/canvas.red | 10 +++++----- tests/test-model.red | 41 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 5 deletions(-) diff --git a/src/graph/model.red b/src/graph/model.red index 084fe01..8e6f103 100644 --- a/src/graph/model.red +++ b/src/graph/model.red @@ -412,6 +412,42 @@ find-node-by-id: func [nodes id /local node] [ none ] +; ══════════════════════════════════════════════════ +; WIRE GUARD — previene múltiples wires al mismo puerto entrada (QA-018) +; ══════════════════════════════════════════════════ +; Regla absoluta #6: NUNCA permitir múltiples wires a un puerto de entrada. +; Esta función verifica si ya existe un wire conectado al mismo nodo+puerto destino. +; Devuelve true si EL wire YA EXISTE (para no añadirlo de nuevo). +wire-exists-to-port?: func [ + "Comprueba si ya existe un wire conectado al mismo puerto de entrada" + wires [block!] "Lista de wires a comprobar (model/wires o st/wires)" + to-id [integer!] "ID del nodo destino" + to-port [word!] "Nombre del puerto de entrada" + /local w +][ + foreach w wires [ + if all [ + (w/to-node = to-id) + (w/to-port = to-port) + ] [ + return true + ] + ] + false +] + +; Añade un wire a una lista solo si el puerto destino no tiene ya uno (QA-018). +; Usar en lugar de `append wires make-wire [...]` en canvas.red y tests. +add-wire: func [ + "Añade wire a la lista si el puerto destino aún no tiene uno (regla #6)" + wires [block!] "Lista de wires destino (model/wires o st/wires)" + wire [object!] "Wire creado con make-wire" +][ + unless wire-exists-to-port? wires wire/to-node wire/to-port [ + append wires wire + ] +] + ; make-fp-item y fp-value-text viven en src/ui/panel/panel.red (canónico). ; model.red no duplica lógica de Front Panel. diff --git a/src/ui/diagram/canvas.red b/src/ui/diagram/canvas.red index a3c16b6..9a5e8da 100644 --- a/src/ui/diagram/canvas.red +++ b/src/ui/diagram/canvas.red @@ -1891,7 +1891,7 @@ render-diagram: func [model canvas-width canvas-height /local canvas-face] [ actual-from-node: model/wire-src-struct/id ] ] - append wire-list make-wire compose [ + add-wire wire-list make-wire compose [ from: (actual-from-node) from-port: (actual-from-port) to: (hit-nd/id) @@ -1953,7 +1953,7 @@ render-diagram: func [model canvas-width canvas-height /local canvas-face] [ _out-t: port-out-type model/wire-src model/wire-port either _out-t = _sr/data-type [ model/broken-wire: none - append model/wires make-wire compose [ + add-wire model/wires make-wire compose [ from: (model/wire-src/id) from-port: (model/wire-port) to: (_st/id) to-port: (to-word _sr/name) ] @@ -1973,7 +1973,7 @@ render-diagram: func [model canvas-width canvas-height /local canvas-face] [ _out-t: port-out-type model/wire-src model/wire-port either _out-t = _sr/data-type [ model/broken-wire: none - append _st/wires make-wire compose [ + add-wire _st/wires make-wire compose [ from: (model/wire-src/id) from-port: (model/wire-port) to: -2 to-port: (to-word _sr/name) ] @@ -2158,7 +2158,7 @@ render-diagram: func [model canvas-width canvas-height /local canvas-face] [ remove-each _w model/wires [ all [_w/to-node = _fst/id _w/to-port = 'count] ] - append model/wires make-wire compose [ + add-wire model/wires make-wire compose [ from: (model/wire-src/id) from-port: (model/wire-port) to: (_fst/id) to-port: "count" ] @@ -2347,7 +2347,7 @@ render-diagram: func [model canvas-width canvas-height /local canvas-face] [ actual-from-node: model/wire-src-struct/id ] ] - append wire-list make-wire compose [ + add-wire wire-list make-wire compose [ from: (actual-from-node) from-port: (actual-from-port) to: (hit-result/1/id) diff --git a/tests/test-model.red b/tests/test-model.red index 91f3033..ea6dff1 100644 --- a/tests/test-model.red +++ b/tests/test-model.red @@ -298,4 +298,45 @@ assert "bundle gen-name bundle_1" (nb1/name = "bundle_1") assert "bundle gen-name bundle_2" (nb2/name = "bundle_2") assert "unbundle gen-name unbundle_1" (nu1/name = "unbundle_1") +; ── QA-018 — prohibir múltiples wires al mismo puerto de entrada ───────── + +reset-name-counters + +; Crear un diagrama con nodos con IDs manuales (make-diagram no tiene next-id) +demo-model: make-diagram "demo" + +n1: make-node compose [id: (1) type: 'add x: 100 y: 100] +n2: make-node compose [id: (2) type: 'add x: 250 y: 100] +n3: make-node compose [id: (3) type: 'add x: 400 y: 100] +n4: make-node compose [id: (4) type: 'add x: 550 y: 100] + +append demo-model/nodes n1 +append demo-model/nodes n2 +append demo-model/nodes n3 +append demo-model/nodes n4 + +; Crear 2 wires al mismo puerto de entrada (to-port = 'a) +; El segundo no debe ser añadido (regla absoluta #6 — add-wire lo rechaza) +add-wire demo-model/wires make-wire compose [ + from: (1) from-port: 'result to: (2) to-port: 'a +] +add-wire demo-model/wires make-wire compose [ + from: (3) from-port: 'result to: (2) to-port: 'a +] + +assert "QA-018: solo 1 wire al mismo puerto" (1 = length? demo-model/wires) +assert "QA-018: el primer wire se mantiene" (1 = demo-model/wires/1/from-node) + +; Crear 2 wires a puertos distintos del mismo nodo → ambos deben añadirse +add-wire demo-model/wires make-wire compose [ + from: (1) from-port: 'result to: (4) to-port: 'a +] +add-wire demo-model/wires make-wire compose [ + from: (2) from-port: 'result to: (4) to-port: 'b +] + +assert "QA-018: 3 wires en total" (3 = length? demo-model/wires) +assert "QA-018: primer wire a puerto 'a" (1 = demo-model/wires/2/from-node) +assert "QA-018: segundo wire a puerto 'b" (2 = demo-model/wires/3/from-node) + print "--- tests finalizados ---"