Remédiation Autonome

Un audit nocturne avec Kimi, un epic dérivé avec Opus, et un workflow qui a mené vingt-deux constats de l'issue à la PR fusionnée en une seule après-midi — sans aucune intervention humaine entre un constat et la branche. Voici comment le run s'est réellement déroulé.

Version 1.0 · Mis à jour

01

Deux runs, polarité inversée

Le 2 juin 2026, la factory d'agents de Roxabi a retourné sa propre machinerie multi-agents sur sa propre base de code. Un audit qualité avait déjà balayé le dépôt — 69 agents sur 20 vagues, huit domaines, 3 291 fichiers — et distillé 1 258 issues brutes en 22 constats actionnables. Voici le compte rendu de la suite : solder ces 22 constats, de bout en bout, sans aucune barrière humaine entre une issue et sa fusion.

22constats
19/19PR fusionnées
4 h 32 mtemps réel
0barrière humaine

L'audit et la remédiation sont la même forme, parcourue en sens inverse. L'audit était un fan-out en lecture : beaucoup d'agents qui observent, rien qui change. La remédiation était un fan-out en écriture suivi d'une fusion sérialisée : beaucoup d'agents qui modifient, une seule branche qui absorbe. Même machinerie, polarité inversée.

PhaseTemps réelÉchelleRésultat
Audit (précurseur)2 h 20 m69 agents · 20 vagues · 8 domaines1 258 issues → 22 actionnables
Remédiation (ce run)4 h 32 m19 feuilles · 4 vagues · auto-merge22 constats livrés · 4 gates de dette CI
02

De l'audit à l'epic

La remédiation n'est pas partie d'une intuition — elle est partie d'un plan, et ce plan a été construit par la machine la nuit précédente. Le mot « audit » recouvre ici deux instruments distincts, à ne pas confondre.

Scanner déterministeAudit multi-agents profond
Quoiune métrique de dette par marqueurs de suppressionun fan-out de lecture qualitatif
Commentaudit_quality_debt.py · make quality-debt-report69 agents · 20 vagues · 8 domaines, piloté par Kimi
Sortiequality-debt-report.json (des comptes)un manifest + 8 rapports de domaine → 1 258 issues
Cadencechaque PR — CI informatif, ne bloque jamaisponctuel, à la demande (de nuit)

Le scanner est le pouls permanent — peu coûteux, déterministe, toujours actif. L'audit profond, lui, est le diagnostic. Il a tourné de nuit, en fan-out de lecture seule — beaucoup d'agents qui lisent, aucun qui écrit — partitionnant 3 291 fichiers sur huit domaines d'analyse en vingt vagues, piloté par Kimi : un modèle peu coûteux à long contexte routé via le proxy LiteLLM, ce qui rend un balayage de 69 agents abordable à lancer pendant que l'on dort. Il a fait remonter 1 258 issues brutes, les a classées P0–P3, et les a synthétisées en un manifest committé et huit rapports de domaine. Cette moitié lecture a son propre compte rendu — le doc compagnon Audit Multi-Agents — et sa méthode est un artefact réutilisable, le playbook d'audit.

Un tas de 1 258 issues n'est pas un plan. Opus a donc pris les constats de plus haute sévérité — les issues P0 et P1 — et a fait le travail qui transforme des symptômes en plan : il a dérivé les causes racines qui les sous-tendent. Non pas « corriger ces deux cents lignes », mais « voici la poignée de causes structurelles que ces lignes partagent ».

Ces causes racines sont devenues l'epic #1662 — 22 constats actionnables. L'epic a été découpé en tâches feuilles, et les feuilles ont été reliées par des arêtes GitHub natives blocked_by en un graphe de dépendances : là où deux correctifs touchaient le même fichier, l'un était marqué bloqué par l'autre ; là où les empreintes étaient disjointes, aucune arête. Ce graphe est l'ordonnancement.

Audit profond Kimi · 69 agents 20 vagues · 8 domaines Cause racine Opus · à partir des constats P0 / P1 Epic #1662 22 actionnables constats blocked_by partagé ⇒ série disjoint ⇒ parallèle Workflow une vague par invocation
De la lecture nocturne d'un modèle à un ordonnancement exécutable par la machine. Kimi audite, Opus remonte aux causes, l'epic se découpe, les arêtes blocked_by encodent l'ordre — et le workflow ne fait que parcourir le graphe.

