From 1d045a44a65d4061987079c174165390a6636ecf Mon Sep 17 00:00:00 2001 From: mptyl Date: Tue, 18 Aug 2026 09:52:53 +0200 Subject: [PATCH] docs: add canonical Evidence structure design Co-authored-by: CommandCodeBot --- .../2026-08-18-evidence-canonica-design.md | 211 ++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 docs/plans/2026-08-18-evidence-canonica-design.md diff --git a/docs/plans/2026-08-18-evidence-canonica-design.md b/docs/plans/2026-08-18-evidence-canonica-design.md new file mode 100644 index 00000000..012f89c4 --- /dev/null +++ b/docs/plans/2026-08-18-evidence-canonica-design.md @@ -0,0 +1,211 @@ +# Evidence canonica — struttura tipizzata per disambiguazione, schema linking e SQL + +## 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`) + `body` markdown libero. `tier` + distingue solo `structural|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, `tier` inadeguato; +- file già rotti (`--` invece di `---`, bullet `•⁠ ⁠` invece di `-`) che `EvidenceDoc.parse` + rifiuterebbe; +- al retrieval la struttura si perde: `tht search pack` proietta solo `title` + 400 char. + +**Decisioni (confermate nel brainstorming):** + +1. **Obiettivo**: strutturare il *contenuto* runtime, non toccare la pipeline corpus. +2. **Forma**: ibrido — frontmatter tipizzato + sezioni canoniche per `kind`. +3. **Tassonomia**: doppia — `kind` (contenuto) + `applies_to` (destinazioni: + `disambiguation`, `rewriting`, `schema_linking`, `sql_generation`, `memory`). +4. **Anchors come fonte primaria** per il value-grounding in F4; LSH solo fallback. +5. **Approccio**: contratto in `tht` + authoring sottile (niente app separata, niente + client LLM diretto in `tht`). +6. **Modello sorgente→canonizzato** (non sovrascrittura in place): file umani in + `source_root/evidence/`, canonizzati derivati in `artifacts/evidence/`, coerente con + l'esistente `tht evidence extract`. +7. **Review**: batch con diff aggregato (approvazione per file). +8. **Rielaborazione**: LLM-assistita via Pi (sessione di manutenzione + gate), con parte + deterministica in `tht`. + +## Modello canonico v2 + +### `CanonicalEvidence` (frontmatter tipizzato) + +```yaml +--- +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`: `## Definizione` +- `domain`: `## Cosa rappresenta`, `## Schema a stella`, `## Granularità`, `## Domande di business tipiche` +- `enum`: `## Valori ammessi` +- `example`: `## Domanda → SQL` + `## Nota clinica` +- `mapping`: `## Trasformazioni disponibili` +- `normalization`: `## 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` + +- `kind` descrive il *contenuto* (i 6 tipi già impliciti). +- `applies_to` descrive *quando usarlo*. Esempi: `enum-tipo-intervento` è `kind: enum` ma + `applies_to: [disambiguation, sql_generation]`; un `example` è + `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) con `schema_version`, `kind`, + `applies_to`, `concepts[]` (`{term, synonyms[]}`), `tables[]` + (`{name, role, columns[]}`), `anchors[]` (`{column, value, match}`), `source_file`, + `source_fingerprint`, `canonicalized_at`. +- Validatore strict: `kind` ammesso, `applies_to` ammesso, `anchors[].column` deve + essere `schema.colonna` ben formato, `match` in `{exact, contains, regex, substring}`. +- `EvidenceDoc` v1 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`/`status` non validi, + bullet Unicode, campi mancanti, `tables` non qualificate con schema, concetti senza + sinonimi, sezioni non canoniche per il `kind` atteso. +- 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 in + `artifacts/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 include `kind`, `applies_to`, `anchors` (non solo + `status/tier/tables/concepts`). +- Il `content` di ogni record resta title+body, ma per file con sezioni canoniche si + indicizza anche un record per sezione (id `evidence::`) così il retrieval + può restringere per sezione oltre che per documento. + +### 5. `harness/tht/search/__init__.py` + `cli/search_cmd.py` (modifica) +- `SearchResult` e `combined_search` accettano `applies_to` come filtro metadata. +- `tht search pack`: la sezione "Evidence rilevanti" ora proietta `kind` + sezione + canonica pertinente (non solo excerpt generico); usa `applies_to` per non mischiare + destinazioni. +- `tht search find --kind evidence --applies-to ` per il retrieval mirato. + +### 6. `harness/tht/cli/evidence_cmd.py` (modifica) +- Nuovi comandi: + - `tht evidence lint --source ` — diagnostica deterministica. + - `tht evidence canonicalize plan --source-root --json` — piano di + (ri)canonizzazione. + - `tht evidence canonicalize apply --plan --approved --json` — applica. +- `--json` sempre 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 tramite `tht evidence canonicalize apply`. +- Aggiungere `tht evidence canonicalize apply` alla 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`, `concepts` con sinonimi, `tables` con ruolo, + `anchors`) e li invia al `reviewer_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 gli `anchors` sono la fonte primaria + per il value-grounding in F4, e che le sezioni canoniche vanno citate per destinazione. +- Aggiungere il nuovo tool `reviewer_evidence_batch` alla lista dei tool disponibili. + +## Migrazione del corpus (incrementale, v1+v2 convivono) + +- `CanonicalEvidence` (v2) convive con `EvidenceDoc` (v1): `lint` segnala i non-canonici + ma nulla si rompe; `load_evidence_dir` carica entrambi. +- Convertire a lotti, partendo da `20-valori-enum` e `10-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, `extract` continua a + rispecchiare il v1 come oggi. + +## Ordine di implementazione + +1. `CanonicalEvidence` + `lint` (TDD, nessun LLM). +2. `canonicalize.py` (plan/apply/diff) + comandi CLI (TDD). +3. `records.py` + filtro `applies_to` in `search` + proiezione pack (TDD). +4. Gate `reviewer_evidence_batch` + skill manutenzione Pi. +5. Aggiornamento `SKILL.md` tht-sessione. +6. Conversione primo lotto (`enum` + `domain`) con review batch. + +## Verifica + +- `cd harness && .venv/bin/pytest -q` — test nuovi per model/lint/canonicalize/records/search. +- `node --test` sul gate per `reviewer_evidence_batch` e anti-bypass. +- Su un campione del corpus: `tht evidence lint` riporta i file rotti (frontmatter `--`, + bullet Unicode) senza crash; `tht evidence canonicalize plan --json` produce piano + corretto; `apply` con fingerprint invariato è no-op. +- `tht search pack ""` mostra evidence con `kind`/sezione pertinente e + gli anchor presenti; `tht search find --kind evidence --applies-to schema_linking` + restituisce solo evidence pertinenti. +- Live: una sessione F4 su psd usa un anchor canonico per il value-grounding invece del + solo LSH (verificabile dal `reviewer_decide` con opzioni `value_grounded` provenienti + dall'evidence, non dal ranking LSH). +- `git diff --check` e typecheck/ruff puliti.