# Review feat/geometry @ 33369790 - Fecha: 2026-10-22T15:26:15+00:00 - Verdict: **FAIL** - Build rama: PASS - Build merge: SKIP - Acción: review-fail - Modo: auto-merge ## Detalle > reviewer · deepseek-v4.1-flash ✱ Glob "demo/vinted-mock/viewer3d/**/*" 0 matches ✱ Glob "**/*.patch" 0 matches > reviewer · deepseek-v4.1-flash ✱ Glob "**/*" 50 matches > reviewer · deepseek-v4.1-flash ✱ Glob "demo/vinted-mock/viewer3d/**" 0 matches ✱ Glob "**/vendor/**" 0 matches > reviewer · deepseek-v4.1-flash ✱ Glob "**/.gitignore" 0 matches ✱ Grep "viewer3d" in . · 0 matches > reviewer · deepseek-v4.1-flash ✱ Grep "ankle|crotch_y_cm|bust_y_cm" in . · 0 matches ✱ Glob "packages/fit-engine/**" 3 matches > reviewer · deepseek-v4.1-flash ✗ Grep "landmark" failed Error: Search path does not exist: /srv/segunda-piel/review-src/packages/fit-engine/MANNEQUIN-PIPELINE.md ✱ Glob "packages/fit-engine/*.md" 0 matches > reviewer · deepseek-v4.1-flash ✱ Grep "viewer|fit-engine|probadores" in README.md · 1 match ✱ Grep "probadores-virtuales-3d" in . · 0 matches > reviewer · deepseek-v4.1-flash VERDICT: FAIL SUMMARY: El diff del viewer3d es funcionalmente ambicioso pero introduce varios riesgos no verificables (imports eliminados, NaN potencial, fusión de geometrías que puede fallar) y solo toca demo/docs; no hay blockers de seguridad ni de infra, pero hay un cambio de comportamiento del cuerpo del anuncio que sí puede romper la demo. FINDINGS: - [risk] demo/vinted-mock/viewer3d/app.js:1 — se elimina el import `superellipsePoint` y las constantes `FABRIC_COLOR`/`BAND_COLOR` junto con `updateUnderwear`/`sampleRingAtY`/`createBand`/`createStrap`; si queda algún uso de `superellipsePoint` en las ~2000 líneas no incluidas en el diff, el módulo revienta con ReferenceError y el viewer no arranca. Verificar con `grep superellipsePoint demo/vinted-mock/viewer3d/app.js`. - [risk] demo/vinted-mock/viewer3d/app.js:~1250 (nuevo `ankleNorm`) — `body.landmarks.ankle_y_cm / body.profile.height_cm` sin fallback ni comprobación; a diferencia de `bust_y_cm ?? chest_y_cm`, aquí no hay protección. Si `ankle_y_cm` no existe en `buildBody()`, `ankleNorm` es NaN → `sample(NaN)` devuelve `cx` NaN → `dx` NaN → todos los vértices del pie a NaN y el maniquí desaparece sin error de consola aparte de la malla invisible. Añadir guarda o usar `Number.isFinite`. - [risk] demo/vinted-mock/viewer3d/app.js:~610 (`mergeBodyGeometry`) — `mergeGeometries([body, ...details], false)` exige que todas las primitivas tengan **exactamente** los mismos atributos (position/normal/uv/skinIndex/skinWeight/tangent...). Si el GLB trae manos/pies con un set distinto (p. ej. sin `uv` o con `tangent`), devuelve `null` y el `throw` lleva al estado de error → demo con "No se ha podido cargar el maniquí". Confirmar por sexo (femenino y masculino) y añadir fallback a la malla sin fusionar. - [risk] demo/vinted-mock/viewer3d/app.js:~1440-1500 (suavizado de normales) — 80 pasadas sobre ~100k vértices con `normals.array.slice()` en cada pasada: ~80 asignaciones de ~1,2 MB por `deform()`, más 14 pasadas de posición pecho y 8 de pubis. `deform()` corre en cada `input` de slider (rAF) → jank probable de varias décimas por frame en la demo. Reducir pasadas, reutilizar buffer y salir antes si el perfil no cambia. - [risk] demo/vinted-mock/viewer3d/app.js:~1240 — `fillBoundaryHoles` recorre todos los bordes abiertos (no solo areola/boca). Cualquier costura UV que sobreviva al `weldGeometryIndex` (índices no soldados por >0,1 mm) se tapa con abanicos de triángulos; el tope `loop.length <= 256` evita lo peor, pero el relleno de un borde abierto largo puede generar geometría visible/artefactos. QA visual obligatorio en ambos GLB y en talla Plus. - [risk] demo/vinted-mock/viewer3d/app.js (import nuevo) — `import { mergeGeometries } from 'three/addons/utils/BufferGeometryUtils.js'` depende de que `vendor/addons/utils/BufferGeometryUtils.js` exista y el importmap exponga `three/addons/`. `GLTFLoader` ya necesita ese archivo por ruta relativa, así que es probable que exista, pero el README de `vendor/` no lo lista; verificar que el preview bajo `/preview//viewer/` carga el módulo (404 aquí tumba el viewer entero). - [risk] demo/vinted-mock/viewer3d/app.js:~1350 (`collectBodyParts`) — la heurística `box.max.y < min.y + height*0.65` para fusionar "manos y pies" es frágil: en A-pose las manos están hacia el 45–55%, pero cualquier primitiva baja extra (o un GLB con distinto origen) se fusiona o se pierde silenciosamente. No hay test ni aserción sobre el número de detalles fusionados. - [risk] demo/vinted-mock/viewer3d/app.js:~1200 (`sameProfile`) + `readListing` — `baselineProfile` se fija siempre al `listing.body`, pero el perfil puede venir de `localStorage` (Mi maniquí). Con un maniquí personal guardado, `shapeStrength` pasa a 1 de inmediato y se aplica la deformación completa (con `softScale` shrink 0.3–0.35) sobre un cuerpo que no es el del anuncio; conviene QA con perfil guardado y preset Plus. - [risk] demo/vinted-mock/viewer3d/app.js — se elimina la rama `?raw` de `deform()`; si el equipo la usa como modo de depuración/QA (o algún enlace del deck/vídeo la referencia), deja de funcionar. Verificar referencias a `raw` en `deck/`, `video/` y `docs/agent-notes/demo-script.md`. - [risk] demo/vinted-mock/viewer3d/index.html / app.js — se mueven `verdict-detail`, `zones`, `confidence-*`, `missing`, `body-line`, `source-note` y `presets` dentro de `
`; los IDs se conservan y `updateFit()`/`syncSliders()` siguen funcionando, pero el veredicto ya no muestra holgura sin abrir "Especificaciones". Es un cambio de guion de demo: `docs/pitch.md` y `docs/PLAN.md` §13 siguen diciendo "holgura por zona" en la vista principal. Actualizar el guion o el ledger antes de presentar. - [risk] docs/PLAN.md:2 / docs/STATS.md:42 / docs/pitch.md:117 — se añaden decenas de cifras de mercado con fechas futuras (Doppl cerrado 30-abr-2026, ChatGPT try-on oct-2026, Zara dic-2025, Tesco sep-2026) y múltiples "no encontramos". No son verificables desde el repo y el propio `AGENTS.md` exige que cada claim del pitch esté en el ledger REAL/DEMO/ROADMAP; al menos las afirmaciones de competencia deberían marcarse como [M] de forma consistente y con fecha de corte. Riesgo reputacional en Q&A, no de build. - [risk] docs/PLAN.md:~230 — el ahorro se etiqueta ahora como "estimación propia", pero el deck (slide 8 de `docs/pitch.md`) sigue narrando "cada devolución cuesta hasta dos tercios del precio" sin el caveat de estimación en el pie. Coherencia ledger. - [risk] probadores-virtuales-3d.txt → docs/probadores-virtuales-3d.txt — rename 100% sin cambios; correcto, pero el archivo no está en el contexto y no se puede comprobar el límite de 5 MB por asset del `AGENTS.md`. Verificar tamaño antes del merge. - [ok] Sin cambios en `.github/`, `deploy/`, `scripts/` ni `AGENTS.md`; sin `package.json`/lockfile ni dependencias npm nuevas; sin secretos, tokens ni datos personales en el diff; las rutas de assets del viewer no se hardcodean a `/`, así que el base `/preview//viewer/` no se rompe por el diff. Nota de proceso: el máximo de pasos del agente se alcanzó durante la verificación y el checkout de revisión no incluye `demo/vinted-mock/viewer3d/` ni `packages/fit-engine/src/body.ts`, así que todo lo anterior se evalúa solo sobre el diff. Antes de mergear: confirmar `superellipsePoint` sin usos, existencia de `vendor/addons/utils/BufferGeometryUtils.js`, `ankle_y_cm` en los landmarks, y QA visual de `mergeGeometries` en ambos sexos y en preset Plus.