Z4 — Lazy generation — Concurrence & cache
Race conditions · Invalidation · Pool épuisé · Sessions parallèles
La génération lazy avec cache partagé est le principal vecteur de bugs silencieux en contexte concurrent (plusieurs sessions ouvertes, re-upload, résolution HITL).
Z4-AC01 — Pas de doublons si deux sessions composées simultanément
|
|
| Lot 0 |
— |
| GIVEN |
Deux sessions pour le même (user_id, chapter_id) sont composées en parallèle (ex : onglets multiples ou race condition réseau). |
| WHEN |
Les deux requêtes de composition de session arrivent dans un intervalle < 500 ms. |
| THEN |
Une seule session est créée (idempotence via lock ou check session_id existante). La deuxième requête retourne la session existante si elle est < 30 min. Aucune question en double n'est générée pour la même session. |
Z4-AC02 — Pool question candidates non partagé entre sessions actives
|
|
| Lot 0 |
— |
| GIVEN |
L'élève a une session active S1 avec 10 questions issues du pool. Il ouvre une nouvelle session S2 (contrôle blanc) sur le même chapitre. |
| WHEN |
S2 est composée. |
| THEN |
S2 pioche dans le pool de candidats mais les questions déjà assignées à S1 (en status = IN_PROGRESS) sont exclues de S2 si le pool le permet. Si le pool est insuffisant (< 5 candidats uniques disponibles), S2 peut réutiliser des questions de S1 — ceci doit être loggué. |
NOTE : En MVP, l'exhaustion de pool est acceptable si loggée. Post-MVP : régénération auto.
Z4-AC03 — Invalidation cache (HITL, pack, exam)
|
|
| Lot 0 |
— |
| GIVEN |
Le cache question_candidates ou item_pool d'un chapitre existe. Un événement déclencheur survient. |
| WHEN |
L'un des événements suivants est persisté : (1) résolution d'une ValidationTask sur un item du chapitre, (2) mise à jour d'un pack (pack_version changé) affectant le chapitre, (3) création, modification (exam_date changée) ou suppression d'un Exam lié au chapitre. |
| THEN |
— Résolution HITL : le cache question_candidates des questions liées à l'item résolu est invalidé dans la même transaction (< 1s). — Pack version : les caches item_pool et question_candidates des chapitres utilisant ce pack sont invalidés. Les Mastery states ne sont pas touchés. — CRUD Exam : le cache question_candidates est invalidé. Les next_due_at sont recalculés (compression Z1-AC08 si exam créé/avancé, décompression aux intervalles standard si exam supprimé). Le cache item_pool n'est pas invalidé (seule la priorité change). Dans tous les cas, les sessions IN_PROGRESS continuent avec les questions déjà générées — pas d'interruption. |
NOTE : Ces 3 triggers d'invalidation couvrent tous les cas où le contenu ou la priorité des questions change.
Z4-AC04 — Session interrompue reprise depuis le dernier état connu
|
|
| Lot 0 |
P1 |
| GIVEN |
Une session S1 avec 10 questions. L'élève répond à 4 questions puis ferme l'application. |
| WHEN |
L'élève rouvre la session (TTL session = 72h). |
| THEN |
La session reprend à la question 5. Les Mastery states des items 1–4 sont déjà mis à jour. L'état de session (current_question_index = 4) est persisté en base et non uniquement en cache. |
Z4-AC05 — Contraintes pack respectées lors de la composition lazy
|
|
| Lot 0 |
P1 |
| GIVEN |
Chapitre HG-INEG avec 5 items document disponibles et 8 items knowledge. Pack : max_writing_per_session = 1, session_must_include_doc = true. |
| WHEN |
Une session quotidienne est composée. |
| THEN |
La session inclut exactement 1 exercice de type document (parmi les 5 disponibles). La session inclut au maximum 1 exercice de rédaction (GEN.WRITE.*). Ces contraintes sont respectées même si l'algorithme 70/20/10 sélectionnerait autrement. |
Z4-AC06 — Pool vide : comportement dégradé gracieux
|
|
| Lot 0 |
P1 |
| GIVEN |
Le cache du pool est expiré et le LLM est indisponible (timeout). L'élève tente de démarrer une session. |
| WHEN |
La composition de session échoue à générer des questions. |
| THEN |
L'interface affiche : 'Préparation de tes exercices en cours… réessaie dans quelques secondes.' Aucune session vide n'est créée en base. La page n'affiche pas d'erreur 500. Si après 10 secondes le LLM n'est toujours pas disponible, le fallback Z4-AC12 est déclenché. |
Z4-AC07 — Contrôle blanc non affecté par une session quotidienne en cours
|
|
| Lot 0 |
P2 |
| GIVEN |
L'élève a une session quotidienne S1 en cours (non terminée). Il lance un contrôle blanc CB1. |
| WHEN |
CB1 est composé. |
| THEN |
CB1 est une session indépendante avec son propre pool de questions. CB1 n'est pas bloqué par S1. Les deux sessions coexistent. Les Mastery updates de CB1 sont appliqués indépendamment de S1. |
Z4-AC08 — Variété de gabarits dans une session (anti-monotonie)
|
|
| Lot 0 |
— |
| GIVEN |
Une session daily est composée avec 10 questions. Le pool contient des questions de types FLASH_MCQ, DEF_SHORT, CLOZE_KEYWORDS, ASSOC_TERM_DEF, et DOC.EXTRACT_EVIDENCE. |
| WHEN |
Le moteur de composition ordonne les questions dans la session. |
| THEN |
Aucun gabarit identique (template_id) ne peut apparaître plus de 2 fois consécutives. Si la contrainte ne peut pas être respectée (pool trop petit), elle est relaxée mais loggée. La session alterne les types de questions (question_type) autant que possible : pas 3 MCQ d'affilée si des SHORT_ANSWER sont disponibles. L'ordonnancement est déterministe (pas random) : il alterne les types par round-robin sur les types disponibles. |
NOTE : 5 flashcards consécutives rendent la session monotone et mécanique. L'alternance des types de questions maintient l'attention et active différents circuits cognitifs (reconnaissance ≠ rappel ≠ production). Cette contrainte n'affecte pas la sélection des items (qui reste 70/20/10), seulement l'ordonnancement des questions dans la session.
Z4-AC09 — Feedback enrichi après réponse incorrecte
|
|
| Lot 0 |
P1 |
| GIVEN |
L'élève répond incorrectement à une question de type KEYWORDS sur l'item « photosynthèse » (keywords attendus : chloroplaste, lumière, CO2). L'élève a répondu « les plantes font de la nourriture ». |
| WHEN |
La correction est affichée. |
| THEN |
Le feedback contient 3 éléments obligatoires : — 1. La réponse correcte : « Les mots-clés attendus étaient : chloroplaste, lumière, CO2 ». — 2. Ce qui manquait (spécifique au type) : KEYWORDS → mots-clés manquants listés. NUMERIC → valeur attendue + unité + formule utilisée. MCQ → explication du distractor choisi (« Tu as choisi X — en réalité, X est faux car... »). — 3. Un indice pour la prochaine fois (1 phrase max) : « Retiens que la photosynthèse se passe dans les chloroplastes grâce à la lumière et au CO2. ». Le feedback est généré par template (pas par LLM en temps réel) pour garantir la cohérence et la vitesse (< 200 ms). Le feedback est toujours factuel, jamais culpabilisant. |
NOTE : Un feedback qui dit juste « Faux — la bonne réponse est X » n'enseigne rien. L'indice en 1 phrase est le micro-moment d'apprentissage le plus puissant de la session. Le contenu est templaté (pas LLM live) pour garantir la rapidité et éviter les hallucinations dans le feedback lui-même.
Z4-AC10 — Bouton « Passer » sur une question (sans pénalité mastery)
|
|
| Lot 0 |
— |
| GIVEN |
L'élève est bloqué sur une question de type NUMERIC. Il ne connaît pas la formule. |
| WHEN |
L'élève appuie sur « Passer cette question ». |
| THEN |
La question est marquée status = SKIPPED. Le Mastery state de l'item n'est PAS modifié (ni progression, ni régression). consecutive_successes n'est pas remis à 0. La question est placée en fin de session (si la session a encore ≥ 3 questions restantes) pour une seconde chance. Si l'élève la passe à nouveau, elle est comptée comme non répondue. Le feedback de la réponse correcte est affiché après le 2ème passage (l'élève voit la solution même s'il n'a pas répondu). Maximum 2 « Passer » par session (au-delà, le bouton est grisé). |
NOTE : Sans mécanisme « Passer », un élève bloqué sur une question de calcul reste immobile → frustration → fermeture de l'app. Le « Passer » sans pénalité mastery est cohérent avec le principe « seule une réponse incorrecte déclenche une régression » (Z1-AC05 à Z1-AC07). La limite de 2 passes par session empêche l'abus (tout passer sans réfléchir). La solution affichée après le 2ème passage transforme un moment de blocage en moment d'apprentissage.
Z4-AC11 — Session viable sur petit chapitre (< 5 items)
|
|
| Lot 0 |
— |
| GIVEN |
Un chapitre n'a que 3 items valides. Le moteur de composition doit créer une session daily. |
| WHEN |
La composition est lancée. |
| THEN |
La session est composée avec au minimum 4 questions : chaque item génère au moins 1 question, et l'item le plus fragile en génère 2 (gabarits différents sur le même item). La durée cible est réduite à 3–5 min (au lieu de 10–20 min). Si le pool de gabarits éligibles est épuisé (tous les gabarits déjà utilisés pour ces 3 items), la session utilise des reformulations : même item + même gabarit mais avec des distractors différents (MCQ) ou un ordre de keywords différent (CLOZE). Le message d'introduction adapte les attentes : « Petite session rapide — [N] questions sur ce chapitre ». |
NOTE : Un chapitre avec 3 items est courant (élève qui n'a photographié qu'une seule page, ou cours très court). Sans ce AC, la session serait de 2 questions identiques à la veille — l'élève sent qu'il tourne en rond. La reformulation (distractors différents, ordre différent) crée une illusion de nouveauté tout en testant les mêmes connaissances sous des angles différents.
Z4-AC12 — Fallback contenu quand le LLM est indisponible
|
|
| Lot 0 |
— |
| GIVEN |
L'élève tente de démarrer une session. Le LLM est indisponible depuis > 10 secondes (Z4-AC06 épuisé). Le chapitre a une carte de leçon avec des blocs de texte et des items existants (même sans questions générées). |
| WHEN |
Le fallback est déclenché. |
| THEN |
L'interface propose un mode « Relecture active » au lieu de laisser l'élève sans rien faire. Ce mode affiche la carte de leçon du chapitre le plus urgent (items dues en priorité) avec des flashcards textuelles statiques : pour chaque item KNOWLEDGE, afficher le term en recto et la définition extraite de l'OCR en verso (pas de génération LLM nécessaire). L'élève peut « retourner » chaque flashcard. Un bouton « Je savais » / « Je ne savais pas » permet un auto-évaluation (sans impact mastery — marqué self_assessment = true). Le message affiché est : « Les exercices ne sont pas disponibles pour le moment — en attendant, révise ta leçon avec ces flashcards ! » Le mode fallback se désactive automatiquement dès que le LLM redevient disponible (vérification toutes les 30s). Si aucun item n'est disponible du tout (chapitre vide), un message s'affiche : « Tes exercices arrivent bientôt — reviens dans quelques minutes. » |
NOTE : Un élève motivé qui ouvre l'app pour réviser et se retrouve face à un mur « réessaie plus tard » ferme l'app et ne revient pas. Le mode relecture active est un filet de sécurité minimal : il ne remplace pas les exercices adaptatifs mais il offre une activité pédagogique en attendant. Les flashcards textuelles ne nécessitent aucun appel LLM (données OCR déjà en base). L'auto-évaluation sans impact mastery évite la corruption des données tout en gardant l'élève engagé.
Z4-AC13 — État « tout est à jour » : session optionnelle quand aucun item n'est dû
|
|
| Lot 0 |
— |
| GIVEN |
L'élève a 15 items, tous en état OK ou SOLID. Aucun next_due_at n'est ≤ aujourd'hui. Aucun exam dans les 7 prochains jours. L'élève ouvre l'app et tente de lancer une session. |
| WHEN |
Le moteur de composition ne trouve aucun item éligible pour le bucket 70% (dues) ni le bucket 20% (consolidation récente). |
| THEN |
L'interface affiche un message positif : « Bravo — tu es à jour sur tous tes chapitres ! Prochaine révision prévue [date du prochain next_due_at]. » Un bouton optionnel « Session de consolidation » est proposé. S'il clique, une session courte (5 questions) est composée à partir des items SOLID les plus anciennement révisés (anti-oubli long terme). Cette session est de type consolidation_optional et n'a aucun impact négatif sur le mastery en cas d'échec ou de score partiel : pas de régression SOLID→OK, pas de reset de consecutive_successes (cf. Z1-AC24, exception consolidation_optional). Seuls les succès sont comptabilisés positivement. En cas d'exam dans les 7 jours, le message change : « Tu es bien préparé pour [nom exam] ! Tu peux refaire un contrôle blanc ou une session de consolidation. » |
NOTE : L'élève diligent qui a tout révisé et ouvre l'app face à un écran vide (« rien à faire ») se sent récompensé par... rien. C'est le moment où il décide que l'app est inutile et arrête de l'ouvrir. Le message positif + la session optionnelle sans risque maintiennent l'habitude quotidienne sans punir la surperformance.
Z4-AC14 — Sélection du gabarit adaptée à l'état de maîtrise
|
|
| Lot 0 |
— |
| GIVEN |
Le moteur de composition sélectionne une question pour un item donné. L'item a un état mastery connu (UNKNOWN, FRAGILE, OK, SOLID). Le pool de gabarits éligibles contient des templates de difficulté 1 à 3. |
| WHEN |
Le gabarit est choisi pour la question instanciée. |
| THEN |
Le gabarit est sélectionné en fonction de l'état mastery de l'item : — UNKNOWN : difficulté 1 uniquement (MCQ, CLOZE, DEF_SHORT). La reconnaissance est suffisante pour un premier contact. — FRAGILE : difficulté 1-2 (SHORT_ANSWER, ASSOC_TERM_DEF en plus des gabarits difficulté 1). Le rappel indicé remplace progressivement la reconnaissance. — OK : difficulté 2-3 (KEYWORDS, NUMERIC, DOC.EXTRACT_EVIDENCE). Les gabarits de production remplacent la reconnaissance. — SOLID : difficulté 3 uniquement (RUBRIC, questions d'élaboration « Explique pourquoi… », « Quel lien entre X et Y ? »). La consolidation SOLID vise l'approfondissement, pas la simple répétition. Si le pool ne contient aucun gabarit dans la plage de difficulté cible pour cet item, la plage est élargie d'un cran (OK sans gabarit difficulté 2-3 → accepter difficulté 1) et un log TEMPLATE_FALLBACK est créé. La contrainte Z4-AC08 (variété de gabarits) s'applique après la sélection par mastery. |
NOTE : La recherche en sciences cognitives (Rawson et al., Smith & Karpicke 2014) établit une hiérarchie claire d'efficacité : MCQ (d=0.36) < rappel indicé (d=0.72) < rappel libre (d=0.81). Mais l'efficacité dépend du succès de la récupération — un item trop dur ne produit aucun apprentissage. L'escalade progressive MCQ → rappel indicé → production → élaboration suit la Zone Proximale de Développement (Vygotsky) : toujours un cran au-dessus du niveau actuel, jamais deux.
Z4-AC15 — Interleaving inter-chapitres dans les sessions daily
|
|
| Lot 0 |
— |
| GIVEN |
Une session daily est composée avec 12 questions couvrant 3 chapitres (A: 5 questions, B: 4 questions, C: 3 questions). |
| WHEN |
Le moteur de composition ordonne les questions dans la session (après sélection 70/20/10 et contrainte Z4-AC08). |
| THEN |
L'ordonnancement alterne les chapitres : jamais 3 questions consécutives du même chapitre si d'autres chapitres sont représentés dans la session. L'alternance suit un round-robin pondéré : A-B-C-A-B-A-C-B-A-B-A-C (proportionnel au poids de chaque chapitre). Si la session ne couvre qu'un seul chapitre, l'alternance se fait par Notion (Z7-AC15) : jamais 3 items consécutifs de la même Notion. Si un seul chapitre avec une seule Notion, la contrainte est relaxée (loggée). L'interleaving s'applique après la contrainte de variété de gabarits Z4-AC08 — les deux contraintes sont composées (gabarit ET chapitre alternés). En cas de conflit (impossible de satisfaire les deux), la variété de gabarits est prioritaire (plus d'impact sur l'engagement immédiat). |
NOTE : L'interleaving (mélange de sujets) produit un effet large (d=0.64, Rohrer et al. 2015) sur la rétention long terme, principalement parce qu'il force la discrimination entre concepts similaires et empêche le « pilote automatique » cognitif. Les élèves préfèrent le blocking (un sujet à la fois) — c'est une illusion métacognitive classique. Le blocking reste approprié pour le premier contact (evening_first = 100% UNKNOWN d'un chapitre, Z6-AC05), mais dès la phase de consolidation (daily), l'interleaving est supérieur.
Z4-AC16 — Calibration dynamique de la difficulté (cible 70-85% de réussite)
|
|
| Lot 0 |
— |
| GIVEN |
L'élève a complété au moins 3 sessions daily dans les 7 derniers jours. Le taux de réussite moyen observé sur ces sessions est calculé : avg_success_rate = total_correct / total_attempted. |
| WHEN |
Le moteur de composition prépare une nouvelle session daily. |
| THEN |
La difficulté moyenne des gabarits sélectionnés est ajustée pour cibler un taux de réussite de 70-85% : — Si avg_success_rate < 60% : la difficulté est abaissée d'un cran pour tous les items de la session (la plage de Z4-AC14 est décalée vers le bas : OK utilise difficulté 1-2 au lieu de 2-3, SOLID utilise difficulté 2-3 au lieu de 3). Un message contextuel s'affiche dans le débrief : « Les prochaines sessions seront un peu plus accessibles — c'est normal, on ajuste à ton rythme ! » — Si avg_success_rate > 92% : la difficulté est relevée d'un cran (FRAGILE utilise difficulté 2-3, OK utilise difficulté 3). Aucun message — la montée en difficulté doit être invisible pour ne pas créer de pression. — Si avg_success_rate est dans la plage 60-92% : pas d'ajustement, les plages Z4-AC14 standards s'appliquent. Le calcul est par-élève, pas global. Le taux de réussite est calculé par type de gabarit (success_rate_by_template) pour un ajustement plus fin : si l'élève réussit 95% des MCQ mais 40% des NUMERIC, les MCQ sont remplacées par des templates plus exigeants tandis que les NUMERIC conservent leur difficulté actuelle. Les sessions evening_first et mock_exam ne sont pas affectées par la calibration (la première est toujours difficulté 1, le second est représentatif du vrai niveau). |
NOTE : Wilson et al. (2019) montrent que ~85% de réussite est le point optimal pour l'apprentissage (« the 85% rule »). En dessous de 60%, la difficulté cesse d'être « désirable » au sens de Bjork et devient simplement frustrante — l'élève accumule des échecs sans bénéfice mnésique. Au-dessus de 92%, les questions ne déclenchent plus l'effort de récupération nécessaire à la consolidation. La plage 70-85% est volontairement large pour absorber la variance naturelle (un mauvais jour ≠ un problème systémique). L'ajustement par type de gabarit évite le piège du « tout facile » : un élève fort en MCQ mais faible en NUMERIC doit monter en MCQ et rester stable en NUMERIC.
|
|
| Lot 0 |
— |
| GIVEN |
Le pipeline J0 a détecté des blocs visuels pédagogiques (cf. Z2-AC15) pour un chapitre. Les VisualBlock sont créés avec image_url, labels[], table_structure?, type. Le LLM de structuration (étape 5) reçoit ces visuels en contexte multimodal. |
| WHEN |
Le LLM génère les items et gabarits associés au chapitre (étape 5 du pipeline J0, puis lazy generation Z4-AC01). |
| THEN |
Le LLM génère des gabarits visuels adaptés au type de chaque VisualBlock. Chaque gabarit visuel produit un rendered_visual_url (image transformée) en plus du prompt texte. Les types d'interaction visuelle sont : (1) LABEL_COMPLETION (schéma, carte, circuit) : les labels[] extraits du VisualBlock sont masqués sur l'image (remplacés par des cases numérotées ①②③…). Le prompt demande : « Complète les légendes du schéma ». L'expected_answer contient les labels originaux associés à chaque numéro. Le masquage est réalisé par image processing (inpainting rectangulaire blanc sur chaque label.position, puis superposition du numéro) — pas de re-génération LLM de l'image. Si le VisualBlock a < 3 labels, le gabarit LABEL_COMPLETION n'est pas généré (trop simple, sans intérêt pédagogique). (2) DESCRIBE (graphique, photo, schéma) : l'image originale est affichée telle quelle. Le prompt demande : « Que représente ce [graphique/schéma/document] ? Décris les éléments principaux. » C'est un gabarit ouvert évalué par rubrique (RUBRIC) avec les labels comme éléments attendus. (3) MATCHING (schéma annoté, circuit) : les éléments visuels sont numérotés sur l'image (①②③…) et une liste de fonctions/définitions est proposée. L'élève associe chaque numéro à sa fonction. L'expected_answer est le mapping numéro→fonction extrait des labels et du contexte item. (4) READ_VALUE (graphique, tableau) : l'image originale est affichée. Le prompt demande de lire une valeur précise : « D'après le graphique, quelle est la valeur de Y quand X = [valeur] ? » Les valeurs-clés sont extraites des axis_labels et labels[] du VisualBlock. Pour les tableaux, la question porte sur une cellule spécifique. (5) IDENTIFY_ZONE (carte, schéma) : une zone de l'image est surlignée (overlay coloré semi-transparent). Le prompt demande : « Identifie la zone surlignée » ou « Quelle est la fonction de cette partie ? ». Contraintes de génération : un VisualBlock avec ≥ 5 labels génère au maximum 3 gabarits visuels (pour éviter la saturation d'un seul schéma). Les gabarits visuels sont marqués template.uses_visual = true et template.visual_interaction_type correspondant. La Question instanciée porte le visual_block_id et le rendered_visual_url. Si le VisualBlock n'a aucun label exploitable ET aucune table_structure, seul le gabarit DESCRIBE (type 2) est généré — pas de masquage ni matching possible. Cache et invalidation : les rendered_visual_url (images transformées) sont cachées avec la même TTL que les questions (Z4-AC02, 24h). L'invalidation suit les règles Z4-AC03 (validation HITL d'un item → invalidation des questions visuelles liées). |
NOTE : La génération de gabarits visuels est le pont entre le dual coding (Z2-AC15) et l'exploitation pédagogique effective. Sans cette étape, les visuels seraient stockés mais jamais utilisés dans les sessions — du stockage inutile. Le masquage de légendes par image processing (pas par LLM) est déterministe, rapide (< 100ms) et ne risque pas d'hallucination. L'approche est progressive : LABEL_COMPLETION (difficulté 2, recall indicé par l'image) → MATCHING (difficulté 3, association) → DESCRIBE (difficulté 3, production libre). La limite de 3 gabarits par VisualBlock empêche qu'un schéma riche (cellule animale avec 12 légendes) ne monopolise une session entière. Les 5 types d'interaction couvrent les cas d'usage principaux des 4 matières pilotes : schémas annotés (SVT), graphiques (PC, Géographie), tableaux (PC, HG), cartes (HG), circuits (PC).