0.3.3-0-pre.1

This commit is contained in:
2026-09-21 08:39:57 +02:00
parent 76a955bd3d
commit f770f99a4a
9 changed files with 680 additions and 13 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/000-README.md -->
<!-- version: 2 -->
<!-- version: 3 -->
# Plans de versions games.sasedev
@@ -12,4 +12,5 @@ Le `ROADMAP.md` reste la trajectoire macroscopique du projet ; les deltas décri
## Plans
- [`001-V0_3_0_WEB_SNAKE_POC_PLAN.md`](001-V0_3_0_WEB_SNAKE_POC_PLAN.md) — plan clôturé de `0.3.0`, baseline Snake et premier POC Web direct.
- [`002-V0_3_1_TAURI_ANDROID_SNAKE_PLAN.md`](002-V0_3_1_TAURI_ANDROID_SNAKE_PLAN.md) — plan actif de `0.3.1`, second host Snake Tauri Android.
- [`002-V0_3_1_TAURI_ANDROID_SNAKE_PLAN.md`](002-V0_3_1_TAURI_ANDROID_SNAKE_PLAN.md) — plan clôturé de `0.3.1`, second host Snake Tauri Android.
- [`003-V0_3_3_ANDROID_NATIVE_MULTI_ABI_PLAN.md`](003-V0_3_3_ANDROID_NATIVE_MULTI_ABI_PLAN.md) — plan actif de `0.3.3`, pipeline Android SDL3 natif Gradle/Cargo multi-ABI.

View File

