Commit Graph
11 Commits
Author SHA1 Message Date
williamandClaude Sonnet 5 d92f75a803 Remplace la modale liste+menus deroulants du Scenario par un vrai graphe visuel
Build and deploy / test-python (push) Successful in 7m32s
Build and deploy / test-js (push) Successful in 49s
Build and deploy / lint-python (push) Successful in 5m21s
Build and deploy / lint-js (push) Failing after 1m12s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Build and deploy / sonarqube (push) Failing after 3m53s
Retour utilisateur : "passons a un veritable graphe visuel". Chaque
nœud gagne une position x/y (document_engine/labels/scenario_config.py
: un x/y manquant/invalide retombe sur un quadrillage en cascade derive
de l'index du nœud, jamais (0, 0) pour tous les nœuds qui les
empilerait au meme endroit).

Cote editeur (static/document/js/document-editor.js) : les nœuds sont
des cartes deplacables a la souris sur un canevas (glisser-deposer reel,
meme principe que le glisser des formes libres), les choix relies a une
cible sont dessines comme des fleches SVG etiquetees par leur texte
(jamais un menu deroulant). Editer le texte/les choix d'un nœud se fait
dans un panneau inspecteur (colonne de droite) pour le nœud
selectionne ; relier un choix se fait en cliquant "Relier" puis le nœud
cible sur le graphe (mode connexion, Echap annule sans fermer la
modale). La modale generique (.docModal*) est agrandie specifiquement
pour ce graphe (jusqu'a 1180px) sans toucher sa taille par defaut.

Verifie via simulation DOM reelle (jsdom) : rendu des nœuds/positions,
glisser-deposer avec persistance au relachement, traces des fleches SVG
+ etiquettes, workflow complet du mode connexion, suppression d'un nœud
avec reparation des references pendantes, et les 3 façons de fermer la
modale (bouton/fond/Echap) y compris l'annulation du mode connexion
sans fermer.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 09:03:47 +02:00
williamandClaude Sonnet 5 a529857379 Refonte du Scenario en arbre de decision (modale dediee, plus de vrai/faux
Build and deploy / test-python (push) Failing after 1m15s
Build and deploy / test-js (push) Successful in 54s
Build and deploy / lint-python (push) Failing after 1m12s
Build and deploy / lint-js (push) Failing after 1m8s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Build and deploy / sonarqube (push) Failing after 1m4s
Retour utilisateur : "une consequence peut mener a d'autres choix et
ainsi de suite, il n'y a pas de notion vrai/faux, il faut une modale
avec la possibilite de construire un veritable arbre de choix
consequence". Remplace le modele plat (situation + 2-4 choix + un seul
bon choix + une consequence terminale) par un vrai graphe de nœuds :
{"title", "nodes": [{"id", "text", "choices": [{"text", "target_id"}]}]}
- nodes[0] est la situation initiale, chaque choix peut pointer vers
n'importe quel autre nœud (branchement, convergence, fins multiples),
un nœud sans choix est une fin de branche valide. Aucune notion de
bonne/mauvaise reponse.

L'arbre se construit desormais dans une modale dediee (trop de
structure pour la colonne etroite du panneau Proprietes) : liste de
nœuds, chaque choix avec un menu deroulant "mene a" listant les autres
nœuds ou "fin de branche". La modale est un composant generique
(.docModal*) independant de tout framework externe.

sanitize_scenario_config degrade silencieusement tout target_id
orphelin (nœud supprime) vers None plutot que de faire echouer le
scenario entier. Le lecteur cote client navigue le graphe nœud par
nœud, le texte du nœud visite remplace le precedent (toujours pas un
Quiz), jusqu'a une fin de branche puis passage au scenario suivant.

Verifie via simulation DOM reelle (jsdom) : navigation ramifiee
(branchement, convergence, fin via nœud vide ET via choix sans cible),
plusieurs arbres a la suite, et l'editeur modal complet (ouverture,
ajout/suppression de nœud avec reparation des references pendantes,
changement de cible, fermeture bouton/fond/Echap).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 17:29:24 +02:00
williamandClaude Sonnet 5 c04a81cfec La consequence du Scenario remplace la situation, pas un feedback Quiz
Build and deploy / test-python (push) Failing after 1m2s
Build and deploy / test-js (push) Successful in 51s
Build and deploy / lint-python (push) Failing after 58s
Build and deploy / lint-js (push) Failing after 51s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Build and deploy / sonarqube (push) Failing after 1m1s
Retour utilisateur : "ce n'est pas un quiz, la consequence s'affiche a
la place de la situation precedente". L'ancien design affichait la
situation ET les choix en permanence avec un encart de feedback separe
en dessous (calque sur le Quiz). Desormais un seul bloc de texte
(.docScenarioSituation) sert successivement a la situation PUIS, une
fois un choix fait, a la consequence a sa place ; les boutons de choix
disparaissent avec elle. Supprime l'element .docScenarioConsequence
devenu inutile.

