U-04Fiche projet
Eternal
エターナル
Plateforme d'apprentissage gamifiée
Contexte
Le code écrit avec une IA part plus vite qu'il n'est compris. Eternal n'est pas une application mais une chaîne de production : à la fin d'un travail significatif, un agent lit le vrai diff du projet, écrit une leçon interactive et la pousse dans un dépôt git. Deux pages HTML sans build la relisent au navigateur — l'interface 2D porte toutes les règles du jeu et zéro dépendance ; le monde 3D n'a aucune règle et exactement une dépendance, three.js chargé depuis un CDN.
Architecture
Contraintes
- 01La leçon ne doit rien coûter au rythme de travail : elle part en arrière-plan à la fin d'une tâche, jamais en bloquant.
- 02Des agents qui n'échangent aucun message doivent produire des fichiers interopérables — il fallait un point de rendez-vous qui ne soit ni une API ni une base.
- 03Plusieurs sessions, sur plusieurs machines, peuvent rédiger en même temps : deux d'entre elles ne doivent pas se donner le même numéro de leçon.
- 04Zéro serveur, zéro compte, hébergement statique — la progression reste donc sur l'appareil, et cette limite est écrite plutôt que masquée.
Décisions techniques
- 01
Un fichier de contrat à la place d'une réunion
`FORMAT.md` est déclaré source de vérité partagée entre l'agent qui écrit et l'interface qui rend : disposition, vocabulaire fermé de huit thèmes, économie d'XP, structure exacte du fragment. Onze leçons plus tard, les onze le respectent.
- 02
Le manifeste est séparé du contenu
Au démarrage, l'interface ne charge que les métadonnées — 5 784 octets — et va chercher le fragment d'une leçon à son ouverture, une seule fois. Trier, filtrer et calculer la progression ne coûtent donc pas les 194 989 octets de fragments.
- 03
Aucun compteur persisté
L'XP, le solde, les rangs et les statistiques de combat se recalculent à chaque affichage depuis ce qui a été lu et répondu. Un état de progression corrompu ou d'une ancienne version ne peut donc pas mentir sur un total.
- 04
Deux vues, un seul moteur
Le monde en trois dimensions ne rend que le décor : il n'a aucune règle. Il pilote le moteur de la page 2D par un pont en lecture seule, exposé depuis une iframe cachée — et il n'écrit jamais l'état.
Le pont, en code
/* Pont lecture seule pour le monde 3D (monde.html, même origine) :
des dérivés calculés, jamais l'état brut ni de mutation. */
window.__eternal = {
solde: () => eclatsSolde(),
xp: () => xpTotal(),
23 lignes omises
shopDo: (action, arg) => actionRPG({ dataset:{ action, item:arg, slot:arg } }), // réutilise le vrai chemin d'achat/équip
};
Tout ce que le monde 3D peut toucher tient entre ces deux accolades : des lectures et des appels au moteur, jamais l'état brut, jamais une mutation. De l'autre côté du pont, `grep -c setItem monde.html` rend 0 — la vue n'écrit rien.
Cotes relevées
| Cote | Valeur | Commande |
|---|---|---|
| Fragments de leçon | 11 | ls lecons/lecon-*.html | wc -l |
| Manifeste | 5 784 o | du -b lecons/index.json |
| Interface 2D | 3 763 lignes | wc -l index.html |
| Fonctions d'index.html | 116 | grep -cE '^(async )?function ' index.html |
| Fichiers TypeScript | 0 | find . -name '*.ts' -not -path './.git/*' | wc -l |
| Écritures d'état dans monde.html | 0 | grep -c setItem monde.html |
| Assets tracés | 226 PNG | find assets -name '*.png' | wc -l |
| Fenêtre de publication | 2026-07-08 → 2026-07-15 | git log --date=short --pretty=%ad | sort -u |
Chaque valeur se rejoue par sa commande, à la racine du dépôt du projet. Relevé du 2026-08-06.
Parc
- HTML
- CSS (OKLCH)
- JavaScript sans build
- three.js r160
- WebGL
- SVG inline
- localStorage
- git / GitHub Pages
- PowerShell
- Claude Code