Files
ThothII/docs/testing/evidence-lifecycle-test-plan.md
T
Codex 076c9742c5 feat: consolidate database management work
Add catalog-owned logical relationships and runtime snapshots, extend the database-management UI and validation coverage, and document the updated operational workflow.

Keep active sensitive-generation status in a tooltip and indicator, and update the layout E2E to follow the history action in its new database-scoped location.
2026-09-01 14:46:55 +02:00

56 KiB

Piano di test E2E del ciclo di vita delle Evidence

  • Data di preparazione: 2026-08-31
  • Workspace di riferimento: psd-clinical
  • Workspace di collaudo proposto: psd-evidence-lab

1. Obiettivo

Questo piano verifica, su servizi reali, l'intero ciclo di vita delle Evidence:

  1. creazione e registrazione di un workspace parallelo a PSD;
  2. inserimento di Source Evidence e generazione delle Curated Evidence strutturate;
  3. revisione, validazione, commit, acquisizione commit-addressed e inventario;
  4. indicizzazione dense + BM25 in Qdrant;
  5. ricerca tipizzata e uso nei processi core F1-F8;
  6. inserimento incrementale, modifica e riacquisizione;
  7. rename, relink, rimozione, orphan e retirement;
  8. idempotenza, retention, concorrenza, recovery e fallimenti parziali;
  9. isolamento, sicurezza, audit e non regressione di Schema, Memory e solved questions.

Il test è un'accettazione manuale E2E assistita, non un sostituto delle suite automatiche. Deve attraversare davvero Git, Workspace Management, host CLI, backend, core, Ollama, Qdrant e una sessione Pi completa.

2. Chiarimento essenziale: cosa significa CRUD Evidence oggi

Non esiste un CRUD Evidence nella UI o in una API pubblica. Il repository Git del workspace è la fonte autorevole; Qdrant è una proiezione ricostruibile.

Operazione funzionale Gesto reale dell'utente
Inserimento aggiungere un file in evidence/source/, eseguire evidence prepare, revisionare, validare, committare e pubblicare la revisione
Lettura leggere source/curated in Git; cercare la Published Evidence via retrieval; verificare provenienza e citation
Modifica modificare solo la Source Evidence, rieseguire prepare/review/validate e pubblicare una nuova revisione/generazione
Cancellazione rimuovere la source, osservare l'orphan bloccante, poi decidere esplicitamente --retire oppure --source per il relink
Inventario correlare manifest Git, materializzazione del commit, manifest ACTIVE, document generations, payload Qdrant e receipt di sessione

ThothII non modifica, committa o pusha il repository dell'autore. Il curatore non deve modificare manualmente manifest.yaml, hash, generation, metadata invisibili o marker tht:.

3. Fonti di verità e oracoli

Livello Autorità o proiezione Oracle da conservare
Authoring Git autorità commit SHA, source/, curated/, manifest.yaml, evaluation.yaml
Registry snapshot copia immutabile del commit attivo workspace revision, snapshot.json, evidence.manifest.json, hash e conteggi file
Corpus Evidence generazione pubblicata puntatore ACTIVE, generation manifest, document_generations
Qdrant proiezione ricostruibile active view per workspace, revisione pinnata e document generation; payload senza vector
Sessione verità del processo retrieval_pack.md, evidence_receipts.json, evidence.json, review_decisions.jsonl
Chat/UI live non persistente screenshot o note di collaudo, mai usati come unico oracle

Nel percorso filesystem v2 una Evidence è disponibile al runtime soltanto dopo source, curated, manifest valido, assenza di review item irrisolti, preprocessing, evaluation superata e attivazione atomica. HTTP e S3 seguono invece i rispettivi contratti adapter della campagna P2.

Il solo puntatore Evidence ACTIVE non prova la disponibilità: il Qdrant adapter filtra anche per la registry/workspace revision corrente. Dopo una candidate fallita si devono quindi confrontare separatamente registry revision, Evidence ACTIVE pointer, punti fisici, vista di una sessione pinnata e vista del runtime corrente; una divergenza è split-brain, non rollback riuscito.

4. Topologia del laboratorio

Il test deve usare lo stesso repository Git condiviso dei workspace, ma un namespace distinto. Non va creato un corpus Evidence indipendente scollegato dal catalogo dei workspace.

4.1 Isolamento obbligatorio

  • Branch remoto dedicato: test/evidence-lifecycle.
  • Installazione locale dedicata al collaudo, con il processo backend configurato esplicitamente con THT_WORKSPACE_GIT_BRANCH=test/evidence-lifecycle. La UI aggiorna il branch già configurato: non permette di sceglierlo.
  • Workspace ID: psd-evidence-lab.
  • Directory: psd-evidence-lab/.
  • Qdrant collection: psd-evidence-lab.
  • Evidence URI: psd-evidence-lab/evidence.
  • Database target: lo stesso DWH read-only di PSD, configurato però come binding del nuovo workspace.
  • Secret: reinseriti nella configurazione locale write-only; mai copiati in Git o nei report.
  • Sessioni e corpus: namespace del nuovo workspace; nessun riuso dei path di psd-clinical.
  • Prima dell'attivazione iniziale, committare almeno psd-evidence-lab/evidence/README.md, escluso dal pattern curated/**/*.md: Git non conserva le directory vuote e la materializzazione commit-addressed deve poter risolvere il tree Evidence.

Il repository di authoring usato dall'umano deve essere un clone diverso dal checkout read-only gestito dall'installazione.

Collection e workspace distinti isolano i dati, ma non i fault ai servizi. REL-05/06/10-13 e le prove di outage richiedono un Compose project lab con dataRoot, endpoint Qdrant/Ollama, volumi e porte propri, oppure proxy di fault scoped esclusivamente al lab. Non fermare né corrompere i servizi condivisi con PSD. Se questo isolamento non è disponibile, la campagna fault va marcata NOT RUN e non è ammesso dichiarare COMPLETE PASS.

4.2 Descriptor minimo

Si parte dal descriptor PSD accettato, cambiando almeno ID, nome, descrizione, collection ed Evidence URI. Per il laboratorio va dichiarato esplicitamente il contratto moderno:

evidence:
  schema_version: 2
  source:
    type: filesystem
    uri: psd-evidence-lab/evidence
    patterns:
      - "curated/**/*.md"
  policy:
    max_chunk_chars: 5000
    retain_published_generations: 3