Verifie via simulation DOM reelle (jsdom) : la consequence remplace bien
le texte de la situation (jamais affichee a cote), les choix
disparaissent, le retour a une situation neutre au scenario suivant/au
redemarrage fonctionne.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 17:10:56 +02:00
williamandClaude Sonnet 5 b2292de122 Implemente le mini-jeu Scenario (situation, choix, consequences)
Build and deploy / test-python (push) Failing after 59s
Build and deploy / test-js (push) Successful in 50s
Build and deploy / lint-python (push) Failing after 59s
Build and deploy / lint-js (push) Failing after 1m1s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Build and deploy / sonarqube (push) Failing after 59s
Cinquieme mini-jeu du support de formation : le createur ecrit une
situation initiale, definit 2 a 4 choix, indique lequel est le bon, et
redige la consequence de chaque choix. Plusieurs scenarios peuvent etre
crees, joues dans l'ordre d'ecriture (jamais melanges, contrairement a
Association/Memory/Mots meles : ce sont des mises en situation
sequentielles). En Apercu, l'apprenant lit la situation, choisit une
option, decouvre la consequence de SON choix et si c'etait le bon, puis
passe au scenario suivant. Comme Association/Memory/Mots meles, le
dernier scenario reste affiche une fois repondu : seul le bouton
Recommencer apparait, jamais un ecran de resultat separe (reserve au
Quiz). Reutilise les classes visuelles du Quiz (docQuizOptions/
docQuizFeedback/docQuizNextBar) plutot que de dupliquer ces regles.

