diff --git a/data/schemas/PENPOT_API_VERIFIED.md b/data/schemas/PENPOT_API_VERIFIED.md index 94dfab6..b78cb94 100644 --- a/data/schemas/PENPOT_API_VERIFIED.md +++ b/data/schemas/PENPOT_API_VERIFIED.md @@ -236,19 +236,45 @@ fills = [{ fillOpacity: 1, fillColorGradient: { | Situación | Forma correcta | | --- | --- | | Padre **sin** layout | `parent.insertChild(parent.children.length, shape)` | -| Board **con** flex | `board.appendChild(shape)`, llamado **en orden visual** | +| Board **con** flex | `board.flex.appendChild(shape)` (preferido, orden visual) o `board.appendChild(shape)` (orden invertido, ver abajo) | | Board **con** grid | `board.grid.appendChild(shape, row, column)` — **1-based** | | Índice específico en flex | `board.insertChild(index, shape)`, recordando el orden invertido | | Reparentar | `newParent.appendChild(shape)` / `insertChild(...)` — quita del padre viejo, preserva x/y absolutos | -| **PROHIBIDO** | `board.flex.appendChild(shape)` — **está roto** | -**Orden invertido, verificado.** En `dir: 'column'` (y `'row'`), apendeando PRIMERO y luego SEGUNDO, el -array `children` queda `[SEGUNDO, PRIMERO, ...]`: `board.appendChild` inserta **al frente**. Por eso hay -que llamarlo en orden visual. +**ACTUALIZACIÓN (2026-08-04, hallazgo 54 de la Fase 6, ronda correctiva 6.4.25c): `board.flex.appendChild(shape)` +NO está roto — verificado en vivo, repetidas veces, contra Penpot 2.16.2.** Es una función real, de +aridad 1, distinta de `board.appendChild` (no es un alias: `board.flex.appendChild !== board.appendChild`, +`board.flex !== board`), que no lanza ninguna excepción y agrega el hijo correctamente, con `layoutChild` +funcionando bien después. La afirmación anterior de que estaba roto **nunca tuvo un error real capturado** +en `penpot_errors.md` (a diferencia de todos los demás comportamientos rotos documentados en este archivo, +que sí lo tienen). Su origen real: el `high_level_overview()` del servidor MCP (capturado verbatim en +`penpot_api_docs.md`, líneas 131-135) le dice al modelo, en mayúsculas y marcado `CRITICAL`, que +**`board.flex.appendChild` está BROKEN y que NUNCA lo use** — instrucción que la sesión original de +diagnóstico tomó como cierta sin verificarla empíricamente con un intento real de romperlo. Esa misma +sección de la doc mezcla además un bug real y distinto (el ejemplo de **grid** con 3 argumentos aparece +escrito como `board.flex.appendChild(shape, row, column)` en vez de `board.grid.appendChild(...)`, ver +`penpot_api_docs.md` línea 143), lo cual reforzó la confusión. **La documentación servida en vivo por el +MCP de Penpot está, en este punto, objetivamente equivocada** (verificado empíricamente, repetidas veces, +el 2026-08-04 contra Penpot 2.16.2) — o el comportamiento se arregló en Penpot después de escribirse esa +documentación, sin actualizarla. Cualquier seed nuevo que muestre al modelo leyendo `high_level_overview` +debería, idealmente, incluir el razonamiento de que esa afirmación puntual sobre `flex.appendChild` no es +confiable y de que hay que verificar con el runtime en vez de creerle a esa línea específica — el mismo +patrón de "la lista de tools es autoritativa, la prosa no" ya usado en el grupo C para `import_image`. + +**Orden invertido, verificado — y por qué `board.flex.appendChild` es preferible.** En `dir: 'column'` +(y `'row'`), apendeando PRIMERO y luego SEGUNDO con `board.appendChild`, el array `children` queda +`[SEGUNDO, PRIMERO, ...]`: `board.appendChild` inserta **al frente**, así que hay que llamarlo en orden +inverso al visual para compensar. `board.flex.appendChild`, en cambio, preserva el **orden visual normal** +de las llamadas (PRIMERO, SEGUNDO, ...) — no necesita el truco de inversión. Para boards con flex, **usar +`board.flex.appendChild(shape)` en orden visual directo es la forma más simple y menos propensa a error.** +`board.appendChild` sigue siendo válido (y necesario para reparentar hacia boards sin layout, o cuando el +código ya maneja el truco de inversión de forma consistente), pero ya no es la única opción recomendada. **La regla absoluta "nunca `appendChild`" que enseñan los seeds viejos es INCORRECTA.** El overview la califica él mismo (`except in flex layout boards`) y la sección de Flex Layout **manda** usar -`board.appendChild`. La política correcta es condicional, y hay 5 seeds del grupo A3 dedicados a ella. +`board.appendChild`. La política correcta es condicional, y hay 5 seeds del grupo A3 dedicados a ella — +esos seeds siguen siendo correctos sobre el comportamiento de `board.appendChild` (el orden invertido es +real), pero ya no reflejan que `board.flex.appendChild` sea una alternativa rota. **Z-order:** el orden del array `children`. Métodos: `bringToFront()`, `sendToBack()`, `bringForward()`, `sendBackward()`, `setParentIndex(index)` (0-based). @@ -269,7 +295,7 @@ califica él mismo (`except in flex layout boards`) y la sección de Flex Layout | `topPadding`/`rightPadding`/`bottomPadding`/`leftPadding`, `verticalPadding`/`horizontalPadding` | ✅ | | | `horizontalSizing` / `verticalSizing` | ⚠️ | `'fill'` \| `'auto'` \| `'fit-content'`. **`'auto'` se lee de vuelta como `'auto'` pero el board NO crece** (penpot#8520). Hay que `board.resize()` a mano | | `wrap` | ✅ | `'wrap'` \| `'nowrap'` | -| `flex.appendChild` | ❌ | **Roto.** Usar `board.appendChild` | +| `flex.appendChild` | ✅ | **Funciona** (verificado 2026-08-04, hallazgo 54). Aridad 1, preserva orden visual — preferible a `board.appendChild` para insertar en boards con flex | ### Grid @@ -401,8 +427,7 @@ en prosa. | --- | --- | | `findShapeById(` con coma en los argumentos | Aridad 1; la forma de 2 devuelve `null` en silencio | | `.layout` en una línea sin `shapeStructure` | La propiedad no existe | -| `.flex.appendChild(` | Roto | -| `appendChild(` sobre un receptor sin evidencia de flex | Solo es correcto en boards con flex | +| `appendChild(` sobre un receptor sin evidencia de flex | Solo es correcto en boards con flex (`board.flex.appendChild` o `board.appendChild`) | | `fontSize`/`fontWeight`/`lineHeight`/`letterSpacing` `= ` | Son strings | | `textAlign =` | Lanza y mata el `execute_code` | | `importImage`, `import_image`, `createImage(`, `filePath` | No existen en este deployment | diff --git a/scripts/05_build_dataset.py b/scripts/05_build_dataset.py index b82a2ed..aa3a6a2 100644 --- a/scripts/05_build_dataset.py +++ b/scripts/05_build_dataset.py @@ -302,7 +302,6 @@ def apply_prefix(content, prefix, mode): FORBIDDEN_PATTERN_NAMES = [ "findShapeById con 2 argumentos", "propiedad .layout inexistente", - "flex.appendChild", "import_image / importImage / createImage / filePath", "textAlign", "typography.setFont", diff --git a/scripts/07_build_lora2_mix.py b/scripts/07_build_lora2_mix.py index 115357b..bf6d3fb 100644 --- a/scripts/07_build_lora2_mix.py +++ b/scripts/07_build_lora2_mix.py @@ -128,7 +128,6 @@ N_PENPOT_BASICOS = 50 FORBIDDEN_REPLAY = [ ("findShapeById 2 args", re.compile(r"findShapeById\s*\([^)]*,")), (".layout inexistente", re.compile(r"\.layout\b(?!Child|Cell)")), - ("flex.appendChild", re.compile(r"\.flex\s*\.\s*appendChild\s*\(")), ("createText sin argumento", re.compile(r"createText\s*\(\s*(''|\"\")?\s*\)")), ("textAlign", re.compile(r"\.textAlign\s*=")), ("importImage/createImage/filePath", re.compile(r"\b(importImage|import_image|createImage\s*\(|filePath)\b")), diff --git a/scripts/07_lint_penpot_code.py b/scripts/07_lint_penpot_code.py index 71253e2..2d13335 100644 --- a/scripts/07_lint_penpot_code.py +++ b/scripts/07_lint_penpot_code.py @@ -85,11 +85,6 @@ FORBIDDEN = [ "La clave `layout` que ves en la salida de shapeStructure() es del OUTPUT del helper, " "no una propiedad del shape.", ), - ( - "flex.appendChild", - re.compile(r"\.flex\s*\.\s*appendChild\s*\("), - "board.flex.appendChild esta roto. Usar board.appendChild(shape), en orden visual.", - ), ( "fontSize/fontWeight/lineHeight/letterSpacing numerico", re.compile(r"\.(fontSize|fontWeight|lineHeight|letterSpacing)\s*=\s*-?\d"), diff --git a/scripts/35_gate5_penpot_design.py b/scripts/35_gate5_penpot_design.py index f3f9cd4..5df379f 100644 --- a/scripts/35_gate5_penpot_design.py +++ b/scripts/35_gate5_penpot_design.py @@ -184,7 +184,6 @@ LINT = load_lint_module() VETO_PATTERN_NAMES = { "findShapeById con 2 argumentos", "propiedad .layout inexistente", - "flex.appendChild", "fontSize/fontWeight/lineHeight/letterSpacing numerico", "import_image / importImage / createImage / filePath", }