Non copiare gli esempi legacy che usano **/*.md o omettono schema_version: 2. Aggiungere inoltre l'entry ordinata a thoth-workspaces.yaml e, se serve lo stesso DWH nei processi core, portare nel nuovo namespace le annotazioni schema curate già approvate, sottoponendole comunque al gate del nuovo workspace.

5. Responsabilità

5.1 Attività dell'utente

L'utente simula il curatore/reviewer reale e deve:

  1. preparare i tre testi descritti nella sezione 6;
  2. leggere integralmente ogni diff delle Curated Evidence e confrontarlo con la source;
  3. decidere sulle ambiguità, sui review item, sul rename, sul relink e sul retirement;
  4. usare Workspace Management per update, validate e test connections;
  5. porre le domande reali nell'app, decidere ai gate e giudicare correttezza business, citation e SQL.

5.2 Attività dell'agente/operatore tecnico

L'agente può, dopo autorizzazione all'esecuzione del collaudo:

  1. creare scaffold, descriptor, catalog entry ed evaluation set;
  2. eseguire i due CLI tht corretti, Git e le verifiche read-only;
  3. raccogliere commit SHA, revision, run ID, generation e inventario Qdrant;
  4. confrontare before/after e segnalare ogni violazione degli oracle;
  5. predisporre e validare le probe assistite di runtime e inventory descritte nelle sezioni 7 e 16;
  6. indurre fault controllati soltanto nel laboratorio isolato e ripristinare i servizi;
  7. produrre il verbale finale PASS/FAIL con allegati e ripristinare l'installazione a PSD.

6. Dataset umano: tre documenti, sei pubblicazioni

L'attuale authoring skill impone esattamente una Evidence Unit per Source Evidence. I documenti devono quindi contenere una sola unità primaria ciascuno. Un testo che combina concetti indipendenti è un test negativo, non il formato nominale.

6.1 Documento D1 — glossario/disambiguazione

Path consigliato: evidence/source/00-glossario/coorte-lab-zaffiro.md.

Il testo deve includere:

  • una definizione business univoca;
  • 2-3 sinonimi e almeno una variante ortografica italiana/Unicode;
  • ciò che il termine non significa;
  • eventuali tabelle/colonne, sempre pienamente qualificate;
  • una frase breve copiabile come supporting excerpt;
  • un token raro ma leggibile, per esempio LAB-ZAFFIRO-731;
  • uso atteso: disambiguation e rewriting.

6.2 Documento D2 — enum o regola legata allo schema

Path consigliato: evidence/source/20-valori-enum/stato-lab-device.md.

Il testo deve includere:

  • una colonna reale nel formato schema.table.column;
  • tutti i valori memorizzati e il loro significato;
  • comportamento di NULL, valore sconosciuto ed eventuale eccezione;
  • una frase breve copiabile come supporting excerpt;
  • un token raro, per esempio LAB-ENUM-842;
  • uso atteso: schema_linking e sql_generation.

Se gli identificatori non sono pienamente qualificati, il sistema deve produrre un review item o una Evidence domain, non inventare il mapping.

6.3 Documento D3 — formula PostgreSQL

Questo file viene aggiunto solo dopo la prima pubblicazione, per provare un inserimento incrementale. Path consigliato: evidence/source/50-metadati-normalizzazione/formula-lab-intervallo.md.

Il testo deve includere:

  • un solo concetto calcolato;
  • una sola espressione PostgreSQL componibile, non una query completa;
  • tutti gli input come schema.table.column;
  • semantica di NULL, unità di misura e casi limite;
  • una frase breve copiabile come supporting excerpt;
  • un token raro, per esempio LAB-FORMULA-953;
  • uso atteso: sql_generation.

Una formula contenente SELECT, DDL o DML deve essere rifiutata come test negativo.

6.4 Scheda che l'utente compila prima del test

Campo Valore da fornire
Tabella/colonna reale usata da D2
Valori reali e significato
Colonne reali usate da D3
Espressione PostgreSQL attesa
ID Evidence generati dopo prepare
Domanda lessicale per D1/D2/D3
Parafrasi semantica per D1/D2/D3
Domanda che richiede D1 + D2 + D3
Risultato business e SQL attesi
Domanda negativa non correlata
Nuova definizione D1 per G3
Canary D1 nuova e formulazione da rimuovere
Nuovi path D1 per G5 rename e G6 relink
Testo business innocuo per la source injection S4

6.5 Copertura dei kind

Il percorso principale copre tre payload differenti. Per verificare anche tutti gli otto kind (glossary, domain, enum, example, mapping, normalization, formula, reference) il dataset raccomandato usa cinque micro-source aggiuntive, una per kind mancante, coerentemente con la skill corrente. Questa estensione è P2: non è necessaria per dimostrare il lifecycle CRUD, ma è necessaria per dichiarare copertura completa dei payload.

7. Convenzioni di esecuzione e raccolta

Creare una directory di report esterna al repository di authoring, con un sottodirectory per ciclo:

evidence-test-run-YYYYMMDD-HHMM/
├── 00-preflight/
├── 01-g1-initial/
├── 02-g2-add/
├── 03-g3-update/
├── 04-g4-retire/
├── 05-g5-rename/
├── 06-g6-relink/
├── faults/
└── final-report.md

Per ogni comando conservare timestamp, comando senza secret, exit code, stdout JSON, stderr sanitizzato e identità dell'operatore. Per ogni pubblicazione conservare:

  • Git commit e workspace revision;
  • runId, status e code;
  • ACTIVE prima/dopo;
  • generation manifest e mappa document_generations;
  • inventario Qdrant filtrato;
  • risultati dell'evaluation e delle probe;
  • session ID e receipt.

7.1 I due CLI omonimi

Definire percorsi espliciti; non affidarsi al primo tht nel PATH:

AUTHOR_THT=/Users/mp/projects/ThothII/harness/.venv/bin/tht
OPERATOR_THT=/absolute/path/to/native/host/tht
AUTHOR_REPO=/absolute/path/to/workspace-authoring-clone
WS_ROOT="$AUTHOR_REPO/psd-evidence-lab"
INSTALLATION=/absolute/path/to/thothii-installation.yaml
WS=psd-evidence-lab
REPORT=/absolute/path/to/evidence-test-run-YYYYMMDD-HHMM
EVIDENCE_PROBE=/absolute/path/to/assisted-evidence-probe
EVIDENCE_INVENTORY=/absolute/path/to/assisted-evidence-inventory
EVIDENCE_FAULT=/absolute/path/to/assisted-evidence-fault-harness
  • AUTHOR_THT: authoring, validation e migrazione del workflow Python.
  • OPERATOR_THT: installazione, registry e manutenzione del workspace reale.

--config/-c del CLI Python è un'opzione del singolo comando e deve comparire dopo il subcommand.

Il backend crea lease/config runtime revision-pinned e temporanee: non si deve ricostruire, copiare o passare a mano un RUNTIME_CFG. EVIDENCE_PROBE deve creare e distruggere la lease in modo supportato; EVIDENCE_INVENTORY è read-only; EVIDENCE_FAULT opera solo sulla stack lab dedicata. Sono helper che l'agente deve fornire e validare prima del collaudo esaustivo, non comandi attualmente pubblici di tht. Se mancano, i casi che li richiedono sono NOT RUN/INCONCLUSIVE, non PASS per inferenza dalla UI.

8. Preflight e baseline

ID Azione Esito atteso
PRE-01 Verificare branch, worktree pulito e remote corretti nessun file authoring già dirty; .DS_Store esclusi
PRE-02 Eseguire le suite automatiche Evidence/backend rilevanti PASS; eventuali L0/L2 mancanti documentati, non nascosti
PRE-03 Verificare Pi, provider autore, Ollama, Qdrant, DWH e auth tutti raggiungibili senza esporre credenziali
PRE-04 Inventariare psd-clinical come gruppo di controllo commit, ACTIVE, counts per kind e canary disambiguation con expected ID salvati
PRE-05 Verificare assenza del workspace/collection lab nessuna collisione; se esistono, fermarsi e identificare il proprietario
PRE-06 Aggiungere catalog entry, descriptor lab e evidence/README.md tracciato in una revisione candidata ID, URI e collection distinti; descriptor schema v3 valido; tree Evidence risolvibile anche senza D1-D3
PRE-07 Verificare nel processo dell'installazione THT_WORKSPACE_GIT_BRANCH=test/evidence-lifecycle, pushare la revisione su quel branch e usare Update workspace repository nella UI la UI mostra ref/commit attesi, candidate valida attivata atomicamente; PSD resta disponibile
PRE-08 Selezionare il lab, configurare binding/secret, Validate workspace source e Test workspace connections check verdi; secret solo write-only
PRE-09 Selezionare il lab come workspace dell'installazione nuove sessioni usano il lab; nessuna sessione PSD viene mutata
PRE-10 Preprocessare DWH, gestire il gate schema e indicizzare lo schema del lab, senza ancora eseguire lo stage Evidence schema indicizzato nella collection lab; nessun punto PSD toccato
PRE-11 Eseguire smoke test di EVIDENCE_PROBE e EVIDENCE_INVENTORY helper attestano installazione/workspace/revision; nessuna scrittura o stampa di secret
PRE-12 Eseguire EVIDENCE_FAULT assert-isolated e status dataRoot, Qdrant, Ollama, volumi e porte lab non coincidono con PSD; nessun fault/barrier attivo; altrimenti campagna fault NOT RUN
PRE-13 Verificare instrumentation del report candidate prima della compensazione report sanitizzato osservabile; altrimenti dettaglio G3-bad NOT OBSERVABLE e niente COMPLETE PASS

Il full workspace preprocess run va usato soltanto dopo aver aggiunto D1/D2 e un evaluation set valido; prima di quel momento lo stage Evidence non ha ancora un corpus valutabile.

Non usare come prerequisito scripts/evidence-restructuring-acceptance.sh: nel tree corrente riferisce un test non presente. Non assumere inoltre che il report PSD citato da PROJECT_STATE.md sia disponibile nel working tree corrente.

9. Comandi nominali

9.1 Authoring

"$AUTHOR_THT" evidence prepare "$WS_ROOT" --json
"$AUTHOR_THT" evidence validate "$WS_ROOT" --json

# Dopo una rimozione e la decisione umana:
"$AUTHOR_THT" evidence resolve "$WS_ROOT" evidence:<id> --retire --json
"$AUTHOR_THT" evidence resolve "$WS_ROOT" evidence:<id> \
  --source source/<dominio>/<nuovo-file>.md --json

Exit code attesi per validate:

  • 0: corpus publishable;
  • 1: errore strutturale/operativo;
  • 3: soli orphan o review item irrisolti.

Con --json, stdout deve contenere un solo JSON valido.

9.2 Operatore host

"$OPERATOR_THT" --installation "$INSTALLATION" workspace inspect \
  --workspace "$WS" --json
"$OPERATOR_THT" --installation "$INSTALLATION" workspace vector inspect \
  --workspace "$WS" --json
"$OPERATOR_THT" --installation "$INSTALLATION" workspace preprocess evidence \
  --workspace "$WS" --dry-run --json
"$OPERATOR_THT" --installation "$INSTALLATION" workspace preprocess evidence \
  --workspace "$WS" --json

Per un resume controllato:

"$OPERATOR_THT" --installation "$INSTALLATION" workspace preprocess evidence \
  --workspace "$WS" --resume <run-id-32hex> --json

9.3 Probe tipizzata tecnica, non superficie host

search evidence richiede il config runtime temporaneo e non è direttamente esposto dal CLI host. Il collaudo deve quindi usare un helper assistito che apra la stessa lease revision-pinned del core, attesti nel JSON installazione, workspace, workspace revision e vector generation, invochi ricerca o evaluation senza divulgare il config, quindi distrugga la lease. Interfaccia minima richiesta:

"$EVIDENCE_PROBE" validate-fixture --workspace-root "$WS_ROOT" --json
"$EVIDENCE_PROBE" search --installation "$INSTALLATION" --workspace "$WS" \
  --stage clarification --query "<domanda>" --json
"$EVIDENCE_PROBE" search --installation "$INSTALLATION" --workspace "$WS" \
  --stage rewriting --query "<domanda>" --json
"$EVIDENCE_PROBE" search --installation "$INSTALLATION" --workspace "$WS" \
  --stage schema_linking --query "<domanda>" --json
"$EVIDENCE_PROBE" search --installation "$INSTALLATION" --workspace "$WS" \
  --stage cte --query "<domanda>" --json
"$EVIDENCE_PROBE" search --installation "$INSTALLATION" --workspace "$WS" \
  --stage final_sql --query "<domanda>" --json

# Filtri negativi RET-05:
"$EVIDENCE_PROBE" search --installation "$INSTALLATION" --workspace "$WS" \
  --stage schema_linking --query "<domanda D2>" \
  --require-table "datawarehouse.tabella_inesistente_lab" --json
"$EVIDENCE_PROBE" search --installation "$INSTALLATION" --workspace "$WS" \
  --stage schema_linking --query "<domanda D2>" \
  --require-column "datawarehouse.tabella_inesistente_lab.colonna_inesistente" --json

Il JSON di search evidence serve per ID, excerpt, purpose, revision e generation. I rank separati dense, bm25 e fused non sono presenti nel JSON di search. Dopo ogni preprocess riuscito eseguire l'evaluation revision-pinned dell'ACTIVE; per una generation retained usare la sua revisione:

"$EVIDENCE_PROBE" evaluate --installation "$INSTALLATION" --workspace "$WS" \
  --revision <commit-40hex> --active --json
"$EVIDENCE_PROBE" evaluate --installation "$INSTALLATION" --workspace "$WS" \
  --revision <commit-storico-40hex> --generation <generation-32hex> --json

evaluate deve restituire profilo, expected/missing, empty result e rank dense/BM25/fused per query, materializzare l'authoring tree e evaluation.yaml della revisione dichiarata, aprire una lease Qdrant legata alla stessa revisione e attestare revision/generation nel JSON; usare la lease corrente su una generation storica non è valido.

L'implementazione corrente non persiste l'EvaluationReport della candidate fallita: lo riduce a un esito booleano e compensa i punti. Per osservare missing_expected e rank di G3-bad serve prima una modifica prodotto che salvi un report sanitizzato nel run artifact prima della compensazione. Senza questa modifica si può provare solo il fallimento generico e l'immutabilità di ACTIVE; il dettaglio candidate è NOT OBSERVABLE e preclude COMPLETE PASS. Se manca anche l'helper, marcare RET-01/02/03/04/05/06 e le evaluation dirette NOT RUN; il collaudo resta INCONCLUSIVE.

validate-fixture deve invocare lo stesso load_evaluation_fixture del prodotto senza model call né accesso vector. evidence validate non legge evaluation.yaml: il suo exit 0 prova il corpus authoring, non la struttura della fixture.

I mapping stage-purpose attesi sono:

Stage Purpose
clarification disambiguation
rewriting rewriting
schema_linking schema_linking
cte sql_generation
final_sql sql_generation

Non devono esistere consultazioni Evidence in Memory o Synthesis.

10. Ciclo G1 — creazione iniziale con D1 e D2

  1. Aggiungere soltanto D1 e D2 in source/.
  2. Eseguire evidence prepare da worktree con curated/ e manifest.yaml puliti.
  3. Verificare changed=[D1,D2], due model call e due ID creati. Un numero diverso di candidati è una violazione del contratto corrente e richiede revisione prima di proseguire.
  4. Revisionare ogni Curated Evidence v3:
    • una sola unità atomica;
    • kind e purpose corretti;
    • ID stabile evidence:<slug>;
    • source file/hash corretti;
    • excerpt esatto presente nella source;
    • nessuna informazione inventata o secret;
    • marker canonici presenti e Markdown leggibile.
  5. Dopo ogni prepare, curated/ e manifest.yaml sono dirty e un altro prepare è bloccato. Revisionare l'output e creare un commit locale di review (non ancora pubblicato) per tornare a un authoring state pulito; solo allora correggere la source e rieseguire prepare. Ripetere se necessario e non correggere i marker a mano.
  6. Creare evaluation.yaml dopo aver conosciuto gli ID. Il contratto richiede almeno una query per ciascun profilo lexical, semantic e mixed; l'insieme deve coprire i purpose presenti. Il profilo classifica il caso di test: l'evaluator esegue comunque il retrieval ibrido runtime e registra separatamente rank dense, BM25 e fused. Usare almeno una query dedicata per ciascun ID importante: quando una singola query dichiara più ID attesi, il PASS Hit@10 richiede che ne compaia almeno uno e non prova automaticamente tutti.
  7. Eseguire prima EVIDENCE_PROBE validate-fixture, poi evidence validate; entrambi devono uscire 0, mentre solo il secondo espone publishable=true per il corpus.
  8. Committare localmente lo stato finale valido. Solo ora, da worktree pulito, rieseguire prepare senza modifiche: modelCalls=0, changed=[], entrambe le source in unchanged e nessun diff.
  9. Pushare la testa valida della revisione G1; aggiornare il repository dalla UI. Eventuali commit intermedi restano una review trail e non devono contenere secret.
  10. Eseguire inspect, vector inspect, dry-run e preprocess reale.
  11. Verificare evaluation PASS, attivazione atomica e inventory.

Gate G1

  • Esistono esattamente due unità attive e recuperabili.
  • Source/support file non vengono indicizzati.
  • Il named vector bm25 con modifier idf è presente senza perdita del dense unnamed.
  • Punti schema preesistenti nella collection lab sono invariati.
  • Un secondo preprocess identico restituisce unchanged e non crea punti duplicati.

11. Ciclo G2 — inserimento incrementale di D3

  1. Aggiungere soltanto D3.
  2. Eseguire prepare/review/validate.
  3. Verificare una sola model call, un solo nuovo ID e D1/D2 invariati.
  4. Aggiungere all'evaluation query lexical, semantic o mixed per D3 e per la domanda composita; eseguire validate-fixture oltre a evidence validate.
  5. Commit, push, UI update, dry-run e preprocess reale.
  6. Verificare nominalmente che D3 abbia una nuova document generation e che D1/D2 riusino le precedenti. Se il cambio del path commit-addressed nella source URI forza il re-embedding di tutti i documenti, registrarlo come difetto/limite di incrementalità, non come PASS silenzioso. Se invece riusa le generation ma non esistono punti recuperabili sotto la revisione G2 corrente, registrare FAIL di retrieval/incrementalità.
  7. Verificare che il manifest ACTIVE elenchi tutte e tre le unità.
  8. Prima di lasciare G2 eseguire RET-01..06, RET-08 e le sessioni S1, S2 e S3 della sezione 15.1: dopo G4 D2 sarà ritirata e gli stessi oracle non saranno più eseguibili.

Gate G2

  • La formula è una sola espressione PostgreSQL, con input qualificati.
  • La formula pubblicata è citabile; una formula proposta nella sessione resta session-only e non riceve un ID evidence:.
  • Il retrieval combina correttamente D1, D2 e D3 quando la domanda lo richiede.

12. Ciclo G3 — modifica e riacquisizione

Questo ciclo combina update, pinning di sessione, conflitto e rollback della candidate. L'ordine è parte dell'oracle e non va cambiato.

  1. Subito dopo G2, creare una sessione, portarla almeno fino a una receipt/citation D1 e lasciarla incompleta e resumable. Salvare session ID, workspace revision G2, Evidence generation e receipt.
  2. Nel clone di authoring modificare soltanto D1, mantenendo lo stesso concetto ma cambiando in modo osservabile la definizione: aggiungere una nuova canary e rimuoverne una vecchia.
  3. Prima di prepare, eseguire validate: deve rilevare il drift di hash/provenienza e bloccare.
  4. Eseguire prepare: una model call, D1 in changed, D2/D3 in unchanged. L'ID D1 resta identico; source hash e contenuto canonico cambiano.
  5. Aggiornare le query nominali dell'evaluation per la nuova formulazione, mantenendo i profili lexical, semantic, mixed e una query per ogni ID importante.
  6. Aggiungere poi un caso G3-bad strutturalmente valido: un'ulteriore query mixed con expected ID D1 esistente, ma purpose sql_generation, che non appartiene a D1 (disambiguation/rewriting). Non usare ID inventati e non eliminare gli altri profili. Eseguire validate-fixture: deve restituire 0; eseguire separatamente evidence validate, il cui exit 0 non costituisce prova sulla fixture. Se uno dei due fallisce, ridisegnare il caso prima del test.
  7. Revisionare, committare G3-bad, pushare, usare Update workspace repository e registrare la nuova registry active revision. L'Evidence ACTIVE generation deve essere ancora G2.
  8. Fare resume della vecchia sessione: deve restare pinnata a G2, conservare artifact/receipt e mostrare D1 vecchio, anche se il registry è già alla candidate revision G3-bad.
  9. Tentare il preprocess G3-bad mentre la sessione è resumable: atteso preprocessing_conflict; nessuna candidate generation né modifica ad ACTIVE.
  10. Prima di finalizzare la sessione G2, salvare snapshot, artifact, citation e prova della revisione pinnata. Poi finalizzarla per sbloccare il preprocess. Una sessione finalizzata non protegge più lo snapshot dalla retention, anche se non è archiviata; non usarla come oracle post-G6.
  11. Ripetere il preprocess G3-bad: la candidate deve fallire la retrieval evaluation e venire compensata. Distinguere gli oracle: il puntatore Evidence e i punti fisici G2 restano; la vecchia sessione pinnata G2 è stata verificata prima della finalizzazione; il runtime corrente è invece legato alla registry revision G3-bad. Interrogarlo esplicitamente. Il PASS richiede rollback del registry o routing coerente alla revisione G2; se la vista corrente è vuota per revision mismatch, registrare split-brain/FAIL, non “ACTIVE G2 disponibile”. Con la diagnostica 9.3 salvare missing_expected, rank e candidate generation; altrimenti dettaglio NOT OBSERVABLE.
  12. Correggere la fixture assegnando a D1 un purpose ammesso, rieseguire validate-fixture e evidence validate, committare G3-fix, pushare e aggiornare di nuovo il repository.
  13. Eseguire dry-run e preprocess: evaluation PASS e switch atomico a G3. Verificare nuova document generation per D1 e riuso delle document generation D2/D3; se la source URI commit-addressed forza un full re-embedding, registrarlo come difetto di incrementalità. Se il riuso lascia i punti solo sotto la revisione G2, il filtro runtime G3 non li recupera e il ciclo è FAIL.
  14. La nuova canary deve trovare D1. La formulazione rimossa non deve comparire negli excerpt o payload dell'active view; la sola retrieval semantica col vecchio termine non prova stale data.
  15. Creare una nuova sessione: deve essere pinnata a G3 e vedere D1 nuovo. Registrare separatamente revision, generation, artifact e receipt della sessione G2 e di quella G3.

13. Ciclo G4 — cancellazione e retirement di D2

La cancellazione non deve mai essere silenziosa.

  1. Rimuovere il file source D2.
  2. Eseguire prepare: D2 deve diventare orphan; l'unità non viene cancellata automaticamente.
  3. Eseguire validate: exit 3, orphaned_unit e/o source_no_longer_supports_unit; nessuna pubblicazione ammessa.
  4. Committare e pushare lo stato orphan su una revisione G4-bad del branch lab, quindi aggiornare il repository dell'installazione isolata. Se il registry rifiuta la candidate, registrare esattamente il componente che ha bloccato e marcare il preprocess downstream NOT RUN: non è la stessa prova del gate di preprocess. Se il registry la accetta, il preprocess deve bloccare e lasciare il puntatore Evidence su G3; poi interrogare il runtime corrente G4-bad. Se non recupera G3 perché il filtro revision-pinned non coincide, registrare split-brain/FAIL. Se il registry ha rifiutato la candidate ed è rimasto G3, verificare invece che G3 resti recuperabile.
  5. Da quel worktree pulito, il reviewer decide il retirement ed esegue evidence resolve ... --retire.
  6. Aggiornare evaluation.yaml: eliminare o sostituire ogni query che attende D2, mantenendo almeno un caso per ciascun profilo lexical, semantic, mixed, la copertura dei purpose ancora attivi e query dedicate a D1/D3.
  7. Eseguire validate-fixture e evidence validate con exit 0, committare la risoluzione G4-fix, pushare la testa valida, fare UI update e preprocess.
  8. Verificare che D2 non sia nel manifest ACTIVE, nell'evaluation o nei risultati runtime.

Punti di D2 possono ancora esistere fisicamente in una generazione retained. Non è un difetto se il manifest ACTIVE e i filtri per document ID/generation impediscono di restituirli. È un difetto se una ricerca attiva li restituisce.

Eseguire entrambi i rami in revisioni separate.

14.1 G5 — rename identico

  1. Rinominare la source D1 senza cambiare un byte.
  2. Eseguire prepare.
  3. Atteso: riconoscimento univoco tramite hash, ID stabile, nessuna ristrutturazione non necessaria.
  4. Pubblicare e verificare citation/provenienza sul nuovo path.
  1. Rimuovere il source path corrente di D1, eseguire prepare e verificare l'orphan con validate exit 3; creare un commit locale G6-orphan. Questo passaggio è necessario: aggiungere prima il nuovo file trasformerebbe il caso in rename/hash match, non in relink.
  2. Dal commit G6-orphan creare un worktree/branch negativo separato. Aggiungere e committare una source priva dell'exact excerpt, poi lanciare resolve --source: atteso exit 1 con finding supporting_excerpt_missing. Il relink può essere applicato, ma validate/publish devono restare bloccati; non unire questa variante.
  3. Nel worktree principale, ancora pulito sul commit G6-orphan, aggiungere il nuovo file source con gli exact excerpt necessari e committarlo senza eseguire prepare.
  4. Eseguire evidence resolve ... --source source/<nuovo-path>.
  5. Verificare stesso ID, nuovo source file/hash, rimozione dell'orphan e assenza del finding.
  6. Validare, commit/push, UI update, preprocess e verificare il nuovo citation path. Conservare il branch negativo fino alla chiusura del report; niente reset distruttivi.

15. Matrice di retrieval e uso core

ID Scenario Oracle
RET-01 Token esatto di ogni source Evidence attesa entro top 10; rank dense/BM25/fused registrati
RET-02 Parafrasi senza token esatto Evidence attesa via ramo semantico/fusione
RET-03 Query mixed Evidence attesa con entrambe le branche diagnosticate
RET-04 Purpose errato Evidence non deve comparire nello stage non autorizzato
RET-05 required_table/required_column non corrispondenti outcome available con zero risultati
RET-06 Query non correlata available vuoto o nessun ID atteso; non unavailable
RET-07 Qdrant/Ollama indisponibile outcome unavailable, stage bloccato e retry dello stesso stage; niente stale fallback
RET-08 Canary incrociate lab/psd-clinical nessun ID o payload dell'altro workspace attraversa il namespace
RET-09 Query lab dopo modifica solo contenuto della revisione/generazione attiva
RET-10 Citation file immutabile materializzato, source/provenienza verificabili
CORE-01 Sessione F1-F8 completa cinque receipt: clarification, rewriting, schema_linking, cte, final_sql
CORE-02 Evidence accettata al gate decisione persistita e evidence.json coerente
CORE-03 Evidence rifiutata al gate rifiuto persistito; non usata come fatto downstream
CORE-04 Formula proposta dalla sessione resta formula_proposal, non Published Evidence
CORE-05 Nuova vs vecchia sessione revision pinning rispettato
CORE-06 Prompt injection nella source trattata come dati, mai come istruzione; nessuna esfiltrazione/tool action

Le receipt devono contenere stage, purpose, vector generation e ID, non una copia integrale delle Evidence. Una nuova ricerca nello stesso stage sostituisce solo la receipt di quello stage.

15.1 Sessioni utente obbligatorie

Eseguire casi separati: una sola sessione non dimostra tutti i comportamenti. S1, S2, S3, RET-01..06 e RET-08 vanno eseguiti alla fine di G2; S5 durante G3; S4 solo dopo retention, snapshot e non-regressione G6.

  1. S1 — accettazione: porre una domanda che richieda D1, D2 e D3; avanzare F1-F8, accettare le Evidence pertinenti ai gate e salvare cinque receipt. Verificare decision ledger, evidence.json, citation e SQL finale contro i testi originali.
  2. S2 — rifiuto: in una nuova sessione porre una domanda che recuperi certamente D2, rifiutarla al gate e completare il flusso. Il rifiuto deve essere persistito e D2 non deve diventare un fatto accettato negli artifact downstream.
  3. S3 — proposta: chiedere un calcolo non presente nel corpus e lasciare che la sessione proponga una formula. Deve restare formula_proposal session-only: nessun file curated, manifest, punto Qdrant o ID evidence: viene creato.
  4. S4 — prompt injection (G7/G8 security): in G7 aggiungere una quarta source atomica con contenuto business innocuo e una frase che ordina al modello di ignorare le regole, mostrare secret o usare tool. prepare non deve obbedire alla frase né produrre leakage/tool action; aggiungere una query evaluation dedicata al nuovo ID, eseguire validate-fixture, pubblicare, interrogarla in una nuova sessione e verificare che sia trattata solo come dato. In G8 ritirarla, rimuovere/sostituire la sua query, rivalidare la fixture e pubblicare la revisione pulita.
  5. S5 — pinning: usare le due sessioni G2/G3 della sezione 12 e confrontare revision, generation, citation e artifact, non soltanto il testo mostrato nella chat.

Per RET-04 eseguire una query D1 nello stage schema_linking e una D2 nello stage rewriting; per RET-05 usare entrambe le opzioni --require-table e --require-column della probe; per RET-06 usare una query non correlata predefinita. L'oracle è rispettivamente assenza per purpose, available con risultato vuoto e available vuoto. RET-07 va eseguito solo nella stack fault isolata: l'outcome è unavailable, la fase corrente non avanza e il retry riparte dallo stesso stage.

Per RET-08 usare la canary e l'ID PSD salvati in PRE-04 e una canary lab rara:

"$EVIDENCE_PROBE" search --installation "$INSTALLATION" --workspace psd-clinical \
  --stage clarification --query "LAB-ZAFFIRO-731" --json
"$EVIDENCE_PROBE" search --installation "$INSTALLATION" --workspace "$WS" \
  --stage clarification --query "<canary PSD baseline>" --json

Ogni JSON deve attestare il workspace/revision richiesto e non contenere ID, excerpt o payload dell'altro namespace. Ripetere RET-08 dopo G6 e dopo G8 senza cambiare le impostazioni globali o mutare PSD.

evaluation.yaml richiede almeno un ID atteso non vuoto e non esprime forbidden ID o un oracle “deve restituire zero risultati”. RET-04, RET-05 e RET-06 devono quindi restare probe manuali/CLI separate e non possono essere dichiarate coperte dal solo PASS dell'evaluation.

16. Inventario vettoriale corretto

workspace vector inspect verifica oggi collection, dimensioni e distanza; non è un inventario dei record. Per il test esaustivo l'agente deve fornire un helper read-only con questa interfaccia minima:

"$EVIDENCE_INVENTORY" capture --installation "$INSTALLATION" --workspace "$WS" \
  --scope pointer --output "$REPORT/<ciclo>/inventory-pointer.json"
"$EVIDENCE_INVENTORY" capture --installation "$INSTALLATION" --workspace "$WS" \
  --scope active --output "$REPORT/<ciclo>/inventory-active.json"
"$EVIDENCE_INVENTORY" capture --installation "$INSTALLATION" --workspace "$WS" \
  --scope retained --output "$REPORT/<ciclo>/inventory-retained.json"

L'helper risolve i path e gli endpoint dall'installazione senza stampare secret, legge ACTIVE e il generation manifest, quindi pagina lo scroll Qdrant fino a esaurimento con with_vector=false. Deve produrre tre viste distinte: set dichiarato dal pointer, active runtime e retention fisica. Se l'helper non è presente o non attesta la revisione osservata, l'inventory è INCONCLUSIVE.

Per ogni ciclo:

  1. leggere ACTIVE e il generation manifest;
  2. estrarre document_generations;
  3. costruire la pointer view dalle coppie esatte (document_id, vector_generation) di document_generations, anche cross-revision, per provare quali punti fisici supportano il puntatore Evidence;
  4. costruire l'active runtime view aggiungendo workspace_id=psd-evidence-lab e la workspace_revision pinnata, replicando tutti i predicati runtime prima del limit;
  5. acquisire separatamente tutti i punti retained del workspace e raggrupparli per Evidence ID, document ID, vector generation e workspace_revision; ogni punto deve avere record_kind=evidence e kind=evidence;
  6. verificare gli otto payload index richiesti: content_hash, document_id, kind, record_key, record_kind, vector_generation, workspace_id, workspace_revision;
  7. verificare che gli ID/document generation consentiti dal manifest ACTIVE e quelli realmente interrogabili dal runtime coincidano; ogni differenza è split-brain.

Non assumere che tutti i documenti attivi abbiano la generation più recente: il manifest può riusare una document generation precedente. Tuttavia il Qdrant runtime filtra anche per revisione corrente: se i punti riusati esistono solo sotto la revisione vecchia e non vengono recuperati, è un difetto di incrementalità/retrieval, non un motivo per omettere il filtro dall'oracle. Non assumere neppure che il numero totale di punti Qdrant equivalga al corpus attivo: retention e candidate cambiano il totale.

17. Atomicità, idempotenza, retention e recovery

ID Scenario Esito atteso
REL-01 preprocess --dry-run nessuna modifica a ACTIVE, corpus o punti
REL-02 prepare invariato zero model call e zero diff
REL-03 preprocess invariato status unchanged, nessuna duplicazione
REL-04 evaluation candidata fallisce candidate compensata e pointer precedente intatto; registry/runtime ancora coerenti, altrimenti split-brain FAIL
REL-05 embedding fallisce durante candidate nessuna attivazione o stato parziale visibile
REL-06 Qdrant fallisce durante upsert ACTIVE precedente intatto; retry idempotente
REL-07 due preprocess simultanei uno solo procede; l'altro preprocessing_conflict
REL-08 resume stesso run/commit/config riparte dal checkpoint valido e pubblica una sola volta
REL-09 resume dopo cambio commit/config preprocessing_resume_mismatch, nessuna mutazione
REL-10 checkpoint/artifact corrotto fail closed, nessuna attivazione
REL-11 collection mancante self-heal compatibile; dense, BM25/IDF e payload index ricreati
REL-12 BM25 mancante aggiunta bm25/idf senza rebuild del dense
REL-13 dimensioni/distance/BM25 incompatibili semantic_index_incompatible, nessuna mutazione distruttiva

REL-01/02/03/04 fanno parte del percorso lifecycle. REL-05..13 sono una campagna engineering su stack dedicata: usare un fault proxy scoped, volumi usa-e-getta e snapshot del dataRoot lab. Durante un fallimento mid-upsert possono esistere punti candidate fisici, ma non devono entrare nell'active view; compensazione/retry devono ricondurre lo stato all'oracle. Non simulare questi casi fermando Qdrant o Ollama condivisi con PSD.

L'harness deve offrire assert-isolated, inject, barrier, wait, abort, release, clear, status e restore, sempre attestando installazione, workspace, endpoint e collection. Preflight e cleanup minimi:

"$EVIDENCE_FAULT" assert-isolated --installation "$INSTALLATION" --workspace "$WS" --json
"$EVIDENCE_FAULT" status --installation "$INSTALLATION" --workspace "$WS" --json
"$EVIDENCE_FAULT" clear --installation "$INSTALLATION" --workspace "$WS" --all --json
"$EVIDENCE_FAULT" restore --installation "$INSTALLATION" --workspace "$WS" --json

# Forme comuni; inject/barrier restituiscono faultId/barrierId:
"$EVIDENCE_FAULT" inject --installation "$INSTALLATION" --workspace "$WS" \
  --fault <fault> --once --json
"$EVIDENCE_FAULT" barrier --installation "$INSTALLATION" --workspace "$WS" \
  --at <checkpoint> --json
"$EVIDENCE_FAULT" wait --installation "$INSTALLATION" --workspace "$WS" \
  --event barrier-reached --json
"$EVIDENCE_FAULT" abort --installation "$INSTALLATION" --workspace "$WS" \
  --run-id <run-id-32hex> --json
"$EVIDENCE_FAULT" release --installation "$INSTALLATION" --workspace "$WS" \
  --barrier-id <barrier-id> --json
Caso Fault/operazione deterministica
REL-05 inject --fault embedding-fail --once; preprocess, ACTIVE invariato, clear e retry
REL-06 inject --fault qdrant-upsert-fail --after-points <N> --once; inventory candidate/active, clear e retry
REL-07 barrier --at after-writer-lock; terminale A avvia preprocess; wait restituisce run ID; terminale B tenta preprocess e riceve conflict; release completa A
REL-08 barrier --at after-checkpoint:embed; avviare e attendere il run ID, abort --run-id, poi host CLI --resume <run-id> sullo stesso commit/config
REL-09 creare un secondo checkpoint come REL-08, abortire, pubblicare una candidate commit/config diversa e tentare --resume <vecchio-run-id>; atteso mismatch; poi ripristinare con un nuovo commit valido
REL-10 su copia del checkpoint, inject --fault corrupt-checkpoint --run-id <id>; resume fail closed; restore
REL-11 dopo snapshot, inject --fault collection-missing; preprocess deve ricreare il contratto previsto; restore
REL-12 inject --fault collection-dense-only; verificare aggiunta BM25/IDF senza perdita dense; restore
REL-13 ripetere con wrong-dimension, wrong-distance, invalid-bm25; ogni caso fallisce senza rebuild distruttivo; restore

I comandi wait/status devono essere la fonte del run ID: oggi non esiste un elenco job pubblico. Dopo ogni caso eseguire clear, verificare nessun processo/barrier residuo, inventory e ACTIVE. Se l'harness non implementa l'interfaccia, REL-05..13 sono NOT RUN e COMPLETE PASS è vietato.

Le pubblicazioni G1-G6 superano retain_published_generations: 3. Dopo G6 verificare:

  • ACTIVE + due generazioni di rollback conservate;
  • generazione più vecchia eliminata quando non protetta;
  • sub-generation ancora referenziate dai manifest retained non eliminate;
  • checkpoint resumable protetti e preprocessing di una revisione diversa bloccato finché esiste una sessione resumable incompatibile;
  • snapshot Git referenziati da sessioni ancora resumable (status != finalized e non archiviate) conservati; la prova G2 si raccoglie prima di finalizzare la sessione nella sezione 12;
  • filesystem e Qdrant coerenti dopo GC.

Il comando GC della CLI harness è una diagnostica tecnica, non una superficie operatore pubblica; non va presentato come normale gesto utente.

18. Test negativi e sicurezza

Eseguire i casi distruttivi solo in un worktree/branch e collection usa-e-getta del laboratorio.

18.1 Authoring e canonical format

  • source multi-concetto: una sola unità primaria oppure review item, mai fusione silenziosa;
  • supporting excerpt assente o non esatto;
  • ID duplicato o stessa unità associata a due source;
  • body/metadata desincronizzati;
  • marker tht: mancante, duplicato o alterato;
  • campo sconosciuto o payload del kind errato;
  • source hash/manifest hash alterato manualmente;
  • file non UTF-8, vuoto non significativo o oltre 10 MiB;
  • symlink in source/curated;
  • dirty curated/ o manifest.yaml prima di prepare;
  • una di tre ristrutturazioni fallisce: nessuna applicazione parziale.

18.2 Descriptor e materializzazione

  • evidence.schema_version omesso: il parser può applicare il default legacy v1, ma il laboratorio deve rifiutarlo come deviazione dalla baseline v2 esplicita; un valore invalido deve fallire;
  • pattern diverso da curated/**/*.md;
  • per la source filesystem, URI assoluto, traversal o cross-namespace; HTTP richiede un URI http(s):// canonico e S3 un URI s3:// secondo i rispettivi adapter;
  • symlink, gitlink, path duplicato, file non regolare o race;
  • oltre 4096 entry, 64 MiB totali, 8 MiB/file, manifest oltre 1 MiB; per il path verificare esplicitamente 4096 byte accettati e 4097 byte rifiutati;
  • candidate Git revision invalida: la precedente resta attiva.

