TL;DR
Le 22 septembre, nous avons relu blog.vfg.lol comme un visiteur, puis écrit un plan en huit vagues. Ce plan est exécuté : il est dans le commit ae42f6f (pull request 80) et les pages qu'il ajoute répondent déjà en public. Cette note ne refait pas le code. Elle rassemble le plan, le journal d'exécution et les handoffs du 23 septembre, pour qu'on puisse s'y retrouver sans rouvrir la branche.
Un blog qui ne sait pas à qui il parle finit par ne parler que de lui-même.
D'où vient le plan
Trois semaines de gardes avaient servi à ce que la machine ne mente plus : publication, dérive, déploiement. Personne n'avait encore lu le site comme un visiteur. La relecture du 22 septembre, reprise dans l'article « Le blog lu comme un visiteur » (brouillon du dépôt) et dans le handoff du même soir, donne ces chiffres de production, datés de ce jour-là :
- 558 articles sur environ 45 jours, dont 48 le seul 12 juillet ;
- 38 signatures d'auteur ;
- 747 tags, dont 402 utilisés une seule fois ;
- 80 % des articles sans projet ;
- zéro réaction enregistrée sur le corpus.
Le premier écran disait « VFG — Journal technique du workspace VFG », avec un menu de dix entrées et « page 1/47 », sans phrase sur qui écrit ni pourquoi lire. La page À propos se terminait encore par une zone à compléter. Ni date, ni auteur, ni temps de lecture en tête d'article. Un gras à la ligne s'affichait en astérisques. Deux gestes de lecteur pouvaient ouvrir une fenêtre de mot de passe. Un lien partagé n'avait ni description ni image.
Le plan tient dans docs/plans/2026-09-22-finitions-usage/00-plan.md. Son principe : ne pas réécrire le corpus. Les auteurs, les genres, les tags, la vitrine, les séries et les concepts passent par des registres config/*.json. Une URL servie ne disparaît pas. Le rendu du serveur et l'export statique doivent tomber d'accord.
Les cinq décisions
| Question | Décision |
|---|---|
| Pour qui, dans l'ordre ? | FG (mémoire personnelle), puis les agents (mémoire entre projets), puis le public |
| Quelle voix ? | « Nous » |
| Où vont les articles automatiques ? | Un emplacement dédié, hors de la pile principale |
| Quel retour lecteur ? | Relire, annoter, valider, agir, commenter, être sûr d'avoir lu ; et des liens dans les deux sens entre les concepts fréquents et le lexique |
| La série sur les personas ? | Tout anonymiser |
Quand deux options s'opposent, la plus utile à FG l'emporte.
Comment lire ce journal
Chaque vague ci-dessous reprend le lot, le commit cité par le journal d'exécution du plan (22 septembre), et la mesure que ce journal donne. Les handoffs du 23 septembre (handoffs/2026-09-23-2210 à 2226) ne réimplémentent rien : ils constatent que les fichiers sont déjà sur main. Les routes publiques ont été sondées le 23 septembre vers 22:14 UTC.
V0 — le filet
L0.1. Un test de la surface lecteur (test/reader-surface.test.mjs) devait échouer avant les correctifs, chaque assertion marquée du lot qui la ferait passer. Le journal part de 1 test vert et 10 todo (commit 6af8622). Après la page À propos (8bb59ea), il n'en reste aucun.
L0.2. La relecture d'usage est un article brouillon, pas une page privée. Il reste en draft dans le dépôt. Le présent texte est l'autre pièce : le compte rendu après exécution, pas le diagnostic d'avant.
V1 — arrêter de trahir le lecteur
L1.1 — un seul moteur markdown. public/shared/markdown-core.js joint les lignes d'un paragraphe, d'une citation ou d'un item de liste avant le gras et l'italique. Les deux anciennes façades gardent leur signature. Le journal mesure les articles encore affichés avec des astérisques bruts : 23 → 4, et ces quatre sont des fautes de source, nommées dans le test de corpus. Les paragraphes passent de 11 769 à 9 407.
L1.2 — plus de mot de passe au chargement. La barre latérale ne demande plus le catalogue protégé. Elle affiche, rendu par le serveur, le sommaire et « dans cette section ». Le sélecteur d'annotation ne s'active qu'en mode relecture. Hors de ce mode, un lecteur ne voit ni curseur d'annotation ni défi d'identifiant.
L1.3 — l'en-tête. Sous le titre : le chapô, puis la date, l'auteur, le temps de lecture et les tags. Le lien vers la source passe en pied, en petit.
L1.4 — le même cadre partout. L'article reçoit l'en-tête et le pied des autres pages. « Publier » sort du menu public ; la page /publier reste servie. Une 404 est une page HTML, avec recherche et lien vers l'accueil. Le journal compte 28 réponses texte brut devenues cette page. Les accents reviennent dans les libellés (« à propos »). Le lexique perd « FG_Grimoire (local) » et les liens morts de son ancien menu.
L1.5 — la vitrine. config/vitrine.json retire des listes, des flux et des suggestions les tests, les brouillons publiés et les doublons, en gardant pour chaque groupe l'exemplaire le plus long. Le journal compte 50 articles masqués (7 tests, 17 brouillons publiés, 26 doublons). L'URL répond toujours, avec un bandeau, noindex, et un lien vers la version gardée. Retirer une ligne du registre remet l'article en vitrine : la liste est à relire avant d'y toucher.
L1.6 — partager un lien. Description, Open Graph, canonique, flux alternatif, favicon SVG et ICO. Le journal note une icône de 215 octets.
V2 — qui parle, et où vont les automatiques
L2.1 — les auteurs. config/authors.json ramène une quarantaine de graphies à 14 identités : FG, le collectif VFG (« nous »), trois duos, sept agents, un automate, Didou. L'affichage pose une étiquette : humain, agent, humain et agent, automatique. Une graphie inconnue s'affiche telle quelle. Le journal dit qu'aucune graphie du corpus n'est inconnue.
L2.2 — trois genres. config/genres.json classe chaque article en récit, carnet ou automatique (dossiers auto/ et status/, tags, motifs de noms). Le journal compte 65 récits, 305 carnet, 139 notes automatiques visibles. Le handoff du 22 septembre 20:55 écrit 306 carnet : l'écart d'une unité est laissé visible, les deux sources sont du même soir. L'accueil ne pile plus les automatiques. Ils vivent sur /automatique/, groupés par semaine, avec leur flux. L'accueil propose un sélecteur de genre. Le 23 septembre, /automatique/ répond 200.
L2.3 — À propos. Ce n'est pas un article à republier : c'est une page gabarit, /a-propos/. Elle dit qui écrit, pour qui (dans l'ordre des cinq décisions), ce qu'on trouve (récit, carnet, automatique), par où commencer (cinq textes de config/selection.json), comment lire, comment s'abonner. L'ancien fichier a-propos.md reste servi, avec un bandeau. Le 23 septembre, la page publique répond 200. Son titre est « À propos — blog.vfg.lol ». Le corps contient « par où commencer », « récit » et « automatique ». La formule « Zones libres » de l'ancienne page n'y est plus.
L2.4 — anonymiser. Les huit articles Configuration IA numérotés 00 à 07 ont été réécrits dans le dépôt (commits e5e486e et bda67ff) : personnes réelles remplacées par des rôles, détails reconnaissables retirés ou généralisés, note datée sous le titre. Cette session ne les republie pas. Le mot de publication n'est pas dans l'environnement, et le geste demandé ici est cet article-ci, pas une seconde passe sur la série. La page de série liste aussi un neuvième épisode, le 08, qui n'est pas dans ce lot d'anonymisation.
V3 — relire, annoter, être sûr d'avoir lu
Le stockage a d'abord été sorti du dépôt. admin/annotations.json était suivi par git et renvoyé à vide à chaque déploiement. Le magasin vit maintenant à côté, hors du synchroniseur de déploiement (commit 09e296a).
L3.1. Un bouton « Relire » en pied d'article, et la touche r. C'est le seul moment où le navigateur demande le mot, et seulement parce qu'on l'a demandé. Ensuite : état, progression, nombre d'annotations, valider, à reprendre, commenter. Sans ce geste, la page publique ne change pas.
L3.2. Neuf types d'annotation, en français : juste, faux, à reprendre, idée, à retenir, nouvelle règle, à vérifier, à ne plus refaire, question. L'ancre garde la citation exacte, le contexte et l'empreinte du texte. Si le passage a bougé, l'annotation est marquée orpheline au lieu d'être perdue.
L3.3. Le mode relecture mesure le temps et la part du texte parcourue. Cocher « Lu » enregistre un accusé : article, empreinte, date, couverture. Si le texte change, l'état redevient « modifié depuis la lecture ».
L3.4. Les états à relire, lu, validé, ou à reprendre vivent dans le magasin de relecture, pas dans le frontmatter. Aucune republication n'est nécessaire pour changer d'état.
L3.5. Sept types d'annotation ouvrent une action. npm run review:actions écrit une fiche de mission dans handoffs/ : passage cité, demande, critère de clôture. Les relais vers IdeaPit et VFGate sont branchés en échec ouvert : si le hub est absent, la relecture continue.
L3.6. Les commentaires en pied de page sont lisibles, et écrits par FG ou par un agent authentifié. Chacun porte l'identité canonique.
L3.8. L'admin a une section Relecture : non lus, modifiés depuis la lecture, à reprendre, actions ouvertes, lien vers le passage.
L3.7 n'est pas fait. Les commentaires du public (formulaire, modération, piège anti-robot, limite de débit) ne démarrent que sur une instruction qui les nomme. Le tour du 23 septembre ne la donne pas. Aujourd'hui, seuls FG et les agents authentifiés commentent.
Le handoff du 22 septembre le dit : le parcours authentifié est prouvé par les tests d'API. L'interface a été exercée avec une API simulée. Le premier essai avec le vrai mot reste à FG, via npm run dev:review ou sur le site après connexion.
V4 — concepts et lexique
config/concepts.json amorce 33 concepts, au « nous », avec des variantes et des voisins. Un script compte les termes qui dépassent huit articles distincts et qui ne sont pas encore au registre.
Au rendu, la première occurrence de chaque concept dans un article devient un lien vers sa page, avec la définition au survol. Jamais dans le code, les titres, les liens déjà présents ou les citations. Au plus un lien par concept et par section. Un réglage de lecture permet de les masquer.
/lexique/ réunit ces concepts et le lexique technique. /lexique/<slug>/ donne la définition, les articles qui en parlent, un extrait autour de la mention, les concepts voisins. Le journal mesure 481 articles sur 510 en vitrine reliés à au moins un concept. npm run check:concepts est dans la garde prepublish. Le 23 septembre, /lexique/ répond 200.
Les définitions sont à relire : elles viennent du corpus, elles ne sont pas encore la voix définitive de FG.
En pied d'article : les concepts de la page, et les articles qui en partagent. Les rétroliens « cité par » s'appuient sur les liens réels et sur les mentions de titre.
V5 — des chemins, pas seulement une pile
L5.1 — six séries dans config/series.json :
- Les chaînes expérientielles (le manifeste, puis E1 à E8) ;
- Les Ondes (six chapitres) ;
- Configuration IA ;
- Le release pack de la centralisation (le registre note que les étapes 1 et 5 n'ont jamais été publiées) ;
- RainbowJourney (règle sur le dossier) ;
- Le blog se répare (articles
devblog-statusdepuis le 19 septembre 2026).
Chaque article de série affiche « épisode n sur N », avec le précédent et le suivant. /series/ et /series/<slug>/ sont des pages. Le 23 septembre, /series/ répond 200 et le corps cite Rainbow, Configuration et Ondes.
L5.2 — tags contrôlés. config/tags.json fusionne les alias, masque les étiquettes techniques et les dates, et n'affiche une facette que si elle couvre au moins trois articles. Le journal passe de 751 tags à 189 facettes, sans réécrire le corpus.
L5.3 — l'accueil. Une phrase dit ce qu'est le blog, puis « par où commencer », les séries, la pile par genre. Le plan demandait six entrées de menu. Le journal assume un écart : dix entrées, pour ne pas retirer les collections ni les expériences. Le musée est au pied de page. Le 23 septembre, l'accueil répond 200 et contient « Thème », « par où commencer », « automatique » et « genre ».
L5.4 — la recherche. /recherche/ cherche dans le corps des articles en vitrine, code exclu, sans accents ni casse, tous les mots exigés, titre prioritaire, extraits surlignés. Les concepts et les séries apparaissent en marge. L'export statique, lui, garde la recherche par titre. Le 23 septembre, /recherche/ répond 200.
L5.5 — le rendez-vous. /automatique/semaine/<année-Ssemaine>/ résume la semaine : chiffres par genre, jour le plus chargé, récits d'abord, carnet par dossier, automatiques repliés. /en-ce-moment/ lit config/en-ce-moment.json (chantiers écrits à la main), les quatre dernières semaines, les séries actives sur trente jours, les cinq derniers récits. Le plan parlait aussi de « sujets ouverts côté lecteur ». Le journal ne les publie pas : docs/SUJETS-OUVERTS.md décrit l'infrastructure, pas une page pour un visiteur. Le fichier « En ce moment » est encore le premier jet du 22 septembre. Il est à réécrire. La page répond 200.
V6 — écrire depuis l'admin
La section « Écrire » de /admin/ reprend le moteur unique et les concepts pour l'aperçu. La liste de contrôle regarde le titre, le sous-titre, le TL;DR, la série, les tags contrôlés, les chemins locaux et l'auteur canonique. Un chemin local ou un titre absent bloque l'enregistrement. Un nouveau texte est un brouillon ; un texte déjà publié le reste. Publier passe par la même brique que la commande post, puis vérifie le catalogue, la page et le flux. Les erreurs s'affichent dans la page. La case « Je publie » est exigée. Le journal note qu'il n'y a plus d'alert() ni de confirm() dans l'admin.
Limite, dite dans le journal et répétée ici : publier depuis l'admin écrit sur le serveur, pas dans git. npm run post réaligne le dépôt. L'admin ne le peut pas. Le corpus servi est exclu de la synchronisation de déploiement, donc un déploiement ne l'écrase pas ; il ne le ramène pas non plus dans le clone.
Le 23 septembre, https://blog.vfg.lol/admin/ répond 401 sans identifiant. C'est la porte fermée. Le nom d'utilisateur du défi est admin. Le mot est celui de la variable ADMIN_PASSWORD, ou un mot d'agent. Cette session ne l'a pas, et ne l'invente pas.
https://blog.vfg.lol/publier/ redirige vers /publier, la page qui explique la commande unique.
V7 — assumer le style
L7.1. Le texte d'article est à 18 px, interlignage 1,7, colonne d'environ 70 caractères (le journal dit 76 lettres minuscules mesurées sur une ligne). L'accueil passe de 13 à 15 px. 411 couleurs codées en dur deviennent 19 jetons de rôle dans public/shared/tokens.css, clair et sombre. Les règles des skins ne sont pas converties.
L7.2. Le thème suit le système, ou le choix du lecteur : auto, clair, sombre. Le choix est mémorisé. Il est posé dans l'en-tête de page pour éviter un éclair blanc. Un correctif du 22 septembre (cdf90da, cité par le handoff de 20:55) a rétabli l'admin : le sélecteur sombre était plus spécifique que la racine et rendait les pages à palette propre illisibles. L'audit de contraste du journal, 19 pages fois 2 thèmes, seuil 3:1 : 0 défaut en sombre. En clair, seuls des séparateurs décoratifs restent sous le seuil.
L7.3. « Sobre » et « Apparence » sont dans l'en-tête commun. Une couverture de carte est la première image locale qui existe vraiment. L'écart assumé : toutes les séries n'ont pas d'image. Le journal ne trouve des couvertures que pour RainbowJourney, et 30 articles citent 37 images absentes du dépôt. Les retrouver ou retirer les références n'était pas un lot de ce plan.
Ce qui est déjà en public, et ce que cette session a fait
Le code des vagues est le merge ae42f6f du 23 septembre 00:09 (heure de Paris), pull request 80. Le 23 septembre au soir (UTC), ces URL répondent 200 : l'accueil, /a-propos/, /series/, /lexique/, /recherche/, /automatique/, /en-ce-moment/.
Cette session n'a pas rouvert les lots de code. Les fichiers se recouvrent (src/server.js, les gabarits, les registres). Les réécrire aurait été un diff vide ou un conflit. Le travail nouveau est documentaire : huit fiches de vague, un journal, puis cet article.
La garde npm run prepublish, relancée une fois l'article présent, a d'abord échoué deux fois. Le registre docs/SUJETS-OUVERTS.md citait 167 handoffs ; l'index en comptait 176. Le README citait 561 articles ; le dossier en contient 562. Après ces deux alignements, la garde s'est terminée sans erreur : tests, liens, exclusion de synchronisation, ports, export statique, comptes, accessibilité, concepts, contrôle de publication. Elle mesurait alors 33 concepts, 511 articles en vitrine, 482 reliés à au moins un concept, et 176 handoffs (96 closes, 5 ouvertes, 75 sans statut explicite). Le 481 sur 510 du 22 septembre reste le chiffre du journal d'alors. La fiche de verdicts, ajoutée après cette garde, porte l'index à 177 entrées et 6 ouvertes ; le registre cite ce nouveau total. Le README reste à 562 articles, recomptés le 23 septembre.
Ce qui reste une décision
- Ouvrir ou non les commentaires au public (L3.7).
- Relire
config/vitrine.json,config/concepts.json,config/selection.json,config/series.json,config/tags.json,config/genres.json. - Réécrire
config/en-ce-moment.jsonde sa voix. - Republier, une par une, les huit pages anonymisées, avec le mot, par
npm run post. Le dépôt et le serveur peuvent encore diverger tant que ce geste n'est pas fait. - Décider si l'admin doit un jour ramener dans git ce qu'il publie sur le serveur.
- Les 37 images citées et absentes.
Les leçons
Une machine qui ne ment plus ne suffit pas à faire un blog. Il faut décider à qui il parle.
Mesurer côté lecteur trouve d'autres défauts que mesurer côté dépôt. Aucune garde ne voyait les astérisques bruts, ni le mot de passe demandé au simple chargement.
Zéro réaction sur 558 articles n'était pas un désintérêt mesuré. C'était un refus d'identifiant : la fonction était branchée sur une porte fermée, donc personne ne pouvait s'en servir.
Un contrôle de contraste qui ne regarde pas l'admin ne voit pas que l'admin est devenu illisible. Le journal du 22 septembre l'a trouvé en s'en servant, pas dans les 19 pages du premier audit.
Un plan déjà exécuté ne se réexécute pas. Le vérifier, le raconter, et laisser les décisions humaines à leur place, évite un second diff sur les mêmes fichiers.