# Appunti di sviluppo - ICS-SimLab Config Generator ## 2026-01-28 - Refactoring pipeline configurazione ### Obiettivo Ottimizzare la pipeline di creazione configuration.json: - Spostare enrich_config nella fase di generazione configurazione - Riscrivere modelli Pydantic per validare struttura reale - Aggiungere validazione semantica per HMI monitors/controllers ### Modifiche effettuate #### Nuovi file creati: - `models/ics_simlab_config_v2.py` - Modelli Pydantic v2 completi - Coercizione tipo sicura: solo stringhe numeriche (^[0-9]+$) convertite a int - Logging quando avviene coercizione - Flag --strict per disabilitare coercizione - Union discriminata per connessioni TCP vs RTU - Validatori per nomi unici e riferimenti HIL - `tools/semantic_validation.py` - Validazione semantica HMI - Verifica outbound_connection_id esiste - Verifica IP target corrisponde a device reale - Verifica registro esiste su device target - Verifica value_type e address corrispondono - Nessuna euristica: se non verificabile, fallisce con errore chiaro - `tools/build_config.py` - Entrypoint pipeline configurazione - Input: configuration.json raw - Step 1: Validazione Pydantic + normalizzazione tipi - Step 2: Arricchisci con monitors/controllers (usa enrich_config esistente) - Step 3: Validazione semantica - Step 4: Scrivi configuration.json (unico output, versione completa) - `tests/test_config_validation.py` - Test automatici - Test Pydantic su tutti e 3 gli esempi - Test coercizione tipo port/slave_id - Test idempotenza enrich_config - Test rilevamento errori semantici #### File modificati: - `main.py` - Integra build_config dopo generazione LLM - Output raw in configuration_raw.json - Chiama build_config per produrre configuration.json finale - Flag --skip-enrich per output raw senza enrichment - Flag --skip-semantic per saltare validazione semantica - `build_scenario.py` - Usa build_config invece di enrich_config diretto ### Osservazioni importanti #### Inconsistenze tipi nelle configurazioni esempio: - water_tank linea 270: `"port": "502"` (stringa invece di int) - water_tank linea 344: `"slave_id": "1"` (stringa invece di int) - La coercizione gestisce questi casi loggando warning #### Struttura HMI registers: - HMI registers NON hanno campo `io` (a differenza di PLC registers) - HMI monitors hanno `interval`, controllers NO #### Connessioni RTU: - Non hanno IP, usano `comm_port` - Validazione semantica salta connessioni RTU (niente lookup IP) ### Comandi di verifica ```bash # Test su esempio water_tank python3 -m tools.build_config \ --config examples/water_tank/configuration.json \ --out-dir outputs/test_water_tank \ --overwrite # Test su tutti gli esempi python3 -m tools.build_config \ --config examples/smart_grid/logic/configuration.json \ --out-dir outputs/test_smart_grid \ --overwrite python3 -m tools.build_config \ --config examples/ied/logic/configuration.json \ --out-dir outputs/test_ied \ --overwrite # Build scenario completo python3 build_scenario.py --out outputs/scenario_run --overwrite # Esegui test python3 -m pytest tests/test_config_validation.py -v # Verifica fix callback PLC python3 validate_fix.py ``` ### Note architetturali - Modelli vecchi (`models/ics_simlab_config.py`) mantenuti per compatibilità IR pipeline - `enrich_config.py` non modificato, solo wrappato da build_config - Pipeline separata: - A) config pipeline: LLM -> Pydantic -> enrich -> semantic -> configuration.json - B) logic pipeline: configuration.json -> IR -> compile_ir -> validate_logic - Output unico: configuration.json (versione arricchita e validata) ## 2026-01-28 - Integrazione validazione semantica nel repair loop LLM ### Problema - LLM genera HMI monitors/controllers con id che NON corrispondono ai registri PLC target - Esempio: HMI monitor usa `plc1_water_level` ma PLC ha `water_tank_level_reg` - build_config fallisce con errori semantici, pipeline si blocca ### Soluzione Integrazione errori semantici nel loop validate/repair di main.py: 1. LLM genera configurazione raw 2. Validazione JSON + patches (come prima) 3. Esegue build_config con --json-errors 4. Se errori semantici (exit code 2), li passa al repair LLM 5. LLM corregge e si riprova (fino a --retries) ### File modificati - `main.py` - Nuovo `run_pipeline_with_semantic_validation()`: - Unifica loop JSON validation + semantic validation - `run_build_config()` cattura errori JSON da build_config --json-errors - Errori semantici passati a repair_with_llm come lista errori - Exit code 2 = errori semantici parsabili, altri = errore generico - `tools/build_config.py` - Aggiunto flag `--json-errors`: - Output errori semantici come JSON `{"semantic_errors": [...]}` - Exit code 2 per errori semantici (distingue da altri fallimenti) - `prompts/prompt_json_generation.txt` - Nuova regola CRITICAL: - HMI monitor/controller id DEVE corrispondere ESATTAMENTE a registers[].id sul PLC target - Build order: definire PLC registers PRIMA, poi copiare id/value_type/address verbatim - `prompts/prompt_repair.txt` - Nuova sezione I): - Istruzioni per risolvere SEMANTIC ERROR "Register 'X' not found on plc 'Y'" - Audit finale include verifica cross-device HMI-PLC ### Comportamento deterministico preservato - Nessun fuzzy matching o rinomina euristica - Validazione semantica rimane strict: se id non corrisponde, errore - Il repair è delegato al LLM con errori espliciti ### Comandi di verifica ```bash # Pipeline completa con repair semantico (fino a 3 tentativi) python3 main.py --input-file prompts/input_testuale.txt --retries 3 # Verifica che outputs/configuration.json esista e sia valido python3 -m tools.build_config \ --config outputs/configuration.json \ --out-dir /tmp/test_final \ --overwrite # Test unitari python3 -m pytest tests/test_config_validation.py -v ```