Config strictement stricte partout (ruff, mypy --strict, bandit, vulture,
import-linter, eslint, stylelint), aucune regle desactivee "pour ne pas
casser le build" - l'existant a ete corrige pour la satisfaire plutot que
l'inverse. Hooks pre-commit locaux (language: system) bloquants.
- Typage mypy --strict propage a tout le moteur (db, screens, auth, core,
ai, routes, puis publish/scripts/tests/app.py/build_css.py).
- Securite : fuite de handle fichier Windows corrigee dans l'export SCORM
(routes/publish/export_scorm.py), CSRF/RNG non-crypto/xAPI documentes
(# nosec, # NOSONAR justifies), nouveau db.json_for_script() (echappe
"</script>" dans le JSON embarque en <script>, 25 sites).
- Architecture : imports circulaires/F811 nettoyes, contrats
import-linter respectes, code mort retire (vulture).
- Accessibilite : 69 champs de formulaire sans label correctement
associe corriges (for/id ou aria-label) sur 11 templates.
- ESLint/Stylelint : lot mecanique JS/CSS, regles ajustees puis
appliquees (aucune desactivee sans verification individuelle).
- Tests : isolation du compte admin partage (nettoyage ponctuel +
fixture de teardown automatique en filet de securite), suite complete
verte (591 tests Python, 241 tests JS).
- SonarQube Community Build self-heberge (Docker + PostgreSQL) : rapport
complet analyse point par point, faux positifs documentes.
- .gitattributes ajoute (LF force) : core.autocrlf=true sur cette machine
faisait echouer ESLint (linebreak-style) via un bug connu de git
(checkout "en place" qui ignore l'eol force sur un fichier deja
present sur disque - contourne en supprimant puis recreant chaque
fichier suivi).
djLint (H021, styles inline) volontairement saute pour ce commit -
backlog assume, deja documente, traite dans un lot separe.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Ajoute deux mécanismes distincts, à la demande de l'utilisateur qui a
précisé qu'un son doit pouvoir être attaché à une SCÈNE (pas seulement
joué ponctuellement par une action de flow, comme prévu initialement) :
- Musique de fond par écran (nouveau champ background_music_url sur
_screens, ALTER TABLE nullable) : réglée dans le panneau gauche de
l'éditeur (URL ou envoi de fichier, réutilise la route d'upload
générique existante), enregistrée en AJAX au même patron que le format
d'aperçu (screen_set_aspect.py). Démarrée en boucle à l'affichage de
l'écran et arrêtée au changement d'écran (runScreenBackgroundMusic(),
appelée depuis showScreen() dans static/js/play/screens.js) — un seul
Audio actif à la fois, jamais cumulé avec une musique restée d'un écran
précédent.
- Action de flow "jouer_son" (aux côtés des actions existantes) : effet
sonore ponctuel, non bouclé, déclenchable sur n'importe quel nœud
Déclencheur. Réutilise data_value (déjà un champ texte générique sur
le nœud action, comme pour "attendre") plutôt qu'une nouvelle colonne
dédiée — fire-and-forget côté client (runActionNode), ne bloque jamais
la suite du graphe.
Les deux réutilisent le même mécanisme d'upload de fichier déjà en place
ailleurs dans l'éditeur (ex. source d'une vidéo), sans nouvelle route.
Ceci complète les 6 phases du plan d'extension du moteur (état par
joueur, hasard/maths, clavier/minuteur, ajout de ligne, position/
collision, son) : Forge Engine peut désormais couvrir des jeux bien
au-delà du narratif/puzzle/quiz (action, arcade, jeux à contrainte de
temps).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>