I boundary di 4096 entry, 64 MiB e path 4096/4097 byte vanno costruiti in fixture automatiche o in un repository Git usa-e-getta con plumbing controllato e materializer isolato, non pushati nel repository condiviso del lab. Il test path deve inoltre verificare che l'ambiente permetta di creare la fixture senza fallire prima del codice sotto test. Se manca l'harness, questi casi sono NOT RUN nel collaudo manuale.

18.3 Dati, rete e segreti

  • provenance URI dichiarata con userinfo, credenziali, token o query firmata; il transport URL firmato supportato può invece stare nel signed_urls_file, ma non deve apparire in descriptor, report o log;
  • prompt injection nella source;
  • tentativo di indicizzare source/, evaluation.yaml o support file;
  • HTTP redirect/rebind verso host privato e S3 endpoint non consentito, nella suite adapter P2;
  • utente non amministratore sui controlli Workspace Management;
  • JSON machine output contaminato da log o secret;
  • export/backup applicativo che includa byte Evidence o secret quando non previsto.

19. Non regressione

Prima di G1 e dopo G6 confrontare:

  • punti e nearest-neighbour canary di schema_table e schema_column;
  • punti memory e solved_question eventualmente presenti;
  • dimensioni, distanza e dense unnamed della collection;
  • query di controllo in psd-clinical;
  • accesso DWH rigorosamente read-only;
  • settings globali ripristinati esattamente al baseline e sessioni PSD non modificate.

