---
name: support-bug-investigate
description: "Investigate a Pysae bug by reading source code locally (cloned repos) and produce a concise root-cause report (30-40 lines max). Use when the user says /support-bug-investigate, 'enquête sur ce bug', 'analyse ce ticket', receives a Pysae bug report from Intercom/Airtable, or when a client reports a problem with Plan de Transport, GTFS, driver UI, passenger display, or any Pysae product."
argument-hint: "[Intercom URL, Airtable record ID, GitLab issue URL, group_id, or a short description of the bug]"
allowed-tools:
  - Read
  - Glob
  - Grep
  - Bash
---

Enquête sur un bug Pysae en lisant le code source **en local** (pas via MCP API), jusqu'à identifier la cause racine exacte. Livre un rapport **concis et actionnable** (30-40 lignes max) que les devs peuvent directement exploiter.

## Required tools

- `glab`
- `mongo-tools`
- `atlas`

Run `pysae-ai-tools tools require <tools>` before starting; if it exits non-zero, abort and report the install command from stderr to the user.

## Principe directeur — cause racine, toujours

**Ne jamais s'arrêter à une analyse de surface.** L'enquête n'est pas terminée tant que tu n'as pas identifié :

- Le **fichier et la ligne exacts** où l'erreur survient
- Le **chemin d'exécution** complet (endpoint → service → repository → modèle → point de crash)
- Le **pourquoi** (changement de modèle, gap de migration, champ manquant, mauvaise query, etc.)
- Un **correctif concret** (commande MongoDB, patch de code, changement de config)

Lis autant de fichiers que nécessaire — pas de limite. Suis les imports, trace les appels de fonctions, lis les définitions de modèles. **Ne devine pas ; lis le code.**

## Workflow

### 1. Identifier le domaine et les repos à cloner

Depuis la description du bug, identifie :
- Le ou les repos probablement concernés — voir [../references/pysae-projects.md](../references/pysae-projects.md)
- Le vocabulaire métier → technique — voir [../references/support-vocabulary.md](../references/support-vocabulary.md)

**Principaux repos de bugs client** :
- `pysae/api` — backend FastAPI + MongoDB (la majorité des bugs)
- `pysae/pysae-common` — lib partagée (types, mongo, auth)
- `pysae/gtfs-validator` — wrapper Docker autour de `etalab/transport-validator` (Rust)
- `pysae/op`, `pysae/driver`, `pysae/editor`, `pysae/info`, `pysae/screen` — frontends
- `pysae/nav-data-processor-api` — API traitement données navigation

### 2. Cloner (ou mettre à jour) les repos localement

Pour chaque repo à inspecter :

```bash
pysae-ai-tools code ensure-repo pysae/api
pysae-ai-tools code ensure-repo pysae/pysae-common
```

La commande clone sous `${PYSAE_AI_TOOLS_GIT_CLONE_DIR:-~/projects}/<path>` si absent, `git pull --ff-only` sinon. Elle imprime un JSON avec `local_path` — utilise-le pour tous les `Read`/`Grep`/`Glob` suivants.

**Toujours `git pull` avant lecture** — c'est le comportement par défaut de `ensure-repo` (ne pas passer `--no-pull`). Sinon tu analyses une copie périmée.

### 3. Chercher des changements récents liés

Avant de plonger dans le code, vérifie l'historique :

```bash
# commits récents qui matchent le symptôme
git -C <local_path> log --oneline --since="30 days ago" --grep="<motclé>"

# MRs récentes via glab
glab mr list --repo pysae/api --search "<motclé>" --all
```

### 4. Lire le code source — chemin d'exécution complet

Avec `Read`, `Grep`, `Glob` sur les copies locales :

1. **Point d'entrée** — router/endpoint qui reçoit la requête qui plante
2. **Service** — la couche métier appelée
3. **Repository** — l'accès MongoDB
4. **Modèle** — la définition Pydantic / type
5. **Point de crash** — la ligne exacte qui lève l'exception ou produit le mauvais résultat

Exemple d'investigation sur l'API :

```bash
# Trouver l'endpoint
grep -rn "path_suffix_qui_plante" "$API/pysae/api/" --include="*.py"

# Suivre la route → service → repo → model
# (Read + Grep par nom de fonction/classe)
```