Le graphe de dépendances est le contrat entre planification et exécution. Les arêtes blocked_by de l'epic sont l'ordonnancement par vagues — le harnais les lit, il ne les invente pas.

03

Le harnais

L'ordonnancement est de la donnée ; le harnais est le moteur qui l'exécute. epic-1662-wave.mjs est un script Workflow — un contrôle de flux JavaScript déterministe (boucles, fan-out, conditions) enveloppant des appels agent() pilotés par le modèle. Chaque invocation exécute exactement une vague de dépendances de feuilles et, délibérément, ne fusionne pas — la fusion est le travail de la boucle principale. C'est cette séparation qui permet aux dépendants de chaque vague de brancher depuis une base déjà fusionnée.

À l'intérieur, chaque feuille suit le même pipeline, adapté à sa taille.

① Implémenter — adaptatif à la taille S → un agent d'impl (worktree isolé) F → PLAN ⇒ sous-impl ×N (fichiers disjoints) ⇒ INTEGRATE PR · trace de décision ② Revue · 5 lentilles en parallèle correctness · axial · sécurité · tests · règles bloquant / majeur ③ Validation · 2 sceptiques / constat réfuter par défaut — ne survit que si confirmé confirmé ④ Correctif · appliquer → re-gates → push deux tours au plus, puis report du résiduel ≤ 2 tours Report → issue sœur boucle principale (hors workflow) CI vert → +reviewed → auto-merge → vague suivante
Une feuille, de bout en bout. La boîte en pointillés est la seule partie hors du script workflow : le harnais produit une PR relue et s'arrête ; la boucle principale fusionne et le ré-invoque pour la vague suivante.
  • Implémenter. Une petite feuille reçoit un agent d'implémentation dans un worktree git isolé. Une grosse est d'abord découpée par un agent PLAN en groupes de fichiers disjoints, implémentés par des sous-agents parallèles (aucun ne touche le même fichier, donc la fusion est sans conflit par construction), puis recousue par un agent INTEGRATE. Dans les deux cas, ça se termine par une PR portant une trace de décision.
  • Revue. Cinq lentilles relisent le diff en parallèle — exactitude, architecture axiale, sécurité, tests et conformité aux règles — chacune un agent spécialiste. Seuls les constats bloquants et majeurs avancent.
  • Validation. Chaque constat qui avance affronte deux sceptiques, chacun invité à le réfuter par défaut. Un constat ne survit que s'il est confirmé — le bruit de revue plausible-mais-faux meurt ici.
  • Correctif & report. Un fixer applique les constats confirmés, relance les gates et pousse. La boucle tourne deux fois au plus ; tout ce qui reste non résolu est déposé en issue sœur reportée, bloquée par l'originale — le lot ne cale jamais sur un constat tenace.

La forme tient en un écran — un panel de revue parallèle, puis un vote sceptique par constat :

epic-1662-wave.mjs · revue → validation
// 5 lentilles relisent le diff en parallèle — chacune un agent spécialiste
const reviews = await parallel(LENSES.map((L) => () =>
  agent(reviewPrompt(n, L, diff), { agentType: L.agent, schema: FINDINGS_SCHEMA })))

// garder bloquant/majeur, puis réfuter chaque constat avec 2 sceptiques
const verdicts = await parallel(findings.map((f) => () =>
  parallel([1, 2].map((k) => () =>
    agent(validatePrompt(n, f, diff, k), { schema: VERDICT_SCHEMA })))
    .then((votes) => ({ f, real: votes.some((v) => v.real) }))))

const confirmed = verdicts.filter((v) => v.real).map((v) => v.f)

Quatre propriétés tiennent pour chaque agent du run, par construction :

  • Sortie typée, jamais en prose. Chaque agent est forcé d'émettre un résultat structuré contre un schéma JSON — le mode d'échec « l'agent a fini en paragraphe au lieu d'un résultat » est éliminé par conception.
  • Un seul contrat, injecté verbatim. Les mêmes règles RCA (§6) entrent dans chaque prompt, pour que dix-neuf agents non coordonnés raisonnent de la même façon.
  • Réessai au niveau de l'inférence. Un wrapper tryAgent réessaie trois fois avec back-off croissant — le correctif de la tempête de surcharge du soir d'ouverture, désormais un défaut.
  • Isoler, différer, continuer. Une feuille qui lève une erreur est capturée, enregistrée et ignorée ; la vague n'avorte jamais sur un échec isolé. La concurrence est plafonnée à trois issues en vol, pour la cadence de fusion.
