docs: add architecture diagrams and evidence guide

This commit is contained in:
2026-08-26 08:09:06 +02:00
parent dbd7787573
commit ec061c42d4
3 changed files with 365 additions and 0 deletions
+174
View File
@@ -0,0 +1,174 @@
# Componenti, moduli e flussi
Questa pagina completa la [panoramica dell'architettura](overview.md) con la struttura dei moduli e i flussi che attraversano ThothII. I diagrammi descrivono il codice corrente, non un'architettura futura.
## Moduli e dipendenze
Il frontend comunica con il backend tramite REST e SSE. Il backend non possiede la persistenza delle sessioni: avvia Pi, invoca la CLI `tht` e inoltra gli eventi. L'harness contiene il workflow, la CLI Python e gli adattatori verso DWH e vector store.
```mermaid
flowchart LR
FE["frontend/\nReact + Vite"] -->|REST + SSE| BE["backend/\nFastify + TypeScript"]
BE -->|RPC stdin/stdout| PI["Pi\n--mode rpc"]
BE -->|subprocess\nJSON stdout| THT["harness/tht\nCLI Python"]
PI --> EXT["harness/.pi/extensions/\ntht-gate.js"]
EXT --> SKILL["harness/.pi/skills/\ntht-sessione"]
EXT --> THT
THT --> FS["Sessioni e artefatti\nworkspace repository"]
THT --> DWH["DWH\nread-only"]
THT --> VDB["Qdrant / vector store"]
BE --> CFG["settings.json\nworkspace registry"]
FE -.->|renderizza widget| EXT
```
Dipendenze principali:
| Modulo | Dipende da | Responsabilità |
| --- | --- | --- |
| `frontend/` | API REST e SSE del backend | UI, widget di gate e transcript in memoria |
| `backend/src/` | Pi, `tht`, configurazione e workspace registry | Trasporto, lifecycle delle sessioni e API |
| `harness/.pi/` | Pi e `tht phase` | Orchestrazione del workflow e gate human-in-the-loop |
| `harness/tht/` | filesystem, DWH e vector store | Persistenza, CLI, evidence, schema e preprocessing |
| workspace repository | `source/`, `curated/`, manifest e artefatti | Sorgente versionata delle evidence e output di sessione |
## Sequenza di una sessione
Il percorso principale parte da una domanda dell'utente e termina con un evento SSE. Le decisioni del revisore rientrano nello stesso canale e vengono persistite dall'harness.
```mermaid
sequenceDiagram
actor U as Utente o revisore
participant FE as Frontend
participant BE as Backend
participant PI as Pi RPC
participant THT as CLI tht
participant WS as Workspace
participant DWH as DWH
U->>FE: Invia domanda o decisione di gate
FE->>BE: POST session / risposta widget
BE->>PI: RPC input o prompt di resume
PI->>THT: phase/session/evidence commands
THT->>WS: Legge e scrive artefatti di fase
THT->>DWH: Introspezione o query read-only
DWH-->>THT: Schema, risultati o diagnostica
THT-->>PI: JSON e stato della fase
PI-->>BE: Eventi RPC e widget descriptor
BE-->>FE: SSE text_delta, info, ui_request
FE-->>U: Testo, artefatto o richiesta di revisione
```
Il backend usa `ThtRunner` per i subprocess della CLI, `PiProcessManager` per un processo Pi per sessione, `SessionBridge` per adattare gli eventi RPC e `SseHub` per distribuirli ai client.
## Classi principali del backend
Il diagramma mostra le classi che compongono il ponte tra browser, Pi e `tht`. Le route Fastify ricevono le richieste e delegano a questi servizi.
```mermaid
classDiagram
class ThtRunner {
+buildArgv(command, args) string[]
+run(args) Promise~ThtResult~
+sessionShow(id) Promise~unknown~
}
class PiProcessManager {
-runtimes Map
+spawnFor(sessionId, mode) SessionRuntime
+resume(sessionId, tht) Promise~SessionRuntime~
+stop(sessionId) Promise~void~
}
class SessionBridge {
+handleRpcEvent(event) ClientEvent
+handleUiResponse(response) Promise~void~
}
class SseHub {
+subscribe(sessionId) AsyncIterable
+publish(sessionId, event) void
+close(sessionId) void
}
class SessionRoutes {
+createSession(request) Response
+resumeSession(id) Response
+postInput(id, input) Response
}
class WorkspaceRegistry {
+list() Workspace[]
+resolve(id) Workspace
}
class SettingsStore {
+get() Settings
+update(patch) Settings
}
class App {
+buildApp() FastifyInstance
}
App --> SessionRoutes
App --> WorkspaceRegistry
App --> SettingsStore
SessionRoutes --> PiProcessManager
SessionRoutes --> ThtRunner
SessionRoutes --> SseHub
PiProcessManager --> SessionBridge
PiProcessManager --> ThtRunner
SessionBridge --> SseHub
```
## Moduli Python della CLI `tht`
La CLI è composta da comandi Typer e da moduli di dominio. `cli/` traduce gli argomenti in operazioni; `evidence/`, `session/`, `db/`, `adapters/` e gli altri package contengono la logica applicativa.
```mermaid
flowchart TB
MAIN["tht/cli/__init__.py"] --> CMD["tht/cli/*_cmd.py"]
CMD --> CONFIG["config.py\nworkspace.py\npaths.py"]
CMD --> SESSION["session_cmd.py\nsession/"]
CMD --> EVIDENCE["evidence_cmd.py\nevidence/"]
CMD --> PRE["preprocess_cmd.py\nevidence/corpus/"]
CMD --> PHASE["phase_cmd.py\nphase.py\nworkflow.py"]
CMD --> SQL["sql_cmd.py\ndb/\nrest/"]
EVIDENCE --> ACQ["evidence/acquisition.py\nadapters/ filesystem/http/s3"]
EVIDENCE --> CANON["evidence/canonical.py\ncontracts.py\nmodel.py"]
EVIDENCE --> AUTHOR["evidence/authoring.py"]
PRE --> PIPE["evidence/corpus/pipeline.py\nchunk.py normalize.py store.py"]
PRE --> VECTOR["adapters/vector/qdrant.py"]
PRE --> DWH["jobs/dwh_pipeline.py\nadapters/dwh/"]
SESSION --> REPO["session/filesystem_repository.py\npostgres_repository.py"]
PHASE --> LEDGER["decisions.py\nreview_decisions"]
```
Il comando di operatore `tht` in `tools/tht/` è distinto dalla CLI Python dell'harness. Il primo gestisce installazione, lifecycle, autenticazione e workspace; il secondo esegue il workflow e le operazioni sui dati.
## Workflow a otto fasi e gate
La fonte di verità è `harness/workflow.yaml`. La fase corrente si calcola dal decision ledger, non da un campo aggiornato manualmente.
```mermaid
flowchart LR
F1["F1\nChiarimento"] --> F2["F2\nMemoria"]
F2 --> F3["F3\nRiscrittura"]
F3 --> F4["F4\nSchema linking\nreviewer_decide"]
F4 --> F5["F5\nSintesi"]
F5 --> F6["F6\nCTE\nauto o skip"]
F6 --> F7["F7\nSQL finale\nreviewer_confirm"]
F7 --> F8["F8\nDatamart\nreviewer_decide"]
F1 -.->|reviewer_confirm| F1
F3 -.->|reviewer_confirm| F3
F4 -.->|decisioni su tabelle, colonne, evidence| F4
F6 -.->|cte_approved o cte_rejected| F6
F7 -.->|sql_approved o sql_rejected| F7
F8 -.->|datamart_requested o declined| F8
```
| Fase | Nome | Avanzamento | Artefatti principali |
| --- | --- | --- | --- |
| F1 | chiarimento | `kind:phase` | decisioni di chiarimento |
| F2 | memoria | automatico se vuota | decisioni memoria |
| F3 | riscrittura | `kind:phase` | `question.md` |
| F4 | schema linking | `reviewer_decide` | `schema_linking.json` |
| F5 | sintesi | `kind:phase` | verifica dello schema linking |
| F6 | CTE | automatico, oppure skip | `cte_plan.json`, `ctes/`, `cte_tests.json` |
| F7 | SQL finale | `kind:phase` dopo `sql_approved` | `sql_final.sql` |
| F8 | datamart | `reviewer_decide` | decisione su richiesta o rifiuto |
Un `reviewer_select` con decisione incorporata può confermare direttamente. Un `reviewer_decide` registra le scelte multiple. Un `reviewer_confirm` conferma un artefatto o la chiusura della fase. Il modello propone; il revisore decide e il ledger registrato è la fonte dello stato.
+189
View File
@@ -0,0 +1,189 @@
# Evidence: sorgenti, preparazione e revisione
Questa pagina descrive il ciclo completo delle Evidence di workspace: dove si trova il materiale originale, come si producono le unità curate, quando diventano disponibili al runtime e quali responsabilità hanno autore e revisore.
## Regola di pubblicazione
Il workspace repository è la sorgente versionata. ThothII lo legge, lo valida e pubblica una generazione atomica. Non modifica, committa o pusha il repository dell'autore.
Una Evidence diventa utilizzabile dal workflow solo quando:
1. il materiale originale è presente in `source/`;
2. l'unità derivata è presente in `curated/`;
3. il manifest collega unità, sorgente e hash;
4. la validazione non produce errori o review item irrisolti;
5. la pipeline di preprocessing costruisce una generazione indicizzata e la attiva.
Una proposta generata durante una sessione non è automaticamente Evidence pubblicata. Il modello può proporre una formula o una spiegazione, ma un curatore deve importarla, revisionarla e pubblicarla nel repository prima che un'altra sessione possa recuperarla.
## Dove deve stare il primo sorgente
Per il filesystem Evidence v2, il primo sorgente autorevole deve stare nella directory `source/` del repository di workspace. `curated/` contiene il risultato revisionato e indicizzato, non il materiale originale.
```text
<workspace-repository>/
├── source/ # materiale originale, preservato
│ └── <dominio>/<file>.md
├── curated/ # Evidence Units revisionate
│ └── <dominio>/<unit>.md
├── manifest.yaml # legami, hash e metadati della preparazione
├── evaluation/ # fixture di valutazione del recupero
└── example/ # esempi e materiale di supporto
```
Il descriptor del workspace deve dichiarare `evidence.schema_version: 2` e, per una sorgente filesystem, usare esattamente:
```yaml
evidence:
schema_version: 2
source:
type: filesystem
uri: "<workspace.id>/evidence"
patterns:
- "curated/**/*.md"
```
La configurazione storica può esporre `source_root`, per esempio `${THT_DOCS_ROOT}` o `/data`. Per la struttura v2 il pattern runtime deve selezionare solo `curated/**/*.md`. Non bisogna indicizzare direttamente `source/`, mescolare `source/` e `curated/`, usare glob più ampi o includere file non Markdown.
HTTP e S3 sono adapter distinti. Non usano la struttura filesystem `source/` e `curated/`, ma devono comunque fornire una provenienza stabile, senza credenziali negli URI e con il contratto specifico dell'adapter.
## Come deve essere fatta un'unità curata
Le unità Markdown lette dal loader storico della CLI hanno frontmatter YAML. I campi minimi sono `id` e `title`; `tier`, `status`, `sources`, `tables`, `concepts` descrivono il contesto dell'unità.
```markdown
---
id: evidence:fascia-pediatrica
title: Fascia pediatrica
tier: structural
status: reviewed
sources:
- source/domain/patient.md
tables:
- patient
concepts:
- concept:patient-age
---
Definizione verificata della fascia pediatrica.
La regola deve essere abbastanza atomica da poter essere citata senza ricostruire
un intero capitolo. Il testo deve distinguere definizione, condizioni e limiti.
```
Le unità curate devono essere atomiche, leggibili da un secondo revisore e sostenute dal sorgente. I riferimenti di provenienza devono permettere di risalire al file originale e alla porzione che supporta l'affermazione. Non inserire segreti, token, password o credenziali nei metadati o negli URI.
La forma canonica moderna conserva anche il tipo di Evidence, la provenienza, gli estratti di supporto, `source_file` e `source_sha256`. Il contratto canonico rifiuta campi sconosciuti, metadati mutabili e URI con credenziali. Gli identificatori devono restare stabili anche quando cambia il tipo di unità.
## Preparazione: dal sorgente alla generazione attiva
```mermaid
flowchart TD
SRC["source/<dominio>/*.md\nmateriale originale"] --> PREP["tht evidence prepare\npreparazione candidata"]
PREP --> CAND["curated/<dominio>/*.md\nunità proposte o aggiornate"]
CAND --> VAL["tht evidence validate\ncontrolli di struttura e legami"]
VAL -->|errori o review item| FIX["Correzioni dell'autore\ne revisione"]
FIX --> PREP
VAL -->|publishable| COMMIT["Commit del repository\nauthoring clone"]
COMMIT --> ING["tht preprocess evidence\nnormalizzazione e chunking"]
ING --> BM25["Indice BM25"]
ING --> VEC["Embedding e vector store"]
BM25 --> GEN["Generazione candidata"]
VEC --> GEN
GEN --> EVAL["tht evidence evaluate\nfixture di retrieval"]
EVAL -->|pass| ACT["Generazione attiva"]
EVAL -->|fail| FIX
ACT --> RUNTIME["Ricerca Evidence nel workflow"]
```
La preparazione può ristrutturare sorgenti cambiate, ma non pubblica da sola. `prepare` produce una proposta e può indicare il file sorgente coinvolto in caso di errore. `validate` non scrive né pubblica. Il commit è un'azione del curatore nel clone di authoring. Il runtime legge una revisione completa e validata, poi la pipeline crea una generazione versionata. L'attivazione è atomica: una generazione precedente resta disponibile secondo la policy di retention.
La ricerca runtime usa il recupero ibrido. Il ramo denso usa gli embedding, il ramo BM25 usa la ricerca lessicale e la fusione deterministica ordina i risultati. L'unità pubblicata conserva la provenienza, che il modello deve citare quando usa l'evidence.
## Responsabilità del creatore
Il creatore prepara il materiale e rende verificabile ogni unità. In pratica deve:
- mettere il materiale originale in `source/`, senza sovrascriverne il significato durante la curatela;
- suddividere il contenuto in unità atomiche, una regola o definizione per unità quando possibile;
- assegnare un identificatore stabile e un titolo comprensibile;
- indicare la provenienza, le tabelle e i concetti coinvolti quando sono noti;
- mantenere il testo nella lingua del workspace;
- separare fatti, regole, esempi, formule e limiti;
- riportare gli estratti che sostengono l'unità, senza estendere la conclusione oltre il sorgente;
- eseguire `tht evidence prepare` e `tht evidence validate`;
- risolvere ogni errore e ogni review item prima di proporre il commit;
- fornire al revisore il contesto necessario, inclusi i cambiamenti nel sorgente e il motivo di eventuali rinomini o ritiri.
Il creatore non deve:
- scrivere direttamente nel corpus attivo di produzione;
- trattare una proposta del modello come fatto verificato;
- eliminare un'unità solo perché non è più supportata senza registrare il ritiro o il relink;
- inserire credenziali nei metadati, nei file o negli URL di provenienza;
- modificare manualmente manifest, hash o generazioni per far passare la validazione.
## Responsabilità del revisore
Il revisore non approva la forma del testo soltanto perché è chiara. Verifica il rapporto tra sorgente, unità e uso previsto. Per ogni unità deve controllare:
1. che il sorgente indicato esista nella revisione esaminata;
2. che l'estratto sostenga davvero l'affermazione;
3. che l'unità non unisca regole incompatibili o concetti indipendenti;
4. che tabelle, colonne e concetti siano identificati correttamente;
5. che l'identificatore sia stabile e non duplichi un'altra unità;
6. che il testo distingua definizione, condizione, eccezione ed esempio;
7. che non contenga informazioni sensibili o dettagli non presenti nel sorgente;
8. che la valutazione del retrieval copra le query rilevanti e non nasconda risultati vuoti.
Il revisore può approvare, chiedere modifiche, rigettare, ritirare o riallacciare un'unità a un nuovo sorgente. Un ritiro deve essere esplicito. Un relink deve indicare il nuovo file e deve lasciare una traccia verificabile della decisione. L'approvazione non comporta la pubblicazione immediata: il repository deve passare la validazione e la generazione deve superare la valutazione prima dell'attivazione.
## Comandi disponibili
I comandi di authoring operano sul repository di workspace e non pubblicano direttamente.
```bash
# Prepara le sorgenti cambiate. Non committa e non pubblica.
tht evidence prepare <workspace-root>
# Rielabora tutte le sorgenti con la pipeline installata.
tht evidence prepare <workspace-root> --upgrade
# Valida struttura, manifest, legami e review item.
tht evidence validate <workspace-root>
# Restituisce JSON per CI o strumenti automatici.
tht evidence validate <workspace-root> --json
# Valuta il retrieval su una generazione o sulla generazione attiva.
tht evidence evaluate <workspace-root> --config <workspace-config>
tht evidence evaluate <workspace-root> --config <workspace-config> --generation <id> --json
# Risolve una unità senza pubblicare: ritiro oppure nuovo collegamento al sorgente.
tht evidence resolve <workspace-root> evidence:<id> --retire
tht evidence resolve <workspace-root> evidence:<id> --source source/domain/nuovo.md
# Materializza e indicizza una generazione versionata.
tht preprocess evidence --config <workspace-config>
# Esecuzione a secco e ripresa di un job, quando supportate dalla configurazione.
tht preprocess evidence --config <workspace-config> --dry-run
tht preprocess evidence --config <workspace-config> --resume <run-id>
```
`evidence prepare`, `evidence validate` e `evidence resolve` richiedono il path del repository. `preprocess evidence` usa invece la configurazione del workspace, perché deve conoscere embedding, vector store, policy di retention e artifact directory.
I codici di uscita sono parte del contratto operativo: `evidence validate` usa `0` quando il corpus è pubblicabile, `1` per errori di validazione e `3` quando restano solo elementi da revisionare o unità orfane. Con `--json`, stdout deve contenere solo JSON valido.
## Formule e proposte di sessione
Le formule hanno un formato distinto dalle Evidence documentali. Una formula proposta durante una sessione può essere citata nella proposta corrente, ma non entra nel corpus runtime, non riceve un ID `evidence:` utilizzabile e non scrive nel repository. Per diventare pubblicata deve seguire lo stesso percorso di importazione, revisione e preprocessing delle altre unità.
## Riferimenti contrattuali
- [Contratto Workspace Evidence v3](contracts/workspace-evidence-v3.md)
- [Contratto della CLI di preprocessing](contracts/workspace-preprocessing-cli.md)
- [ADR: confine di pubblicazione](adr/0001-evidence-publication-boundary.md)
- [ADR: preparazione atomica e ancorata al sorgente](adr/0006-grounded-atomic-evidence-preparation.md)
- [ADR: valutazione prima dell'attivazione](adr/0003-evaluate-evidence-before-activation.md)
- [ADR: recupero ibrido deterministico](adr/0008-make-hybrid-evidence-retrieval-deterministic.md)
+2
View File
@@ -62,6 +62,8 @@ nav:
- Collaudo PSD Progetto B: testing/psd-server-project-b-manual.md - Collaudo PSD Progetto B: testing/psd-server-project-b-manual.md
- ThothII (Documentazione Tecnica): - ThothII (Documentazione Tecnica):
- Panoramica Architettura: architecture/overview.md - Panoramica Architettura: architecture/overview.md
- Componenti, moduli e flussi: architecture/components.md
- Evidence: evidence.md
- Autenticazione: architecture/authentication.md - Autenticazione: architecture/authentication.md
- Installazione autenticazione locale: install/authentication-local.md - Installazione autenticazione locale: install/authentication-local.md
- OIDC generico: install/authentication-oidc.md - OIDC generico: install/authentication-oidc.md