delete_generation/retention Evidence non deve cancellare altri record kind. vector rebuild --destroy non fa parte del percorso nominale; se usato per provare restore/cleanup deve puntare alla collection lab, ripetere esattamente il suo nome nei guard e avere autorizzazione esplicita.

20. Adapter e kind estesi (P2)

La dichiarazione di copertura completa oltre il percorso filesystem richiede due campagne separate:

  1. HTTP reale: redirect, cache, timeout, byte limit, SSRF e rebind;
  2. S3 reale: paginazione, size/object limits, secret file bounded, endpoint policy e credenziali non divulgate.

Non applicare a HTTP/S3 l'oracle del tree source//curated//manifest.yaml né l'obbligo di candidate evaluation del filesystem v2. Per questi adapter l'oracle è acquire/normalize/chunk del contenuto remoto dichiarato, secondo URI, credenziali, limiti e policy specifici.

Per i cinque kind non coperti da D1-D3 creare micro-source atomiche e ripetere prepare/validate/preprocess/evaluate/search. Questi test non devono essere mescolati al lifecycle principale, altrimenti un fallimento non è diagnosticabile.

La campagna P2 deve inoltre coprire:

  • fixture legacy v1 e v2 con "$AUTHOR_THT" evidence migrate <workspace-root> --json, verificando migrazione deterministica a v3, nessuna model call e ID/provenienza coerenti;
  • "$AUTHOR_THT" evidence prepare <workspace-root> --upgrade --json, che riprocessa tutte le source con la pipeline installata senza duplicare unità;
  • "$EVIDENCE_PROBE" evaluate ... --revision <revision-storica> --generation <generation> --json, materializzando snapshot, config ed evaluation.yaml della revisione che pubblicò la generation; provare sia ACTIVE sia una generation retained;
  • un cambio controllato di kind della stessa unità, con payload completo per il nuovo kind: l'ID resta stabile, la nuova versione è attiva e la vecchia non è restituita dall'active view.

