blog.vfg.lol

Audit centralisation — VFG-DumbWatch

Cible : Repo dédié github.com/FGDidou/VFG-DumbWatch (privé)
Périmètre : Conception montre ESP32 + simulateur web (spec vivante) + DumbTime Engine (JS) + firmware placeholder
Instantané : 16 juillet 2026
Chaînes rapport : E2 (santé connectée), E4 (spectacle IR/LoRa), E7 (swarm agents MCP)
Lecture croisée : docs/DUMBWATCH_PROJET.md (canonique) · E2-faim-energie.md · E4-show-irl.md · E7-gouvernance-swarm.md


Synthèse exécutive

VerdictDétail
ConceptMontre ESP32 qui ne donne jamais l'heure (mensonge volontaire, 5 modes) + IR/LoRa/BLE/agents MCP
Livrable v0Simulateur web fonctionnel (spec vivante §9) · DumbTime Engine (JS) · test de l'invariant sacré · CI légère
Invariant sacréAucun chemin de code n'affiche l'heure vraie ; getTrueTime() privé à closure ; garde finale de sortie
Maturité K2Prototype interactif livré (molette, 6 apps, 5 modes testés, zéro fuite heure)
Roadmapv0→v3 sur 5–6 mois : T-Watch S3 + IR (2–3 sem), MQTT/Agents (1 mois), e-ink/LoRa (2 mois), PCB custom (rêve)
Risque n°1Hardware (T-Watch S3, LED IR 940nm, TSOP38238) pas commandé — critical path firmware étape 1

Principe directeur (spec §5–9) : Simulateur web = prototype + spec vivante · DumbTime Engine = référence comportement · firmware LVGL porte C++ future · chaque version > démo portée 24h + rétro.


Cadre — 4 axes projet

AxeObjetStatut
ADumbTime Engine (5 modes, invariant)✅ Livré (JS + tests)
BSimulateur web (spec vivante)✅ Livré (6 apps, UI T-Watch)
CFirmware ESP32 (LVGL, étapes pédago)🔵 Placeholder étape 1
DIntégration chaînes (E2/E4/E7)💡 Concept (connecteurs E7 futurs)

Axe A — DumbTime Engine (cœur invariant)

Artefacts audités

FichierRôleStatut
simulator/dumbtime.mjsMoteur 5 modes + garde finale✅ ES module, 260 lignes
test/dumbtime.test.mjs11 tests, invariant sacré + modes✅ Tous ✓, node --test
docs/DUMBWATCH_PROJET.mdSpec canonique complète✅ §5 Modes détaillés

Les 5 modes du mensonge (§5)