04

De la PR relue à la fusion

Le workflow rend une PR relue ; la boucle principale prend le relais — et c'est là que tout reste autonome. La séparation compte : le workflow développe, la boucle principale fusionne, pour que les dépendants branchent toujours depuis une base fraîchement fusionnée.

1
Gate CI
ci et le scan de secrets doivent être au vert — les mêmes checks que l'agent a déjà exécutés en local.
2
Label + auto-merge
Ajouter le label reviewed, activer gh pr merge --auto. Aucune approbation humaine dans le chemin.
3
Watcher base-stricte
staging exige des branches à jour ; une boucle de poll lance update-branch à chaque BEHIND et abandonne sur DIRTY.
4
Fusionné → débloque
La fusion libère les feuilles qui étaient blocked_by elle, ouvrant la vague suivante.
5
Vague suivante
Ré-invoquer le workflow ; ses agents branchent depuis la base que la dernière vague vient de fusionner.

La barrière de fusion était CI au vert + un label reviewed + la revue croisée entre agents en cours de run — et rien d'autre. Aucune approbation humaine ne se tenait entre une PR au vert et la branche staging.

05

Ordonnancer par empreinte

Dix-neuf feuilles ne peuvent pas tourner toutes en même temps — certaines touchent les mêmes fichiers, et deux agents qui éditent un seul fichier produisent un conflit de fusion, pas une fonctionnalité. L'ordonnanceur a suivi un unique prédicat, lu directement sur le graphe blocked_by de l'epic : empreinte disjointe ⇒ parallèle ; fichier partagé ⇒ série. Le parallélisme était plafonné à trois agents concurrents, et autorisé uniquement là où les empreintes étaient prouvablement disjointes.

ORDONNANCEMENT TEMPS → V1 9 feuilles fan-out parallèle V2 3 feuilles départ conditionné V3 5 feuilles strictement en série V4 2 feuilles en série empreintes disjointes core · infra · config attend une fusion de V1 partagent ci.yml · pre-commit · stack.yml partagent un CLAUDE.md
Quatre vagues, ordonnancées par empreinte : en parallèle là où les feuilles sont disjointes, en série là où elles partagent un fichier. Sérialiser V3 — cinq feuilles éditant toutes la config CI — a maintenu le lot sans conflit.
VagueFeuillesStratégiePourquoi
V19fan-out parallèleempreintes disjointes — core, infra, config, adapters
V23départ conditionnéchacune dépend d'une fusion de V1
V35strictement en sériepartagent toutes ci.yml · pre-commit · stack.yml
V42en sériepartagent un CLAUDE.md

Sérialiser V3 fut la décision d'ordonnancement la plus déterminante. Cinq feuilles ajoutaient toutes à la même config CI ; en parallèle, elles se seraient écrasées les unes les autres. En série, chacune voyait le changement de la précédente.

06

Un seul contrat, dix-neuf agents

Dix-neuf agents ont travaillé en isolation, aucun conscient des autres. Ce qui a gardé leur production cohérente — et relisible — fut un unique contrat de raisonnement, injecté verbatim dans chaque agent d'implémentation et répercuté dans chaque corps de PR.

obs(constat)  →  cause_racine            # pas le symptôme
              →  corrections ∈ {Patch ⊻ Archi}   # choisir, explicitement
              →  corriger au niveau de la cause
              →  trust(input)?  ·  testé ∧ correct   # vert ≠ correct
              →  tracer la décision dans le corps de PR

La règle qui a le plus servi fut vert ≠ correct : un run CI au vert est nécessaire, jamais suffisant. Et forcer chaque agent à choisir entre un patch (traiter le symptôme) et un correctif architectural (déplacer la cause) — à voix haute, dans la PR — a transformé dix-neuf runs non coordonnés en un dossier relisible. Ce document est rédigeable parce que ce dossier existe.

07

Ce qui a cassé, et pourquoi

La valeur d'un retour d'expérience est dans les échecs. Sept blocages ont enrayé le run ; chacun a été ramené à une cause racine et corrigé à ce niveau, pas rustiné. Les coûteux étaient systémiques — et vivent désormais comme défauts durcis dans le harnais d'orchestration.

