0.3.3-0-pre.3

This commit is contained in:
2026-09-21 10:32:31 +02:00
parent f770f99a4a
commit 5854ac3d07
16 changed files with 1004 additions and 107 deletions

180
deltas/0.3.3/0-pre.2.md Normal file
View File

@@ -0,0 +1,180 @@
<!-- file: deltas/0.3.3/0-pre.2.md -->
<!-- version: 1 -->
# Delta 0.3.3-0-pre.2
## Base et statut précédent
Cette tranche part exclusivement de `0.3.3-0-pre.1` validé par l'utilisateur le 2026-09-21. `history/0.3.3/0-pre.1.md` enregistre la gate propre et l'inventaire Android réellement observé avant ouverture du développement productif.
Aucun fix de `0-pre.1` n'est requis.
## Objectif
Prouver sur Snake Debug et une seule ABI que Gradle possède désormais la chaîne native complète :
```text
:game-snake-poc:assembleDebug
-> source jniLibs générée par AGP Variant API
-> extraction de libSDL3.so depuis l'AAR
-> résolution du NDK projet r28c
-> cargo ndk arm64-v8a
-> feature snake uniquement
-> libSDL3.so + libgame_android_entrypoint.so
-> APK Debug ARM64
```
La commande normale ne dépend plus d'un appel préalable à `scripts/build_android_rust.py snake`.
## Gradle Wrapper reproductible
Le projet Android reçoit le wrapper Gradle et l'épingle à `9.6.0`, version attendue par AGP `9.4.0` dans le cadrage `0-pre.1`.
Contrats de chaîne d'approvisionnement :
```text
Gradle 9.6.0 binary ZIP SHA-256
bbaeb2fef8710818cf0e261201dab964c572f92b942812df0c3620d62a529a01
Gradle Wrapper JAR SHA-256
497c8c2a7e5031f6aa847f88104aa80a93532ec32ee17bdb8d1d2f67a194a9c7
```
`validateDistributionUrl=true` reste activé. L'audit de distribution vérifie statiquement ces contrats.
Le wrapper respecte `JAVA_HOME`; l'environnement utilisateur validé expose JDK 17 via cette variable même si `java` dans le `PATH` pointe vers JDK 25.
## Ownership Gradle/Cargo
`Android/gradle/sasedev-rust-android.gradle` introduit une tâche native incrémentale par ABI. Ses inputs comprennent l'AAR SDL3, les manifests/configurations Cargo utiles, le code Rust, la feature, l'ABI, l'API Android et la version NDK. Son output est un répertoire `jniLibs` généré sous `build/generated/sasedevNative/...`.
La tâche :
1. extrait `libSDL3.so` depuis Prefab ou le fallback AAR compatible ;
2. résout `${ANDROID_HOME}/ndk/28.2.13676358` ou l'équivalent `ANDROID_SDK_ROOT` ;
3. définit `ANDROID_NDK_HOME`, `CARGO_NDK_PLATFORM=21` et le chemin de linkage SDL3 uniquement pour le sous-processus ;
4. lance `cargo ndk` sans defaults avec la seule feature Snake ;
5. vérifie les deux `.so` attendus ;
6. remet l'output à `variant.sources.jniLibs.addGeneratedSourceDirectory`, qui crée la dépendance de build AGP.
Aucun nouvel orchestrateur Python ou shell spécifique au projet n'est introduit.
## Borne mono-ABI
`game-snake-poc` fixe volontairement :
```text
feature snake
ABI arm64-v8a
API Rust 21
```
et `ndk.abiFilters 'arm64-v8a'` empêche ce jalon de masquer une erreur de task wiring derrière le packaging d'autres ABI. `x86_64` reste pour `0-pre.3` après validation réelle de cette preuve ARM64.
Reflex n'est pas modifié dans cette tranche.
## Audit de distribution
`scripts/audit_distribution_layout.py` exige désormais les cinq nouveaux éléments durables du pipeline :
```text
Android/gradlew
Android/gradlew.bat
Android/gradle/wrapper/gradle-wrapper.jar
Android/gradle/wrapper/gradle-wrapper.properties
Android/gradle/sasedev-rust-android.gradle
```
Il contrôle également le checksum du JAR wrapper, la distribution 9.6.0, l'absence de délégation Python dans le nouveau build natif et le contrat mono-ABI Snake.
## Fichiers
Ajoutés :
```text
Android/gradlew
Android/gradlew.bat
Android/gradle/sasedev-rust-android.gradle
Android/gradle/wrapper/gradle-wrapper.jar
Android/gradle/wrapper/gradle-wrapper.properties
deltas/0.3.3/0-pre.2.md
history/0.3.3/0-pre.1.md
```
Modifiés :
```text
Android/README.md
Android/game-snake-poc/build.gradle
Cargo.toml
docs/development/006-ANDROID_RUST_NATIVE_BUILD.md
scripts/audit_distribution_layout.py
```
`scripts/build_android_rust.py`, Reflex, les sources Rust, `CHANGELOG.md` et `ROADMAP.md` restent inchangés.
## Validations exécutées dans l'environnement de génération
Le générateur exécute uniquement les audits statiques autorisés après constitution du delta :
```bash
python3 scripts/audit_rust_workspace_rules.py
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates Android Web deltas history
python3 scripts/audit_distribution_layout.py
```
Aucun build Cargo/Gradle, test ou smoke final n'est attribué au générateur.
## Validation utilisateur demandée
Depuis la racine :
```bash
export JAVA_HOME=/usr/lib/jvm/temurin-17-jdk-amd64
python3 scripts/audit_rust_workspace_rules.py
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates Android Web deltas history
python3 scripts/audit_distribution_layout.py
cargo fmt --all
cargo fmt --all -- --check
cargo check --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
sha256sum Android/gradle/wrapper/gradle-wrapper.jar
grep -E '^(distributionUrl|distributionSha256Sum|validateDistributionUrl)=' Android/gradle/wrapper/gradle-wrapper.properties
(cd Android && ./gradlew --version)
(cd Android && ./gradlew :game-snake-poc:assembleDebug)
```
Le build Snake doit être lancé directement : ne pas appeler `scripts/build_android_rust.py snake` avant Gradle.
Puis inspecter l'APK produit :
```bash
APK="$(find Android/game-snake-poc/build/outputs/apk/debug -maxdepth 1 -type f -name '*.apk' -print -quit)"
test -n "$APK"
printf 'APK=%s\n' "$APK"
unzip -Z1 "$APK" | grep '^lib/' | sort
unzip -Z1 "$APK" | grep -Fx 'lib/arm64-v8a/libSDL3.so'
unzip -Z1 "$APK" | grep -Fx 'lib/arm64-v8a/libgame_android_entrypoint.so'
if unzip -Z1 "$APK" | grep -Eq '^lib/(x86_64|armeabi-v7a|x86)/'; then
printf '%s\n' 'unexpected non-ARM64 native library in mono-ABI proof' >&2
exit 1
fi
```
Le checksum attendu du wrapper JAR est :
```text
497c8c2a7e5031f6aa847f88104aa80a93532ec32ee17bdb8d1d2f67a194a9c7
```
Aucun smoke appareil n'est requis dans cette tranche ; il reste planifié après établissement du packaging multi-ABI.
## Suite après validation
Si cette gate est propre, `0-pre.3` crée `history/0.3.3/0-pre.2.md`, étend le même ownership à `arm64-v8a + x86_64`, exige un APK Debug universal contenant les deux couples de bibliothèques et migre Reflex uniquement si la factorisation commune reste naturelle.
Une erreur de wrapper, de task wiring, de linkage SDL3, de feature Cargo ou de contenu APK produit d'abord `0-pre.2.fix.N`.

