diff --git a/Android/.gitignore b/Android/.gitignore
new file mode 100644
index 0000000..a287092
--- /dev/null
+++ b/Android/.gitignore
@@ -0,0 +1,7 @@
+# file: Android/.gitignore
+# version: 1
+
+.gradle/
+**/build/
+local.properties
+libs/*.aar
diff --git a/Android/README.md b/Android/README.md
index 4415e99..0ba68a7 100644
--- a/Android/README.md
+++ b/Android/README.md
@@ -1,13 +1,11 @@
-
+
# Android
-Squelette du frontend Android multi-module.
+Le frontend Android est un projet Gradle multi-module séparé du workspace Cargo.
-La baseline définit les frontières Java et les modules, mais ne fige pas encore Android Gradle Plugin, SDK/NDK, SDL3 AAR ni le pipeline Cargo/NDK. Ces éléments seront ajoutés ensemble dans la prerelease Android exécutable afin d'éviter une fausse configuration partiellement fonctionnelle.
-
-Structure cible :
+## Modules
```text
Android/
@@ -16,4 +14,44 @@ Android/
└── game-snake-poc/
```
-`common` deviendra une Android Library. Chaque module jeu deviendra une application indépendante et réutilisera directement les crates Rust du workspace racine sans les recopier.
+`common` est une Android Library Java qui fournit la frontière commune et dépend de l'AAR officiel SDL3.
+
+Chaque module `game-*` est une application Android indépendante et dépend du module `common`.
+
+## Toolchain de référence
+
+Pour la baseline `0.1.0-0-pre.6` :
+
+- Android Gradle Plugin `9.4.0` ;
+- Gradle `9.6.0` attendu par AGP 9.4 ;
+- JDK `17` ;
+- `compileSdk 36` ;
+- `targetSdk 36` ;
+- `minSdk 21` ;
+- SDL3 Android AAR `3.4.16`.
+
+Le NDK n'est pas encore utilisé directement dans ce delta. Le prochain jalon introduira la compilation Rust Android `cdylib` et figera la configuration NDK réellement nécessaire.
+
+## SDL3 AAR
+
+L'archive n'est pas vendorizée dans le dépôt.
+
+Placer :
+
+```text
+SDL3-3.4.16.aar
+```
+
+dans :
+
+```text
+Android/libs/
+```
+
+Le module `common` consomme cet artefact et `SaseGameActivity` étend désormais `org.libsdl.app.SDLActivity`.
+
+## Limite volontaire de ce jalon
+
+Les APK peuvent être compilés côté Java/SDL3 une fois l'AAR disponible, mais ne disposent pas encore du `cdylib` Rust contenant le point d'entrée de jeu.
+
+Le lancement fonctionnel sur appareil/émulateur appartient donc au delta suivant.
diff --git a/Android/build.gradle b/Android/build.gradle
index 254b818..3895b7a 100644
--- a/Android/build.gradle
+++ b/Android/build.gradle
@@ -1,4 +1,7 @@
// file: Android/build.gradle
-// version: 1
+// version: 2
-// Android Gradle Plugin and repositories are intentionally introduced in the dedicated executable Android prerelease.
+plugins {
+ id 'com.android.application' version '9.4.0' apply false
+ id 'com.android.library' version '9.4.0' apply false
+}
diff --git a/Android/common/build.gradle b/Android/common/build.gradle
index 5af6d2a..eff9eee 100644
--- a/Android/common/build.gradle
+++ b/Android/common/build.gradle
@@ -1,4 +1,26 @@
// file: Android/common/build.gradle
-// version: 1
+// version: 2
-// This module will become the reusable Android library containing SDLActivity integration and common platform services.
+plugins {
+ id 'com.android.library'
+}
+
+def sdl3AarName = providers.gradleProperty("sdl3AarName").get()
+
+android {
+ namespace 'com.sasedev.games.common'
+ compileSdk 36
+
+ defaultConfig {
+ minSdk 21
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
+ }
+}
+
+dependencies {
+ api files("../libs/${sdl3AarName}")
+}
diff --git a/Android/common/src/main/AndroidManifest.xml b/Android/common/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..116f143
--- /dev/null
+++ b/Android/common/src/main/AndroidManifest.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/Android/common/src/main/java/com/sasedev/games/common/SaseGameActivity.java b/Android/common/src/main/java/com/sasedev/games/common/SaseGameActivity.java
index ad82e34..718153c 100644
--- a/Android/common/src/main/java/com/sasedev/games/common/SaseGameActivity.java
+++ b/Android/common/src/main/java/com/sasedev/games/common/SaseGameActivity.java
@@ -1,14 +1,14 @@
// file: Android/common/src/main/java/com/sasedev/games/common/SaseGameActivity.java
-// version: 1
+// version: 2
package com.sasedev.games.common;
/**
* Common Android activity boundary for games.sasedev applications.
*
- *
The executable Android delta will make this class extend SDLActivity once the SDL3 AAR is introduced.
+ * The SDL3 Android AAR supplies the common {@code SDLActivity} host. Game-specific activities extend this class.
*/
-public abstract class SaseGameActivity {
+public abstract class SaseGameActivity extends org.libsdl.app.SDLActivity {
/**
* Returns the stable identifier of the game hosted by the activity.
*
diff --git a/Android/game-reflex-poc/build.gradle b/Android/game-reflex-poc/build.gradle
index 0b2eaa7..7dd25ac 100644
--- a/Android/game-reflex-poc/build.gradle
+++ b/Android/game-reflex-poc/build.gradle
@@ -1,4 +1,28 @@
// file: Android/game-reflex-poc/build.gradle
-// version: 1
+// version: 2
-// This module will become the Reflex POC Android application.
+plugins {
+ id 'com.android.application'
+}
+
+android {
+ namespace 'com.sasedev.games.reflex'
+ compileSdk 36
+
+ defaultConfig {
+ applicationId 'com.sasedev.games.reflex'
+ minSdk 21
+ targetSdk 36
+ versionCode 1
+ versionName '0.1.0-0-pre.6'
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
+ }
+}
+
+dependencies {
+ implementation project(':common')
+}
diff --git a/Android/game-reflex-poc/src/main/AndroidManifest.xml b/Android/game-reflex-poc/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..dc7b9d4
--- /dev/null
+++ b/Android/game-reflex-poc/src/main/AndroidManifest.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Android/game-snake-poc/build.gradle b/Android/game-snake-poc/build.gradle
index 89932aa..bc68786 100644
--- a/Android/game-snake-poc/build.gradle
+++ b/Android/game-snake-poc/build.gradle
@@ -1,4 +1,28 @@
// file: Android/game-snake-poc/build.gradle
-// version: 1
+// version: 2
-// This module will become the Snake POC Android application.
+plugins {
+ id 'com.android.application'
+}
+
+android {
+ namespace 'com.sasedev.games.snake'
+ compileSdk 36
+
+ defaultConfig {
+ applicationId 'com.sasedev.games.snake'
+ minSdk 21
+ targetSdk 36
+ versionCode 1
+ versionName '0.1.0-0-pre.6'
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
+ }
+}
+
+dependencies {
+ implementation project(':common')
+}
diff --git a/Android/game-snake-poc/src/main/AndroidManifest.xml b/Android/game-snake-poc/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..77b9ec7
--- /dev/null
+++ b/Android/game-snake-poc/src/main/AndroidManifest.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Android/gradle.properties b/Android/gradle.properties
new file mode 100644
index 0000000..bf6534f
--- /dev/null
+++ b/Android/gradle.properties
@@ -0,0 +1,6 @@
+# file: Android/gradle.properties
+# version: 1
+
+android.useAndroidX=true
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+sdl3AarName=SDL3-3.4.16.aar
diff --git a/Android/libs/README.md b/Android/libs/README.md
new file mode 100644
index 0000000..e9f6c56
--- /dev/null
+++ b/Android/libs/README.md
@@ -0,0 +1,24 @@
+
+
+
+# SDL3 Android Archive
+
+Le projet Android consomme l'archive Android officielle SDL3 sous forme de dépendance externe locale.
+
+Version attendue pour cette baseline :
+
+```text
+SDL3-3.4.16.aar
+```
+
+Le fichier doit être placé ici :
+
+```text
+Android/libs/SDL3-3.4.16.aar
+```
+
+L'archive AAR n'est pas versionnée dans le dépôt.
+
+La version attendue est déclarée dans `Android/gradle.properties` avec `sdl3AarName`.
+
+SDL recommande l'utilisation de son archive Android pour éviter de recopier les sources C et Java de SDL dans chaque projet Android. L'AAR contient notamment la couche Java SDL et les bibliothèques natives nécessaires au runtime Android.
diff --git a/Android/settings.gradle b/Android/settings.gradle
index 9891dcc..314f713 100644
--- a/Android/settings.gradle
+++ b/Android/settings.gradle
@@ -1,5 +1,21 @@
// file: Android/settings.gradle
-// version: 1
+// version: 2
+
+pluginManagement {
+ repositories {
+ google()
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
rootProject.name = "games-sasedev-android"
diff --git a/Cargo.toml b/Cargo.toml
index 99d050a..4078aa2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,5 +1,5 @@
# file: Cargo.toml
-# version: 11
+# version: 12
[workspace]
resolver = "3"
@@ -15,7 +15,7 @@ members = [
]
[workspace.package]
-version = "0.1.0-0-pre.5.fix.3"
+version = "0.1.0-0-pre.6"
edition = "2024"
license = "MIT"
repository = "https://git.sasedev.com/Sasedev/games"
diff --git a/ROADMAP.md b/ROADMAP.md
index f5f2d79..744163e 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -1,5 +1,5 @@
-
+
# Roadmap
@@ -9,12 +9,13 @@
- [x] `0-pre.2` — consolidation documentaire issue de l'architecture de référence, runners Desktop par jeu et politique normative des commandes.
- [x] `0-pre.3` — première boucle moteur exécutable Desktop : temps, input abstrait, capacités de monétisation optionnelles et état de jeu minimal via les runners.
- [x] `0-pre.4` — architecture de tests hors `src/`, stratégie de tests ciblés et socle `tracing`/`tracing-subscriber`/`tracing-appender`.
-- [ ] `0-pre.5` — intégration SDL3 Desktop réelle et premier rendu POC Reflex.
-- [ ] `0-pre.6` — projet Gradle Android exécutable, SDL3 AAR/NDK, compilation Rust `cdylib`, lancement sur appareil/émulateur.
-- [ ] `0-pre.7` — bridge Java/JNI minimal et input tactile Android.
-- [ ] `0-pre.8` — assets communs + spécifiques empaquetés sans copie dans les crates.
-- [ ] `0-pre.9` — POC Reflex jouable Desktop + Android.
-- [ ] `0-pre.10` — POC Snake jouable et validation de la réutilisation du moteur.
+- [x] `0-pre.5` — intégration SDL3 Desktop réelle et premier rendu POC Reflex.
+- [ ] `0-pre.6` — fondation Gradle Android, SDL3 AAR, Activity Java commune et politique de fenêtre Desktop redimensionnable.
+- [ ] `0-pre.7` — compilation Rust Android `cdylib`, point d'entrée SDL Android et premier lancement APK sur appareil/émulateur.
+- [ ] `0-pre.8` — bridge Java/JNI minimal et input tactile Android.
+- [ ] `0-pre.9` — assets communs + spécifiques empaquetés sans copie dans les crates.
+- [ ] `0-pre.10` — POC Reflex jouable Desktop + Android.
+- [ ] `0-pre.11` — POC Snake jouable et validation de la réutilisation du moteur.
- [ ] `1-alpha.1` — première API moteur V1 volontairement stabilisée.
- [ ] `2-beta.1` — stabilisation, packaging, tests multi-appareils.
- [ ] `3-rc.1` — candidat de release du socle 0.1.0.
diff --git a/crates/apps/game-reflex-poc-desktop/src/main.rs b/crates/apps/game-reflex-poc-desktop/src/main.rs
index 20960da..e33f569 100644
--- a/crates/apps/game-reflex-poc-desktop/src/main.rs
+++ b/crates/apps/game-reflex-poc-desktop/src/main.rs
@@ -1,5 +1,5 @@
// file: crates/apps/game-reflex-poc-desktop/src/main.rs
-// version: 4
+// version: 5
#![warn(missing_docs)]
#![deny(unreachable_pub)]
@@ -17,7 +17,7 @@ fn main() {
};
tracing::info!(target: "games::runner", game = "reflex", "desktop SDL3 runner started");
let _monetization = engine_v1_platform_api::MonetizationCapabilities::disabled();
- let runtime = engine_v1_sdl::SdlRuntime::new("Reflex POC", 720, 1280, std::time::Duration::from_millis(16));
+ let runtime = engine_v1_sdl::SdlRuntime::new("Reflex POC", 405, 720, std::time::Duration::from_millis(16));
let mut state = game_reflex_poc::ReflexState::new();
match runtime.run(&mut state) {
std::result::Result::Ok(()) => {},
diff --git a/crates/apps/game-snake-poc-desktop/src/main.rs b/crates/apps/game-snake-poc-desktop/src/main.rs
index 9ca0e16..757c1a6 100644
--- a/crates/apps/game-snake-poc-desktop/src/main.rs
+++ b/crates/apps/game-snake-poc-desktop/src/main.rs
@@ -1,5 +1,5 @@
// file: crates/apps/game-snake-poc-desktop/src/main.rs
-// version: 4
+// version: 5
#![warn(missing_docs)]
#![deny(unreachable_pub)]
@@ -17,7 +17,7 @@ fn main() {
};
tracing::info!(target: "games::runner", game = "snake", "desktop SDL3 runner started");
let _monetization = engine_v1_platform_api::MonetizationCapabilities::disabled();
- let runtime = engine_v1_sdl::SdlRuntime::new("Snake POC", 720, 1280, std::time::Duration::from_millis(16));
+ let runtime = engine_v1_sdl::SdlRuntime::new("Snake POC", 405, 720, std::time::Duration::from_millis(16));
let mut state = game_snake_poc::SnakeState::new();
match runtime.run(&mut state) {
std::result::Result::Ok(()) => {},
diff --git a/crates/engines/engine-v1-sdl/src/runtime.rs b/crates/engines/engine-v1-sdl/src/runtime.rs
index 180c9ed..98b63ab 100644
--- a/crates/engines/engine-v1-sdl/src/runtime.rs
+++ b/crates/engines/engine-v1-sdl/src/runtime.rs
@@ -1,5 +1,5 @@
// file: crates/engines/engine-v1-sdl/src/runtime.rs
-// version: 3
+// version: 4
/// Minimal SDL3 runtime used by Desktop POC runners.
pub struct SdlRuntime {
@@ -29,7 +29,7 @@ impl SdlRuntime {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
- let window = match video.window(&self.title, self.width, self.height).position_centered().build() {
+ let window = match video.window(&self.title, self.width, self.height).position_centered().resizable().build() {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
diff --git a/deltas/0.1.0/0-pre.6.md b/deltas/0.1.0/0-pre.6.md
new file mode 100644
index 0000000..ff35282
--- /dev/null
+++ b/deltas/0.1.0/0-pre.6.md
@@ -0,0 +1,140 @@
+
+
+
+# Delta 0.1.0-0-pre.6
+
+## Base
+
+Base validée : `0.1.0-0-pre.5.fix.3`.
+
+## Validation du delta précédent
+
+`0.1.0-0-pre.5.fix.3` a été validée par l'utilisateur le 2026-09-16.
+
+Les résultats fournis étaient propres pour :
+
+- formatage Rust ;
+- audits Rust/workspace ;
+- audit Markdown : `1 table(s), 43 file(s)` ;
+- `cargo check --workspace` ;
+- Clippy global strict ;
+- test ciblé `engine-v1-sdl` ;
+- runners SDL3 Reflex et Snake.
+
+Les runners ont utilisé `sdl3 0.20.0` / `sdl3-sys 0.7.1` et se sont fermés proprement.
+
+## Objectifs
+
+- préparer le projet Gradle Android réel sans introduire prématurément le `cdylib` Rust ;
+- utiliser l'AAR officiel SDL3 comme frontière Android commune ;
+- conserver Java comme langage Android du projet ;
+- réduire la taille initiale des fenêtres Desktop et autoriser leur redimensionnement.
+
+## Desktop
+
+Les runners portrait utilisent désormais une fenêtre initiale :
+
+```text
+405 × 720
+```
+
+La fenêtre SDL3 est redimensionnable.
+
+Cette dimension est une taille physique de développement, pas une résolution logique de gameplay.
+
+## Android
+
+Le projet Android introduit :
+
+- AGP `9.4.0` ;
+- `compileSdk 36` ;
+- `targetSdk 36` ;
+- `minSdk 21` ;
+- Java 17 ;
+- SDL3 AAR `3.4.16` ;
+- module `common` Android Library ;
+- modules applications `game-reflex-poc` et `game-snake-poc` ;
+- manifests de lancement portrait ;
+- `SaseGameActivity` dérivée de `org.libsdl.app.SDLActivity`.
+
+L'AAR SDL3 reste externe et n'est pas commité dans le dépôt.
+
+## Découpage volontaire de la roadmap
+
+Le précédent objectif `0-pre.6` regroupait trop de frontières à la fois : Gradle, AAR SDL3, NDK, Rust `cdylib` et lancement.
+
+Il est scindé en :
+
+- `0-pre.6` : projet Gradle + AAR + Java SDLActivity ;
+- `0-pre.7` : Rust Android `cdylib` + point d'entrée SDL + premier APK lancé ;
+- `0-pre.8` : Java/JNI services + input tactile.
+
+## Validation Rust à exécuter par l'utilisateur
+
+Le delta modifie du Rust :
+
+```bash
+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 deltas history
+
+cargo check --workspace
+cargo clippy --workspace --all-targets --all-features -- -D warnings
+```
+
+Test ciblé SDL3 :
+
+```bash
+cargo test -p engine-v1-sdl --all-targets --all-features
+```
+
+Smokes Desktop :
+
+```bash
+cargo run -p game-reflex-poc-desktop
+cargo run -p game-snake-poc-desktop
+```
+
+Vérifier notamment que :
+
+- la fenêtre initiale est sensiblement plus petite que précédemment ;
+- elle est redimensionnable ;
+- `Escape` et la fermeture système restent fonctionnels.
+
+## Préflight Android
+
+Vérifier Java :
+
+```bash
+java -version
+```
+
+Une JVM 17 doit être disponible pour AGP 9.4.
+
+Placer l'AAR officiel SDL3 :
+
+```text
+Android/libs/SDL3-3.4.16.aar
+```
+
+Le build Gradle est alors validable avec Gradle `9.6.0` ou via Android Studio compatible AGP 9.4.
+
+Si une installation Gradle 9.6.0 est disponible :
+
+```bash
+cd Android
+gradle :common:assembleDebug
+gradle :game-reflex-poc:assembleDebug
+gradle :game-snake-poc:assembleDebug
+cd ..
+```
+
+Le lancement des APK n'est pas une gate de ce delta : le `cdylib` Rust et le point d'entrée SDL Android seront ajoutés en `0-pre.7`.
+
+## Règle de transition
+
+Si les gates Rust sont propres et que la synchronisation/build Android Java+SDL3 AAR est propre sur la machine équipée, passer automatiquement à `0.1.0-0-pre.7`.
+
+En cas d'échec provoqué par les fichiers de ce delta, produire `0.1.0-0-pre.6.fix.1`.
diff --git a/docs/000-README.md b/docs/000-README.md
index c18f5e7..7d4ad79 100644
--- a/docs/000-README.md
+++ b/docs/000-README.md
@@ -1,5 +1,5 @@
-
+
# Documentation games.sasedev
@@ -49,6 +49,7 @@ Voir [`../RULES.md`](../RULES.md), notamment [`rules/RULES_COMMANDS.md`](rules/R
- [`testing/001-TEST_ARCHITECTURE.md`](testing/001-TEST_ARCHITECTURE.md) — séparation `unit_tests/` / `tests/`, tests ciblés et tracing de test.
- [`development/003-TRACING_AND_DIAGNOSTICS.md`](development/003-TRACING_AND_DIAGNOSTICS.md) — socle `tracing`, subscriber et appender communs.
- [`development/004-SDL3_DESKTOP_PREREQUISITES.md`](development/004-SDL3_DESKTOP_PREREQUISITES.md) — prérequis SDL3 Desktop, stratégie de liaison système et vérification `pkg-config`.
+- [`development/005-DESKTOP_WINDOW_POLICY.md`](development/005-DESKTOP_WINDOW_POLICY.md) — taille initiale, redimensionnement et séparation future entre fenêtre physique et résolution virtuelle.
## Historique validé
diff --git a/docs/development/005-DESKTOP_WINDOW_POLICY.md b/docs/development/005-DESKTOP_WINDOW_POLICY.md
new file mode 100644
index 0000000..15aa382
--- /dev/null
+++ b/docs/development/005-DESKTOP_WINDOW_POLICY.md
@@ -0,0 +1,36 @@
+
+
+
+# Politique de fenêtre Desktop
+
+## Objectif
+
+La taille de fenêtre Desktop est une surface de développement et ne doit pas être confondue avec la résolution logique ou la résolution d'un téléphone.
+
+## Baseline portrait
+
+Les POC portrait utilisent par défaut :
+
+```text
+405 × 720
+```
+
+La fenêtre SDL3 est redimensionnable.
+
+Cette taille initiale tient plus facilement sur un écran Desktop qu'une fenêtre `720 × 1280`, tout en conservant un ratio portrait proche de `9:16`.
+
+## Évolution
+
+Le moteur devra ensuite distinguer :
+
+- taille physique de fenêtre ;
+- taille du drawable/backbuffer ;
+- résolution virtuelle logique ;
+- viewport ;
+- scaling ;
+- letterboxing/pillarboxing ;
+- densité de pixels.
+
+Le gameplay ne devra jamais dépendre directement de la taille physique de la fenêtre.
+
+Une politique de taille minimale et de conservation éventuelle du ratio pourra être ajoutée lorsque le renderer 2D réel sera introduit.
diff --git a/history/0.1.0/0-pre.5.fix.3.md b/history/0.1.0/0-pre.5.fix.3.md
new file mode 100644
index 0000000..ac99d45
--- /dev/null
+++ b/history/0.1.0/0-pre.5.fix.3.md
@@ -0,0 +1,35 @@
+
+
+
+# Historique 0.1.0-0-pre.5.fix.3
+
+## Statut
+
+Validé par l'utilisateur le 2026-09-16.
+
+## Gates validées
+
+- `cargo fmt --all` ;
+- `cargo fmt --all -- --check` ;
+- audits Python du workspace et des tableaux Markdown ;
+- `cargo check --workspace` ;
+- `cargo clippy --workspace --all-targets --all-features -- -D warnings` ;
+- `cargo test -p engine-v1-sdl --all-targets --all-features` ;
+- smoke interactif `game-reflex-poc-desktop` ;
+- smoke interactif `game-snake-poc-desktop`.
+
+## Résultats observés
+
+La crate Rust SDL3 a été résolue en `sdl3 0.20.0` avec `sdl3-sys 0.7.1`.
+
+Les deux runners ont ouvert puis fermé proprement leur fenêtre SDL3 avec tracing actif.
+
+## Portée durable
+
+Ce jalon valide :
+
+- SDL3 Desktop réel ;
+- liaison Linux via `pkg-config` ;
+- version SDL3 Rust canonique portée par le workspace ;
+- features SDL3 portées uniquement par la crate consommatrice ;
+- séparation fonctionnelle entre crates de jeu et runners Desktop.