- gateway/rerank.py: catena da RERANK_CHAIN (JSON, per-nodo key+timeout),
cooldown 60s sui nodi falliti, score sigmoide [0,1], degrada con grazia
all'ordine di fusione se tutti i nodi sono giù
- routes: /v1/memories:search applica il rerank post-fusione (fetch esteso a
RERANK_CANDIDATES), risposta con rerank{used,backend,took_ms}, flag
per-query rerank=false; /v1/version espone lo stato rerank
- store: search() accetta limit esteso; models: SearchIn.rerank
- metrics: qmem_rerank_calls_total + durata per backend
- test: 10 nuovi (fallback, cooldown, degradazione, integrazione) — 46 pass
- gateway: campo private (bool) in MemoryIn; filtro must_not private=true
di default in search_filter; include_private in SearchIn per ricerche
esplicite; campo private esposto in format_results
- estensione: parametro private in qmem_store, include_private in qmem_search
(con descrizioni e avvertenze sui prompt dei modelli)
- testato su brain: record private invisibile alla ricerca standard,
visibile solo con include_private=true; topic esplicito da solo non sblocca
- deploy: /opt/memory/gateway ricostruito (container memory-gateway)
- gateway: nel blocco supersede, i figli attivi (parent_id == vecchio UUID,
superseded_by vuoto) vengono ri-parentati al nuovo UUID; audit action
'reparent'; risposta con campo 'reparented'. Un solo livello: i nipoti
puntano agli UUID dei figli, invariati. I figli superseduti restano
storici ancorati alla vecchia lineage.
- estensione: qmem_tree con fallback lineage (cerca figli anche per
supersedes_id del root) per gli orfani pre-fix; qmem_correct riporta
il numero di figli ri-parentati.
- test: 2 nuovi (ri-parenta figli attivi; ri-parenta solo attivi con
figlio già superseduto). 34 pass.
- deploy su brain (10.8.0.3): main.py aggiornato, container ricreato,
smoke test end-to-end OK (reparented=1).
Regola auto-miglioramento: lezioni strutturate TRIGGER→CAUSA→AZIONE→VERIFICA
dopo fallimenti/successi sorprendenti; promozione a fact procedurale per
operazioni ricorrenti; consolidamento periodico. Vietate lezioni vaghe e
promozioni senza evidenza (anti-drift). Solo prompt: nessun cambiamento
server/API.
Aggiunge qmem_get (GET /v1/memories/{id}) per recuperare un record
esatto per memory_id: usato quando un puntatore/playbook cita un ID.
La ricerca semantica (qmem_search) non garantisce di trovare record
lunghi con query generiche; qmem_get lo risolve in modo deterministico.
Restituisce anche record superseduti (lineage/audit).
INCIDENTE 2026-08-16: l'upsert parziale in Qdrant sostituisce l'intero punto,
cancellando payload e vettori densi di tutti i record. update_vectors aggiorna
solo il vettore specificato. Recovery: 278/330 record ricostruiti dalle sessioni
pi (qmem_store/qmem_correct con memory_id), 52 persi (agenti su altre macchine).
- descrizione parametro expires_at in qmem_store: chiarisce che il default è permanente
- skill qmem: sezione Igiene dei record con la garanzia di permanenza
- comportamento verificato sul server: record senza expires_at non selezionato dal filtro cleanup
- raccolta in-memory: richieste per endpoint, latenza (sum/count), errori per status, search queries/hits, punti
- push periodico (30s) a VM via /api/v1/import/prometheus (pattern energy engine, timestamp ms)
- VM_PUSH_URL/VM_PUSH_INTERVAL/METRICS_ENABLED configurabili; default host.docker.internal:8428
- endpoint /v1/metrics (auth) per verifica manuale
- dashboard Grafana versionata in monitoring/qmem-dashboard.json (provisioning: /home/enne2/domotics/grafana/dashboards/)
- verificato sul server: /v1/metrics OK, 6 serie qmem_* in VM
- prima di salvare: ricerca top-3 con min_score 0.92 e stesso project_id
- se trovati: avviso nella risposta con id/score/testo dei candidati e suggerimento qmem_correct
- il salvataggio non viene bloccato
- verificato sul server: record quasi identici trovati con score 1.0/0.9908
- gateway: MemoryIn + payload + risultati search; 422 su valore invalido
- estensione: confidence in qmem_store e qmem_correct (eredita dal superseduto), mostrato nei risultati
- backward compatible: record esistenti → confidence null
- verificato sul server: high/medium/default, 422 su invalida (istanza di test)
- middleware: genera o accetta X-Request-ID, lo restituisce in header
- contextvar letto da _audit: correlazione richieste nei log
- verificato sul server: header + audit correlati (istanza di test)
- _get_http(): creazione lazy, keep-alive riusato tra le chiamate
- lifespan shutdown: aclose del client
- verificato sul server: status + search OK (istanza di test)
- startup (collection+indici) e cleanup task nel context manager lifespan
- shutdown: cancel del cleanup task
- verificato sul server: startup OK, scrittura OK (istanza di test)
- rifiuta il supersede se lo score del top-1 è sotto soglia (evidenza debole/rumorosa)
- messaggio guida: verifica con qmem_search e riprova con memory_id esplicito
- soglia configurabile in ~/.config/pi-qmem/config.json
- gatewayRequest: max 3 retry su 429/5xx/timeout/errore rete, backoff esponenziale + jitter, rispetta Retry-After (cap 10s)
- AbortError (annullamento utente) propagato, mai ritentato
- timeoutMs dalla config usato come fallback quando pi non fornisce signal
- testato: 503→200, sempre-503 (4 tentativi), 429+Retry-After, rete giù, abort
- gateway: tabella in-memory con TTL 24h, hash canonico del payload, scoped per API key
- estensione: crypto.randomUUID() per operazione (store e correct), riusata su retry
- from __future__ import annotations (forward-reference _payload_hash)
- promptGuidelines sui 4 tool (qmem_store/search/correct/meta): bullets nel Guidelines del system prompt, solo quando i tool sono attivi
- before_agent_start: blocco 'Regole pi-qmem' iniettato nel system prompt a ogni turno (solo se i tool qmem sono attivi) — regole vincolanti versionate con l'estensione
- skills/qmem/SKILL.md: procedura completa (punteggi, project_id, supersede, discovery) standard agentskills.io, distribuita via pi.skills nel manifest
- AGENTS.md ridotto a puntatore (riepilogo essenziale + rinvio a skill/tool)
- README aggiornato