Files
ThothII/harness/.pi/skills/tht-sessione/sql-generation.md
T
marcopan de61034a8d feat(harness): riscrittura skill tht-sessione (F1-F8 + 4 sottomoduli)
Skill ex-novo che riflette Thoth (non copia di ChironeWp3):
- vocabolario widget-descriptor (reviewer_select/decide/confirm) invece di 'dialog native'
- D11 save-one in F2 (upsert mirato vs full resync)
- D14a value_grounded (LSH multi-colonna non collassa) + D14b concept_formula in F4
- D13 free-text e D15 rollback nelle discipline trasversali
- memory vive SOLO nel vectordb (drop registry, spec 5): save-one/promote senza registry
- F8 datamart onesto (stub NotImplementedError)

Sottomoduli cte/memoria/rewriting/sql-generation portati adattando nsp->tht, con
i vincoli precisi trasferiti fedelmente (max 5 memorie, solo 3 tipi riusabili,
CTE solo WITH senza SELECT, dim_time join non aritmetica, sql_final pulito).

Verifica: zero residui nsp/chirone/psd nella skill; ogni 'tht <cmd>' citato e'
registrato (correzione: 'tht formula retrieve' era inesistente -> riformulato in
'ricerca nelle evidence'). Suite: 165 passed.
2026-06-27 14:24:20 +02:00

54 lines
2.8 KiB
Markdown

# Tecnica di generazione del SQL finale
Adattata dallo step "query generation" di AV-SQL (divide-and-conquer ricorsivo)
e dalla sua checklist di revisione.
## Generazione (divide-and-conquer)
1. **Dividi**: scomponi la domanda riscritta in sotto-domande, ognuna mirata a
un pezzo di informazione o logica (una popolazione, un filtro, un aggregato).
2. **Conquista**: per ogni sotto-domanda formula uno pseudo-SQL, con segnaposto
per le sotto-domande non ancora risolte. I CTE gia' testati in Fase 6 sono i
mattoni preferenziali: riusali per nome, col loro esito noto.
3. **Ricombina**: sostituisci i segnaposto dal basso verso l'alto fino al SQL
completo. Il SQL finale puo' includere i CTE nel proprio WITH.
4. Dialetto: PostgreSQL. Copia ESATTAMENTE i nomi di tabelle e colonne dal
contesto schema; mai inventare oggetti.
Il file `sessions/<id>/sql_final.sql` deve contenere SOLO il SQL, pulito e
copiabile: niente commenti di razionale (quello vive negli artefatti di audit).
## Dimensione tempo (analisi per anno/mese/trimestre)
Le fact table hanno `data_time_key` (`integer`, formato `YYYYMMDD`): è la FK
verso `dim_time.day_key`. **Questa FK non è dichiarata** nel DWH (le fact hanno
`foreign_keys: []`), quindi non comparirà in `schema_linking.json`: vai aggiunta
a mano nel join.
- Per estrarre anno, mese, trimestre, semestre ecc. fai
`JOIN dim_time dt ON dt.day_key = <fact>.data_time_key` e usa le colonne della
dimensione: `dt.year`, `dt.month`, `dt.quarter`, `dt.semester`, `dt.full_date`,
`dt.month_name_it`, `dt.year_month`.
- **Non** fare aritmetica sulla chiave (es. `data_time_key / 10000` per l'anno):
funziona per caso ma è fragile e si rompe appena serve formattare una data o
fare cast. Usa sempre `dim_time`.
- "Ultimi N anni dall'anno più recente": `dt.year >= (SELECT MAX(year) FROM
dim_time WHERE day_key IN (SELECT data_time_key FROM <fact>)) - (N-1)`, oppure
calcola il max anno sulle righe effettivamente presenti nella fact.
## Checklist di revisione (su errori o risultati sospetti)
- Le colonne restituite rispondono esattamente alla domanda?
- I filtri (WHERE/HAVING) riflettono tutte le condizioni della domanda riscritta?
- Aggregazioni, raggruppamenti e ordinamenti sono quelli richiesti?
- Risultato vuoto o zero: quasi sempre indica un problema in condizioni o join.
Verifica i valori dei filtri con `tht search "<valore>"` (match sui valori reali).
- I join seguono quelli promossi in schema_linking.json? (eccezione: la FK
`data_time_key → dim_time.day_key` non è dichiarata, vedi sezione tempo.)
- Analisi temporali: stai usando `JOIN dim_time` e non aritmetica sulla chiave?
Ogni revisione sostanziale va registrata con:
`reviewer_decide(options:[{label:"Registra revisione", type:"sql_revised",
subject:"sql_final", detail:"<cosa e' cambiato>", rationale:"<perche'>"}],
allow_other:false)`.