Ce que vous saurez faire
- Définir des noms de règles figés et un auditeur qui ne fait que signaler, renvoyant page, règle et détail, consignés sous forme de bugs dédoublonnés.
- Enregistrer la requête des bugs ouverts comme pool et choisir l'exécuteur qui y puise.
- Écrire un environnement isolé au moindre privilège : un seul dépôt, des listes d'outils autorisés, des écritures limitées à sa propre tâche, des références d'identifiants, un plafond de répartition.
- Orienter les bugs vers des voies de réparation et une voie d'attente, et vérifier chaque écriture par un nouveau lint avant de fermer.
- Tenir un registre de prévention qui transforme les constats récurrents en contrôles à l'écriture.
Points clés
- Un agent IA d'autoréparation de site web lit ce que reçoit un lecteur, ouvre un bug pour chaque défaut et ne répare que ce qu'il peut réécrire via l'API du CMS puis revérifier.
- Séparez la détection de la correction : un balayage qui ne fait que signaler ouvre des bugs, et chaque bug a sa propre exécution de réparation dans son propre environnement isolé.
- C'est le mécanisme qui décide de la sécurité : un pool décide de ce qui est traité, l'environnement de ce que l'agent peut toucher, le workflow du moment où c'est terminé.
- Une réparation ne compte qu'une fois sa revérification réussie : un nouveau lint propre de l'article enregistré, un tampon de vérification qui a avancé, ou un HTTP 200 avec le contenu propre de la page ; tout ce que l'agent ne peut pas vérifier est mis de côté pour une personne.
- Un défaut qui revient sans cesse relève d'un refus à l'écriture, pas du balayage de la semaine suivante.
Ce que fait la boucle du site web autoréparateur
Un site web ne se répare lui-même que là où l'agent peut prouver la correction, et nous avons construit tout le mécanisme autour de cette limite. Notre agent IA d'autoréparation balaie le site en ligne chaque semaine, ouvre un bug pour chaque défaut et envoie chaque bug vers sa propre exécution dans un environnement isolé. Cette exécution réécrit ce qu'elle peut via l'API du CMS, revérifie la page enregistrée et ne ferme le bug que si la vérification est propre. ConvOps fait tourner la planification, la file de bugs et les deux workflows. C'est l'une des boucles sur lesquelles tourne notre entreprise.
Un site web autoréparateur est un site où un agent détecte les défauts visibles par les lecteurs et répare ceux qu'il peut vérifier, en mettant le reste de côté pour une personne. Ce n'est pas une suite de tests autoréparatrice : celles-ci réparent les sélecteurs des tests, alors que cette boucle répare le contenu que voit un lecteur.
Chaque écran et chaque chiffre ci-dessous utilisent des données d'exemple de Shutterlane, un site fictif de tests de matériel photo tenu par deux personnes, à l'adresse shutterlane.example.com.
| Élément | Ce que c'est |
|---|---|
| Déclencheur | Une planification hebdomadaire, chaque mardi à 5 h UTC |
| Entrées | Les pages en ligne, l'API du CMS, la base de données d'entités derrière les pages de modèles et du répertoire |
| Composants | Le balayage, le pool de bugs, l'exécuteur et son environnement isolé, le workflow de réparation par bug |
| Sorties | Des bugs, des réparations, des bugs mis en attente, des propositions de prévention, un journal d'exécution dans git |
| Périmètre | Réécrit absolute-self-link, dead-link et encoding-artifact sur les articles. Revérifie freshness et reader-error. Met en attente counter-sanity, vocab-drift et toute règle sur un type de page qu'il ne peut pas modifier |

Le balayage (repère 1) consigne les constats (2), les compare au registre de prévention (3) et répartit les bugs ouverts (4). Chaque bug est réparé selon sa voie (5), vérifié (6), puis fermé ou mis en attente (7).
Pourquoi nous l'avons construite : un agent IA qui corrige les bugs de contenu d'un site
Un agent de QA qui se contente de signaler produit du bruit. Un agent qui détecte et corrige dans la même exécution corrige sa propre copie. Nous avons séparé les deux.
Notre balayage ne faisait au départ que signaler. Il retrouvait chaque semaine les mêmes liens cassés et les mêmes pages périmées, et personne ne se chargeait de la correction. Le graphique montre ce schéma sur les données de Shutterlane : un bug est ouvert (repère 1), reçoit une note de récurrence chaque mardi (2) et n'est jamais réparé (3).