### 4b. Si le bug sent le timeout / la lenteur Mongo

Quand le rapport mentionne timeout, requête qui n'aboutit pas, page qui rame côté DB, ou erreur intermittente sous charge, vérifie côté Atlas avant de plonger plus loin :

```bash
# Slow ops récents (utilise le host du primary, cf. `atlas -P pysae-prod processes list`)
atlas -P pysae-prod performanceAdvisor slowQueryLogs list --processName <host:port> --output json

# Index manquants détectés par Atlas Performance Advisor
atlas -P pysae-prod performanceAdvisor suggestedIndexes list --output json
```

Si le slow op matche la collection/forme de requête du bug, la cause racine est probablement un index manquant ou une query mal indexée — confirme avec `mcp__mongodb-prod__explain` sur la même requête avant de conclure.

### 5. Formuler la cause racine

**Une seule** cause racine proven, pas une liste d'hypothèses. Appuie chaque affirmation sur une ligne de code précise (fichier + numéro de ligne).

### 6. Fournir un correctif concret

Au minimum un des éléments :
- **Commande MongoDB** pour réparer l'état en base
- **Patch de code** (diff ou snippet) à appliquer
- **Changement de config** (env var, feature flag)
- **MR de correction** si un fix simple (1-5 fichiers) est évident → proposer l'enchaînement avec `support-mr-fix`

## Format de sortie (obligatoire)

Toujours ce format, **30-40 lignes utiles max** :

```markdown
### Résumé du bug
[1-3 lignes : qu'est-ce qui est cassé, pour qui, depuis quand]

### Cause racine
[3-5 lignes : cause racine exacte avec fichier, ligne et explication technique]

### Chemin d'exécution
1. `<endpoint>` — `path/to/router.py:42`
2. `<service>` — `path/to/service.py:120`
3. `<repo>` — `path/to/repository.py:85`
4. Point de crash — `path/to/model.py:67`

### Quoi faire
- [Action concrète 1 — commande MongoDB ou patch de code]
- [Action concrète 2 — validation ou changement de config]
- [Option MR directe si petit fix : `/support-mr-fix`]
```

**Si tu dépasses 40 lignes, tu violes le format. Coupe sans pitié.** Pas de sections A-G, pas d'explications verbeuses, pas de liste d'hypothèses.

## Priorité — règle non négociable

Les niveaux de priorité sur GitLab doivent **toujours correspondre à la criticité Airtable**. Ne jamais s'auto-assigner une priorité sur GitLab. Le ticket Airtable est la source de vérité pour la criticité (voir [../references/support-vocabulary.md](../references/support-vocabulary.md#criticité-airtable--label-priority-gitlab)).

## Erreurs fréquentes

- **S'arrêter en surface** — « l'API retourne 500 » n'est **pas** une cause racine. Lis le code jusqu'à la ligne exacte.
- **Trop verbeux** — les devs ignorent les rapports > 40 lignes. Coupe.
- **Oublier `git pull`** — tu analyses une copie périmée. `ensure-repo` le fait par défaut, ne passe jamais `--no-pull`.
- **Confusion métier/technique** — toujours traduire via `support-vocabulary.md`.
- **Rater la chaîne de validation GTFS** — beaucoup de bugs PAN tracent vers etalab. Voir la section « Chaîne de validation GTFS » dans `support-vocabulary.md`.
- **S'auto-attribuer une priorité** — la priorité vient d'Airtable, toujours.

## Enchaînement avec les autres skills

Après l'enquête, les étapes suivantes habituelles :

1. `/support-ticket-create` — créer le ticket Airtable (injecte cette analyse dans Notes)
2. `/glab-issue-create --from-airtable <recID>` — créer l'issue GitLab depuis le ticket Airtable (pratiques du projet : templates GitLab, labels `priority::*`, `type::*`, board column, `/label ~augmented`)
3. `/support-mr-fix` — **uniquement** si la cause racine est simple, précise, 1-5 fichiers, pas de migration DB, pas de changement d'API publique — et si Patrick le valide explicitement

$ARGUMENTS
