ADR-004 : Propagation des mises à jour CAL vers le catalog providers
Statut
Accepté — 2026-04-16
Contexte
Le 16/04/2026, Charles-Albert Lehalle (CAL) a posé par email une question d'apparence anodine :
« si tu pense qu'il y a une meilleure façon de la [liste des datasets] mettre à jour qui se propage dans ton système »
Il a demandé cela parce qu'il sent — à raison — que son rythme d'édition sur
son Google Doc Datasets pipeline for MaQI.docx (partagé via
~/gdrive/cal-shared/) est plus rapide que notre rythme de curation vers
docs/providers/catalog.yaml (28 entrées) et les
21 fiches docs/providers/<id>.md.
Le pipeline actuel est :
flowchart LR
gdoc["Google Doc<br>Datasets pipeline for MaQI"]
rclone["~/gdrive/cal-shared/<br>(rclone mount)"]
sync["scripts/sync-cal-docs.sh<br>pandoc, hash-keyed"]
cal["docs/cal/datasets-pipeline.md<br>(mirror, read-only)"]
curation(("curation<br>Emmanuel"))
yaml["docs/providers/catalog.yaml<br>(28 entrées typées)"]
fiches["docs/providers/<id>.md<br>(21 fiches)"]
gdoc --> rclone --> sync --> cal --> curation
curation --> yaml
curation --> fiches
style gdoc fill:#eef,stroke:#448
style curation fill:#fed,stroke:#c60
style yaml fill:#dfd,stroke:#0a0
style fiches fill:#dfd,stroke:#0a0
Coût observé à ce jour : ~30 min de curation humaine par re-sync, dont l'essentiel est du diff-against-memory ("qu'est-ce qui a changé depuis la dernière fois ?").
Une délibération inter-personas (5 personas : Jobs, Torvalds, Shannon, Feynman, Godin) a examiné 7 options (A–G) et identifié les convergences et divergences suivantes.
Ce sur quoi le panel a convergé
- Le vrai bottleneck est la curation, pas le transport. Le sync prend quelques secondes ; la compréhension du delta prend des dizaines de minutes.
- CAL ne doit rien changer à sa pratique. Son Google Doc reste son espace, éditable en continu, partagé avec qui il choisit.
- Option E (formulaire web qui commit le YAML en son nom) : rejetée unanimement — elle détruit l'acte d'auteur et demande une infra injustifiée pour un débit réel de < 1 bit/jour (Shannon).
- Option C comme workflow backbone (watcher gdrive qui alerte Emmanuel en temps réel) : rejetée — solves transport, transport isn't the problem (Feynman) ; surveillance dressed as workflow (Godin).
- Option B (GitHub issue template pour CAL) : rejetée — CAL n'est pas développeur et n'adoptera pas GitHub comme canal.
- Un ADR + un workflow écrit (option A) est un no-regret implicite pour tous.
Ce qui divisait le panel
- Faut-il mesurer avant de construire ? Feynman argue que la fréquence d'édition de CAL (~5 fois/an, empirique) peut rendre toute construction > 2 h un net loss. Les autres estiment que l'intervention proposée coûte moins cher que la mesure elle-même.
- F (reverse feed CAL valide) : pour Godin c'est le cadeau relationnel, pour Jobs c'est inverser la charge sur CAL. La tension se résout par la cadence : F-lourd (PR queue) = fardeau, F-léger (résumé unidirectionnel d'Emmanuel, CAL répond quand il veut) = cadeau.
- D (section novelties dans le doc CAL) : Shannon la prescrit au
ratio signal/coût, Jobs la reframe à 1 caractère (
⭐), Feynman la rejette comme homework déguisé. Résolution : convention opt-in, jamais un champ obligatoire. - Quelle est la nature de
catalog.yaml? Miroir du doc CAL (Torvalds), projection typée stable (ADR-002), ou travail à forte valeur ajoutée d'Emmanuel/Wissal qui utilise le doc CAL comme source d'intention (Jobs, Shannon, Godin) ? — cette divergence est tranchée ci-dessous (§2.1).
Décision
1. Reformulation ontologique : catalog.yaml est une projection, pas un miroir
Le doc CAL est la source d'intention ; catalog.yaml est le travail
curaté d'Emmanuel (et demain Wissal). La relation est asymétrique par
design :
- CAL écrit en continu, en narration libre. Il n'est pas tenu de produire de structure.
- Le YAML est enrichi à la main — en s'appuyant sur le doc, sur les emails de CAL, sur les échanges hors-repo.
- La drift entre les deux est une information utile, pas une anomalie à corriger immédiatement.
Corollaire : on n'essaie plus de maintenir le YAML synchrone avec le doc CAL. On maintient la visibilité de la drift, et on la résorbe à la cadence humaine.
Cette reformulation est cohérente avec ADR-002 §1 (catalog.yaml comme « table des matières machine-lisible » et squelette enrichi), et la précise sur le point où ADR-002 restait implicite.
2. Stack opérationnelle en 4 couches
| # | Couche | Coût setup | Qui agit | Quand |
|---|---|---|---|---|
| L1 | Extension sync-cal-docs.sh : émet un diff + drift report à chaque re-sync | ~2 h Emmanuel | script | à chaque re-sync |
| L2 | Cet ADR + mise à jour docs/workflows.md avec la boucle CAL → sync → drift report → curation → reverse-feed email | ~1 h Emmanuel | humain | à l'acceptation de l'ADR |
| L3 | Reverse-feed unidirectionnel léger : Emmanuel envoie à CAL un email \(\leq\) 10 lignes "voici ce qu'on a extrait" après chaque re-sync notable | ~5 min / re-sync | Emmanuel | dès la 1re re-sync post-ADR |
| L4 | Mesure passive : sur 8 semaines (2026-04-16 \(\to\) 2026-06-16), on logge le nombre d'édits CAL, le nombre d'emails CAL \(\to\) Emmanuel, le temps de curation réel | ~0 | passif | décidé à 8 semaines |
2.1 — Couche L1 : contenu du drift report
scripts/sync-cal-docs.sh est étendu pour émettre, à chaque re-sync qui
modifie docs/cal/datasets-pipeline.md, un fichier
docs/cal/.sync-report.md contenant :
- Diff unifié (ancien \(\leftrightarrow\) nouveau mirror) tronqué à 200 lignes, plein
en pièce jointe
.prev-*.mdgitignorée. - Nouveaux headings (
###sous sections taxonomiques) présents dans le nouveau mirror mais absents decatalog.yaml\(\to\) candidats nouveaux providers. - Entrées YAML orphelines : IDs de
catalog.yamldont lenamene paraît plus dans le mirror \(\to\) candidats reclassements ou retraits. - Timestamp de la re-sync.
Le .sync-report.md est commité (il fait partie de la mémoire du
dépôt, il n'est pas ré-écrit sans être versioné). Les .prev-*.md sont
gitignorés (historique uniquement local ; le git log suffit comme
archive).
Le script reste idempotent (pas de re-sync si le hash n'a pas changé, pas de drift report si pas de diff).
2.2 — Couche L3 : format du reverse-feed
À chaque re-sync non-triviale, Emmanuel envoie à CAL un email bref de la forme :
Sujet : MaQI — datasets pipeline, résumé du sync YYYY-MM-DD
Bonjour Charles-Albert,
J'ai re-synchronisé ton doc. Voici ce qu'on en a extrait :
- Nouveaux providers détectés : <X, Y> (intégrés dans catalog.yaml).
- Providers dont le statut a changé : <Z : to_buy → owned>.
- Points d'ambiguïté à ton avis si tu as 2 min :
- <question 1>
- <question 2>
Le catalogue courant : https://github.com/eserie/MaQI/blob/main/docs/providers/catalog.yaml
Merci — pas besoin de répondre si tout te convient, on part de là.
Trois invariants :
- \(\leq\) 10 lignes, factuel.
- Pas de question bloquante — l'absence de réponse est acceptable et doit rester acceptable pour que la cadence reste respectueuse.
- Le lien pointe vers la version committée du YAML, pas un brouillon — CAL voit l'état stable.
2.3 — Couche L2 : convention opt-in légère pour CAL
Proposée dans le premier reverse-feed email (L3) et documentée dans
docs/workflows.md, sans jamais être un champ obligatoire :
Si tu veux signaler une nouveauté notable dans ton doc, tu peux préfixer le nom du provider par
[NEW]ou⭐— c'est un simple indice pour notre curation, jamais une contrainte de format.
Le drift report (L1) détecte les nouveaux providers même sans ce marqueur. La convention ne remplace pas l'automatisation ; elle la complète quand CAL sent le besoin de hiérarchiser.
3. Options explicitement rejetées
| Option | Raison du rejet (synthèse panel) |
|---|---|
| B — GitHub issue template | CAL n'est pas développeur ; GitHub n'est pas son canal ; l'email l'est déjà. |
| C comme workflow backbone | Le transport n'est pas le bottleneck ; watcher = surveillance, pas coopération. Un watcher silencieux peut être ajouté plus tard comme notification passive, mais pas comme colonne vertébrale. |
| E — formulaire auto-commit | Détruit l'acte d'auteur de CAL (commits signés en son nom) ; infrastructure disproportionnée pour un débit de l'ordre de ~5 événements/an. |
| F-lourd — PR review queue imposée à CAL | Inverse la relation, demande à CAL de travailler à notre cadence. |
4. Contraintes d'écriture (reprises d'ADR-002)
Inchangées. Le drift report et le reverse-feed email respectent :
- C1 (non-redistribution) : le report ne cite que des noms de providers et des numéros de ligne, jamais des extraits de contenu tiers.
- C2 (pas de secret) : aucun prix, aucune condition commerciale dans le report ni dans l'email.
- C3 (gdrive read-only) : ni le script ni l'email ne modifient le Google Doc. Toute correction passe par le repo, jamais par le doc CAL.
- C4 (pas de scraping actif) : L1 est une extension d'un sync déjà déclenché manuellement.
- C5 (idempotence) : si le hash du docx n'a pas changé, ni le mirror ni le drift report n'est ré-écrit.
5. Critère de révision à 8 semaines (2026-06-16)
À mi-parcours de l'horizon septembre, on regarde la mesure L4 et on décide :
- Si CAL a édité \(\geq\) 4 fois ET le temps de curation par re-sync est tombé sous 10 min : la stack L1–L3 est suffisante, on la laisse en place pour la rentrée. Décision par défaut.
- Si CAL a édité \(\geq\) 8 fois : ré-ouvrir la question, envisager D ou F-léger plus formalisé (mais pas E).
- Si CAL a édité \(\leq\) 2 fois : la cathédrale de Feynman est confirmée, on peut même retirer L3 et ne garder que L1+L2 (le script + l'ADR).
Ce critère est tranché en sprint ultérieur, pas maintenant.
Conséquences
Positives
- CAL ne change rien. Tout ce qui existe côté gdrive reste identique, c'est la seule chose qu'il nous a explicitement demandée.
- Emmanuel gagne ~25 min par re-sync. Le drift report élimine le diff-against-memory, qui est le coût dominant.
- Wissal peut hériter proprement en septembre. La couche L1 est un script bash de < 150 lignes, L2 est un ADR, L3 est un template d'email. Aucune infra à maintenir.
- La relation CAL \(\leftrightarrow\) équipe est explicitement pair-à-pair. Le reverse-feed (L3) positionne CAL comme co-auteur du catalogue, pas comme source à pipeline.
- La mesure L4 tranche la question dans 8 semaines, sans forcer une décision prématurée.
Négatives
- L3 crée une petite dette relationnelle : si Emmanuel oublie d'envoyer l'email, le signal envoyé à CAL est "ton doc ne compte plus pour eux". Mitigation : l'email est optionnel si la re-sync est cosmétique (diff < 5 lignes), et obligatoire seulement sur les re-syncs qui créent un nouveau provider ou changent un statut.
- Le
.sync-report.mdcommité alourdit le repo de quelques KB par re-sync. Mitigation : la fréquence étant faible \((\leq\) 1 re-sync / mois observée), le coût cumulé reste négligeable. - Pas de garantie que CAL lira les emails L3. C'est un choix assumé — la cadence doit rester non-intrusive. S'il les ignore, c'est un signal légitime que la relation n'a pas besoin de ce canal.
Action à envisager (sprint ultérieur, non engagé ici)
- Si L4 montre que CAL envoie régulièrement des emails de delta, créer
un dossier
docs/cal/inbox/pour archiver ces emails (avec accord CAL) et les lier aux entrées YAML concernées. - Si le nombre de re-syncs dépasse 2/semaine, automatiser un watcher silencieux (option C réintroduite comme notification, pas comme workflow).
- Envisager un linter de cohérence YAML \(\leftrightarrow\) fiche markdown (cf. ADR-002 « Action à envisager »), potentiellement couplé au drift report.
Références
- ADR-001 — Réconciliation des données primaires
- ADR-002 — Cartographie opérationnelle des sources de données
- Script de sync
- Document CAL (mirror read-only)
- Catalogue providers
- Workflows opérationnels
- Délibération inter-personas — synthèse des 5 personas (Jobs, Torvalds, Shannon, Feynman, Godin).