View as:

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/&lt;id&gt;.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é

Ce qui divisait le panel

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 :

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

#CoucheCoût setupQui agitQuand
L1Extension sync-cal-docs.sh : émet un diff + drift report à chaque re-sync~2 h Emmanuelscriptà chaque re-sync
L2Cet ADR + mise à jour docs/workflows.md avec la boucle CAL → sync → drift report → curation → reverse-feed email~1 h Emmanuelhumainà l'acceptation de l'ADR
L3Reverse-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-syncEmmanueldès la 1re re-sync post-ADR
L4Mesure 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~0passifdé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 :

  1. Diff unifié (ancien \(\leftrightarrow\) nouveau mirror) tronqué à 200 lignes, plein en pièce jointe .prev-*.md gitignorée.
  2. Nouveaux headings (### sous sections taxonomiques) présents dans le nouveau mirror mais absents de catalog.yaml \(\to\) candidats nouveaux providers.
  3. Entrées YAML orphelines : IDs de catalog.yaml dont le name ne paraît plus dans le mirror \(\to\) candidats reclassements ou retraits.
  4. 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 :

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

OptionRaison du rejet (synthèse panel)
B — GitHub issue templateCAL n'est pas développeur ; GitHub n'est pas son canal ; l'email l'est déjà.
C comme workflow backboneLe 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-commitDé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 à CALInverse 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 :

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 :

Ce critère est tranché en sprint ultérieur, pas maintenant.

Conséquences

Positives

Négatives

Action à envisager (sprint ultérieur, non engagé ici)

Références