Phase 6.3.17: fix a harness fidelity bug and add a vibrancy metric

The first baseline measured production with only 2290 of the 16392
characters of the server's instructions block - 14%. The missing 86% is
exactly the API grounding: Core Shape Properties and Methods, Layout
Systems, Text Elements, and The penpot and penpotUtils Objects, which is
where insertChild, resize(), the layouts and penpotUtils are documented.

That was worth catching, because the discrepancy had a visible signature:
the measurement said production creates nothing, while the user's real
Claude Code session produced grey boxes, i.e. shapes greater than zero.
When a harness and reality disagree, the harness is the first suspect. In
phase 5 a low max_tokens manufactured an apparent regression the same way.

The gate now injects the full document, minus the trailing "You have hereby
read the Penpot High-Level Overview" line, which is framing of the tool
response rather than part of the instructions block and would otherwise
tell the model it had already read something.

The finding survives the fix. Across the five prompts measured cleanly
under the corrected condition, shapeCount is still zero on every one. So
the API invention is not an artefact of withholding documentation from the
model - it happens with the documentation present.

Also adds the vibrancy requirement the user raised as first-class scope:
given an ambiguous brief the model must choose and justify a palette rather
than ask or fall back to defaults. Neither distinctFillColors nor
placeholderGreys distinguishes a vibrant palette from a muted but
technically non-grey one, so four metrics are added: chromaticFills,
meanChromaticSaturation, paletteStructured (a dominant brand hue, an accent
at least 30 degrees away, and neutrals), and finalMessageListsHex, because
a palette chosen in silence cannot be adjusted by the user.

The saturation floor of 45 is derived, not asserted: measured over the 325
non-neutral fills of this phase's hand-authored corpus, median HSL
saturation is 75, p25 is 48 and p10 is 35. A floor of 45 sits just under
the first quartile and is cleared by 79% of those fills, so it is a floor
the target behaviour already clears rather than an aspiration. The
lightness band of 15 to 85 excludes near-blacks and near-whites, which can
compute as highly saturated while reading as neutral.

Gate prompt 6 becomes the user's literal failing sentence, and two
ambiguous-brief prompts are added. One of them had to be re-domained after
the disjointness check found it shared a 6-gram with a seed - the check
fails on a single shared shingle, which is what makes it useful.

