Spaces:
Sleeping
Sleeping
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
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.
|