11 KiB
Evidence canonica — struttura tipizzata per disambiguazione, schema linking e SQL
Superseded (2026-08-24). Questo documento conserva la storia della prima proposta. Il disegno approvato è
2026-08-24-evidence-restructuring-design.mde il relativo piano esecutivo è2026-08-24-evidence-restructuring.md.
Contesto e decisioni prese
ThothII ha già due livelli separati che non si parlano:
EvidenceDoc(harness/tht/evidence/model.py) — runtime: frontmatter piatto (id/title/tier/status/tables/concepts/sources) +bodymarkdown libero.tierdistingue solostructural|concept, insufficiente rispetto ai 6 tipi reali del corpus.- Pipeline corpus (
harness/tht/corpus/) — canonizzazione tecnica (hash, provenienza, chunking, vettorizzazione), agnostica rispetto al tipo di evidenza.
Il corpus reale (ChironeWp3/artifacts/evidence/) ha una tassonomia implicita in 6
directory (00-glossario, 10-domini-clinici, 20-valori-enum, 30-esempi-nlq,
40-mapping-semantico, 50-metadati-normalizzazione) ma:
- frontmatter piatto,
tierinadeguato; - file già rotti (
--invece di---, bullet• invece di-) cheEvidenceDoc.parserifiuterebbe; - al retrieval la struttura si perde:
tht search packproietta solotitle+ 400 char.
Decisioni (confermate nel brainstorming):
- Obiettivo: strutturare il contenuto runtime, non toccare la pipeline corpus.
- Forma: ibrido — frontmatter tipizzato + sezioni canoniche per
kind. - Tassonomia: doppia —
kind(contenuto) +applies_to(destinazioni:disambiguation,rewriting,schema_linking,sql_generation,memory). - Anchors come fonte primaria per il value-grounding in F4; LSH solo fallback.
- Approccio: contratto in
tht+ authoring sottile (niente app separata, niente client LLM diretto intht). - Modello sorgente→canonizzato (non sovrascrittura in place): file umani in
source_root/evidence/, canonizzati derivati inartifacts/evidence/, coerente con l'esistentetht evidence extract. - Review: batch con diff aggregato (approvazione per file).
- Rielaborazione: LLM-assistita via Pi (sessione di manutenzione + gate), con parte
deterministica in
tht.
Modello canonico v2
CanonicalEvidence (frontmatter tipizzato)
---
schema_version: 2
id: ev-dom-ablazione-see
title: Dominio Ablazione e SEE
kind: domain # glossario | domain | enum | example | mapping | normalization
applies_to: # destinazioni d'uso
- disambiguation # F1
- schema_linking # F4
- sql_generation # F6/F7
status: reviewed
language: it
concepts:
- term: ablazione
synonyms: [ablazione transcatetere, SEE, studio elettrofisiologico]
- term: fibrillazione atriale
synonyms: [FA]
tables:
- name: datawarehouse.fact_studio_elettrofisiologico_endocavitario_ablazione
role: fact
columns: [ablazione_transcatetere, cod_paz, num]
anchors:
- column: datawarehouse.fact_see_ablazione_procedura_patologia.patologia
value: ablazione
match: exact
sources: [...]
# provenienza del derivato (aggiunta dal canonicalize, non dall'umano):
source_file: 10-domini-clinici/ablazione.md
source_fingerprint: sha256:...
canonicalized_at: 2026-08-18T...
---
Il body resta markdown, ma con titoli di sezione canonici per kind:
glossario:## Definizionedomain:## Cosa rappresenta,## Schema a stella,## Granularità,## Domande di business tipicheenum:## Valori ammessiexample:## Domanda → SQL+## Nota clinicamapping:## Trasformazioni disponibilinormalization:## Regole di normalizzazione
Le sezioni canoniche permettono al retrieval di estrarre solo la sezione rilevante per fase invece di 400 caratteri generici.
kind vs applies_to
kinddescrive il contenuto (i 6 tipi già impliciti).applies_todescrive quando usarlo. Esempi:enum-tipo-interventoèkind: enummaapplies_to: [disambiguation, sql_generation]; unexampleèapplies_to: [sql_generation, memory].
Modello a 3 livelli
source_root/evidence/*.md (umano, libero, può essere sporco)
│ tht evidence canonicalize (deterministico + LLM via Pi + review batch)
▼
artifacts/evidence/*.md (canonico, validato, derivato, rigenerabile)
│ tht evidence index (esistente)
▼
corpus / vector store (vettorializzato dal canonico, mai dal sorgente)
Il canonizzato porta source_file + source_fingerprint: se il sorgente cambia, la
canonizzazione ripropone il diff; se invariato, no-op.
Componenti da creare/modificare
1. harness/tht/evidence/model.py (modifica)
- Aggiungere
CanonicalEvidence(pydantic, v2) conschema_version,kind,applies_to,concepts[]({term, synonyms[]}),tables[]({name, role, columns[]}),anchors[]({column, value, match}),source_file,source_fingerprint,canonicalized_at. - Validatore strict:
kindammesso,applies_toammesso,anchors[].columndeve essereschema.colonnaben formato,matchin{exact, contains, regex, substring}. EvidenceDocv1 resta per leggere il sorgente e per retro-compatibilità dei vecchi canonizzati;CanonicalEvidenceè un modello separato, non una sottoclasse.- Validatore che garantisce
source_fingerprint= sha256 del contenuto sorgente.
2. harness/tht/evidence/lint.py (nuovo, deterministico)
lint_source(path) -> list[Diagnostic]: frontmatter rotto,tier/statusnon validi, bullet Unicode, campi mancanti,tablesnon qualificate con schema, concetti senza sinonimi, sezioni non canoniche per ilkindatteso.- Exit code 0 se nessun errore, 1 se warning, 2 se errori. Nessun LLM.
3. harness/tht/evidence/canonicalize.py (nuovo)
plan(sources, artifacts) -> CanonicalizePlan: confronta fingerprint dei sorgenti con i canonizzati esistenti, produce la lista dei file da (ri)canonizzare.render_proposal(source, llm_completions) -> CanonicalEvidence: assembla il canonizzato da parsing deterministico + campi semantici forniti da Pi.apply(plan, approved_ids) -> None: scrive solo i canonizzati approvati inartifacts/evidence/, atomico per file, mantiene la gerarchia per dominio.diff(source, candidate) -> str: diff markdown per il gate.
4. harness/tht/vectorstore/records.py (modifica)
evidence_records(): metadata ora includekind,applies_to,anchors(non solostatus/tier/tables/concepts).- Il
contentdi ogni record resta title+body, ma per file con sezioni canoniche si indicizza anche un record per sezione (idevidence:<id>:<sezione>) così il retrieval può restringere per sezione oltre che per documento.
5. harness/tht/search/__init__.py + cli/search_cmd.py (modifica)
SearchResultecombined_searchaccettanoapplies_tocome filtro metadata.tht search pack: la sezione "Evidence rilevanti" ora proiettakind+ sezione canonica pertinente (non solo excerpt generico); usaapplies_toper non mischiare destinazioni.tht search find --kind evidence --applies-to <dest>per il retrieval mirato.
6. harness/tht/cli/evidence_cmd.py (modifica)
- Nuovi comandi:
tht evidence lint --source <path|dir>— diagnostica deterministica.tht evidence canonicalize plan --source-root <dir> --json— piano di (ri)canonizzazione.tht evidence canonicalize apply --plan <file> --approved <ids> --json— applica.
--jsonsempre pristine (solo JSON su stdout), come da contratto di progetto.
7. harness/.pi/extensions/tht-gate.js (modifica)
- Nuovo tool
reviewer_evidence_batch: riceve il piano + i diff aggregati e presenta un multiselect per file (approva/rifiuta/richiedi modifica). Le scelte approvate vengono persistite tramitetht evidence canonicalize apply. - Aggiungere
tht evidence canonicalize applyalla FORBIDDEN anti-bypass list (il modello non può applicare canonizzazioni senza review).
8. Sessione di manutenzione Pi (nuova skill o sezione SKILL)
- Una skill dedicata
tht-evidence-canonicalize(o un comando slash nel gate) descrive la sessione di manutenzione: il modello legge i sorgenti marcati dal piano, propone i campi semantici (kind,applies_to,conceptscon sinonimi,tablescon ruolo,anchors) e li invia alreviewer_evidence_batch. - Il gate è l'unico canale di review; il modello non scrive mai direttamente
artifacts/evidence/.
9. harness/.pi/skills/tht-sessione/SKILL.md (modifica)
- Aggiornare i punti F1/F4/F6-F7 dove il modello legge evidence: spiegare che l'evidence
canonica espone
kind/applies_to/anchors, che glianchorssono la fonte primaria per il value-grounding in F4, e che le sezioni canoniche vanno citate per destinazione. - Aggiungere il nuovo tool
reviewer_evidence_batchalla lista dei tool disponibili.
Migrazione del corpus (incrementale, v1+v2 convivono)
CanonicalEvidence(v2) convive conEvidenceDoc(v1):lintsegnala i non-canonici ma nulla si rompe;load_evidence_dircarica entrambi.- Convertire a lotti, partendo da
20-valori-enume10-domini-clinici(impatto maggiore su F1/F4, anchors più ricchi). - Il canonizzato derivato in
artifacts/evidence/sostituisce progressivamente il file sorgente mirrorato; finché un sorgente non è canonizzato,extractcontinua a rispecchiare il v1 come oggi.
Ordine di implementazione
CanonicalEvidence+lint(TDD, nessun LLM).canonicalize.py(plan/apply/diff) + comandi CLI (TDD).records.py+ filtroapplies_toinsearch+ proiezione pack (TDD).- Gate
reviewer_evidence_batch+ skill manutenzione Pi. - Aggiornamento
SKILL.mdtht-sessione. - Conversione primo lotto (
enum+domain) con review batch.
Verifica
cd harness && .venv/bin/pytest -q— test nuovi per model/lint/canonicalize/records/search.node --testsul gate perreviewer_evidence_batche anti-bypass.- Su un campione del corpus:
tht evidence lintriporta i file rotti (frontmatter--, bullet Unicode) senza crash;tht evidence canonicalize plan --jsonproduce piano corretto;applycon fingerprint invariato è no-op. tht search pack "<domanda ablazione>"mostra evidence conkind/sezione pertinente e gli anchor presenti;tht search find --kind evidence --applies-to schema_linkingrestituisce solo evidence pertinenti.- Live: una sessione F4 su psd usa un anchor canonico per il value-grounding invece del
solo LSH (verificabile dal
reviewer_decidecon opzionivalue_groundedprovenienti dall'evidence, non dal ranking LSH). git diff --checke typecheck/ruff puliti.