0.3.1-0-pre.2
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# file: Cargo.toml
|
||||
# version: 70
|
||||
# version: 71
|
||||
|
||||
[workspace]
|
||||
resolver = "3"
|
||||
@@ -17,10 +17,11 @@ members = [
|
||||
"crates/apps/game-reflex-poc-tauri",
|
||||
"crates/apps/game-reflex-poc-wasm",
|
||||
"crates/apps/game-snake-poc-wasm",
|
||||
"crates/apps/game-snake-poc-tauri",
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.3.1-0-pre.1"
|
||||
version = "0.3.1-0-pre.2"
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
repository = "https://git.sasedev.com/Sasedev/games"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: README.md -->
|
||||
<!-- version: 41 -->
|
||||
<!-- version: 42 -->
|
||||
|
||||
# games.sasedev
|
||||
|
||||
@@ -26,7 +26,7 @@ Workspace expérimental puis productif pour des jeux multiplateformes principale
|
||||
|
||||
Version stable de référence : `0.3.0`.
|
||||
|
||||
Version de développement courante : `0.3.1-0-pre.1`.
|
||||
Version de développement courante : `0.3.1-0-pre.2`.
|
||||
|
||||
Les deux premiers jeux sont des POC structurels : `game-reflex-poc` et `game-snake-poc`. Ils existent d'abord pour valider les frontières du workspace, le moteur, les assets et le packaging multiplateforme.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: Web/game-snake-poc/frontend/ts/provenance.ts
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
import type { SnakeWasmGame } from "@snake-wasm";
|
||||
import { webInfo } from "./logging";
|
||||
@@ -83,7 +83,7 @@ export class BrowserRuntimeProvenance {
|
||||
|
||||
private synchronize(): void {
|
||||
const profile = inputProfile(this.keyboardMouseObserved, this.touchObserved);
|
||||
if (!this.game.configure_runtime_provenance(this.deviceClass, profile)) {
|
||||
if (!this.game.configure_runtime_provenance("web", "browser", this.deviceClass, profile)) {
|
||||
throw new Error("La provenance navigateur n'a pas pu être configurée dans le bridge WASM.");
|
||||
}
|
||||
this.output.value = displayLabel(this.game);
|
||||
|
||||
34
crates/apps/game-snake-poc-tauri/Cargo.toml
Normal file
34
crates/apps/game-snake-poc-tauri/Cargo.toml
Normal file
@@ -0,0 +1,34 @@
|
||||
# file: crates/apps/game-snake-poc-tauri/Cargo.toml
|
||||
# version: 1
|
||||
|
||||
[package]
|
||||
name = "game-snake-poc-tauri"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
authors.workspace = true
|
||||
publish.workspace = true
|
||||
|
||||
[lib]
|
||||
name = "game_snake_poc_tauri_lib"
|
||||
path = "src/lib.rs"
|
||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||
|
||||
[[bin]]
|
||||
name = "game-snake-poc-tauri"
|
||||
path = "src/main.rs"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build.workspace = true
|
||||
|
||||
[dependencies]
|
||||
engine-v1-platform-api = { path = "../../engines/engine-v1-platform-api" }
|
||||
game-logging-lib = { path = "../../common/game-logging-lib" }
|
||||
serde.workspace = true
|
||||
tauri.workspace = true
|
||||
tauri-plugin-tracing.workspace = true
|
||||
tracing.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
25
crates/apps/game-snake-poc-tauri/README.md
Normal file
25
crates/apps/game-snake-poc-tauri/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
<!-- file: crates/apps/game-snake-poc-tauri/README.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# game-snake-poc-tauri
|
||||
|
||||
Host Tauri Android du POC Snake. Cette application réutilise le gameplay Rust de `game-snake-poc` et l'unique adapter WebAssembly `game-snake-poc-wasm` ; elle ne possède aucune règle de jeu.
|
||||
|
||||
## Responsabilités
|
||||
|
||||
La crate possède uniquement la frontière Tauri : initialisation du logging Rust, assemblage/plugins/commandes Tauri, contrat minimal de provenance native et frontend Vite/TypeScript exécuté dans la WebView Android.
|
||||
|
||||
L'organisation Rust suit le modèle des applications Desk KSP :
|
||||
|
||||
- `src/lib.rs` reste une façade et réexporte les éléments partagés au crate-root ;
|
||||
- `src/tauri.rs` assemble Tauri et fait déléguer les commandes aux modules propriétaires ;
|
||||
- `src/runtime.rs` possède le petit contrat runtime/provenance ;
|
||||
- `frontend/` contient le host WebView et consomme les bindings générés de `game-snake-poc-wasm`.
|
||||
|
||||
Le frontend minimal de `0.3.1-0-pre.2` valide uniquement le démarrage Tauri, le bridge Rust, le tracing et le chargement du même adapter WASM que le Web direct. Canvas, contrôles, assets et lifecycle complet sont prévus dans les tranches suivantes.
|
||||
|
||||
## Build
|
||||
|
||||
Les hooks `beforeDevCommand` et `beforeBuildCommand` de Tauri possèdent le build WASM et Vite. Aucun orchestrateur Python n'est utilisé. Les bindings WASM, la distribution Vite, les caches, `node_modules/` et le projet Android généré restent hors des sources livrées ou dans des chemins générés ignorés.
|
||||
|
||||
Voir [`USAGE.md`](USAGE.md) pour l'initialisation locale et les smokes Android.
|
||||
42
crates/apps/game-snake-poc-tauri/USAGE.md
Normal file
42
crates/apps/game-snake-poc-tauri/USAGE.md
Normal file
@@ -0,0 +1,42 @@
|
||||
<!-- file: crates/apps/game-snake-poc-tauri/USAGE.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Utilisation — Snake Tauri Android
|
||||
|
||||
## Prérequis locaux
|
||||
|
||||
Le host utilise Cargo/Rust, `cargo tauri`, Node/npm, `wasm-bindgen`, Java et le SDK Android. Le dépôt attend `ANDROID_HOME` vers le SDK Android et des NDK side-by-side sous `$ANDROID_HOME/ndk/<version>`.
|
||||
|
||||
`NDK_HOME` n'est pas imposé globalement par le projet. Si une commande Tauri locale le réclame, définir ponctuellement `NDK_HOME` vers une version NDK exacte installée sous `$ANDROID_HOME/ndk/`; ne pas sélectionner implicitement une version lorsque plusieurs NDK coexistent.
|
||||
|
||||
`JAVA_HOME` n'est pas imposé tant que la CLI Tauri résout correctement `java` depuis l'environnement. En cas de diagnostic explicite de la CLI, fixer alors `JAVA_HOME` vers le JDK réellement choisi.
|
||||
|
||||
Pour les cibles actuellement disponibles, `aarch64-linux-android` permet le smoke sur l'appareil ARM64 et `x86_64-linux-android` celui des AVD x86_64. Les autres ABI ne sont pas requises pour `0-pre.2`.
|
||||
|
||||
## Initialisation locale
|
||||
|
||||
Installer les dépendances frontend dans la crate :
|
||||
|
||||
```bash
|
||||
(cd crates/apps/game-snake-poc-tauri && npm install)
|
||||
```
|
||||
|
||||
Initialiser une fois le projet Android généré par Tauri :
|
||||
|
||||
```bash
|
||||
(cd crates/apps/game-snake-poc-tauri && cargo tauri android init)
|
||||
```
|
||||
|
||||
Le répertoire `gen/` produit par Tauri est généré et ignoré ; il n'appartient pas aux deltas.
|
||||
|
||||
## Smoke Android de développement
|
||||
|
||||
Lancer ensuite :
|
||||
|
||||
```bash
|
||||
(cd crates/apps/game-snake-poc-tauri && cargo tauri android dev)
|
||||
```
|
||||
|
||||
Choisir l'appareil réel ou l'AVD voulu lorsque la CLI le demande. Le frontend doit afficher une provenance `android / tauri-webview / wasm / unknown / unknown` et les événements de démarrage doivent apparaître dans le tracing/logcat.
|
||||
|
||||
Ne pas utiliser `npm run dev` ou `npm run build` comme gate manuelle : ces scripts sont des hooks internes possédés par Tauri. `cargo tauri android build` reste réservé au jalon de packaging prévu par le plan, sauf diagnostic explicite.
|
||||
7
crates/apps/game-snake-poc-tauri/build.rs
Normal file
7
crates/apps/game-snake-poc-tauri/build.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
// file: crates/apps/game-snake-poc-tauri/build.rs
|
||||
// version: 1
|
||||
|
||||
fn main() {
|
||||
tauri_build::build();
|
||||
return;
|
||||
}
|
||||
12
crates/apps/game-snake-poc-tauri/capabilities/default.json
Normal file
12
crates/apps/game-snake-poc-tauri/capabilities/default.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "default",
|
||||
"description": "Default capability for the Snake Tauri Android POC",
|
||||
"windows": [
|
||||
"main"
|
||||
],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"tracing:default"
|
||||
]
|
||||
}
|
||||
58
crates/apps/game-snake-poc-tauri/frontend/css/main.css
Normal file
58
crates/apps/game-snake-poc-tauri/frontend/css/main.css
Normal file
@@ -0,0 +1,58 @@
|
||||
/* file: crates/apps/game-snake-poc-tauri/frontend/css/main.css */
|
||||
/* version: 1 */
|
||||
|
||||
:root {
|
||||
font-family: system-ui, sans-serif;
|
||||
color-scheme: dark;
|
||||
background: #101418;
|
||||
color: #f4f7f8;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
min-height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
padding: max(1.5rem, env(safe-area-inset-top)) max(1.5rem, env(safe-area-inset-right)) max(1.5rem, env(safe-area-inset-bottom))
|
||||
max(1.5rem, env(safe-area-inset-left));
|
||||
}
|
||||
|
||||
.bootstrap-panel {
|
||||
width: min(100%, 34rem);
|
||||
padding: 1.5rem;
|
||||
border: 1px solid currentColor;
|
||||
border-radius: 0.75rem;
|
||||
}
|
||||
|
||||
.eyebrow {
|
||||
margin: 0 0 0.5rem;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0 0 1rem;
|
||||
font-size: clamp(1.6rem, 7vw, 2.4rem);
|
||||
}
|
||||
|
||||
#runtime-status {
|
||||
margin: 0 0 0.75rem;
|
||||
}
|
||||
|
||||
#runtime-provenance {
|
||||
display: block;
|
||||
overflow-wrap: anywhere;
|
||||
font-family: ui-monospace, monospace;
|
||||
}
|
||||
|
||||
body[data-runtime-state="error"] #runtime-status {
|
||||
font-weight: 700;
|
||||
}
|
||||
17
crates/apps/game-snake-poc-tauri/frontend/main.html
Normal file
17
crates/apps/game-snake-poc-tauri/frontend/main.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!doctype html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
||||
<title>Snake POC Tauri</title>
|
||||
</head>
|
||||
<body>
|
||||
<main class="bootstrap-panel" aria-labelledby="runtime-title">
|
||||
<p class="eyebrow">games.sasedev</p>
|
||||
<h1 id="runtime-title">Snake — Tauri Android</h1>
|
||||
<p id="runtime-status">Initialisation du runtime…</p>
|
||||
<output id="runtime-provenance" aria-live="polite">provenance en attente</output>
|
||||
</main>
|
||||
<script type="module" src="/ts/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
20
crates/apps/game-snake-poc-tauri/frontend/ts/bridge.ts
Normal file
20
crates/apps/game-snake-poc-tauri/frontend/ts/bridge.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
// file: crates/apps/game-snake-poc-tauri/frontend/ts/bridge.ts
|
||||
// version: 1
|
||||
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
|
||||
export interface RuntimeDescriptor {
|
||||
deviceClass: string;
|
||||
executionModel: string;
|
||||
inputProfile: string;
|
||||
platformFamily: string;
|
||||
runtimeHost: string;
|
||||
}
|
||||
|
||||
export async function getRuntimeDescriptor(): Promise<RuntimeDescriptor> {
|
||||
return await invoke<RuntimeDescriptor>("get_runtime_descriptor");
|
||||
}
|
||||
|
||||
export async function reportFrontendReady(): Promise<void> {
|
||||
await invoke("frontend_ready");
|
||||
}
|
||||
16
crates/apps/game-snake-poc-tauri/frontend/ts/logging.ts
Normal file
16
crates/apps/game-snake-poc-tauri/frontend/ts/logging.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
// file: crates/apps/game-snake-poc-tauri/frontend/ts/logging.ts
|
||||
// version: 1
|
||||
|
||||
import { attachConsole, error, info } from "@fltsci/tauri-plugin-tracing";
|
||||
|
||||
export async function initializeFrontendTracing(): Promise<void> {
|
||||
await attachConsole();
|
||||
}
|
||||
|
||||
export function frontendInfo(message: string): void {
|
||||
info(message);
|
||||
}
|
||||
|
||||
export function frontendError(message: string): void {
|
||||
error(message);
|
||||
}
|
||||
56
crates/apps/game-snake-poc-tauri/frontend/ts/main.ts
Normal file
56
crates/apps/game-snake-poc-tauri/frontend/ts/main.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
// file: crates/apps/game-snake-poc-tauri/frontend/ts/main.ts
|
||||
// version: 1
|
||||
|
||||
import init, { SnakeWasmGame } from "@snake-wasm";
|
||||
import "../css/main.css";
|
||||
import { getRuntimeDescriptor, reportFrontendReady } from "./bridge";
|
||||
import { frontendError, frontendInfo, initializeFrontendTracing } from "./logging";
|
||||
|
||||
function requiredElement<T extends HTMLElement>(identifier: string): T {
|
||||
const element = document.getElementById(identifier);
|
||||
if (element === null) {
|
||||
throw new Error(`Élément frontend requis absent : ${identifier}`);
|
||||
}
|
||||
return element as T;
|
||||
}
|
||||
|
||||
async function bootstrap(): Promise<void> {
|
||||
await initializeFrontendTracing();
|
||||
frontendInfo("Snake Tauri frontend bootstrap started");
|
||||
const descriptor = await getRuntimeDescriptor();
|
||||
await init();
|
||||
const game = new SnakeWasmGame();
|
||||
const configured = game.configure_runtime_provenance(
|
||||
descriptor.platformFamily,
|
||||
descriptor.runtimeHost,
|
||||
descriptor.deviceClass,
|
||||
descriptor.inputProfile,
|
||||
);
|
||||
if (!configured) {
|
||||
game.free();
|
||||
throw new Error("La provenance Tauri Android n'a pas été acceptée par l'adapter Snake WASM.");
|
||||
}
|
||||
const status = requiredElement<HTMLParagraphElement>("runtime-status");
|
||||
const provenance = requiredElement<HTMLOutputElement>("runtime-provenance");
|
||||
status.textContent = "Runtime minimal initialisé. Le Canvas et les contrôles arrivent dans 0-pre.3.";
|
||||
provenance.value = [
|
||||
game.provenance_platform_family(),
|
||||
game.provenance_runtime_host(),
|
||||
game.provenance_execution_model(),
|
||||
game.provenance_device_class(),
|
||||
game.provenance_input_profile(),
|
||||
].join(" / ");
|
||||
window.addEventListener("pagehide", () => game.free(), { once: true });
|
||||
await reportFrontendReady();
|
||||
frontendInfo(`Snake Tauri frontend ready: ${provenance.value}`);
|
||||
}
|
||||
|
||||
void bootstrap().catch(reason => {
|
||||
const message = reason instanceof Error ? reason.message : String(reason);
|
||||
document.body.dataset.runtimeState = "error";
|
||||
const status = document.getElementById("runtime-status");
|
||||
if (status !== null) {
|
||||
status.textContent = `Échec d'initialisation : ${message}`;
|
||||
}
|
||||
frontendError(`Snake Tauri frontend bootstrap failed: ${message}`);
|
||||
});
|
||||
BIN
crates/apps/game-snake-poc-tauri/icons/icon.png
Normal file
BIN
crates/apps/game-snake-poc-tauri/icons/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 242 B |
21
crates/apps/game-snake-poc-tauri/package.json
Normal file
21
crates/apps/game-snake-poc-tauri/package.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "game-snake-poc-tauri",
|
||||
"private": true,
|
||||
"version": "0.1.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"wasm:dev": "cargo build -p game-snake-poc-wasm --target wasm32-unknown-unknown && wasm-bindgen ../../../../builds/sasedev-games/target/wasm32-unknown-unknown/debug/game_snake_poc_wasm.wasm --target web --out-dir ../../../../builds/sasedev-games/game-snake-poc-tauri/wasm --out-name game_snake_poc_wasm",
|
||||
"wasm:build": "cargo build -p game-snake-poc-wasm --release --target wasm32-unknown-unknown && wasm-bindgen ../../../../builds/sasedev-games/target/wasm32-unknown-unknown/release/game_snake_poc_wasm.wasm --target web --out-dir ../../../../builds/sasedev-games/game-snake-poc-tauri/wasm --out-name game_snake_poc_wasm",
|
||||
"dev": "npm run wasm:dev && vite",
|
||||
"build": "npm run wasm:build && tsc && vite build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fltsci/tauri-plugin-tracing": "^0.3",
|
||||
"@tauri-apps/api": "^2.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^26.1",
|
||||
"typescript": "^7.0",
|
||||
"vite": "^8.2"
|
||||
}
|
||||
}
|
||||
21
crates/apps/game-snake-poc-tauri/src/lib.rs
Normal file
21
crates/apps/game-snake-poc-tauri/src/lib.rs
Normal file
@@ -0,0 +1,21 @@
|
||||
// file: crates/apps/game-snake-poc-tauri/src/lib.rs
|
||||
// version: 1
|
||||
|
||||
//! Tauri Android application facade for the Snake WebAssembly POC.
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(unreachable_pub)]
|
||||
#![warn(missing_docs)]
|
||||
|
||||
mod runtime;
|
||||
mod tauri;
|
||||
|
||||
/// Runs the Snake Tauri application.
|
||||
pub use self::tauri::run;
|
||||
|
||||
/// Runtime descriptor exposed by the native Tauri bridge.
|
||||
pub(crate) use self::runtime::RuntimeDescriptorDto;
|
||||
/// Records that the Tauri frontend completed its minimal startup sequence.
|
||||
pub(crate) use self::runtime::record_frontend_ready;
|
||||
/// Returns the canonical runtime descriptor for the Android WebView host.
|
||||
pub(crate) use self::runtime::runtime_descriptor;
|
||||
20
crates/apps/game-snake-poc-tauri/src/main.rs
Normal file
20
crates/apps/game-snake-poc-tauri/src/main.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
// file: crates/apps/game-snake-poc-tauri/src/main.rs
|
||||
// version: 1
|
||||
|
||||
//! Binary entry point for host-side Snake Tauri checks.
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(unreachable_pub)]
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
fn main() -> std::process::ExitCode {
|
||||
let result = game_snake_poc_tauri_lib::run();
|
||||
return match result {
|
||||
std::result::Result::Ok(()) => std::process::ExitCode::SUCCESS,
|
||||
std::result::Result::Err(error) => {
|
||||
eprintln!("Snake Tauri application error: {error}");
|
||||
std::process::ExitCode::FAILURE
|
||||
},
|
||||
};
|
||||
}
|
||||
87
crates/apps/game-snake-poc-tauri/src/runtime.rs
Normal file
87
crates/apps/game-snake-poc-tauri/src/runtime.rs
Normal file
@@ -0,0 +1,87 @@
|
||||
// file: crates/apps/game-snake-poc-tauri/src/runtime.rs
|
||||
// version: 1
|
||||
|
||||
/// Stable runtime dimensions exposed to the Tauri frontend.
|
||||
#[derive(Clone, Debug, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct RuntimeDescriptorDto {
|
||||
device_class: String,
|
||||
execution_model: String,
|
||||
input_profile: String,
|
||||
platform_family: String,
|
||||
runtime_host: String,
|
||||
}
|
||||
|
||||
/// Returns the canonical runtime descriptor for the Android WebView host.
|
||||
pub(crate) fn runtime_descriptor() -> RuntimeDescriptorDto {
|
||||
let provenance = engine_v1_platform_api::RuntimeProvenance::new(
|
||||
engine_v1_platform_api::DeviceClass::Unknown,
|
||||
engine_v1_platform_api::ExecutionModel::Wasm,
|
||||
engine_v1_platform_api::InputProfile::Unknown,
|
||||
engine_v1_platform_api::PlatformFamily::Android,
|
||||
engine_v1_platform_api::RuntimeHost::TauriWebView,
|
||||
);
|
||||
return RuntimeDescriptorDto {
|
||||
device_class: device_class_label(provenance.device_class()).to_string(),
|
||||
execution_model: execution_model_label(provenance.execution_model()).to_string(),
|
||||
input_profile: input_profile_label(provenance.input_profile()).to_string(),
|
||||
platform_family: platform_family_label(provenance.platform_family()).to_string(),
|
||||
runtime_host: runtime_host_label(provenance.runtime_host()).to_string(),
|
||||
};
|
||||
}
|
||||
|
||||
/// Records that the Tauri frontend completed its minimal startup sequence.
|
||||
pub(crate) fn record_frontend_ready() {
|
||||
let descriptor = crate::runtime_descriptor();
|
||||
tracing::info!(
|
||||
target: "games::tauri::snake",
|
||||
action = "frontend_ready",
|
||||
platform_family = descriptor.platform_family,
|
||||
runtime_host = descriptor.runtime_host,
|
||||
execution_model = descriptor.execution_model,
|
||||
"Snake Tauri frontend ready"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
fn device_class_label(value: engine_v1_platform_api::DeviceClass) -> &'static str {
|
||||
return match value {
|
||||
engine_v1_platform_api::DeviceClass::Desktop => "desktop",
|
||||
engine_v1_platform_api::DeviceClass::Phone => "phone",
|
||||
engine_v1_platform_api::DeviceClass::Tablet => "tablet",
|
||||
engine_v1_platform_api::DeviceClass::Unknown => "unknown",
|
||||
};
|
||||
}
|
||||
|
||||
fn execution_model_label(value: engine_v1_platform_api::ExecutionModel) -> &'static str {
|
||||
return match value {
|
||||
engine_v1_platform_api::ExecutionModel::Native => "native",
|
||||
engine_v1_platform_api::ExecutionModel::Wasm => "wasm",
|
||||
};
|
||||
}
|
||||
|
||||
fn input_profile_label(value: engine_v1_platform_api::InputProfile) -> &'static str {
|
||||
return match value {
|
||||
engine_v1_platform_api::InputProfile::Gamepad => "gamepad",
|
||||
engine_v1_platform_api::InputProfile::KeyboardMouse => "keyboard-mouse",
|
||||
engine_v1_platform_api::InputProfile::Mixed => "mixed",
|
||||
engine_v1_platform_api::InputProfile::Touch => "touch",
|
||||
engine_v1_platform_api::InputProfile::Unknown => "unknown",
|
||||
};
|
||||
}
|
||||
|
||||
fn platform_family_label(value: engine_v1_platform_api::PlatformFamily) -> &'static str {
|
||||
return match value {
|
||||
engine_v1_platform_api::PlatformFamily::Android => "android",
|
||||
engine_v1_platform_api::PlatformFamily::Desktop => "desktop",
|
||||
engine_v1_platform_api::PlatformFamily::Web => "web",
|
||||
};
|
||||
}
|
||||
|
||||
fn runtime_host_label(value: engine_v1_platform_api::RuntimeHost) -> &'static str {
|
||||
return match value {
|
||||
engine_v1_platform_api::RuntimeHost::Browser => "browser",
|
||||
engine_v1_platform_api::RuntimeHost::Native => "native",
|
||||
engine_v1_platform_api::RuntimeHost::TauriWebView => "tauri-webview",
|
||||
};
|
||||
}
|
||||
65
crates/apps/game-snake-poc-tauri/src/tauri.rs
Normal file
65
crates/apps/game-snake-poc-tauri/src/tauri.rs
Normal file
@@ -0,0 +1,65 @@
|
||||
// file: crates/apps/game-snake-poc-tauri/src/tauri.rs
|
||||
// version: 1
|
||||
|
||||
//! Tauri runtime assembly and Web/Rust commands for the Snake Android POC.
|
||||
|
||||
#[tauri::command]
|
||||
fn get_runtime_descriptor() -> crate::RuntimeDescriptorDto {
|
||||
return crate::runtime_descriptor();
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn frontend_ready() {
|
||||
crate::record_frontend_ready();
|
||||
return;
|
||||
}
|
||||
|
||||
fn configure_plugins(builder: tauri::Builder<tauri::Wry>) -> tauri::Builder<tauri::Wry> {
|
||||
let tracing_plugin = tauri_plugin_tracing::Builder::new().build::<tauri::Wry>();
|
||||
return builder.plugin(tracing_plugin);
|
||||
}
|
||||
|
||||
#[allow(clippy::question_mark_used)] // Tauri generates the question-mark operator internally for command dispatch.
|
||||
fn configure_commands(builder: tauri::Builder<tauri::Wry>) -> tauri::Builder<tauri::Wry> {
|
||||
return builder.invoke_handler(tauri::generate_handler![get_runtime_descriptor, frontend_ready]);
|
||||
}
|
||||
|
||||
/// Runs the Snake Tauri application.
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() -> std::result::Result<(), String> {
|
||||
let logging_guard = game_logging_lib::init_console_tracing();
|
||||
let _logging_guard = match logging_guard {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
|
||||
};
|
||||
tracing::info!(
|
||||
target: "games::tauri::snake",
|
||||
action = "runtime_start",
|
||||
platform_family = "android",
|
||||
runtime_host = "tauri-webview",
|
||||
execution_model = "wasm",
|
||||
"Starting Snake Tauri Android runtime"
|
||||
);
|
||||
let builder = tauri::Builder::default();
|
||||
let builder = configure_plugins(builder);
|
||||
let builder = configure_commands(builder);
|
||||
return match builder.run(tauri::generate_context!()) {
|
||||
std::result::Result::Ok(()) => {
|
||||
tracing::info!(
|
||||
target: "games::tauri::snake",
|
||||
action = "runtime_stop",
|
||||
"Snake Tauri runtime stopped"
|
||||
);
|
||||
std::result::Result::Ok(())
|
||||
},
|
||||
std::result::Result::Err(error) => {
|
||||
tracing::error!(
|
||||
target: "games::tauri::snake",
|
||||
action = "runtime_error",
|
||||
error = error.to_string(),
|
||||
"Snake Tauri runtime failed"
|
||||
);
|
||||
std::result::Result::Err(error.to_string())
|
||||
},
|
||||
};
|
||||
}
|
||||
41
crates/apps/game-snake-poc-tauri/tauri.conf.json
Normal file
41
crates/apps/game-snake-poc-tauri/tauri.conf.json
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "Snake POC Tauri",
|
||||
"identifier": "com.sasedev.games.snake.tauri",
|
||||
"build": {
|
||||
"beforeDevCommand": {
|
||||
"script": "npm run dev",
|
||||
"cwd": "."
|
||||
},
|
||||
"devUrl": "http://localhost:1436",
|
||||
"beforeBuildCommand": {
|
||||
"script": "npm run build",
|
||||
"cwd": "."
|
||||
},
|
||||
"frontendDist": "../../../../builds/sasedev-games/game-snake-poc-tauri/dist"
|
||||
},
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"label": "main",
|
||||
"url": "main.html",
|
||||
"title": "Snake POC Tauri",
|
||||
"width": 405,
|
||||
"height": 720,
|
||||
"minWidth": 320,
|
||||
"minHeight": 480,
|
||||
"resizable": true,
|
||||
"center": true
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
"csp": null
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
"active": false,
|
||||
"icon": [
|
||||
"icons/icon.png"
|
||||
]
|
||||
}
|
||||
}
|
||||
36
crates/apps/game-snake-poc-tauri/tsconfig.json
Normal file
36
crates/apps/game-snake-poc-tauri/tsconfig.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": [
|
||||
"ES2022",
|
||||
"DOM",
|
||||
"DOM.Iterable"
|
||||
],
|
||||
"skipLibCheck": true,
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"types": [
|
||||
"vite/client",
|
||||
"node"
|
||||
],
|
||||
"paths": {
|
||||
"@snake-wasm": [
|
||||
"../../../../builds/sasedev-games/game-snake-poc-tauri/wasm/game_snake_poc_wasm.d.ts"
|
||||
]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"frontend",
|
||||
"vite.config.ts"
|
||||
]
|
||||
}
|
||||
72
crates/apps/game-snake-poc-tauri/vite.config.ts
Normal file
72
crates/apps/game-snake-poc-tauri/vite.config.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
// file: crates/apps/game-snake-poc-tauri/vite.config.ts
|
||||
// version: 1
|
||||
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { resolve } from "node:path";
|
||||
import { defineConfig, normalizePath } from "vite";
|
||||
|
||||
const appRoot = fileURLToPath(new URL(".", import.meta.url));
|
||||
const repositoryRoot = normalizePath(resolve(appRoot, "../../.."));
|
||||
const frontendRoot = normalizePath(resolve(appRoot, "frontend"));
|
||||
const externalBuildRoot = normalizePath(resolve(repositoryRoot, "../builds/sasedev-games/game-snake-poc-tauri"));
|
||||
const wasmRoot = normalizePath(resolve(externalBuildRoot, "wasm"));
|
||||
const wasmModule = normalizePath(resolve(wasmRoot, "game_snake_poc_wasm.js"));
|
||||
const frontendDist = normalizePath(resolve(externalBuildRoot, "dist"));
|
||||
const viteCacheDir = normalizePath(resolve(externalBuildRoot, "vite-cache"));
|
||||
const devHost = process.env.TAURI_DEV_HOST;
|
||||
|
||||
export default defineConfig({
|
||||
base: "./",
|
||||
cacheDir: viteCacheDir,
|
||||
clearScreen: false,
|
||||
root: frontendRoot,
|
||||
publicDir: false,
|
||||
input: {
|
||||
main: normalizePath(resolve(frontendRoot, "main.html")),
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
"@snake-wasm": wasmModule,
|
||||
},
|
||||
},
|
||||
build: {
|
||||
outDir: frontendDist,
|
||||
emptyOutDir: true,
|
||||
minify: true,
|
||||
sourcemap: false,
|
||||
cssCodeSplit: true,
|
||||
rolldownOptions: {
|
||||
output: {
|
||||
entryFileNames: "js/[name]-[hash].js",
|
||||
chunkFileNames: "js/chunks/[name]-[hash].js",
|
||||
assetFileNames: assetInfo => {
|
||||
const originalName = assetInfo.names[0] ?? "";
|
||||
const extension = originalName.substring(originalName.lastIndexOf(".") + 1).toLowerCase();
|
||||
if (extension === "css") {
|
||||
return "css/[name]-[hash][extname]";
|
||||
}
|
||||
if (extension === "wasm") {
|
||||
return "wasm/[name]-[hash][extname]";
|
||||
}
|
||||
return "otherassets/[name][extname]";
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
server: {
|
||||
port: 1436,
|
||||
strictPort: true,
|
||||
host: devHost || false,
|
||||
fs: {
|
||||
allow: [appRoot, repositoryRoot, externalBuildRoot],
|
||||
},
|
||||
ws: {
|
||||
protocol: "ws",
|
||||
host: devHost || "localhost",
|
||||
port: 1437,
|
||||
},
|
||||
watch: {
|
||||
ignored: ["**/src/**"],
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/apps/game-snake-poc-wasm/src/runtime.rs
|
||||
// version: 2
|
||||
// version: 3
|
||||
|
||||
const FIXED_STEP_MILLIS: u64 = 16;
|
||||
|
||||
@@ -31,8 +31,16 @@ impl SnakeWasmGame {
|
||||
};
|
||||
}
|
||||
|
||||
/// Updates browser-observed device and input dimensions while preserving Web/WASM/Browser provenance.
|
||||
pub fn configure_runtime_provenance(&mut self, device_class: &str, input_profile: &str) -> bool {
|
||||
/// Updates host-observed runtime provenance while preserving WebAssembly execution.
|
||||
pub fn configure_runtime_provenance(&mut self, platform_family: &str, runtime_host: &str, device_class: &str, input_profile: &str) -> bool {
|
||||
let platform_family = match parse_platform_family(platform_family) {
|
||||
Some(value) => value,
|
||||
None => return false,
|
||||
};
|
||||
let runtime_host = match parse_runtime_host(runtime_host) {
|
||||
Some(value) => value,
|
||||
None => return false,
|
||||
};
|
||||
let device_class = match parse_device_class(device_class) {
|
||||
Some(value) => value,
|
||||
None => return false,
|
||||
@@ -45,8 +53,8 @@ impl SnakeWasmGame {
|
||||
device_class,
|
||||
engine_v1_platform_api::ExecutionModel::Wasm,
|
||||
input_profile,
|
||||
engine_v1_platform_api::PlatformFamily::Web,
|
||||
engine_v1_platform_api::RuntimeHost::Browser,
|
||||
platform_family,
|
||||
runtime_host,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
@@ -236,6 +244,24 @@ impl SnakeWasmGame {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_platform_family(label: &str) -> Option<engine_v1_platform_api::PlatformFamily> {
|
||||
return match label {
|
||||
"android" => Some(engine_v1_platform_api::PlatformFamily::Android),
|
||||
"desktop" => Some(engine_v1_platform_api::PlatformFamily::Desktop),
|
||||
"web" => Some(engine_v1_platform_api::PlatformFamily::Web),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
|
||||
fn parse_runtime_host(label: &str) -> Option<engine_v1_platform_api::RuntimeHost> {
|
||||
return match label {
|
||||
"browser" => Some(engine_v1_platform_api::RuntimeHost::Browser),
|
||||
"native" => Some(engine_v1_platform_api::RuntimeHost::Native),
|
||||
"tauri-webview" => Some(engine_v1_platform_api::RuntimeHost::TauriWebView),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
|
||||
fn parse_device_class(label: &str) -> Option<engine_v1_platform_api::DeviceClass> {
|
||||
return match label {
|
||||
"desktop" => Some(engine_v1_platform_api::DeviceClass::Desktop),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/apps/game-snake-poc-wasm/unit_tests/runtime.rs
|
||||
// version: 2
|
||||
// version: 3
|
||||
|
||||
#[test]
|
||||
fn direction_is_queued_without_advancing_simulation() {
|
||||
@@ -34,7 +34,7 @@ fn browser_runtime_provenance_preserves_static_and_observed_dimensions() {
|
||||
assert_eq!(game.provenance_runtime_host(), "browser");
|
||||
assert_eq!(game.provenance_device_class(), "unknown");
|
||||
assert_eq!(game.provenance_input_profile(), "unknown");
|
||||
assert!(game.configure_runtime_provenance("phone", "touch"));
|
||||
assert!(game.configure_runtime_provenance("web", "browser", "phone", "touch"));
|
||||
assert_eq!(game.provenance_device_class(), "phone");
|
||||
assert_eq!(game.provenance_input_profile(), "touch");
|
||||
assert_eq!(game.provenance_platform_family(), "web");
|
||||
@@ -45,8 +45,19 @@ fn browser_runtime_provenance_preserves_static_and_observed_dimensions() {
|
||||
#[test]
|
||||
fn invalid_runtime_provenance_labels_are_rejected_without_mutation() {
|
||||
let mut game = crate::SnakeWasmGame::new();
|
||||
assert!(game.configure_runtime_provenance("desktop", "keyboard-mouse"));
|
||||
assert!(!game.configure_runtime_provenance("console", "telepathy"));
|
||||
assert!(game.configure_runtime_provenance("web", "browser", "desktop", "keyboard-mouse"));
|
||||
assert!(!game.configure_runtime_provenance("console", "spaceship", "console", "telepathy"));
|
||||
assert_eq!(game.provenance_device_class(), "desktop");
|
||||
assert_eq!(game.provenance_input_profile(), "keyboard-mouse");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tauri_android_runtime_provenance_is_supported_by_the_shared_adapter() {
|
||||
let mut game = crate::SnakeWasmGame::new();
|
||||
assert!(game.configure_runtime_provenance("android", "tauri-webview", "phone", "touch"));
|
||||
assert_eq!(game.provenance_platform_family(), "android");
|
||||
assert_eq!(game.provenance_runtime_host(), "tauri-webview");
|
||||
assert_eq!(game.provenance_execution_model(), "wasm");
|
||||
assert_eq!(game.provenance_device_class(), "phone");
|
||||
assert_eq!(game.provenance_input_profile(), "touch");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/engines/engine-v1-platform-api/src/environment.rs
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
/// Broad physical device class relevant to interaction and score provenance.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
@@ -56,7 +56,7 @@ pub enum RuntimeHost {
|
||||
Browser,
|
||||
/// Native process managed directly by the operating system.
|
||||
Native,
|
||||
/// Tauri desktop WebView host.
|
||||
/// Tauri WebView host on a supported native platform.
|
||||
TauriWebView,
|
||||
}
|
||||
|
||||
|
||||
161
deltas/0.3.1/0-pre.2.md
Normal file
161
deltas/0.3.1/0-pre.2.md
Normal file
@@ -0,0 +1,161 @@
|
||||
<!-- file: deltas/0.3.1/0-pre.2.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta 0.3.1-0-pre.2
|
||||
|
||||
## Base requise
|
||||
|
||||
`0.3.1-0-pre.1`, validée par l'utilisateur le 2026-09-20.
|
||||
|
||||
## Objectif
|
||||
|
||||
Créer le host Tauri Android minimal de Snake sans dupliquer le gameplay, sans créer un second adapter WASM et sans réintroduire de build orchestré par Python.
|
||||
|
||||
Cette tranche vise le premier démarrage Android et la validation des frontières Tauri/WASM/tracing. Le Canvas, les contrôles, les assets et le lifecycle complet restent réservés à `0-pre.3` et `0-pre.4` conformément au plan vivant.
|
||||
|
||||
## Audit Tauri KSP direct
|
||||
|
||||
L'archive fournie `khadhroony-solana-project-v0.3.15.zip` a été extraite et les six crates `ksp-app-*-desk` ont été vérifiées directement. Elles possèdent toutes les frontières structurantes retenues pour games.sasedev :
|
||||
|
||||
```text
|
||||
src/lib.rs
|
||||
src/tauri.rs
|
||||
package.json
|
||||
vite.config.ts
|
||||
tauri.conf.json
|
||||
capabilities/default.json
|
||||
tauri-plugin-tracing côté Rust
|
||||
@fltsci/tauri-plugin-tracing côté frontend
|
||||
```
|
||||
|
||||
Le nouveau host Snake reprend cette organisation, avec un scope volontairement plus petit. Le Tauri Reflex historique reste seulement une référence de compatibilité : son orchestration Python n'est pas reproduite.
|
||||
|
||||
## Changements Rust et WASM
|
||||
|
||||
- passage du workspace à `0.3.1-0-pre.2` ;
|
||||
- ajout de `game-snake-poc-tauri` au workspace ;
|
||||
- création de la façade `src/lib.rs`, de l'assemblage `src/tauri.rs` et du module propriétaire `src/runtime.rs` ;
|
||||
- ajout du point d'entrée mobile `#[cfg_attr(mobile, tauri::mobile_entry_point)]` ;
|
||||
- initialisation du subscriber partagé via `game-logging-lib` avant le premier événement Rust ;
|
||||
- installation de `tauri-plugin-tracing` ;
|
||||
- généralisation minimale de `game-snake-poc-wasm::configure_runtime_provenance` afin que le même adapter accepte explicitement la famille et le host observés ;
|
||||
- conservation de `ExecutionModel::Wasm` dans l'adapter ;
|
||||
- adaptation du Web direct pour fournir explicitement `web / browser` ;
|
||||
- ajout d'un test ciblé `android / tauri-webview / wasm` ;
|
||||
- généralisation de la rustdoc `RuntimeHost::TauriWebView`, qui n'est plus décrite comme Desktop uniquement.
|
||||
|
||||
## Frontend et build Tauri
|
||||
|
||||
La nouvelle app contient :
|
||||
|
||||
- `package.json`, `tsconfig.json` et `vite.config.ts` ;
|
||||
- un frontend minimal sous `frontend/` ;
|
||||
- un bridge IPC vers le descriptor runtime Rust ;
|
||||
- le chargement des bindings produits depuis `game-snake-poc-wasm` ;
|
||||
- le tracing frontend via `@fltsci/tauri-plugin-tracing` ;
|
||||
- `tauri.conf.json` et `capabilities/default.json` ;
|
||||
- un icon POC cohérent avec le host Tauri historique ;
|
||||
- `README.md` et `USAGE.md` initiaux.
|
||||
|
||||
Les hooks Tauri exécutent eux-mêmes le build Cargo WASM, `wasm-bindgen` puis Vite. Les outputs restent sous `../builds/sasedev-games/`. Aucun script Python n'est impliqué dans ce chemin.
|
||||
|
||||
`cargo tauri android init` reste une opération locale de la gate : son répertoire `gen/` est généré et ignoré, donc il n'est pas distribué dans le delta.
|
||||
|
||||
## NDK et JDK
|
||||
|
||||
La machine de validation possède plusieurs NDK sous `$ANDROID_HOME/ndk/`; `NDK_HOME` n'est donc pas imposé globalement par le dépôt. Si la CLI Tauri exige une valeur explicite pendant `android init/dev`, utiliser ponctuellement le chemin exact de la version NDK concernée.
|
||||
|
||||
`JAVA_HOME` reste également facultatif tant que `java` est résolu correctement par la CLI dans l'environnement courant. Les deux variables deviennent des outils de diagnostic local, pas des invariants source du projet.
|
||||
|
||||
## Audit de distribution
|
||||
|
||||
`audit_distribution_layout.py` couvre désormais le host Tauri Snake minimal : fichiers requis, hooks Tauri, outputs WASM externes au dépôt, point d'entrée mobile, bridge tracing, provenance Android/TauriWebView et interdiction de Python/`console.*` dans le chemin touché.
|
||||
|
||||
## Fichiers ajoutés
|
||||
|
||||
```text
|
||||
crates/apps/game-snake-poc-tauri/Cargo.toml
|
||||
crates/apps/game-snake-poc-tauri/README.md
|
||||
crates/apps/game-snake-poc-tauri/USAGE.md
|
||||
crates/apps/game-snake-poc-tauri/build.rs
|
||||
crates/apps/game-snake-poc-tauri/capabilities/default.json
|
||||
crates/apps/game-snake-poc-tauri/frontend/css/main.css
|
||||
crates/apps/game-snake-poc-tauri/frontend/main.html
|
||||
crates/apps/game-snake-poc-tauri/frontend/ts/bridge.ts
|
||||
crates/apps/game-snake-poc-tauri/frontend/ts/logging.ts
|
||||
crates/apps/game-snake-poc-tauri/frontend/ts/main.ts
|
||||
crates/apps/game-snake-poc-tauri/icons/icon.png
|
||||
crates/apps/game-snake-poc-tauri/package.json
|
||||
crates/apps/game-snake-poc-tauri/src/lib.rs
|
||||
crates/apps/game-snake-poc-tauri/src/main.rs
|
||||
crates/apps/game-snake-poc-tauri/src/runtime.rs
|
||||
crates/apps/game-snake-poc-tauri/src/tauri.rs
|
||||
crates/apps/game-snake-poc-tauri/tauri.conf.json
|
||||
crates/apps/game-snake-poc-tauri/tsconfig.json
|
||||
crates/apps/game-snake-poc-tauri/vite.config.ts
|
||||
history/0.3.1/0-pre.1.md
|
||||
```
|
||||
|
||||
## Fichiers modifiés
|
||||
|
||||
```text
|
||||
Cargo.toml
|
||||
README.md
|
||||
Web/game-snake-poc/frontend/ts/provenance.ts
|
||||
crates/apps/game-snake-poc-wasm/src/runtime.rs
|
||||
crates/apps/game-snake-poc-wasm/unit_tests/runtime.rs
|
||||
crates/engines/engine-v1-platform-api/src/environment.rs
|
||||
docs/plans/002-V0_3_1_TAURI_ANDROID_SNAKE_PLAN.md
|
||||
scripts/audit_distribution_layout.py
|
||||
```
|
||||
|
||||
## Validation générateur
|
||||
|
||||
Les audits statiques applicables sont exécutés avant livraison. Aucun `cargo`, `npm`, `wasm-bindgen`, Gradle, Tauri Android ou smoke n'est déclaré validé par le générateur.
|
||||
|
||||
## Gate utilisateur
|
||||
|
||||
Appliquer d'abord la gate workspace :
|
||||
|
||||
```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
|
||||
|
||||
cargo fmt --all
|
||||
cargo fmt --all -- --check
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
cargo test -p game-snake-poc-wasm --all-targets --all-features
|
||||
```
|
||||
|
||||
Comme l'API de provenance partagée est utilisée par le Web direct, reconstruire ses bindings et son frontend :
|
||||
|
||||
```bash
|
||||
cargo build -p game-snake-poc-wasm --target wasm32-unknown-unknown
|
||||
wasm-bindgen ../builds/sasedev-games/target/wasm32-unknown-unknown/debug/game_snake_poc_wasm.wasm --target web --out-dir ../builds/sasedev-games/game-snake-poc-web/wasm --out-name game_snake_poc_wasm
|
||||
(cd Web/game-snake-poc && npm install && npm run build)
|
||||
```
|
||||
|
||||
Puis initialiser et lancer le nouveau host par Tauri, sans exécuter ses scripts npm de build directement :
|
||||
|
||||
```bash
|
||||
(cd crates/apps/game-snake-poc-tauri && npm install)
|
||||
(cd crates/apps/game-snake-poc-tauri && cargo tauri android init)
|
||||
(cd crates/apps/game-snake-poc-tauri && cargo tauri android dev)
|
||||
```
|
||||
|
||||
Critères du smoke `android dev` :
|
||||
|
||||
- l'app démarre sur l'appareil/AVD choisi ;
|
||||
- le frontend affiche `android / tauri-webview / wasm / unknown / unknown` ;
|
||||
- le bridge Rust répond ;
|
||||
- le frontend charge `game-snake-poc-wasm` ;
|
||||
- les logs Rust et frontend atteignent le pipeline tracing/logcat ;
|
||||
- aucune erreur runtime bloquante n'est visible.
|
||||
|
||||
`cargo tauri android build` reste reporté au jalon de packaging prévu par le plan.
|
||||
|
||||
## Suite après validation
|
||||
|
||||
Si la gate est propre, passer automatiquement à `0.3.1-0-pre.3` pour intégrer le Canvas Snake, les inputs et les assets dans le WebView Tauri. Tout défaut source de `0-pre.2` produit d'abord un `0-pre.2.fix.N` borné.
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/plans/002-V0_3_1_TAURI_ANDROID_SNAKE_PLAN.md -->
|
||||
<!-- version: 1 -->
|
||||
<!-- version: 2 -->
|
||||
|
||||
# Plan v0.3.1 — second host Snake Tauri Android
|
||||
|
||||
@@ -55,7 +55,7 @@ Audit complet de l'archive stable, règles, baseline Web/WASM, Tauri Reflex, ré
|
||||
|
||||
Livraison : étude `024`, présent plan, correction des règles Tauri Android, clarification `PlatformFamily`, index documentaires et ouverture de la version technique `0.3.1-0-pre.1`.
|
||||
|
||||
Aucun scaffold Tauri Snake n'est créé.
|
||||
Aucun scaffold Tauri Snake n'est créé. Tranche validée par la gate utilisateur du 2026-09-20.
|
||||
|
||||
### `0-pre.2` — host Tauri Android minimal
|
||||
|
||||
@@ -73,7 +73,9 @@ Créer `game-snake-poc-tauri` avec :
|
||||
|
||||
La tranche vise un premier démarrage Tauri Android minimal, pas encore toute la finition input/lifecycle.
|
||||
|
||||
Gate utilisateur : audits, Cargo workspace strict, build WASM nécessaire, `cargo tauri android dev` sur un AVD ou appareil disponible. `cargo tauri android build` reste reporté aux phases finales sauf besoin diagnostique.
|
||||
État candidat livré : crate `game-snake-poc-tauri`, bridge Rust/Tauri, hooks WASM/Vite sans Python, frontend minimal, tracing frontend/Rust et provenance partagée `Android / TauriWebView / Wasm`. L'initialisation générée `cargo tauri android init` reste volontairement locale et fait partie de la gate utilisateur, car `gen/` n'est pas un artefact source distribué.
|
||||
|
||||
Gate utilisateur : audits, Cargo workspace strict, test ciblé de l'adapter WASM, non-régression du build Web direct, `cargo tauri android init` puis `cargo tauri android dev` sur un AVD ou appareil disponible. `cargo tauri android build` reste reporté aux phases finales sauf besoin diagnostique.
|
||||
|
||||
### `0-pre.3` — shell Snake, Canvas, input et assets
|
||||
|
||||
@@ -158,6 +160,8 @@ emulator -list-avds
|
||||
|
||||
L'absence d'un outil ne doit pas être masquée. Elle devient un prérequis concret de `0-pre.2` ou motive un fix borné de `0-pre.1`.
|
||||
|
||||
La gate `0-pre.1` validée le 2026-09-20 a confirmé Rust `1.94.1`, Tauri CLI `2.11.3`, Node `24.21.0`, npm `11.19.0`, wasm-bindgen `0.2.128`, OpenJDK `25.0.4.1`, `ANDROID_HOME=/home/sinus/DEV/AndroidSDK`, un appareil ARM64 réel et trois AVD disponibles. `JAVA_HOME` et `NDK_HOME` sont vides dans cet environnement mais ne sont pas traités comme prérequis globaux du dépôt : Java est résolu depuis le `PATH`, et les NDK side-by-side restent sous `$ANDROID_HOME/ndk/<version>`. Si la CLI Tauri exige explicitement `NDK_HOME` pour une opération donnée, la validation utilisera une variable ponctuelle visant une version NDK exacte plutôt qu'un réglage global ambigu.
|
||||
|
||||
## Critères de fermeture de 0.3.1
|
||||
|
||||
La version peut entrer en RC lorsque :
|
||||
|
||||
45
history/0.3.1/0-pre.1.md
Normal file
45
history/0.3.1/0-pre.1.md
Normal file
@@ -0,0 +1,45 @@
|
||||
<!-- file: history/0.3.1/0-pre.1.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Historique 0.3.1-0-pre.1
|
||||
|
||||
## Statut
|
||||
|
||||
Cadrage `0.3.1-0-pre.1` validé par l'utilisateur le 2026-09-20. Les audits, le formatage, le check workspace et Clippy strict passent ; aucun `.fix.N` n'est requis avant l'ouverture de `0-pre.2`.
|
||||
|
||||
## Gate utilisateur
|
||||
|
||||
La gate fournie dans le delta a été exécutée avec succès :
|
||||
|
||||
```text
|
||||
General Rust rule audit: clean
|
||||
Rust export completeness audit: 0 candidate(s)
|
||||
games.sasedev workspace audit: clean
|
||||
Markdown table audit: clean (5 table(s), 210 file(s))
|
||||
Distribution layout audit: clean (31 required path(s), 1 forbidden path(s) absent)
|
||||
cargo fmt --all: clean
|
||||
cargo fmt --all -- --check: clean
|
||||
cargo check --workspace: clean
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings: clean
|
||||
```
|
||||
|
||||
## Environnement confirmé
|
||||
|
||||
L'inventaire de transmission vers `0-pre.2` confirme :
|
||||
|
||||
- Rust/Cargo `1.94.1` ;
|
||||
- Tauri CLI `2.11.3` ;
|
||||
- cibles Rust `aarch64-linux-android`, `x86_64-linux-android`, `wasm32-unknown-unknown` et `x86_64-unknown-linux-gnu` ;
|
||||
- Node `24.21.0`, npm `11.19.0`, wasm-bindgen `0.2.128` ;
|
||||
- OpenJDK Temurin `25.0.4.1` disponible via `java` ;
|
||||
- `ANDROID_HOME=/home/sinus/DEV/AndroidSDK` ;
|
||||
- `JAVA_HOME` et `NDK_HOME` non définis globalement ;
|
||||
- Android Debug Bridge `37.0.1` ;
|
||||
- un Samsung SM-G965F réel connecté ;
|
||||
- AVD `Medium_Phone`, `Medium_Phone_API_36.0` et `sasedev_games_api36` disponibles.
|
||||
|
||||
Le projet ne transforme pas l'absence de `NDK_HOME` en défaut : l'installation locale conserve plusieurs NDK sous `$ANDROID_HOME/ndk/<version>`. Si une commande Tauri demande cette variable, elle sera définie ponctuellement vers une version exacte. De même, `JAVA_HOME` ne devient nécessaire que si la CLI ne résout pas le JDK disponible depuis l'environnement.
|
||||
|
||||
## Transmission vers 0-pre.2
|
||||
|
||||
L'archive complète `khadhroony-solana-project-v0.3.15.zip` est désormais disponible directement pour la tranche suivante. L'audit de ses six applications `ksp-app-*-desk` confirme le modèle retenu : façade `lib.rs`, assemblage `tauri.rs`, frontend Vite dans la crate, `tauri.conf.json`, capability dédiée et dépendances tracing Rust/TypeScript.
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# file: scripts/audit_distribution_layout.py
|
||||
# version: 7
|
||||
# version: 8
|
||||
|
||||
"""Audit the static distribution layout expected by supported POCs."""
|
||||
|
||||
@@ -30,6 +30,17 @@ REQUIRED_PATHS = (
|
||||
"crates/apps/game-reflex-poc-tauri/frontend/ts/main.ts",
|
||||
"crates/apps/game-reflex-poc-wasm/Cargo.toml",
|
||||
"crates/apps/game-snake-poc-wasm/Cargo.toml",
|
||||
"crates/apps/game-snake-poc-tauri/Cargo.toml",
|
||||
"crates/apps/game-snake-poc-tauri/README.md",
|
||||
"crates/apps/game-snake-poc-tauri/USAGE.md",
|
||||
"crates/apps/game-snake-poc-tauri/package.json",
|
||||
"crates/apps/game-snake-poc-tauri/tsconfig.json",
|
||||
"crates/apps/game-snake-poc-tauri/vite.config.ts",
|
||||
"crates/apps/game-snake-poc-tauri/tauri.conf.json",
|
||||
"crates/apps/game-snake-poc-tauri/capabilities/default.json",
|
||||
"crates/apps/game-snake-poc-tauri/icons/icon.png",
|
||||
"crates/apps/game-snake-poc-tauri/frontend/main.html",
|
||||
"crates/apps/game-snake-poc-tauri/frontend/ts/main.ts",
|
||||
"Web/game-snake-poc/package.json",
|
||||
"Web/game-snake-poc/tsconfig.json",
|
||||
"Web/game-snake-poc/vite.config.ts",
|
||||
@@ -136,6 +147,56 @@ def audit_snake_web_integration(root: pathlib.Path) -> list[str]:
|
||||
violations.append(message)
|
||||
return violations
|
||||
|
||||
def audit_snake_tauri_android_integration(root: pathlib.Path) -> list[str]:
|
||||
"""Validate the minimal Snake Tauri Android host boundary."""
|
||||
|
||||
violations: list[str] = []
|
||||
cargo_path = root / "crates/apps/game-snake-poc-tauri/Cargo.toml"
|
||||
package_path = root / "crates/apps/game-snake-poc-tauri/package.json"
|
||||
tauri_path = root / "crates/apps/game-snake-poc-tauri/tauri.conf.json"
|
||||
tauri_rust_path = root / "crates/apps/game-snake-poc-tauri/src/tauri.rs"
|
||||
frontend_path = root / "crates/apps/game-snake-poc-tauri/frontend/ts/main.ts"
|
||||
logging_path = root / "crates/apps/game-snake-poc-tauri/frontend/ts/logging.ts"
|
||||
wasm_runtime_path = root / "crates/apps/game-snake-poc-wasm/src/runtime.rs"
|
||||
paths = (cargo_path, package_path, tauri_path, tauri_rust_path, frontend_path, logging_path, wasm_runtime_path)
|
||||
if not all(path.exists() for path in paths):
|
||||
return violations
|
||||
|
||||
cargo = cargo_path.read_text(encoding="utf-8")
|
||||
package = package_path.read_text(encoding="utf-8")
|
||||
tauri = tauri_path.read_text(encoding="utf-8")
|
||||
tauri_rust = tauri_rust_path.read_text(encoding="utf-8")
|
||||
frontend = frontend_path.read_text(encoding="utf-8")
|
||||
logging = logging_path.read_text(encoding="utf-8")
|
||||
wasm_runtime = wasm_runtime_path.read_text(encoding="utf-8")
|
||||
required_fragments = (
|
||||
(cargo, 'game-logging-lib = { path = "../../common/game-logging-lib" }', "DIST-LAYOUT-021: Snake Tauri host must use shared Rust logging"),
|
||||
(cargo, 'tauri-plugin-tracing.workspace = true', "DIST-LAYOUT-022: Snake Tauri host must enable the tracing plugin"),
|
||||
(package, '"wasm:dev": "cargo build -p game-snake-poc-wasm', "DIST-LAYOUT-023: Snake Tauri dev hook must build the shared Snake WASM adapter"),
|
||||
(package, 'wasm-bindgen ../../../../builds/sasedev-games/', "DIST-LAYOUT-024: Snake Tauri bindings must be generated outside the repository"),
|
||||
(tauri, '"script": "npm run dev"', "DIST-LAYOUT-025: Tauri must own the frontend development hook"),
|
||||
(tauri, '"script": "npm run build"', "DIST-LAYOUT-026: Tauri must own the frontend production hook"),
|
||||
(tauri_rust, '#[cfg_attr(mobile, tauri::mobile_entry_point)]', "DIST-LAYOUT-027: Snake Tauri run entry point must support Tauri mobile"),
|
||||
(tauri_rust, 'tauri_plugin_tracing::Builder::new()', "DIST-LAYOUT-028: Snake Tauri runtime must install the tracing plugin"),
|
||||
(frontend, 'configure_runtime_provenance(', "DIST-LAYOUT-029: Snake Tauri frontend must configure provenance through the shared adapter"),
|
||||
(logging, '@fltsci/tauri-plugin-tracing', "DIST-LAYOUT-030: Snake Tauri frontend logs must use the tracing bridge"),
|
||||
(wasm_runtime, '"tauri-webview" => Some(engine_v1_platform_api::RuntimeHost::TauriWebView)', "DIST-LAYOUT-031: Snake WASM adapter must accept the Tauri WebView host"),
|
||||
(wasm_runtime, '"android" => Some(engine_v1_platform_api::PlatformFamily::Android)', "DIST-LAYOUT-032: Snake WASM adapter must accept Android provenance"),
|
||||
)
|
||||
for content, fragment, message in required_fragments:
|
||||
if fragment not in content:
|
||||
violations.append(message)
|
||||
forbidden_fragments = (
|
||||
(package, "python", "DIST-LAYOUT-033: Snake Tauri build hooks must not use Python"),
|
||||
(tauri, "python", "DIST-LAYOUT-034: Snake Tauri configuration must not use Python build orchestration"),
|
||||
(frontend, "console.", "DIST-LAYOUT-035: Snake Tauri application frontend must not log directly through console.*"),
|
||||
)
|
||||
for content, fragment, message in forbidden_fragments:
|
||||
if fragment in content.lower():
|
||||
violations.append(message)
|
||||
return violations
|
||||
|
||||
|
||||
def main() -> int:
|
||||
"""Validate that every static distribution boundary exists."""
|
||||
|
||||
@@ -154,6 +215,7 @@ def main() -> int:
|
||||
forbidden_present.append(relative)
|
||||
contract_violations.extend(audit_snake_web_shell(root))
|
||||
contract_violations.extend(audit_snake_web_integration(root))
|
||||
contract_violations.extend(audit_snake_tauri_android_integration(root))
|
||||
if missing:
|
||||
for relative in missing:
|
||||
print(f"DIST-LAYOUT-001: missing required path: {relative}", file=sys.stderr)
|
||||
|
||||
Reference in New Issue
Block a user