# RAG Quality Guard

> Gate de qualité pour le RAG jarvis-rag-local. Audite toute note ou batch de notes avant ingestion pour éviter la pollution du graph (zombies, duplicats, contradictions, bruit). Produit un verdict APPROVE / WARN / REJECT avec diff des entités/relations qui seraient créées. Utilise ce skill dès que l'utilisateur veut ingérer dans le RAG, auditer un dossier de notes avant ingestion, vérifier la qualité d'un ajout récent, ou quand un autre skill (curateur RAG, workflow sessions→RAG, agent veille Telegram) a besoin de valider du contenu. Déclenche aussi sur : 'audite avant ingestion', 'check qualité RAG', 'cette note est-elle prête pour le RAG', 'garbage-in-out', 'quality-guard', 'batch pré-ingestion', 'ingestion zombie', 'ingestion duplicat'. NE PAS utiliser pour : indexation simple, lecture du RAG, query Hermès.

- Skill: `lucasleduc/rag-quality-guard` (Agent Skill, multi-file: 42 files)
- Install (CLI): `npx skillmds@latest add lucasleduc/rag-quality-guard`
- Raw SKILL.md: https://api.skillmd.com/api/skills/lucasleduc/rag-quality-guard/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: LucasLeduc (https://skillmd.com/u/lucasleduc)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/lucasleduc/rag-quality-guard

---


# rag-quality-guard — Gate de qualité pré-ingestion

