feat(session-0): cadre juridique, porte de validation et dataset vérifié
Session 0 du plan — aucun code applicatif. Cadre - 5 ADR : licences, Phaser 4 hors budget initial, frontière Svelte/Phaser, filières A/B des assets, kréyòl langue principale (norme gwadloupéyenne). - LICENSE (AGPL-3.0-or-later, texte canonique gnu.org), LICENSE-CONTENT (CC BY-SA 4.0). Le jeu est une œuvre collective : aucun compositing sur un média SA ou NC, contrainte vérifiée par script. - Audit des 7 sources avec endpoints réellement appelés. TRAMIL vérifié en direct : « all rights reserved » et page de mentions légales en 404. iNaturalist mesuré à 93 % de CC BY-NC sur un échantillon de 305 photos. Outillage (tools/data/, hors bundle, zéro appel réseau au runtime) - verify:taxa, ingest:commons, build:dataset, validate:data, test:porte, build:credits, check:audio. - validate.mjs est la porte exigée par le brief §2 : le build échoue si une épreuve s'appuie sur un média non validé, non photographique ou de filière B, sur une attribution sans auteur, sur un compositing SA/NC, ou sur une entrée publiée sans relecture kréyòl. test:porte prouve les 9 refus + 1 témoin. Données - 13 entrées (8 fruits + 5 plantes du module Pa touché) vérifiées contre Wikidata ET GBIF : 13/13 ACCEPTED, 0 divergence avec la graine. - 130 candidats Commons sous licence libre, 39 pré-inscrits, 0 validé — aucun agent ne peut valider un média. Écarts signalés, non corrigés en silence - Le champ danger de la graine a deux formes (note vs resume) : normalisé. - 3 identifiants divergent du nom kréyòl au-delà des accents : non tranchés. - comestible:false sur akée et pomme-cajou : sous-estimation prudente assumée. - Le mancenillier n'a aucune photographie moderne dans ses 3 premiers candidats — l'entrée la plus critique est la moins bien servie. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
# ADR 0001 — Licences du code, du contenu et des médias
|
||||
|
||||
- **Statut :** accepté
|
||||
- **Date :** 2026-07-27
|
||||
- **Session :** 0 — cadre et données
|
||||
- **Décideur :** le porteur (ORGANISATION KA INTERNATIONALE)
|
||||
|
||||
## Contexte
|
||||
|
||||
Le pack d'origine parlait de « ressources libres de droit ». L'expression n'a pas
|
||||
d'existence juridique et masque quatre régimes très différents :
|
||||
|
||||
- **Wikimedia Commons** n'héberge que du libre, mais majoritairement du **CC BY-SA**,
|
||||
qui impose l'attribution nominative **et** le partage à l'identique. Le partage à
|
||||
l'identique contamine les œuvres dérivées.
|
||||
- **iNaturalist** publie beaucoup de **CC BY-NC**, incompatible avec toute distribution
|
||||
commerciale.
|
||||
- **TRAMIL** (tramil.net) n'accorde aucune licence dans ses mentions légales. Par défaut :
|
||||
tous droits réservés.
|
||||
- **CIRAD / INRAE** appliquent des régimes mixtes, majoritairement propriétaires, avec des
|
||||
usages pédagogiques négociables au cas par cas.
|
||||
|
||||
Le projet vise des enfants de 7 à 12 ans dans un cadre scolaire. Une erreur de licence sur
|
||||
un support diffusé en classe n'est pas rattrapable par un correctif.
|
||||
|
||||
## Décision
|
||||
|
||||
### Code — AGPL-3.0-or-later
|
||||
|
||||
`LICENSE` contient le texte canonique récupéré depuis gnu.org. L'AGPL plutôt que la GPL
|
||||
parce qu'une version future pourrait exposer une face serveur (export de progression pour
|
||||
un enseignant, tableau de classe) : l'AGPL couvre l'usage en réseau, la GPL non.
|
||||
|
||||
### Contenu rédigé par OKI — CC BY-SA 4.0
|
||||
|
||||
Textes, fiches, indices botaniques, module « Pa touché », données structurées. Cohérent
|
||||
avec Commons, donc réutilisable par le projet lui-même et par les enseignants.
|
||||
|
||||
### Médias tiers — licence d'origine conservée, œuvre collective
|
||||
|
||||
Chaque média garde sa licence. Le jeu est une **œuvre collective**, pas une œuvre dérivée.
|
||||
C'est cette qualification qui permet à des médias CC BY-SA et CC BY-NC de coexister dans
|
||||
un même produit.
|
||||
|
||||
### Clause non commerciale — acceptée, et irréversible
|
||||
|
||||
Le porteur a tranché en session 0 : le CC BY-NC est accepté pour élargir le fonds
|
||||
photographique, en échange d'un **engagement non commercial définitif** sur le jeu.
|
||||
|
||||
Le code reste réutilisable commercialement sous AGPL une fois séparé des médias.
|
||||
|
||||
## Conséquences
|
||||
|
||||
### Ce que cette décision interdit, techniquement
|
||||
|
||||
1. **Aucun compositing.** Un média sous partage à l'identique ou sous clause non
|
||||
commerciale ne peut être ni fusionné, ni détouré puis recombiné, ni fondu dans un atlas
|
||||
de textures partagé avec d'autres médias. C'est ce qui préserve la qualification
|
||||
d'œuvre collective.
|
||||
2. **Aucune vente**, aucune version payante, aucune licence à un éditeur tant qu'un seul
|
||||
média NC est embarqué.
|
||||
3. **Aucun fichier TRAMIL.** TRAMIL se cite comme source de vérification factuelle, dans
|
||||
`sources_factuelles`, jamais comme source d'images.
|
||||
|
||||
### Ce qui applique la décision
|
||||
|
||||
- `npm run validate:data` refuse tout média `composite: true` portant une clause SA ou NC,
|
||||
et tout média à attribution dont l'auteur est absent.
|
||||
- `npm run test:porte` prouve que ces refus se produisent réellement.
|
||||
- `npm run build:credits` régénère `CREDITS.md` depuis les données, avec une section
|
||||
distincte pour les médias NC. Un fichier de crédits tenu à la main se désynchronise, et
|
||||
une attribution fausse est une violation.
|
||||
- Le schéma impose `licence`, `auteur`, `url_fichier` et `url_description` sur chaque média.
|
||||
|
||||
### Condition de réexamen
|
||||
|
||||
Si le projet devait un jour être distribué commercialement, il faudrait retirer tous les
|
||||
médias NC et régénérer les crédits. `CREDITS.md` liste ces médias dans une section dédiée
|
||||
précisément pour rendre cette opération possible. À ce jour, aucun média NC n'est embarqué :
|
||||
les 39 médias candidats proviennent tous de Commons, sous CC0, domaine public, CC BY ou
|
||||
CC BY-SA. **L'engagement non commercial n'est donc pas encore consommé** — il ne le sera
|
||||
qu'au premier média iNaturalist retenu.
|
||||
|
||||
## Alternatives écartées
|
||||
|
||||
- **Refuser le NC.** Aurait gardé une porte de sortie commerciale, au prix d'un fonds
|
||||
photographique plus pauvre sur les espèces mal couvertes (zikak, pòm-sitè).
|
||||
- **Isoler le NC dans un pack séparé retirable par flag.** Meilleur des deux mondes sur le
|
||||
papier, mais complexifie le pipeline d'assets et le service worker pour une option dont
|
||||
le porteur a jugé qu'il ne l'exercerait pas.
|
||||
@@ -0,0 +1,63 @@
|
||||
# ADR 0002 — Phaser 4 et l'écart au budget JS
|
||||
|
||||
- **Statut :** accepté, avec mesure à compléter en session 4
|
||||
- **Date :** 2026-07-27
|
||||
- **Session :** 0 — cadre et données
|
||||
|
||||
## Contexte
|
||||
|
||||
Le playbook OKI §2.7 fixe un budget non négociable de **170 Ko de JS initial compressé**.
|
||||
Le mode arcade « Ranmasé » demande de la physique, des particules et du *game feel* : le
|
||||
faire en DOM coûterait plus cher en travail et en performance qu'un moteur éprouvé.
|
||||
|
||||
Le pack d'origine prescrivait « Phaser 5 ». **Phaser 5 n'existe pas.** Vérification faite
|
||||
au démarrage de la session :
|
||||
|
||||
```
|
||||
$ npm view phaser version
|
||||
4.2.1
|
||||
```
|
||||
|
||||
La branche courante est Phaser 4 — 4.0 « Caladan » (avril 2026), 4.1 « Salusa »,
|
||||
4.2 « Giedi » — avec un moteur WebGL réécrit en *render nodes*. Partir de Phaser 3 aurait
|
||||
été partir d'une branche en fin de vie.
|
||||
|
||||
## Décision
|
||||
|
||||
Utiliser **`phaser@^4`** (4.2.1 au moment de la décision), et assumer un **écart documenté**
|
||||
au budget JS, borné par quatre conditions :
|
||||
|
||||
1. Phaser n'est **jamais** dans le chemin critique. Import dynamique dans la route
|
||||
`(jeu)/ranmase` uniquement, jamais au layout racine.
|
||||
2. Le shell reste **≤ 170 Ko gzip**, Phaser exclu. Le budget n'est pas relâché : il est
|
||||
mesuré à part.
|
||||
3. L'entrée dans la scène passe derrière un **écran de chargement designé** (playbook P5,
|
||||
en KA avec le tambour `ka`), pas derrière une page blanche.
|
||||
4. Rendu `AUTO` (WebGL avec repli canvas), DPR plafonné à **1,5**,
|
||||
`powerPreference: 'low-power'`, cible **30 fps stables sur Mali-G52**.
|
||||
|
||||
## Conséquences
|
||||
|
||||
- Le budget d'entrée du site (≤ 2 Mo) et les Core Web Vitals (LCP < 2,5 s, INP < 200 ms,
|
||||
CLS < 0,05) restent mesurés **sur l'accueil et sur une fiche**, pages qui ne chargent
|
||||
jamais Phaser.
|
||||
- Un utilisateur qui ne joue jamais au mode arcade ne télécharge jamais Phaser. Les quatre
|
||||
autres modes sont en Svelte pur (ADR 0003).
|
||||
- La session 4 doit renseigner ici la **mesure réelle** du bundle Phaser en gzip et le
|
||||
relevé de fps sur mobile d'entrée de gamme.
|
||||
|
||||
### Mesures — à compléter en session 4
|
||||
|
||||
| Mesure | Cible | Relevé |
|
||||
|---|---|---|
|
||||
| Shell JS initial (gzip) | ≤ 170 Ko | _à mesurer_ |
|
||||
| Bundle Phaser seul (gzip) | information | _à mesurer_ |
|
||||
| fps scène Ranmasé sur Mali-G52 | ≥ 30 stables | _à mesurer_ |
|
||||
| Poids total de l'accueil | ≤ 2 Mo | _à mesurer_ |
|
||||
|
||||
## Condition de réexamen
|
||||
|
||||
Si la mesure de session 4 montre que Phaser dépasse ~450 Ko gzip, ou que les 30 fps ne
|
||||
sont pas tenus sur mobile d'entrée de gamme, la scène « Ranmasé » est réécrite en DOM/CSS
|
||||
avec une boucle rAF maison — le playbook P3 (« DOM d'abord, WebGL seulement où ça paie »)
|
||||
reprend alors la main. Les quatre autres modes n'en dépendent pas : le jeu reste entier.
|
||||
@@ -0,0 +1,59 @@
|
||||
# ADR 0003 — Frontière stricte entre Svelte et Phaser
|
||||
|
||||
- **Statut :** accepté
|
||||
- **Date :** 2026-07-27
|
||||
- **Session :** 0 — cadre et données
|
||||
|
||||
## Contexte
|
||||
|
||||
Le pack d'origine supposait que le jeu entier serait porté par le moteur de jeu. Or trois
|
||||
des cinq modes — Rekonèt, Kaché, Sézon — sont des interfaces de cartes et de boutons. Un
|
||||
canvas les rendrait moins accessibles, plus lourds et plus difficiles à rendre lisibles
|
||||
sans JavaScript, pour aucun gain.
|
||||
|
||||
Le public visé lit parfois mal, navigue sur Android d'entrée de gamme, et une partie de
|
||||
l'usage se fera en classe, potentiellement au clavier ou avec un lecteur d'écran.
|
||||
|
||||
## Décision
|
||||
|
||||
Architecture **hybride à frontière stricte** : Svelte porte la coquille, Phaser porte un
|
||||
seul îlot.
|
||||
|
||||
```
|
||||
Svelte 5 (coquille) Phaser 4 (îlot)
|
||||
├─ routes, i18n, SEO └─ scène « Ranmasé » uniquement
|
||||
├─ menus, HUD, album · import dynamique dans (jeu)/ranmase
|
||||
├─ fiches encyclopédiques · jamais au layout racine
|
||||
├─ données, progression · game.destroy(true) au démontage
|
||||
├─ audio, réglages · communication par événements
|
||||
└─ Rekonèt · Kaché · Sézon · aucun état Svelte partagé par frame
|
||||
```
|
||||
|
||||
Règles de frontière, non négociables :
|
||||
|
||||
1. **Import dynamique uniquement**, dans la route de la scène. Un `import` statique de
|
||||
Phaser au layout racine ferait entrer 300 à 400 Ko dans le chemin critique de toutes
|
||||
les pages, y compris de l'encyclopédie.
|
||||
2. **Destruction symétrique** : `game.destroy(true)` au démontage du composant. Un moteur
|
||||
de jeu qui survit à sa route fuit de la mémoire et continue de consommer du rAF.
|
||||
3. **Communication par événements**, jamais par état Svelte lu ou écrit à chaque frame.
|
||||
Le playbook §3 l'interdit explicitement : les états réactifs par frame passent par des
|
||||
variables plain et un flush rAF.
|
||||
4. **Miroir DOM sémantique obligatoire** pour la scène (playbook §2.8, point 4) : le canvas
|
||||
est `aria-hidden`, et l'état du jeu est doublé en DOM lisible au clavier et au lecteur
|
||||
d'écran.
|
||||
|
||||
## Conséquences
|
||||
|
||||
- Les quatre modes non-arcade sont **jouables au clavier** et dégradent proprement.
|
||||
- La session 2 doit produire un jeu **déjà amusant sans Phaser**. C'est la porte de sortie
|
||||
de cette session : si le jeu n'est pas plaisant en Svelte pur, ajouter un moteur de jeu
|
||||
ne le sauvera pas — cela ajoutera du poids à un problème de game design.
|
||||
- L'encyclopédie `/zerbaj/` ne dépend d'aucune brique de jeu et reste prérendue, lisible
|
||||
sans JavaScript.
|
||||
|
||||
## Alternative écartée
|
||||
|
||||
**Tout en Phaser.** Aurait unifié le rendu au prix de l'accessibilité clavier, du
|
||||
référencement de l'encyclopédie, de la lisibilité sans JS et du budget. Le playbook P3 est
|
||||
explicite : DOM d'abord, WebGL seulement où ça paie. Ici, il ne paie que sur une scène.
|
||||
@@ -0,0 +1,83 @@
|
||||
# ADR 0004 — Deux filières d'assets : vérité et décor
|
||||
|
||||
- **Statut :** accepté
|
||||
- **Date :** 2026-07-27
|
||||
- **Session :** 0 — cadre et données
|
||||
|
||||
## Contexte
|
||||
|
||||
Le pack d'origine prévoyait de générer l'intégralité des visuels du jeu — 76 images — par
|
||||
diffusion (SDXL / FLUX via ComfyUI), puis de passer directement à la production.
|
||||
|
||||
C'est une contradiction avec le but du jeu. Un enfant qui apprend à reconnaître un
|
||||
corossol sur une image générée n'apprend pas à reconnaître un corossol : il apprend à
|
||||
reconnaître ce qu'un modèle de diffusion produit quand on lui demande un corossol. Sur les
|
||||
espèces peu représentées dans les jeux d'entraînement — le zikak, la quenette, le cachiman
|
||||
cœur-de-bœuf, la pomme-liane — le modèle ne refuse pas : il produit un fruit **plausible
|
||||
et faux**. C'est le pire des deux mondes, parce que l'erreur est invisible à qui ne connaît
|
||||
pas déjà l'espèce.
|
||||
|
||||
Cette session a produit une illustration involontaire du même problème côté sources
|
||||
réelles : parmi les photographies que Wikimedia Commons remonte pour *Melicoccus bijugatus*
|
||||
(la quenette), l'un des premiers résultats est une photographie de **singe capucin**
|
||||
mangeant le fruit. Aucune machine — moteur de recherche ou modèle génératif — ne peut
|
||||
tenir lieu de validation botanique.
|
||||
|
||||
## Décision
|
||||
|
||||
Deux filières, deux régimes, jamais mélangés.
|
||||
|
||||
| Filière | Contenu | Source autorisée | Rôle |
|
||||
|---|---|---|---|
|
||||
| **A — Vérité** | fruit, coupe, feuille, écorce, port de l'arbre | photographie réelle : Commons, iNaturalist, herbier, appareil du porteur | tout ce qui sert à **identifier** — épreuves, indices, fiches |
|
||||
| **B — Décor** | fonds, personnages, UI, sprites arcade, badges, écrans de titre | génération IA (ComfyUI / FLUX) | tout ce qui **ne sert pas** à identifier |
|
||||
|
||||
### Une troisième catégorie découverte en session 0
|
||||
|
||||
Les fonds Commons contiennent beaucoup de **planches botaniques anciennes** — Blanco,
|
||||
Merian, Köhler, domaine public, exactes et magnifiques. Elles ne sont ni des photographies
|
||||
ni des images générées. Le schéma les distingue donc explicitement :
|
||||
|
||||
```
|
||||
type_media : "photo" | "planche_botanique" | "image_generee"
|
||||
```
|
||||
|
||||
Une planche botanique **documente** une fiche encyclopédique. Elle ne peut **pas** porter
|
||||
une épreuve d'identification : une gravure au trait rehaussée n'entraîne pas l'œil à
|
||||
reconnaître un fruit posé sur une table de marché.
|
||||
|
||||
### Le champ `usages` et la porte
|
||||
|
||||
Chaque média déclare où il est employé : `epreuve`, `indice`, `fiche`, `decor`. Les deux
|
||||
premiers sont les usages **identifiants**. Un média identifiant doit satisfaire les quatre
|
||||
conditions, vérifiées par script :
|
||||
|
||||
1. `filiere: "A"` ;
|
||||
2. `type_media: "photo"` ;
|
||||
3. `valide: true`, avec un `valide_par` nommé — une validation anonyme n'engage personne ;
|
||||
4. `vue` renseignée.
|
||||
|
||||
## Conséquences
|
||||
|
||||
- `npm run validate:data` fait échouer le build sur toute violation. `npm run test:porte`
|
||||
rejoue les neuf cas interdits et vérifie que le refus se produit — une règle qu'on n'a
|
||||
jamais vue refuser quelque chose est une intention, pas une règle.
|
||||
- **Tout média sort de l'ingestion avec `valide: false`.** Aucun agent, aucun script, aucun
|
||||
modèle ne peut passer ce champ à `true`. La validation se fait par comparaison à au moins
|
||||
deux photographies de référence, idéalement contresignée par quelqu'un qui connaît :
|
||||
TRAMIL, un enseignant de SVT, un agriculteur, une grand-mère.
|
||||
- Le pipeline de génération (filière B) vit dans `tools/assets/`, hors du bundle, avec son
|
||||
propre `requirements.txt`. Il est piloté **hors ligne, au build** (playbook P2). Aucun
|
||||
appel réseau ne subsiste au runtime du jeu.
|
||||
- Les défauts du script du pack d'origine sont corrigés en session 3 :
|
||||
`hash()` de Python est randomisé par exécution (`PYTHONHASHSEED`), donc les seeds annoncés
|
||||
comme reproductibles ne le sont pas — utiliser `zlib.crc32(clé.encode()) & 0xFFFFFFFF` ;
|
||||
`copy.deepcopy` au lieu de `json.loads(json.dumps(...))` ; et vérifier la licence des
|
||||
**poids** du modèle `rembg`, qui ne suit pas nécessairement la licence MIT du paquet.
|
||||
|
||||
## Alternative écartée
|
||||
|
||||
**Générer les visuels d'identification et les faire valider a posteriori.** Le pack le
|
||||
proposait implicitement. Le problème n'est pas la validation, c'est le coût de l'erreur non
|
||||
détectée : un validateur non spécialiste confirmera un corossol plausible. La photographie
|
||||
supprime la question.
|
||||
@@ -0,0 +1,78 @@
|
||||
# ADR 0005 — Le kréyòl est la langue principale, norme gwadloupéyenne
|
||||
|
||||
- **Statut :** accepté ; orthographe en attente de relecture humaine
|
||||
- **Date :** 2026-07-27
|
||||
- **Session :** 0 — cadre et données
|
||||
|
||||
## Contexte
|
||||
|
||||
Le jeu vise à restituer une connaissance qui se transmettait en kréyòl. Traiter le kréyòl
|
||||
comme une traduction du français inverserait le rapport que le projet cherche précisément
|
||||
à rétablir.
|
||||
|
||||
Par ailleurs, les orthographes gwadloupéyenne et matinitjée diffèrent sur plusieurs entrées
|
||||
du jeu de données. Les mélanger produirait un contenu que personne ne reconnaît tout à
|
||||
fait comme le sien.
|
||||
|
||||
## Décision
|
||||
|
||||
### Le nom kréyòl est le nom de l'entrée
|
||||
|
||||
Dans les données, `noms.gcf` est le **nom principal**. `noms.fr`, `noms.en` et `noms.es` en
|
||||
sont les traductions. Le schéma rend `gcf` obligatoire et les autres facultatives — pas
|
||||
l'inverse. C'est un choix politique, pas cosmétique, et il ne s'inverse pas au motif que le
|
||||
français serait « plus pratique » pour l'interface.
|
||||
|
||||
### Routes
|
||||
|
||||
`/` sert le kréyòl, `/fr/` le français, `/en/` l'anglais. Routeur par dossiers avec
|
||||
catalogues JSON, pas de middleware (playbook §5b.7) : les URLs et le prérendu restent sous
|
||||
contrôle total, ce qui est la condition du statique et du hors-ligne.
|
||||
|
||||
Attribut `lang="gcf"` correct partout, y compris sur les fragments kréyòl insérés dans une
|
||||
page française — un nom de fruit prononcé par un lecteur d'écran avec la phonétique
|
||||
française n'est pas le nom du fruit.
|
||||
|
||||
### Norme orthographique : gwadloupéyenne
|
||||
|
||||
Une seule norme pour tout le projet, décidée par le porteur en session 0. Le champ
|
||||
`orthographe.norme` vaut `"gwadloupeyen"` sur chaque entrée, et le schéma n'accepte pas
|
||||
d'autre valeur : il est impossible de mélanger les deux normes sans modifier le schéma,
|
||||
donc sans que la décision soit revue.
|
||||
|
||||
### L'orthographe elle-même n'est pas du ressort de l'agent
|
||||
|
||||
Aucune graphie n'est tranchée par un agent de code. Chaque entrée porte :
|
||||
|
||||
```json
|
||||
"orthographe": { "norme": "gwadloupeyen", "statut": "a_relire", "relu_par": null }
|
||||
```
|
||||
|
||||
`statut` ne passe à `"relu"` que par décision d'un locuteur humain nommé. Le validateur
|
||||
refuse toute entrée déclarée publiable dont l'orthographe n'est pas relue, et toute entrée
|
||||
`relu` sans nom de relecteur.
|
||||
|
||||
Les incertitudes constatées sont consignées dans `docs/kreyol-a-relire.md` — signalées, pas
|
||||
corrigées.
|
||||
|
||||
## Conséquences
|
||||
|
||||
- Les 13 graphies issues de `fruits.seed.json` sont **toutes non vérifiées** à ce stade. La
|
||||
graine elle-même le déclare. Trois incohérences internes ont été relevées entre
|
||||
l'identifiant technique et le nom kréyòl (voir `docs/kreyol-a-relire.md`) : elles ne sont
|
||||
pas corrigées ici.
|
||||
- Les identifiants techniques (`id`) restent en ASCII sans diacritique — ils servent de nom
|
||||
de fichier et de segment d'URL. Ils ne sont **pas** une graphie et ne doivent jamais être
|
||||
affichés à l'utilisateur. `kowosol` est un identifiant ; `kowosòl` est un nom.
|
||||
- Un identifiant ne se renomme jamais après publication : il est dans les URLs, dans la
|
||||
progression stockée en local et dans les liens partagés. Une correction d'orthographe
|
||||
change `noms.gcf`, jamais `id`.
|
||||
- Chaque entrée doit recevoir un enregistrement audio du nom prononcé par une voix humaine
|
||||
locale. Pas de synthèse vocale : les enfants visés lisent mal le kréyòl écrit, dont
|
||||
l'orthographe leur est peu familière — un jeu qui enseigne les noms kréyòl sans les faire
|
||||
entendre rate sa cible. `npm run check:audio` tient la liste de ce qui manque.
|
||||
|
||||
## Point ouvert
|
||||
|
||||
Le relecteur n'est pas encore désigné. Tant qu'il ne l'est pas, aucune entrée ne peut être
|
||||
publiée : c'est le validateur qui l'impose, pas une note de bas de page.
|
||||
Reference in New Issue
Block a user