feat: complete evidence restructuring worktree
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
# Componenti, moduli e flussi
|
||||
# Components, modules, and flows
|
||||
|
||||
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.
|
||||
This page complements the [architecture overview](overview.md) with the module structure and flows through ThothII. The diagrams describe the current code, not a future architecture.
|
||||
|
||||
## Moduli e dipendenze
|
||||
## Modules and dependencies
|
||||
|
||||
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.
|
||||
The frontend communicates with the backend through REST and SSE. The backend does not own session persistence: it starts Pi, invokes the `tht` CLI, and forwards events. The harness contains the workflow, the Python CLI, and adapters for the DWH and vector store.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
@@ -14,30 +14,30 @@ flowchart LR
|
||||
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 --> FS["Sessions and artifacts\nworkspace repository"]
|
||||
THT --> DWH["DWH\nread-only"]
|
||||
THT --> VDB["Qdrant / vector store"]
|
||||
BE --> CFG["settings.json\nworkspace registry"]
|
||||
FE -.->|renderizza widget| EXT
|
||||
FE -.->|renders widgets| EXT
|
||||
```
|
||||
|
||||
Dipendenze principali:
|
||||
|
||||
| Modulo | Dipende da | Responsabilità |
|
||||
| Module | Depends on | Responsibility |
|
||||
| --- | --- | --- |
|
||||
| `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 |
|
||||
| `frontend/` | Backend REST and SSE APIs | UI, gate widgets, and in-memory transcript |
|
||||
| `backend/src/` | Pi, `tht`, configuration, and workspace registry | Transport, session lifecycle, and APIs |
|
||||
| `harness/.pi/` | Pi and `tht phase` | Workflow orchestration and human-in-the-loop gates |
|
||||
| `harness/tht/` | Filesystem, DWH, and vector store | Persistence, CLI, Evidence, schema, and preprocessing |
|
||||
| workspace repository | `source/`, `curated/`, manifest, and artifacts | Versioned Evidence source and session output |
|
||||
|
||||
## Sequenza di una sessione
|
||||
## Session sequence
|
||||
|
||||
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.
|
||||
The main path starts with a user question and ends with an SSE event. Reviewer decisions use the same channel and are persisted by the harness.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
actor U as Utente o revisore
|
||||
actor U as User or reviewer
|
||||
participant FE as Frontend
|
||||
participant BE as Backend
|
||||
participant PI as Pi RPC
|
||||
@@ -45,24 +45,24 @@ sequenceDiagram
|
||||
participant WS as Workspace
|
||||
participant DWH as DWH
|
||||
|
||||
U->>FE: Invia domanda o decisione di gate
|
||||
U->>FE: Send question or gate decision
|
||||
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
|
||||
THT->>WS: Read and write phase artifacts
|
||||
THT->>DWH: Introspection or read-only query
|
||||
DWH-->>THT: Schema, results, or diagnostics
|
||||
THT-->>PI: JSON and phase state
|
||||
PI-->>BE: RPC events and widget descriptor
|
||||
BE-->>FE: SSE text_delta, info, ui_request
|
||||
FE-->>U: Testo, artefatto o richiesta di revisione
|
||||
FE-->>U: Text, artifact, or review request
|
||||
```
|
||||
|
||||
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.
|
||||
The backend uses `ThtRunner` for CLI subprocesses, `PiProcessManager` for one Pi process per session, `SessionBridge` to adapt RPC events, and `SseHub` to distribute them to clients.
|
||||
|
||||
## Classi principali del backend
|
||||
## Main backend classes
|
||||
|
||||
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.
|
||||
The diagram shows the classes that form the bridge between the browser, Pi, and `tht`. Fastify routes receive requests and delegate to these services.
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
@@ -114,9 +114,9 @@ classDiagram
|
||||
SessionBridge --> SseHub
|
||||
```
|
||||
|
||||
## Moduli Python della CLI `tht`
|
||||
## Python modules in the `tht` CLI
|
||||
|
||||
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.
|
||||
The CLI consists of Typer commands and domain modules. `cli/` turns arguments into operations; `evidence/`, `session/`, `db/`, `adapters/`, and the other packages contain the application logic.
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
@@ -137,11 +137,11 @@ flowchart TB
|
||||
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.
|
||||
The operator command `tht` in `tools/tht/` is separate from the harness Python CLI. The former handles installation, lifecycle, authentication, and workspaces; the latter runs the workflow and data operations.
|
||||
|
||||
## Workflow a otto fasi e gate
|
||||
## Eight-phase workflow and gates
|
||||
|
||||
La fonte di verità è `harness/workflow.yaml`. La fase corrente si calcola dal decision ledger, non da un campo aggiornato manualmente.
|
||||
The source of truth is `harness/workflow.yaml`. The current phase is computed from the decision ledger, not from a manually updated field.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
# Panoramica dell'architettura
|
||||
# Architecture overview
|
||||
|
||||
> Per il dettaglio dei moduli e dei flussi vedi
|
||||
> [Componenti, moduli e flussi](components.md).
|
||||
> For details about modules and flows, see [Components, modules, and flows](components.md).
|
||||
|
||||
ThothII è un **datamart builder human-in-the-loop**: trasforma una domanda in linguaggio naturale in SQL validato (ed eventualmente un datamart dbt) attraverso un **workflow deterministico a 8 fasi NL→SQL**, in cui il modello *propone* e un revisore umano *decide* ai gate.
|
||||
ThothII is a **human-in-the-loop datamart builder**. It turns a natural-language question into validated SQL, and optionally a dbt datamart, through a **deterministic eight-phase NL-to-SQL workflow** in which the model *proposes* and a human reviewer *decides* at gates.
|
||||
|
||||
L'autenticazione di produzione usa local oppure OIDC generico; il solo CLI operatore è tht.
|
||||
Per sessioni, ruoli, gruppi, diagnostica e ripristino vedere la [documentazione autenticazione](authentication.md).
|
||||
Production authentication uses local authentication or generic OIDC. `tht` is the only operator CLI.
|
||||
For sessions, roles, groups, diagnostics, and recovery, see the [authentication documentation](authentication.md).
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
@@ -20,71 +19,71 @@ flowchart LR
|
||||
THT --> FE
|
||||
```
|
||||
|
||||
## I tre progetti indipendenti
|
||||
## The three independent projects
|
||||
|
||||
```
|
||||
frontend (React/SSE) → backend (Fastify) → pi --mode rpc → tht/harness → DWH (sola lettura)
|
||||
frontend (React/SSE) → backend (Fastify) → pi --mode rpc → tht/harness → DWH (read-only)
|
||||
```
|
||||
|
||||
| Layer | Stack | Ruolo |
|
||||
|---|---|---|
|
||||
| **harness/** | Python (`tht` CLI) + Pi gate extension (JS) | Possiede il workflow e **tutta** la persistenza |
|
||||
| **backend/** | Fastify + TypeScript | Ponte sottile senza database proprio |
|
||||
| **frontend/** | React 18 + Vite | UI che renderizza i widget di gate e ricostruisce il transcript live dallo stream SSE |
|
||||
| **harness/** | Python (`tht` CLI) + Pi gate extension (JS) | Owns the workflow and **all** persistence |
|
||||
| **backend/** | Fastify + TypeScript | Thin bridge with no database of its own |
|
||||
| **frontend/** | React 18 + Vite | UI that renders gate widgets and rebuilds the live transcript from the SSE stream |
|
||||
|
||||
## L'harness possiede il workflow
|
||||
## The harness owns the workflow
|
||||
|
||||
`tht` (Python) è una CLI deterministica; `harness/.pi/extensions/tht-gate.js` è un'estensione Pi che guida il workflow a 8 fasi. La fonte di verità unica del workflow è `harness/workflow.yaml`; le regole di orchestrazione che il modello deve seguire sono in `harness/.pi/skills/tht-sessione/SKILL.md`. La "fase corrente" **non è memorizzata**: viene calcolata piegando il decision ledger (`harness/tht/phase.py`) — va letta prima di ragionare sulla logica di fase.
|
||||
`tht` (Python) is a deterministic CLI. `harness/.pi/extensions/tht-gate.js` is a Pi extension that guides the eight-phase workflow. `harness/workflow.yaml` is the single source of workflow truth, and `harness/.pi/skills/tht-sessione/SKILL.md` contains the orchestration rules the model must follow. The "current phase" is **not stored**. It is computed by folding the decision ledger (`harness/tht/phase.py`), which must be read before reasoning about phase logic.
|
||||
|
||||
## Persistenza = documenti di fase, non chat
|
||||
## Persistence means phase documents, not chat
|
||||
|
||||
Una sessione è una directory sotto `sessions/` (path definito dal workspace): `session_manifest.yaml` + artefatti per fase (`question.md`, `schema_linking.json`, `sql_final.sql`, …) + `review_decisions.jsonl`. Il contratto (SKILL.md): *"lo stato persistito è la verità — ciò che non è registrato non è accaduto"*. Non esiste uno store di transcript verbatim. Un processo Pi ripreso ricostruisce il contesto da `tht session show <id>` + gli artefatti su disco.
|
||||
A session is a directory under `sessions/` (the workspace defines the path): `session_manifest.yaml`, phase artifacts (`question.md`, `schema_linking.json`, `sql_final.sql`, and others), and `review_decisions.jsonl`. The contract says: *"persisted state is the truth; what is not recorded did not happen"*. There is no verbatim transcript store. A resumed Pi process rebuilds context from `tht session show <id>` and the artifacts on disk.
|
||||
|
||||
## Il backend è un ponte sottile senza database
|
||||
## The backend is a thin bridge with no database
|
||||
|
||||
- `ThtRunner` esegue subcommand `tht` in shell
|
||||
- `PiProcessManager` esegue un processo Pi figlio per sessione e fa da bridge al suo stream RPC
|
||||
- `SessionBridge` mappa eventi RPC di Pi → eventi client (`ui_request` / `text_delta` / `info`)
|
||||
- `SseHub` distribuisce questi eventi via SSE al browser
|
||||
- `ThtRunner` runs `tht` subcommands in a shell.
|
||||
- `PiProcessManager` runs one Pi child process per session and bridges its RPC stream.
|
||||
- `SessionBridge` maps Pi RPC events to client events (`ui_request` / `text_delta` / `info`).
|
||||
- `SseHub` distributes these events to the browser over SSE.
|
||||
|
||||
Le impostazioni applicative vivono in un file JSON (`backend/data/settings.json`), non in un database.
|
||||
Application settings live in a JSON file (`backend/data/settings.json`), not in a database.
|
||||
|
||||
## Contratto del gate human-in-the-loop
|
||||
## Human-in-the-loop gate contract
|
||||
|
||||
Il modello propone; un revisore umano decide ai gate tramite widget:
|
||||
The model proposes; a human reviewer decides at gates through widgets:
|
||||
|
||||
- **`reviewer_select`** — scelta singola: un'opzione con `decision` payload auto-conferma/persiste direttamente; un'opzione senza payload chiede soltanto
|
||||
- **`reviewer_decide`** — multiselect: ogni scelta È una decisione
|
||||
- **`reviewer_confirm`** — gate su artefatto/fase
|
||||
- **`reviewer_select`**: single choice. An option with a `decision` payload confirms and persists directly; an option without a payload only asks.
|
||||
- **`reviewer_decide`**: multiselect. Each choice is a decision.
|
||||
- **`reviewer_confirm`**: artifact or phase gate.
|
||||
|
||||
Il frontend renderizza questi widget-descriptor (registro in `src/widgets/`); il transcript live viene ricostruito in memoria dallo stream SSE (`src/store/sessionStore.ts`) — **non è persistito**.
|
||||
The frontend renders these widget descriptors (registry in `src/widgets/`). It rebuilds the live transcript in memory from the SSE stream (`src/store/sessionStore.ts`); it is **not persisted**.
|
||||
|
||||
## Evidence curata e immutabile
|
||||
## Curated and immutable Evidence
|
||||
|
||||
Il repository del workspace è il confine di pubblicazione: il curatore prepara `evidence/source/`,
|
||||
revisa le unità in `evidence/curated/`, valida e fa merge. Per `evidence.schema_version: 2` il
|
||||
runtime materializza l'intero albero `evidence/` dal commit Git esatto, ma il renderer consegna al
|
||||
preprocessing esattamente `curated/**/*.md` dalla root immutabile della revisione. Sorgenti, manifest
|
||||
ed evaluation restano disponibili solo per tracciabilità. Il runtime non modifica, stagea, committa
|
||||
o pubblica il repository di authoring.
|
||||
The workspace repository is the publication boundary. The curator prepares `evidence/source/`,
|
||||
reviews units in `evidence/curated/`, validates them, and merges them. With `evidence.schema_version: 2`,
|
||||
the runtime materializes the full `evidence/` tree from the exact Git commit, but the renderer passes
|
||||
only `curated/**/*.md` from the immutable revision root to preprocessing. Sources, manifests, and
|
||||
evaluation data remain available for traceability. The runtime never modifies, stages, commits, or
|
||||
publishes the authoring repository.
|
||||
|
||||
Prima dell'indicizzazione, il corpus curato della revisione pinnata viene validato. La collezione
|
||||
Qdrant condivisa conserva il vettore dense senza nome di Schema e Memory; il preprocessing Evidence
|
||||
può aggiungere soltanto in modo additivo il vettore sparse `bm25` con `idf`, senza eliminare,
|
||||
rinominare o ricreare la collezione. `workspace preprocess evidence` e la parte Evidence di
|
||||
`workspace preprocess run` sono le sole operazioni pubbliche che effettuano questo upgrade.
|
||||
Before indexing, the curated corpus from the pinned revision is validated. The shared Qdrant
|
||||
collection keeps the unnamed dense vector used by Schema and Memory. Evidence preprocessing may
|
||||
add only the sparse `bm25` vector with `idf`, without deleting, renaming, or recreating the collection.
|
||||
`workspace preprocess evidence` and the Evidence part of `workspace preprocess run` are the only public
|
||||
operations that perform this upgrade.
|
||||
|
||||
## Punti di attenzione ricorrenti
|
||||
## Recurring points of attention
|
||||
|
||||
- `tht -c`/`--config` è un'opzione **per-comando**: deve seguire il subcommand, mai precederlo (`ThtRunner.buildArgv` lo impone).
|
||||
- L'output `--json` deve essere JSON puro su stdout — è un contratto machine-readable.
|
||||
- Le stringhe UI sono in inglese; il *contenuto* dei documenti resta nella lingua del workspace, perché è il dato reale — solo chrome e label sono in inglese.
|
||||
- Ogni workspace imposta il target DWH e le proprie directory operative. I segreti restano nei file protetti dell'installazione e non nel repository del workspace.
|
||||
- Le impostazioni sono globali (`backend/data/settings.json`: workspace/provider/modello/thinking); il form di nuova sessione richiede solo la domanda.
|
||||
- **Resume**: una sessione riprendibile rientra all'ultima fase incompleta. Il backend rifiuta il resume con 409 se `finalized` o `archived`; `PiProcessManager.spawnFor` deve inviare `/riprendi-sessione <id>` (resume) vs `/nuova-domanda` (nuova) — il prompt sbagliato trasforma silenziosamente un resume in una nuova domanda.
|
||||
- `tht -c`/`--config` is a **per-command** option. It must follow the subcommand, never precede it (`ThtRunner.buildArgv` enforces this).
|
||||
- `--json` output must be plain JSON on stdout. It is a machine-readable contract.
|
||||
- UI strings are in English. Document *content* stays in the workspace language because it is the actual data; only chrome and labels are in English.
|
||||
- Each workspace defines its DWH target and working directories. Secrets remain in protected installation files, not in the workspace repository.
|
||||
- Settings are global (`backend/data/settings.json`: workspace/provider/model/thinking); the new-session form asks only for the question.
|
||||
- **Resume**: a resumable session returns to its last incomplete phase. The backend rejects resume with 409 when `finalized` or `archived`; `PiProcessManager.spawnFor` must send `/riprendi-sessione <id>` for resume and `/nuova-domanda` for a new session. The wrong prompt silently turns a resume into a new question.
|
||||
|
||||
## Come si lancia lo stack
|
||||
## Starting the stack
|
||||
|
||||
Lo stack locale si avvia con `./scripts/run-stack.sh`, dopo aver creato
|
||||
`deploy/env/local.env` da `deploy/env/local.env.example`. Il core Compose include Pi; DWH,
|
||||
vector DB, embedding e LLM sono endpoint esterni configurati nel file locale.
|
||||
Start the local stack with `./scripts/run-stack.sh` after creating
|
||||
`deploy/env/local.env` from `deploy/env/local.env.example`. The Compose core includes Pi; DWH,
|
||||
the vector database, embeddings, and the LLM are external endpoints configured in the local file.
|
||||
|
||||
Reference in New Issue
Block a user