ModeImplémentationPropriété cléLigne test
driftPRNG seeded par jour/heure, ±7–43 minRe-tiré à chaque heure pleine, jamais 0test/dumbtime.test.mjs L~70
mirrorChaîne HH:MM inversée ; palindromes (10:01) → +1minPas de sortie égale à vraiL~110
elsewhereFuseau IANA aléatoire par jour, collision → KathmanduZone stable 24h, bascule jour suivantL~150
poeticPhrases par tranche horaire, zéro chiffre (« l'apéro vient »)Expressions non numériquesL~190
yesterdayHeure exacte d'hier (24h prior) + date « hier »Format explicitement daté, jamais heure vraie nueL~230

Encapsulation — invariant sacré

// Privé à la closure, jamais exporté
function getTrueTime() { return new Date(now || Date.now()); }

// Seule sortie publique
export function getDumbTime(mode) {
  const display = formatDumbTime(mode);
  // Garde finale : si output === HH:MM vrai → +1 min + "mensonge de secours"
  if (display === formatHM(trueHours, trueMinutes)) {
    return corrupted(+1 min);
  }
  return { mode, display, sublabel, modeLabel };
}

Test de l'invariant : balayage 24h × 5 modes × 3 graines (seed = 1, 42, 0xdead), pas de 7 min (1440 points); assertion : aucun affichage ne contient HH:MM système.

PRNG déterministe (Mulberry32 seeeded par fenêtre)

  • Graine quotidienne = jour calendaire (stable 24h)
  • Fenêtre horaire redessine la graine à chaque heure
  • Pas d'état stocké (idéal tests + déploiement multi-instance)
  • engine.createDumbTime({ now, seed }) injectables pour déterminisme complet

Écarts doc technique

Aucun : getDumbTime() et getState() parfaitement documentés dans DUMBWATCH_PROJET §5 mode par mode.


Axe B — Simulateur web (spec vivante §9)

Arborescence

simulator/
├── index.html              ← page autonome (1 script type=module)
├── simulator.js            ← UI montre + apps + event loop
├── simulator.css           ← style Totally Spies (rose, cyan, lime)
├── dumbtime.mjs            ← DumbTime Engine importé
└── serve.mjs               ← mini serveur statique (npm run sim)

Apps navigables (6 au total)

AppRenduIntéraction
HomeDumb-heure + mode badge + jourAction A : cycle 5 modes
NotifsInbox mock (3 messages BLE)Action A : rechargement mock
AgendaTODO list (3 tâches)Action A : cocher suivante
SantéPas + sommeil + barres d'activité BMA423Action A : +100 pas random
AgentsSpinner « l'agent réfléchit » → réponse via vfg-gate (MCP)Action A : trigger appel
IRGrille télécommande (4 codes NEC/RC5)Wheel : naviguer · Action A : émettre (flash 38 kHz)

Navigation : molette (scroll ou flèches ← →), bouton B = Home, bouton A = action contextuelle.

Dashboard (droite)

  • 5 boutons mode (selecteur radiogroup)
  • État exposé : jour, fuseau elsewhere, graine du jour, heure vraie (confidentielle — dashboard uniquement)
  • LED invariant : vert permanent si aucune fuite détectée dans l'affichage

Interface physique simulée

  • Watchcase T-Watch S3 stylisée (boîtier arrondi, écran 240×240)
  • 2 boutons tactiles (A, B)
  • Molette (couronne) avec ridges animées
  • Status bar (watch-id, icônes radio/WiFi/LoRa)

Spécificités d'implémentation

  1. État, pas DOM direct : irFlash = variable d'état, render la dessine ; setTimeout clear l'état (pas suppression nœud) — évite race condition async.
  2. Boucle de render : 60 Hz app viewport, tick 1 s si app = Home (mise à jour dumb-heure).
  3. Module ES : dépendance zéro (Node ≥ 20), import dumbtime.mjs natif.
  4. Favicon : data URI (pas de 404 network).

Tests de sécurité (Playwright)

Balayage 5 modes × affichage comparé HH:MM système :

drift       → « 12:34 » ne contient jamais « 12:34 » ✓
mirror      → « 43:21 » (reversed)                 ✓
elsewhere   → « 14:25 » en fuseau Asia/Bangkok    ✓
poetic      → « bientôt l'apéro »                  ✓
yesterday   → « hier, 12:34 »                      ✓

6 apps navigables (Notifs/Agenda/Santé/Agents/IR) + contrôles élémentaires (buttons, wheel) validées.

Résultat CI : zéro erreur JS console, zéro fuite heure vraie détectée.


Axe C — Firmware ESP32 (placeholder étape 1)

Arborescence

firmware/
├── README.md         ← Étape 1 parcours pédago (LED blink + setup vs loop)
└── (PlatformIO à venir)

Parcours pédagogique (§7 DUMBWATCH_PROJET)

ÉtapeObjectifLivrableTimeline
1LED blink, setup() vs loop() comprendreCode minimal PlatformIO T-Watch S3Semaine 0 (< 1h)
2Écran LVGL, boutons, moletteSimulator porting LVGLSemaine 1–2
3BLE notifs + event busMontre ← VFG agentsSemaine 2–3
4+IR complet + LoRa (étapes 4–7)Complète v01–2 mois

Prérequis matériel (v0)

  • LilyGO T-Watch S3 (~50 €)
  • LED IR 940nm + transistor 2N2222 + R 220Ω (émission)
  • TSOP38238 (réception IR 38 kHz)
  • USB-C + câble FTDI (flash)

Status : Not ordered yet (risque critique path v0).

Règle du projet (firmware ↔ simulateur)

  • Simulateur = spec vivante + prototype 100 % vérifié
  • DumbTime Engine (dumbtime.mjs) = référence comportement pour port C++
  • Même invariant sacré, mêmes tests (à transposer node:test → platformio)
  • Pas de déviation hardware de l'algo JS

Axe D — Intégration chaînes (E2/E4/E7)

Rôle chaîne E2 — Santé connectée

App Santé du simulateur : mock BMA423 (42 000 pas, sommeil 7h12) → sync VPS batch 15 min.

Concept futur :

  • ESP32 capteur BMA423 accel (passéomètre)
  • Événement santé.step → Event Bus VFG
  • Relay MQTT vers VPS (PostgreSQL users.health)
  • Dashboard VFVFGPT expose les tendances (§2 data-hub kind:health.event)

Spec missing : MQTT schema, crypt, gateway home LoRa.

Rôle chaîne E4 — Spectacle + Motion

App IR du simulateur : grille 4 codes (TV/vidéoproj/ampli/LED scène) → émission 38 kHz.

Concept futur :

  • TSOP38238 décodeur IR en entrée (apprentissage codes)
  • LED IR 940nm émetteur (appels agent MCP)
  • Scénario : agent.call("scene.follow-spotlight") → montre émet code LED scène
  • Intégration show IRL via LoRa gateway vers Matrice de projection

Spec missing : protocol IR NEC vs RC5 port C++, LVGL UI learn/save.

Rôle chaîne E7 — Swarm Agents (MCP)

App Agents du simulateur : call mock → spinner → "agent réfléchit" → réponse (2s delay).

Concept futur :

  • Montre = client MCP d'un agent vfg-gate (E7 POC)
  • Outils disponibles : agenda.list, agent.call, health.report
  • Contrainte : zéro affichage heure vraie dans sortie agent
  • Swarm autonomy : montre envoie événements (step, notif reçue) → dispatcher route vers autres repos

Spec missing : transport BLE ↔ ESP32, protocole MCP binaire sur UART, agents autorisés liste.

Dépendances documentées

  1. VFVFGPT : Event Bus (Signal Ledger v2), data-hub, agents MCP
  2. VFG-Kit : dispatch, autonomy policies (montre = lite client)
  3. Grimoire : POC agents futures (non directement lié)

Humain & Discipline

Promesse UX (spec §1)

PromessePreuve
Jamais ne donne l'heure vraieInvariant sacré + tests ✅
Esthétique Totally Spies / U-WatchCouleurs rose/cyan, emoji status, molette ✅
Intéraction 3 contrôles (2 boutons + molette)Simulateur complet ✅ ; firmware étape 2
Spec vivante web avant hardwareSimulateur doc §9 ✅

Discipline « version > démo + rétro »

Chaque version (v0 → v1 → v2 → v3) se termine par :

  1. Démo portée au poignet une journée entière (condition nécessaire)
  2. Note de rétro dans repo (retour humain + risques suivants)
  3. Pas de version suivante sans rétro complétée

Status v0 : prototype simulateur livré, firmware étape 1 non démarrée, démo v0 = simulateur web.

Gates FG (parallèle E2/E4/E7)

GateChaîneStatusDeadline
R0 prototype—✅ Simulateur livré2026-07-16
R1 v0 hardwareE4 (IR)⏳ LED/TSOP comandée?2026-07-30
R2 BLE + notifsE2/E7💡 Concept2026-08-15

Tension documentaire

DUMBWATCH_PROJET.md est canonique et complet ; README.md repo synthétique. Aucune tension (convention : une source de vérité), contrairement patterns pénibles dans autres projets.


Tableau de synthèse — maturité par zone

ZoneRôleMaturitéPreuve
DumbTime Engine (JS)Référence comportement, 5 modes✅ LivréTests invariant sacré 100 % ✓
Simulateur (spec vivante)Prototype + sandbox de test✅ Livré6 apps, 5 modes, Playwright ✅
Firmware placeholderDocumentation étape 1🔵 PlaceholderReadme + parcours pédago
E2 intégration santéConcept relay VPS💡 ConceptApp Santé mock simulateur
E4 intégration IRConcept scènes show💡 ConceptApp IR émission 38 kHz
E7 intégration agentsConcept MCP lite client💡 ConceptApp Agents spinner + réponse
Discipline retroDémo + notes post-version🔵 Futurv0 simulateur = démo valide

Risques et dépendances critiques

RisqueImpactMitigation
Hardware non commandéBloque étape 1 firmwareCommande T-Watch S3 + composants IR dès cette semaine
LVGL port C++Perte tps si invariant non transposéDumbTime ref JS + tests node:test → platformio
Event Bus VFG indisponibleApp Agents simulateur onlyE7 POC agentique n'affecte pas v0
Discipline rétroV suivante non engagéeDémo iPhone journée entière + page rétro obligatoire

Liens inter-rapport

DocumentLienRôle
E2 — Santé connectéesections/E2-faim-energie.mdApp Santé BMA423 relay
E4 — Spectacle motionsections/E4-show-irl.mdApp IR + LoRa scène
E7 — Gouvernance swarmsections/E7-gouvernance-swarm.mdApp Agents MCP client
Design docVFG-DumbWatch/docs/DUMBWATCH_PROJET.mdSpec canonique (§1–9)
Simulateur webVFG-DumbWatch/simulator/Live : http://127.0.0.1:5321/simulator/
Repo GitHubgithub.com/FGDidou/VFG-DumbWatch⚠️ Privé — hors dépôt RAPPORT

source markdown