ADR-002 : Cartographie opérationnelle des sources de données (M3)
Statut
Accepté — 2026-04-14
Contexte
Le sprint M1 (cf. docs/sprint/2026-04-14-maqi-sprint.md) a livré
un catalogue curé des providers nommés par Charles-Albert dans son
doc gdrive : docs/providers/catalog.yaml (22 entrées à l'époque,
28 au 2026-04-16 après ajout des legacy dumps et des sources classe III), une vue
humaine docs/providers/README.md, et une copie markdown versionnée
des docs CAL source (docs/cal/).
Ce catalogue est une photographie d'intention. Il ne dit pas, pour chaque source :
- ce que nous avons réellement téléchargé et relu,
- où en est la négociation (qui, quand, réponse, prochaine action),
- ce qui manque pour passer d'une source à un livrable du Master.
Sans cette information, chaque décision d'achat ou de négociation repart de zéro, et la mémoire du dossier vit implicitement dans la tête de Charles-Albert — ce qui est fragile et peu scalable.
L'effort M3 a capturé et évalué cette dette sur les trois axes : explore (ce qu'il y a à regarder), validate (ce qu'il y a à relire), et negotiate (ce qu'il y a à demander).
La présente ADR tranche le format à retenir pour la cartographie opérationnelle, et fixe les contraintes d'écriture qui s'appliqueront à chaque tâche enfant.
Décision
1. Format retenu : B (principal) + A (squelette enrichi) + C (vue dérivée)
La cartographie M3 est portée par trois artefacts composables, chacun jouant un rôle distinct :
flowchart LR
cal["docs/cal/datasets-pipeline.md<br>(CAL source, read-only)"]
yaml["docs/providers/catalog.yaml<br><i>squelette enrichi</i>"]
md["docs/providers/<id>.md<br><i>un fichier par provider</i>"]
matrix["docs/providers/cartography.md<br><i>vue matricielle dérivée</i>"]
cal --> yaml
yaml --> md
md --> matrix
yaml --> matrix
style cal fill:#eef,stroke:#448
style yaml fill:#dfd,stroke:#0a0
style md fill:#dfd,stroke:#0a0
style matrix fill:#ffe,stroke:#cc0
-
A —
docs/providers/catalog.yaml(déjà en place, à enrichir). Reste la table des matières machine-lisible. On ajoute à chaque entrée les champs suivants :operational_status\(\in\) {not_started,explored,validated,in_negotiation,blocked,rejected}last_reviewed(ISO date)detail_doc: chemin vers le markdown détaillé (docs/providers/<id>.md)linked_deliverables: liste de tags (colab-demo,notebook,article,backtest, …)
- B —
docs/providers/<id>.md(nouveau, livrable principal). Un markdown par provider, avec frontmatter typé (miroir du YAML) et corps narratif structuré en trois sections : Explore, Validate, Negotiate. Chaque section peut être vide si non applicable. Les logs datés s'ajoutent en bas de section. - C —
docs/providers/cartography.md(nouveau, vue dérivée). Une seule page matricielle : {provider \(\times\) axe} avec statut opérationnel et date de dernière action. Maintenue à la main à partir du YAML, utile pour le pilotage équipe et pour Charles-Albert.
2. Squelette imposé du markdown par provider (Option B)
Tous les docs/providers/<id>.md suivent le même squelette, pour
rendre la cartographie lisible de façon uniforme :
---
id: <slug>
name: <display name>
operational_status: not_started | explored | validated | in_negotiation | blocked | rejected
last_reviewed: YYYY-MM-DD
owner: <repo handle or "unassigned">
class: I | II | III | IV # cf. idée step 2
upstream: docs/providers/catalog.yaml#<id>
linked_deliverables: [<tag>, ...]
---
# <Nom du provider>
## Explore
<ce que le provider annonce livrer, où, comment, sous quelle licence.
Minimum attendu : URL, type de livraison, fréquence, coverage, CGU.>
## Validate
<pour les sources déjà en notre possession : ce qu'on a vraiment
regardé. Schéma observé, compte de lignes, fenêtre temporelle,
anomalies. *Aucun extrait de données payées — uniquement des résumés.*>
## Negotiate
<log daté des actions de négociation. Lignes du type :
`2026-04-14 — email envoyé à X, en attente de réponse`.
*Aucun prix, aucune condition commerciale, aucun draft NDA.*>
## Decisions
<liens vers les ADR ou issues GitHub qui s'appuient sur cette source.>
3. Contraintes d'écriture (non-négociables)
Reprises de docs/cal/tech-solutions.md et du capture step :
- C1 — Non-redistribution. Aucun contenu brut d'un provider payé dans le repo. La section Validate contient des résumés de schéma (nom de colonnes, types, compte de lignes, plages de dates), pas des extraits.
- C2 — Pas de secret. Pas de prix, pas de drafts NDA, pas de contenu d'emails privés dans la section Negotiate. Seuls qui / quand / statut court sont autorisés. Le détail sensible vit hors repo, référencé par un pointeur opaque si nécessaire.
- C3 — Gdrive read-only. La section Explore ne modifie jamais le doc CAL source. Tout retour à Charles-Albert passe par revue du repo.
- C4 — Pas de scraping actif. M3 documente la possibilité de scraper (classe III), il ne scrape pas. Exécution réelle nécessite un futur sprint + accord explicite.
- C5 — Idempotence. Toute extraction automatique reste ré-exécutable sans casser la main-curation. Corollaire : les enrichissements humains ne sont pas écrasés par un re-sync.
4. Découpage en tâches enfants (par classe, pas par provider)
Pour éviter l'inflation du backlog (28 tâches = 28 worktrees = ingérable), la cartographie est découpée en 4 tâches enfants, une par classe (cf. idée step 2). Chaque classe est tackle-able indépendamment, avec ses propres gates de sortie.
| Enfant | Scope | N providers | Effort estimé | Bloquant |
|---|---|---|---|---|
task-m3-class-1 | Classe I — owned, needs validation (5 flux S&P Global) | 5 | \(\approx\) 15 h | Accès local Xpressfeed |
task-m3-class-2 | Classe II — owned legacy, needs verification (RavenPack dump, Databento NASDAQ) | 2 | \(\approx\) 3 h | Non |
task-m3-class-3 | Classe III — public URL, needs lightweight exploration (8 sources publiques) | 8 | \(\approx\) 3 h | Non |
task-m3-class-4 | Classe IV — opaque / contact-only, needs email log (7 sources à négocier) | 7 | < 1 h actif + async | Dépend de tiers |
Chaque enfant a pour Definition of Done :
- Tous les markdown
docs/providers/<id>.mdde sa classe sont créés (squelette rempli au moins pour Explore). - Les entrées YAML correspondantes portent
operational_status,last_reviewed, etdetail_doc. - La vue matricielle
docs/providers/cartography.mdreflète le nouvel état de la classe. - Tous les enfants nucléés portent le tag
temp:warm(contrainte formulaidea-to-plan).
5. Règle de resynchronisation
Quand scripts/sync-cal-docs.sh est ré-exécuté et fait apparaître un
provider non présent dans catalog.yaml :
- Le provider est ajouté manuellement au YAML avec
operational_status: not_started. - Un markdown
docs/providers/<id>.mdvide (squelette seul) est créé. - Le provider est classé (I / II / III / IV) selon le même critère que step 2 de l'idée.
- Si la classe est I, II ou IV, une nouvelle tâche enfant de la classe correspondante est nucléée (warm).
Cette règle n'est pas automatisée dans le sprint M3 : elle est documentée ici pour les sprints futurs, et sera reprise par un sprint d'outillage si la fréquence le justifie.
Conséquences
Positives
- Chaque provider reçoit un emplacement éditable stable et unique, ce qui élimine les conflits de merge entre tâches parallèles.
- Le YAML reste la source de vérité pour l'automatisation (projection
dans
STATUS.md, tri, filtrage, lien cartography.md). - La séparation Explore / Validate / Negotiate rend explicite l'état d'une source : on ne confond plus « j'ai vu le site » avec « j'ai validé le fichier ».
- Le découpage en 4 tâches enfants au lieu de 22 rend le sprint exécutable en une semaine de calendrier.
- Charles-Albert peut corriger un provider en éditant un seul fichier markdown, sans toucher au YAML ni au docx gdrive.
Négatives
- Duplication partielle entre YAML et frontmatter markdown (le nom, le statut, la classe). La règle : le YAML est source pour les champs typés, le markdown est source pour le récit. Un script de cohérence pourra être ajouté plus tard si la dérive apparaît.
- La matrice
cartography.mdest maintenue à la main — risque de dérive par rapport au YAML. Parade : la matrice est regénérée à chaque fin de tâche enfant, pas édité librement. - La classe I dépend de l'accès local aux flux Xpressfeed. Si
l'accès n'est pas prêt quand
task-m3-class-1est tackle, la tâche serablockedet devra attendre.
Action à envisager
- Définir (sprint ultérieur) un linter de cohérence YAML \(\leftrightarrow\) markdown, déclenché en pré-commit.
- Déclarer dans
surfaces.tomlune projection de la cartographie dansSTATUS.md(one-liner par classe : combienvalidated, combienblocked). - Ouvrir (sprint ultérieur) la question du store secret externe pour les détails de négociation (C2).