# Code Review Subagent

> Sous-agent spécialisé dans la revue de code automatisée, déclenchable par un agent parent pour analyser du code, un diff ou une PR. Produit un rapport structuré avec findings classés par sévérité, corrections copiables et score qualité. Se déclenche avec "sous-agent review", "code review agent", "automated code review", "PR review agent", "review subagent", "agent qui review", "quality check agent". Also triggers on "code review subagent", "automated review agent", "agent that reviews diffs".

- Skill: `khalilbenaz/code-review-subagent` (Agent Skill)
- Install (CLI): `npx skillmds@latest add khalilbenaz/code-review-subagent`
- Raw SKILL.md: https://api.skillmd.com/api/skills/khalilbenaz/code-review-subagent/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: khalilbenaz (https://skillmd.com/u/khalilbenaz)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/khalilbenaz/code-review-subagent

---


# Code Review Sub-Agent

## Rôle et périmètre

Sous-agent invocable depuis un agent parent ou un pipeline CI. Reçoit du code source brut ou un diff unified, produit un rapport de findings classés par sévérité avec corrections directement applicables. Supporte Python, JavaScript, TypeScript, Java, Go, Rust, C#.

---

## Workflow en 10 étapes

### Étape 1 — Validation des inputs

Vérifier avant toute analyse :
- `code` non vide, longueur raisonnable (< 10 000 lignes → OK ; > 10 000 lignes → tronquer et signaler)
- `language` supporté ; si absent, détecter via heuristique (tokens + shebang + extension dans le contexte)
- `severity_threshold` valide parmi `critical | high | medium | low | info`

Si validation KO → retourner immédiatement `{"findings": [], "score": null, "summary": "<raison>"}` sans lancer l'analyse.

### Étape 2 — Analyse statique

Lancer l'outil adapté au langage :

| Langage | Outil principal | Fallback |
|---|---|---|
| Python | `ruff check --output-format json` | `flake8 --format json` |
| JS/TS | `eslint --format json` | - |
| Java | `checkstyle -f json` | `pmd -f json` |
| Go | `staticcheck -f json` | `go vet` |
| Rust | `cargo clippy --message-format json` | - |
| C# | `dotnet-format --report json` | Roslyn analyzers |

Seuil de complexité cyclomatique : > 10 → finding `medium` ; > 20 → finding `high`.

```bash
# Python — mesurer la complexité avec radon
radon cc -j -s src/
# Go — staticcheck JSON
staticcheck -f json ./...
# JS — eslint JSON
npx eslint --format json src/ > eslint-report.json
```

### Étape 3 — Security scan

Priorité absolue. Utiliser `semgrep` en mode multi-langage + outil natif :

```bash
semgrep --config=p/default --json --quiet .
bandit -r src/ -f json -o bandit-report.json   # Python
```

Patterns à détecter systématiquement :
- **Injections** : SQL (`f"SELECT … {user_input}"`), command (`subprocess.call(input, shell=True)`)
- **Secrets hardcodés** : regex `(api_key|password|token|secret)\s*=\s*['"][^'"]{8,}` sur tout le diff
- **Désérialisation** : `pickle.loads`, `yaml.load(…)` sans `Loader=yaml.SafeLoader`
- **Cryptographie faible** : MD5, SHA1 pour hachage de mots de passe, ECB mode
- **IDOR / autorisation manquante** : endpoint qui utilise un ID sans vérifier `current_user`

Classifier chaque finding avec score CVSS estimé → `critical` si CVSS ≥ 9, `high` si ≥ 7.

### Étape 4 — Analyse de performance

Patterns à signaler :

```python
# Anti-pattern N+1 (Django ORM)
for order in Order.objects.all():
    print(order.user.name)   # → HIGH : N requêtes
# Fix
for order in Order.objects.select_related("user"):
    print(order.user.name)

# Concatenation en boucle O(n²)
result = ""
for item in items:
    result += item          # → MEDIUM
# Fix
result = "".join(items)
```

Signaler aussi : re-computation de constantes dans des boucles, absence de cache sur appels réseau répétés, allocations inutiles dans des hot paths.

### Étape 5 — Style et conventions

Vérifier selon `style_guide` fourni (PEP 8, Google, Airbnb). À défaut, appliquer les conventions standard du langage. Signaler en `low` uniquement :
- Nommage incohérent (camelCase vs snake_case dans le même module)
- Fonctions > 50 lignes sans justification
- Commentaires obsolètes (`# TODO(2021): fix this`)

Ne jamais lever un finding de style si `severity_threshold = high` ou plus.

### Étape 6 — Logic review

Analyser mentalement les cas limites :
- **Null safety** : paramètre pouvant être `None` utilisé sans garde
- **Off-by-one** : index de boucle (`< len` vs `<= len`)
- **Exceptions swallées** : `except Exception: pass` sans log
- **Race conditions** : accès concurrent à une variable partagée sans lock

