Le pari : un wiki que l’IA entretient, que l’humain valide
En avril 2026, Andrej Karpathy publie un court texte, le « LLM Wiki ». Trois couches : des sources brutes qu’on ne modifie pas, un wiki en Markdown écrit par le modèle, et un fichier de schéma qui fixe les règles. Trois opérations : ingest, query, lint. La thèse tient en une phrase : les humains abandonnent leurs wikis parce que l’entretien est fastidieux, et avec un LLM, le coût d’entretien tend vers zéro.
Je l’ai pris au mot, mais pour un autre usage que les lectures qu’il avait en tête : le registre de pilotage d’un indépendant. Une vingtaine de projets, clients et personnels, avec leurs statuts, leurs prochaines actions et les décisions prises. Le point de départ était banal : une documentation éclatée entre Notion, Obsidian, un drive et des conversations avec l’IA, plus une vraie méfiance envers les hallucinations.
Ce qui a été construit en une soirée, le 28 septembre :
- un dépôt Git sur ma forge auto-hébergée, ouvert dans Obsidian, avec un
CLAUDE.mdqui sert de constitution ; - une
inbox/alimentée par deux agents, un quotidien (celui qui tient ce blog) et une synchronisation hebdomadaire depuis Notion ; ils ont seulement le droit d’y déposer des captures ; /ingest, avec un humain dans la boucle, pour intégrer ces captures dans les pages ;- un lint en Python sans dépendance, lancé par un CronJob du cluster chaque lundi, rapport sur Telegram.
Les règles de vérité sont ce que j’en retiens de meilleur. Chaque fait porte une source et une date. Un « ? » vaut mieux qu’une supposition. Quand l’information manque, la réponse est « Pas dans le wiki », jamais une improvisation. Et une échelle de livraison en cinq paliers : spécifié → codé → testé → préprod → en service vérifié, le dernier exigeant de coller dans la page la sortie de la commande qui le prouve. Un reçu de test, transposé à la documentation.
Le retour sur investissement est arrivé en vingt-quatre heures : un suivi administratif oublié depuis des semaines, deux documents de référence qui se contredisaient, un envoi dont plus personne ne savait quelle version était partie, et neuf actions classées par priorité. Aucun des outils précédents n’avait produit ça.
Les chiffres à J+4 : le wiki ne suivait pas
Le 2 octobre, j’ai fait ce qu’on fait avec n’importe quel système qu’on vient de mettre en production : compter.
| Mesure | Valeur |
|---|---|
| Pages | 30, dont 20 projets et 4 décisions |
| Lignes versionnées | 24 086, dont 1 689 de Markdown (7 %) |
| Points ouverts « ? / à confirmer » | 42 |
| Commits du wiki | 8 les 28 et 29.09 · 0 les 30.09 et 01.10 · 2 le 02.10 |
| Commits du dépôt d’infra le 02.10 | 17 |
/ingest, /query, /lint tapés comme commandes | 0 |
Le 2 octobre est un bon test grandeur nature. Ce jour-là, le dépôt GitOps reçoit 17 commits : trois sites et le blog passent à un nouveau patron de déploiement, une application est retirée et redéployée sous un autre nom, deux outils partent dans leurs propres dépôts. Le wiki reçoit 2 commits. La nouvelle application n’a pas de page. Les pages des sites migrés ne parlent pas de la migration. Le même jour, la mémoire automatique de mon assistant modifie 6 fichiers, dont une fiche complète sur la nouvelle application.
Les 93 % de lignes qui ne sont pas du Markdown ? Un plugin Obsidian de requêtes, installé le premier soir, utilisé dans aucune page. Et la page la plus citée du wiki n’était pas le portfolio mais le catalogue de migration : l’échafaudage portait encore le bâtiment.
La chaîne d’alimentation : quatre maillons, quatre pannes
L’agent quotidien avait pourtant tout vu. Le 1er octobre, son journal note qu’une page de projet actif est en retard. Le 2, il trouve deux projets sans page et une page encore plus périmée. Et il n’a rien déposé dans l’inbox. En remontant la chaîne, j’ai trouvé non pas une panne mais quatre, empilées, chacune masquant la suivante.
le lanceur lisait 8 % et autorisait ; le skill relisait sur 15 min, ne trouvait rien, et sautaitthe launcher read 8 % and allowed; the skill re-read over 15 min, found nothing, and skipped
une capture coûte quelques lignes ; seul l'article de blog mérite d'attendre le quotaa capture costs a few lines; only the blog article deserves to wait for quota
à 3 items par run derrière l'arriéré blog et docs, le wiki aurait attendu plus d'une semaineat 3 items per run behind the blog and docs backlog, the wiki would have waited over a week
les captures restaient sur le PC, invisibles de la forge et du lint du clustercaptures stayed on the PC, invisible to the forge and to the cluster lint
Maillon 1, le quota. L’agent tourne sur mon abonnement, pas sur une clé d’API ; avant de rédiger quoi que ce soit, il lit la consommation publiée par un petit collecteur. Le lanceur PowerShell lisait cette série sur une fenêtre de 48 heures et trouvait 8 % : feu vert. Le skill, lui, relisait la même série sur une fenêtre de 15 minutes, tombait dans un trou de collecte, et concluait « réponse vide, prudence ». Deux fenêtres pour une même mesure.
Maillon 2, la prudence. Quota illisible, le run passait en « détection seule ». Logique pour la rédaction d’un article de blog, l’étape chère. Absurde pour une capture de dix lignes qui ne coûte presque rien. La règle ne distinguait pas les deux.
Maillon 3, la file. Les sujets « projets » étaient traités comme les autres : trois items par run, les plus anciens d’abord. Les six items de projets en attente étaient aux rangs 22 à 33 sur 33, derrière un arriéré d’articles et de dérives de doc. Même avec la vanne ouverte, le wiki aurait attendu plus d’une semaine.
Maillon 4, le commit. La décision fondatrice disait : l’agent dépose, « Obsidian Git s’en charge ». Le plugin était bien configuré, sauvegarde toutes les 15 minutes. Il n’a produit aucun commit depuis la création du wiki, parce qu’Obsidian n’était tout simplement pas ouvert sur ce PC. Une capture déposée serait restée un fichier local, invisible de la forge et du lint du cluster.
Le lint hebdomadaire, lui, était impeccable. Pod sans root, système de fichiers en lecture seule, aucune capability, pas de git : il récupère une archive du dépôt par l’API de la forge. Il contrôlait la forme du wiki, frontmatter, liens, dates déclarées. Il ignorait qu’une application existait sans page. Celui qui le savait vivait dans un autre système.
Le lint qui criait au loup
En passant, trois défauts du lint lui-même, parce qu’ils sont instructifs.
Le compteur de points ouverts détectait ? et « à confirmer » séparément. Or la convention du wiki écrit « ? à confirmer » : chaque point était compté deux fois. Les 42 points ouverts étaient en réalité 22. Mieux : la page qui décrit le système de connaissance collait la sortie du lint comme preuve de mise en service, sortie qui contient la chaîne « ? / à confirmer ». Le lint se détectait lui-même. Le rituel de preuve polluait le signal.
Le seul point rouge, une URL publique répondant 530 parce que le serveur n’est pas encore installé, était connu et accepté. Sans moyen d’acquitter, chaque rapport du lundi s’ouvrait sur « rouge : à corriger ».
Et la date de vérification était stockée deux fois, dans le portfolio et dans chaque page : deux écarts sur vingt au bout de quatre jours.
Lot 1 : réparer l’alimentation avant d’ajouter des fonctions
Tout le lot 1 tient en une demi-journée et quatre gestes, chacun couvert par un test qui a échoué avant d’être au vert.
- Une seule fenêtre de quota, 48 heures, lue de la même façon par le lanceur et le skill.
- Quota illisible → captures seules, plus jamais « rien ». La rédaction d’articles reste soumise au quota.
- Les items projets passent en tête, hors de la limite de trois, dix au plus par run.
- Le lanceur committe les captures. Un script PowerShell, sans LLM, qui ajoute uniquement les nouveaux fichiers
inbox/AAAA-MM-JJ-*.md, pousse la branche principale, rebase en préservant le travail en cours si le remote a avancé, et ne fait rien si le dépôt n’est pas surmain. Vingt-cinq contrôles contre un vrai dépôt git jetable : rebase, push refusé puis repris au run suivant, mauvaise branche.
Et pour le lint : « ? à confirmer » compté une fois, code et citations ignorés, un champ connu_jusqu_au: qui acquitte un échec d’URL connu jusqu’à une date, et un contrôle nouveau : une entrée d’historique qui dit « vérifié » sans que verifie_le bouge est signalée.
La décision fondatrice a été remplacée par une nouvelle, comme le wiki l’exige de lui-même : on ne rediscute pas une décision, on en écrit une autre avec remplace:.
Lot 2 : mesurer au lieu de déclarer
Le lot 1 rouvrait la vanne. Le lot 2 s’attaque au vrai problème : un verifie_le est une déclaration, et une déclaration se périme sans bruit.
Couverture. Chaque page revendique ses dépôts dans le frontmatter : depots: [nom-du-depot, autre]. Le lint liste les dépôts de la forge par l’API, avec le jeton en lecture seule déjà monté dans le pod. Tout dépôt non archivé, poussé depuis moins de 30 jours et qu’aucune page ne revendique, sort en rouge « projet sans page ». Les dépôts sans projet se déclarent dans une page dédiée, avec la raison. Premier relevé : 22 dépôts actifs, tous revendiqués.
Fraîcheur. Même champ : si un dépôt a reçu des commits après verifie_le, la page sort en jaune « N commits depuis la vérification ». Premier relevé : 5 pages à revérifier, dont une page « parquée » dont le dépôt avait reçu plus de 50 commits depuis sa date de vérification. Exactement ce que l’agent avait vu la veille, mais calculé chaque lundi par le cluster, sans aucun appel à un modèle.
Deux détails de robustesse qu’une relecture indépendante a relevés et que les tests couvrent désormais : une erreur d’API sur un seul dépôt ne doit pas annuler tout le contrôle (chaque dépôt en panne sort seul en jaune), et la pagination au-delà de 50 dépôts est vérifiée par mutation, en supprimant la boucle pour voir le test échouer.
Le portfolio est généré. Un script reconstruit les tableaux du portfolio entre deux marqueurs HTML, depuis statut, un nouveau champ action: et verifie_le. Le doublon qui dérivait disparaît, et le plugin de requêtes aussi : moins 20 875 lignes.
/ingest passe en PR. Une branche ingest/…, une pull request ouverte par un script (en JSON UTF-8 : l’API de la forge rejette un corps en curl dont les accents sont corrompus), une CI sur le runner du NAS qui lance les 47 tests, vérifie que le portfolio est à jour et passe le lint sans réseau. Je fusionne depuis mon téléphone. « L’IA maintient, l’humain valide » cesse d’être un rituel de fin de session pour devenir un mécanisme.
J+5 : la chaîne tourne, et elle attrape ce que j’avais raté
Le 3 octobre à 12:30, premier run complet après réparation.
| Étape | Le 02.10 | Le 03.10 |
|---|---|---|
| Quota lu | 8 %, puis « vide » | 35 %, session 3 % |
| Traitement | sauté | 12 items en 8 min |
| Items projets traités | 0 | 9 sur 9, en tête |
| Captures déposées | 0 | 5 |
| Commit sur la forge | aucun | « inbox: 5 capture(s) », 2 secondes après le run |
Quatre des neuf items ont été clos sans capture, avec une référence de ligne exacte vers la page qui couvrait déjà le fait : le dédoublonnage marche. Les cinq captures restantes sont sourcées (commits, kubectl, curl, docker ps), chacune avec une suggestion d’intégration par page.
Deux d’entre elles corrigent des trous de mon propre rattrapage manuel de la veille : un service déployé le 1er octobre et une nouvelle carte de l’infrastructure, oubliés tous les deux. Une troisième remplace un « ? à confirmer » par une sortie docker ps. C’est la plus-value attendue : le wiki ne dépend plus de ce que je pense à écrire.
La première /ingest en PR a suivi dans l’heure : CI verte, fusion, inbox vide, 0 rouge au lint.
Ce que j’en retiens
Karpathy a raison, et c’est plus subtil qu’il n’y paraît. Écrire ne coûte presque plus rien. Ce qui coûte, c’est de déclencher l’écriture. Depuis la création du wiki, aucune des trois commandes n’avait été tapée. La règle « toute session se termine par /ingest » est un rituel, et un rituel perd toujours contre un effet de bord. La mémoire automatique de mon assistant gagnait parce qu’elle s’écrit pendant le travail, pas après.
Le savoir s’accumule, l’état se périme. Le modèle LLM Wiki vise un savoir qui s’accumule : des lectures, des concepts. J’y range un état qui se périme chaque jour. Un statut de projet ressemble plus à une métrique qu’à une note : il faut le mesurer, et la mesure la plus honnête est le dépôt git lui-même.
Testez la chaîne, pas les maillons. Chaque maillon fonctionnait « en principe ». Aucun test ne traversait la chaîne entière, du détecteur au commit sur la forge. La question qui m’a manqué le 28 septembre : « si l’agent trouve quelque chose demain midi, où est le commit à 12:45 ? »
Un rouge permanent est un rouge invisible. Le lint produisait le même point rouge chaque semaine pour une cause connue. Au deuxième rapport, personne ne le lit plus. Acquitter avec une date d’expiration coûte une ligne de frontmatter et sauve le signal.
Les tests ont attrapé ce que les relectures ont manqué. Le BOM que PowerShell 5.1 glisse dans un JSON, l’espace de tête que Out-String().Trim() mange dans la sortie de git status --porcelain, le # d’une URL pris pour un commentaire de frontmatter : trois bugs réels, trouvés par des tests écrits avant le code, contre de vrais dépôts git jetables et un faux serveur d’API.
Reste une question ouverte, honnête : un agent en lecture seule doit bientôt répondre à des questions depuis ce wiki. Avant de le brancher, je veux un jeu de vingt questions, dont cinq sans réponse dans le wiki, et mesurer combien de fois le système répond correctement « Pas dans le wiki ». La promesse anti-hallucination deviendra un chiffre. Ou pas.