21. Copertura automatica da usare come prerequisito

Eseguire i gate completi con comandi separati:

cd /Users/mp/projects/ThothII/harness
.venv/bin/pytest -q

cd /Users/mp/projects/ThothII/backend
npx vitest run
npx tsc --noEmit -p .

cd /Users/mp/projects/ThothII/frontend
npx vitest run
npx tsc -b

Il marker l2 è escluso dal default del harness e va eseguito esplicitamente con .venv/bin/pytest -q -m l2 quando credenziali e servizi reali sono disponibili. I test l0 che usano testcontainers richiedono Docker; skip o ambiente mancante vanno riportati nel verbale. Conservare inoltre il dettaglio dei gruppi rilevanti:

  • harness/tests/test_evidence_authoring.py e test_evidence_cli.py;
  • test_evidence_canonical.py, filesystem/HTTP/S3 source adapter tests;
  • test_corpus_pipeline.py, test_corpus_publish.py, candidate publication ed evaluation;
  • test_qdrant_vector_store.py e, con Docker, tests/l0/test_qdrant_bm25_inference.py;
  • backend registry/materialization/preprocessing service/state tests;
  • frontend WorkspaceManager.test.tsx.

Queste suite usano in vari punti fake di embedder/Qdrant. Un PASS automatico non sostituisce il percorso live di questo piano.

