Triage des faux positifs Sentry CLI
Périmètre
- Org Sentry :
buildwithfern - Projet Sentry :
cli - Utiliser le Sentry CLI intégré au repo :
pnpm exec sentry-cli. - Requête par défaut : non résolu uniquement, sauf si la tâche demande explicitement de revérifier les problèmes résolus.
Fichiers requis
Lisez-les avant de proposer des changements de code :
.devin/automation/sentry-triage/DESIGN_CHOICES.md— principes généraux, pas des solutions pré-écrites..devin/automation/sentry-triage/ledger/— un fichier JSON parshortId(ex.ledger/CLI-2W.json) ; plusledger/_meta.jsonpour les constantes au niveau du repo. Lisez uniquement les lignes dont vous avez besoin..devin/automation/sentry-triage/SUBAGENT_CONTRACT.md— transmis à chaque sous-agent lancé.
Le ledger contient un fichier par shortId. Les branches parallèles de sous-agents touchent des fichiers disjoints, éliminant ainsi les conflits de fusion par construction. Ne chargez ou ne réécrivez le répertoire complet que si une tâche demande explicitement une maintenance large des enregistrements.
Vue d'ensemble du workflow
- Parent — récupère Sentry, filtre-ledger (recherche bon marché), déduplique les PR existantes (script), groupe par site d'appel (hypothèse à partir des stacks Sentry), écrit les Plans de groupe, lance les sous-agents.
- Lancer — strict 1:1 : un sous-agent parallèle par groupe éligible. N groupes → N sous-agents parallèles, jamais un sous-agent chargé de plusieurs groupes et jamais séquentiellement. Voir Orchestration des sous-agents.
- Réconcilier — collecte les résultats des sous-agents, vérifie le ledger, résume, ouvre optionnellement une PR de réconciliation parent. Voir Réconciliation du parent.
L'autorité de classification vit dans le sous-agent, pas dans le parent. Le parent prend des décisions bon marché et structurelles (filtre ledger, déduplique, hypothèse de regroupement). Le sous-agent a le code devant lui et possède l'appel de disposition réel — y compris keep_sentry, ignored, pending_review, et « le regroupement du parent était faux ». Le Plan de groupe du parent est une hypothèse de travail, pas une classification contraignante.
Récupérer
pnpm exec sentry-cli issues list \
--org buildwithfern \
--project cli \
--status unresolved
pnpm exec sentry-cli issues list \
--org buildwithfern \
--project cli \
--id <ISSUE_ID>
Si le CLI intégré ne peut pas afficher assez de détails pour un shortId, utilisez l'API Sentry via pnpm exec sentry-cli ou une commande Sentry approuvée par le projet authentifié. Gardez les payloads petits.
Filtre du ledger
- Collectez les
shortIds actuels de Sentry. - Interrogez uniquement ces lignes :
for id in CLI-2W CLI-2V; do
path=".devin/automation/sentry-triage/ledger/$id.json"
if [[ -f "$path" ]]; then
jq --arg shortId "$id" '{shortId: $shortId, disposition, duplicateOf, problemSignature, prOrIssue}' "$path"
else
jq -n --arg shortId "$id" '{shortId: $shortId, status: "unknown"}'
fi
done
- Ignorez les fichiers
shortIdexacts avec disposition terminale :shipped,ignored,duplicate, oukeep_sentry. - Retraitez
pending_review. - Un texte
problemSignaturesimilaire n'est qu'un indice. Ne traitez jamais un problème passé similaire comme preuve que leshortIdactuel est résolu. - Listing de toutes les lignes :
ls .devin/automation/sentry-triage/ledger/CLI-*.json._meta.jsoncontient les constantes au niveau du repo et change rarement.
Procédure de déduplicate des PR existantes
Après le filtre du ledger, exécutez le script de déduplicate pour chaque shortId restant. N'exécutez pas de recherches ad-hoc gh à cet effet.
gh auth status
.devin/automation/sentry-triage/scripts/find-existing-pr.sh CLI-44 CLI-4T
Étapes que le script effectue, par shortId :
- Recherche dans le ledger —
prOrIssueetdispositiondeledger/<SHORT_ID>.json; siprOrIssueest une URL de PR, récupère l'état de la PR (toute branche). - Recherche de branche de triage — un appel
gh pr listpar exécution pour les PRs ouvertes avec le préfixe de branche headfix/cli-sentry-triage/; parshortId, correspond quand le nom de la branche, le titre ou le corps contient l'id (insensible à la casse). - Métadonnées de vérification — pour chaque candidat, récupère
files,title,body,state,headRefName.
La découverte des PR ne recherche pas toutes les PRs ouvertes du repo — uniquement les branches de forme triée (plus les URLs du ledger).
Stdout est un tableau JSON (un objet par shortId avec ledger et candidates). Pour chaque shortId, jugez par rapport à la limite que vous avez identifiée :
none— aucun candidat ne couvre la limite ; éligible pour un sous-agent.covered— le diff/titre/corps d'une PR candidate correspond à la limite et à la correction du groupe ; enregistrez la mise à jourprOrIssuepour la PR de réconciliation parent (ne lancez pas).partial— certainsshortIds couverts, d'autres non ; divisez le groupe et lancez uniquement pour lesshortIds non couverts.
Si le script se termine avec un code non zéro (panne d'auth, limite de débit, réseau), arrêtez l'exécution et demandez à un humain de corriger l'auth gh ou le débit avant de continuer. La limite de triage --limit 100 est peu susceptible d'être dépassée ; si elle l'est, affinez le filtre et réexécutez.
Variables d'environnement : FERN_REPO (par défaut fern-api/fern), LEDGER_DIR (par défaut .devin/automation/sentry-triage/ledger).
Règle de regroupement
Groupez par site d'appel, pas uniquement par titre.
- Un groupe de site d'appel est un ensemble de problèmes Sentry qui échouent à partir de la même fonction, limite ou chemin throw/catch et peuvent être résolus par le même changement de code.
- Le regroupement doit être rare. La plupart des problèmes Sentry sont uniques et doivent devenir leur propre investigation et PR.
- Plusieurs
shortIds peuvent partager une PR uniquement quand la stack prouve que la même fonction ou limite produit la même classification de faux positif. - Ne regroupez pas les problèmes juste parce que les messages se ressemblent, la même dépendance apparaît, ou une ligne de ledger antérieure a un
problemSignaturesimilaire. - Le parent finalise la liste des groupes avant de lancer. Le regroupement en cours de flux n'est pas autorisé. Si un sous-agent réfute un groupe, il s'arrête et retourne les conclusions ; le parent replanifie au prochain run.
Périmètre d'investigation du parent. Le parent lit les stacks Sentry et peut optionnellement grep le codebase pour le frame du haut. N'ouvrez pas les fichiers source — le sous-agent fait la lecture du code source. Le Plan de groupe est construit à partir des données Sentry et du contexte du ledger, rien de plus profond.
Avant de lancer, écrivez un bloc Plan de groupe par groupe. Le plan est l'hypothèse de travail du parent ; le sous-agent la vérifie par rapport au code et peut retourner n'importe quelle disposition.
Group: <site d'appel ou fonction — hypothèse à partir du top frame de stack>
ShortIds: <CLI-XX, CLI-YY>
Evidence:
- frames du haut (>=3, avec file:line si disponible)
- type d'exception et message
- queue des breadcrumbs si pertinent
- nombre d'événements et lastSeen
ExistingPR: <none | URL de PR et pourquoi elle couvre/ne couvre pas ce groupe>
Branch: fix/cli-sentry-triage/<YYYY-MM-DD>-<jusqu'à-3-short-ids-kebab>
Evidence est la seule fenêtre du sous-agent vers Sentry — le sous-agent est interdit de refetch, donc incluez tout ce dont il a besoin pour localiser et vérifier la limite. Collez les données en tant que texte ; pas besoin de JSON structuré.
Le parent ne propose pas une correction ou ne pré-associe pas les principes de DESIGN_CHOICES.md — le sous-agent possède les deux une fois qu'il lit le code. Le parent contribue uniquement ce qu'il peut produire de manière fiable à partir des données Sentry : l'hypothèse de site d'appel, l'ensemble des ShortIds, les données brutes, le résultat de déduplicate, et le nom de la branche. Le sous-agent présente tout nouveau principe digne d'enregistrement via newPrincipleProposal.
Tout groupe sans couverture de ExistingPR et sans ligne de ledger terminale est éligible pour un sous-agent. Le parent ne doit pas pré-classer les groupes comme keep_sentry, ignored, ou pending_review pour éviter de lancer ; ces décisions appartiennent au sous-agent. Les seuls raccourcis du côté parent sont :
- Ignorer quand la ligne du ledger est déjà terminale (
shipped,duplicate,keep_sentry,ignored). - Ignorer quand le script de déduplicate confirme qu'une PR existante couvre complètement le groupe (enregistrez
prOrIssuepour la PR de réconciliation parent).
Tout le reste reçoit un sous-agent.
Orchestration des sous-agents
Un sous-agent par groupe éligible. Strict 1:1, aucune exception.
Pour chaque groupe éligible de Règle de regroupement, le parent lance exactement un sous-agent. Le mappage est :
| 1 Plan de groupe | 1 sous-agent | 1 branche | 1 PR | 1 ensemble disjoint de ShortIds |
- N groupes éligibles → N sous-agents parallèles dans le même batch de lancement. Ne confiez jamais à un sous-agent plusieurs Plans de groupe ; ne lancez jamais séquentiellement pour « voir comment le premier se débrouille ».
- Lancez via la primitive de worker parallèle de l'hôte :
- Devin : Devins gérés (une session séparée par groupe).
- Cursor : outil
Taskavecrun_in_background: true, appelé une fois par groupe dans un seul message. - Autres hôtes : le mécanisme de worker parallèle équivalent.
- Les règles des sous-agents vivent dans
SUBAGENT_CONTRACT.md. Passez uniquement le chemin de ce fichier plus un seul bloc Plan de groupe. Ne collez jamais plusieurs Plans de groupe dans un seul spawn. - Chaque sous-agent travaille sur sa propre branche fraîche off
main. Les branches ne doivent pas être empilées entre groupes. - Chaque sous-agent possède : sa branche, sa correction, sa PR, et les fichiers ledger pour ses
ShortIdsuniquement.
Anti-patterns (ne faites pas ça) :
- Lancer un sous-agent avec une liste de Plans de groupe (« voici 5 groupes, travaillez-les »).
- Lancer les sous-agents séquentiellement entre groupes, même quand le parent se sent incertain sur le parallélisme.
- Laisser un sous-agent ouvrir une deuxième PR parce qu'il a remarqué un autre groupe en lisant le code (c'est une replanification, pas une expansion de périmètre — voir Arrêter et retourner les conclusions).
- Regrouper plusieurs
shortIds de différents sites d'appel dans un groupe « divers » pour lancer moins de sous-agents.
Si le parent est incertain qu'un groupe est bien formé, laissez-le lancé et versez-le dans le prochain run — ignorer est mieux que fusionner des groupes.
Prompt de lancement parent (uniforme pour chaque groupe, un lancement par groupe) :
Lisez .devin/automation/sentry-triage/SUBAGENT_CONTRACT.md et suivez-le.
Group Plan:
<collez le bloc Plan de groupe unique ici>
Règles de sécurité parallèle
- Les noms de branches par groupe sont uniques par le schéma date +
shortId(chaqueshortIdappartient à exactement un groupe). - Les écritures du ledger sont partitionnées par
shortIddans des fichiers séparés (ledger/<SHORT_ID>.json) ; les sous-agents parallèles ne touchent jamais le même fichier. C'est la raison principale de la disposition par fichier. DESIGN_CHOICES.mdest parent-only. Les sous-agents retournentnewPrincipleProposalau lieu de l'éditer.ledger/_meta.jsonest parent-only et rarement édité.- Si deux groupes partagent un chemin de code pendant l'investigation, les deux sous-agents s'arrêtent et retournent les conclusions ; le parent replanifie.
Réconciliation du parent
Après que tous les sous-agents se terminent :
-
Collectez les
prUrlde chaque sous-agent (ouskipped: <reason>),shortIdsTouched,principlesApplied,newPrincipleProposal. -
Vérification des collisions du ledger (la disposition par fichier rend cela trivial) : aucune deux PR de triage ouvertes ne devrait inclure le même fichier
ledger/CLI-XX.json. Vérifiez avecgh pr view <num> --json filespar rapport à chaque PR de triage ouverte. -
Affichez un résumé par groupe : libellé du groupe,
ShortIds, URL de PR ou raison d'ignorance. -
PR de réconciliation parent optionnelle (uniquement quand il y a quelque chose à écrire) :
- Mises à jour du ledger
prOrIssuepour les groupes que le parent a marqués commecoveredpendant la déduplicate. - 1–3 nouvelles puces
DESIGN_CHOICES.mdprésentées vianewPrincipleProposal, après examen humain.
La PR de réconciliation ne contient aucun changement de code, uniquement les mises à jour des pointeurs ledger et/ou les édits de
DESIGN_CHOICES.md. Branche :chore/cli-sentry-triage/<YYYY-MM-DD>-reconcile. - Mises à jour du ledger
Règles des PR
- Une PR par groupe de solution de site d'appel, ouverte par le sous-agent (voir Orchestration des sous-agents).
- Une exécution peut créer plusieurs PRs ; ne créez pas une PR de triage catch-all.
- Avant de créer une branche ou une PR, la Procédure de déduplicate des PR existantes doit avoir été exécutée ; si une PR de triage ouverte adresse déjà le groupe, ne lancez pas un sous-agent en double.
- Si une réexécution trouve les mêmes
ShortIdstoujours non résolus et une PR de triage ouverte existe déjà à la bonne limite, poussez des commits supplémentaires à cette branche au lieu de créer une nouvelle PR (convention host-agent). La plupart des cas n'arrivent jamais ici car les lignes de ledger terminales sont ignorées à l'étape du filtre du ledger. - Branche :
fix/cli-sentry-triage/{date}-<short-ids>(ex.fix/cli-sentry-triage/2026-11-03-cli-44-cli-4t-cli-4v). - Utilisez la date ISO (
YYYY-MM-DD) et au maximum troisshortIds dans le nom de la branche, en minuscules et kebab-case. - Le titre de la PR doit inclure les
shortIds résolus. S'il y en a plus de trois, listez les trois premiers et résumez la famille. - La description de la PR liste chaque
shortIdrésolu et une note de correction courte. - Mettez à jour uniquement les fichiers par
shortIdsous.devin/automation/sentry-triage/ledger/pour ce groupe, dans la même PR que le code. Ne touchez jamais les fichiers d'autres lignes ou_meta.json. - Ajoutez
packages/cli/cli/changes/unreleased/quand le comportement ou le reporting CLI change.
Enregistrements du ledger
Un fichier par problème à .devin/automation/sentry-triage/ledger/<SHORT_ID>.json. Champs requis :
titleproblemSignaturedispositionrationalefixSummaryprOrIssuelastAnalyzedduplicateOfquanddispositionestduplicate
Le shortId est le nom du fichier (aucun champ shortId à l'intérieur du fichier). ledger/_meta.json contient les constantes au niveau du repo (schemaVersion, project) et est rarement édité.
Valeurs de disposition : shipped, duplicate, keep_sentry, ignored, pending_review. pending_review est la seule valeur non terminale (retraitée au prochain run) ; le reste est terminal. Les règles de décision complètes vivent dans SUBAGENT_CONTRACT.md (Choosing a disposition).
Résolution Sentry
Ne marquez pas les problèmes Sentry comme résolus à moins que la version CLI expédiée exacte soit connue et explicitement fournie. Préférez la résolution explicite de la version à « next release ».