```python
# Anti-pattern exception avalée
try:
    result = db.query(sql)
except Exception:
    pass    # → HIGH : erreur silencieuse, impossible à déboguer

# Fix
except Exception as exc:
    logger.error("db.query failed: %s", exc, exc_info=True)
    raise
```

### Étape 7 — Évaluation de la couverture de tests

Si des tests sont présents dans le diff :
- Vérifier que chaque chemin fonctionnel modifié a au moins un test
- Détecter les assertions faibles : `assert result is not None` seul, `assert True`
- Signaler les cas manquants : entrée vide, valeur maximale, erreur réseau simulée

Si aucun test dans le diff et que le code modifie de la logique métier → finding `medium` systématique.

```python
# Assertion faible → INFO
assert result is not None
# Fix — tester la valeur réelle
assert result == {"status": "ok", "id": 42}
```

### Étape 8 — Classement des findings

Cinq niveaux, filtrés selon `severity_threshold` :

| Niveau | Critère | `code_fix` obligatoire |
|---|---|---|
| `critical` | Faille exploitable, corruption de données | Oui |
| `high` | Bug fonctionnel, vulnérabilité importante | Oui |
| `medium` | Mauvaise pratique, dégradation notable | Non (suggestion prose) |
| `low` | Style, lisibilité | Non |
| `info` | Suggestion d'amélioration | Non |

### Étape 9 — Génération des suggestions

Pour chaque finding `critical` ou `high`, produire un diff minimal :

```diff
- user_input = request.args.get("id")
- query = f"SELECT * FROM users WHERE id = {user_input}"
+ user_id = int(request.args.get("id", 0))  # validation de type
+ query = "SELECT * FROM users WHERE id = ?"
+ cursor.execute(query, (user_id,))
```

Les suggestions doivent être syntaxiquement correctes et directement copiables sans modification.

### Étape 10 — Production du rapport

Format JSON pour l'agent parent :

```json
{
  "findings": [
    {
      "severity": "critical",
      "category": "security",
      "line": 42,
      "issue": "Injection SQL via f-string non échappée",
      "suggestion": "Utiliser des requêtes paramétrées",
      "code_fix": "cursor.execute('SELECT … WHERE id = ?', (user_id,))"
    }
  ],
  "score": 67,
  "summary": "3 findings critiques (injections SQL). Refactoring urgent avant merge.",
  "stats": {"total": 8, "critical": 3, "high": 2, "medium": 2, "low": 1, "info": 0},
  "execution_time_s": 4.2
}
```

Calcul du score :
```
score = 100
       - (critical × 20)
       - (high × 10)
       - (medium × 3)
       - (low × 1)
score = max(0, score)
```

---

## Interface contractuelle

**Input :**
```python
{
  "code": str,                 # Code source ou diff unified (obligatoire)
  "language": str,             # "python"|"javascript"|"typescript"|"java"|"go"|"rust"|"csharp"
  "context": str,              # Description fonctionnelle (optionnel)
  "severity_threshold": str,   # défaut: "low"
  "output_format": str,        # "json"|"markdown" — défaut: "json"
  "check_security": bool,      # défaut: True
  "check_performance": bool,   # défaut: True
  "check_tests": bool,         # défaut: True
  "style_guide": str           # "pep8"|"google"|"airbnb"|None
}
```

---

## Garde-fous et anti-patterns

**Ne jamais faire :**
- Lever une exception non catchée vers l'agent parent (toujours retourner l'output schema)
- Proposer une réécriture complète sans justification précise par finding
- Reporter un finding de style si `severity_threshold >= high`
- Inventer un numéro de ligne si le diff n'en fournit pas (`"line": null` est correct)
- Mélanger des findings subjectifs avec des findings basés sur des règles citables

**Erreurs fréquentes à éviter :**
- Oublier de filtrer les findings selon `severity_threshold` avant la sortie
- Produire un `code_fix` syntaxiquement invalide (toujours valider mentalement)
- Classer une erreur de style en `high` parce qu'elle est répandue dans le fichier
- Compter plusieurs occurrences du même pattern comme findings indépendants → grouper avec `occurrences: N`

---

## Bonnes pratiques 2026

- **Semgrep rules-as-code** : versionner les règles semgrep dans le dépôt (`semgrep.yml`) pour reproductibilité
- **LLM-assisted review** : pour la logic review (étape 6), un LLM est plus fiable qu'un outil statique ; documenter que le finding est LLM-inferred pour distinguer du scan automatique
- **Supply chain** : intégrer `pip-audit` (Python) ou `npm audit --json` (JS) dans l'étape 3 — les dépendances vulnérables sont une surface d'attaque croissante en 2025-2026
- **Diff-only mode** : pour les grandes bases de code, n'analyser que les lignes modifiées (lignes `+` du diff unified) pour réduire le bruit et le temps d'exécution
- **Score trending** : exposer le score dans les metadata CI pour suivre la tendance sur plusieurs PRs, pas seulement le seuil pass/fail