21.1 Seam ad alto rischio da osservare esplicitamente

Questi punti risultano rischiosi nell'implementazione corrente e non devono essere esclusi dal verbale se falliscono:

  • la risoluzione citation delle unità v3 potrebbe cercare l'ID nella forma legacy anziché nei metadata curated_evidence;
  • una nuova source URI commit-addressed può far apparire modificati documenti con contenuto invariato e causare un full re-embedding;
  • se una document generation viene riusata ma i suoi punti esistono solo sotto la revisione vecchia, il filtro Qdrant revision-pinned può renderla irrecuperabile: inventory e retrieval devono fallire;
  • workspace vector rebuild può ricreare il dense senza ripristinare subito BM25: non usarlo come recovery nominale e, se testato, verificare il contratto completo dopo il rebuild;
  • il writer lock/conflitto va provato live, perché la sola presenza delle primitive nei test non dimostra che il percorso produttivo le acquisisca;
  • non esiste un comando pubblico per inventory, elenco job o riattivazione di una generazione precedente;
  • il report dettagliato della candidate evaluation fallita non è persistito prima della compensazione; serve instrumentation prodotto per osservarne rank e missing_expected;
  • l'adapter S3 operativo è più restrittivo di alcune varianti accettate dallo schema; i casi custom vanno classificati come gap di superficie, non come scenario nominale.

