Commit Graph
11 Commits
Author SHA1 Message Date
enne2 1b293efb2c test: aggiorna fake cross per soglia SUGGEST 0.85 2026-09-08 13:04:57 +02:00
enne2 128059dd4b feat(gateway): strategie rerank oltre la search (A-F)
- A: gate store con cross-encoder — guardrail.decide async, conferma/scarta
  quasi-duplicati (CROSS_DUP_CONFIRMED/WEAK/LOW_COSINE), suggerimento
  supersedes in WARN, degrada a cosine-only se il reranker è giù
- B: verifica supersede — cross-score (nuovo,vecchio) sotto soglia →
  supersede_warning non bloccante + audit
- C: score composito in search — rerank + importance (nuovo campo payload)
  + recency decay (180gg) + authority, pesi SCORE_W_* da env
- E: multi-query — SearchIn.queries (max 3), pool unito con dedup, rerank
  unico; endpoint POST /v1/score come primitiva cross-encoder (F-lite)
- extension search.ts: param queries + rerank_score/composite in output
- D: scripts/consolidate.py — dedup periodico a coppie via cross-encoder
  con report ntfy e --apply via gateway
- test: 69 pass (+11 strategie); guardrail_version similarity-v2
2026-09-08 12:57:33 +02:00
enne2 fcd6b1670e feat(gateway): catena di fallback per gli embedding + retry transiente su Qdrant
- embed.py: EMBED_CHAIN (JSON per-nodo {name,url,api,key,timeout_ms}, api
  llamacpp|ollama), cooldown 60s sui nodi falliti, validazione dimensione
  EMBED_DIM, compatibilità legacy quando la catena è vuota
- state.py: ResilientQdrant — proxy che ritenta i metodi del client Qdrant
  su httpx.TransportError (store/search/transienti), errori applicativi
  esenti; contatore qdrant_retries in metriche
- metrics: qmem_embed_calls_total + durata per backend
- /v1/version espone embed_nodes; versione 2.10.0
- test: 11 nuovi (chain, cooldown, dim mismatch, legacy, retry transiente) — 58 pass
2026-09-08 12:19:16 +02:00
enne2 78a93ee771 fix(gateway): troncamento documenti rerank (RERANK_MAX_DOC_CHARS=800) — evita 500 batch-size e costi oltre il ctx 2026-09-08 12:12:38 +02:00
enne2 20766de540 feat(gateway): stadio rerank con catena di fallback resiliente (frigate→brain)
- 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
2026-09-08 12:10:27 +02:00
Matteo Benedetto 4776b4b496 refactor: split gateway and pi-qmem extension into modules
- gateway: separate config, models, state, audit, guardrail, embeddings,
  store, metrics, cleanup and routes; keep main.py as FastAPI bootstrap
- extension: split client/config, six tools, config command and rules;
  preserve jiti entrypoint and registrations
- Dockerfile copies the complete gateway module set
- tests: update monkeypatch boundaries for modular config/state
2026-08-24 16:19:19 +02:00
Matteo Benedetto e68fca3388 feat(reparenting): supersede di un record ri-parenta automaticamente i figli attivi
- 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).
2026-08-24 15:43:33 +02:00
Matteo Benedetto 369a2c2d9e feat(hierarchy): supporto metadati strutturati e gerarchici su Qdrant (parent_id, level, topic, links) 2026-08-23 13:07:16 +02:00
Matteo Benedetto b7809fc92d feat(version): endpoint /v1/version + git_commit nel build Docker
- GET /v1/version (pubblico): espone version, git_commit, guardrail_version,
  guardrail_enabled, soglie, embedding_model
- /v1/status include version, git_commit, guardrail_version
- Dockerfile: ARG GIT_COMMIT / ENV GIT_COMMIT (default unknown)
- GATEWAY_VERSION 2.7.0, GIT_COMMIT da env
- Test: 2 nuovi (version endpoint, status git_commit) — 30/30 passano
2026-08-18 16:19:36 +02:00
Matteo Benedetto eccb2cb870 feat(guardrail): similarità pre-scrittura su POST /v1/memories
Guardrail deterministico FUORI dall'LLM (stessa architettura di egeos-copilot):
- Strato 1: text_hash SHA-256 normalizzato -> BLOCK 409 (EXACT_DUPLICATE)
- Strato 2: similarità semantica top-3 BGE-M3 cosine -> BLOCK/WARN/ALLOW
  (soglie configurabili: GUARDRAIL_BLOCK_THRESHOLD 0.85, WARN 0.70)
- Supersede esplicito bypassa il guardrail (correzione intenzionale)
- text_hash e flag guardrail nel payload; audit create_blocked
- Indice payload su text_hash
- Test: 6 nuovi (duplicato esatto, similarità alta/moderata, nessun candidato,
  supersede bypass, disabilitato, text_hash) — 28/28 passano
2026-08-18 12:58:28 +02:00
Matteo Benedetto 70f3699396 test: suite pytest per il gateway (21 test) + script di verifica pre-push
- conftest: FakeQdrant in-memory + mock embed (nessuna dipendenza da Qdrant/Ollama)
- test: validazione (project_id, kind, expires_at, confidence, lunghezza), auth (422/401/429), idempotency (replay/409/key diverse), supersede (404/409/lineage), filtri search, meta, status, metrics
- scripts/check.sh: esbuild (estensione) + pytest (gateway)
- requirements-dev.txt: pytest
2026-08-16 19:53:45 +02:00