U-04Fiche projet

Eternal

Plateforme d'apprentissage gamifiée

Cadre
Projet personnel
Période
En cours
État
En cours

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

Architecture d'Eternal : une chaîne d'écriture dépose deux fichiers dans un dépôt git, que deux vues du navigateur relisent — index.html porte toutes les règles, monde.html n'en porte aucune.1chaîne d'écriture2transport3runtimedépôt git — Zokuzo/eternalbase · canal multi-machine · hébergementiframe cachée — pont en lecture seule1 moteur · 0 règle dupliquéestate.jsoninterrupteur — actif : falseun projet quelconquegit diff · git logFORMAT.mdle contrat — 8 thèmes fermésagent professeurlit le diff, écrit, pousselecon-N.htmlle fragment — 11 fichiersindex.jsonle manifeste — 5 784 oindex.htmlle moteur — 0 dépendance3 763 lignes · 116 fonctionsmonde.htmlla vue — three.js r160aucune règle : 0 setItem1un interrupteur, un contrat, un rédacteur — et deux fichiers déposés2le dépôt est à la fois la base, le canal entre machines et l'hébergement3deux vues, un seul moteur — le pont ne rend que des dérivés, en lecture seule

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

  1. 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.

  2. 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.

  3. 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.

  4. 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

index.html:3729-3758 — extrait, 3 des 15 méthodes
/* 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

CoteValeurCommande
Fragments de leçon11ls lecons/lecon-*.html | wc -l
Manifeste5 784 odu -b lecons/index.json
Interface 2D3 763 ligneswc -l index.html
Fonctions d'index.html116grep -cE '^(async )?function ' index.html
Fichiers TypeScript0find . -name '*.ts' -not -path './.git/*' | wc -l
Écritures d'état dans monde.html0grep -c setItem monde.html
Assets tracés226 PNGfind assets -name '*.png' | wc -l
Fenêtre de publication2026-07-08 → 2026-07-15git 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