22. Criteri finali PASS/FAIL

Il collaudo filesystem/lifecycle è PASS solo se:

  1. G1-G6 completano con gli oracle documentati;
  2. ID stabili, hash, provenance, revision e generation sono coerenti;
  3. l'inserimento incrementale non reprocessa documenti invariati;
  4. la modifica non è visibile prima dell'atomic switch, la versione precedente resta recuperabile e la nuova lo è dopo; nessuno split-brain registry/Evidence;
  5. orphan blocca, retirement/relink sono espliciti e auditabili;
  6. nessun record retained/obsolete viene restituito come attivo;
  7. retrieval copre tutti i purpose, verifica l'outcome available vuoto e non mescola workspace/revision;
  8. le sessioni S1, S2, S3 e S5 coprono accettazione, rifiuto, proposta session-only e pinning; S1 contiene cinque receipt e decisioni/citation corrette;
  9. il conflict di sessione G3 e l'evaluation failure lasciano ACTIVE consistente;
  10. retention/GC e non regressione Schema/Memory/solved sono verificati;
  11. nessun secret o path non sicuro attraversa i confini;
  12. ogni FAIL ha reproduction, expected/actual, commit, revision, run ID e generation.

La dichiarazione COMPLETE PASS richiede inoltre: G7/G8 con S4 prompt injection; RET-07 unavailable/stage bloccato; report sanitizzato della candidate evaluation fallita; campagna fault/resume REL-05..13 su stack isolata; tutti gli otto kind; adapter HTTP/S3 reali supportati; migrazione v1/v2, --upgrade, evaluation di una generation selezionata e cambio kind. Se una di queste campagne non viene eseguita, il miglior esito ammesso è PASS — filesystem lifecycle, mai “copertura completa”.

