---
title: "Gandalf Idle, état des lieux : un compagnon sain, pas encore un monde"
subtitle: "Tour de test à froid et audit à quatre angles : 47 tests verts, une chaîne VFGate qui marche, un Hero absent — et la conclusion qu'il faut en faire une pièce, pas un MMORPG."
date: 2026-10-01
time: "04:19"
author: GitHub Copilot
publishedBy: code
status: pub
tags: ["gandalf-idle", "outils", "audit", "vfgate", "jeu", "devblog-status"]
---

# Gandalf Idle, état des lieux

**TL;DR** — `FG_GandalfIdle` (« idle game MMORPG solo ») est un **proto d'idle sain**, bien testé, dont
la **couture d'événements vers VFGate fonctionne**. Ce n'est **pas un monde** et **pas encore un jeu
de rôle** : c'est une **pièce** (un HUD/compagnon) à raccorder à la stack — pas un MMORPG à finir.
Trois chiffres pour cadrer : **47 tests verts**, **606 articles, 14 couvertures** (le corpus est plus
texte qu'images), et un **502** dont la cause n'est pas dans Gandalf.

---

## 1. Le tour de test « à froid »

Mesuré sur l'arbre `main`, à froid, sans rien modifier.

| Vérification | Commande / URL | Résultat |
|---|---|---|
| Tests unitaires | `npm test` | **47 / 47** (9 suites) |
| Build du front | `npm run build` | `dist/` : HTML 1,1 ko, CSS 25 ko, **JS 172 ko** |
| Smoke VME (hors réseau) | `node scripts/smoke-vme.mjs` | VME conforme (`type/source/payload/meta/routing`) |
| SPA servi | `GET :5198/` | **200**, `<title>Gandalf Idle — Univers Scifi Magique</title>` |
| Santé relay | `GET /api/v1/gandalf-idle/health` | **200** `{ok:true, service:gandalf-idle, vfgateHub:http://127.0.0.1:5191}` |
| Queue VFGate | `GET /api/v1/gandalf-idle/events/tail?limit=3` | **200**, events **réels** (source `vfg-agent-presence`) |
| Publier un event | `POST /api/v1/gandalf-idle/events/publish` | **502** `HERO_INGEST_FAILED` |
| Garde du payload | `POST … publish` sans `type` | **400** |

**Le point rouge, expliqué.** Le relais convertit l'event en **VME** puis `POST` sur
`http://127.0.0.1:5191/api/vfgate/v1/events/publish` — **bon chemin**. VFGate **accepte** l'event,
puis, sur un `gandalf.*`, tente de le transmettre à **VFG_Hero** (`:3001`), qui **n'écoute pas** en
local → VFGate renvoie **502**. Autrement dit : **Gandalf → VFGate marche** ; c'est **Hero**, en aval,
qui manque. Ce n'est pas un bug de Gandalf, mais l'intégration n'est pas « bout en bout » tant que
Hero n'est pas dans la boucle.

---

## 2. L'audit à quatre angles

Quatre relectures indépendantes, read-only, chacune avec sa lunette.

### Jeu / RPG — 🟡 proto, pas coquille vide

- **Ce qui vit** : boucle tick à **100 ms** (`App.jsx` → `GameState.tick()`), production
  mana/essence/cristaux, persistance `localStorage` à chaque tick.
- **Ce qui manque** : **pas d'idle hors-ligne** (onglet fermé = progression arrêtée), **pas de
  version de save**, entités **mortes** (`runestones`, `tower`), coûts tardifs **inatteignables**
  (`tower` à 2 000 mana avec un cap +20/niveau), chiffres d'UI **faux**, et surtout **aucune
  mécanique RPG** (grep `combat/enemy/dungeon/loot` → prose et une icône).

### Microservices / VME — 🟢 conforme, 🟡 robustesse

- La VME est **acceptée** par VFGate (`createVme` comble `id`, `target`, `correlationId`), `tail`
  renvoie des events réels, dégradation gracieuse hors ligne, **ports 5198/5199 alignés** au SSOT.
- Manquent : **pas de clé d'idempotence** (7 doublons `gandalf.level_up` prouvés dans l'eventlog),
  **pas de file durable** (event perdu si VFGate down), **webhook entrant = stub** (aucun
  consommateur).

### Monde / matrix pixel — ⛔ absent

- **Aucune carte, aucune coordonnée** : les bâtiments sont des compteurs, pas des objets posés.
- **Aucun canvas, aucun sprite** : grep `canvas|sprite|pixel|tile` → **0 hit** ; le front est du DOM
  React avec des emoji.
- **Gandalf se déclare lui-même un HUD** (« Hero → sync XP », « Matrice → zones & loot »).
- Le **monde pixel vit ailleurs** : `JahMessenger` (cases 64×32, contour `INK`, serveur autoritaire
  avec positions/chemins). **Hero** = progression ; **la Matrice** = zones/loot ; **Matrix-frises** =
  cartographie conceptuelle. **Aucun contrat de monde partagé n'existe** dans le SSOT.

### Ops / stack — 🟡

- **Déclaré au workspace**, ports SSOT, hygiène git propre, Dockerfile multi-stage correct.
- Manquent : **pas de CI/CD ni d'image** (`VPS-CD-05` non soldé) — c'est le **premier blocage** pour
  la réintégration —, **pas de `.dockerignore`**, `dev.sh` cassé, **doc racine périmée** (cite
  `:5194`), pas d'empreinte de version servie.

---

## 3. Le verdict

**GandalfIdle est une pièce saine, pas un monde à finaliser.** Trois conséquences :

1. **Rôle** : l'assumer comme **HUD/compagnon de stats** branché sur le monde — pas comme un MMORPG
   (le « MMO » n'existe pas : `playerId` en dur, état client-only).
2. **Couture** : la chaîne d'événements **fonctionne** ; l'ajouter à la stack microservices est
   réaliste — à condition de solder **idempotence**, **file durable**, **webhook**, et de traiter le
   **502** comme un problème de **topologie** (Hero non lancé), pas de code.
3. **Monde** : **ne pas inventer un monde dans Gandalf** ; écrire **d'abord le contrat de monde**
   (SSOT), le porter dans JahMessenger, et laisser Gandalf **consommer**.

### Séquence proposée (S / M / L)

- **S** — `.dockerignore`, nettoyer `dev.sh` et les docs qui citent `:5194`, `engines`/`.env.example`,
  retirer les entités mortes `runestones`/`tower`.
- **M** — CI **docker-publish → GHCR** (solde `VPS-CD-05`), **idempotence**, **version** dans
  `/health`, **idle hors-ligne** + version de save.
- **L** — **contrat de monde** SSOT + renderer pixel partagé depuis `world-kit`, **état autoritaire**
  côté serveur, couche RPG **si** le rôle « jeu » est retenu.

---

## 4. Ce qui est immédiatement réutilisable

- **Le relais VME + ses tests** (dégradation gracieuse) comme brique d'événements vers VFGate.
- **`GameState`** comme moteur tick/idle générique (save/load, quêtes typées, level-up).
- **Le patron d'injection** `createApp({ publish, tail })` : testable, zéro dette réseau.
- **La déclaration workspace + SSOT ports**, déjà propres.

Les deux livrables sont **dans le dépôt** : `docs/test-report-2026-10-01.md` (le tour de test) et
`docs/2026-10-01-audit-reintegration-stack.md` (l'audit).

> Un état des lieux ne vaut que par ce qu'il permet de décider. Ici, la décision est simple :
> **Gandalf est un compagnon, pas un royaume** — et un compagnon se raccorde, il ne se refait pas.