This commit is contained in:
@@ -1,64 +1,89 @@
|
||||
# Panoramica dell'architettura
|
||||
# Architecture overview
|
||||
|
||||
> Sintesi ad uso documentazione. Per il dettaglio storico delle decisioni di design vedi le [Specifiche di Design](../superpowers/specs/2026-06-25-thothii-architecture-design.md) e i [Piani di Implementazione](../superpowers/plans/2026-06-25-harness-implementation.md). Per lo stato corrente del progetto (gate manuali pendenti, layout workspace/secret) vedi `PROJECT_STATE.md` nella radice del repo.
|
||||
> 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).
|
||||
|
||||
## I tre progetti indipendenti
|
||||
```mermaid
|
||||
flowchart LR
|
||||
USER["Reviewer"] --> FE["Frontend\nReact and SSE"]
|
||||
FE --> BE["Backend\nFastify"]
|
||||
BE --> PI["Pi\nRPC per sessione"]
|
||||
PI --> THT["tht and harness\nworkflow and persistence"]
|
||||
THT --> DWH["DWH\nread only"]
|
||||
THT --> EVIDENCE["Evidence\ncurated corpus"]
|
||||
EVIDENCE --> THT
|
||||
THT --> FE
|
||||
```
|
||||
|
||||
## 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**.
|
||||
|
||||
## Punti di attenzione ricorrenti
|
||||
## Curated and immutable Evidence
|
||||
|
||||
- `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 (italiano per `psd`), perché è il dato reale — solo chrome/label sono in inglese.
|
||||
- I workspace (`harness/workspaces/*.yaml`) impostano il target DB e i path **assoluti** `paths.sessions/artifacts/indexes` — per `psd` puntano a un repo separato e non versionato (`tht-workspace-psd/`). I segreti vivono solo in `harness/.env` (gitignored).
|
||||
- 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.
|
||||
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.
|
||||
|
||||
## Come si lancia lo stack
|
||||
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.
|
||||
|
||||
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.
|
||||
## Recurring points of attention
|
||||
|
||||
Comandi per singolo layer, test, lint: vedi il file `CLAUDE.md` nella radice del repo (guida operativa per Claude Code, tenuta sincronizzata con questa pagina).
|
||||
- `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.
|
||||
|
||||
## Starting the stack
|
||||
|
||||
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