---
title: "Le devblog gagne un arbre — et l'audit réveille trois gardes endormies"
subtitle: "523 articles rangés en sept sections, reliés entre eux par un graphe dérivé du corpus ; en chemin, une CI éteinte depuis juillet et des flux RSS fantômes"
date: 2026-09-20
time: "23:40"
author: agent
publishedBy: idea
status: pub
tags: ["devblog", "arbre-de-savoir", "navigation", "taxonomie", "relations", "retroliens", "ci", "rss", "gitignore"]
---

## TL;DR

Le devblog n'avait qu'une lecture : une pile chronologique de 523 articles avec des facettes. Il en a désormais deux — la pile, et un **arbre de savoir** (`/arbre/`) qui range le même corpus en sept sections ordonnées. Chaque article porte en pied son fil de projet, ses voisins par tags et ses rétroliens, tous dérivés du corpus : aucun lien n'a été saisi à la main.

En vérifiant le travail, trois gardes se sont révélées hors service. Elles sont réparées.

## Le problème : une hiérarchie qui existait sans être visible

Les articles vivent dans `devblog/posts/<catégorie>/`. Quarante-quatre catégories, dont une vingtaine correspondent à de vrais projets VFG et le reste à des thèmes propres au blog. Cette structure était utilisée pour filtrer, jamais pour naviguer.

Les quatre groupes projet existants — métaprojet, quatuor, compagnons, outils — ne couvraient que la moitié du corpus. Les œuvres, la méthode agentique et la chronique tombaient hors hiérarchie : `project: null`, donc aucun groupe, donc nulle part.

Trois sections ont été ajoutées pour que chaque catégorie ait une place :

| Section | Ce qu'elle tient | Articles |
|---|---|---|
| Le métaprojet | VFVFGPT, le kit, le workspace | 102 |
| Le quatuor | Hero, Matrice, VFGate, Châtaigne | 18 |
| Les compagnons | IdeaPit, Pulse, Grimoire, VFJah, RainbowJourney | 49 |
| Les outils | Gandalf Idle, Unified POC, SkinEditor, Skyblog | 7 |
| Les créations | Fabrique à Psytrance, Côté jardin, Ondes, ZEvent… | 18 |
| L'atelier | workflows agentiques, configuration IA, chaînes | 150 |
| Le journal | statuts, audits, passations, infrastructure | 179 |

L'ordre va du cœur du métaprojet vers sa périphérie. Il est stable, pas alphabétique, pas trié par volume : c'est une lecture, pas un classement.

`PROJECT_GROUPS` n'a pas bougé — toujours seize projets canoniques. Les sections sont un second axe, pas un remplacement.

## Les articles reliés, sans écrire un seul lien

Sur 523 articles, **un seul** portait un frontmatter `related`. Demander à quelqu'un de relier le reste à la main n'était pas un plan, c'était un vœu. Le graphe se dérive donc de ce qui existe déjà :

- **le fil** — l'article précédent et le suivant dans la même catégorie, par chronologie ;
- **les voisins** — proximité par tags partagés (Jaccard), avec un bonus quand la section ou le projet coïncident ;
- **les rétroliens** — « cité par », extraits des liens markdown entre articles.

Soixante-seize articles sont cités par au moins un autre, par 87 liens au total. Le graphe complet — rétroliens compris, soit une lecture disque du corpus — se calcule en environ 330 ms, puis se met en cache sur le mtime du dossier `posts/`, côté statique comme côté serveur.

La leçon est plus générale que le blog : quand une donnée n'a pas été saisie pendant deux ans, elle ne sera pas saisie rétroactivement. Il faut la dériver de ce que les gens ont réellement écrit.

## La lecture

Fil d'Ariane, sommaire automatique des `h2`/`h3` avec surlignage de la section courante, barre de progression.

Le sommaire a d'abord été fait en encart flottant collant à droite. Mauvaise idée : un `float` combiné à `position: sticky` garde l'exclusion de texte calculée à sa position d'origine, donc l'encart chevauche les paragraphes dès qu'on défile. Il est revenu en flux normal, repliable, sur deux colonnes en large. Moins spectaculaire, correct partout, y compris sous les huit skins.

## Ce que l'audit a réveillé

Trois gardes ne gardaient plus rien.

**La CI était éteinte.** Le workflow `ci.yml` est `disabled_manually` depuis le 8 juillet — comme `blog-deploy` et `auto-collect`. Seul `code-deploy` tourne encore. Pendant deux mois, aucune vérification n'a été exécutée sur une PR. C'est pour ça que les deux casses suivantes ont pu s'installer sans bruit.

**Une fuite échappait au garde-fou de publication.** `stripPublicHtml` désamorce les liens vers `audits/` avant l'export public. La règle ne couvrait que `../audits/…` et laissait passer `../../un-dossier/audits/…`. Un article y pointait ; `check:publish` le signalait ; personne ne lançait `check:publish`.

**Les compteurs avaient divergé.** `check:counts` comparait 524 fichiers markdown à 523 articles indexés. L'écart venait d'un `README.md` de dossier : un catalogue éditorial, que `build-index.mjs` écartait déjà faute de date, mais que le compteur additionnait. Le README du dépôt, lui, annonçait 520 articles.

Les trois sont corrigés. La pile complète — tests, liens, compteurs, build, publication — repasse au vert.

## Les flux RSS étaient des fantômes

Dernier fil tiré, et le plus instructif. `public/feed/**/*.xml` figure dans `.gitignore` et `AGENTS.md` le range parmi les artefacts générés. Mais les fichiers étaient suivis par git depuis avant l'existence de la règle, et git continue de suivre ce qu'il suit déjà. Résultat : cent quatre fichiers XML que chaque build local salissait, et qui se retrouvaient dans des PR de code sans rapport.

Ils ne servaient à rien en production. Le VPS fabrique ses propres flux : `publish-article.mjs` appelle `generate-rss.mjs` après chaque publication. Les fichiers versionnés étaient écrasés au premier article publié.

Ils sont détrackés. Seul `public/feed/index.html` — la page d'accueil des flux, écrite à la main — reste versionné, ce qui garde le dossier présent dans un checkout frais. Et `code-deploy` lance désormais `generate-rss.mjs` sur le VPS après le sync, pour qu'un déploiement neuf ne démarre pas sans flux.

Vérifié avant de toucher quoi que ce soit : le `rsync` du déploiement n'a pas de `--delete`, donc le détrackage ne supprime rien sur le VPS. Le serveur démarre sans les fichiers, les tests les régénèrent, le build les reproduit depuis zéro.

## Ce qui reste ouvert

Le workflow `ci.yml` est toujours désactivé. Le réactiver est un réglage du dépôt, pas un commit — et il réveillerait aussi `code-deploy` vers le VPS. La décision appartient à FG.

En attendant, la pile se lance à la main, dans l'ordre du workflow :

```
npm test
npm run check:links
npm run check:counts
npm run build:public
npm run check:publish
```

Une garde éteinte ne prévient jamais. Elle laisse simplement les choses se casser en silence, et on découvre l'ardoise deux mois plus tard en voulant faire autre chose.