Phase 6: train a second LoRA for real Penpot UI design capability #5

Merged
aleleba merged 36 commits from agente-fase6-lora2-penpot into master 2026-08-04 21:36:07 -06:00
5 changed files with 682 additions and 647 deletions
Showing only changes of commit 18efe3fa5d - Show all commits
+128 -128
View File
File diff suppressed because one or more lines are too long
+50 -50
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+23 -1
View File
@@ -31,9 +31,16 @@ la interfaz lanza, y la excepción **aborta todo el `execute_code`**, no solo es
| Disparador | Mensaje verbatim |
| --- | --- |
| `text.textAlign = 'center'` | `Cannot add property textAlign, object is not extensible` |
| `text.color = '#...'` | `Cannot add property color, object is not extensible` |
Forma del mensaje, generalizable: `Cannot add property <nombre>, object is not extensible`.
**`text.color` (capturado en vivo, puerta 5 modo full, paso 6.4.25, prompts `g5-06-landing-pizzeria` y
`g5-01-boton-primario`, 2026-08-03):** el modelo asume que `Text` tiene una propiedad `color` de nivel
superior (analogía con CSS) en vez de usar `fills`. Es el mismo mecanismo que `textAlign` —el objeto
`Text` no es extensible— pero para una propiedad distinta, y hoy no hay ningún seed que lo enseñe (el
lint ya lo detecta como patrón prohibido, cero ejemplos de recuperación en el corpus).
La propiedad correcta para alineación horizontal de texto es **`align`**
(`'left' \| 'center' \| 'right' \| 'justify'`). Ver `penpot_api_docs.md` Captura 4.
@@ -48,9 +55,17 @@ composición completa, no solo el título.
| Disparador | Mensaje verbatim |
| --- | --- |
| `penpotUtils.importImage(url)` | `penpotUtils.importImage is not a function` |
| `penpot.importImage(url)` | `penpot.importImage is not a function` |
| `typography.setFont(font)` sobre un `LibraryTypography` | `t.setFont is not a function` |
Dos casos distintos, y la diferencia importa pedagógicamente:
**`penpot.importImage` (capturado en vivo, puerta 5 modo full y holdout, paso 6.4.25, 2026-08-03):**
variante distinta de la ya documentada `penpotUtils.importImage` — el modelo la invoca directamente
sobre el objeto `penpot` (no sobre `penpotUtils`), en 1 de los 10 prompts de la puerta 5 modo full
(`g5-03-card-producto`) y en 4 de los 60 del holdout, siempre en prompts que piden "una foto real
traída de una URL". El único seed de recuperación existente (grupo D) enseña la variante
`penpotUtils.importImage`, no ésta — de ahí que el modelo no generalizara la lección.
Tres casos distintos, y la diferencia importa pedagógicamente:
- `penpotUtils.importImage` **nunca existió**: no está en la Captura 1 de `penpot_api_docs.md`, ni
`import_image` está entre las herramientas MCP de este deployment (ver `data/schemas/penpot.json`).
@@ -76,6 +91,13 @@ llamadas de creación y de búsqueda pueden devolver `null`; usar el resultado s
| `const s = penpotUtils.findShapeById(page, id); s.x = 10` | `Cannot read properties of null (reading 'x')` |
| `const s = penpotUtils.findShapeById(idInexistente); return s.fills` | `Cannot read properties of null (reading 'fills')` |
| `const b = penpot.createBoolean('union', []); b.name = 'x'` | `Cannot set properties of null (setting 'name')` |
| `const r = penpot.createRectangle(); const f = r.addFlexLayout(); f.dir = 'row'` | `Cannot set properties of null (setting 'dir')` |
**`addFlexLayout()` sobre un `Rectangle` (capturado en vivo, puerta 5 modo full, `g5-02-navbar-flex`,
2026-08-03):** `addFlexLayout()` solo existe en `Board`. Llamarlo sobre un `Rectangle` (o sobre un
`Board` que ya tiene un layout asignado) devuelve `null` en silencio en vez de lanzar; el error real
aparece recién en la línea siguiente al intentar setear una propiedad del layout inexistente. Hay que
chequear el retorno de `addFlexLayout()` antes de usarlo, igual que con `createText()`.
Forma del mensaje, generalizable:
`Cannot read properties of null (reading '<prop>')` y
+468 -468
View File
File diff suppressed because one or more lines are too long