Chapitre 10
Les conventions : arborescence plate et front-matter normé
Objectifs du chapitre
- Justifier une arborescence de cinq dossiers sans sous-hiérarchie.
- Lire le validateur de contenu et comprendre ce qu'il garantit — et ce qu'il ne garantit pas.
- Comprendre pourquoi son périmètre est une liste blanche et non une liste noire.
- Voir comment conventions, templates, vues et validateur se tiennent mutuellement.
1. L'arborescence
vault/
├── 00-inbox/ # capture brute, sans front-matter
├── 10-journal/2026/ # notes quotidiennes, un sous-dossier par année
├── 20-notes/ # fiches de connaissance, à plat
├── 30-projets/ # une note par project, à plat
├── 80-assets/ # images, PDF
├── 90-meta/ # manifeste, conventions, templates, vues, outillage
└── 99-archive/
Les préfixes numériques ne servent qu'à l'ordre d'affichage. Aucun dossier n'a de
sous-dossier, sauf 10-journal/ découpé par année pour ne pas atteindre mille
fichiers dans un même répertoire.
Pourquoi si peu
Une hiérarchie profonde impose de répondre à « où ça va ? » à chaque note, et cette question n'a souvent pas de bonne réponse. Une fiche sur les temps de cycle PROFINET appartient-elle au réseau, à la performance, ou au projet en cours ? Les trois. Un dossier n'en garde qu'un.
Le modèle plat déplace la question : on ne demande plus où ranger, mais ce que c'est. Le classement se reconstruit ensuite à volonté par requête — et une note peut apparaître dans autant de vues qu'elle concerne, sans jamais être dupliquée ni déplacée.
Le test qui valide une arborescence : combien de temps hésites-tu avant de créer une note ? Plus d'une seconde, et la structure travaille contre toi. Avec cinq dossiers dont trois seulement reçoivent des notes rédigées, l'hésitation disparaît.
Ce que porte chaque dossier
| Dossier | Contenu | Front-matter |
|---|---|---|
00-inbox/ | Une ligne horodatée par capture, un fichier par mois | aucun, par conception |
10-journal/ | Une note par jour | type:
daily |
20-notes/ | Fiches durables, une idée par note | type: concept |
30-projets/ | Une note par projet, cible des liens
projects | type: project |
90-meta/ | Conventions, vues, templates, manifeste, outillage | selon le fichier |
99-archive/ | Ce qu'on ne veut plus voir sans vouloir le supprimer | non validé |
2. Le contrat, rappelé
Le chapitre 3 l'a introduit ; le voici comme règle exécutable. Cinq champs obligatoires partout :
type: daily | project | concept
title: …
created: 2026-08-02 # ISO, jamais modifié
updated: 2026-08-02 # touché à chaque édition
scope: work | personal
Plus, selon le type : status obligatoire sur un projet (active,
dormant, closed), repo et milestones optionnels ;
sources et see_also sur un concept ; projects sur une
note quotidienne.
Ce contrat est documenté dans 90-meta/conventions.md — une note ordinaire,
lisible dans Obsidian, à côté des vues qu'elle rend possibles.
3. Le validateur
$ uv run --project 90-meta/tooling 90-meta/tooling/vault.py doctor
0 probleme(s)
Il parcourt les notes du périmètre et vérifie cinq choses : le front-matter est présent et
lisible, les champs obligatoires sont là, type et scope sont dans
leur énumération, un projet a un status valide, et chaque lien de
projects vise une note qui existe dans 30-projets/.
La précédence des problèmes
Le validateur s'arrête au premier problème d'une note plutôt que de tout accumuler :
# La précédence est délibérée : un champ manquant rend les contrôles
# suivants ininterprétables, on ne les tente pas.
for champ in CHAMPS_OBLIGATOIRES:
if champ not in entete:
problemes.append(...)
if problemes:
return problemes
if entete["type"] not in TYPES:
return [Probleme(relatif, f"type invalide : {entete['type']}")]
Signaler « type invalide » sur une note où type est absent n'aide
personne. Le comportement est fixé par deux tests, pour qu'un remaniement ne le change pas
par accident.
Une note illisible n'arrête pas le reste
Version initiale du validateur : yaml.safe_load sans garde. Une seule note
avec un YAML mal formé — un deux-points non quoté suffit — levait une exception qui remontait
jusqu'à la sortie du programme. Résultat : une note cassée masquait les diagnostics de
toutes les autres, sur un outil dont le seul travail est de lister les problèmes.
La note illisible doit devenir un problème signalé comme un autre, et le parcours continuer. Même traitement pour un fichier illisible en UTF-8.
4. Le périmètre : liste blanche
DOSSIERS_VALIDES = ("10-journal", "20-notes", "30-projets", "90-meta")
DOSSIERS_EXCLUS = ("90-meta/templates", "90-meta/tooling")
Le validateur ne regarde que ces dossiers, moins ces exclusions. La formulation inverse — une liste noire de ce qu'on ignore — paraît plus naturelle et se révèle fausse.
Ce qui doit rester dehors, et pourquoi :
00-inbox/— pas de front-matter, par conception (chapitre 6) ;90-meta/templates/— les templates contiennent<% tp.date.now() %>, qui n'est pas une date valide ;90-meta/tooling/— du code, et surtout des artefacts générés ;README.md,docs/,99-archive/— pas des notes normées.
C'est le dernier point qui tranche. Avec une liste noire, chaque nouveau fichier apparu à la racine devient un faux positif jusqu'à ce qu'on pense à l'ajouter.
Le cas réel : 90-meta/tooling/ est dans le périmètre, et pytest y écrit
.pytest_cache/README.md. Lancer la suite de tests suffisait donc à faire échouer
doctor — sur un fichier généré, sans rapport avec le contenu du vault. Pire, le
test d'acceptation du vault lançait doctor depuis pytest : il échouait à
cause d'un fichier que pytest venait de créer lui-même.
5. Les vues comme notes
Les trois vues du vault vivent dans 90-meta/vues/ et sont des notes ordinaires,
avec leur front-matter type: concept. Elles sont donc versionnées, liables, et
validées comme les autres.
Ce n'est pas anodin. Une vue rangée dans la configuration serait invisible dans le vault, non liable, et perdue à la reconstruction. Comme note, elle se cite, se modifie, s'améliore au fil de l'usage.
Concepts orphelins est celle qui rend le mieux service — elle liste les fiches que rien ne cite et qui ne citent rien. C'est le détecteur de base de connaissance qui pourrit : une fiche isolée ne remontera jamais dans un lien retour, donc ne sera jamais relue, donc n'aurait pas dû être écrite sous cette forme.
6. Comment les pièces se tiennent
Chaque élément de ce chapitre dépend des autres, et c'est ce qui rend l'ensemble stable :
| Pièce | Ce qu'elle exige | Ce qu'elle permet |
|---|---|---|
| Arborescence plate | Un classement porté ailleurs | Aucune hésitation au moment d'écrire |
| Front-matter normé | Des templates qui l'appliquent | Des vues qui reconstruisent le classement |
| Templates | Templater correctement déclenché | Que la voie conforme soit la plus rapide |
| Validateur | Un périmètre bien défini | Que la dérive se voie en trois secondes |
| Vues | Un front-matter fiable | Que le vault réponde à des questions |
Retire une pièce et l'édifice penche. Sans templates, le front-matter dérive et les vues se vident. Sans validateur, la dérive ne se voit qu'au moment où une vue devient fausse — trop tard. Sans vues, plus rien ne justifie l'effort du front-matter, et on retourne aux dossiers.
Récapitulatif
- Cinq dossiers, aucune sous-hiérarchie sauf l'année du journal : la question devient « qu'est-ce que c'est » et non « où ça va ».
- Cinq champs obligatoires, trois types fermés, un
statussur les projets. - Le validateur s'arrête au premier problème d'une note — précédence délibérée, fixée par des tests.
- Une note illisible devient un problème signalé, jamais une exception qui masque les autres.
- Le périmètre est une liste blanche : une liste noire produit un faux positif à chaque fichier nouveau.
- Les vues sont des notes : versionnées, liables, validées.
Exercices
Exercice 1 — Placer une note
Où ranges-tu, et avec quel front-matter : (a) le compte-rendu d'un essai du 12 août ; (b) une fiche sur la norme IEC 61158 ; (c) une idée notée en réunion, pas encore réfléchie ; (d) le suivi d'un projet terminé l'an dernier ?
Voir la solution
(a) Dans la note quotidienne du 12 août, 10-journal/2026/,
comme une section. Un essai est un événement, il appartient à sa date. S'il mérite une
conclusion durable, celle-ci devient une fiche dans 20-notes/ que la note du
jour cite.
(b) 20-notes/, type: concept, avec
sources renseigné. Connaissance durable, pas datée.
(c) 00-inbox/ via la capture — pas de front-matter, pas de
décision de rangement. C'est tout l'intérêt : décider coûte, et à ce moment-là tu es en
réunion.
(d) Il reste dans 30-projets/ avec
status: closed. Le déplacer vers 99-archive/ le sortirait du
périmètre de validation et casserait les liens des notes quotidiennes qui le citent —
enfin, pas les liens eux-mêmes, mais le contrôle qui vérifie qu'ils pointent quelque part.
L'archive est pour ce qu'on ne veut plus voir du tout.
Exercice 2 — Étendre le contrat
Tu veux ajouter un type source pour les références externes — normes,
articles, documentation constructeur. Quelles modifications, et dans quel ordre ?
Voir la solution
Cinq fichiers, dans un seul commit — c'est ce qui rend l'ajout d'un type volontairement coûteux :
vaulttool/notes.py: ajouter"source"àTYPES, et les champs propres au type s'il y en a d'obligatoires.tests/test_notes.py: un test qui accepte une notetype: sourcevalide, un qui refuse une variante fautive.90-meta/conventions.md: documenter le type et ses champs. C'est le document que tu reliras dans six mois.90-meta/templates/source.md: le template, sans quoi le type ne sera pas utilisé correctement.- Une vue, ou une colonne dans une vue existante. Un type qu'aucune vue n'expose ne sert à rien : personne ne verra jamais ces notes autrement qu'en les cherchant.
La vraie question, avant tout ça : est-ce qu'une fiche
concept avec sources renseigné ne fait pas déjà le travail ? Un
type se justifie quand il porte des champs différents et qu'on veut l'interroger
séparément. Sinon, c'est une étiquette.
Exercice 3 — Le validateur qui certifie à tort
vault.py doctor --racine /chemin/qui/n-existe-pas retourne
0 probleme(s) et sort en code 0. Pourquoi, et est-ce grave ?
Voir la solution
Pourquoi : le parcours repose sur rglob et
glob, qui sur un dossier inexistant retournent simplement une séquence vide
plutôt que de lever une erreur. Zéro note parcourue, donc zéro problème trouvé, donc
« tout va bien ».
Est-ce grave : en usage interactif, non — on voit qu'on s'est trompé de chemin. Dans un script, oui : un contrôle qui répond « conforme » alors qu'il n'a rien examiné est pire qu'un contrôle absent, parce qu'on lui fait confiance.
C'est la même famille de défaut que l'exercice 2 du chapitre 9 : la commande ne distingue pas « rien à signaler » de « rien examiné ». Le correctif tient en deux lignes — vérifier que la racine existe et contient au moins un des dossiers attendus, sinon échouer franchement.
Généralisation utile : tout contrôle qui peut retourner « conforme » sans avoir rien vérifié doit être capable de dire combien d'objets il a examinés. Afficher « 0 probleme(s) sur 148 notes » aurait rendu le défaut visible immédiatement.