@@ -0,0 +1,208 @@
<!-- file: docs/plans/003-V0_3_3_ANDROID_NATIVE_MULTI_ABI_PLAN.md -->
<!-- version: 1 -->
# Plan 0.3.3 — Android SDL3 natif multi-ABI et packaging Gradle
## Statut
Plan actif créé pendant `0.3.3-0-pre.1` à partir de la stable taggée `v0.3.1`.
`0.3.2` reste volontairement différée. Aucun placeholder, POC Tauri Desktop ou changement cérémoniel n'est introduit pour cette version.
## Mission
`0.3.3` doit rendre le chemin Android SDL3 natif reproductible et possédé par Gradle/Cargo :
```text
Gradle -> Rust natif -> SDL3/JNI -> APK universal de test
Gradle -> Rust natif multi-ABI -> AAB de distribution
```
Le chemin productif Android ne doit dépendre ni de Tauri, ni de WebView, ni de WASM, ni d'un orchestrateur Python de build.
## Baseline et décisions retenues
La baseline `0.3.1` conserve :
- `game-android-entrypoint` comme `cdylib` commun ;
- exactement une feature jeu par application native ;
- Java comme glue Android ;
- `SaseGameActivity`/SDLActivity et un contrat JNI réduit ;
- assets canoniques hors modules Android et staging Gradle déjà basé sur la Variant API ;
- SDL3 AAR non vendorizé ;
- Snake Tauri Android uniquement comme POC de référence ARM64/x86_64.
Les décisions de cadrage `0-pre.1` sont :
```text
AGP 9.4.0
Gradle 9.6.0 à épingler par wrapper lors de l'implémentation
JDK 17
compileSdk 36
targetSdk 36
minSdk candidat 21
NDK 28.2.13676358 / r28c
SDL3 3.4.16
ABI par défaut arm64-v8a + x86_64
armeabi-v7a différée sans besoin produit mesuré
APK test universal multi-ABI
AAB artefact de distribution cible
splits ABI hors chemin par défaut
```
Le `minSdk 21` est fondé sur le plancher Android actuellement documenté par SDL3, pas sur la seule valeur historique du dépôt. Le `targetSdk 36` est maintenu pour la politique Google Play actuelle.
Le pipeline devra aussi vérifier la compatibilité 16 KB des bibliothèques natives finales. AGP 9.4 et NDK r28c fournissent le socle requis, mais le prébuild SDL3 doit être contrôlé dans l'APK/AAB produit.
## Ownership cible
La logique durable doit rester répartie ainsi :
- Cargo/Rust : moteur, gameplay et `game-android-entrypoint` ;
- `Android/common` : glue Java/JNI commune durable ;
- `Android/game-*` : identité et configuration applicative par jeu ;
- `Android/gradle/` : logique de build Android commune, y compris orchestration Rust native et staging des sorties générées ;
- `assets/` : sources d'assets canoniques ;
- `Android/<app>/build/generated/` : outputs jetables de packaging ;
- `scripts/build_android_rust.py` : mécanisme historique à retirer du chemin normal dès que la responsabilité Gradle est prouvée, puis fichier à supprimer seulement lorsque toutes ses responsabilités sont remplacées.
Aucune `.so` générée ne doit être écrite durablement dans `src/main/jniLibs/` par le nouveau chemin.
## Contrat de la logique Gradle native
La future logique commune doit couvrir au minimum :
1. résolution du NDK side-by-side exact déclaré dans `Android/gradle.properties` ;
2. validation de la présence de l'AAR SDL3 attendu ;
3. extraction par ABI de `libSDL3.so` depuis Prefab vers un répertoire de build ;
4. linkage Rust contre la SDL extraite ;
5. invocation de `cargo ndk` avec `CARGO_NDK_PLATFORM=21` ;
6. mapping strict de chaque module vers exactement une feature `snake` ou `reflex` ;
7. build des ABI demandées, `arm64-v8a` et `x86_64` par défaut ;
8. staging de `libSDL3.so` et `libgame_android_entrypoint.so` dans un répertoire `jniLibs` généré ;
9. branchement de ce répertoire à la variante Android avant packaging ;
10. inputs/outputs Gradle assez précis pour un rebuild incrémental ;
11. diagnostics explicites si outil, target, AAR, NDK ou output manque ;
12. absence de secret de signature dans le dépôt.
Le projet Android natif doit acquérir un Gradle Wrapper épinglé à la version compatible AGP afin que `CMD-051` devienne réellement reproductible sans dépendre d'un Gradle global.
## ABI et compatibilité OS
Le support CPU et le support de versions Android restent deux axes séparés.
`arm64-v8a` est la cible productive obligatoire. `x86_64` est la cible AVD obligatoire de la matrice de développement. Ces deux ABI doivent être présentes dans l'APK universal de validation et dans l'AAB tant qu'aucune décision ultérieure ne restreint la distribution.
`armeabi-v7a` n'est pas introduite par défaut : elle ne permet pas de descendre sous API 21 avec SDL3, agrandit la matrice et ne répond à aucun besoin utilisateur mesuré à ce stade.
Le plancher OS candidat est Android 5.0 / API 21. La version doit tenter un smoke sur API 21 si une image exploitable est raisonnablement disponible. À défaut, elle teste la plus ancienne API localement disponible et consigne explicitement la lacune ; elle ne transforme pas un smoke absent en validation fictive.
## Packaging attendu
L'APK Debug de test doit rester universal : un seul fichier installable contient toutes les ABI retenues. La validation inspecte les entrées `lib/<abi>/...` avant les smokes.
L'AAB est l'artefact de distribution. La validation doit vérifier au minimum :
- présence des bibliothèques natives des ABI retenues ;
- absence de secret/keystore embarqué ;
- configuration d'alignement compatible pages mémoire 16 KB ;
- possibilité d'inspecter le bundle avec les outils Android appropriés ;
- distinction documentée entre bundle de distribution et APK installable.
Les APK split ABI ne sont pas générés par défaut dans `0.3.3`.
## Validation par type de jalon
Pendant les tranches d'implémentation, les validations restent ciblées : audits statiques, gates Rust dès qu'un fichier Rust/Cargo change, puis tâche Gradle du module touché.
Les smokes de packaging deviennent plus larges seulement quand le jalon produit un artefact installable :
- APK universal : inspection ARM64/x86_64 + AVD x86_64 + appareil ARM64 ;
- compatibilité basse : AVD API 21 si raisonnablement disponible, sinon plus ancienne API disponible avec écart documenté ;
- AAB : inspection du bundle et des bibliothèques natives, y compris compatibilité 16 KB ;
- beta/RC : gate workspace large planifiée, rebuild reproductible et smokes finaux.
Les builds, tests et smokes finaux restent exécutés et attestés par l'utilisateur.
## Forecast révisé
### `0-pre.1` — cadrage Android natif
Audit complet de `v0.3.1`, règles, pipeline Python historique, Gradle/AGP/NDK/SDL3, ABI/API, minSdk, APK universal, AAB, pages 16 KB, risques, matrice de validation et plan vivant.
Aucune réécriture Gradle productive dans cette tranche.
### `0-pre.2` — ownership Gradle/Cargo sur Snake mono-ABI
Introduire le Gradle Wrapper compatible AGP 9.4 et la logique Gradle commune minimale. Faire de `:game-snake-poc:assembleDebug` le propriétaire du build Rust `arm64-v8a`, de l'extraction/linkage SDL3 et des `jniLibs` générés, sans appel préalable au script Python.
Le delta doit rester borné à une ABI pour valider l'ordre des tâches, les inputs/outputs, le mapping de feature et les diagnostics avant de multiplier les dimensions.
### `0-pre.3` — multi-ABI et APK universal
Étendre la logique commune à `arm64-v8a + x86_64`, produire un APK Debug universal Snake et vérifier mécaniquement les deux couples `libSDL3.so`/`libgame_android_entrypoint.so`.
Ajouter Reflex comme second consommateur dans cette tranche si, et seulement si, la factorisation commune réduit son activation à une configuration de module sans nouvelle architecture.
### `0-pre.4` — AAB, minSdk et fermeture du chemin historique
Ajouter/valider le chemin `bundleRelease` sans secret, inspecter le bundle et la compatibilité 16 KB, exécuter la stratégie de smoke du plancher Android et supprimer `scripts/build_android_rust.py` si toutes ses responsabilités ont effectivement migré.
Mettre à jour les documents Android/JNI/build durables pour décrire le nouveau chemin réel et ajuster l'audit de distribution si le script historique n'est plus un path requis.
### `2-beta.1` — validation large et packaging final
Exécuter la gate Rust/workspace large planifiée et les tâches Android finales pour Snake et Reflex réellement inclus. Reconstruire l'APK universal et l'AAB depuis un état nettoyé raisonnablement, puis revalider AVD x86_64, appareil ARM64, ABI packagées, 16 KB et compatibilité basse disponible.
Corriger uniquement par `2-beta.1.fix.N` si nécessaire ; ne pas ouvrir une beta cérémonielle supplémentaire si la matrice est propre.
### `3-rc.1` — gel et reproductibilité
Geler le scope, consolider `CHANGELOG.md`, documentation finale, historique beta, matrice RC et prompt de la prochaine version. Rejouer uniquement les gates de publication/reproductibilité prévues ; aucune nouvelle capacité.
### `0.3.3` — stable
Promotion mécanique de la RC validée. Aucun changement fonctionnel ou architectural.
## Sizing
Le scope reste raisonnable pour une seule version si les quatre prereleases conservent leurs frontières verticales. Les zones susceptibles de forcer un split de version sont uniquement une incompatibilité profonde de `cargo-ndk` avec AGP/Gradle, une SDL3 AAR non exploitable par Prefab comme prévu, ou une exigence produit nouvelle pour le 32 bits.
Un simple besoin de `.fix.N` après validation ne remet pas ce sizing en cause.
## Gate avant 0-pre.2
La validation utilisateur de `0-pre.1` doit inclure la gate Rust liée au changement de version workspace et l'inventaire frais suivant :
```bash
rustc --version
cargo --version
cargo ndk --version
rustup target list --installed
java -version
printf 'JAVA_HOME=%s\nANDROID_HOME=%s\n' "$JAVA_HOME" "$ANDROID_HOME"
adb version
adb devices -l
emulator -list-avds
(cd Android && gradle --version)
printf 'configured NDK: '; sed -n 's/^androidNdkVersion=//p' Android/gradle.properties
ls -ld "$ANDROID_HOME/ndk/28.2.13676358"
test -f Android/libs/SDL3-3.4.16.aar && sha256sum Android/libs/SDL3-3.4.16.aar
```
L'absence du Gradle global n'est pas destinée à devenir une dépendance durable : `0-pre.2` doit introduire le wrapper. En revanche, l'inventaire demandé par le prompt `004` doit relever l'état actuel avant cette transition.
## Critères d'entrée en RC
`0.3.3` peut entrer en RC lorsque :
- un build Gradle Android natif n'exige plus `scripts/build_android_rust.py` ;
- Snake produit un APK universal ARM64/x86_64 par un seul chemin Gradle ;
- l'AAB de distribution est constructible sans secret embarqué ;
- les bibliothèques natives finales sont vérifiées pour la contrainte 16 KB ;
- le minSdk soutenu et la preuve de smoke disponible sont documentés sans surpromesse ;
- l'appareil ARM64 réel et l'AVD x86_64 passent le smoke prévu ;
- Reflex est soit branché naturellement au pipeline commun, soit explicitement borné selon les résultats de factorisation ;
- le script Python historique est supprimé s'il n'a plus aucune responsabilité durable ;
- les documents Android, build, JNI et validation décrivent le chemin réellement livré ;
- les gates workspace/beta applicables sont propres.