View File

@@ -0,0 +1,4 @@
Android/gradlew
Android/gradlew.bat
Android/gradle/wrapper/gradle-wrapper.jar
Android/gradle/wrapper/gradle-wrapper.properties

253
deltas/0.3.3/0-pre.3.md Normal file
View File

@@ -0,0 +1,253 @@
<!-- file: deltas/0.3.3/0-pre.3.md -->
<!-- version: 1 -->
# Delta 0.3.3-0-pre.3
## Base et statut précédent
Cette tranche part exclusivement de `0.3.3-0-pre.2`, validé par l'utilisateur le 2026-09-21. `history/0.3.3/0-pre.2.md` enregistre la gate complète, le build Gradle réussi et l'APK Snake ARM64 inspecté.
Aucun fix de `0-pre.2` n'est requis.
## Objectif
Cette tranche traite ensemble les deux décisions prévues avant l'AAB :
1. passer d'une version Gradle/JDK imposée pour la preuve à un contrat de minimum compatible avec l'environnement ;
2. élargir le pipeline Gradle/Cargo natif à `arm64-v8a + x86_64` et produire des APK Debug universal.
Snake reste le jeu-sonde principal. Reflex devient le second consommateur de la logique commune puisque sa migration ne demande qu'un mapping de feature et d'ABI, sans nouvelle architecture.
## Politique Gradle minimale
AGP `9.4.0` conserve Gradle `9.6.0` comme minimum. Le projet déclare désormais dans `Android/settings.gradle` :
```text
minimumGradleVersion = 9.6.0
```
Le script compare ce minimum à `GradleVersion.current()` et échoue explicitement si le Gradle système est trop ancien.
Le projet Android natif ne versionne plus de Gradle Wrapper. Une machine avec Gradle `9.6.0`, `9.7.1` ou une version ultérieure compatible utilise directement sa propre version. La version réellement employée est consignée par la gate avec :
```bash
(cd Android && gradle --version)
```
Cette décision concerne uniquement `Android/`. Les wrappers générés ou contraintes historiques propres au POC Tauri restent locaux à la crate Tauri et ne sont pas réinterprétés.
## Politique JDK
Aucun `export JAVA_HOME=/usr/lib/jvm/temurin-17-jdk-amd64` n'est imposé au chemin SDL3 natif.
Gradle/AGP utilisent le JDK fourni normalement par le shell ou l'IDE. Le minimum de la chaîne reste Java 17, tandis que la gate doit vérifier le JDK réellement sélectionné. Le JDK 25 installé dans l'environnement utilisateur est donc un candidat normal pour cette validation.
La glue Java Android conserve volontairement :
```text
sourceCompatibility = 17
targetCompatibility = 17
```
Le JDK de build et le niveau Java de l'application restent deux contrats distincts.
## Multi-ABI Snake
`game-snake-poc` déclare maintenant :
```text
feature snake
ABI arm64-v8a + x86_64
API Rust 21
```
et :
```text
abiFilters 'arm64-v8a', 'x86_64'
```
La logique commune `sasedev-rust-android.gradle`, déjà prouvée en mono-ABI, enregistre une tâche Rust par ABI et remet les deux répertoires `jniLibs` générés à AGP. L'APK Debug attendu est universal, sans split ABI par défaut.
## Reflex devient second consommateur
`game-reflex-poc` reçoit uniquement la configuration symétrique :
```text
feature reflex
ABI arm64-v8a + x86_64
API Rust 21
```
puis applique la même logique Gradle commune. Aucun nouveau script, type de tâche, bridge JNI ou chemin d'output n'est introduit.
Cette symétrie confirme que la factorisation appartient bien à `Android/gradle/sasedev-rust-android.gradle` et non aux modules de jeu.
## Suppression du wrapper natif
Un ZIP delta n'efface pas les fichiers d'un jalon précédent. Le manifest :
```text
deltas/0.3.3/0-pre.3.delete.txt
```
supprime :
```text
Android/gradlew
Android/gradlew.bat
Android/gradle/wrapper/gradle-wrapper.jar
Android/gradle/wrapper/gradle-wrapper.properties
```
Après extraction du delta à la racine du dépôt, appliquer :
```bash
while IFS= read -r path; do
rm -f -- "$path"
done < deltas/0.3.3/0-pre.3.delete.txt
rmdir --ignore-fail-on-non-empty Android/gradle/wrapper
```
L'audit de distribution traite désormais ces quatre fichiers comme interdits dans le projet Android natif afin d'éviter un retour involontaire à une version Gradle épinglée.
## Règles et documentation
Les règles de commandes Android utilisent désormais `gradle` depuis `Android/` et exigent le minimum déclaré par le projet. `CMD-051` devient :
```text
(cd Android && gradle :<app>:assembleDebug)
```
Le plan `0.3.3`, la documentation Android et le document de build natif distinguent explicitement :
- Gradle système `>= 9.6.0` ;
- JDK runtime fourni par l'environnement ;
- Java source/target 17 ;
- contraintes Tauri historiques séparées ;
- deux ABI natives productives de cette tranche.
## Fichiers
Ajoutés :
```text
deltas/0.3.3/0-pre.3.md
deltas/0.3.3/0-pre.3.delete.txt
history/0.3.3/0-pre.2.md
```
Modifiés :
```text
Android/README.md
Android/game-reflex-poc/build.gradle
Android/game-snake-poc/build.gradle
Android/settings.gradle
Cargo.toml
docs/development/006-ANDROID_RUST_NATIVE_BUILD.md
docs/plans/003-V0_3_3_ANDROID_NATIVE_MULTI_ABI_PLAN.md
docs/rules/RULES_COMMANDS.md
docs/rules/RULES_VALIDATION_MATRIX.md
scripts/audit_distribution_layout.py
```
Supprimés par manifest :
```text
Android/gradlew
Android/gradlew.bat
Android/gradle/wrapper/gradle-wrapper.jar
Android/gradle/wrapper/gradle-wrapper.properties
```
`scripts/build_android_rust.py`, le code Rust, les manifests Android, `CHANGELOG.md` et `ROADMAP.md` restent inchangés.
## Validations exécutées dans l'environnement de génération
Le générateur exécute uniquement les audits statiques autorisés après constitution du delta :
```bash
python3 scripts/audit_rust_workspace_rules.py
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates Android Web deltas history
python3 scripts/audit_distribution_layout.py
```
Aucun build Cargo/Gradle, test ou smoke final n'est attribué au générateur.
## Validation utilisateur demandée
Exécuter la gate depuis un shell normal, sans ajouter l'ancien `export JAVA_HOME=/usr/lib/jvm/temurin-17-jdk-amd64` :
```bash
java -version
printf 'JAVA_HOME=%s\nANDROID_HOME=%s\n' "$JAVA_HOME" "$ANDROID_HOME"
(cd Android && gradle --version)
cargo fmt --all
cargo fmt --all -- --check
python3 scripts/audit_rust_workspace_rules.py
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates Android Web deltas history
python3 scripts/audit_distribution_layout.py
cargo check --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
(cd Android && gradle :game-snake-poc:assembleDebug)
(cd Android && gradle :game-reflex-poc:assembleDebug)
```
La sortie `gradle --version` doit montrer une version `>= 9.6.0` et le JDK effectivement fourni par votre environnement. Une version supérieure au minimum n'est pas une divergence.
## Inspection des APK universal
Pour chaque jeu :
```bash
for game in game-snake-poc game-reflex-poc; do
APK="$(find "Android/${game}/build/outputs/apk/debug" -maxdepth 1 -type f -name '*.apk' -print -quit)"
test -n "$APK"
printf 'APK=%s\n' "$APK"
unzip -Z1 "$APK" | grep '^lib/' | sort
for abi in arm64-v8a x86_64; do
unzip -Z1 "$APK" | grep -Fx "lib/${abi}/libSDL3.so"
unzip -Z1 "$APK" | grep -Fx "lib/${abi}/libgame_android_entrypoint.so"
done
if unzip -Z1 "$APK" | grep -Eq '^lib/(armeabi-v7a|x86)/'; then
printf '%s\n' "unexpected 32-bit native library in ${game} universal APK" >&2
exit 1
fi
done
```
L'absence de split est démontrée par un seul APK Debug par module contenant simultanément les bibliothèques ARM64 et x86_64.
## Smoke multi-architecture Snake
Après inspection mécanique, installer le même APK Snake sur l'AVD x86_64 puis sur l'appareil ARM64 réel.
AVD connu :
```bash
APK="Android/game-snake-poc/build/outputs/apk/debug/game-snake-poc-debug.apk"
adb -s emulator-5554 install -r "$APK"
adb -s emulator-5554 shell am start -n com.sasedev.games.snake/.SnakeActivity
```
Puis sur l'appareil réel en remplaçant `<arm64-serial>` par le serial affiché par `adb devices -l` :
```bash
adb -s <arm64-serial> install -r "$APK"
adb -s <arm64-serial> shell am start -n com.sasedev.games.snake/.SnakeActivity
```
Le smoke attendu est borné : lancement sans erreur de chargement JNI/SDL3 et affichage du jeu. La validation gameplay exhaustive reste hors de ce jalon.
## Suite après validation
Si cette gate est propre, `0-pre.4` ouvre le chemin AAB, la vérification 16 KB, la validation du plancher Android disponible et la fermeture de `scripts/build_android_rust.py` si aucune responsabilité n'y subsiste.
Toute erreur de minimum Gradle, exécution JDK, task wiring x86_64, linkage SDL3, packaging universal ou activation Reflex produit d'abord `0-pre.3.fix.1`.