Ce qui a casséCause racineCorrectif
9 agents sur 9 ont échoué au premier essaiUne surcharge transitoire API 529 à la première inférence, masquée en « terminé »Réessai + back-off au niveau de l'inférence
Les agents lourds finissaient en prose, sans résultatLes gros diffs faisaient exploser le budget de sortie structuréeRendre le diff optionnel, le récupérer hors bande, scinder les feuilles surdimensionnées
Les PR ne fusionnaient jamaisUn blocage par retard en strict-merge — aucune PR n'est à jour, donc l'auto-update ne se déclenche jamaisUne boucle watcher update-branch manuelle par PR
Les refactos parallèles passaient DIRTYDes éditions interdépendantes sur les mêmes fichiers CISérialiser les vagues par empreinte de fichier partagé
Le check CI requis disparaissait en silenceUn deux-points non quoté dans un name: d'étape YAML invalidait tout le workflowQuoter tout name: contenant un deux-points + un gate de validation YAML
Un gate de dette criait au loupLe formateur recomposait un appel multi-ligne hors de sa ligne de commentaireRéécriture du gate pour parcourir les parenthèses équilibrées, multi-ligne
Un agent a livré un câblage casséUn worktree branché depuis un staging local périmé n'a jamais vu les nouveaux hooksFast-forward et épinglage de la base sur origin/staging avant le spawn

Seul le dernier a exigé un sauvetage humain. Tout le reste a été capté, ramené à sa cause, et transformé en défaut — la différence entre un correctif ponctuel et un pipeline qui tourne plus propre la fois suivante.

08

Le coût, sans fard

Le temps est une donnée dure, lue directement sur les horodatages des PR. Les tokens, non — le harnais n'a jamais capté l'usage par agent, donc le total du run est une estimation ascendante : compter les agents que le pipeline lance réellement, multiplier par ce que coûte un agent. C'est étiqueté comme une estimation, mais l'ordre de grandeur ne fait pas de doute.

4 h 32 m1ʳᵉ PR → dernière fusion
~3 minCI moyen par PR
~96commits
+4,6k / −1,5klignes modifiées

Combien d'agents par issue ?

Le run n'a jamais été trente agents — c'était le compte des invocations /dev de premier niveau. Le vrai fan-out, c'est le pipeline par issue (§4) qui lance un sous-agent neuf à chaque étape, et les étapes lourdes qui re-fan-out à leur tour. Lu directement sur epic-1662-wave.mjs :

Étape (§4)Agents, un tourNote
Implémenter — petite feuille21 impl (worktree isolé) + 1 récupération de diff hors bande
Implémenter — grosse feuille5–61 PLAN + 2–3 sous-impl en parallèle + 1 INTEGRATE + 1 diff
Revue (panel)5un agent spécialiste par lentille, en parallèle
Validation2 × chaque constatdeux sceptiques indépendants par constat (~3 constats → ~6 agents)
Correctif1 / tourla boucle revue→validation→correctif tourne deux fois au plus
Report0–1une fois, seulement si un résiduel survit à 2 tours

Une petite feuille représentative, un seul tour de revue, ~3 constats : 2 + 5 + 6 + 1 ≈ 14 agents. Un second tour double presque le bloc revue/validation/correctif, poussant une feuille contestée vers ~25. Moyenné sur les dix-neuf feuilles fusionnées (majoritairement petites, quatre grosses), comptez ~18 agents par issue → ~340 invocations d'agents sur le run.

Plus le debug. La tempête de surcharge d'ouverture (§7) a lancé une vague entière morte à la première inférence — 9 agents, ≈ 0 token chacun (l'API 529 a frappé avant tout travail réel) : ça a coûté du temps mural et un re-run, pas des tokens. Ajoutez une poignée de re-devs et la récupération à la main du #1697 (base périmée) par-dessus.

Les tokens, estimés

Un agent vivant d'impl, de revue ou de correctif lit sa tranche du dépôt, le diff de la PR, et exécute toute la suite de gates — ce qui place un seul agent à 100–200k tokens, parfois plus. L'unique donnée dure se situe au bas de cette fourchette, exactement comme attendu : les deux agents instrumentés étaient des récupérations post-compaction, reprises depuis un contexte rétréci. Donc ~340 agents × ~150k ≈ ~50 M tokens pour le run — une fourchette de ~35–70 M aux bornes 100–200k — et ~2,5–3 M tokens par issue. L'estimation antérieure de « ~1,5–2,5 M pour tout le run » était fausse d'un facteur ~20 : c'était à peu près le coût d'une seule issue.

