CURRENT_SLOT_REFACTOR_AUDIT.md

Audit du projet existant (Tails Never Fails v2, approuvé & publié) en vue du Slot Factory Engine Réf. audité : TAILS NEVER FAILS/game/index.html (2 551 lignes : ~874 CSS + ~1 508 JS + DOM) · TAILS NEVER FAILS/math/tails_never_fails/ · état au 15 juil. 2026.

Règle d'or de cette migration : la build v2 approuvée par Stake est GELÉE. On ne refactore jamais le fichier soumis en place ; on extrait vers le moteur et TNF devient un consommateur de la couche partagée. Zéro risque de régression sur un jeu déjà en production.


0. Chiffres du couplage (mesurés)

Mesure Valeur Verdict
Fichier unique index.html 2 551 lignes Monolithe — à découper en modules
Chemins d'assets codés en dur 70 (./assets/...) À déplacer vers un asset manifest par thème
Références au thème (goblin/panther/ferret) 52 Majoritairement déjà dans des objets data → JSON de thème
Constantes math dans le front FREE_FLIPS=5, BUY_COST=100 (+ P_TAILS dans le bloc demo) À servir par la config du jeu (dérivée d'index.json math)
Blocs demo strippés par regex 2 blocs __DEMO_ONLY Fragile — remplacer par une vraie étape de build
Assets totaux ~123 Mo (52 Mo de clips villains) OK pour TNF (jeu à vidéo) ; INTERDIT pour un slot à rouleaux (voir PERFORMANCE_BUDGET)

1. DÉJÀ GÉNÉRIQUE — extraire tel quel (les bijoux de famille)

Ces systèmes ont été validés en production par la review Stake. Ils deviennent les premiers modules du moteur, quasiment sans modification.

Système Où (repères) Devient
Client RGS completrgsCall, authenticate/play/end-round/balance/bet-event, montants en micro-unités (×1e6), params de launch (rgs_url, sessionID, lang, device, social, currency), reprise de round actif, erreurs (y compris erreurs dans un body 200, quirk vérifié contre le source ts-client), payoutMultiplier float direct, /bet/event en string let RGS = {...} + rgsCall packages/stake-rgs/ — LA couche Stake Integration, commune à tous les jeux
Bet Replayreplay=true, GET /bet/replay/..., bet bar visible, SPIN rejoue, zéro appel wallet authentifié bootReplay() Module replay du moteur (mode du GameCore)
Couche social/stake.us — table STR/STR_SOCIAL (bet→play, pays→wins…), SC/GC sans $, audité 0 résidu S(), applyStrings() Module i18n+compliance (le pattern de substitution est générique)
Audio Web AudioloadBuf/sfx, décodage buffers, armAudio sur geste, résilience iOS (resume dans sfx + au trigger bonus), holdBgm/releaseBgm autour des cinématiques, alias de fichiers, fallback HTMLAudio bloc audio modules/audio/ — AudioBus générique piloté par manifest
Lecteur de cinématiquesplayCinema/hideCinema : safety timeout, hook « pluie à N s de la fin », fondu du coin, shield anti-tap modules/cinematics/
fitVal() — aucun montant ne déborde jamais de sa plaque (boucle scrollWidth, min 8px) util UI du moteur
Framework modales conformité — règles/paytable (disclaimer officiel verbatim, table coût/RTP/max-win par mode), confirmations autoplay & bonus-buy .modal-veil etc. modules/modals/ + contenu injecté par config
Gestion d'erreurs — écran fatal, toasts, codes RGS fatal(), toast() GameCore
Harnais de QA Playwright — screenshots multi-viewports, forçage d'événements, comparaison au mockup, tests de clic/opacité scripts scratchpad de la session factory/qa/ — formalisé en scripts de validation (Phase 10)
Pipeline de déploiement — wrangler Pages, previews hashées par déploiement factory/deploy/

2. RÉUTILISABLE APRÈS REFACTOR LÉGER

Système Couplage actuel Refactor
Moteur FX texte or (fxAnnounce canvas : layout par glyphe, enter/hold/exit, sticky+tags, halo, pièces) Cinzel 900 + palette or codées en dur ; coords cy par jeu Paramétrer police/palettes/positions via thème → modules/fx-text/
Acteur personnage chroma-key (villainLoop : distance couleur + de-spill sur canvas, crossfade #villainFade, boucles panic alternées) CHROMA par villain, chemins _gs.mp4 en dur modules/character-actor/ : config {clips, chromaRGB, states, loopPolicy}. Réutilisable pour TOUT jeu à personnage réactif (gros différenciateur Cool Kids)
Autoplay (compteurs, garde bonus/busy, confirmation) mélangé au flux TNF Extraire la machine à états ; hooks onAutoStep
Logique bet bar (stepper mise, MAX, clamp 0.10..balance, niveaux RGS, ~30 devises) skin TNF dans le CSS Séparer logique (générique) / skin (thème)
Objet 3D CSP-safe (Three.js + glTF en data-URI car le CDN Stake bloque blob:) Coin.gltf spécifique Pattern documenté + loader générique modules/three-actor/ (optionnel par jeu)
Pattern playBook — itérer les events du book → handler map (evCoinFlip, evBonusTrigger…) — c'est exactement le bookEventHandlerMap du web-sdk handlers spécifiques TNF Le moteur fournit playBook + bus d'événements ; chaque jeu déclare ses handlers (cœur de l'architecture Phase 4)

3. FORTEMENT COUPLÉ AU THÈME (à passer en config/thème JSON)

4. FORTEMENT COUPLÉ AUX MATHS ACTUELLES

5. À RECONSTRUIRE (n'existe pas dans TNF)

Tout le cœur « rouleaux » — TNF est un coin-flip, il n'y a NI grille, NI symboles, NI paylines : * ReelGrid (n×m, masque, cadre), reel strips, spin/stop/anticipation, turbo ; * évaluation des gains (paylines / ways / cluster / scatter-pays) côté présentation uniquement (le résultat vient toujours du book) ; * présentation des gains (lignes, compteur, paliers Big/Mega/Epic Win) ; * cascades/tumble, symboles spéciaux (wild/scatter/mystery/sticky/géants).

→ C'est le chantier neuf principal. Recommandation techno en Phase 4 (PixiJS 8 self-hosté pour le rendu grille, en s'appuyant sur les schémas du web-sdk officiel — bookEventHandlerMap, typesBookEvent — dont on a déjà un fork dans game/web-sdk-app/).

Côté math : le math-sdk officiel gère nativement reels/paytable/optimizer — nos scripts (generate_v2.py, verify_v2.py) apportent en plus le pinning RTP exact en Fractions et le vérificateur book↔LUT ligne à ligne → généralisés en factory/math-tools/ (validation de N'IMPORTE quel package math avant soumission).

6. À SUPPRIMER / ASSAINIR

Élément Action
play.html (redirect legacy) Supprimer du moteur (garder dans TNF gelé)
Assets sources non référencés (mp3 bruts, mockups, vieux boutons — déjà exclus du zip v2) Politique factory : les sources vivent HORS de game/assets/ (dossier art-src/ non buildé)
Strip des blocs demo par regex Étape de build réelle (flag --production qui exclut le module mock/devpanel)
Duplication dist-submission* à la main Généré par l'action Export du Slot Factory

7. RISQUES IDENTIFIÉS & PARADES

Risque Gravité Parade
Régression sur TNF publié ÉLEVÉE TNF v2 gelé ; migration sur COPIE ; diff visuel Playwright pixel-à-pixel avant tout swap
Le moteur reels devient une usine à gaz abstraite ÉLEVÉE On ne généralise que ce que DEUX jeux réels consomment ; chaque module doit avoir un consommateur concret (règle : pas d'abstraction sans 2e client)
Poids assets des slots vidéo-heavy MOYENNE Budgets stricts par catégorie (PERFORMANCE_BUDGET.md) ; le style « personnage vidéo chroma » reste un module OPT-IN coûteux
Sur-couplage au web-sdk Svelte (chaîne de build lourde) MOYENNE On adopte les schémas du web-sdk (events, structure math) sans forcément sa stack UI ; décision argumentée en Phase 4
Pièges Safari re-découverts à chaque jeu (filter+transform, background-clip+scale, clip-path+filter, autoplay audio…) MOYENNE Tous les pièges rencontrés sont encodés dans le moteur (lint CSS + doc SAFARI_TRAPS.md + tests QA dédiés)
Deux sources de vérité front/math MOYENNE La config front est générée depuis le package math (costs, wincap, features) — jamais éditée à la main

8. Verdict de migration TNF

TNF ne devient PAS un jeu à rouleaux : il est migré comme « template machine ultra-simple » du factory — il consomme stake-rgs, audio, fx-text, character-actor, cinematics, modals, i18n, et garde sa présentation propre. C'est la preuve vivante que le moteur supporte des jeux non-reels (l'ADN Cool Kids), pendant que le template reels 5×3 sert les jeux « classiques » (cowboy, aliens, mythologie, horreur).


9. RÉSULTAT DE MIGRATION (exécutée)

La migration décrite au §8 a été réalisée le 2026-07-15 :