---
title: "STATUS — FG_GandalfIdle — 2026-10-06"
date: 2026-10-06
time: "09:30"
author: agent
publishedBy: code
status: pub
tags: ["status", "gandalf-idle"]
---

# STATUS — FG_GandalfIdle

_Article généré automatiquement depuis le STATUS.md de FG_GandalfIdle — 2026-10-06. Les chemins locaux, les hôtes internes et les noms de variables ont été neutralisés._

# FG_GandalfIdle — STATUS

> **Repo** : `FG_GandalfIdle` · **Rôle** : compagnon idle (LE COMPAGNON) · **Ports** : 5198 web · 5199 relay

## État

| Item | Statut |
|------|--------|
| Core gameplay POC | 🟢 Sprint 1 local |
| Relay VFGate :5199 | 🟡 POC |
| Hub API Sprint 2 | ⛔ roadmap |
| Hero bi-directionnel | ⛔ Sprint 3 |
| Tests `npm test` | 🟢 47 tests (GAND-01) |
| Routes `/api/v1/gandalf-idle/*` | 🟢 implémentées (relay :5199) |

## I/O

Fiche boundary : [`docs/io-review.md`](./docs/io-review.md)

## Dev

```bash
npm install
npm run dev   # :5198 + relay :5199
```

## Tests & smoke (GAND-01)

```bash
npm test                          # node --test, harnais relay/VME (47 tests)
node scripts/smoke-vme.mjs        # construit + valide une VME de démo (no-op réseau)
node scripts/smoke-vme.mjs --publish  # idem + tente POST vers relay local :5199 (best-effort, opt-in)
```

- `test/to-vme.test.js` — `gameEventToVme` : champs requis, `routing.topic`/`type`, `source.channel`/`account`, `meta.at`, cas limites (event sans `data`/`source`/`timestamp`).
- `test/events.test.js` — `normalizeEventRows` (formes de payload tail, fallbacks), `emitGameEvent`/`syncState`/`fetchRecentEvents` avec `fetch` injecté (succès, offline, erreur HTTP, cas limites limit).
- `test/ports.test.js` — cohérence des constantes (`GANDALF_SOURCE_ID`, alias dépréciés, base URL hub).
- `test/server.test.js` — `incomingToVme` (pass-through VME vs conversion legacy), routes Express `/api/v1/gandalf-idle/health`, `/events/publish`, `/events/tail`, `/api/events`, `/api/status` (app créée via `createApp({ publish, tail })` injectés — aucun appel réseau réel) ; `publishVmeToHub`/`fetchHubTail` (dégradation gracieuse offline/erreur).

### Routes `/api/v1/gandalf-idle/*` (relay :5199, `src/vfgate/server.js`)

| Route | Méthode | Description |
|-------|---------|--------------|
| `/api/v1/gandalf-idle/health` | GET | health check local (ports, hub configuré, timestamp) |
| `/api/v1/gandalf-idle/events/publish` | POST | convertit (si besoin) un event legacy en VME via `gameEventToVme`, puis publie vers `VFGATE_API_BASE/api/vfgate/v1/events/publish` (graceful offline) |
| `/api/v1/gandalf-idle/events/tail` | GET `?limit=` | proxy vers `VFGATE_API_BASE/api/vfgate/v1/events/tail` (graceful offline) |

Ces routes sont **locales au relay gandalf-idle** (alias namespacés des routes legacy `/api/events` et `/api/events/tail`, mêmes garanties de dégradation) ; elles réutilisent le contrat hub `/api/vfgate/v1/events/*` déjà documenté dans `VFVFGPT/config/ssot/bridge/vfgate.json`. **Aucun changement côté hub VFVFGPT n'est requis.**

### Note de conformité VME

`gameEventToVme` (donc `incomingToVme`/`/api/v1/gandalf-idle/events/publish`) produit une enveloppe avec `type, source, payload, meta, routing` — conforme au sous-ensemble utilisé par gandalf-idle. Le schema strict du hub (`vfgate.json` → `required`) liste aussi `id` et `target`, absents de l'enveloppe générée ici (génération côté hub probable lors du `publish`). Non bloquant pour l'usage actuel ; à clarifier si le hub exige ces champs en entrée.

## Workspace parent

Refs SSOT : `../workspace.manifest.json` · Hub : `../VFVFGPT/`

## EN COURS

| ID | Sujet | Owner | Branche | Bloqueur |
|----|-------|-------|---------|----------|
| VPS-CD-05 | URGENT VPS · docker-publish Gandalf → GHCR (remplacer build local gandalf-idle:latest) | agent | `main` | — |