Tu es le garde-fou du RAG `jarvis-rag-local` (LightRAG, vault Obsidian de l'utilisateur). Ton job : empêcher la pollution du knowledge graph en auditant toute note ou batch avant ingestion.

## Principe

> **Garbage in → garbage out.** Une seule note pourrie ingérée = des heures à diagnostiquer pourquoi le RAG hallucine.

Ce skill est **read-only strict** sur le storage LightRAG. Il ne modifie jamais rien — il observe, analyse, verdict.

## Quand déclencher

### Déclencher
- Avant toute ingestion manuelle ou batch dans `jarvis-rag-local`
- Audit post-ingestion d'un batch récent
- Appel par un autre skill (curateur-rag-daily, workflow sessions→RAG, agent-veille-telegram)
- Décision "ce dossier est-il prêt pour ingestion ?"

### Ne pas déclencher
- Pour requêter le RAG (utiliser `mcp__jarvis-rag-local__rag_query`)
- Pour ingérer (utiliser le pipeline `scripts/ingest.py` du repo)
- Pour la veille vidéo IA (exclue du RAG par règle CLAUDE.md)

## Architecture des 7 checks

Le skill exécute 7 checks dans l'ordre. Chaque check produit un verdict partiel : `PASS` / `WARN` / `REJECT` / `ERROR`.

| # | Check | Verdict bloquant ? |
|---|-------|---|
| 1 | Frontmatter YAML | ✅ REJECT bloque tout (fail fast) |
| 2 | Densité & structure | ❌ WARN seulement |
| 3 | Dry-run extraction (Claude Haiku) | ❌ WARN seulement |
| 4 | Similarité excessive (duplicat) | ✅ REJECT si > 0.95 |
| 5 | Cohérence entités (zombies) | ✅ REJECT si zombie détecté |
| 6 | Signal-to-noise | ❌ WARN seulement |
| 7 | Contradictions avec graph existant | ✅ REJECT si critique |

→ Détail complet : `reference/checks-detail.md`
→ Tous les seuils : `reference/thresholds.md` + runtime dans `data/thresholds.json`

## Système de verdict final

- ≥1 REJECT sur checks 1, 4, 5, 7 → **REJECT global** (ne pas ingérer)
- 0 REJECT + ≥3 WARN → **WARN global** (ingestion possible mais risquée)
- 0 REJECT + ≤2 WARN → **APPROVE** (feu vert)

**Exception fail-fast** : Check 1 en REJECT → on ne lance même pas les autres checks.
**Exception ERROR** : si ≥1 check en ERROR (timeout, API down) → verdict global "AUDIT PARTIEL — décision humaine requise".

## Modes d'invocation

### Mode 1 — Note unique (le plus courant)
```bash
python scripts/audit_note.py <chemin-vers-note.md>
```

### Mode 2 — Batch de notes
```bash
python scripts/audit_batch.py <dossier>
```

### Mode 3 — Pipeline silencieux (JSON pour autres skills)
```bash
python scripts/audit_note.py <chemin> --json --silent
```

Exit codes (CLI) :
- `0` = APPROVE
- `1` = WARN
- `2` = REJECT
- `3` = ERROR (audit a échoué, ne pas se baser sur le verdict)

### Mode 4 — Invocation Claude (conversationnel)
```
"Audite la note 03-VEILLE/rag/benchmark-reranker-2026.md avant ingestion"
"Check qualité du dossier 00-INBOX/sessions-curated/2026-04-22/"
```

## Output

Un rapport markdown structuré (template : `reference/report-template.md`).

Pour les batchs, un récap tableau + un sous-rapport par note auditée. Recommandation priorisée à la fin : "ingérer A, B, D ; corriger C, E ; rejeter F, G, H".

Tous les rapports sont aussi loggés en JSONL dans `data/logs/audit-YYYY-MM-DD.jsonl` pour traçabilité.

## Règles non-négociables (sécurité)

1. **Read-only sur le storage LightRAG.** Zéro exception. Tout accès passe par `lib/storage_reader.py` qui n'expose que des méthodes lecture et lève `RuntimeError` à toute tentative de mutation.
2. **Logs structurés obligatoires.** Chaque audit produit une entrée JSONL avec : timestamp, fichier, checks détail, verdict, durée, erreurs éventuelles.
3. **Fail explicite.** Si un check plante (timeout LLM, API down, fichier corrompu) → log ERROR + verdict `ERROR` sur ce check, on continue les autres, et le rapport indique "AUDIT PARTIEL".
4. **`known-zombies.json` versionnée.** Toute modification = commit Git avec justification dans le message.
5. **Pas de modification du fichier audité.** Lecture seule sur la note source.
6. **Pas de side-effect réseau autre que** : LLM extraction (Check 3) + MCP rag_query (Check 7) + Ollama embedding local (Check 4). Pas de webhook, pas de notif Slack/Telegram automatique (l'orchestrateur appelant décide).
7. **Validation des inputs.** Tout chemin reçu est vérifié : existe, est un fichier `.md`, taille < 5 MB. Refus explicite sinon.
8. **Pas de secrets en clair.** API keys lues depuis l'environnement (`ANTHROPIC_API_KEY`). Aucun secret dans le code ou les logs.

## Stack technique

- Python 3.10+
- `python-frontmatter` (parsing YAML)
- `numpy` (cosinus similarity)
- `anthropic` SDK (Claude Haiku pour extraction Check 3)
- `requests` (appel local nomic-embed-text via Ollama pour Check 4)
- `mcp__jarvis-rag-local__rag_query` (pour Check 7, optionnel)
- pytest (tests)

→ Liste complète : `scripts/requirements.txt`

## Tuning et maintenance

Tous les seuils sont dans `reference/thresholds.md` (doc) ET `data/thresholds.json` (source de vérité runtime). Modifier le JSON et committer.

La liste des zombies vit dans `data/known-zombies.json`. Format :
```json
{
  "Noah Carter": {
    "added": "2026-04-22",
    "reason": "Entité hallucinée pendant ingestion Phase B 21/04 (exemple SEO du dossier positionnement-2026)",
    "added_by": "owner",
    "context": "ingestion-20260421.log"
  }
}
```

## Quand un autre skill m'appelle

Si tu es un autre skill qui veut valider du contenu avant ingestion, utilise le mode silent :

```python
import subprocess, json
result = subprocess.run(
    ["python", "scripts/audit_note.py", note_path, "--json", "--silent"],
    capture_output=True, text=True
)
verdict = json.loads(result.stdout)
exit_code = result.returncode  # 0/1/2/3

if exit_code == 0:  # APPROVE
    proceed_with_ingestion()
elif exit_code == 1:  # WARN
    notify_human_for_review(verdict)
elif exit_code == 2:  # REJECT
    quarantine(note_path, verdict)
else:  # ERROR
    fallback_safe(note_path, verdict)
```

## Anti-patterns à éviter

| Anti-pattern | Pourquoi |
|---|---|
| Bloquer sur WARN | WARN = info, pas blocker. L'humain décide. |
| Hardcoder des seuils dans le code | Tout dans `data/thresholds.json` pour tuning sans redéploiement |
| Marquer une nouvelle entité comme zombie auto | Seule la liste `known-zombies.json` (validée humainement) bloque |
| Lancer extraction LightRAG complète | Coûteux. Utiliser Claude Haiku en standalone (Check 3) |
| Ne pas logger | Sans logs, impossible de tuner les seuils ou de déboguer un faux positif |
| Ignorer les erreurs partielles | Un check qui plante = log + ERROR + on continue, jamais "fail silencieux" |

## Tests d'acceptation

9 tests pytest dans `scripts/tests/`. Couvrent les cas du brief section 10 :
PASS clean, REJECT frontmatter, REJECT duplicat, REJECT zombie, WARN densité, WARN extraction, batch mixte, read-only, performance.

Lancer :
```bash
cd scripts && python -m pytest tests/ -v
```

## Owner et évolution

- Companion repo: https://github.com/LucasLeduc/jarvis-rag-local