Trois principes en sont ressortis :
- Détecter et corriger sont deux tâches distinctes. Le balayage n'écrit jamais de contenu, et la réparation ne juge jamais le site.
- Un défaut, une unité de travail. Chaque nouveau constat devient son propre bug, et chaque exécution de réparation prend en charge exactement un bug.
- Terminé veut dire vérifié. Un bug n'est fermé qu'après une revérification de la page enregistrée, jamais sur la parole de l'agent.
Si vos rapports de QA s'empilent de la même façon, découvrez comment ConvOps transforme les constats en bugs que des exécuteurs prennent en charge un par un(s’ouvre dans un nouvel onglet).
Comment elle tourne : pool, exécuteur, environnement, workflow
Le modèle est la partie la moins intéressante. Le pool décide de ce qui est traité, l'environnement de ce que l'agent peut toucher, le workflow du moment où c'est terminé. Deux workflows portent le travail : le workflow de balayage, WF-qa, et le workflow de réparation, WF-bugfix. C'est un graphe d'étapes et de contrôles, la forme que nous décrivons dans Qu'est-ce que le graph engineering ?, la même boucle contrôlée et planifiée que nos expériences SEO avec Claude Code, et la réponse à la prolifération d'agents.

Les constats deviennent des bugs dans un pool
Un pool est une requête enregistrée dans ConvOps : un filtre sur le type de tâche, les tags, le projet, l'horizon et le statut, plus un tri. Il ne contient jamais de tâches ; il se résout en tâches correspondantes au moment où on l'interroge, de sorte que les bugs de n'importe quel projet arrivent dans chaque pool qui leur correspond. pools_next renvoie la tâche placée en tête, départage les égalités par identifiant de tâche et enregistre une ligne de prélèvement par appel : chaque prélèvement est donc auditable.
Le pool open-qa-bugs de Shutterlane est type = bug AND tags contains qa-finding AND status in [backlog, todo], du plus ancien au plus récent (repère 1).
Les exécuteurs prennent le travail en charge
Un exécuteur est un exécutant nommé, éventuellement rattaché au pool dans lequel il puise (repère 2). Il en existe exactement deux sortes :
| Type | Comment s'exécute une répartition |
|---|---|
| Isolé | ConvOps lance Claude Code ou OpenCode, dans une version de son catalogue, comme un Job Kubernetes à part entière |
| Local | Un agent de code sur une machine, comme Claude Code ou Kimi Code CLI, se connecte à ConvOps, récupère l'enveloppe de répartition et exécute la tâche sur place |
Notre boucle tourne sur un exécuteur Claude Code isolé, désigné dans la planification. L'étape de répartition du balayage exécute elle-même la requête au format du pool et envoie chaque bug à cet exécuteur ; rattacher l'exécuteur à un pool déplace ce même prélèvement dans ConvOps. Une exécution bloquée est arrêtée au bout de time_limit_s (par exécuteur, de 60 à 86 400 secondes, sinon le réglage de l'espace de travail : 14 400 ici).
Les environnements isolés limitent ce que l'agent peut toucher
Un environnement isolé est la définition écrite de tout ce qu'une exécution peut toucher. Chaque exécution est un Job Kubernetes, créé en pause ; un Secret propre à l'exécution, rattaché au Job, est ajouté avant son démarrage. Un volume de tâche conserve le dossier de travail de la tâche d'une exécution à l'autre. Le Job est supprimé 300 secondes après sa fin et le Secret disparaît avec lui : les identifiants ne survivent jamais à l'exécution.

- Dépôts. Un seul reçoit le travail et il est toujours poussé (repère 1) : directement sur la ref extraite, rejoué une fois, jamais en force.
- Règles d'outils. Le serveur du CMS refuse tout par défaut et autorise 8 outils (repère 2). Le navigateur n'autorise que des outils de lecture : navigation, instantané, capture d'écran et trois autres.
- Des références, pas des valeurs.
CMS_API_TOKENpointe vers une entrée du gestionnaire de secrets (repère 3), et l'identifiant de l'exécuteur est lui aussi une référence enregistrée (repère 4). Le repère 5 est le rattachement au pool. - Droits ConvOps. Les écritures de tâches n'atteignent que la tâche de l'exécution. Les notes et les lectures atteignent n'importe quelle tâche, si bien que le balayage peut annoter les bugs, mais seule une exécution de réparation ferme son propre bug.
- Limites de répartition.
run_dispatch_limitvaut 10 par exécution, ce qui borne le coût et le rayon d'impact d'un balayage.run_dispatch_named_environmentvaut false : une exécution ne peut pas élargir le bac à sable de ce qu'elle répartit.
Deux workflows : l'un détecte, l'autre corrige
| # | Étape du balayage | Exécutée par | Condition |
|---|---|---|---|
| 1 | recall-scope | Agent d'exécution | Pas d'hôte cible : ouvrir un bug d'exécution en échec et s'arrêter |
| 2 | scan-audit | qa-auditor, signalement seul | Sept noms de règles figés. Une lecture en échec est un reader-error |
| 3 | file-findings | Agent d'exécution | qa-dedupe sur (page, rule) : un nouveau constat ouvre un bug, une récidive ajoute une note |
| 4 | prevent | Agent d'exécution | Fuite ou lacune : une prevention-proposal par règle |
| 5 | dispatch-bugs | Agent d'exécution | Du plus ancien au plus récent, arrêt à la limite de répartition |
| 6 | finalize | Agent d'exécution | Committer le journal d'exécution, enregistrer une mémoire |
| # | Étape de réparation | Exécutée par | Condition |
|---|---|---|---|
| 1 | read-bug | Agent d'exécution | Choisit la voie. hold passe à blocked et s'arrête |
| 2 | heal-post | Agent d'exécution | Une écriture protégée par version, puis un nouveau lint propre |
| 3 | heal-freshness | verifier | Tampon général à la date de création du bug ou après |
| 4 | heal-reader | Agent d'exécution | HTTP 200 avec le contenu propre de la page |
| 5 | close | Agent d'exécution | Réparé : terminé. Sinon blocked avec la raison |
L'auditeur lit les pages comme un lecteur les reçoit : certaines rendues dans un navigateur, les autres en HTML brut, avec les compteurs et la fraîcheur recoupés avec la base de données. La promesse de fraîcheur est de 7 jours pour les modèles d'appareils photo et de 14 pour les entrées du répertoire, la cadence de leurs boucles de vérification.


La planification (repère 1) est FREQ=WEEKLY;BYDAY=TU;BYHOUR=5;BYMINUTE=0. Le rythme hebdomadaire correspond à la promesse de fraîcheur de 7 jours : un constat est encore d'actualité quand sa réparation s'exécute.
Une exécution, étape par étape : un bug, du constat à la correction vérifiée
Le plus intéressant dans une réparation, c'est la vérification après l'écriture, pas l'écriture. Voici le balayage qa/2026-09-15 de Shutterlane, de la planification au verdict.
Mardi 5 h UTC : le balayage détecte et consigne
Le balayage tourne sur isolated-sonnet dans un seul Job avec shutterlane-qa. L'auditeur lit 24 pages (6 dans le navigateur, 18 en HTML brut) et renvoie 7 constats, un par règle.

Ce constat est nouveau : il devient le bug demo0101, absolute-self-link: /blog/best-travel-cameras-2026, statut todo. L'exécution consigne qa-dedupe: 5 novel, 2 recurrences ; chaque récidive ajoute une note à son bug ouvert.
L'étape de prévention lit le registre. absolute-self-link est covered et l'article a 3 jours, soit dans la fenêtre de fuite de 7 jours : le balayage ouvre donc l'idée demo0110 comme prevention-proposal.
La répartition liste les bugs de QA ouverts, du plus ancien au plus récent : 7, sous la limite de 10. Chacun part vers isolated-sonnet sans environnement désigné, et reçoit donc l'environnement par défaut de son projet.
Un bug, une exécution

demo0101 reçoit son propre Job, run-demoex01, et son propre volume. read-bug choisit la voie selon le type de page et la règle : un lien vers soi-même sur une page /blog/ relève de post. Il écrit bugfix-demo0101/2026-09-15 lane=post avant de toucher quoi que ce soit.
Une seule écriture protégée

heal-post lance post-lint, qui désigne la cible fautive et sa correction. Il effectue ensuite un seul remplacement ancré body_md_edits, protégé par l'expected_version qu'il a lue. Il ne transmet jamais status : une réparation ne peut donc jamais publier ni dépublier une page.
En cas de conflit de version, l'agent relit une fois et reconstruit ; un second refus se termine en not healed. Un lien mort sans adresse connue est retiré et son libellé conservé. Retirer un lien est sans risque ; deviner une cible ne l'est pas.
Réparé, ou mis en attente

L'agent relit l'article enregistré et repasse le lint. Réparé signifie que la règle n'a plus aucun constat ET que la cible fautive a disparu du corps enregistré, car le lint peut manquer une cible que l'auditeur a vue. La note indique healed: https://shutterlane.example.com/models/orrin-k5 -> /models/orrin-k5, le journal d'exécution est committé, le bug est terminé, et le Job et le Secret disparaissent 300 secondes plus tard.
À droite, demo0104 (counter-sanity: /news) arrive dans hold. Il passe à blocked, « nécessite une correction produit ou opérateur », contenu intact.
À quoi ressemble la sortie : rapport, notes, registre
Lisez le balayage par statut, pas par nombre. Une récidive sur une règle couverte est un bug de votre garde-fou, pas de votre contenu.

| Artefact | Colonnes | Comment le lire |
|---|---|---|
| Rapport de balayage | page, règle, détail, nouveau ou récidive, voie | Les lignes nouvelles sont de nouveaux bugs. Les récidives sont des notes sur des bugs ouverts |
| Fil de notes du bug | identifiant d'exécution, voie, healed: ou not healed: avec une raison | La décision d'une exécution, lisible sans la transcription |
| Registre de prévention | règle, covered / partial / uncovered, empêchée par, voie de réparation | L'endroit où chaque règle est arrêtée avant d'atteindre le site |
Deux signaux pilotent l'étape de prévention :
- Fuite : une règle couverte sur un article
/news/ou/blog/publié depuis moins de 7 jours. Seul un article récent prouve que le garde-fou à l'écriture l'a laissé passer. - Lacune : une règle partielle ou non couverte sur 2 pages ou plus dans une même exécution, ou qui est revenue. Une page, c'est un défaut ; deux pages ou une récidive, c'est un schéma.
Chaque règle reçoit une seule proposition ; une proposition ouverte reçoit une note, jamais une seconde idée.
Sur le rapport de Shutterlane, encoding-artifact est covered et pourtant revenu sur /directory : le garde-fou fuit par un ancien chemin de publication. Nous avons rencontré ce schéma, et il a produit un second garde-fou, post-lint à l'étape de publication, en plus des refus à l'écriture dans les outils du CMS. Chaque journal d'exécution arrive dans git, la trace que nous décrivons dans l'observabilité des agents IA.
Ce qui tourne mal : une règle, trois orthographes
La plupart de nos échecs venaient de la plomberie et des droits, pas du modèle. Le pire ressemblait à une boucle qui fonctionne.
Le dédoublonnage s'appuie sur (page, rule). Notre auditeur écrivait les noms de règles librement et, d'une exécution à l'autre, orthographiait un même contrôle de trois façons. Le dédoublonnage voyait trois règles et ouvrait trois bugs pour un seul défaut. Sur les données de Shutterlane : dead-link, broken-link et dead-internal-link sur /news/corvane-x2-firmware-3 sont devenus demo0081, demo0084 et demo0087.

La règle qui en est sortie tient en une ligne dans la fiche de l'auditeur : « rule est exactement l'un de encoding-artifact, dead-link, absolute-self-link, counter-sanity, vocab-drift, freshness, reader-error ; jamais une variante. » Désormais, un lien correspond à un bug, avec une note de récurrence par exécution.
| Échec mineur | Règle qui en est sortie |
|---|---|
| Une exécution n'atteignait que sa propre tâche, et ne pouvait donc ni fermer ni annoter d'autres bugs | Droits par environnement : notes et lectures sur toute tâche, tasks_dispatch et tasks_list activés, écritures limitées à sa propre tâche, répartition plafonnée à 10 |
| Un contrôle portant uniquement sur les prix ne faisait pas avancer le tampon de fraîcheur général d'une entité | Une réparation de fraîcheur exige un contrôle content ou status ; réparé signifie que last_verified_date a avancé |
| Le dédoublonnage correspondait à la propre ligne de journal de l'exécution et écartait tous les constats | Un enregistrement du corpus identique aux constats entrants est ignoré, jamais mis en correspondance |
Construisez la vôtre : la version minimale
Commencez par la voie d'attente et les droits sur les outils. Décidez de ce que l'agent ne doit jamais toucher avant de le laisser toucher quoi que ce soit.

Gardez le script de lint hors réseau : le nôtre juge les liens d'après la table des routes et les listes d'entités, si bien que son verdict se reproduit à l'identique. La voie d'attente est le contrôle humain décrit dans Concevoir des systèmes d'IA avec humain dans la boucle. La table des voies, prête à copier :
lanes:
post: # rewrite through the CMS API, then re-lint
rules: [absolute-self-link, dead-link, encoding-artifact]
pages: ["/blog/<slug>", "/news/<slug>"]
freshness: # re-verify; healed when the general stamp moves
rules: [freshness]
pages: ["/models/<slug>", "/directory/<slug>"]
reader: # re-read; healed on HTTP 200 with the page's own content
rules: [reader-error]
hold: # everything else: blocked, a person fixes it
rules: ["*"]
L'environnement, prêt à copier :
environment: shutterlane-qa
repos:
- repo: shutterlane/site-ops
receives_work: true
push_target: ref
mcp_servers:
shutterlane-cms:
default: deny
allow: [post_get, post_list, post_update,
translations_manage, model_get, tool_get,
verification_log_manage, verdict_history]
playwright:
default: deny
allow: [browser_navigate, browser_snapshot,
browser_take_screenshot, browser_console_messages,
browser_wait_for, browser_close]
convops_tools_any_task: [task_notes_add, task_notes_list, tasks_get]
run_dispatch_limit: 10
run_dispatch_named_environment: false
secrets:
CMS_API_TOKEN: {kind: gcp-sm, ref: demo-project/cms-token}
Copiez la table des voies et la définition de l'environnement, puis planifiez votre balayage hebdomadaire dans ConvOps(s’ouvre dans un nouvel onglet). Vous voulez que cela tourne sur votre propre site ? Réservez une séance de découverte gratuite.
Étapes
Figez vos noms de règles
Listez les identifiants de règles exacts que votre auditeur peut renvoyer et interdisez toute variante, pour que le dédoublonnage sur la page et la règle continue de fonctionner d'une exécution à l'autre.
Faites tourner un auditeur qui ne fait que signaler
Faites-lui lire les pages comme un lecteur les reçoit et renvoyer un constat par défaut, avec page, règle et détail. Il n'écrit jamais de contenu.
Dédoublonnez sur la page et la règle
Un nouveau constat devient un bug intitulé règle : page. Une récidive ajoute une note au bug ouvert au lieu d'en créer un second.
Enregistrez la requête des bugs ouverts comme pool
Filtrez sur le type bug, votre tag de QA et le statut backlog ou todo, triés du plus ancien au plus récent, pour que chaque prélèvement soit la même requête déterministe.
Définissez l'environnement isolé
Un seul dépôt qui reçoit le travail, le serveur MCP du CMS avec une liste d'outils autorisés, un navigateur en lecture seule, des écritures limitées à la propre tâche de l'exécution, des identifiants sous forme de références et une limite de répartition.
Définissez l'exécuteur
Choisissez l'agent de code et sa version, le modèle et une référence d'identifiant, puis rattachez-le au pool ou désignez-le dans la planification.
Écrivez le workflow de réparation avec une voie d'attente
Orientez chaque bug vers une voie selon sa règle et le type de page. Tout ce que vous ne pouvez pas réécrire et revérifier part en attente et est bloqué avec sa raison.
Faites une seule écriture protégée, puis repassez le lint
Écrivez une seule fois avec la version que vous avez lue et ne modifiez jamais le statut. Ne fermez le bug que lorsque le nouveau lint est propre et que la cible fautive a disparu.
Tenez un registre de prévention
Marquez chaque règle comme couverte, partielle ou non couverte, et transformez les fuites et les récidives en refus à l'écriture dans votre CMS.
Planifiez le balayage chaque semaine
Faites-le tourner à jour et heure fixes, et laissez son étape de répartition envoyer les bugs ouverts, du plus ancien au plus récent, jusqu'à la limite de répartition.
Questions fréquentes
Qu'est-ce qu'un site web autoréparateur ?
Un site web autoréparateur est un site où un agent IA lit les pages comme un lecteur les reçoit, ouvre un bug pour chaque défaut, répare ce qu'il peut réécrire et revérifier, et met le reste de côté pour une personne. ConvOps fait tourner le balayage hebdomadaire, le pool de bugs et le workflow de réparation par bug. Ce n'est pas une suite de tests autoréparatrice, qui répare les sélecteurs dans des tests automatisés.
À qui s'adresse une boucle de site web autoréparateur ?
Une boucle de site web autoréparateur s'adresse aux petites équipes qui gèrent un site de contenu via l'API d'un CMS : fondateurs, équipes contenu et marketing, et petites équipes techniques. ConvOps planifie le balayage hebdomadaire, et le balayage répartit une exécution de réparation par bug : liens cassés, artefacts d'encodage et pages d'entités périmées sont réparés et revérifiés chaque semaine. Les écarts de compteurs et les dérives de vocabulaire arrivent à une personne sous forme de bugs bloqués qui en indiquent la raison.
En quoi un site web autoréparateur diffère-t-il des tests autoréparateurs ?
Les tests autoréparateurs réparent les sélecteurs cassés dans une suite de tests pour que les tests automatisés continuent de passer. Une boucle de site web autoréparateur dans ConvOps répare le contenu qu'un lecteur voit sur les pages en ligne : liens, encodage et faits périmés. Elle tourne sous forme de workflows planifiés qui écrivent via l'API du CMS, revérifient la page enregistrée et mettent de côté pour une personne tout ce qu'ils ne peuvent pas vérifier.
Comment détecter et corriger automatiquement les liens cassés de mon site web ?
Ajoutez le serveur MCP de ConvOps, https://mcp.convops.app/, à votre client IA et connectez-vous une fois. Créez ensuite un workflow de balayage hebdomadaire dont l'auditeur renvoie page, règle et détail pour chaque lien cassé, et ouvrez un bug pour chaque nouveau constat. Envoyez chaque bug vers une exécution de réparation qui réécrit le lien vers son adresse connue, ou le retire, et repasse le lint sur la page enregistrée avant de fermer le bug.
Un agent IA peut-il corriger les bugs d'un site web sans relecture humaine ?
Oui, pour les défauts qu'il peut réécrire et vérifier. Dans ConvOps, le workflow de réparation réécrit trois règles de liens et d'encodage sur les articles via l'API du CMS, et ne ferme un bug qu'après un nouveau lint propre. L'agent ne publie ni ne dépublie jamais une page. Les écarts de compteurs et les dérives de vocabulaire vont dans une voie d'attente, où le bug est bloqué avec sa raison et attend une personne.
Comment des agents IA prennent-ils en charge les bugs d'une file ?
Dans ConvOps, un pool est une requête enregistrée sur le type de tâche, les tags, le projet, l'horizon et le statut, qui se résout en tâches correspondantes au moment où on l'interroge. L'appel pools_next renvoie la tâche placée en tête selon le tri du pool et enregistre le prélèvement. Un exécuteur isolé ou local exécute chaque bug réparti, et chaque exécution de réparation prend en charge exactement un bug.
Comment isoler dans un bac à sable un agent IA qui modifie votre site web ?
ConvOps exécute chaque répartition isolée comme un Job Kubernetes à part entière, avec un Secret propre à l'exécution qui disparaît avec le Job. La définition de l'environnement désigne un seul dépôt qui reçoit le travail, des serveurs MCP avec des listes d'outils autorisés, des écritures de tâches limitées à la propre tâche de l'exécution, et une limite de 10 répartitions par exécution. Les identifiants sont stockés sous forme de références, jamais de valeurs.
Qu'est-ce qui empêche un agent IA d'appliquer une mauvaise correction sur mon site ?
ConvOps exécute la réparation comme un workflow avec un contrôle après chaque écriture. L'agent effectue une seule écriture par article, protégée par la version qu'il a lue, et ne modifie jamais le statut de l'article. En cas de conflit, il relit une fois, et un second refus se termine en échec de réparation. Un lien mort sans adresse connue est retiré, pas deviné, et le bug n'est fermé qu'après un nouveau lint propre.
