debugging-difficult-bugs — instrumenter, reproduire, lire, puis corriger
Idée centrale : quand tu ne vois pas la défaillance en lisant le code, fais parler le runtime. Ajoute du logging JSONL temporaire append-only le long du vrai chemin de code, reproduis le vrai problème une fois, lis le log chronologiquement, et seulement alors corrige. Ne fais jamais une deuxième correction spéculative sans nouvelle preuve du runtime.
Annonce au démarrage : « Utilisation de la skill debugging-difficult-bugs — instrumentation du chemin d'exécution pour observer la défaillance. »
Étape 1 : Énonce l'incertitude
Écris : ce que tu crois, ce que tu ne peux pas vérifier statiquement, et le chemin d'exécution exact qui doit être observé (route → service → query, edge function, job).
Étape 2 : Ajoute l'instrumentation temporaire inconditionnelle
Règles :
- Inconditionnelle — jamais derrière une variable d'env, flag de débogage, ou log level. Si la reproduction nécessite de se souvenir de définir un flag, elle ne s'activera silencieusement pas.
- JSONL append-only, un objet JSON par ligne, dans un fichier du répertoire de travail du processus.
- Log les frontières et décisions, pas chaque ligne : entrée/sortie de fonction, décisions de branchement avec les données qui les ont causées, état avant/après mutation, marqueurs d'ordre async, erreurs attrapées, formes de valeurs retournées.
- Log les formes, pas les payloads : ids, clés, compteurs, statuts. Ne log jamais de tokens, en-têtes d'auth, cookies, ou contenu utilisateur complet.
import { appendFileSync } from "node:fs";
import { join } from "node:path";
function debugBug(event: string, data: Record<string, unknown> = {}) {
appendFileSync(
join(process.cwd(), "debug-difficult-bug.jsonl"),
`${JSON.stringify({ ts: new Date().toISOString(), event, ...data })}\n`
);
}
debugBug("service.beforeUpdate", { id, companyId, status: row.status });
Note multi-processus Carbon. Les serveurs dev ERP/MES, les edge functions (conteneur Docker edge-runtime), et les handlers Inngest s'exécutent comme des processus séparés avec des répertoires de travail différents. Log process.cwd() + un rôle de processus une fois au démarrage, ou utilise des noms de fichiers distincts (debug-erp.jsonl, debug-edge.jsonl). Pour les edge functions, console.error les lignes JSON (visibles dans les logs du conteneur) peut suffire quand le filesystem du conteneur est difficile d'accès.
Étape 3 : Reproduis le vrai problème une fois
- Privilégie te reproduire toi-même : démarre la stack (
crbn upsi pas déjà en cours), authentifie-toi avec/auth, et pilote le flux défaillant exact avecagent-browser(la skill/testdocumente les pièges de formulaires Carbon —requestSubmit, react-aria blur). - Si seul l'utilisateur peut reproduire (ses données, son environnement), dis-lui exactement : « J'ai ajouté du logging temporaire. Reproduis le problème une fois, puis pointe-moi sur
<cwd>/debug-difficult-bug.jsonl. »
Étape 4 : Lis le log AVANT de corriger
Lis chronologiquement et réponds par écrit :
- Le chemin instrumenté a-t-il vraiment exécuté ?
- Quelle était la séquence d'événements attendue ?
- Quelle a été la séquence réelle ?
- Quel est le premier point où l'état/ordre/branchement diverge de l'attente ?
Cette première divergence est le candidat cause racine. Réinjecte-le dans le brief cause-racine (ou écris-le maintenant) — puis implémente via /fix, dont le test de régression défaillant doit affirmer la vraie divergence que tu as observée, pas ton hypothèse antérieure.
Étape 5 : Nettoie — obligatoire
- Supprime chaque appel de log temporaire, helper, et import.
- Supprime les fichiers
.jsonlgénérés. - Vérifie explicitement le diff final pour les restes :
git diff | grep -n "debugBug\|debug-difficult\|\.jsonl"→ aucun hit attendu.
Le diff final contient seulement la correction et ses tests.
Terminé quand
- [ ] Le premier point de divergence est identifié par preuve du log (cite les lignes)
- [ ] La correction est déployée via
/fixavec un test de régression rouge→vert affirm ant ce comportement - [ ] La reproduction du flux original passe maintenant
- [ ] Zéro remnant d'instrumentation dans le diff