Paciente 6: paridad integral de cuatro vistas¶
Estado: PASS técnico desplegado; aceptación clínica pendiente
Última consolidación: 2026-08-03
Caso local: P6-LOCAL / alias exclusivo Paciente 6
Propósito y frontera de la evidencia¶
Este documento define el recorrido verificable de EPPA con las cuatro fotografías del Paciente 6: anterior, posterior, lateral derecha y lateral izquierda. El objetivo técnico es ejecutar en la aplicación real los mismos inputs que en MATLAB y comparar todas las medidas no angulares compatibles.
Hay tres afirmaciones distintas y no deben mezclarse:
- Replay histórico: reproduce valores que se ven en el video o quedaron registrados en artefactos de Cristina. Sólo la vista anterior tiene clics y resultados de referencia observables directamente en el video recuperado.
- Paridad técnica actual: Playwright y MATLAB R2026a reciben exactamente los mismos puntos derivados de las fotos actuales; sus resultados deben coincidir dentro de una tolerancia explícita por métrica.
- Aceptación clínica: confirma que las asignaciones anatómicas y los puntos manuales son los que Cristina pretende usar. La paridad matemática no sustituye esta aprobación.
La evidencia disponible permite construir el contrato técnico de cuatro vistas. No permite afirmar que los clics posteriores, laterales o auxiliares que no aparecen en el video sean los clics históricos de Cristina.
Privacidad y límites operativos¶
- Las cuatro fotografías y el video original permanecen fuera de Git. El manifiesto sólo conserva nombres de archivo, dimensiones, hashes y coordenadas naturales.
- Playwright debe resolver las imágenes mediante
EPPA_PATIENT6_IMAGE_DIR; nunca debe copiarlas al repositorio, al reporte HTML ni a un artifact público. - El identificador de replay es
P6-LOCAL. No registrar nombre real, historia clínica ni otra identidad. - Toda salida compartible debe pixelar el rostro y ocultar credenciales, correos, cookies y cualquier identificador. El contact sheet final también debe inspeccionarse antes de compartirse.
- Las fotos originales sólo están autorizadas para desarrollo local interno. El video fuente no es el video tutorial entregable.
- No tocar
.git/lfs,.gitattributesnisources/. No copiar outputs a.tmp/como si fueran evidencia durable y excluir.tmp/de cualquier commit. - No ejecutar publicación, deploy, push, merge ni commit como parte de este protocolo.
Fuentes y huellas¶
Imágenes privadas¶
| Vista | Archivo externo | Dimensiones | Bytes | SHA-256 |
|---|---|---|---|---|
| Anterior | 6- Frente.jpg |
610 × 1101 | 161131 | a0c181b7eadc59ae292890ddb4f51d63a86aca064dd3e42f5775a9838f380309 |
| Posterior | 6- Posterior.jpg |
612 × 1108 | 99312 | 99fbae8e514170f590d84a178b708d89f64edd9c21b96431da6a4334693ca47f |
| Lateral derecha | 6- Perfil derecho.jpg |
607 × 1099 | 107124 | 820cc16eba28e5e4a18992a9b9aabb7e63ed4d0901df5dab5c1e07d5ba82db5d |
| Lateral izquierda | 6- Perfil izquierdo.jpg |
593 × 1094 | 103529 | 6b7c8ccf9558392930319084ed745a77d42ff475e45c25dcc27be43f48e6cc7b |
Las cuatro imágenes son menores al ancho mínimo productivo de 800 px. El E2E debe usar el override auditable exacto del manifiesto:
Foto historica P6 provista por Cristina; hash y grilla verificados.
No se permite reescalar silenciosamente ni debilitar el umbral global.
Video, subtítulos y resultados asociados¶
| Artefacto externo | SHA-256 | Rol probatorio |
|---|---|---|
chh-gjaa-tps-2026-05-25-1041-parte-1.mp4 |
003ce544a4b64453df91ff836f1bbc11f7bebb3a4c28d6dc829f79adc96d594b |
Video fuente: H.264, 1280 × 720, 24 fps, 4698.875 s |
subtitulos-cristina-2026-05-25.srt |
4e28eaa382195d89f802d23e06066bdf8e346f5742580b50826ee8110f53a1c7 |
Secuencia verbal y tiempos guía |
Marcadores_IDSIN_ID_VistaA_19-05-2026_10-40-05.txt |
dae256986d81340ca0d195a994d69a133db426b7b51756b349326f839d08a87f |
Confirma anterior #12, #13, #14, #15, #16 y #21 |
captura_pantalla_anterior_2026-05-19_10-57-28.png |
abd8e4dab5605e8aa071cc819a3ad285d6b6a35631c70ecadfafce00afa9e90a |
Evidencia visual anterior histórica |
resultados_analisis_anterior_2026-05-19_10-58-54.csv |
a5d62fa2ede11f6863e2c8cb939b6d5963bc5635ddab7bedaf270e5bbb00496e |
Registro histórico, no oracle de la foto actual |
Base completa- CORREGIDA.xlsx |
f3fca102685d018ebd7d9c7acaa75f6715377f96f10d3886d401634148b4ca14 |
39 filas [cm] de Evaluado 6 / Evaluador 8; sólo registro histórico |
Marcadores_ID_6_28-2-2024_11-12-47.mat |
a3ba6e9b0a5e8960e1847b0e63f17b45311c8bd777127c53ecdf99990747c737 |
MAT derecho histórico en otro espacio de coordenadas; permite reconstruir sólo tres filas |
Antes de declarar que no existe otro oracle, el cierre debe anexar un inventario
reproducible de todos los .mat, CSV, TXT y resultados P6 localizados fuera de
sources/, con hash y estado materialized, pointer o
different-coordinate-space.
MATLAB fuente y oracle ejecutado¶
El oracle actual lee las copias explícitas entregables de
matlab-para-cristina/; no lee las variantes de old/matlab/ ni resultados de
la web o de FastAPI.
| Vista | Fuente ejecutable | SHA-256 verificado |
|---|---|---|
| Anterior | matlab-para-cristina/InterfazMedicionFrenteJulio2024v2.m |
9da8918663e8715fe7ddec272ad5ea588c11056f0ec01df3ba418644acf2f890 |
| Posterior | matlab-para-cristina/InterfazMedicionEspaldaJulio2024v2.m |
4af164865c2a4158e2c22e120395d2d773cb893d8e719d066d21061380242332 |
| Lateral derecha | matlab-para-cristina/InterfazMedicionPerfilDerechoJulio2024.m |
bfd7a914c7795841739390fc4ce20f94fd17fc17ded5ddaed982525762057216 |
| Lateral izquierda | matlab-para-cristina/InterfazMedicionPerfilIzquierdoJulio2024.m |
17b53ad33b8119725cf5132e07bc3cf556937f16852f053aef5c7f988d3ceb0d |
La ejecución materializada fue realizada con MATLAB
26.1.0.3312084 (R2026a) Update 4. Su cadena de procedencia es:
| Artefacto | SHA-256 verificado |
|---|---|
tests/fixtures/patient-6-workflow-manifest.v1.json |
074745585048fbb0392bec8c20d8816d9aea17f43f21514bd288a997c60f79c8 |
matlab_validation/patient_6_nonangular_matlab_oracle.m |
863d4f303d17a0fda66710a67f22cfe1c17620ffd80d46605cb943ab1109db7f |
tests/fixtures/patient-6-nonangular-matlab-oracle.expected.json |
7b5e90b4a84c1da982d14abe03f70e9d0f4b8f5966ff87bf8aaf8aee6c67e657 |
El JSON contiene 39 métricas únicas en centímetros: 37 soportadas y dos
unsupported exclusivamente por los marcadores izquierdos #59 y #63 ausentes.
No contiene ángulos ni las excepciones de ángulos corregidos.
Matriz temporal del video fuente¶
La tabla distingue tiempos guía de transiciones verificadas a 1/24 s. Un guion general no se convierte en coordenada gold si el click no quedó visible.
| Tiempo | Vista | Acción observable | Coordenada natural / resultado | Fuente y fuerza | Uso en replay |
|---|---|---|---|---|---|
00:32:08 |
General/anterior | Comienza el trabajo de marcadores | Sin coordenada exacta | Video + SRT, tiempo guía | Define inicio del protocolo |
00:33:52 |
Anterior | Se ve 6- Frente.jpg y coincide píxel a píxel con la foto privada |
Imagen 610 × 1101 | Video, nombre visible y registro con la foto | Confirma que el sujeto del recorrido es P6 |
00:34:08 |
Anterior | Guía de calibración/referencia | No extraída como click exacto | Tiempo guía del Goal | Secuencia, no oracle numérico |
00:35:56 |
Anterior | Se observa la recta fija | Endpoint no visible con precisión | Tiempo guía del Goal | Semántica de la recta |
00:37:52 |
Anterior | Guía de vertical desde punto medio | Sin coordenada fuente completa | Tiempo guía del Goal | No sustituye la fórmula MATLAB |
00:39:52 |
Anterior | Imagen final del tramo guiado | Sin nueva coordenada | Tiempo guía del Goal | Control visual |
00:40:42.812 |
Anterior | Primer click de calibración | Aproximadamente (106.9, 457.6); replay entero (107, 458) |
Transición nativa; registro foto↔video >0.99 |
Click 1 de 10 cm |
00:40:46.688 |
Anterior | Segundo click y línea de calibración | Aproximadamente (157.0, 457.6); replay entero (157, 458); UI histórica FC=0.199721 |
Transición nativa + texto UI | Click 2; replay entero produce FC=0.2 |
00:41:08.354 |
Anterior | Primer maléolo medial, de izquierda a derecha en pantalla | Aproximadamente (305.82366, 937); replay entero (306, 937) |
Transición nativa + registro foto↔video | Click 1 de referencia |
00:41:09.896 |
Anterior | Segundo maléolo medial y aparece la T | Aproximadamente (336.41634, 937); replay entero (336, 937) |
Transición nativa + texto UI | UI histórica: LRV X=321.12, maléolos 6.11 cm; replay entero: 321, 6.0 cm |
00:42:40 |
Anterior | Observación del grosor de rectas | Sin nueva coordenada | Tiempo guía del Goal | Revisión visual, no cálculo |
00:44:36 |
Anterior | Vista final y observación de puntos entre cóndilos/gemelos | El contrato actual usa cóndilos (313,780)→(321,780) y gemelos (309,850)→(331,850) |
El transcript confirma la semántica “entre”; las coordenadas se derivaron de la foto actual | Oracle técnico reproducible; pendiente de aceptación clínica, no click histórico exacto |
00:48:00–00:49:00 |
Anterior/tutorial | Secuencia marcadores → importar → calibrar → rectas | Sin set completo de clicks | Video + SRT | Orden funcional, no coordenadas de otras vistas |
El video no demuestra los clics de posterior ni de los dos perfiles. Las fotos de esas vistas son del mismo caso, pero sus referencias y puntos auxiliares no deben describirse como históricos.
Secuencia ejecutable de la demostración¶
El recorrido base debe ser un único test() y un único browser context para
probar la misma sesión v2 e IndexedDB en las cuatro vistas.
- Iniciar stack local real y autenticar un usuario local mediante el formulario
visible. El login real se prueba sin
EPPA_E2E_AUTH_BYPASSy sin credenciales embebidas en código o artifacts. - Abrir captura y usar el mismo ID
P6-LOCALen las cuatro vistas. - Antes de cada upload, resolver el archivo desde
EPPA_PATIENT6_IMAGE_DIRy verificar bytes, dimensiones y SHA-256. - Para cada marcador visible, ejecutar esta microsecuencia real:
encuadrar → seleccionar → ampliar/recentrar → comprobar X/Y natural en el DOM → marcar → confirmar progreso → volver a encuadrar. - No fabricar los cuatro puntos ausentes. Registrar su ausencia y comprobar el
comportamiento
Sin datos / Punto no visiblecuando afecte un análisis. - Aceptar el override de resolución con el motivo exacto documentado; marcar que la referencia de calibración es visible; guardar y descargar el TXT de cada vista.
- Comprobar que
Object.keys(session.views).lengthprogresa1 → 2 → 3 → 4sin perder vistas previas y que las imágenes quedan en IndexedDB, no inline ensessionStorage. - En cada análisis, restaurar imagen y marcadores desde captura. No inyectar estado desde el test y no usar el botón del caso sintético.
- Calibrar, crear las rectas, marcar los puntos auxiliares con el mismo helper de precisión, ejecutar endpoints FastAPI reales y comparar cada resultado no angular con el JSON MATLAB P6 por clave semántica.
- Recargar cada vista y volver a comprobar geometría, caches y resultados.
- Validar TXT, CSV, Excel y capturas por nombre, tipo, encabezado y cantidad de filas. Toda captura compartible debe ser anonimizada.
- Repetir un smoke móvil a 390 × 844 que cubra al menos carga/captura precisa, calibración, referencia y un resultado usando las tabs reales.
- Grabar el tutorial desde esta misma ruta exitosa; no recrearlo con una simulación paralela.
Contrato geométrico común¶
Calibración de 10 cm¶
En cada foto se marcan dos intersecciones de la grilla separadas por dos cuadrados de 5 cm. El segmento debe ser horizontal, de izquierda a derecha, screen-left del cuerpo y cerca de la cadera:
distancePx = hypot(c2.x - c1.x, c2.y - c1.y)
FC = 10 / distancePx
Los cuatro pares ejecutables miden 50 px y producen FC=0.2 cm/px.
Anterior y posterior¶
D = hypot(q2.x - q1.x, q2.y - q1.y)
PM = D / 2
origin = (q1.x + PM, q1.y)
end = (origin.x, q1.y - 200 / FC)
q1 y q2 son los contornos mediales de los tobillos, de izquierda a
derecha en pantalla; no son los stickers verdes exteriores. La X no debe
reemplazarse por un promedio arbitrario: MATLAB usa literalmente q1.x+D/2.
Perfiles¶
Los dos clicks manuales dibujan la horizontal y aportan q1.y. La X vertical
proviene del marcador importado:
rightOrigin = (marker45.x, q1.y)
leftOrigin = (marker65.x, q1.y)
end = (origin.x, origin.y - 200 / FC)
Con FC=0.2, la vertical MATLAB mide 1000 px. Puede terminar fuera de la foto;
eso es válido. El snapshot histórico anterior usaba un endpoint relativo al
viewport, pero el contrato actual elige la fórmula literal MATLAB 200/FC.
Contrato por vista¶
Todas las coordenadas se expresan en píxeles naturales con origen arriba a la izquierda. Los centroides fuente conservan decimales; la UI actual direcciona el píxel entero más cercano y el readout debe quedar a ≤1 px del centroide.
El manifiesto materializado cubre el catálogo completo de las cuatro vistas: 60 marcadores visibles y cuatro ausencias explícitas (#33, #53, #59 y #63), sin sintetizar coordenadas. También contiene las cuatro referencias concretas y 18 interacciones de superficie: anterior 4, posterior 8 y tres por cada perfil. Salvo la calibración/referencia anterior observada en video, las referencias posterior/laterales y todos los puntos de superficie son contratos técnicos actuales pendientes de aceptación clínica.
Anterior¶
| ID | Marcador | X | Y | Evidencia |
|---|---|---|---|---|
| 12 | Eminencia Frontal Media | 317.823529 | 99.983193 | Sticker + sidecar |
| 13 | Espina Nasal | 319.817391 | 135.904348 | Sticker + sidecar |
| 14 | Punto Mentoniano | 321.196429 | 173.973214 | Sticker + sidecar |
| 15 | Tragus Izq. | 367.698276 | 157.103448 | Sticker + sidecar |
| 16 | Tragus Der. | 276.271930 | 163.035088 | Sticker + sidecar |
| 17 | Punto Acromion Izq. | 432.972973 | 237.225225 | Centroide estable + catálogo |
| 18 | Punto Acromion Der. | 213.269565 | 245.339130 | Centroide estable + catálogo |
| 19 | Escotadura Esternal | 321.070175 | 239.859649 | Centroide estable + catálogo |
| 20 | Apéndice Xifoides | 325.858407 | 345.911504 | Centroide estable + catálogo |
| 21 | Ombligo | 323.882353 | 483.773109 | Sticker + sidecar |
| 22 | Punto Sínfisis Pubiana | 319.956522 | 565.269565 | Centroide estable + catálogo |
| 23 | Espina Ilíaca Anterosuperior Izq. | 407.284483 | 489.215517 | Centroide estable + catálogo |
| 24 | Espina Ilíaca Anterosuperior Der. | 229.192982 | 481.921053 | Centroide estable + catálogo |
| 25 | Centro Rótula Izq. | 371.018018 | 783.162162 | Centroide estable + catálogo |
| 26 | Centro Rótula Der. | 276.018349 | 777.091743 | Centroide estable + catálogo |
| 27 | TAT Izq. | 369.868421 | 809.087719 | Centroide estable + catálogo |
| 28 | TAT Der. | 273.771186 | 805.864407 | Centroide estable + catálogo |
Hay cuatro stickers físicos adicionales en codos y muñecas. No pertenecen al catálogo anterior y no deben convertirse en IDs inventados.
| Elemento | Contrato actual | Fuente/estado |
|---|---|---|
| Calibración | (107,458) → (157,458), 50 px, FC=0.2 |
Replay entero de clicks del video |
| Calibración histórica | (~106.9,457.6) → (~157.0,457.6), UI FC=0.199721 |
Video directo; tolerancia de registro ±0.5 px |
| Referencia | (306,937) → (336,937); vertical (321,937) → (321,-63); maléolos 6.0 cm |
Replay entero actual |
| Referencia histórica | (~305.82366,937) → (~336.41634,937); UI LRV X=321.12, maléolos 6.11 cm |
Video directo; no mezclar con replay entero |
| Cóndilos | (313,780) → (321,780), izquierda→derecha; tolerancia ±2 px |
Contrato actual derivado de foto + semántica del transcript; pendiente clínica |
| Gemelos | (309,850) → (331,850), izquierda→derecha; tolerancia ±2 px |
Contrato actual derivado de foto + semántica del transcript; pendiente clínica |
Medidas no angulares directas: EFM, nasal, mentón, escotadura, xifoides y
pubis usan FC*(LRV_X-marker_X). Cóndilos, gemelos y maléolos dependen de los
clicks manuales. El oracle MATLAB actual fija para esos tres campos 1.6,
4.4 y 6.0 cm, respectivamente, usando los píxeles enteros del manifiesto.
El futuro Playwright debe demostrar que la UI direcciona esos mismos píxeles;
el JSON expected no prueba por sí solo la interacción web.
Posterior¶
Los 19 centroides físicos son reproducibles. Su identidad semántica es una asignación de alta confianza por catálogo y ubicación, pero no existe un export posterior materializado; toda la vista permanece pendiente de aceptación clínica.
| ID | Marcador | X | Y |
|---|---|---|---|
| 72 | Lóbulo Izq. | 261.882883 | 153.963964 |
| 73 | Lóbulo Der. | 359.681818 | 157.990909 |
| 74 | Punto Interno Espina Omóplato Izq. | 253.133333 | 226.961905 |
| 75 | Ángulo Inferior Omóplato Izq. | 261.231481 | 304.009259 |
| 76 | Punto Interno Espina Omóplato Der. | 375.108108 | 232.000000 |
| 77 | Ángulo Inferior Omóplato Der. | 375.899083 | 314.009174 |
| 78 | Cervical 7 | 307.752294 | 191.990826 |
| 79 | Torácica 3 | 305.820755 | 228.066038 |
| 80 | Torácica 7 | 307.911504 | 305.061947 |
| 81 | Torácica 12 | 309.045455 | 385.018182 |
| 82 | Lumbar 5 | 309.925926 | 455.981481 |
| 83 | EIPS izquierda | 289.077586 | 498.025862 |
| 84 | EIPS derecha | 340.008264 | 493.099174 |
| 85 | EIPI izquierda | 285.074074 | 520.000000 |
| 86 | EIPI derecha | 348.028169 | 513.042254 |
| 87 | Aquiles Izq. | 281.080357 | 1054.946429 |
| 88 | Aquiles Der. | 351.894737 | 1055.043860 |
| 89 | Calcáneo Izq. | 285.267241 | 1085.025862 |
| 90 | Calcáneo Der. | 351.016260 | 1083.227642 |
| Elemento | Contrato actual | Fuente/estado |
|---|---|---|
| Calibración | (59,515) → (109,515), 50 px, FC=0.2 |
Contrato de foto actual, revisado visualmente; no histórico |
| Referencia | (303,1010) → (334,1010); vertical (318.5,1010) → (318.5,10); maléolos 6.2 cm |
Contrato actual derivado visualmente; pendiente clínica, no histórico |
| Cóndilos | (319,800) → (324,800); tolerancia ±2 px |
Contrato actual derivado de la foto; pendiente clínica |
| Gemelos | (308,880) → (332,880); tolerancia ±2 px |
Contrato actual derivado de la foto; pendiente clínica |
| Pliegue poplíteo izquierdo | (238,807) → (315,807); punto medio (276.5,807) |
Contrato actual derivado; tolerancia ±3 px |
| Pliegue poplíteo derecho | (327,802) → (401,796); punto medio (364,799) |
Contrato actual derivado; tolerancia ±3 px; ejecutar con estimate_popliteal=false |
La referencia ya es concreta y el oracle calcula las 12 métricas posteriores.
Entre ellas: cóndilos 1.0 cm, gemelos 4.8 cm y maléolos 6.2 cm. No se
deriva la referencia desde Aquiles o Calcáneos, y esta paridad técnica no
convierte el par propuesto en un click histórico de Cristina.
Lateral derecha¶
| ID | Marcador | X | Y | Estado |
|---|---|---|---|---|
| 32 | Tragus Der. | 309.937500 | 147.017857 | Visible |
| 33 | Lóbulo Oreja Der. | — | — | Ausente; alternativa al tragus, no inventar |
| 34 | Apex Cervical Der. | 261.123810 | 185.895238 | Visible |
| 35 | Punto Acromion Der. | 283.740385 | 226.009615 | Visible |
| 36 | Punto Epicóndilo Der. | 283.095238 | 419.028571 | Visible |
| 37 | Base 3er Metacarpiano Der. | 323.223301 | 605.029126 | Visible |
| 38 | Apex Lumbar Der. | 235.268519 | 449.064815 | Visible |
| 39 | Tubérculo Ilíaco Der. | 321.245455 | 464.981818 | Visible |
| 40 | EIAS Der. | 356.073394 | 484.944954 | Visible |
| 41 | EIPS Der. | 249.268519 | 494.842593 | Visible |
| 42 | EIPI Der. | 245.843750 | 514.937500 | Visible |
| 43 | Trocánter Mayor Der. | 325.287037 | 536.037037 | Visible |
| 44 | Tubérculo Cóndilo Externo Der. | 291.878505 | 812.000000 | Visible |
| 45 | Borde anterior de Maléolo Der. | 275.144928 | 1050.014493 | Visible; ancla vertical |
| Elemento | Contrato actual | Fuente/estado |
|---|---|---|
| Calibración | (159,509) → (209,509), 50 px, FC=0.2 |
Contrato de foto actual; no histórico |
| Referencia horizontal | (75,1050) → (525,1050) |
Propuesta determinista actual; pendiente clínica |
| Referencia vertical | X de #45: (275.144928,1050) → (275.144928,50) |
Fórmula MATLAB; X fuente-verificada, Y no histórica |
| Punto Cabeza | (229,105); tolerancia ±2 px |
Contorno de foto actual; pendiente clínica |
| Punto Dorsal | (209,290); tolerancia ±2 px |
Contorno de foto actual; pendiente clínica |
| Punto Sacro | (214,560); tolerancia ±2 px |
Contorno de foto actual; pendiente clínica |
El oracle MATLAB real, que redondea los centroides a los píxeles direccionables
por la UI, produce nueve métricas soportadas. Entre ellas: cabeza 7.0,
tangentes occipital–dorso 4.0, hombro 1.8, ilíaco 9.2, trocánter 10.0
y rodilla 3.4 cm. Playwright todavía debe comparar la aplicación real con
ese JSON.
Lateral izquierda¶
| ID | Marcador | X | Y | Estado |
|---|---|---|---|---|
| 52 | Tragus Izq. | 321.915094 | 138.990566 | Visible |
| 53 | Lóbulo Oreja Izq. | — | — | Ausente; alternativa al tragus, no inventar |
| 54 | Apex Cervical Izq. | 372.018519 | 180.916667 | Visible |
| 55 | Punto Acromion Izq. | 345.130841 | 217.018692 | Visible |
| 56 | Punto Epicóndilo Izq. | 335.792793 | 412.045045 | Visible |
| 57 | Base 3er Metacarpiano Izq. | 306.191176 | 592.029412 | Visible |
| 58 | Apex Lumbar Izq. | 407.250000 | 430.982143 | Visible |
| 59 | Tubérculo Ilíaco Izq. | — | — | No hay sticker; no inventar |
| 60 | EIAS Izq. | 283.214953 | 492.046729 | Visible |
| 61 | EIPS Izq. | 399.063636 | 506.018182 | Visible |
| 62 | EIPI Izq. | 403.945455 | 523.990909 | Visible |
| 63 | Trocánter Mayor Izq. | — | — | No hay sticker; no inventar |
| 64 | Tubérculo Cóndilo Externo Izq. | 355.833333 | 806.018519 | Visible |
| 65 | Borde anterior de Maléolo Izq. | 363.841121 | 1037.028037 | Visible; ancla vertical |
| Elemento | Contrato actual | Fuente/estado |
|---|---|---|
| Calibración | (147,505) → (197,505), 50 px, FC=0.2 |
Contrato de foto actual; no histórico |
| Referencia horizontal | (75,1037) → (525,1037) |
Propuesta determinista actual; pendiente clínica |
| Referencia vertical | X de #65: (363.841121,1037) → (363.841121,37) |
Fórmula MATLAB; X fuente-verificada, Y no histórica |
| Punto Cabeza | (400,100); tolerancia ±2 px |
Contorno de foto actual; pendiente clínica |
| Punto Dorsal | (428,300); tolerancia ±2 px |
Contorno de foto actual; pendiente clínica |
| Punto Sacro | (423,560); tolerancia ±2 px |
Contorno de foto actual; pendiente clínica |
El oracle MATLAB real produce siete métricas soportadas en esta vista. Cabeza
es 8.4 cm, tangentes occipital–dorso 5.6 cm, hombro 3.8 cm y, de forma
importante, rodilla sí está soportada: 1.6 cm / Genu Flexo, porque sólo
requiere #64, #65 y FC. Únicamente ilíaco (#59) y trocánter (#63) quedan
unsupported. El E2E debe comprobar Sin datos / Punto no visible para esos
dos campos, no bloquear ni reemplazar el resultado válido de rodilla.
Histórico registrado frente al replay actual¶
El workbook P6/Evaluador 8 contiene 39 filas en centímetros. Son evidencia de lo que quedó registrado, no expected values de las fotos actuales.
| Vista | Filas históricas | Qué puede reconstruirse exactamente | Qué no puede afirmarse |
|---|---|---|---|
| Anterior | 9 | Ninguna fila completa con todos sus inputs históricos actuales | Igualdad con centroides/calibración/referencia actuales |
| Posterior | 12 | Ninguna: falta referencia y clicks auxiliares históricos | Que una referencia propuesta reproduzca el workbook |
| Lateral derecha | 9 | Cabeza 7.673697031027, hombro 8.608485242161 y rodilla 3.292934240540 usando el MAT histórico y FC=0.2565382924677817 |
Aplicar ese FC o esas coordenadas a la foto 607 × 1099 actual |
| Lateral izquierda | 9 | Ninguna: no hay MAT izquierdo histórico materializado | Reemplazar valores faltantes por coordenadas inferidas |
Dos filas derechas del workbook fueron correcciones decimales registradas:
Tangentes Dorso–Sacro 43.48 → 4.35 y Lordosis lumbar 49.13 → 4.91. No son
un oracle reproducible conjuntamente y no deben ocultarse con una tolerancia.
La comparación final debe usar estas clases separadas:
| Clase | Fuente | Assertion permitida |
|---|---|---|
videoObserved |
Texto/clicks visibles del video | Comparación histórica sólo de los campos observables, con tolerancia documentada |
currentReplay |
Píxeles naturales efectivamente observados por Playwright | Igualdad web↔MATLAB R2026a por métrica no angular |
historicalRecorded |
Workbook/CSV/MAT histórico | Mostrar y trazar; no comparar como si los inputs fueran los actuales |
clinicalAcceptance |
Confirmación explícita de Cristina | Única fuente para declarar correcto el significado clínico de inputs propuestos |
Las cuatro excepciones angulares existentes
MATLAB-ANGLE-001..004 continúan cubiertas por la suite corregida actual. No
participan de la comparación histórica P6 y no autorizan una tolerancia global
para medidas no angulares.
Contrato Playwright y API¶
El spec ejecutado es playwright/e2e/patient-6-four-view.spec.ts. Los gates
desktop y mobile completaron el recorrido P6 de cuatro vistas con evidencia
Jenkins verificable; su presencia no se usa como sustituto de esa evidencia.
Reglas del spec:
- un único
test(),P6-LOCALy browser context para las cuatro vistas; - cero
btn-open-synthetic-casey cero respuestas de dominio fabricadas; - el redirect local de API puede usar
route.fetch()/route.fulfill()sólo para transportar la respuesta real de FastAPI, nunca para inventarla; - todos los clicks usan
clickAtNaturalImageCoordinatey verifican el readout DOM antes de marcar; - los hashes y dimensiones se comprueban antes de cada upload;
- las ausencias se conservan y no se completan por estimación anatómica;
- comparación por
(view, region, canonicalVariable), no por índice de fila; - tolerancia individual y justificada por métrica;
- la falta fuente-confirmada produce
Sin datos / Punto no visibley, cuando corresponde, ausencia de request; - persistencia, reload y exports son obligatorios.
| Vista | Endpoints reales que debe ejercitar |
|---|---|
| Anterior | /api/anterior/cervico-cefalica, /api/anterior/tronco-columna, /api/anterior/escapular-ms, /api/anterior/pelvica-mi |
| Posterior | /api/posterior/cervico-cefalica, /api/posterior/escapular-ms, /api/posterior/tronco-columna, /api/posterior/pelvica, /api/posterior/pie-tobillo |
| Lateral derecha | /api/lateral/cervico-cefalica, /api/lateral/tronco-columna, /api/lateral/miembro-superior, /api/lateral/miembro-inferior con side=right |
| Lateral izquierda | Los mismos endpoints laterales con side=left; no enviar una petición inferior incompleta por #59/#63, pero conservar el cálculo local válido de rodilla con #64/#65 |
El TXT de cada vista debe conservar el formato:
Marcador,Vista,X,Y
<nombre>,<A|P|D|I>,<X natural con 4 decimales>,<Y natural con 4 decimales>
El CSV de resultados debe incluir
Región,Variable,Medición,Unidad,Diagnóstico. También se validan el Excel y la
captura clínica/anonimizada mediante nombre accesible o data-testid real.
Comandos previstos¶
Estos comandos permiten reproducir los gates. La tabla siguiente distingue los
focales ya ejecutados de los que siguen pendientes. Ejecutarlos desde
fronts/eppa con la ruta privada configurada localmente.
export EPPA_PATIENT6_IMAGE_DIR='/ruta/privada/a/las/fotos'
npm run test:unit -- \
tests/unit/patient-6-workflow-manifest.test.ts \
tests/unit/patient-6-nonangular-matlab-oracle.test.ts \
tests/unit/clinical-calibration.test.ts \
tests/unit/clinical-calibration-wiring.test.ts
npm run typecheck
npm run lint
El oracle P6 real se regenera desde el mismo manifiesto con este comando. No usar el oracle sintético como sustituto:
/Applications/MATLAB_R2026a.app/bin/matlab -batch \
"addpath('matlab_validation'); patient_6_nonangular_matlab_oracle([], 'tests/fixtures/patient-6-nonangular-matlab-oracle.expected.json');"
E2E desktop y mobile, una vez creado el spec:
EPPA_PATIENT6_IMAGE_DIR="$EPPA_PATIENT6_IMAGE_DIR" \
npm run test:e2e:playwright -- \
playwright/e2e/patient-6-four-view.spec.ts
Para aislar infraestructura de producto, registrar health checks y logs antes, durante y después del run:
curl --fail --silent --show-error http://127.0.0.1:8100/health
curl --fail --silent --show-error http://127.0.0.1:9102/es/login >/dev/null
npm run build
git diff --check
git status --short
El login real requiere un lane separado con storageState vacío y secretos
inyectados sólo por entorno:
export EPPA_E2E_EMAIL='...'
export EPPA_E2E_PASSWORD='...'
No imprimir esos valores ni incluir el tramo de escritura de credenciales en el video compartible.
Gates de aceptación¶
Snapshot final actualizado al 2026-08-03. Los run IDs y rutas durables se detallan en la sección de cierre técnico.
| Gate | Evidencia exigida | Estado actual documentado |
|---|---|---|
| Integridad fuente | Cuatro hashes/dimensiones/bytes comprobados en runtime | PASS |
| Manifest P6 | Unit test verde, 60 visibles + 4 ausentes, refs y surface completos | PASS |
| Fórmulas y wiring | Unitarios de fórmula + cuatro pantallas | PASS |
| Oracle MATLAB P6 | JSON R2026a generado desde los inputs ejecutables, con hash y tolerancias | PASS técnico: 37 soportadas + 2 ausencias explícitas |
| Playwright desktop P6 | Un único recorrido 4 vistas, APIs reales, persistencia, reload y exports | PASS — Jenkins #19 |
| Login real local | Formulario + POST real, sin bypass | PASS — tutorial #20 |
| Mobile 390 × 844 | Captura precisa + calibración + referencia + resultado | PASS — Jenkins #30 |
| Ángulos corregidos | Suite vigente verde con MATLAB-ANGLE-001..004 |
PASS en suite integral; fuera de comparación no angular P6 |
| Typecheck | npm run typecheck exit 0 |
PASS — Jenkins #19 |
| Lint | npm run lint sin errores |
PASS — Jenkins #19 |
| Build/servidor | Build exit 0, web/API health y run limpio con logs | PASS — Jenkins #19 + deploy smoke |
| Video tutorial | Flujo real completo, rostro/credenciales anonimizados | PASS — Jenkins #20 |
| Evidencia audiovisual | Hash, codec, duración y contact sheet inspeccionado | PASS — QA independiente |
| Scope final | git diff --check; sin fotos, .tmp, LFS, secretos ni cambios ajenos |
PASS |
Un fallo ERR_FAILED o CONNECTION_REFUSED no se clasifica como producto sin
comprobar primero ambos health endpoints y los logs del proceso. El rerun limpio
debe distinguir crash del servidor, fixture no consumido y fallo funcional.
Pendientes clínicos y técnicos honestos¶
Requieren fuente adicional o aceptación de Cristina¶
- Confirmar la asignación semántica de los 19 centroides posteriores.
- Confirmar la asignación semántica lateral fuera de los puntos evidentes y las ausencias #33, #53, #59 y #63.
- Aprobar la referencia posterior derivada de la foto; no existe click histórico materializado.
- Aprobar la Y/horizontal propuesta en ambos perfiles. Sólo X=#45/#65 está fuente-verificada.
- Aprobar los clicks actuales de Cóndilos, Gemelos, cuatro extremos poplíteos y Cabeza/Dorsal/Sacro que no aparecen en una fuente histórica completa.
- Confirmar que las fotos de ancho menor a 800 px son aceptables para este replay interno con override auditable.
Resueltos técnicamente sin inventar clínica¶
- Spec P6, login real, mobile, exports y video anonimizado: completados.
- El recorrido real demostró que los píxeles observados por la UI coinciden con los inputs ya fijados en el manifiesto y comparó sus responses por clave semántica con las 37 métricas soportadas del oracle.
- La UI conserva
1.6 cm / Genu Flexopara rodilla izquierda aunque ilíaco y trocánter estén explícitamente ausentes. - Relay, evidencia por vista y riesgo residual quedaron actualizados.
Condición de cierre¶
La misión sólo puede declarar PASS técnico cuando estén verdes el manifest, MATLAB P6, Playwright desktop/mobile, login real, unitarios, typecheck, lint, build/health, persistencia, exports y privacidad audiovisual; además, cada diferencia frente al video/workbook debe estar explicada.
El cierre debe seguir diciendo pendiente de aceptación clínica mientras Cristina no confirme los puntos cuya única fuente es la derivación de las fotos actuales. Nunca presentar paridad de software como validación clínica.
Cierre técnico ejecutado¶
| Carril | SHA | Evidencia final |
|---|---|---|
| Base + desktop | e205a97431efabe670173025f64576cbc48e85e3 |
Jenkins eppa-p6-final #19: 472/472 unit, typecheck, lint, build, 585/585 pytest y Playwright desktop 1/1 |
| Mobile | b427848abecf13805f2cdebcb15e5141f1898de3 |
Jenkins eppa-p6-mobile-focal #30: Pixel 7 390x844, 60 marcadores, 4 ausencias, cuatro vistas, 16/16 POST 200 y exports válidos |
| Docker | b427848abecf13805f2cdebcb15e5141f1898de3 |
Jenkins eppa-p6-docker #11: image sha256:7b1bb5abf7171c3fbc59f2a274270850da651cfec16fdace012953cf26f7a8fd |
| Tutorial | 78244147035c1976a93323e3f4a483aaa916b901 |
Jenkins eppa-p6-tutorial-focal #20: login real, cuatro vistas, MP4 narrado y anonimizado; QA visual independiente PASS |
La separación de SHA no altera el runtime: después de b427848, los cambios
son exclusivamente el conteo del gate base y un helper Playwright. El árbol
src es idéntico y Docker excluye ci/, playwright/ y docs/.
El MP4 final dura 562.64 segundos, usa H.264 800x500, AAC y subtítulos
mov_text; SHA-256
da6260822de4b4c8b6554a9b7170bbcfeae8ec236bcd51d05c973d1f253977ce.
El contact sheet tiene SHA-256
a6c1d7f33c3afbf78d293f41a487c70c271b33bda19c42e2f5f1b1ae30e0d811.
Los entregables están en
/Users/luis/Desktop/EPPA-Paciente-6-Tutorial-7824414.
La imagen se desplegó exclusivamente como servicio eppa2 en
https://eppa2.firemandeveloper.com. Health local, smoke público, login real
y /api/auth/me pasaron; legacy eppa, PostgreSQL y MinIO conservaron sus IDs.
Resultado: EPPA queda técnicamente terminado para este alcance y desplegado. Sólo continúa la aceptación clínica explícita de Cristina para los puntos que el video recuperado no permite atribuir históricamente.