Jose Salazar Claude Opus 5 commited on
Commit
eaa81c2
·
1 Parent(s): af530a3

CLAUDE.md: invariantes de pdf.js, panel-vacio y léxico clínico

Browse files
Files changed (1) hide show
  1. CLAUDE.md +15 -1
CLAUDE.md CHANGED
@@ -60,7 +60,21 @@ User clicks "Análisis IA"
60
  - **`frontend/src/ia.ts`** — Cliente tipado de `POST /api/interpret`; renderiza la salida estructurada (hallazgos, diferenciales con citas, banner de derivación). No construye el prompt (eso vive en el backend).
61
  - **`frontend/src/main.ts`** — Orquestación: carga los JSON, cablea eventos del formulario, dispara el análisis, exporta PDF.
62
  - **`frontend/src/ui.ts`** — Tab navigation (8 panels, 4 exam sub-tabs), swipe gestures, mobile/desktop field sync, collapsible panels.
63
- - **`frontend/src/pdf-parser.ts`** — Client-side PDF extraction using PDF.js. 47 regex patterns to identify analytes in Spanish/English. Runs fully in the browser.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  - **`backend/app/ai/hf_space.py`** — Cliente del HF Space (Gradio) donde vive medGemma. El Space devuelve texto libre, así que va por la ruta de prosa: `ai/prosa.py` limpia los tokens del modelo, detecta salida defectuosa (razonamiento filtrado, bucle, frase cortada) y envuelve el resultado en el campo `interpretacion`. Es la ruta por defecto sin salida estructurada; un modelo local declarado `=prosa` usa la misma.
65
  - **`backend/app/ai/claude.py`** — Ruta Claude vía tool use forzado: el `input_schema` es el JSON Schema de `InterpretacionClinica`, así que valida contra Pydantic sin regex.
66
  - **`data/valores_referencia.json`** — Reference ranges for 90 analytes per species.
 
60
  - **`frontend/src/ia.ts`** — Cliente tipado de `POST /api/interpret`; renderiza la salida estructurada (hallazgos, diferenciales con citas, banner de derivación). No construye el prompt (eso vive en el backend).
61
  - **`frontend/src/main.ts`** — Orquestación: carga los JSON, cablea eventos del formulario, dispara el análisis, exporta PDF.
62
  - **`frontend/src/ui.ts`** — Tab navigation (8 panels, 4 exam sub-tabs), swipe gestures, mobile/desktop field sync, collapsible panels.
63
+ - **`frontend/src/pdf-parser.ts`** — Client-side PDF extraction using PDF.js. 47 regex patterns to identify analytes in Spanish/English. Runs fully in the browser. También cablea el arrastrar-y-soltar sobre los paneles de exámenes.
64
+ - **pdf.js va vendorizado y la versión es un invariante.** Los ficheros de `assets/lib/pdfjs/`
65
+ se copian de la devDependency `pdfjs-dist` con `npm run vendor-pdfjs`, para que la versión que
66
+ usa el navegador y la que usan las pruebas sean la misma. **No volver a la 3.x**: leía mal los
67
+ CMap `ToUnicode` con destinos de un byte —fuera de especificación, pero los emiten informes de
68
+ laboratorio reales generados con Ghostscript— y devolvía cada carácter desplazado 8 bits
69
+ ('H' → U+4800), con lo que la importación fallaba entera con «No se encontraron datos
70
+ reconocibles». El desplazamiento **no se puede reparar a posteriori**: el '0' desplazado cae
71
+ en U+3000 y el extractor lo normaliza a espacio, así que una ALT de 260 U/L se leería como 26.
72
+ Por eso `textoIlegible()` detecta el caso y aborta en vez de importar números equivocados.
73
+ Fijado en `frontend/tests/pdf-parser.test.ts` con un PDF construido con esa anomalía.
74
+ - Un valor sólo se acepta en la línea de su etiqueta o en la línea `RESULTADO` que sigue a su
75
+ cabecera. La ventana ciega anterior saltaba de sección: importaba el cociente A/G como
76
+ albúmina y una densidad urinaria sacada de un párrafo interpretativo.
77
+ - **`frontend/src/panel-vacio.ts`** — Estado vacío de los seis paneles de exámenes **en escritorio**: la clase `.sin-datos` del `<section>` cambia el formulario por una zona de adjuntar (arrastrar / explorar / «Insertar resultados manualmente»). En móvil no aplica: el CSS que la enciende vive dentro de `@media (min-width: 1101px)`. Los importadores llaman a `revelarPanelDeCampo()` por cada valor inyectado, así que un panel que recibe datos sale del estado vacío solo. **Sólo depende de `dom.ts`**: lo importa `form-inject.ts`, que es la base común de los dos importadores, y colgarlo de `ui.ts` —que toca el DOM al cargarse— rompería sus tests.
78
  - **`backend/app/ai/hf_space.py`** — Cliente del HF Space (Gradio) donde vive medGemma. El Space devuelve texto libre, así que va por la ruta de prosa: `ai/prosa.py` limpia los tokens del modelo, detecta salida defectuosa (razonamiento filtrado, bucle, frase cortada) y envuelve el resultado en el campo `interpretacion`. Es la ruta por defecto sin salida estructurada; un modelo local declarado `=prosa` usa la misma.
79
  - **`backend/app/ai/claude.py`** — Ruta Claude vía tool use forzado: el `input_schema` es el JSON Schema de `InterpretacionClinica`, así que valida contra Pydantic sin regex.
80
  - **`data/valores_referencia.json`** — Reference ranges for 90 analytes per species.