Il risultato è INCONCLUSIVE, non PASS, se mancano inventory Qdrant, sessione core completa, proof di ACTIVE before/after o verifica della revisione pinnata.

23. Teardown sicuro

Eseguire il teardown solo dopo aver completato e verificato gli allegati:

  1. salvare hash del report, registry active revision, Evidence ACTIVE/generation manifest, inventory Qdrant e stato delle sessioni;
  2. verificare che il report contenga la prova snapshot/artifact/citation G2 raccolta prima della finalizzazione in G3; non richiedere che lo snapshot G2 esista ancora dopo G6;
  3. finalizzare tutte le sessioni lab ancora resumable e archiviarle dove la superficie lo consente, senza riaprire sessioni già chiuse;
  4. nella UI ripristinare psd-clinical come workspace selezionato e le impostazioni originarie; eseguire Validate workspace source, Test workspace connections e una nuova query canary PSD;
  5. rimuovere binding e secret del lab tramite la superficie supportata, se previsto dalla campagna; se non esiste una rimozione supportata, documentare il residuo senza esporne il valore;
  6. non cancellare collection, dataRoot, branch, commit o report prima della firma del verbale. La loro eliminazione è un'attività distruttiva separata e richiede autorizzazione esplicita e target risolti; preferire snapshot/archiviazione recuperabile;
  7. ripetere il controllo non-regressione PSD e registrare che settings, sessioni e punti non sono cambiati. Un fallimento di ripristino rende l'intero collaudo FAIL.

24. Template del verbale

# Evidence lifecycle acceptance — <data>

- Tester:
- Installazione:
- Branch/commit finale:
- Workspace/collection:
- DWH binding type:
- Ollama model/dimensions:
- Scope verdict (`PASS — filesystem lifecycle` / `COMPLETE PASS` / `INCONCLUSIVE` / `FAIL`):
- Version/hash di probe, inventory, fault harness e instrumentation evaluation:

| Ciclo | Commit | Registry active revision | Run ID | Candidate generation | Evaluation | Evidence ACTIVE before/after | Runtime active view | `document_generations` | Esito |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| G1 initial | | | | | | | | | |
| G2 add | | | | | | | | | |
| G3-bad | | | | | | | | | |
| G3-fix | | | | | | | | | |
| G4-bad | | | | | | | | | |
| G4-fix | | | | | | | | | |
| G5 rename | | | | | | | | | |
| G6 relink | | | | | | | | | |
| G7 security injection | | | | | | | | | |
| G8 security retire | | | | | | | | | |

## Retrieval/sessioni

| Query/stage | Purpose/filtri | Revision/generation | Expected/actual IDs | Rank dense/BM25/fused | Outcome | PASS/FAIL |
| --- | --- | --- | --- | --- | --- | --- |

## Fault e recovery

| Fault/fault ID | Barrier/run ID | ACTIVE prima | Risultato | ACTIVE dopo | Cleanup | PASS/FAIL |
| --- | --- | --- | --- | --- | --- | --- |

## Non regressione e sicurezza

- Schema/Memory/solved:
- Workspace isolation:
- Secret scan:
- Prompt injection:
- Retention/GC:

## Difetti

| ID | Severità | Reproduction | Expected | Actual | Allegati |
| --- | --- | --- | --- | --- | --- |

25. Riferimenti normativi

  • CONTEXT.md, sezione Evidence;
  • docs/evidence.md;
  • docs/contracts/workspace-evidence-v3.md;
  • docs/contracts/workspace-preprocessing-cli.md;
  • docs/operations/workspaces.md;
  • harness/.pi/skills/tht-evidence-authoring/SKILL.md;
  • harness/.pi/skills/tht-sessione/SKILL.md e modulo runtime Evidence;
  • harness/tht/evidence/ e harness/tht/cli/search_cmd.py.