# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Missione Convertire PDF digitali in Markdown **perfetto per la vettorizzazione RAG**, senza revisione manuale. L'output deve essere testo pulito, strutturato in sezioni semanticamente coerenti, privo di artefatti, pronto per chunking e indicizzazione in un vector store. **Non supportato:** PDF scansionati (immagini), PDF protetti da password. --- ## Regole invarianti - **Lingua:** Rispondi sempre in italiano. - **Venv:** Usa `.venv/bin/python` o `source .venv/bin/activate`. Mai `pip`/`python` di sistema. - **`raw.md` immutabile:** Non modificare mai `raw.md`. La copia di lavoro è sempre `clean.md`. - **Obiettivo zero revisioni:** ogni miglioramento alla pipeline deve ridurre i casi in cui il `clean.md` richiede correzioni manuali. --- ## Setup ```bash python -m venv .venv source .venv/bin/activate pip install -r requirements.txt # Java 11+ richiesto da opendataloader-pdf sudo apt install default-jdk # Ubuntu/Debian/WSL java -version ``` --- ## Comandi ```bash # Converti un PDF (posizionalo prima in sources/.pdf) .venv/bin/python conversione/ --stem # Tutti i PDF in sources/ .venv/bin/python conversione/ # Forza riesecuzione (sovrascrive clean.md esistente) .venv/bin/python conversione/ --stem --force # Validazione batch di tutti gli stem .venv/bin/python conversione/ validate # Validazione con dettaglio penalità .venv/bin/python conversione/ validate --detail # Rimuove l'output di uno stem bash conversione/clear.sh ``` `--stem` = nome file PDF senza estensione. --- ## Architettura Il codice è organizzato in `conversione/__main__.py` (entry point) e il package `conversione/_pipeline/` (logica modulare). ``` conversione/ ├── __main__.py # Entry point unificato: convert + validate ├── clear.sh # Rimuove output di uno stem └── _pipeline/ ├── __init__.py # Re-export pubblico ├── extract.py # _check_deps() + validate_pdf() + convert_pdf() ├── runner.py # run() — orchestrazione 4 fasi ├── structure.py # analyze() + rilevamento lingua e struttura ├── report.py # build_report() → report.json ├── validator.py # validate() + _score() + _grade() ├── _apply.py # apply_transforms() — orchestratore in ordine semantico ├── _constants.py # Regex compilate e mappe statiche condivise ├── _encoding.py # Gruppo 1: PUA font Symbol, accenti LaTeX, simboli SI ├── _artifacts.py # Gruppo 2: immagini, BR, footnote, URL, righe ricorrenti, watermark ├── _headers.py # Gruppo 3: normalizzazione livelli, concat, bold, ALLCAPS ├── _structure.py # Gruppo 4: TOC, ALLCAPS→##, sezioni numerate, math, articoli ├── _text.py # Gruppo 5: merge paragrafi, whitespace, poesia, versi ├── _finish.py # Gruppo 6: header vuoti/garbage, formula-header, frontmatter └── _helpers.py # Funzioni pure condivise (_sentence_case, _is_allcaps_line, ecc.) ``` ### `__main__.py` — entry point unificato CLI con due modalità: conversione (default, `--stem`, `--force`) e validazione (subcommand `validate`, con stems opzionali e `--detail`). Aggiunge `conversione/` a `sys.path` e delega a `_pipeline`. Uso: `python conversione/ [--stem X] [--force]` oppure `python conversione/ validate [X] [--detail]`. ### `_pipeline/extract.py` — fronte PDF Raggruppa in un unico modulo le tre responsabilità legate al PDF: `_check_deps()` verifica che `opendataloader-pdf` e Java 11+ siano disponibili; `validate_pdf(pdf_path) -> (bool, str)` controlla esistenza, dimensione e presenza di testo digitale; `convert_pdf(pdf_path, out_dir) -> Path` invoca opendataloader-pdf con i parametri RAG-ottimali e restituisce il percorso del `.md` prodotto. Auto-rileva i PDF taggati (Word/InDesign) per attivare `use_struct_tree`. ### `_pipeline/_apply.py` — cuore della pipeline Contiene `apply_transforms(text) -> (text, stats)` che chiama ~35 trasformazioni atomiche (`_t_*`) in ordine semantico fisso — **non modificare l'ordine senza capire le dipendenze tra gruppi**. Ogni `_t_*` vive nel modulo del suo gruppo; le costanti regex compilate stanno in `_constants.py`. Ordine logico dei gruppi: 1. **Encoding** (`_encoding.py`) — PUA font Symbol, accenti backtick LaTeX, moltiplicazione, micro 2. **Pulizia artefatti** (`_artifacts.py`) — immagini, `
`, footnote superscript, URL, box symbol, righe ricorrenti, watermark 3. **Struttura header** (`_headers.py`) — fix header+body concatenati, Capitolo inline, normalizzazione livelli numerati, `####`→`###`, bold, ALL-CAPS 4. **Costruzione struttura** (`_structure.py`) — TOC rimosso, ALL-CAPS→`##`, sezioni numerate→`###`, ambienti matematici, articoli 5. **Testo** (`_text.py`) — merge paragrafi spezzati, whitespace, blank lines, poesia, versi 6. **Rifinitura** (`_finish.py`) — header vuoti, garbage header, merge titoli isolati, frontmatter Flag automatico: se il testo contiene "Esercizi/Problems/Homework", `_t_numbered_sections` non converte `- N. testo` in header (sono numerazioni di esercizi, non titoli). ### `_pipeline/structure.py` — analisi struttura `analyze(md_path) -> dict` conta `#`/`##`/`###`, rileva lingua (it/en/fr/de/es), sceglie `strategia_chunking`: | Strategia | Condizione | |-----------|------------| | `h3_aware` | ≥5 `###` | | `h2_paragraph_split` | ≥3 `##`, pochi `###` | | `paragraph` | struttura rada | | `sliding_window` | testo piatto | ### `_pipeline/report.py` — metriche qualità `build_report()` genera `report.json` con: statistiche trasformazioni, struttura, distribuzione lunghezze sezioni (`min`/`p25`/`mediana`/`p75`/`max`), anomalie (bare headers, sezioni corte/lunghe), residui con esempi (backtick, dot-leader, URL, `
`, simboli encoding, formule inline, footnote, PUA). ### `validate.py` — scoring Assegna un voto 0–100 (A/B/C/D/F) leggendo `report.json`. Penalità principali: | Problema | Penalità | Cap | |----------|----------|-----| | Struttura assente (livello 0) | −40 | — | | Struttura piatta (livello 1) | −15 | — | | Backtick residui | −2/cad | −20 | | Caratteri PUA font Symbol | −2/cad | −20 | | Dot-leader | −5/cad | −10 | | URL/watermark | −5/cad | −15 | | `
` inline | −2/cad | −15 | | Bare headers | −3/cad | −15 | --- ## Cosa rende un Markdown perfetto per la vettorizzazione - **Struttura semantica:** header Markdown = confini naturali dei chunk; ogni sezione è un'unità concettuale. - **Testo pulito:** nessun backtick, dot-leader, footnote superscript, carattere PUA, `
`. - **Paragrafi interi:** nessuna frase troncata da salto pagina PDF. - **Formule e simboli:** lettere greche e operatori in Unicode standard, non in font-encoding privato. - **Nessun rumore strutturale:** TOC, header/footer ripetuti, URL, watermark — tutto rimosso. - **Gerarchia corretta:** h1/h2/h3 riflettono la struttura logica, non il layout tipografico. --- ## Linee guida per migliorare la pipeline Quando si aggiunge una trasformazione in `apply_transforms()`: - Ogni `_t_*` deve restituire `(testo, n_modifiche)` — il contatore alimenta `report.json`. - Implementare la funzione nel modulo del gruppo corretto (`_encoding.py`, `_artifacts.py`, ecc.), importarla in `_apply.py` e inserire la coppia `("stat_key", _t_nuova)` nella lista `_transforms` nel punto logicamente corretto. - Compilare i pattern regex in `_constants.py` come costanti di modulo, mai dentro la funzione. - Testare con `.venv/bin/python conversione/ --stem --force` e confrontare `report.json`. - Un nuovo tipo di artefatto: prima aggiungerlo come residuo in `report.py` (funzione `_scan`), poi implementare la `_t_*` che lo rimuove. - I residui in `report.py` usano `_MATH_SYMBOLS_RE`, `_EXERCISE_TRIGGER_RE` e `_MATH_HDR_RE` da `transforms._constants` — non ridefinirli localmente. --- ## Skills custom - `/prepare-md ` — corregge `clean.md` quando la pipeline non basta: sillabazione, artefatti residui, header malformati, gerarchia incoerente.