FND-006 : Le zéro compromis en pratique : santé du code, discipline des erreurs et norme de préparation à la production
À partir de la version 0.7.0 · Type : Qualité · Rév. 1
Référence canonique · Ratifié par l’équipe · Rév. 1 Discussion RFC originale : #5653
Une note à l’équipe avant que vous lisiez ceci.
Ceci est le sixième document du cadre de maturité de ZeroClaw. Les cinq précédents traitaient de l’architecture, de la documentation, de la gouvernance, de l’infrastructure d’ingénierie et de la collaboration — l’échafaudage structurel et humain qui entoure le travail. Chacun répondait à une question différente sur la manière dont nous construisons ce projet ensemble. Si vous les avez tous lus, vous avez peut-être remarqué une question à laquelle aucun d’eux n’a répondu : oui, mais comment l’écrire bien, concrètement ? La RFC sur l’architecture vous a indiqué dans quelle forme construire. La RFC sur la documentation vous a indiqué comment le consigner. La RFC sur la gouvernance vous a indiqué comment vous coordonner. La RFC sur le CI/CD vous a indiqué comment le contrôler. La RFC sur la culture vous a indiqué comment travailler avec les personnes qui vous entourent. Aucune ne vous a dit à quoi ressemble la qualité au niveau de la phrase, à l’intérieur d’une fonction, au moment où vous faites un choix.
C’est à cela que sert ce document.
Les sujets spécifiques abordés ici, la gestion des erreurs, la documentation d’API, la conception de tests, la dette technique, sont des sujets Rust en surface. Les compétences qu’ils développent ne le sont pas. La technologie change. Elle change plus vite à chaque itération que la fois précédente. Les outils que vous utilisez aujourd’hui, ce langage, ce framework, cet assistant IA, seront remplacés. Certains d’entre eux pendant la durée de vie de ce projet. Le jugement que ce document tente de vous aider à construire ne sera pas remplacé. Il se cumulera silencieusement en arrière-plan de chaque décision que vous prendrez, dans chaque langage que vous écrirez, dans chaque système que vous construirez, et dans des travaux qui n’auront peut-être rien à voir avec le logiciel. C’est l’investissement que nous faisons en vous. Pas dans votre capacité à écrire du Rust. Dans votre capacité à réfléchir à la qualité, à l’échec et au savoir-faire, et à emporter cette réflexion avec vous dans chaque outil que vous prendrez en main, y compris les outils d’IA que vous utilisez aujourd’hui et ceux qui n’existent pas encore.
Prenez votre temps.
La suite du cadre de maturité
Ce RFC est le sixième d’un ensemble de documents qui forment ensemble le cadre de maturité de ZeroClaw. Ils sont conçus pour être lus dans leur ensemble, bien que chacun puisse être lu indépendamment.
| RFC | Portée | Problème |
|---|---|---|
| Architecture intentionnelle : transition vers le micronoyau | Ce que nous construisons et comment il est structuré | #5574 |
| Normes de documentation et architecture des connaissances | Comment nous documentons ce que nous construisons | #5576 |
| Organisation de l’équipe et gouvernance du projet | Comment nous coordonnons et prenons des décisions | #5577 |
| Infrastructure d’ingénierie : Pipeline CI/CD | Comment nous construisons, testons et déployons de manière fiable | #5579 |
| Culture de contribution : collaboration humaine, partenariat avec l’IA et développement de l’équipe | Comment nous travaillons ensemble et grandissons | #5615 |
| Zéro compromis en pratique : santé du code, discipline de gestion des erreurs et norme de préparation à la production | Comment écrire du code qui dure | ce RFC |
Les cinq premières RFC répondent à des questions structurelles et humaines. Celle-ci répond à la question qui se trouve au cœur de toutes les autres : étant donné la structure, étant donné l’équipe, étant donné les outils, que signifie bien écrire le code ?
Table des matières
- Une philosophie de développement : l’investissement dans le jugement
- Évaluation honnête : Ce que la base de code nous dit
- 2.1 Les preuves
- 2.2 Ce que les chiffres ne montrent pas
- 2.3 Ce qui est déjà bien
- Portes et normes : la distinction centrale
- Les Sept Disciplines
- 4.1 La gestion des erreurs comme préoccupation de conception
- 4.2 Surface de l’API publique en tant que Promise
- 4.3 Les tests comme retour sur la conception
- 4.4 Tri de la dette technique
- 4.5 Sécurité au niveau de l’application
- 4.6 L’observabilité comme capacité de débogage
- 4.7 Travailler au-dessus du sol
- Ce que cela signifie pour le développement assisté par l’IA
- La portabilité de Craft
- Ce que cela signifie pour les contributeurs
Historique des révisions
| Rév | Date | Résumé |
|---|---|---|
| 1 | 2026-04-12 | Brouillon initial |
1. Une philosophie de développement : l’investissement dans le jugement
La RFC sur l’architecture a introduit une hiérarchie de décisions qui décrit comment chaque choix dans ce projet doit être pris :
Vision
└── Architecture
└── Design
└── Implementation
└── Testing
└── Documentation
└── Release
Cette hiérarchie répond à la question de quoi construire à chaque niveau. Ce RFC se situe dans les couches Implémentation et Tests et pose une question différente : à quel point ?
La réponse à « dans quelle mesure » n’est pas une liste de contrôle. Les listes de contrôle peuvent être satisfaites sans être comprises, et en logiciel, c’est la compréhension qui produit des résultats durables. Un contributeur qui a mémorisé les règles les suivra jusqu’à ce que la situation soit légèrement différente. Un contributeur qui a intériorisé le jugement derrière les règles l’appliquera correctement aux situations que les règles n’avaient pas anticipées, y compris les situations qui comptent le plus, qui sont toujours celles que personne n’avait prévues.
Cette distinction est particulièrement importante dans le contexte de ce projet. ZeroClaw est exploité dans un environnement d’outils puissants : génération de code par IA, portes de contrôle CI qui détectent un large éventail d’erreurs courantes, linters d’IDE, scanners de sécurité automatisés. Ces outils sont réellement précieux. Ils définissent un plancher, un minimum en dessous duquel le code ne devrait pas être fusionné. Mais ce qu’ils ne peuvent pas faire, c’est réfléchir. Ils ne peuvent pas décider si une erreur est opérationnelle ou une erreur de programmeur. Ils ne peuvent pas évaluer si un test vérifie le bon comportement. Ils ne peuvent pas déterminer si une API publique est documentée assez clairement pour qu’un futur contributeur puisse l’implémenter correctement. Ils ne peuvent vérifier que ce qu’ils ont été programmés pour vérifier.
L’écart entre « ce que les outils peuvent vérifier » et « la qualité qui sert les utilisateurs, les contributeurs et le projet dans la durée » est comblé par le jugement. C’est ce jugement que ce document cherche à vous aider à développer, non pas pour remplacer les outils, mais pour les orienter.
2. Évaluation honnête : Ce que la base de code nous dit
Cette section n’est pas une critique. C’est un diagnostic. Le même cadre qui s’appliquait dans la RFC sur l’architecture s’applique ici : vous ne pouvez pas améliorer ce que vous ne pouvez pas nommer, et les détails sont utiles précisément parce qu’ils sont spécifiques.
2.1 Les preuves
La décomposition du workspace issue de la RFC §5574 a réussi. Les crates existent, les frontières des traits sont réelles, et le compilateur fait respecter la direction des dépendances. C’est un travail véritablement de qualité. Et au sein de ces nouveaux crates, les mêmes patterns qui caractérisaient le monolithe d’origine ont été reconduits, parce que la base de code a évolué avant que l’équipe ne dispose d’un modèle partagé de ce à quoi ressemble la « qualité au niveau de l’implémentation ».
Ce sont des faits mesurés, pas des estimations :
| Métrique | Valeur | Ce que cela indique |
|---|---|---|
zeroclaw-config/src/schema.rs | 16 800 lignes | Désormais le fichier le plus volumineux de la base de code ; le loop_.rs d’origine avait été signalé à 9 500 lignes dans la RFC d’architecture ; celui-ci le dépasse |
zeroclaw-channels/src/orchestrator/mod.rs | 11 813 lignes | Deuxième fichier le plus volumineux ; un seul module portant une responsabilité concentrée |
zeroclaw-runtime/src/onboard/wizard.rs | 7 988 lignes | Un seul workflow dans un seul fichier |
zeroclaw-runtime/src/agent/loop_.rs | 6 101 lignes | Réduit par rapport aux ~9 500 du monolithe : un progrès réel et mesurable ; reste néanmoins volumineux |
zeroclaw-channels/src/orchestrator/telegram.rs | 5 122 lignes | Une implémentation de canal ; un fichier |
Appels à .unwrap() / .expect() dans les crates | 5 630 | Chacune est une décision reportée concernant la gestion des erreurs, voir §4.1 |
Appels à .unwrap() / .expect() dans src/ hérité | 240 | La migration a propagé le modèle à grande échelle. |
Fonctions publiques dans zeroclaw-api | 371 | La totalité de la surface d’API fondamentale ; tous les autres crates dépendent de celui-ci |
Lignes de commentaires de documentation dans zeroclaw-api | ~27 | Ratio d’environ 14:1 d’API publique non documentée, voir §4.2 |
#[allow(unused_imports)] / #[allow(dead_code)] dans les modules src/ hérités | ~30+ instances | Le compilateur a identifié du code qui n’est plus utilisé ; il a été demandé de ne pas l’indiquer. |
TODO / FIXME / todo!() / unimplemented!() dans l’ensemble de la base de code | 20 | Notablement faible, ce qui suggère que la majeure partie de la dette est silencieuse plutôt que marquée |
La dernière ligne mérite une note à part. Vingt marqueurs explicites de travail incomplet dans une base de code de cette taille ne sont pas un signe que le travail est presque terminé. C’est un signe que la plupart des travaux incomplets ne sont pas étiquetés comme tels. La dette non marquée est plus difficile à trouver, à prioriser et à attribuer que la dette qui a été nommée. Le silence n’est pas synonyme de complétude.
2.2 Ce que les chiffres ne montrent pas
Ces chiffres mesurent ce qui est comptable. Les questions de qualité plus importantes ne peuvent pas être comptées :
- Que les 5 630 appels à
.unwrap()se trouvent dans des chemins critiques ou dans des utilitaires de test - Si les tests existants testent le comportement ou les détails de l’implémentation.
- Les fonctions publiques de
zeroclaw-apipeuvent-elles être correctement implémentées par quelqu’un qui lit uniquement la signature et le type ? - Si un message de journal émis lors d’une défaillance en production contient suffisamment de contexte pour diagnostiquer la défaillance.
- Si un contributeur travaillant dans le module de sécurité comprend quelles données ont franchi une limite de confiance et lesquelles ne l’ont pas.
Il s’agit de questions d’évaluation. Elles ne sont pas soumises à un contrôle CI. Elles reposent sur les normes que ce document propose de nommer, ainsi que sur la culture de revue et de mentorat que nous construisons ensemble.
2.3 Ce qui est déjà bien
Le diagnostic ne doit pas obscurcir ce qui est véritablement bien conçu.
La couche de traits dans zeroclaw-api est la bonne architecture. Provider, Channel, Tool, Memory, Observer, RuntimeAdapter et Peripheral sont des abstractions propres et bien pensées. Ce sont les bonnes lignes de séparation. Le problème ne vient pas de la conception. C’est que la conception n’est pas encore pleinement exprimée dans la documentation, la couverture de tests et la discipline de gestion des erreurs. Cette RFC vise à combler cet écart.
Le modèle de sécurité est réfléchi. Les codes d’appairage, les niveaux d’autonomie, les couches de sandboxing et l’application des politiques témoignent d’une véritable intention de conception. Cette intention doit être comprise par chaque contributeur qui écrit du code à proximité d’une frontière de confiance, et cette RFC existe en partie pour donner aux contributeurs le vocabulaire nécessaire pour reconnaître où se situent ces frontières.
L’infrastructure d’observabilité est mature. OpenTelemetry, Prometheus et les indicateurs DORA sont tous implémentés en fonction d’un trait Observer propre. L’infrastructure est en place. Le fossé pédagogique réside dans la manière dont les contributeurs l’utilisent pour qu’elle soit réellement utile en cas de problème.
La suite de tests n’est pas absente. L’investissement existant dans les tests est réel. Le travail décrit dans cette RFC concerne la qualité et la répartition de cet investissement : ce qui est testé, comment, et si les tests prouvent ce qu’ils semblent prouver.
ADR-004 est un excellent exemple de documentation architecturale. Il prouve que l’équipe peut produire une documentation de conception de haute qualité lorsque l’attente est claire. Ce RFC propose une attente équivalente pour le code lui-même.
3. Portes et normes : la distinction centrale
C’est l’idée organisatrice de l’ensemble du document. La comprendre clairement est plus importante que toute technique spécifique du §4.
Une gate est binaire : succès ou échec. Elle est automatisée, imposée par des outils et définit le seuil minimum en dessous duquel aucun code n’est fusionné. La RFC CI/CD a établi ces gates. Elles sont réelles et fonctionnelles.
| Porte | Ce qu’il vérifie |
|---|---|
cargo fmt --check | Le code est formaté de manière cohérente dans l’ensemble de l’espace de travail. |
cargo clippy --workspace --all-targets -D warnings | Aucune antipattern connue de Clippy ; à l’échelle de l’espace de travail |
cargo deny check | Aucun avis de sécurité non acquitté ; conformité de la licence et de la source |
cargo nextest run --workspace | Les tests qui existent, passent |
Un standard est un idéal à atteindre. Il décrit à quoi ressemble la qualité au-delà du minimum requis. Il est appliqué grâce au jugement, à la revue par les pairs et aux habitudes que l’équipe construit ensemble.
| Standard | Ce que cela décrit |
|---|---|
| Discipline de gestion des erreurs | Les échecs sont catégorisés ; les erreurs opérationnelles remontent avec du contexte à la bonne couche. |
| Documentation de l’API | Chaque élément public dispose d’une documentation suffisante pour être utilisé correctement sans avoir à lire l’implémentation. |
| Qualité des tests | Les tests affirment le comportement, pas l’implémentation ; la difficulté des tests est considérée comme un retour sur la conception. |
| Triage des dettes | La dette non résolue est étiquetée, localisée et pondérée en fonction du risque ; la dette à haut risque a un propriétaire. |
| Posture de sécurité | Les limites de confiance sont explicites au niveau de l’implémentation, et pas seulement au niveau de la politique. |
| Discipline d’observabilité | Les messages de journal répondent à la question diagnostique ; les étendues lient des unités significatives de travail. |
Les portes et les normes ne sont pas en concurrence. Elles constituent des couches complémentaires. Des portes sans normes produisent du code qui passe tous les contrôles mais échoue auprès des utilisateurs. Des normes sans portes sont inapplicables. Vous avez besoin des deux. Le projet dispose actuellement de bonnes portes et de normes sous-développées.
Un code peut réussir chaque étape de validation et rester incompréhensible pour le prochain contributeur, se taire au lieu de remonter les erreurs, être impossible à tester de manière isolée, et présenter des failles de sécurité à l’interface entre les entrées utilisateur et la logique métier. La coche verte répond à la question « ce code a-t-il passé les règles que nous avons définies ? » Elle ne répond pas à la question « ce code est-il de qualité ? » Ces deux questions ne sont pas identiques.
Ceci n’est pas une critique des barrières de qualité. Les barrières sont précieuses justement parce qu’elles définissent un socle commun et applicable dans lequel chaque contributeur travaille. L’objectif de ce document est de construire le vocabulaire et le jugement partagés qui définissent ce à quoi ressemble la qualité au-delà de ce socle, et d’expliquer clairement pourquoi ce jugement ne peut pas être délégué à un outil.
4. Les sept disciplines
4.1 La gestion des erreurs comme préoccupation de conception
Chaque appel à .unwrap() est une décision. La plupart des 5 630 présents dans la base de code n’ont pas été faits consciemment. Ils ont été faits par défaut, parce que .unwrap() est le chemin de moindre résistance quand on a besoin d’extraire une valeur d’un Result ou d’une Option et qu’on veut passer à autre chose. Le problème avec les décisions prises par défaut, c’est qu’elles ne sont pas des décisions. Ce sont des reports. Et ce qu’elles reportent, c’est une vraie question : que devrait-il se passer ici en cas d’échec ?
La réponse dépend du type de panne que vous rencontrez. Il existe trois types de pannes, et chacune a sa propre réponse correcte.
Les erreurs de programmation sont des violations d’invariants qui devraient être impossibles dans un code correct. Une fonction qui exige un Vec non vide, appelée avec un Vec vide. Un match sur une enum qui atteint une branche que le système de types aurait dû rendre inaccessible. Cela représente des bugs, et non des défaillances opérationnelles, mais une logique incorrecte. panic! est la réponse correcte, car l’objectif est de détecter ces erreurs au moment du développement, et non devant un utilisateur à l’exécution. assert! et debug_assert! sont les bons outils. .expect() avec un message expliquant pourquoi cet état est impossible est également approprié ici. Cela rend le raisonnement explicite et facile à rechercher, afin que la prochaine personne qui lit le code comprenne pourquoi le panic était intentionnel.
Les erreurs opérationnelles sont des modes de défaillance attendus. Délais d’attente réseau. Fichiers inexistants. Clés API expirées. Réponses de fournisseurs portant un statut d’erreur. Utilisateurs fournissant des entrées mal formées. Ce ne sont pas des bugs. Ce sont les conditions de fonctionnement normales d’un système qui interagit avec le monde. La réponse correcte est Result<T, E>. L’opérateur ? propage la défaillance à un appelant qui est mieux placé pour décider quoi en faire. Un .unwrap() sur une erreur opérationnelle est une panique différée : elle se déclenchera, tôt ou tard, dans des conditions réelles, devant un utilisateur réel, sans contexte utile et sans possibilité de récupération.
Les erreurs de configuration sont des configurations malformées ou manquantes découvertes au démarrage. La bonne réponse consiste à échouer rapidement, mais de manière précise. Pas une panique avec une trace de pile, pas un message vague du type « invalid config ». Un message qui pointe vers le champ spécifique, explique ce qui était attendu et indique à l’opérateur ce qu’il doit fournir. Un utilisateur qui ne peut pas démarrer ZeroClaw à cause d’une mauvaise configuration devrait quitter le processus en comprenant clairement ce qu’il doit corriger.
| Type d’échec | Ce que cela signifie | Réponse correcte |
|---|---|---|
| Erreur de programmation | Invariant violée ; devrait être impossible dans un code correct | panic!, assert!, .expect("raison pour laquelle ceci est sûr") |
| Erreur opérationnelle | Mode d’échec attendu ; le monde ne coopère pas | Result<T, E>, ?, type d’erreur structuré avec contexte |
| Erreur de configuration | Configuration de démarrage invalide ou manquante | Échec rapide avec un message spécifique et exploitable |
Avant chaque .unwrap() ou .expect(), demandez-vous : de quel type de défaillance s’agit-il ? Si la réponse est « erreur de programmation : cet état ne peut pas se produire dans un code correct », alors .expect() accompagné d’un commentaire expliquant pourquoi est le bon choix, et cela communique votre raisonnement à chaque futur lecteur. Si la réponse est autre, utilisez ? ou gérez la défaillance explicitement.
L’opérateur ? mérite d’être compris pour ce qu’il dit, pas seulement pour ce qu’il fait. Il dit : je reconnais que cette opération peut échouer. Je propage explicitement cet échec à mon appelant, qui est mieux placé pour décider quoi en faire. Cette reconnaissance est significative sur le plan architectural : elle rend le contrat de gestion des erreurs visible au point d’appel et reporte les décisions vers la couche qui dispose du plus de contexte.
L’objectif n’est pas d’éliminer tous les appels .unwrap(). Certains sont justifiés. L’objectif est que chaque appel représente une décision consciente, avec la justification rendue visible pour quiconque lit le code. La différence entre .unwrap() et .expect("ce vecteur est garanti non vide par l’appelant — voir §4.2 des invariants du moteur SOP") n’est pas seulement une question de style. C’est la différence entre un jugement différé et un jugement documenté.
4.2 Surface de l’API publique en tant que Promise
pub est un contrat.
Lorsque vous marquez une fonction, une structure, un trait ou un module comme public, vous faites une promesse à chaque appelant. Cela inclut le contributeur qui implémente contre cette API le mois prochain, sans se souvenir de votre intention initiale. Cela inclut l’assistant IA qui lit votre crate pour générer une implémentation. Cela inclut la personne qui débogue un incident en production et qui doit comprendre ce que cela était censé faire. Cela inclut également vous-même, revenant à ce code après deux mois passés sur autre chose.
Un élément public sans documentation est une promesse sans conditions. L’appelant n’a aucun moyen de connaître les hypothèses que vous avez faites en l’écrivant, les conditions d’erreur qu’il peut renvoyer et dans quelles circonstances, ses effets de bord, s’il peut être appelé en toute sécurité de manière concurrente, ou quelle est la différence subtile entre deux fonctions aux noms similaires. Il ne lui reste plus qu’à déduire, à partir du nom, de la signature de type et du corps de l’implémentation, ce que vous auriez pu lui dire en trois phrases.
La situation de zeroclaw-api est suffisamment spécifique pour être nommée directement. C’est la seule crate dont dépend l’ensemble de l’architecture. Chaque provider, canal, outil, backend de mémoire, observateur, adaptateur de runtime et implémentation périphérique de l’espace de travail est construit sur ces traits et ces types. Une interface non documentée dans cette fondation propage la confusion dans chaque crate qui l’implémente, chaque test qui l’exerce et chaque code généré par IA qui interagit avec elle. Le ratio de 14:1 de surface d’API publique non documentée n’est pas une préférence de style de documentation. C’est une lacune dans le contrat que la RFC d’architecture désignait comme la couche la plus importante du système.
La dimension IA ici est pratique et directe : lorsque vous demandez à un assistant IA d’implémenter un trait ou d’appeler une fonction sans documentation, l’IA infère l’intention à partir du nom et de la signature de type. Parfois, cette inférence est correcte. Plus souvent, elle produit du code qui compile, passe le vérificateur de types et se comporte incorrectement dans des conditions spécifiques que l’IA ne pouvait pas anticiper, parce que personne ne les a écrites. La documentation n’est pas seulement destinée aux humains. C’est la spécification que vous fournissez à chaque outil qui travaillera un jour avec votre code, et à chaque personne qui en dépendra un jour.
Au minimum, chaque élément public de zeroclaw-api doit comporter :
- Une phrase décrivant ce qu’il fait. Pas ce qu’il est : ce qu’il fait.
- Une section
# Erreurs(si elle retourneResult) : dans quelles conditions échoue-t-elle, et quelles variantes d’erreur l’appelant doit-il gérer ? - Une section
# Paniques(si elle peut provoquer une panique) : dans quelles conditions et pourquoi ? - Préconditions (le cas échéant) : que doit être vrai avant d’appeler cela ?
Un commentaire de documentation de trois phrases sur une méthode publique de trait vaut plus pour le prochain implémenteur que cent lignes d’implémentation sans explication. L’implémentation lui indique ce que le code fait. La documentation lui indique ce qu’il est censé faire, ce qui est ce qui compte lorsque les deux divergent.
4.3 Les tests comme retour sur la conception
Le but d’un test n’est pas de produire une coche verte. Le but est de créer un enregistrement précis et exécutable de ce qu’un morceau de code est censé faire : un enregistrement qui échoue bruyamment si ce comportement vient à changer.
Cette distinction est importante car il existe deux types fondamentalement différents de tests, et un seul d’entre eux permet d’atteindre cet objectif.
Un test qui accède à l’état interne d’une struct, définit des valeurs directement, appelle une méthode et fait des assertions sur les valeurs de retour teste l’implémentation. Si l’implémentation change, si le même comportement est obtenu par un mécanisme différent, le test échoue, alors même que rien de ce qui importe à l’utilisateur n’a changé. Cela crée des frictions contre le refactoring sans apporter de sécurité. Un tel test a aussi tendance à réussir alors que le comportement est incorrect, de manières que le test n’avait pas anticipées.
Un test qui construit des valeurs via des interfaces publiques, exerce le comportement par le biais de méthodes publiques et vérifie les résultats observables teste le comportement. Si l’implémentation change mais que le comportement est préservé, le test réussit. Si le comportement change d’une manière qui a de l’importance pour les utilisateurs, le test échoue. C’est ce qui rend possible une refactorisation en toute confiance : les tests vérifient que vous avez obtenu le bon résultat, et non que vous l’avez obtenu d’une manière particulière.
Le principe plus important est le principe diagnostique :
Un test difficile à écrire indique généralement un problème de conception.
Si écrire un test unitaire pour une fonction nécessite de mettre en place une connexion à une base de données, de simuler six dépendances, de construire un objet de configuration complet et de démarrer explicitement un runtime asynchrone, cette fonction en fait probablement trop, dépend de trop de choses, ou se situe au mauvais niveau de l’architecture. Cette difficulté n’est pas une gêne à contourner. C’est un retour d’information. Le test est honnête à propos de quelque chose dont le code n’est pas encore honnête.
Cela se rattache directement à la structure de crates établie par le RFC d’architecture. L’un des objectifs de la décomposition en crates était de créer des composants pouvant être testés de manière isolée. zeroclaw-tool-call-parser devrait être testable avec une entrée &str et sans runtime. zeroclaw-config devrait être testable en construisant directement les structs de configuration. Les implémentations de traits dans zeroclaw-api devraient être testables avec des implémentations factices du trait, et non avec la pile de production complète. Lorsque vous constatez qu’il est impossible de tester un composant sans l’intégralité de son environnement, demandez-vous si une dépendance non prévue par l’architecture ne s’est pas glissée dans l’implémentation. Le test vous donne la réponse ; la question est de savoir si vous l’écoutez.
Une approche pratique pour améliorer la qualité des tests au fil du temps :
- Lorsque vous corrigez un bug, écrivez un test qui l’aurait détecté. Cette habitude, pratiquée de manière constante, oriente la suite de tests vers les modes de défaillance qui comptent vraiment.
- Lorsque vous ajoutez un comportement, écrivez un test qui prouve que ce comportement existe et peut être vérifié de manière isolée.
- Lorsqu’un test est difficile à écrire, prenez le temps de vous demander pourquoi avant de recourir à un mock. La réponse à cette question est généralement plus précieuse que le test que vous étiez sur le point d’écrire.
4.4 Tri de la dette technique
Le mot « dette » est utile car il véhicule la bonne implication : elle produit des intérêts. Une dette laissée sans examen dans une zone très fréquentée de la base de code s’accumule de manière composée : le nouveau code s’adapte à sa présence, de nouvelles hypothèses s’édifient sur les anciennes, et le coût de son traitement augmente à chaque couche ajoutée au-dessus.
L’erreur la plus courante que les équipes commettent avec la dette technique est de la considérer comme binaire : soit tout est de la dette et rien ne peut être fait à ce sujet, soit rien n’est de la dette et aucun temps ne devrait être consacré à cela. Ces deux positions sont erronées. La question utile est : quelle dette, à quel endroit, présente le plus de risque en ce moment ?
Deux axes déterminent la priorité.
Proximité d’une frontière de confiance. Le code qui gère les entrées utilisateur, applique les politiques de sécurité, exécute des outils, gère l’authentification ou traite des données provenant de sources externes opère près d’une frontière de confiance. Des défaillances à cet endroit peuvent être exploitées, corrompre silencieusement l’état du système ou produire un comportement incorrect avec des conséquences sur la sécurité. La dette technique près des frontières de confiance présente un risque disproportionné par rapport à sa taille.
Rayon d’impact. La dette dans zeroclaw-api, la fondation dont tout le reste dépend, a un rayon d’impact plus large que la dette dans l’implémentation d’un seul canal. Une hypothèse erronée dans un type fondamental se propage partout où ce type est utilisé. La dette dans un crate feuille n’affecte que les consommateurs de ce crate.
| Forte impact | Faible rayon d’explosion | |
|---|---|---|
| Près d’une limite de confiance | Adresse dans le cycle actuel | Adresse dans le prochain cycle prévu |
| Loin d’une frontière de confiance | Adresse dans une refactorisation planifiée | Traiter de manière opportuniste, au fur et à mesure que le travail adjacent passe. |
Ce cadre signifie qu’un .unwrap() dans le chemin de vérification de la politique de sécurité n’est pas le même problème qu’un .unwrap() dans un formateur d’affichage CLI. Les deux apparaissent dans le décompte de 5 630. Le décompte nous indique l’étendue. Le triage nous indique la priorité.
Lorsque vous travaillez dans un fichier et que vous remarquez de la dette, un .unwrap() qui représente une erreur opérationnelle non gérée, une fonction qui a grossi au point de gérer quatre préoccupations distinctes, un #[allow(dead_code)] qui fait taire quelque chose que personne n’appelle, vous n’avez pas besoin de tout corriger. Vous devez vous demander : est-ce situé à un emplacement à haut risque ? Si c’est le cas, traitez le problème dans cette PR ou créez un ticket de suivi avec l’emplacement précis, le risque et un responsable proposé. Si ce n’est pas le cas, vous pouvez le marquer avec un commentaire // TODO(debt): <description> qui le rend visible sans le rendre urgent. Ce que vous ne devez pas faire, c’est le laisser complètement non marqué, car c’est par le silence que 5 630 décisions différées s’accumulent sans que personne ne remarque la tendance.
Le patron Strangler Fig s’applique aussi à ce niveau. La RFC d’architecture l’a appliqué au niveau des crates : construire la nouvelle structure autour de l’ancienne, puis migrer vers l’intérieur au fil du temps. Le même patron fonctionne à l’intérieur d’un fichier volumineux. On ne réécrit pas schema.rs en une seule PR. On identifie les fonctions les plus proches des frontières de confiance, les plus fréquemment modifiées ou les plus difficiles à tester, et on les extrait en premier, en améliorant la structure de manière incrémentale, en laissant le reste suivre à un rythme que l’équipe peut soutenir.
4.5 Sécurité au niveau de l’application
La RFC CI/CD a défini la posture de sécurité de la chaîne d’approvisionnement : cargo deny détecte les vulnérabilités connues dans les dépendances, impose la conformité des licences et garantit que les dépendances proviennent de sources approuvées. C’est le système immunitaire de ce qui entre dans le projet. Cette section traite de la posture de sécurité du code qui s’exécute.
cargo deny ne peut pas détecter une vulnérabilité créée par la logique de votre application. Il ne peut pas vous indiquer si les entrées utilisateur sont validées avant d’atteindre votre logique métier. Il ne peut pas vérifier si l’exécution d’un outil respecte le niveau d’autonomie qu’il est censé imposer. Il ne peut pas non plus vous dire si un chemin d’erreur avale silencieusement un échec de vérification de sécurité. Cela nécessite un contributeur qui comprend où se trouvent les limites de confiance et à quoi ressemble un code responsable de part et d’autre de celles-ci.
Trois principes qui devraient guider tout code écrit près d’une limite de confiance :
Les frontières de confiance sont explicites, pas supposées. Une frontière de confiance est tout point où des données arrivent depuis l’extérieur de votre contrôle direct : entrées utilisateur provenant de n’importe quel canal, réponses d’API des fournisseurs, contenus de fichiers du système de fichiers, sorties de plugins, résultats d’outils, mesures matérielles. À chaque frontière de confiance, validez avant de traiter. Ne supposez pas la forme, la taille, le type ou le contenu de données que vous n’avez pas produites. Le modèle de sécurité de ZeroClaw définit ces frontières au niveau de la politique. L’implémentation doit les refléter au niveau du code, non pas parce que la politique échouera, mais parce que la défense en profondeur signifie que chaque couche du système fait sa part, plutôt que de présumer que toutes les autres couches ont fait la leur.
Empreinte minimale. Une fonction qui doit lire un fichier ne devrait pas pouvoir en écrire un. Une implémentation de trait qui gère les messages d’un canal ne devrait pas avoir accès à l’état d’un autre canal. Un outil s’exécutant au niveau d’autonomie 1 ne devrait pas être en mesure d’exercer des capacités qui requièrent le niveau 3. Le modèle de sécurité définit déjà ces contraintes. La discipline consiste à écrire des implémentations qui n’acquièrent pas plus de capacités que ce dont elles ont besoin pour la tâche en cours, et à remarquer lorsqu’une implémentation cherche à atteindre quelque chose en dehors de son périmètre prévu.
Échouez bruyamment à proximité des limites de sécurité. Une erreur dans une vérification de sécurité, une évaluation de politique échouée, un échec de vérification de signature, une tentative d’appel d’outil non autorisée, une non-correspondance de code d’appairage, ne doit jamais être silencieusement ignorée. Elle doit être journalisée, propagée et gérée explicitement. Une erreur dans une fonction d’aide à l’affichage peut être récupérée avec élégance via un message de journal. Une erreur dans un chemin d’autorisation ne le peut pas. Sachez quel type de fonction vous écrivez, et laissez cette détermination guider l’intensité avec laquelle vous faites remonter les échecs qui en proviennent.
Ce ne sont pas des principes de sécurité avancés. Ce sont des règles d’hygiène fondamentales qui s’appliquent à tout code en contact avec quelque chose qu’un utilisateur peut influencer. La RFC d’architecture décrivait le modèle de sécurité comme « réfléchi ». Le travail demandé par cette RFC consiste à rendre cette réflexion lisible au niveau de l’implémentation : dans les fonctions qui valident les entrées, dans les chemins d’erreur qui gèrent les échecs de politique, et dans les frontières entre ce que le système a été chargé de faire et ce qu’il fait réellement.
4.6 L’observabilité comme capacité de débogage
L’infrastructure d’observabilité est mature : traçage OpenTelemetry, métriques Prometheus, suivi DORA et un trait Observer propre sont tous en place. C’est un travail de qualité production. Le manque pédagogique se situe entre le fait de disposer de l’infrastructure et le fait de l’utiliser d’une manière qui aide réellement quand quelque chose tourne mal, idéalement avant de savoir ce qui a mal tourné.
Considérez deux messages de journal. Les deux se compilent. Les deux passent les vérifications CI. Les deux sont syntaxiquement corrects.
#![allow(unused)]
fn main() {
error!(« la requête a échoué »);
}
#![allow(unused)]
fn main() {
error!(
provider = %provider_name,
model = %model_id,
user = %sender_id,
tool = %tool_name,
attempt = attempt,
elapsed = ?elapsed,
err = %e,
« la requête du fournisseur a échoué — les tentatives de retry sont épuisées »
);
}
Le premier est un constat. Il confirme que quelque chose s’est mal passé. Le second est un diagnostic. Il répond aux questions qui comptent : qu’essayions-nous de faire, dans quel contexte, avec quels paramètres, et qu’est-ce qui s’est exactement mal passé. La différence entre les deux n’est pas une question de sophistication technique. C’est de savoir si la personne qui a écrit le message pensait à la personne qui aura un jour besoin de le lire.
La question à se poser avant de rédiger tout message de journal au niveau warn ou supérieur :
Que doit savoir la personne qui doit diagnostiquer cette défaillance au pire moment ?
Cette personne pourrait être vous, dans six mois, sans aucun souvenir d’avoir écrit ce code. Cela pourrait être un autre contributeur qui n’a jamais vu ce module. Cela pourrait être un utilisateur soumettant un rapport de bug avec un extrait de journal qu’il a copié depuis son terminal. Écrivez pour eux. Les champs qui importent presque toujours sont : que cherchions-nous à faire, quel contexte était pertinent à ce moment-là, et qu’est-ce qui a spécifiquement mal tourné.
Le même principe régit la conception des spans de traçage. Une span doit représenter une unité de travail significative, porter le contexte nécessaire pour comprendre ce travail, et avoir un nom pertinent lorsqu’on le lit dans un graphe de flamme ou un visualiseur de traces.
#![allow(unused)]
fn main() {
// Un enregistrement
let _span = span!(Level::INFO, "processus");
// Un diagnostic
let _span = span!(
Level::INFO,
"agent.tool_call",
tool = %tool_name,
turn = turn_number,
sender = %sender_id,
);
}
La journalisation structurée et la conception de spans pertinents ne sont pas des préférences de style. C’est ce qui rend l’infrastructure d’observabilité dont vous disposez réellement utile, non seulement pendant le développement, mais aussi entre les mains d’utilisateurs exécutant ZeroClaw sur du matériel que vous ne verrez jamais, dans des configurations que vous n’aviez pas anticipées, face à des erreurs que vous n’aviez pas prévues. L’infrastructure crée la capacité. La discipline avec laquelle les contributeurs l’utilisent détermine si cette capacité se traduit par des systèmes diagnosticables.
4.7 Travailler au-dessus du sol
Les six disciplines précédentes traitent chacune d’un domaine spécifique. Cette section les synthétise en une vision unifiée de ce à quoi ressemble concrètement le « au-dessus du minimum » : ce qu’un relecteur, un futur contributeur ou un utilisateur vit réellement lorsqu’il rencontre du code conforme aux normes décrites dans cette RFC.
| Dimension | Au sol, les portes passent | Au-dessus du plancher, norme respectée |
|---|---|---|
| Gestion des erreurs | Le code compile ; aucun avertissement Clippy | Les erreurs sont catégorisées ; les erreurs opérationnelles apparaissent avec du contexte ; les paniques sont intentionnelles et documentées. |
| Documentation | Les tests de documentation passent s’ils existent | Chaque élément public peut être compris et utilisé correctement sans avoir à lire l’implémentation. |
| Tests | Les tests qui existent passent | Les tests affirment le comportement ; la difficulté des tests est considérée comme un retour sur la conception ; les modes de défaillance pertinents sont couverts |
| Dette | Aucune erreur ni avertissement du compilateur (avec #[allow] pour masquer le reste) | La dette est étiquetée, localisée et pondérée en fonction du risque ; la dette à haut risque a un propriétaire et un calendrier. |
| Sécurité | cargo deny est passé avec succès | Les limites de confiance sont explicites ; les échecs de sécurité se manifestent de manière visible ; les implémentations respectent leur périmètre prévu. |
| Observabilité | Le code s’exécute et émet quelque chose. | Les messages de journal répondent à la question diagnostique ; les étendues lient des unités significatives de travail avec un contexte utile. |
| Organisation du code | Le fichier compile ; la structure du module existe. | Les fonctions font une seule chose ; les fichiers regroupent les préoccupations liées ; les fichiers volumineux sont des candidats à l’extraction, et non la norme. |
Aucun de ces éléments n’est entièrement réalisable par l’automatisation. Tous peuvent être atteints par des contributeurs qui comprennent leur importance et ont développé le jugement nécessaire pour les appliquer de manière cohérente. C’est précisément l’objectif de ce document.
5. Ce que cela signifie pour le développement assisté par l’IA
La RFC sur la culture abordait la manière de travailler avec les outils d’IA au sein d’une équipe collaborative. Cette section traite d’un sujet plus spécifique : ce qui se passe lorsque le code généré par l’IA est confronté aux normes décrites ci-dessus, et ce qu’il faut pour reconnaître et combler l’écart lorsqu’il ne les respecte pas.
Les outils d’IA sont réellement performants pour franchir les étapes de validation. Ils génèrent du code qui compile, satisfait le vérificateur de types, passe Clippy, et produisent souvent des tests en même temps que l’implémentation. C’est une vraie valeur ajoutée, et il ne s’agit pas ici de la minimiser. Le problème n’est pas que les outils d’IA sont peu fiables. Le problème est qu’ils sont fiables sur le mauvais aspect : produire du code qui passe les vérifications, plutôt que du code qui respecte les normes.
La raison est structurelle. L’IA génère du code en fonction de ce qu’elle peut inférer. Si une fonction n’a pas de documentation, l’IA infère l’intention à partir du nom et de la signature, et parfois cette inférence est correcte, et parfois elle produit un comportement subtilement erroné qui ne se manifeste que dans des conditions que personne n’a testées. Si un type d’erreur n’a pas de documentation indiquant quand il est retourné, l’IA le gère en se basant sur le nom du variant. Si une suite de tests teste l’implémentation plutôt que le comportement, l’IA génère des implémentations qui correspondent à ces tests, lesquelles peuvent ou non correspondre au comportement attendu que les tests étaient censés capturer. Le plafond de qualité des sorties de l’IA est déterminé par la qualité du contexte que vous fournissez. Un meilleur contexte, une documentation plus claire, des types d’erreur plus spécifiques, des tests axés sur le comportement, produisent de meilleures sorties. Un contexte sous-développé produit des sorties qui passent les contrôles et reportent le jugement sur la personne qui les examinera ensuite.
Cela crée une responsabilité spécifique et non optionnelle pour les contributeurs travaillant avec des outils d’IA.
La revue n’est pas facultative parce que c’est l’IA qui l’a écrit. La RFC sur la culture l’a clairement énoncé, et cela mérite d’être répété avec des précisions : lors de la revue de code généré par IA, les questions de validation — est-ce que ça compile, est-ce que les tests passent — sont le début de la revue, pas la fin. Les questions standard sont : ce code gère-t-il correctement les erreurs opérationnelles, ou les traite-t-il avec .unwrap() ? La nouvelle API publique est-elle documentée ? Le test vérifie-t-il le comportement ou l’implémentation ? Ce code est-il proche d’une frontière de confiance, et si oui, valide-t-il ses entrées ? Ces questions relèvent de votre responsabilité, quel que soit l’auteur du code ou les outils utilisés pour le produire.
L’IA amplifie votre jugement, pas son absence. Un contributeur qui n’a pas encore de modèle mental de ce à quoi ressemble une bonne gestion des erreurs acceptera telle quelle la gestion des erreurs générée par l’IA : .unwrap() et tout le reste. Un contributeur qui a intériorisé le §4.1 peut examiner le même résultat et diriger l’outil : « il s’agit d’un chemin d’erreur opérationnel ; utilisez ? et propagez l’échec à l’appelant avec du contexte. » L’outil produira une version corrigée. Le même schéma s’applique à chaque discipline du §4. L’outil est puissant entre les mains de quelqu’un qui sait quoi demander. Sans cette direction, il produit du code qui satisfait le compilateur et reporte les véritables décisions sur la personne suivante dans la chaîne.
Cette relation se renforce dans les deux sens. Une équipe qui comprend les normes tire progressivement davantage de valeur des outils d’IA à mesure que ces outils s’améliorent, car elle peut diriger des outils plus performants avec plus de précision. L’écart entre « ce que l’outil a produit » et « ce que la norme exige » devient quelque chose qu’elle peut combler par des directives plutôt que par une réécriture manuelle. Une équipe qui ne développe pas ce jugement obtient un chemin plus rapide vers le même niveau de qualité plancher, sans la capacité de le dépasser. L’investissement décrit tout au long de ce document est aussi, directement, un investissement dans l’efficacité à long terme de chaque outil d’IA que l’équipe utilisera, car la valeur de ces outils évolue proportionnellement à la clarté du jugement qui les dirige.
6. La portabilité de l’artisanat
La technologie change. Elle change plus vite à chaque itération que la fois précédente, et ce rythme s’accélère. Les outils spécifiques mentionnés dans ce document : Rust, cargo, clippy, le SDK OpenTelemetry, les assistants IA que l’équipe utilise aujourd’hui, seront remplacés. Certains d’entre eux au cours de la durée de vie de ce projet. Les plateformes changeront. Les langages évolueront. L’écosystème d’outillage sera différent dans cinq ans de ce qu’il est aujourd’hui, et différent encore dans dix ans.
Les modèles mentuels dans ce document ne changeront pas.
La question « que doit-il se passer ici en cas d’échec, et qui doit en être informé ? » n’expire pas lorsque le langage change. Vous la poserez dans le prochain langage que vous apprendrez. Vous la poserez lors de la conception d’un système distribué où le « langage » est un protocole de communication. Vous la poserez lorsque vous construirez quelque chose dont d’autres personnes dépendent et que vous ne pouvez pas superviser personnellement. Le mécanisme Rust spécifique pour y répondre : Result<T, E>, l’opérateur ?, les types d’erreurs structurés avec contexte, est une réponse à une question qui existe partout.
La question « quelle est l’interface publique que je promets, et ma documentation reflète-t-elle cette promesse ? » : vous vous la poserez lors de la conception d’une API, lors de la rédaction d’une spécification technique, lors de la définition du périmètre des responsabilités d’une équipe, lors de la communication d’exigences à une autre équipe, à un outil d’IA, à un client, à un prestataire. Le modèle de promesse et de conditions des interfaces publiques s’étend bien au-delà de Rust et bien au-delà du logiciel.
La question « que prouve réellement mon test ? » s’étend au-delà du logiciel à tout domaine où vous devez vérifier qu’un système se comporte comme prévu. L’instinct de la poser, de distinguer entre la preuve que votre implémentation existe et la preuve que la bonne chose se produit, voilà la compétence. La syntaxe pour l’exprimer en Rust est accessoire.
La question « que devrait savoir la personne qui doit diagnostiquer cette panne ? » est une question d’ingénierie qui s’applique à tout ce que vous construisez et dont d’autres personnes dépendent. C’est aussi, à un niveau plus profond, une question d’empathie, qui nous rappelle que la personne de l’autre côté de votre travail est une personne réelle avec un problème réel, à un moment que vous ne pouvez pas prédire, avec un contexte que vous ne serez pas là pour fournir.
Vous n’êtes pas en train d’apprendre Rust. Vous êtes, par l’intermédiaire de Rust, en train d’apprendre à construire des choses dignes de confiance. C’est transférable. Cela se cumulera aussi longtemps que vous le pratiquerez, dans chaque langage, chaque système, chaque équipe et chaque domaine où vous travaillerez.
C’est l’investissement que le projet fait en vous. Non pas dans vos compétences techniques spécifiques, mais dans votre capacité à apporter du jugement, du savoir-faire et du soin à tout ce que vous construirez ensuite. Et c’est, à son tour, l’investissement que vous faites en chaque personne qui, un jour, dépendra de quelque chose que vous avez créé.
7. Ce que cela signifie pour les contributeurs
Si vous êtes nouveau dans Rust ou dans le développement logiciel :
Les sept disciplines du §4 ne sont pas des prérequis à maîtriser avant de pouvoir contribuer. Elles constituent une carte du territoire : des choses que vous rencontrerez au fil de votre travail, nommées suffisamment clairement pour que vous sachiez ce que vous avez sous les yeux lorsque vous les croiserez.
Commencez par la section 4.1. Le modèle mental de gestion des erreurs est l’élément qui offre le plus grand levier d’action à intégrer tôt, et il n’est pas spécifique à Rust. Lorsque vous lisez du code existant et que vous rencontrez .unwrap(), demandez-vous dans laquelle des trois catégories il se situe. Lorsque vous écrivez du nouveau code, posez-vous la même question concernant vos propres choix. Cette habitude unique, pratiquée de manière constante, améliore chaque fichier qu’elle touche et développe un jugement qui vous accompagnera partout.
N’attendez pas de vous sentir prêt pour appliquer ces normes. Appliquez-les de manière imparfaite, posez des questions lorsque vous n’êtes pas sûr de la catégorie à laquelle appartient quelque chose, et considérez les retours que vous recevez lors de la révision comme l’enseignement qu’ils sont censés être. Personne n’est arrivé en sachant tout cela. Cela s’apprend, lentement, à travers exactement ce type de travail que vous effectuez ici.
Si vous utilisez des outils d’IA pour vous aider à contribuer :
Les normes décrites dans ce document sont les critères selon lesquels une revue attentive évaluera le code généré par l’IA. Elles constituent également, en pratique, le contexte qui rend les résultats de l’IA plus corrects avant qu’ils n’atteignent la revue. Avant de demander à une IA d’implémenter quelque chose, vérifiez si les interfaces sur lesquelles elle s’appuiera sont documentées. Si elles ne le sont pas, documentez-les d’abord, ou incluez la documentation dans ce que vous demandez à l’IA de produire. Le résultat sera plus correct, vous aurez comblé une véritable lacune dans les fondations, et le prochain contributeur qui passera par là bénéficiera des deux.
Lorsque vous recevez des commentaires sur du code généré par l’IA, considérez-les comme des retours sur le code lui-même, et non sur votre choix d’utiliser l’IA. Les normes s’appliquent de manière égale, quelle que soit l’auteur. La question est toujours : ce code respecte-t-il les normes ? Si ce n’est pas le cas, qu’est-ce qui doit être modifié et pourquoi ?
Si vous examinez des pull requests :
Les questions de validation — est-ce que ça compile, les tests passent-ils, Clippy l’accepte-t-il — constituent le plancher, pas le plafond. Une revue qui ne répond qu’à ces questions est une revue incomplète. Utilisez le cadre du §3 et les disciplines du §4 pour structurer vos observations. Nommez le standard que vous appliquez, expliquez pourquoi il est important, et séparez clairement les préoccupations bloquantes des suggestions non bloquantes.
L’objectif d’une revue n’est pas de trouver des fautes. C’est de transférer de la compréhension. Chaque retour spécifique accompagné d’une explication, « ceci est un chemin d’erreur opérationnel ; voici pourquoi .unwrap() crée ici un risque en production et ce qu’il faut utiliser à la place », est un investissement dans le contributeur dont vous relisez le travail. Cet investissement se cumule. Le contributeur qui comprend le principe l’appliquera correctement aux dix prochaines situations où il compte, sans qu’on ait besoin de le lui redire.
Si vous êtes un mainteneur ou un contributeur plus expérimenté :
Vous êtes le mieux placé pour rendre ces normes concrètes, non pas en les imposant d’en haut, mais en les illustrant dans votre propre code et en les nommant explicitement lors des revues. L’enseignement le plus efficace dans un projet open source se fait dans les fils de discussion des PR et les commentaires de code, pas dans les documents. Ce document fournit le vocabulaire. C’est son utilisation systématique dans les revues quotidiennes qui le fait passer de simples mots sur une page à une pratique partagée.
Lorsque vous voyez un .unwrap() sur un chemin d’erreur opérationnel, nommez-le comme tel. Lorsque vous voyez une fonction publique sans documentation, posez la question : que doit savoir un futur implémenteur ici ? Lorsque vous voyez un test qui échouerait lors d’un refactoring valide, expliquez pourquoi cela compte. Ce ne sont pas des corrections : c’est le mentorat continu que la RFC sur la culture a identifié comme l’une des choses les plus importantes qu’un contributeur plus expérimenté puisse offrir.