Results so far are partial: prompts 1-5 measured cleanly, 6 has a timed-out
audit and 7-10 hit the MCP outage, so those get re-measured. Both runs are
kept, the 14% one renamed to record what it was.
This commit is contained in:
2026-07-30 18:38:24 +00:00
parent 5f0ddd962c
commit 8094183940
6 changed files with 7903 additions and 52 deletions
@@ -0,0 +1,77 @@
[OK] los 8 prompts son disjuntos de train/eval/seeds (7472 shingles de referencia)
[MCP] handshake ok con 'penpot-mcp-server'; tools: execute_code, high_level_overview, penpot_api_info, export_shape
[MCP] sonda de conectividad del plugin: {
"result": {
"gate5Probe": true
},
"log": ""
}
--- g5-01-boton-primario (baja) -> pagina gate5/prod-baseline/g5-01-boton-primario/20260730T175220Z
[MCP] fallo transitorio en 'tools/call' (intento 1/5): error de transporte contra el MCP de Penpot: ConnectionError. Reintento en 4s
[MCP] rehaciendo el handshake (la sesion pudo haber muerto)
[MCP] handshake ok con 'penpot-mcp-server'; tools: execute_code, high_level_overview, penpot_api_info, export_shape
[WARN] g5-01-boton-primario: se agotaron los 14 turnos sin mensaje final
[WARN] g5-01-boton-primario: export_shape no devolvio binario
score=0.0 (2/14) grises=0 prohibido=7 shapes=0 colores=0 textos=0
--- g5-02-navbar-flex (baja) -> pagina gate5/prod-baseline/g5-02-navbar-flex/20260730T175644Z
[WARN] g5-02-navbar-flex: se agotaron los 14 turnos sin mensaje final
[WARN] g5-02-navbar-flex: export_shape no devolvio binario
score=17.6 (3/17) grises=0 prohibido=0 shapes=0 colores=0 textos=0
--- g5-03-card-producto (media) -> pagina gate5/prod-baseline/g5-03-card-producto/20260730T175753Z
[WARN] g5-03-card-producto: se agotaron los 14 turnos sin mensaje final
[WARN] g5-03-card-producto: export_shape no devolvio binario
score=20.0 (3/15) grises=0 prohibido=0 shapes=0 colores=0 textos=0
--- g5-04-tokens-biblioteca (media) -> pagina gate5/prod-baseline/g5-04-tokens-biblioteca/20260730T175855Z
[WARN] g5-04-tokens-biblioteca: se agotaron los 14 turnos sin mensaje final
[WARN] g5-04-tokens-biblioteca: export_shape no devolvio binario
score=20.0 (3/15) grises=0 prohibido=0 shapes=0 colores=0 textos=0
--- g5-05-grid-tres-diferenciales (media) -> pagina gate5/prod-baseline/g5-05-grid-tres-diferenciales/20260730T175957Z
[WARN] g5-05-grid-tres-diferenciales: se agotaron los 14 turnos sin mensaje final
[WARN] g5-05-grid-tres-diferenciales: export_shape no devolvio binario
score=17.6 (3/17) grises=0 prohibido=0 shapes=0 colores=0 textos=0
--- g5-06-landing-pizzeria (alta) -> pagina gate5/prod-baseline/g5-06-landing-pizzeria/20260730T180102Z
[MCP] fallo transitorio en 'tools/call' (intento 1/5): error de transporte contra el MCP de Penpot: ConnectionError. Reintento en 4s
[MCP] rehaciendo el handshake (la sesion pudo haber muerto)
[MCP] handshake ok con 'penpot-mcp-server'; tools: execute_code, high_level_overview, penpot_api_info, export_shape
[WARN] g5-06-landing-pizzeria: export_shape no devolvio binario
score=0.0 (3/17) grises=0 prohibido=5 shapes=0 colores=0 textos=0
--- g5-07-onboarding-mobile (alta) -> pagina gate5/prod-baseline/g5-07-onboarding-mobile/20260730T180525Z
[WARN] g5-07-onboarding-mobile: se agotaron los 14 turnos sin mensaje final
[WARN] g5-07-onboarding-mobile: export_shape no devolvio binario
score=17.6 (3/17) grises=0 prohibido=0 shapes=0 colores=0 textos=0
--- g5-08-reparacion-grises (alta) -> pagina gate5/prod-baseline/g5-08-reparacion-grises/20260730T180627Z
[WARN] g5-08-reparacion-grises: se agotaron los 14 turnos sin mensaje final
[WARN] g5-08-reparacion-grises: export_shape no devolvio binario
score=26.7 (4/15) grises=0 prohibido=0 shapes=0 colores=0 textos=0
=== Puerta 5 -- calidad de diseno en Penpot (tag=prod-baseline) ===
prompt dif score pasa grises prohib shapes colores textos
g5-01-boton-primario baja 0.0 2/14 0 7 0 0 0
g5-02-navbar-flex baja 17.6 3/17 0 0 0 0 0
g5-03-card-producto media 20.0 3/15 0 0 0 0 0
g5-04-tokens-biblioteca media 20.0 3/15 0 0 0 0 0
g5-05-grid-tres-diferenciales media 17.6 3/17 0 0 0 0 0
g5-06-landing-pizzeria alta 0.0 3/17 0 5 0 0 0
g5-07-onboarding-mobile alta 17.6 3/17 0 0 0 0 0
g5-08-reparacion-grises alta 26.7 4/15 0 0 0 0 0
condiciones de aprobacion:
[NO ] score medio >= 65 -> 14.9
[NO ] veto limpio en 8/8 -> 6/8
[NO ] >= 6/8 prompts >= 60 -> 0/8
[NO ] landing de pizzeria >= 60 -> 0.0
VEREDICTO GLOBAL: NO APRUEBA
tiempo total: 15.1 min
resultados en data/gate5_results_prod-baseline.json
PNGs en data/gate5_png_prod-baseline/ (la puerta no borra nada: las paginas quedan para inspeccion humana)
+26 -48
View File
@@ -1,4 +1,5 @@
[OK] los 8 prompts son disjuntos de train/eval/seeds (7472 shingles de referencia)
[SYSTEM] documento completo del servidor: 16293 chars (247 lineas)
[OK] los 10 prompts son disjuntos de train/eval/seeds (7472 shingles de referencia)
[MCP] handshake ok con 'penpot-mcp-server'; tools: execute_code, high_level_overview, penpot_api_info, export_shape
[MCP] sonda de conectividad del plugin: {
"result": {
@@ -7,71 +8,48 @@
"log": ""
}
--- g5-01-boton-primario (baja) -> pagina gate5/prod-baseline/g5-01-boton-primario/20260730T175220Z
[MCP] fallo transitorio en 'tools/call' (intento 1/5): error de transporte contra el MCP de Penpot: ConnectionError. Reintento en 4s
[MCP] rehaciendo el handshake (la sesion pudo haber muerto)
[MCP] handshake ok con 'penpot-mcp-server'; tools: execute_code, high_level_overview, penpot_api_info, export_shape
[WARN] g5-01-boton-primario: se agotaron los 14 turnos sin mensaje final
--- g5-01-boton-primario (baja) -> pagina gate5/prod-baseline/g5-01-boton-primario/20260730T182503Z
[WARN] g5-01-boton-primario: export_shape no devolvio binario
score=0.0 (2/14) grises=0 prohibido=7 shapes=0 colores=0 textos=0
score=0.0 (2/14) grises=0 prohibido=5 shapes=0 colores=0 textos=0
--- g5-02-navbar-flex (baja) -> pagina gate5/prod-baseline/g5-02-navbar-flex/20260730T175644Z
--- g5-02-navbar-flex (baja) -> pagina gate5/prod-baseline/g5-02-navbar-flex/20260730T182608Z
[WARN] g5-02-navbar-flex: se agotaron los 14 turnos sin mensaje final
[WARN] g5-02-navbar-flex: export_shape no devolvio binario
score=17.6 (3/17) grises=0 prohibido=0 shapes=0 colores=0 textos=0
score=0.0 (3/17) grises=0 prohibido=1 shapes=0 colores=0 textos=0
--- g5-03-card-producto (media) -> pagina gate5/prod-baseline/g5-03-card-producto/20260730T175753Z
--- g5-03-card-producto (media) -> pagina gate5/prod-baseline/g5-03-card-producto/20260730T182706Z
[WARN] g5-03-card-producto: se agotaron los 14 turnos sin mensaje final
[WARN] g5-03-card-producto: export_shape no devolvio binario
score=20.0 (3/15) grises=0 prohibido=0 shapes=0 colores=0 textos=0
--- g5-04-tokens-biblioteca (media) -> pagina gate5/prod-baseline/g5-04-tokens-biblioteca/20260730T175855Z
[WARN] g5-04-tokens-biblioteca: se agotaron los 14 turnos sin mensaje final
--- g5-04-tokens-biblioteca (media) -> pagina gate5/prod-baseline/g5-04-tokens-biblioteca/20260730T182804Z
[WARN] g5-04-tokens-biblioteca: export_shape no devolvio binario
score=20.0 (3/15) grises=0 prohibido=0 shapes=0 colores=0 textos=0
score=0.0 (3/15) grises=0 prohibido=1 shapes=0 colores=0 textos=0
--- g5-05-grid-tres-diferenciales (media) -> pagina gate5/prod-baseline/g5-05-grid-tres-diferenciales/20260730T175957Z
[WARN] g5-05-grid-tres-diferenciales: se agotaron los 14 turnos sin mensaje final
--- g5-05-grid-tres-diferenciales (media) -> pagina gate5/prod-baseline/g5-05-grid-tres-diferenciales/20260730T182903Z
[WARN] g5-05-grid-tres-diferenciales: export_shape no devolvio binario
score=17.6 (3/17) grises=0 prohibido=0 shapes=0 colores=0 textos=0
score=23.5 (4/17) grises=0 prohibido=0 shapes=0 colores=0 textos=0
--- g5-06-landing-pizzeria (alta) -> pagina gate5/prod-baseline/g5-06-landing-pizzeria/20260730T180102Z
--- g5-06-landing-pizzeria (alta) -> pagina gate5/prod-baseline/g5-06-landing-pizzeria/20260730T183005Z
[MCP] fallo transitorio en 'tools/call' (intento 1/5): error de transporte contra el MCP de Penpot: ConnectionError. Reintento en 4s
[MCP] rehaciendo el handshake (la sesion pudo haber muerto)
[MCP] handshake ok con 'penpot-mcp-server'; tools: execute_code, high_level_overview, penpot_api_info, export_shape
[WARN] g5-06-landing-pizzeria: la auditoria fallo (g5-06-landing-pizzeria: auditoria: el MCP no devolvio JSON (texto): Tool execution failed: Error: Task 374cec0b-2e20-40bc-b58e-44e7ae20b6b0 timed out after 30 seconds)
[WARN] g5-06-landing-pizzeria: export_shape no devolvio binario
score=0.0 (3/17) grises=0 prohibido=5 shapes=0 colores=0 textos=0
score=0.0 (2/21) grises=0 prohibido=1 shapes=0 colores=0 textos=0
--- g5-07-onboarding-mobile (alta) -> pagina gate5/prod-baseline/g5-07-onboarding-mobile/20260730T180525Z
[WARN] g5-07-onboarding-mobile: se agotaron los 14 turnos sin mensaje final
[WARN] g5-07-onboarding-mobile: export_shape no devolvio binario
score=17.6 (3/17) grises=0 prohibido=0 shapes=0 colores=0 textos=0
--- g5-07-onboarding-mobile (alta) -> pagina gate5/prod-baseline/g5-07-onboarding-mobile/20260730T183529Z
[ERROR] g5-07-onboarding-mobile: g5-07-onboarding-mobile: setup de la pagina: el MCP no devolvio JSON (texto): Tool execution failed: Error: Task 98dda7fa-baed-4e2e-99f4-fa8bf33c1326 timed out after 30 seconds
[INFO] se guardan los 6 prompt(s) ya medidos y se sigue con el siguiente; el JSON queda marcado como parcial
--- g5-08-reparacion-grises (alta) -> pagina gate5/prod-baseline/g5-08-reparacion-grises/20260730T180627Z
[WARN] g5-08-reparacion-grises: se agotaron los 14 turnos sin mensaje final
[WARN] g5-08-reparacion-grises: export_shape no devolvio binario
score=26.7 (4/15) grises=0 prohibido=0 shapes=0 colores=0 textos=0
--- g5-08-reparacion-grises (alta) -> pagina gate5/prod-baseline/g5-08-reparacion-grises/20260730T183559Z
[ERROR] g5-08-reparacion-grises: g5-08-reparacion-grises: setup de la pagina: el MCP no devolvio JSON (texto): Tool execution failed: Error: Task 725a0fd0-3c6e-4b4b-bf1c-bb65776c4fb0 timed out after 30 seconds
[INFO] se guardan los 7 prompt(s) ya medidos y se sigue con el siguiente; el JSON queda marcado como parcial
=== Puerta 5 -- calidad de diseno en Penpot (tag=prod-baseline) ===
--- g5-09-brief-ambiguo-escuela (alta) -> pagina gate5/prod-baseline/g5-09-brief-ambiguo-escuela/20260730T183629Z
prompt dif score pasa grises prohib shapes colores textos
g5-01-boton-primario baja 0.0 2/14 0 7 0 0 0
g5-02-navbar-flex baja 17.6 3/17 0 0 0 0 0
g5-03-card-producto media 20.0 3/15 0 0 0 0 0
g5-04-tokens-biblioteca media 20.0 3/15 0 0 0 0 0
g5-05-grid-tres-diferenciales media 17.6 3/17 0 0 0 0 0
g5-06-landing-pizzeria alta 0.0 3/17 0 5 0 0 0
g5-07-onboarding-mobile alta 17.6 3/17 0 0 0 0 0
g5-08-reparacion-grises alta 26.7 4/15 0 0 0 0 0
condiciones de aprobacion:
[NO ] score medio >= 65 -> 14.9
[NO ] veto limpio en 8/8 -> 6/8
[NO ] >= 6/8 prompts >= 60 -> 0/8
[NO ] landing de pizzeria >= 60 -> 0.0
VEREDICTO GLOBAL: NO APRUEBA
tiempo total: 15.1 min
resultados en data/gate5_results_prod-baseline.json
PNGs en data/gate5_png_prod-baseline/ (la puerta no borra nada: las paginas quedan para inspeccion humana)
[ABORTA] el servidor MCP de Penpot no tiene ningun plugin conectado.
Abri el archivo de Penpot en el navegador, arranca el plugin del MCP y espera a
que quede conectado; recien ahi volve a correr la puerta. Sin plugin conectado no
tiene sentido gastar los 8 prompts.
Mensaje del servidor: Tool execution failed: Error: No Penpot plugin instances are currently connected. Please ensure the plugin is running and connected.
+3 -1
View File
@@ -3,6 +3,8 @@
{"id": "g5-03-card-producto", "dificultad": "media", "prompt": "Hacé una card de producto de 320 de ancho con una foto real traída de https://picsum.photos/seed/espresso/640/480, un título, una bajada de dos líneas, el precio destacado y un botón de compra. La foto tiene que ser la imagen de verdad: nada de rectángulos grises simulando la imagen."}
{"id": "g5-04-tokens-biblioteca", "dificultad": "media", "prompt": "Creá en la biblioteca local del archivo una paleta de 6 colores nombrados por rol y una escala tipográfica de 5 pasos, y después aplicá esos tokens a una muestra visible: un encabezado, un párrafo de apoyo y tres chips que muestren los colores aplicados desde la biblioteca."}
{"id": "g5-05-grid-tres-diferenciales", "dificultad": "media", "prompt": "Componé una sección de 3 diferenciales de 1140 de ancho resuelta con un grid de 3 columnas: cada columna con una figura geométrica propia a modo de ícono, un titular corto y dos líneas de texto de apoyo, todo con la misma alineación y respiración entre columnas."}
{"id": "g5-06-landing-pizzeria", "dificultad": "alta", "prompt": "hazme una landing page de una pizzería napolitana con colores vibrantes, de 1200 de ancho"}
{"id": "g5-06-landing-pizzeria", "dificultad": "alta", "prompt": "hazme una landing page de una pizzería con colores vibrantes", "brief": "ambiguo"}
{"id": "g5-07-onboarding-mobile", "dificultad": "alta", "prompt": "Diseñá una pantalla mobile de onboarding de 375x812 para una app de reservas: ilustración o figura de bienvenida arriba, titular, párrafo explicativo, indicador de tres pasos y dos acciones al pie (una primaria y una secundaria)."}
{"id": "g5-08-reparacion-grises", "dificultad": "alta", "prompt": "Este board está hecho enteramente de rectángulos grises y no tiene una sola línea de texto. Auditalo, definí una paleta y una escala tipográfica, y rehacelo hasta que sea una pantalla de verdad, con contenido legible y jerarquía visual.", "seed_board": {"nombre": "Wireframe sin disenar", "x": 0, "y": 0, "ancho": 960, "alto": 640, "gris": "#B1B2B5", "rectangulos": [{"nombre": "header", "x": 32, "y": 32, "ancho": 896, "alto": 88}, {"nombre": "hero", "x": 32, "y": 144, "ancho": 896, "alto": 208}, {"nombre": "card-1", "x": 32, "y": 376, "ancho": 288, "alto": 160}, {"nombre": "card-2", "x": 336, "y": 376, "ancho": 288, "alto": 160}, {"nombre": "card-3", "x": 640, "y": 376, "ancho": 288, "alto": 160}, {"nombre": "footer", "x": 32, "y": 560, "ancho": 896, "alto": 48}]}}
{"id": "g5-09-brief-ambiguo-escuela", "dificultad": "alta", "brief": "ambiguo", "prompt": "necesito la home de una escuela de música para chicos, que sea alegre; no tengo paleta ni logo, elegí vos"}
{"id": "g5-10-brief-ambiguo-notaria", "dificultad": "alta", "brief": "ambiguo", "prompt": "quiero el sitio de una notaría, que transmita seriedad; no te paso colores"}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff