# M2 — Ricerca ibrida e collegamenti Data: 2026-09-09. Implementazione locale dell'incremento M2 del [piano Memory approvato](2026-09-08-memory-management.md#piano-esecutivo). ## Risultato La ricerca Memory ed exemplar usa embedding dense e BM25 in Qdrant. I filtri sono applicati in entrambi i rami prima della selezione dei candidati. Il core espande i collegamenti uscenti, deduplica, limita cicli e visite, riordina insieme i risultati e restituisce il contenuto corrente verificato in PostgreSQL. Non usa un database a grafo né una chiamata LLM per il riordinamento. Il contesto fisico distingue database, schema, tabella e colonna e richiede che corrispondano alla stessa dipendenza strutturata. Le card senza dipendenze valgono per il workspace; un riferimento a un antenato fisico si applica ai suoi discendenti. Ambito descrittivo e concetti possono restringere ulteriormente la ricerca tramite `--filters`. La CLI impedisce di sostituire database/schema del runtime. Il dettaglio dei limiti e della formula di ranking è nel [contratto operativo](../gestione-memory.md#hybrid-recall-and-links). L'incremento conserva i confini dei gate correnti: F2 riceve chiarimenti di dominio, gli exemplar restano consultativi. Un collegamento non autorizza a consumare una famiglia diversa o una card fuori ambito. Il riepilogo finale, i nuovi gate e la pulizia delle dipendenze dopo sincronizzazione fisica appartengono a M3. ## Transizione e recupero La migrazione versionata `002_hybrid_projection.sql` aggiunge il formato delle proiezioni. Le card M1 restano autorevoli e consultabili; le loro proiezioni dense risultano pendenti e non possono alimentare il recall. Un retry esplicito o `tht memory index -c ` costruisce dense e BM25 dal contenuto corrente. Il formato della proiezione e la revisione della card sono verificati prima dell'uso. Il salvataggio può aggiungere il vettore sparse mancante nella sola collezione Memory. Non sostituisce configurazioni incompatibili e non modifica Reference. Il rebuild esplicito ricrea anche una collezione Memory assente; il test elimina la collezione, ricostruisce da PostgreSQL e verifica il ritorno della sola card conservata. Fallimenti lasciano il lavoro di propagazione persistito e recuperabile. Nessuna importazione da JSONL, sessioni storiche o vecchi payload Qdrant. ## Verifiche | Controllo | Esito | | --- | --- | | Suite harness senza L0/L2, escluso il file dei percorsi portabili | 1.152 test passati nell'esecuzione finale. | | Suite mirata Memory, adapter e CLI, con embedding reale | 78 test passati. | | Verifica aggiuntiva del rebuild con collezione assente e adapter | 54 passati; il solo test del modello reale era escluso in questa riesecuzione. | | API Fastify Memory | 13 test passati, compresa propagazione della lingua del workspace. | | Browser amministrativo integrato | Passato: creazione, modifica, riavvio, rilettura, cancellazione e verifica del recall. | | Wheel e casi CLI | 10 test passati; il wheel include entrambe le migrazioni Memory. | | Build e controlli statici | Build/typecheck backend, Ruff sui file Python interessati e build documentale strict passati. | - Test deterministici: collegamenti necessari, contenuto corrente, duplicati, cicli, profondità e limiti, card mancanti o pendenti, rifiuti già registrati, famiglie e ambiti esclusi, dipendenze omonime e filtri CLI vincolati al runtime. - Adapter: stesso filtro nei prefetch dense/BM25 per Memory ed exemplar; restano coperti i contratti Evidence esistenti. - PostgreSQL/Qdrant: salvataggio, modifica, cambio famiglia, cancellazione, ricostruzione, riferimento separato, isolamento, RLS, errori, retry e transizione delle proiezioni M1 al formato ibrido. - Recupero effettivo: client Ollama di produzione con il modello configurato `qwen3-embedding:0.6b`, dimensione 1024, e Qdrant dell'immagine fissata in Compose. La domanda sulla chiave commessa fra esercizi recupera la regola attesa e la granularità collegata, escludendo un altro database, un altro ambito e dipendenze che corrispondono soltanto combinando riferimenti distinti. Verifica separatamente dense, BM25 e fusione, poi recall, cancellazione e rebuild. Il test effettivo avvia un processo Ollama separato, montando il volume del modello installato in sola lettura. PostgreSQL e Qdrant sono container temporanei dedicati, eliminati a fine test. Non usa ID di risultati predisposti. Il browser amministrativo usa invece embedding deterministici: verifica il collegamento fra UI, autenticazione, Fastify, ThtRunner e persistenza, senza essere una misura di qualità del recupero. Non è una valutazione generale della qualità semantica su un corpus di produzione; verifica i casi di recupero richiesti da M2, con il percorso reale configurato. ## Riproduzione Dalla directory `harness`, con Docker disponibile: ```sh THT_HOME=/private/tmp/thothii-m2-test-home \ THT_MEMORY_TEST_OLLAMA_VOLUME= \ THT_MEMORY_TEST_MODEL=qwen3-embedding:0.6b \ THT_MEMORY_TEST_DIMENSIONS=1024 \ .venv/bin/pytest -q tests/memory/test_administration.py \ tests/memory/test_retrieval.py tests/memory/test_recall.py \ tests/test_qdrant_vector_store.py tests/test_solved_search_cli.py ``` Senza il volume esplicito, il solo test con modello reale viene escluso; gli altri test restano eseguibili. Il volume deve contenere il modello indicato. Le immagini Qdrant e Ollama del test sono lette da `compose.yaml`. Consegna locale: non sono stati eseguiti deploy, migrazioni delle installazioni attive o aggiornamenti remoti dell'issue tracker.