# Review feat/cloth-v2 @ c911e922 - Fecha: 2026-10-22T16:24:06+00:00 - Verdict: **FAIL** - Build rama: PASS - Build merge: SKIP - Acción: review-fail - Modo: auto-merge ## Detalle > reviewer · deepseek-v4.1-flash ✗ Read stat.txt failed Error: File not found: /srv/segunda-piel/review-src/stat.txt ✱ Glob "**/*" 54 matches > reviewer · deepseek-v4.1-flash ✱ Grep "torso|sample\(" in docs/agent-notes/3d-procedural.md · 2 matches ✱ Glob "**/viewer3d/*" 0 matches > reviewer · deepseek-v4.1-flash VERDICT: FAIL SUMMARY: La rama cambia el builder de prendas en producción (tops al legacy, jeans/falda/vestido a la V2) pero deja un archivo crítico re-codificado con mojibake, un `null`-deref en la ruta de vaqueros y una dependencia de API (`model.torso.sample`) que no aparece en el diff. FINDINGS: - [blocker] demo/vinted-mock/viewer3d/garment-builder.js:1 — el archivo entero se ha reescrito cambiando la codificación: se añade BOM (U+FEFF) y todos los acentos se corrompen (`paramétricas`, `colisión`, `caída`, `triángulos`), con pérdida de caracteres (`patr�n` = U+FFFD, irrecuperable). Afecta a texto de UI: `LISTING_STYLE['vintage-leather-jacket'].label` pasa de `'marrón'` a `'marrón'`. Regresión visible en es-ES + diff de 570 líneas irrevisable. - [blocker] demo/vinted-mock/viewer3d/garment-builder-v2.js:752 — `base = makeJeansPatch(...); geometry = base.geometry;`: `makeJeansPatch` devuelve `null` si `extractPatch` no conserva triángulos, así que se lanza `TypeError` antes del guard `if (!geometry) return null` (que queda inalcanzable para jeans). Los vaqueros son justo la ruta nueva en la demo (`levis-501-w32`, `weekday-mom-jeans-38`): un fallo del parche tumba el viewer en vez de degradar. - [blocker] demo/vinted-mock/viewer3d/garment-builder-v2.js:196 — la V2 asume `model.torso.sample()`, `model.baseHeight` y `model.legs[].sample()` (también línea 201). Esa API no se introduce en este diff (`body-engine.js` no está en el parche) y contradice el uso existente del mismo archivo, que trata el torso como array de anillos: `sampleRingAt(body.torso, …)` en la rama de jeans. Si `model.torso` no expone `.sample`, jeans/falda/vestido (6 de los listings de la demo) rompen en runtime con `TypeError` y se cae el probador. - [risk] demo/vinted-mock/viewer3d/garment-builder-v2.js:297 — el límite del bucle se recalcula con `samples.length`, que el propio cuerpo incrementa: `i < rows - samples.length` deja de cumplirse a la 4ª iteración. La manga sale con 7 anillos en vez de 11 y termina a ~80% de `sleeve_cm` declarado. - [risk] demo/vinted-mock/viewer3d/garment-builder-v2.js:368 — tras `relax()` y `addFolds()` se hace `geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3))` desde el array JS original (pre-solver). El atributo con el resultado relajado se descarta: toda la relajación y las arrugas de la manga se pierden en silencio, y el centro de la tapa se calcula con coordenadas viejas. - [risk] demo/vinted-mock/viewer3d/garment-builder.js:extendHem — `mergeGeometries([geometry, tube], false)` puede devolver `null` y se asigna a `patch.geometry` sin comprobación → `TypeError` en `boundaryLoops(base.patch.geometry...)`. Además, cuando `targetHemY === hemY` se generan anillos degenerados (normales cero) y el tubo ignora la silueta del cuerpo (cilindro recto bajo la cintura). - [risk] tools/pipeline/legacy/src/types.ts:1 — copia íntegra del contrato congelado (`packages/fit-engine/src/types.ts`) y de `garment.ts`/`mesh.ts`/`validate.ts`, con el mismo mojibake (`ÔÇô`, `├│`, `v├ílida`) y ya divergente (`capStart`/`capEnd` en paneles). El contrato solo lo toca el lead; duplicarlo garantiza deriva. - [risk] tools/pipeline/export-legacy-garments.mjs:20 — el script reescribe en cada ejecución archivos versionados (`legacy/src/*.ts` + `legacy/src/package.json`) con un regex de imports. Efecto lateral no determinista sobre el árbol de trabajo; debería generar en `out/`, no mutar el fuente. - [risk] tools/pipeline/export-garments.mjs:23 — importa `packages/fit-engine/scripts/ts-runtime.mjs` (ruta no verificable en este diff) y carga `.ts` directamente con `node`, sin flag de type-stripping; con Node 22 el comando del README falla con `ERR_UNKNOWN_FILE_EXTENSION`. Duplica funcionalidad con `export-legacy-garments.mjs`. - [risk] tools/pipeline/blender_lib.py:33 — `scene.render.engine = 'BLENDER_EEVEE'` no es válido en Blender ≥4.2 (es `BLENDER_EEVEE_NEXT`) y el README asume 5.2: `reset_scene()` revienta al arrancar cualquiera de los scripts. - [risk] demo/vinted-mock/viewer3d/app.js:19 — el dispatch deja toda la rama de tops de la V2 (`makeTop`, `makeSleeve`, detalles de jacket/hoodie) como código muerto; conviven dos builders con holguras y estilos distintos y no hay tests ni verificación de que ambas rutas devuelvan la misma forma de resultado (`group` vs `root`) al viewer.