Qu'est-ce qui a été mesuré ?
Deux agents de récupération post-compaction ont rapporté 122 505 tokens cumulés (~61k chacun) avec une confiance élevée, directement depuis leurs notifications de tâche — l'ancre basse pour un agent.
Qu'est-ce qui a été estimé ?
~340 invocations d'agents × 100–200k tokens chacune ⇒ ~35–70 M tokens pour le run complet (central ~50 M), ≈ ~2,5–3 M par issue. Confiance faible sur le multiplicateur exact ; confiance élevée sur l'ordre : des dizaines de millions, pas un chiffre unique.
Suite : capture de tokens par agent dans le harnais — on n'optimise pas ce qu'on ne mesure pas.
09

La preuve que c'est passé

Dix-neuf PR fusionnées prouvent que le processus est allé au bout. Elles ne prouvent pas que le code est juste — un pipeline vert et un epic clos peuvent tous deux reposer sur un correctif qui a discrètement dérivé de son intention. Une fois le run terminé, un audit de second niveau a donc relu directement la source fusionnée sur staging, constat par constat, avec une seule question : chaque correctif a-t-il vraiment atterri comme sa PR le prétendait ?

Trois agents spécialistes se sont partagé la surface — refactors et architecture, les chemins sensibles à la sécurité, et la dérive inter-couches — et ont lu les fichiers, pas les diffs.

AuditeurPérimètreVerdict
backend-devrefactors DRY, axe d'étage, configs, protocoles8 / 8 ✅
security-auditorprocess_one, journalisation des tours, catch large, sleep()4 / 4 ✅
axial-adr-reviewpollution inter-couches, dérive hors de l'axe primaire2 fuites mineures
19/19feuilles confirmées dans la source
0régression
0bloqueur
3points résiduels

Les deux fuites architecturales étaient réelles mais minces — du code de cœur de hub discriminant encore deux types de message propres à une plateforme là où un trait générique a sa place, et un classificateur d'erreurs s'appuyant sur les noms de modules d'adaptateur plutôt que sur une taxonomie que les adaptateurs déclarent. Ajoutez une limite codée en dur qui réclame un nom, et c'était tout le résidu : versé en suivis non bloquants, au dossier plutôt qu'enfoui.

La machinerie qui a trouvé la dette a été retournée sur le code qui l'a résorbée. 19 correctifs sur 19 confirmés dans la source, zéro régression — et les trois points qu'elle a soulevés sont versés au dossier, pas balayés. La validation, c'est le fan-out de lecture, rejoué une fois de plus.

10

Ce qui se capitalise

Les constats étaient propres à une base de code. Les patterns, non — voici les parties qui se reportent au run suivant.

  • Les feuilles plutôt que les parapluies. Ordonnancer sur la feuille actionnable ; laisser les issues parentes se fermer d'elles-mêmes quand leurs enfants fusionnent. Aucune dépendance fantôme.
  • Parallélisme par empreinte. « Empreinte disjointe ⇒ parallèle ; fichier partagé ⇒ série » est un prédicat plus propre, pour éviter les conflits, que la taille ou la priorité d'une issue.
  • Corps de PR à trace de décision. Cause racine + Patch ⊻ Archi + niveau, dans chaque PR. Cela rend des agents indépendants relisibles — et un retour d'expérience rédigeable.
  • Isoler, différer, continuer. Une feuille en échec est isolée et différée ; la vague avance. Aucun échec isolé n'enraye le lot.
  • Antériorité de référence pour les gates de dette. Un nouveau gate atterrit en bloquant les nouvelles violations tout en tolérant l'existant par antériorité, avec un plan de résorption à suivre — pour que le gate atterrisse aujourd'hui au lieu d'attendre une refonte de 90 items.

Un seul opérateur a mené vingt-deux constats jusqu'à la fusion en une seule après-midi — et chaque décision est au dossier. C'est toute la thèse en un run : le rendement d'une équipe, entièrement auditable, sans verrouillage.

11

Sources & code

Chaque artefact de ce compte rendu est public. Le dépôt est Roxabi/roxabi-factory (AGPL-3.0).

ArtefactCe que c'est
Epic #1662l'epic aux 22 constats (clos)
epic-1662-wave.mjsle harnais workflow (§3)
epic-1662-ledger.mdjournal d'exécution (source de vérité)
AUDIT-SUMMARY.mdle rapport final de l'audit profond
REMEDIATION-RECAP.mdle retour d'expérience que ce doc distille
playbook d'audit multi-agentsla méthodologie d'audit réutilisable
playbook pipeline qualité-dettele mode d'emploi du scanner de dette permanent