Verifie via simulation DOM reelle (jsdom) : progression entre plusieurs
scenarios, choix correct/incorrect avec revelation de la bonne reponse,
comportement de fin de partie, panneau Proprietes (ajout/suppression de
scenario, changement du nombre de choix, selection du bon choix).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 16:50:10 +02:00
williamandClaude Sonnet 5 d8be80ebd1 Implemente le mini-jeu Mots meles (grille reelle, placement 4 directions)
Build and deploy / test-python (push) Failing after 1m0s
Build and deploy / test-js (push) Failing after 50s
Build and deploy / lint-python (push) Failing after 1m2s
Build and deploy / lint-js (push) Failing after 1m7s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Build and deploy / sonarqube (push) Failing after 1m1s
Quatrieme mini-jeu du support de formation : le createur ecrit 5 a 10
mots (recommandation souple, comme MIN_PAIRS/MIN_CARDS), places par le
serveur dans une grille carree horizontalement, verticalement, ou en
diagonale (deux sens seulement, jamais a l'envers) via un vrai
algorithme de placement avec retry/agrandissement de grille en cas de
conflit. La grille ET la position exacte de chaque mot sont calculees
cote serveur puis embarquees en JSON ; le client valide chaque
selection (glisser ou cliquer-cliquer) par comparaison de coordonnees
exactes, jamais une simple comparaison de texte (qui se tromperait sur
des lettres partagees entre deux mots qui se croisent). Comme
Association/Memory, la grille reste affichee une fois tous les mots
trouves : seul le bouton Recommencer (.docMinigameRestartBar, partage)
apparait.

Verifie via simulation DOM reelle (jsdom) : selection au glisser ET au
clic-clic, mot invalide sans crash, barre de fin qui bascule, panneau
Proprietes (ajout/suppression de mot avec revalidation serveur).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 15:31:46 +02:00
williamandClaude Sonnet 5 1b1307bb85 Association et Memory restent affiches une fois termines, seul Recommencer bascule
Build and deploy / test-python (push) Failing after 59s
Build and deploy / test-js (push) Failing after 52s
Build and deploy / lint-python (push) Failing after 59s
Build and deploy / lint-js (push) Failing after 1m1s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Build and deploy / sonarqube (push) Failing after 1m4s
Les deux mini-jeux gardaient jusqu'ici un ecran de resultat separe qui
remplacait le plateau de jeu (comme le Quiz). Le plateau reste desormais
visible en permanence ; seule une barre partagee .docMinigameRestartBar
apparait/disparait. Le Quiz garde son propre comportement (ecran de
resultat separe), inchange.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 14:43:26 +02:00
williamandClaude Sonnet 5 4111081e1a Implemente le mini-jeu Memory (retournement de cartes, mode paire/single)
document_engine/labels/memory_config.py (nouveau) : modele de donnees,
meme convention resolve_X/sanitize_X que quiz_config.py/
association_config.py - DEFAULT_MEMORY_CONFIG, sanitize_memory_config.
Chaque carte a un recto ET un verso, chacun avec image/texte
independants et tous deux optionnels ; seul le verso doit avoir au
moins l'un des deux non vide (rien a reveler/apparier sinon) - le
recto peut rester entierement vide (dos de carte generique "?" par
defaut). Liste tronquee a MAX_CARDS=8.

Cote serveur, routes/document/document_element_update.py revalide
desormais aussi memory avant persistance. Le rendu (_render_memory)
affiche un resume reel (nombre de cartes, mode) et, des qu'au moins
une carte existe, un plateau de retournement REELEMENT interactif en
Mode Apercu (_render_memory_player) : en mode "paire", chaque carte
definie est DUPLIQUEE en deux instances partageant le meme card_index
(appariement classique) ; en mode "single", une seule instance par
carte (simple retournement, sans appariement - "c'est donc un
retourner de carte classique plus un jeu memory"). Les instances sont
melangees (random.shuffle, documente dans CODE_QUALITY.md) puis
embarquees en JSON dans data-memory-config.

Cote editeur, le panneau Proprietes propose un bascule segmentee
Paire/Simple et une liste de cartes repetable, chaque carte avec ses
deux faces (recto/verso) editables independamment (image + texte).
Extrait au passage forgeDocEscapeHtml (ex-forgeDocEscapeForTextarea,
generalise pour couvrir aussi les attributs) reutilise pour les deux
mini-jeux. Le plateau jouable (static/document/js/document-editor.js)
est une vraie carte-retournement CSS 3D (perspective/rotateY), contenu
de chaque face construit via DOM (textContent/img.src, jamais
innerHTML avec le texte du createur - meme precaution que le plateau
Association) : bon appariement verrouille en vert, mauvais reinitialise
apres un delai, ecran de resultat une fois le jeu termine (les deux
modes), et un "Recommencer" qui remelange reellement les cartes
(Fisher-Yates cote client).

Tests : 11 tests purs (tests/document/test_memory_config.py, sans
Flask, dont un qui verifie explicitement la duplication en mode paire
vs son absence en mode single) + 1 test de route verifiant la
sanitization a l'ecriture.

SKIP=djlint : backlog H021 pre-existant, aucun template touche ici.
ruff/mypy --strict/vulture/bandit/import-linter/eslint/stylelint tous
verts ; 62 tests document verifies frais. Verification manuelle live
complete : ajout, sanitization sur carte invalide, rendu du plateau,
et simulation DOM du gameplay reel dans les DEUX modes (mode paire :
mauvais appariement puis bon appariement puis jeu complet ; mode
single : retournement puis jeu complet) - script de diagnostic non
conserve dans le depot.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 14:13:28 +02:00
williamandClaude Sonnet 5 ce750ec697 Implemente le mini-jeu Association (glisser-deposer par paires)
document_engine/labels/association_config.py (nouveau) : modele de
donnees, meme convention resolve_X/sanitize_X que quiz_config.py -
DEFAULT_ASSOCIATION_CONFIG, sanitize_association_config (chaque paire
doit avoir ses deux cotes non vides, sinon supprimee silencieusement ;
liste tronquee a MAX_PAIRS=8).

Cote serveur, routes/document/document_element_update.py revalide
desormais aussi l'association avant persistance (meme raisonnement que
pour le quiz). Le rendu (_render_association) affiche un resume reel
(nombre de paires) et, des qu'au moins une paire existe, un plateau de
glisser-deposer REELEMENT interactif en Mode Apercu
(_render_association_player) : les deux colonnes (termes/
correspondances) sont melangees independamment (random.shuffle,
melange d'affichage documente dans CODE_QUALITY.md) puis embarquees en
JSON dans un attribut data-assoc-config.

Cote editeur, le panneau Proprietes d'une association ("relier
visuellement deux champs qui vont ensemble") est une liste de paires
repetable, chaque ligne reliant visuellement un champ "Element" et un
champ "Correspondance" par un glyphe ↔. Le plateau jouable en Apercu
(static/document/js/document-editor.js) supporte deux facons de jouer,
toutes deux reelles : glisser-deposer HTML5 natif, ou cliquer une
carte puis son emplacement (repli pour les appareils sans support
fiable du drag) - bonne association verrouillee en vert, mauvaise
signalee puis reinitialisee, ecran de resultat une fois toutes les
paires associees.

Bug reel trouve ET corrige via simulation DOM complete (glisser-
deposer + clic simules, pas juste un chargement de page) : le
feedback visuel reutilisait la classe CSS du quiz via une
reaffectation de className qui supprimait au passage la classe
d'identite docAssocFeedback, rendant l'element introuvable des le
premier essai de match (aurait plante en usage reel des la premiere
tentative). Corrige en gardant toujours les deux classes ensemble.

Tests : 8 tests purs (tests/document/test_association_config.py, sans
Flask) + 1 test de route verifiant la sanitization a l'ecriture.

SKIP=djlint : backlog H021 pre-existant, aucun template touche ici.
ruff/mypy --strict/vulture/bandit/import-linter/eslint/stylelint tous
verts ; 50 tests document verifies frais. Verification manuelle live
complete : ajout, sanitization sur paire invalide, rendu du plateau,
et simulation DOM du gameplay reel (glisser-deposer correct/incorrect,
clic-selection, progression, ecran de resultat) - script de
diagnostic non conserve dans le depot.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 13:01:21 +02:00
williamandClaude Sonnet 5 9fb22be1ae Quiz reellement interactif en Mode Apercu (voir maquette document-formation-web.html)
Build and deploy / test-python (push) Failing after 1m5s
Build and deploy / test-js (push) Successful in 51s
Build and deploy / lint-python (push) Failing after 1m2s
Build and deploy / lint-js (push) Failing after 1m4s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Build and deploy / sonarqube (push) Failing after 1m0s
Le quiz affichait jusqu'ici la meme carte resume en edition comme en
Apercu. Ajoute un vrai questionnaire jouable, visible UNIQUEMENT en
Mode Apercu (masque en edition via CSS, jamais les deux a la fois) :
options de reponse cliquables, marquage correct/incorrect immediat,
score qui accumule les points de chaque question repondue
correctement, progression "Question suivante", et un ecran de
resultat final (score obtenu / total des points possibles) avec
"Recommencer le quiz" - structure et identite visuelle calquees sur
docs/plan/maquettes/document-formation-web.html (cartes en degrade,
options A/B/C/D, feedback vert/orange), adaptees aux tokens --doc-*
deja en place (theme clair/sombre inclus, nouvelles variables
--doc-quiz-success-*/--doc-quiz-danger-*).

Cote rendu (document_engine/rendering/render_document_element.py),
_render_quiz ajoute desormais le questionnaire (fonction privee
_render_quiz_player) des qu'au moins une question existe : les
questions sont embarquees en JSON dans un attribut data-quiz-config
(jamais un <script> par element), echappees pour l'HTML - aucun
aller-retour serveur pendant qu'on joue, tout le deroulé (reponse/
score/suivant/resultat) est gere par
static/document/js/document-editor.js. pointer-events, desactive sur
tout element en Apercu pour empecher la selection/le glisser-deposer
pendant le test, est reactive specifiquement dans le questionnaire
pour qu'il reste reellement cliquable.

Tests : 3 nouveaux tests de rendu purs (sans Flask, dont un qui
verifie l'echappement HTML du texte d'une question contre une
injection). Verifie en live via une simulation DOM complete
(basculer Apercu, repondre correctement puis incorrectement,
verifier score/feedback/etat des options, passer a la question
suivante, voir l'ecran de resultat) - le script de diagnostic n'a pas
ete conserve dans le depot.

SKIP=djlint : backlog H021 pre-existant, aucun template touche ici.
ruff/mypy --strict/vulture/bandit/import-linter/eslint/stylelint tous
verts ; 48 tests cibles (document + onboarding) verifies frais.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 12:08:03 +02:00
williamandClaude Sonnet 5 9d87a4bfef Implemente le mini-jeu Quiz (questions/choix/points/timer)
Build and deploy / test-python (push) Failing after 1m3s
Build and deploy / test-js (push) Successful in 48s
Build and deploy / lint-python (push) Failing after 1m2s
Build and deploy / lint-js (push) Failing after 1m5s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Build and deploy / sonarqube (push) Failing after 1m5s
document_engine/labels/quiz_config.py (nouveau) : modele de donnees
complet, meme convention resolve_X/sanitize_X que
game_engine/rendering/quiz_box_config.py cote jeu (aucun import
croise) - DEFAULT_QUIZ_CONFIG, sanitize_quiz_config (valide/nettoie
chaque question independamment, jamais ne leve, tronque a 2-4 choix,
remet correct_index a 0 si hors bornes/non-entier, clampe points >= 0
et timer_seconds dans [5,300]), quiz_total_points.

Cote serveur, routes/document/document_element_update.py revalide
desormais un quiz avant persistance (seul kind qui en a besoin - les
autres n'ont que des attributs scalaires sans structure a garantir) et
renvoie les attributs REELLEMENT persistes dans sa reponse, pour que
le client ne derive jamais de la verite serveur apres un nettoyage
serveur (ex. choix en trop tronque).

Cote editeur (static/document/js/document-editor.js), le panneau
Proprietes d'un quiz est desormais reel : chronometre optionnel,
couleur de theme, liste de questions repetable (ajout/suppression),
chacune avec son texte, un nombre de choix ajustable (2-4, les
inputs texte suivent), le choix correct via un radio par question,
et les points gagnes. Le rendu canevas (render_document_element.py)
affiche un resume reel (nombre de questions, total des points,
minuteur) au lieu du placeholder generique.

Tests : document_engine/labels/quiz_config.py couvert par 13 tests
purs (tests/document/test_quiz_config.py, sans Flask - defauts,
troncature, validation, cas limites dont bool comme correct_index) +
1 test de route verifiant la sanitization a l'ecriture et le rendu.

SKIP=djlint : backlog H021 pre-existant, aucun template touche ici.
ruff/mypy --strict/vulture/bandit/import-linter/eslint/stylelint tous
verts ; 63 tests cibles (document + onboarding + auth) verifies
fraichement + verification manuelle live via le serveur de dev
(ajout, sanitization sur choix invalides/en trop, rendu du resume
avec minuteur).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 11:40:48 +02:00
williamandClaude Sonnet 5 bab581737a Ajoute le support de formation : entite racine separee du jeu 2D
Build and deploy / test-python (push) Successful in 11m2s
Build and deploy / test-js (push) Successful in 1m2s
Build and deploy / lint-python (push) Successful in 4m6s
Build and deploy / lint-js (push) Failing after 1m21s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Build and deploy / sonarqube (push) Failing after 4m2s
Nouveau moteur document_engine/ (elements CRUD + rendering + labels),
db/supports/ (stockage independant de db/games), routes/document/
(CRUD AJAX + publication), et l'editeur frontend complet
(templates/document/, static/document/) avec moteur de layout reel
(glisser-deposer -> fusion en rangee ou insertion avant/apres), vrai
Undo/Redo par pile de commandes, grille d'accroche pour les formes
libres, apercu responsive a largeurs fixes, mode Apercu, et publication
persistee.

"Mes formations" (templates/index.html) liste desormais les
environnements 2D et les supports de formation cote a cote ;
l'onboarding et core/auth_guard.py sont generalises pour qu'un compte
restreint puisse posseder un projet de chaque type independamment.

SKIP=djlint : le hook ne signale que le backlog H021 (styles en ligne)
deja documente dans CODE_QUALITY.md sur des fichiers pre-existants non
touches ici (base.html, game/play.html, scene_edit.html,
game_dashboard_simple.html, clause_row.html) plus une ligne de
index.html deja presente avant cette session — aucun nouveau fichier
(document_edit.html compris) n'y figure. Tous les autres outils
(ruff, mypy --strict, vulture, bandit, import-linter, eslint,
stylelint) passent sans erreur ; 617 tests Python + 276 tests JS
verts, plus une verification manuelle complete du cycle de vie via le
serveur de developpement.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 09:20:33 +02:00