Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 778da67e22 | |||
| a9620ef84c | |||
| 45c31d4721 | |||
| 54121215b4 | |||
| fca477eb23 | |||
| ff1ec09d68 | |||
| 3e1153eb8c | |||
| 7f0635ec9d | |||
| 86b8af3b61 | |||
| 023825b89b | |||
| f433e99a12 | |||
| c4b68b8a60 | |||
| c7ccf57723 | |||
| a6a59222d6 | |||
| 6f37fea9ed | |||
| d16648c34c | |||
| 54079accb5 |
23
CHANGELOG.md
23
CHANGELOG.md
@@ -1,8 +1,29 @@
|
||||
<!-- file: CHANGELOG.md -->
|
||||
<!-- version: 12 -->
|
||||
<!-- version: 14 -->
|
||||
|
||||
# Changelog
|
||||
|
||||
## 0.3.0 — 2026-09-20
|
||||
|
||||
- publication stable du premier POC Snake Web direct, construit autour du gameplay Rust partagé, d'un adapter WASM dédié et d'un host navigateur Vite/TypeScript ;
|
||||
- validation du shell Bootstrap 5/Bootswatch + SimpleBar, du Canvas au ratio logique `12 × 20`, des contrôles clavier/pointer, du lifecycle navigateur, des assets et de la provenance runtime ;
|
||||
- validation de la non-régression Desktop SDL3 et des builds release Desktop et Web/WASM ;
|
||||
- promotion mécanique de `0.3.0-3-rc.1` après gate workspace complète, 34 tests réussis et absence de défaut nécessitant un correctif RC ;
|
||||
- préparation de `0.3.1` pour le second host Snake Tauri Android, sans ouvrir ce scope dans la release `0.3.0`.
|
||||
|
||||
Les détails des phases `pre`, `beta`, `rc` et de leurs correctifs restent dans `deltas/0.3.0/` et `history/0.3.0/`.
|
||||
|
||||
## 0.3.0-3-rc.1 — 2026-09-20
|
||||
|
||||
- gel fonctionnel du premier POC Snake Web direct après validation beta et consolidation documentaire ;
|
||||
- gameplay Snake conservé dans `game-snake-poc`, avec adapter `game-snake-poc-wasm` dédié et host navigateur Vite/TypeScript séparé ;
|
||||
- shell Web responsive fondé sur Bootstrap 5/Bootswatch, SimpleBar et Canvas au ratio logique du jeu, avec clavier et contrôles pointer/tactiles ;
|
||||
- lifecycle navigateur fixed-step sans rattrapage massif, resize `devicePixelRatio`, assets `common/` + `game/`, logging frontend structuré et provenance `Web / Browser / Wasm` ;
|
||||
- runner Desktop SDL3 maintenu comme témoin de non-régression et builds release Desktop/Web déjà exercés pendant la beta ;
|
||||
- prompt `0.3.1` préparé pour le second host Snake Tauri Android, avec workflow de session, commandes et validations consolidés.
|
||||
|
||||
La RC n'ouvre aucun nouveau scope. Les détails des phases `pre`, `beta` et de leurs correctifs restent dans `deltas/0.3.0/` et `history/0.3.0/`.
|
||||
|
||||
## 0.2.0 — conception modulaire, POC et Uroburas
|
||||
|
||||
- Gouvernance documentaire renforcée : catégories `ideas/studies/architecture/rules`, immutabilité des deltas, conventions de statuts et workflow de session/version.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# file: Cargo.toml
|
||||
# version: 57
|
||||
# version: 69
|
||||
|
||||
[workspace]
|
||||
resolver = "3"
|
||||
@@ -16,10 +16,11 @@ members = [
|
||||
"crates/apps/game-android-entrypoint",
|
||||
"crates/apps/game-reflex-poc-tauri",
|
||||
"crates/apps/game-reflex-poc-wasm",
|
||||
"crates/apps/game-snake-poc-wasm",
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
repository = "https://git.sasedev.com/Sasedev/games"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: README.md -->
|
||||
<!-- version: 25 -->
|
||||
<!-- version: 40 -->
|
||||
|
||||
# games.sasedev
|
||||
|
||||
@@ -14,6 +14,7 @@ Workspace expérimental puis productif pour des jeux multiplateformes principale
|
||||
- assets hors des crates sous `assets/` ;
|
||||
- `assets/common/` pour les ressources mutualisées et un répertoire par jeu pour les ressources spécifiques ;
|
||||
- frontend Android sous `Android/`, en Java, avec une partie commune et une partie spécifique par jeu ;
|
||||
- hosts navigateur directs sous `Web/`, avec frontend Vite/TypeScript séparé des adapters Rust/WASM ;
|
||||
- monétisation optionnelle et spécifique à chaque plateforme/distribution ;
|
||||
- runner Desktop natif SDL3 par défaut, avec variante Tauri uniquement si un besoin futur la justifie ;
|
||||
- documentation sous `docs/` ;
|
||||
@@ -23,9 +24,9 @@ Workspace expérimental puis productif pour des jeux multiplateformes principale
|
||||
|
||||
## Baseline
|
||||
|
||||
Version stable de référence : `0.1.0`.
|
||||
Version stable de référence : `0.3.0`.
|
||||
|
||||
Version candidate en cours de conception : `0.2.0`.
|
||||
Version suivante planifiée : `0.3.1` (non démarrée).
|
||||
|
||||
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.
|
||||
|
||||
|
||||
30
ROADMAP.md
30
ROADMAP.md
@@ -1,5 +1,5 @@
|
||||
<!-- file: ROADMAP.md -->
|
||||
<!-- version: 19 -->
|
||||
<!-- version: 21 -->
|
||||
|
||||
# Roadmap
|
||||
|
||||
@@ -26,11 +26,31 @@ Le détail historique des prereleases `0.1.0-*` reste dans `deltas/0.1.0/` et `h
|
||||
|
||||
- (x) `0.2.0` — fixer la gouvernance documentaire, la nomenclature et le cycle de maturation des idées et décisions.
|
||||
- (x) `0.2.0` — inventorier et réserver les capabilities déjà justifiées sans les implémenter prématurément.
|
||||
- ( ) `0.2.0` — définir les couches, les dépendances autorisées et la frontière entre kernel, capability, plateforme, provider, système de jeu et service.
|
||||
- ( ) `0.2.0` — établir la matrice plateformes et les archétypes de jeux utilisés pour challenger l'architecture.
|
||||
- ( ) `0.2.0` — définir le modèle de composition statique, le manifest produit/jeu et l'architecture cible des crates.
|
||||
- ( ) `0.2.0` — définir la trajectoire d'implémentation progressive des versions suivantes seulement après revue de la conception.
|
||||
- (x) `0.2.0` — définir les couches, les dépendances autorisées et la frontière entre kernel, capability, plateforme, provider, système de jeu et service.
|
||||
- (x) `0.2.0` — établir la matrice plateformes et les archétypes de jeux utilisés pour challenger l'architecture.
|
||||
- (x) `0.2.0` — retenir la composition Rust statique comme direction de référence.
|
||||
- (d) `0.2.0` — figer un manifest produit/jeu et l'architecture physique définitive des crates → target TBD après observation des POC `0.3.x`.
|
||||
- (x) `0.2.0` — définir la trajectoire d'implémentation progressive `0.3.x` POC puis `0.4.x` Uroburas.
|
||||
- (x) `0.2.0` — consolider les études acceptées en architecture/règles durables, notamment ownership, réseau, Uroburas et POC, puis fermer les points encore candidats.
|
||||
- (x) `0.2.0` — formaliser la stratégie réseau : Actix Web pour le Web/API, asset delivery auto-hébergé H2/H3, WebSocket baseline et WebTransport/QUIC candidat.
|
||||
- (x) `0.2.0` — préparer une trajectoire `0.3.x` dédiée aux POC plateforme/réseau avec Snake comme jeu-sonde.
|
||||
- (x) `0.2.0` — préparer la trajectoire `0.4.x` Uroburas Mode 1 et le prompt de session associé après gel de la conception.
|
||||
|
||||
## 0.3.0 — Baseline Snake + premier POC Web direct
|
||||
|
||||
- (x) `0.3.0` — nettoyer la baseline Snake sans introduire de logique Uroburas et maintenir le runner Desktop SDL3 fonctionnel.
|
||||
- (x) `0.3.0` — produire une adaptation WASM dédiée à Snake sans déplacer le gameplay hors de `game-snake-poc`.
|
||||
- (x) `0.3.0` — réaliser un POC navigateur direct Snake couvrant clavier, boutons directionnels tactiles, resize, lifecycle, logging, assets et provenance runtime.
|
||||
- (x) `0.3.0` — utiliser uniquement Cargo, `wasm-bindgen` et Vite/npm pour le chemin de build Web ; aucun script Python ne pilote ce build.
|
||||
- (x) `0.3.0` — documenter les duplications observées et conserver les adapters Web/WASM spécifiques tant qu’un second consommateur ne justifie pas une extraction commune.
|
||||
|
||||
## Série 0.3.x — trajectoire actuelle après 0.3.0
|
||||
|
||||
- ( ) `0.3.1` — second host Snake : Tauri Android, en réutilisant la baseline Web/WASM validée et en remplaçant toute orchestration Python du chemin touché.
|
||||
- ( ) `0.3.2` — Tauri Desktop + Snake et factorisation WebView uniquement lorsque deux consommateurs réels justifient l'extraction.
|
||||
- ( ) `0.3.3` — Android SDL natif multi-ABI avec Cargo/Gradle natifs, sans script Python de build.
|
||||
- ( ) `0.3.4` — API de transport realtime + WebSocket/tokio-tungstenite baseline, sans serveur Uroburas Mode 3.
|
||||
- ( ) `0.3.5` — POC WebTransport/QUIC sur le même protocole, avec comparaison mesurée et fallback WebSocket.
|
||||
- ( ) `0.3.6` — consolidation des POC plateforme/réseau et préparation de la baseline `0.4.x`.
|
||||
|
||||
La numérotation `0.3.1+` reste révisable à partir des résultats réels ; les lignes ci-dessus décrivent le planning actuel, pas une obligation de créer des versions artificielles.
|
||||
|
||||
7
RULES.md
7
RULES.md
@@ -1,5 +1,5 @@
|
||||
<!-- file: RULES.md -->
|
||||
<!-- version: 4 -->
|
||||
<!-- version: 5 -->
|
||||
|
||||
# Index normatif games.sasedev
|
||||
|
||||
@@ -17,8 +17,9 @@ Les règles détaillées sont maintenues sous `docs/rules/` et sont cumulatives
|
||||
6. [`docs/rules/VERSION_WORKFLOW.md`](docs/rules/VERSION_WORKFLOW.md) — SemVer, niveaux de maturité, fixes, deltas et livraisons ;
|
||||
7. [`docs/rules/RULES_COMMANDS.md`](docs/rules/RULES_COMMANDS.md) — politique d’exécution des commandes Cargo, audits, runners, Android, Web et Git ;
|
||||
8. [`docs/rules/RULES_VALIDATION_MATRIX.md`](docs/rules/RULES_VALIDATION_MATRIX.md) — matrice évolutive des commandes, dépendances de validation et politiques de nettoyage ;
|
||||
9. [`docs/rules/RULES_SESSION_PLANNING.md`](docs/rules/RULES_SESSION_PLANNING.md) — cadrage `pre.1`, dimensionnement des sessions et contrat des prompts de reprise ;
|
||||
10. [`docs/rules/RULES_SERVER_HOSTING.md`](docs/rules/RULES_SERVER_HOSTING.md) — contraintes durables de portabilité et préférence d'auto-hébergement.
|
||||
9. [`docs/rules/RULES_SESSION_PLANNING.md`](docs/rules/RULES_SESSION_PLANNING.md) — cadrage `pre.1`, dimensionnement des sessions et cycle de transmission ;
|
||||
10. [`docs/rules/PROMPT_STRUCTURE.md`](docs/rules/PROMPT_STRUCTURE.md) — structure minimale des prompts de reprise et rappels de workflow obligatoires ;
|
||||
11. [`docs/rules/RULES_SERVER_HOSTING.md`](docs/rules/RULES_SERVER_HOSTING.md) — contraintes durables de portabilité et préférence d'auto-hébergement.
|
||||
|
||||
## Hiérarchie
|
||||
|
||||
|
||||
118
Web/game-snake-poc/frontend/main.html
Normal file
118
Web/game-snake-poc/frontend/main.html
Normal file
@@ -0,0 +1,118 @@
|
||||
<!-- file: Web/game-snake-poc/frontend/main.html -->
|
||||
<!-- version: 4 -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="width=device-width, initial-scale=1.0, viewport-fit=cover" name="viewport">
|
||||
<meta content="#593196" name="theme-color">
|
||||
<link rel="stylesheet" href="sass/main.scss">
|
||||
<title>Snake POC — Web direct</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header class="app-header">
|
||||
<nav class="navbar h-100 py-0 bg-light text-dark">
|
||||
<div class="container-fluid px-3 px-md-4 flex-nowrap">
|
||||
<div class="navbar-brand d-flex align-items-center me-3 flex-nowrap min-w-0">
|
||||
<span class="app-logo d-inline-flex align-items-center justify-content-center text-primary" aria-hidden="true">
|
||||
<i class="fa-solid fa-gamepad"></i>
|
||||
</span>
|
||||
<span class="ps-2 fs-4 fw-semibold text-primary text-nowrap">Snake POC</span>
|
||||
<span class="mx-2 fs-5 text-body-secondary d-none d-sm-inline" aria-hidden="true">—</span>
|
||||
<span class="fs-5 text-body text-nowrap d-none d-sm-inline">Web direct</span>
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-2 ms-auto">
|
||||
<span class="badge text-bg-light border text-dark d-none d-md-inline">Rust/WASM</span>
|
||||
<span id="runtime-status" class="badge text-bg-secondary" role="status" aria-live="polite">Initialisation…</span>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main class="app-main container-fluid p-0">
|
||||
<div class="row g-0 h-100 flex-nowrap">
|
||||
<section class="col app-content app-scrollable h-100" data-simplebar>
|
||||
<div class="container-fluid px-3 px-md-4 py-3 py-md-4">
|
||||
<div class="card app-shell-card mx-auto shadow-sm border-0">
|
||||
<div class="card-body p-3 p-md-4">
|
||||
<div class="d-flex align-items-start justify-content-between gap-3 flex-wrap mb-3">
|
||||
<div>
|
||||
<h1 class="h3 mb-1">Snake</h1>
|
||||
<p class="text-body-secondary mb-0">Gameplay Rust portable, adapter WebAssembly et rendu Canvas piloté par TypeScript.</p>
|
||||
</div>
|
||||
<div class="d-flex gap-2 flex-wrap" aria-label="État de la partie">
|
||||
<output id="score" class="badge text-bg-primary">Score : 0</output>
|
||||
<output id="length" class="badge text-bg-info">Longueur : 0</output>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-3 g-lg-4 align-items-start">
|
||||
<div class="col-12 col-lg-8">
|
||||
<div class="card border-primary-subtle shadow-sm">
|
||||
<div class="card-body p-2 p-sm-3">
|
||||
<div class="game-stage">
|
||||
<canvas id="game" width="640" height="640" tabindex="0" aria-label="Zone de jeu Snake"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-4">
|
||||
<div class="card shadow-sm app-controls-card">
|
||||
<div class="card-header d-flex align-items-center justify-content-between gap-2">
|
||||
<span class="fw-semibold"><i class="fa-solid fa-keyboard me-2" aria-hidden="true"></i>Contrôles</span>
|
||||
<span class="small text-body-secondary">clavier / tactile</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="small text-body-secondary">Utilisez les flèches, WASD, ZQSD ou les boutons directionnels.</p>
|
||||
<div class="direction-pad mx-auto" aria-label="Contrôles directionnels tactiles">
|
||||
<button class="btn btn-outline-primary direction-up" type="button" data-direction="up" aria-label="Haut">
|
||||
<i class="fa-solid fa-arrow-up" aria-hidden="true"></i>
|
||||
</button>
|
||||
<button class="btn btn-outline-primary direction-left" type="button" data-direction="left" aria-label="Gauche">
|
||||
<i class="fa-solid fa-arrow-left" aria-hidden="true"></i>
|
||||
</button>
|
||||
<button class="btn btn-outline-primary direction-down" type="button" data-direction="down" aria-label="Bas">
|
||||
<i class="fa-solid fa-arrow-down" aria-hidden="true"></i>
|
||||
</button>
|
||||
<button class="btn btn-outline-primary direction-right" type="button" data-direction="right" aria-label="Droite">
|
||||
<i class="fa-solid fa-arrow-right" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
<dl class="runtime-details small border-top pt-3 mt-3 mb-0">
|
||||
<div class="d-flex justify-content-between gap-3">
|
||||
<dt class="text-body-secondary fw-normal">Provenance</dt>
|
||||
<dd class="mb-2 text-end"><output id="runtime-provenance">web / browser / wasm / unknown / unknown</output></dd>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between gap-3">
|
||||
<dt class="text-body-secondary fw-normal">Assets</dt>
|
||||
<dd class="mb-0 text-end"><output id="asset-status">chargement…</output></dd>
|
||||
</div>
|
||||
</dl>
|
||||
<div class="alert alert-info small mt-3 mb-0" role="note">
|
||||
Les entrées ne font pas avancer la simulation : elles sont consommées au prochain <code>tick()</code> WASM.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p id="startup-error" class="alert alert-danger mt-3 mb-0" role="alert" hidden></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="app-footer bg-dark text-light">
|
||||
<div class="container h-100 d-flex align-items-center justify-content-center">
|
||||
<small>© 2026 SASEDEV</small>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script type="module" src="ts/main.ts" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
165
Web/game-snake-poc/frontend/sass/_app.scss
Normal file
165
Web/game-snake-poc/frontend/sass/_app.scss
Normal file
@@ -0,0 +1,165 @@
|
||||
// file: Web/game-snake-poc/frontend/sass/_app.scss
|
||||
// version: 4
|
||||
|
||||
$app-header-height: 72px;
|
||||
$app-footer-height: 42px;
|
||||
|
||||
html,
|
||||
body {
|
||||
width: 100%;
|
||||
min-width: 320px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
background: $gray-100;
|
||||
overscroll-behavior: none;
|
||||
}
|
||||
|
||||
.min-w-0 {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.app-header {
|
||||
position: fixed;
|
||||
inset: 0 0 auto;
|
||||
height: $app-header-height;
|
||||
z-index: 1020;
|
||||
border-bottom: 2px solid rgba($primary, 0.3);
|
||||
}
|
||||
|
||||
.app-footer {
|
||||
position: fixed;
|
||||
inset: auto 0 0;
|
||||
height: $app-footer-height;
|
||||
z-index: 1020;
|
||||
border-top: 2px solid rgba($primary, 0.3);
|
||||
}
|
||||
|
||||
.app-main {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: calc(100vh - $app-header-height - $app-footer-height);
|
||||
margin-top: $app-header-height;
|
||||
margin-bottom: $app-footer-height;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.app-main > .row {
|
||||
flex-wrap: nowrap;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.app-scrollable {
|
||||
height: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.app-content {
|
||||
min-width: 0;
|
||||
height: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.app-logo {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
|
||||
.app-shell-card {
|
||||
width: 100%;
|
||||
max-width: 1180px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.game-stage {
|
||||
width: 100%;
|
||||
max-width: 520px;
|
||||
margin-inline: auto;
|
||||
aspect-ratio: 3 / 5;
|
||||
overflow: hidden;
|
||||
background: $black;
|
||||
border: 1px solid rgba($primary, 0.35);
|
||||
}
|
||||
|
||||
#game {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
touch-action: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#game:focus-visible {
|
||||
box-shadow: inset 0 0 0 3px rgba($primary, 0.85);
|
||||
}
|
||||
|
||||
.app-controls-card {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.runtime-details dd {
|
||||
min-width: 0;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.direction-pad {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(64px, 88px));
|
||||
grid-template-rows: repeat(2, minmax(56px, 72px));
|
||||
gap: 0.5rem;
|
||||
justify-content: center;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.direction-pad .btn {
|
||||
touch-action: manipulation;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.direction-up {
|
||||
grid-column: 2;
|
||||
grid-row: 1;
|
||||
}
|
||||
|
||||
.direction-left {
|
||||
grid-column: 1;
|
||||
grid-row: 2;
|
||||
}
|
||||
|
||||
.direction-down {
|
||||
grid-column: 2;
|
||||
grid-row: 2;
|
||||
}
|
||||
|
||||
.direction-right {
|
||||
grid-column: 3;
|
||||
grid-row: 2;
|
||||
}
|
||||
|
||||
@media (max-width: 575.98px) {
|
||||
$mobile-header-height: 64px;
|
||||
|
||||
.app-header {
|
||||
height: $mobile-header-height;
|
||||
}
|
||||
|
||||
.app-main {
|
||||
height: calc(100vh - $mobile-header-height - $app-footer-height);
|
||||
margin-top: $mobile-header-height;
|
||||
}
|
||||
|
||||
.app-logo {
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
.direction-pad {
|
||||
width: 100%;
|
||||
grid-template-columns: repeat(3, minmax(72px, 1fr));
|
||||
}
|
||||
}
|
||||
160
Web/game-snake-poc/frontend/sass/_bootswatch.scss
Normal file
160
Web/game-snake-poc/frontend/sass/_bootswatch.scss
Normal file
@@ -0,0 +1,160 @@
|
||||
// file: Web/game-snake-poc/frontend/sass/_bootswatch.scss
|
||||
// version: 1
|
||||
|
||||
// Pulse 5.3.8
|
||||
// Bootswatch
|
||||
|
||||
|
||||
// Variables
|
||||
|
||||
// Buttons
|
||||
|
||||
.btn {
|
||||
|
||||
&:focus,
|
||||
&:active,
|
||||
&:active:focus,
|
||||
&.active:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&-secondary {
|
||||
color: $gray-900;
|
||||
background-color: $white;
|
||||
border-color: #ccc;
|
||||
|
||||
&:hover {
|
||||
color: $gray-900;
|
||||
background-color: $gray-300;
|
||||
border-color: $gray-500;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
color: tint-color($gray-900, 5%);
|
||||
background-color: $white;
|
||||
border-color: tint-color(#ccc, 5%);
|
||||
}
|
||||
}
|
||||
|
||||
&-warning {
|
||||
color: $white;
|
||||
}
|
||||
|
||||
&-primary:focus {
|
||||
box-shadow: 0 0 5px tint-color($primary, 10%);
|
||||
}
|
||||
|
||||
&-secondary:focus {
|
||||
box-shadow: 0 0 5px $gray-400;
|
||||
}
|
||||
|
||||
&-success:focus {
|
||||
box-shadow: 0 0 5px tint-color($success, 10%);
|
||||
}
|
||||
|
||||
&-info:focus {
|
||||
box-shadow: 0 0 5px tint-color($info, 10%);
|
||||
}
|
||||
|
||||
&-warning:focus {
|
||||
box-shadow: 0 0 5px tint-color($warning, 10%);
|
||||
}
|
||||
|
||||
&-danger:focus {
|
||||
box-shadow: 0 0 5px tint-color($danger, 10%);
|
||||
}
|
||||
|
||||
&.disabled:focus {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
// Tables
|
||||
|
||||
.table .thead-dark th {
|
||||
background-color: $secondary;
|
||||
border-color: $table-border-color;
|
||||
}
|
||||
|
||||
.table-primary,
|
||||
.table-secondary,
|
||||
.table-success,
|
||||
.table-warning,
|
||||
.table-danger,
|
||||
.table-info,
|
||||
.table-light {
|
||||
--#{$prefix}table-color: #{$body-color};
|
||||
}
|
||||
|
||||
// Forms
|
||||
|
||||
.form-control:focus {
|
||||
box-shadow: 0 0 5px rgba(100, 65, 164, .4);
|
||||
}
|
||||
|
||||
// Navs
|
||||
|
||||
.nav-tabs {
|
||||
|
||||
.nav-link,
|
||||
.nav-link.active {
|
||||
border-width: 0 0 1px;
|
||||
}
|
||||
|
||||
.nav-link:hover,
|
||||
.nav-link.active,
|
||||
.nav-link.active:hover,
|
||||
.nav-link.active:focus {
|
||||
border-bottom: 1px solid $primary;
|
||||
}
|
||||
|
||||
.nav-item+.nav-item {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
&-item.active {
|
||||
color: $gray-700;
|
||||
}
|
||||
}
|
||||
|
||||
// Indicators
|
||||
|
||||
.badge {
|
||||
&.bg-light {
|
||||
color: $dark;
|
||||
}
|
||||
}
|
||||
|
||||
// Progress bars
|
||||
|
||||
.progress {
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
// Containers
|
||||
|
||||
.list-group {
|
||||
&-item {
|
||||
color: rgba(255, 255, 255, .8);
|
||||
|
||||
&.active,
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: $white;
|
||||
}
|
||||
|
||||
&.active {
|
||||
font-weight: 700;
|
||||
|
||||
&:hover {
|
||||
background-color: $list-group-hover-bg;
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled:hover {
|
||||
color: $list-group-disabled-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
19
Web/game-snake-poc/frontend/sass/_fontawesome.scss
Normal file
19
Web/game-snake-poc/frontend/sass/_fontawesome.scss
Normal file
@@ -0,0 +1,19 @@
|
||||
// file: Web/game-snake-poc/frontend/sass/_fontawesome.scss
|
||||
// version: 1
|
||||
|
||||
//@use '@fortawesome/fontawesome-free/scss/variables' with (
|
||||
// // customizing $font-path - make sure it points to where your webfonts are stored in your project
|
||||
// $font-path: '../webfonts',
|
||||
//);
|
||||
@use '@fortawesome/fontawesome-free/scss/variables' with (
|
||||
// use fonts from @fortawesome/fontawesome-free
|
||||
$font-path: '@fortawesome/fontawesome-free/webfonts',
|
||||
);
|
||||
// load Font Awesome core
|
||||
@use '@fortawesome/fontawesome-free/scss/fontawesome';
|
||||
|
||||
// load and make available Font Awesome helpers (mixins, functions, and variables)
|
||||
@use '@fortawesome/fontawesome-free/scss/fa' as fa;
|
||||
@use '@fortawesome/fontawesome-free/scss/brands' as fa-brands;
|
||||
@use '@fortawesome/fontawesome-free/scss/regular' as fa-regular;
|
||||
@use '@fortawesome/fontawesome-free/scss/solid' as fa-solid;
|
||||
248
Web/game-snake-poc/frontend/sass/_simplebar.scss
Normal file
248
Web/game-snake-poc/frontend/sass/_simplebar.scss
Normal file
@@ -0,0 +1,248 @@
|
||||
// file: Web/game-snake-poc/frontend/sass/_simplebar.scss
|
||||
// version: 1
|
||||
|
||||
/* Rtl support */
|
||||
[data-simplebar] {
|
||||
position: relative;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
align-content: flex-start;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.simplebar-wrapper {
|
||||
overflow: hidden;
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
max-width: inherit;
|
||||
max-height: inherit;
|
||||
}
|
||||
|
||||
.simplebar-mask {
|
||||
direction: inherit;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: auto !important;
|
||||
height: auto !important;
|
||||
// z-index: 0;
|
||||
inset: 0;
|
||||
}
|
||||
|
||||
.simplebar-offset {
|
||||
direction: inherit !important;
|
||||
box-sizing: inherit !important;
|
||||
resize: none !important;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
inset: 0;
|
||||
}
|
||||
|
||||
.simplebar-content-wrapper {
|
||||
direction: inherit;
|
||||
box-sizing: border-box !important;
|
||||
position: relative;
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
overflow: auto;
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.simplebar-hide-scrollbar {
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
position: fixed;
|
||||
left: 0;
|
||||
visibility: hidden;
|
||||
overflow-y: scroll;
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
}
|
||||
|
||||
.simplebar-content {
|
||||
&:before {
|
||||
content: ' ';
|
||||
display: table;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: ' ';
|
||||
display: table;
|
||||
}
|
||||
}
|
||||
|
||||
.simplebar-placeholder {
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.simplebar-height-auto-observer-wrapper {
|
||||
box-sizing: inherit !important;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
max-width: 1px;
|
||||
position: relative;
|
||||
float: left;
|
||||
max-height: 1px;
|
||||
overflow: hidden;
|
||||
// z-index: -1;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
pointer-events: none;
|
||||
flex-grow: inherit;
|
||||
flex-shrink: 0;
|
||||
flex-basis: 0;
|
||||
}
|
||||
|
||||
.simplebar-height-auto-observer {
|
||||
box-sizing: inherit;
|
||||
display: block;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 1000%;
|
||||
width: 1000%;
|
||||
min-height: 1px;
|
||||
min-width: 1px;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
// z-index: -1;
|
||||
}
|
||||
|
||||
.simplebar-track {
|
||||
// z-index: 1;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
pointer-events: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
[data-simplebar].simplebar-dragging {
|
||||
pointer-events: none;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
|
||||
.simplebar-content {
|
||||
pointer-events: none;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.simplebar-track {
|
||||
pointer-events: all;
|
||||
}
|
||||
}
|
||||
|
||||
.simplebar-scrollbar {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
min-height: 10px;
|
||||
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
background: black;
|
||||
border-radius: 7px;
|
||||
left: 2px;
|
||||
right: 2px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s 0.5s linear;
|
||||
top: 2px;
|
||||
bottom: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.simplebar-scrollbar.simplebar-visible {
|
||||
&:before {
|
||||
opacity: 0.5;
|
||||
transition-delay: 0s;
|
||||
transition-duration: 0s;
|
||||
}
|
||||
}
|
||||
|
||||
.simplebar-track.simplebar-vertical {
|
||||
top: 0;
|
||||
width: 11px;
|
||||
}
|
||||
|
||||
.simplebar-track.simplebar-horizontal {
|
||||
left: 0;
|
||||
height: 11px;
|
||||
|
||||
.simplebar-scrollbar {
|
||||
right: auto;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
min-height: 0;
|
||||
min-width: 10px;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
[data-simplebar-direction='rtl'] {
|
||||
.simplebar-track.simplebar-vertical {
|
||||
right: auto;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.simplebar-dummy-scrollbar-size {
|
||||
direction: rtl;
|
||||
position: fixed;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
height: 500px;
|
||||
width: 500px;
|
||||
overflow-y: hidden;
|
||||
overflow-x: scroll;
|
||||
-ms-overflow-style: scrollbar !important;
|
||||
|
||||
>div {
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
margin: 10px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.simplebar-hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
95
Web/game-snake-poc/frontend/sass/_variables.scss
Normal file
95
Web/game-snake-poc/frontend/sass/_variables.scss
Normal file
@@ -0,0 +1,95 @@
|
||||
// file: Web/game-snake-poc/frontend/sass/_variables.scss
|
||||
// version: 1
|
||||
|
||||
// Pulse 5.3.8
|
||||
// Bootswatch
|
||||
|
||||
$theme: "pulse" !default;
|
||||
|
||||
//
|
||||
// Color system
|
||||
//
|
||||
|
||||
$white: #fff !default;
|
||||
$gray-100: #fafafa !default;
|
||||
$gray-200: #f9f8fc !default;
|
||||
$gray-300: #ededed !default;
|
||||
$gray-400: #cbc8d0 !default;
|
||||
$gray-500: #adb5bd !default;
|
||||
$gray-600: #868e96 !default;
|
||||
$gray-700: #444 !default;
|
||||
$gray-800: #343a40 !default;
|
||||
$gray-900: #17141f !default;
|
||||
$black: #000 !default;
|
||||
|
||||
$blue: #007bff !default;
|
||||
$indigo: #6610f2 !default;
|
||||
$purple: #593196 !default;
|
||||
$pink: #e83e8c !default;
|
||||
$red: #fc3939 !default;
|
||||
$orange: #fd7e14 !default;
|
||||
$yellow: #efa31d !default;
|
||||
$green: #13b955 !default;
|
||||
$teal: #20c997 !default;
|
||||
$cyan: #009cdc !default;
|
||||
|
||||
$primary: $purple !default;
|
||||
$secondary: #a991d4 !default;
|
||||
$success: $green !default;
|
||||
$info: $cyan !default;
|
||||
$warning: $yellow !default;
|
||||
$danger: $red !default;
|
||||
$light: $gray-200 !default;
|
||||
$dark: $gray-900 !default;
|
||||
|
||||
$min-contrast-ratio: 2.1 !default;
|
||||
|
||||
// Options
|
||||
|
||||
$enable-rounded: false !default;
|
||||
|
||||
// Body
|
||||
|
||||
$body-color: $gray-700 !default;
|
||||
|
||||
// Links
|
||||
|
||||
$link-hover-color: $primary !default;
|
||||
|
||||
// Tables
|
||||
|
||||
$table-color: initial !default;
|
||||
|
||||
$table-border-color: rgba(0, 0, 0, .05) !default;
|
||||
|
||||
// Forms
|
||||
|
||||
$input-focus-border-color: $primary !default;
|
||||
|
||||
// Dropdowns
|
||||
|
||||
$dropdown-link-hover-color: $white !default;
|
||||
$dropdown-link-hover-bg: $primary !default;
|
||||
|
||||
// Navs
|
||||
|
||||
$nav-tabs-border-color: $gray-300 !default;
|
||||
$nav-tabs-link-hover-border-color: $primary !default;
|
||||
|
||||
// Navbar
|
||||
|
||||
$navbar-padding-y: 1.2rem !default;
|
||||
|
||||
// Progress bars
|
||||
|
||||
$progress-bg: $gray-300 !default;
|
||||
$progress-bar-bg: $primary !default;
|
||||
|
||||
// List group
|
||||
|
||||
$list-group-bg: $gray-900 !default;
|
||||
$list-group-border-color: transparent !default;
|
||||
$list-group-hover-bg: lighten($list-group-bg, 10%) !default;
|
||||
$list-group-active-color: $white !default;
|
||||
$list-group-active-bg: $list-group-bg !default;
|
||||
$list-group-disabled-color: lighten($list-group-bg, 30%) !default;
|
||||
10
Web/game-snake-poc/frontend/sass/main.scss
Normal file
10
Web/game-snake-poc/frontend/sass/main.scss
Normal file
@@ -0,0 +1,10 @@
|
||||
// file: Web/game-snake-poc/frontend/sass/main.scss
|
||||
// version: 2
|
||||
|
||||
@import "bootstrap/scss/functions";
|
||||
@import "variables";
|
||||
@import "fontawesome";
|
||||
@import "simplebar";
|
||||
@import "bootstrap/scss/bootstrap";
|
||||
@import "bootswatch";
|
||||
@import "app";
|
||||
54
Web/game-snake-poc/frontend/ts/assets.ts
Normal file
54
Web/game-snake-poc/frontend/ts/assets.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
// file: Web/game-snake-poc/frontend/ts/assets.ts
|
||||
// version: 1
|
||||
|
||||
export interface SnakeWebAssets {
|
||||
engineGeneration: number;
|
||||
game: string;
|
||||
gameKind: string;
|
||||
}
|
||||
|
||||
interface CommonRuntimeAsset {
|
||||
schema: number;
|
||||
scope: string;
|
||||
engine_generation: number;
|
||||
}
|
||||
|
||||
interface GameRuntimeAsset {
|
||||
schema: number;
|
||||
game: string;
|
||||
kind: string;
|
||||
}
|
||||
|
||||
async function fetchJson<T>(relativePath: string): Promise<T> {
|
||||
const response = await fetch(new URL(relativePath, document.baseURI));
|
||||
if (!response.ok) {
|
||||
throw new Error(`Asset runtime indisponible (${response.status}) : ${relativePath}`);
|
||||
}
|
||||
return (await response.json()) as T;
|
||||
}
|
||||
|
||||
function validateCommonRuntime(asset: CommonRuntimeAsset): void {
|
||||
if (asset.schema !== 1 || asset.scope !== "common" || asset.engine_generation !== 1) {
|
||||
throw new Error("Asset common://data/runtime.json invalide pour le POC Web Snake.");
|
||||
}
|
||||
}
|
||||
|
||||
function validateGameRuntime(asset: GameRuntimeAsset): void {
|
||||
if (asset.schema !== 1 || asset.game !== "game-snake-poc" || asset.kind !== "snake") {
|
||||
throw new Error("Asset game://data/game.json invalide pour le POC Web Snake.");
|
||||
}
|
||||
}
|
||||
|
||||
export async function loadSnakeWebAssets(): Promise<SnakeWebAssets> {
|
||||
const [commonRuntime, gameRuntime] = await Promise.all([
|
||||
fetchJson<CommonRuntimeAsset>("./common/data/runtime.json"),
|
||||
fetchJson<GameRuntimeAsset>("./game/data/game.json"),
|
||||
]);
|
||||
validateCommonRuntime(commonRuntime);
|
||||
validateGameRuntime(gameRuntime);
|
||||
return {
|
||||
engineGeneration: commonRuntime.engine_generation,
|
||||
game: gameRuntime.game,
|
||||
gameKind: gameRuntime.kind,
|
||||
};
|
||||
}
|
||||
179
Web/game-snake-poc/frontend/ts/game.ts
Normal file
179
Web/game-snake-poc/frontend/ts/game.ts
Normal file
@@ -0,0 +1,179 @@
|
||||
// file: Web/game-snake-poc/frontend/ts/game.ts
|
||||
// version: 3
|
||||
|
||||
import init, { SnakeWasmGame } from "@snake-wasm";
|
||||
import { webDebug, webInfo } from "./logging";
|
||||
import { BrowserRuntimeProvenance, type SnakeInputSource } from "./provenance";
|
||||
|
||||
const FRAME_MILLIS = 16;
|
||||
const MAX_FRAME_ELAPSED_MILLIS = 250;
|
||||
|
||||
export type SnakeDirection = "left" | "right" | "up" | "down";
|
||||
|
||||
export interface SnakeWebSession {
|
||||
queueDirection(direction: SnakeDirection, source: SnakeInputSource): void;
|
||||
pause(): void;
|
||||
resume(): void;
|
||||
renderNow(): void;
|
||||
refreshDeviceClass(): void;
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
function color(red: number, green: number, blue: number): string {
|
||||
return `rgb(${red} ${green} ${blue})`;
|
||||
}
|
||||
|
||||
function resizeCanvas(canvas: HTMLCanvasElement): void {
|
||||
const ratio = window.devicePixelRatio || 1;
|
||||
const width = Math.max(1, Math.floor(canvas.clientWidth * ratio));
|
||||
const height = Math.max(1, Math.floor(canvas.clientHeight * ratio));
|
||||
if (canvas.width !== width || canvas.height !== height) {
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
}
|
||||
}
|
||||
|
||||
function render(
|
||||
game: SnakeWasmGame,
|
||||
canvas: HTMLCanvasElement,
|
||||
context: CanvasRenderingContext2D,
|
||||
score: HTMLOutputElement,
|
||||
length: HTMLOutputElement,
|
||||
): void {
|
||||
resizeCanvas(canvas);
|
||||
context.fillStyle = color(game.background_red(), game.background_green(), game.background_blue());
|
||||
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||
const count = game.rectangle_count();
|
||||
for (let index = 0; index < count; index += 1) {
|
||||
context.fillStyle = color(game.rectangle_red(index), game.rectangle_green(index), game.rectangle_blue(index));
|
||||
context.fillRect(
|
||||
game.rectangle_x(index) * canvas.width,
|
||||
game.rectangle_y(index) * canvas.height,
|
||||
game.rectangle_width(index) * canvas.width,
|
||||
game.rectangle_height(index) * canvas.height,
|
||||
);
|
||||
}
|
||||
score.value = `Score : ${game.score()}`;
|
||||
length.value = `Longueur : ${game.length()}`;
|
||||
}
|
||||
|
||||
function queueDirection(game: SnakeWasmGame, direction: SnakeDirection): void {
|
||||
switch (direction) {
|
||||
case "left":
|
||||
game.left();
|
||||
return;
|
||||
case "right":
|
||||
game.right();
|
||||
return;
|
||||
case "up":
|
||||
game.up();
|
||||
return;
|
||||
case "down":
|
||||
game.down();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
export async function startGame(
|
||||
canvas: HTMLCanvasElement,
|
||||
score: HTMLOutputElement,
|
||||
length: HTMLOutputElement,
|
||||
provenanceOutput: HTMLOutputElement,
|
||||
): Promise<SnakeWebSession> {
|
||||
await init();
|
||||
webInfo("snake-web-runtime", "wasm_initialized");
|
||||
const context = canvas.getContext("2d");
|
||||
if (context === null) {
|
||||
throw new Error("Le contexte Canvas 2D est indisponible.");
|
||||
}
|
||||
const renderingContext: CanvasRenderingContext2D = context;
|
||||
const game = new SnakeWasmGame();
|
||||
const provenance = new BrowserRuntimeProvenance(game, provenanceOutput);
|
||||
let previous = performance.now();
|
||||
let accumulator = 0;
|
||||
let animationFrame: number | null = null;
|
||||
let running = false;
|
||||
let disposed = false;
|
||||
|
||||
function renderNow(): void {
|
||||
if (disposed) {
|
||||
return;
|
||||
}
|
||||
render(game, canvas, renderingContext, score, length);
|
||||
}
|
||||
|
||||
function schedule(): void {
|
||||
if (!running || disposed || animationFrame !== null) {
|
||||
return;
|
||||
}
|
||||
animationFrame = window.requestAnimationFrame(frame);
|
||||
}
|
||||
|
||||
function frame(now: number): void {
|
||||
animationFrame = null;
|
||||
if (!running || disposed) {
|
||||
return;
|
||||
}
|
||||
const elapsed = Math.min(Math.max(0, now - previous), MAX_FRAME_ELAPSED_MILLIS);
|
||||
previous = now;
|
||||
accumulator += elapsed;
|
||||
while (accumulator >= FRAME_MILLIS) {
|
||||
game.tick();
|
||||
accumulator -= FRAME_MILLIS;
|
||||
}
|
||||
renderNow();
|
||||
schedule();
|
||||
}
|
||||
|
||||
function pause(): void {
|
||||
if (!running || disposed) {
|
||||
return;
|
||||
}
|
||||
running = false;
|
||||
accumulator = 0;
|
||||
if (animationFrame !== null) {
|
||||
window.cancelAnimationFrame(animationFrame);
|
||||
animationFrame = null;
|
||||
}
|
||||
webDebug("snake-web-runtime", "runtime_paused");
|
||||
}
|
||||
|
||||
function resume(): void {
|
||||
if (running || disposed) {
|
||||
return;
|
||||
}
|
||||
previous = performance.now();
|
||||
accumulator = 0;
|
||||
running = true;
|
||||
schedule();
|
||||
webDebug("snake-web-runtime", "runtime_resumed");
|
||||
}
|
||||
|
||||
renderNow();
|
||||
resume();
|
||||
return {
|
||||
queueDirection(direction: SnakeDirection, source: SnakeInputSource): void {
|
||||
if (disposed) {
|
||||
return;
|
||||
}
|
||||
provenance.recordInput(source);
|
||||
queueDirection(game, direction);
|
||||
},
|
||||
pause,
|
||||
resume,
|
||||
renderNow,
|
||||
refreshDeviceClass(): void {
|
||||
if (!disposed) {
|
||||
provenance.refreshDeviceClass();
|
||||
}
|
||||
},
|
||||
dispose(): void {
|
||||
if (disposed) {
|
||||
return;
|
||||
}
|
||||
pause();
|
||||
disposed = true;
|
||||
game.free();
|
||||
},
|
||||
};
|
||||
}
|
||||
61
Web/game-snake-poc/frontend/ts/input.ts
Normal file
61
Web/game-snake-poc/frontend/ts/input.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
// file: Web/game-snake-poc/frontend/ts/input.ts
|
||||
// version: 2
|
||||
|
||||
import type { SnakeDirection, SnakeWebSession } from "./game";
|
||||
import { webDebug } from "./logging";
|
||||
|
||||
const KEY_DIRECTIONS: Readonly<Record<string, SnakeDirection>> = {
|
||||
arrowleft: "left",
|
||||
a: "left",
|
||||
q: "left",
|
||||
arrowright: "right",
|
||||
d: "right",
|
||||
arrowup: "up",
|
||||
w: "up",
|
||||
z: "up",
|
||||
arrowdown: "down",
|
||||
s: "down",
|
||||
};
|
||||
|
||||
function buttonDirection(button: HTMLButtonElement): SnakeDirection | null {
|
||||
const direction = button.dataset.direction;
|
||||
if (direction === "left" || direction === "right" || direction === "up" || direction === "down") {
|
||||
return direction;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function bindInputs(session: SnakeWebSession, buttons: readonly HTMLButtonElement[]): void {
|
||||
window.addEventListener("keydown", event => {
|
||||
if (event.repeat) {
|
||||
return;
|
||||
}
|
||||
const direction = KEY_DIRECTIONS[event.key.toLowerCase()];
|
||||
if (direction === undefined) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
session.queueDirection(direction, "keyboard-mouse");
|
||||
webDebug("snake-web-input", "direction", { direction, source: "keyboard-mouse" });
|
||||
});
|
||||
|
||||
for (const button of buttons) {
|
||||
const direction = buttonDirection(button);
|
||||
if (direction === null) {
|
||||
continue;
|
||||
}
|
||||
button.addEventListener("pointerdown", event => {
|
||||
event.preventDefault();
|
||||
const source = event.pointerType === "touch" ? "touch" : "keyboard-mouse";
|
||||
session.queueDirection(direction, source);
|
||||
webDebug("snake-web-input", "direction", { direction, source });
|
||||
});
|
||||
button.addEventListener("click", event => {
|
||||
if (event.detail !== 0) {
|
||||
return;
|
||||
}
|
||||
session.queueDirection(direction, "keyboard-mouse");
|
||||
webDebug("snake-web-input", "direction", { direction, source: "keyboard-mouse" });
|
||||
});
|
||||
}
|
||||
}
|
||||
58
Web/game-snake-poc/frontend/ts/lifecycle.ts
Normal file
58
Web/game-snake-poc/frontend/ts/lifecycle.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
// file: Web/game-snake-poc/frontend/ts/lifecycle.ts
|
||||
// version: 1
|
||||
|
||||
import type { SnakeWebSession } from "./game";
|
||||
import { webDebug, webInfo } from "./logging";
|
||||
|
||||
export interface SnakeLifecycleBinding {
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
export function bindBrowserLifecycle(session: SnakeWebSession, stage: HTMLElement): SnakeLifecycleBinding {
|
||||
const resizeObserver = new ResizeObserver(() => {
|
||||
session.refreshDeviceClass();
|
||||
session.renderNow();
|
||||
});
|
||||
|
||||
function synchronizeVisibility(): void {
|
||||
if (document.visibilityState === "hidden") {
|
||||
session.pause();
|
||||
webDebug("snake-web-lifecycle", "visibility_hidden");
|
||||
return;
|
||||
}
|
||||
session.resume();
|
||||
session.renderNow();
|
||||
webDebug("snake-web-lifecycle", "visibility_visible");
|
||||
}
|
||||
|
||||
function pageHide(event: PageTransitionEvent): void {
|
||||
if (event.persisted) {
|
||||
session.pause();
|
||||
} else {
|
||||
session.dispose();
|
||||
}
|
||||
webInfo("snake-web-lifecycle", "page_hide", { persisted: event.persisted });
|
||||
}
|
||||
|
||||
function pageShow(event: PageTransitionEvent): void {
|
||||
session.resume();
|
||||
session.renderNow();
|
||||
webInfo("snake-web-lifecycle", "page_show", { persisted: event.persisted });
|
||||
}
|
||||
|
||||
resizeObserver.observe(stage);
|
||||
document.addEventListener("visibilitychange", synchronizeVisibility);
|
||||
window.addEventListener("pagehide", pageHide);
|
||||
window.addEventListener("pageshow", pageShow);
|
||||
synchronizeVisibility();
|
||||
|
||||
return {
|
||||
dispose(): void {
|
||||
resizeObserver.disconnect();
|
||||
document.removeEventListener("visibilitychange", synchronizeVisibility);
|
||||
window.removeEventListener("pagehide", pageHide);
|
||||
window.removeEventListener("pageshow", pageShow);
|
||||
session.dispose();
|
||||
},
|
||||
};
|
||||
}
|
||||
45
Web/game-snake-poc/frontend/ts/logging.ts
Normal file
45
Web/game-snake-poc/frontend/ts/logging.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
// file: Web/game-snake-poc/frontend/ts/logging.ts
|
||||
// version: 1
|
||||
|
||||
export type WebLogLevel = "debug" | "info" | "warn" | "error";
|
||||
export type WebLogFields = Readonly<Record<string, boolean | number | string | null>>;
|
||||
|
||||
type ConsoleMethod = (...items: unknown[]) => void;
|
||||
|
||||
function consoleMethod(level: WebLogLevel): ConsoleMethod {
|
||||
if (level === "debug") {
|
||||
return console.debug.bind(console);
|
||||
}
|
||||
if (level === "info") {
|
||||
return console.info.bind(console);
|
||||
}
|
||||
if (level === "warn") {
|
||||
return console.warn.bind(console);
|
||||
}
|
||||
return console.error.bind(console);
|
||||
}
|
||||
|
||||
function emit(level: WebLogLevel, target: string, action: string, fields: WebLogFields = {}): void {
|
||||
const event = {
|
||||
target,
|
||||
action,
|
||||
...fields,
|
||||
};
|
||||
consoleMethod(level)(`[games.sasedev][${target}] ${action}`, event);
|
||||
}
|
||||
|
||||
export function webDebug(target: string, action: string, fields: WebLogFields = {}): void {
|
||||
emit("debug", target, action, fields);
|
||||
}
|
||||
|
||||
export function webInfo(target: string, action: string, fields: WebLogFields = {}): void {
|
||||
emit("info", target, action, fields);
|
||||
}
|
||||
|
||||
export function webWarn(target: string, action: string, fields: WebLogFields = {}): void {
|
||||
emit("warn", target, action, fields);
|
||||
}
|
||||
|
||||
export function webError(target: string, action: string, fields: WebLogFields = {}): void {
|
||||
emit("error", target, action, fields);
|
||||
}
|
||||
66
Web/game-snake-poc/frontend/ts/main.ts
Normal file
66
Web/game-snake-poc/frontend/ts/main.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
// file: Web/game-snake-poc/frontend/ts/main.ts
|
||||
// version: 3
|
||||
|
||||
import ResizeObserver from "resize-observer-polyfill";
|
||||
import "simplebar";
|
||||
import { loadSnakeWebAssets } from "./assets";
|
||||
import { startGame } from "./game";
|
||||
import { bindInputs } from "./input";
|
||||
import { bindBrowserLifecycle } from "./lifecycle";
|
||||
import { webError, webInfo } from "./logging";
|
||||
|
||||
(window as Window & typeof globalThis & { ResizeObserver?: typeof ResizeObserver }).ResizeObserver = ResizeObserver;
|
||||
|
||||
function requireElement<T extends Element>(selector: string): T {
|
||||
const element = document.querySelector<T>(selector);
|
||||
if (element === null) {
|
||||
throw new Error(`Élément frontend requis absent : ${selector}`);
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
const canvas = requireElement<HTMLCanvasElement>("#game");
|
||||
const stage = requireElement<HTMLElement>(".game-stage");
|
||||
const score = requireElement<HTMLOutputElement>("#score");
|
||||
const length = requireElement<HTMLOutputElement>("#length");
|
||||
const provenance = requireElement<HTMLOutputElement>("#runtime-provenance");
|
||||
const assets = requireElement<HTMLOutputElement>("#asset-status");
|
||||
const status = requireElement<HTMLSpanElement>("#runtime-status");
|
||||
const error = requireElement<HTMLParagraphElement>("#startup-error");
|
||||
const buttons = Array.from(document.querySelectorAll<HTMLButtonElement>("[data-direction]"));
|
||||
|
||||
status.textContent = "Chargement assets…";
|
||||
const assetMetadata = await loadSnakeWebAssets();
|
||||
assets.value = `${assetMetadata.gameKind} / engine-v${assetMetadata.engineGeneration}`;
|
||||
webInfo("snake-web-assets", "runtime_assets_loaded", {
|
||||
engineGeneration: assetMetadata.engineGeneration,
|
||||
game: assetMetadata.game,
|
||||
gameKind: assetMetadata.gameKind,
|
||||
});
|
||||
|
||||
status.textContent = "Chargement WASM…";
|
||||
const session = await startGame(canvas, score, length, provenance);
|
||||
bindInputs(session, buttons);
|
||||
bindBrowserLifecycle(session, stage);
|
||||
status.className = "badge text-bg-success";
|
||||
status.textContent = "Prêt";
|
||||
error.hidden = true;
|
||||
canvas.focus();
|
||||
webInfo("snake-web-main", "runtime_ready");
|
||||
}
|
||||
|
||||
void main().catch(caughtError => {
|
||||
const status = document.querySelector<HTMLSpanElement>("#runtime-status");
|
||||
const error = document.querySelector<HTMLParagraphElement>("#startup-error");
|
||||
const message = caughtError instanceof Error ? caughtError.stack ?? caughtError.message : String(caughtError);
|
||||
if (status !== null) {
|
||||
status.className = "badge text-bg-danger";
|
||||
status.textContent = "Erreur";
|
||||
}
|
||||
if (error !== null) {
|
||||
error.textContent = `Impossible de démarrer Snake : ${message}`;
|
||||
error.hidden = false;
|
||||
}
|
||||
webError("snake-web-main", "runtime_start_failed", { message });
|
||||
});
|
||||
98
Web/game-snake-poc/frontend/ts/provenance.ts
Normal file
98
Web/game-snake-poc/frontend/ts/provenance.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
// file: Web/game-snake-poc/frontend/ts/provenance.ts
|
||||
// version: 1
|
||||
|
||||
import type { SnakeWasmGame } from "@snake-wasm";
|
||||
import { webInfo } from "./logging";
|
||||
|
||||
export type SnakeInputSource = "keyboard-mouse" | "touch";
|
||||
|
||||
type DeviceClass = "desktop" | "phone" | "tablet" | "unknown";
|
||||
type InputProfile = "keyboard-mouse" | "mixed" | "touch" | "unknown";
|
||||
|
||||
function detectedDeviceClass(): DeviceClass {
|
||||
const coarsePointer = window.matchMedia("(pointer: coarse)").matches;
|
||||
const finePointer = window.matchMedia("(pointer: fine)").matches;
|
||||
if (!coarsePointer || finePointer) {
|
||||
return "desktop";
|
||||
}
|
||||
const shortEdge = Math.min(window.screen.width, window.screen.height);
|
||||
if (!Number.isFinite(shortEdge) || shortEdge <= 0) {
|
||||
return "unknown";
|
||||
}
|
||||
return shortEdge < 768 ? "phone" : "tablet";
|
||||
}
|
||||
|
||||
function inputProfile(keyboardMouseObserved: boolean, touchObserved: boolean): InputProfile {
|
||||
if (keyboardMouseObserved && touchObserved) {
|
||||
return "mixed";
|
||||
}
|
||||
if (keyboardMouseObserved) {
|
||||
return "keyboard-mouse";
|
||||
}
|
||||
if (touchObserved) {
|
||||
return "touch";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
function displayLabel(game: SnakeWasmGame): string {
|
||||
return [
|
||||
game.provenance_platform_family(),
|
||||
game.provenance_runtime_host(),
|
||||
game.provenance_execution_model(),
|
||||
game.provenance_device_class(),
|
||||
game.provenance_input_profile(),
|
||||
].join(" / ");
|
||||
}
|
||||
|
||||
export class BrowserRuntimeProvenance {
|
||||
private keyboardMouseObserved = false;
|
||||
private touchObserved = false;
|
||||
private deviceClass: DeviceClass = detectedDeviceClass();
|
||||
|
||||
public constructor(
|
||||
private readonly game: SnakeWasmGame,
|
||||
private readonly output: HTMLOutputElement,
|
||||
) {
|
||||
this.synchronize();
|
||||
}
|
||||
|
||||
public recordInput(source: SnakeInputSource): void {
|
||||
if (source === "touch") {
|
||||
if (this.touchObserved) {
|
||||
return;
|
||||
}
|
||||
this.touchObserved = true;
|
||||
} else {
|
||||
if (this.keyboardMouseObserved) {
|
||||
return;
|
||||
}
|
||||
this.keyboardMouseObserved = true;
|
||||
}
|
||||
this.synchronize();
|
||||
}
|
||||
|
||||
public refreshDeviceClass(): void {
|
||||
const nextDeviceClass = detectedDeviceClass();
|
||||
if (nextDeviceClass === this.deviceClass) {
|
||||
return;
|
||||
}
|
||||
this.deviceClass = nextDeviceClass;
|
||||
this.synchronize();
|
||||
}
|
||||
|
||||
private synchronize(): void {
|
||||
const profile = inputProfile(this.keyboardMouseObserved, this.touchObserved);
|
||||
if (!this.game.configure_runtime_provenance(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);
|
||||
webInfo("snake-web-provenance", "runtime_provenance", {
|
||||
deviceClass: this.game.provenance_device_class(),
|
||||
executionModel: this.game.provenance_execution_model(),
|
||||
inputProfile: this.game.provenance_input_profile(),
|
||||
platformFamily: this.game.provenance_platform_family(),
|
||||
runtimeHost: this.game.provenance_runtime_host(),
|
||||
});
|
||||
}
|
||||
}
|
||||
25
Web/game-snake-poc/package.json
Normal file
25
Web/game-snake-poc/package.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "game-snake-poc-web",
|
||||
"private": true,
|
||||
"version": "0.3.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^7.3",
|
||||
"bootstrap": "^5.3",
|
||||
"resize-observer-polyfill": "^1.5",
|
||||
"simplebar": "^6.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bootstrap": "^5.2",
|
||||
"@types/node": "^26.1",
|
||||
"sass-embedded": "^1.102",
|
||||
"typescript": "^7.0",
|
||||
"vite": "^8.2",
|
||||
"vite-plugin-static-copy": "^4.1"
|
||||
}
|
||||
}
|
||||
36
Web/game-snake-poc/tsconfig.json
Normal file
36
Web/game-snake-poc/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-web/wasm/game_snake_poc_wasm.d.ts"
|
||||
]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"frontend",
|
||||
"vite.config.ts"
|
||||
]
|
||||
}
|
||||
96
Web/game-snake-poc/vite.config.ts
Normal file
96
Web/game-snake-poc/vite.config.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
// file: Web/game-snake-poc/vite.config.ts
|
||||
// version: 3
|
||||
|
||||
import { NodePackageImporter } from "sass-embedded";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { resolve } from "node:path";
|
||||
import { defineConfig, normalizePath } from "vite";
|
||||
import { viteStaticCopy } from "vite-plugin-static-copy";
|
||||
|
||||
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-web"));
|
||||
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 commonRuntimeAsset = normalizePath(resolve(repositoryRoot, "assets/common/data/runtime.json"));
|
||||
const gameRuntimeAsset = normalizePath(resolve(repositoryRoot, "assets/game-snake-poc/data/game.json"));
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
viteStaticCopy({
|
||||
targets: [
|
||||
{ src: commonRuntimeAsset, dest: "common/data", rename: { stripBase: true } },
|
||||
{ src: gameRuntimeAsset, dest: "game/data", rename: { stripBase: true } },
|
||||
],
|
||||
}),
|
||||
],
|
||||
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 (["eot", "otf", "ttf", "woff", "woff2"].includes(extension)) {
|
||||
return "fonts/[name]-[hash][extname]";
|
||||
}
|
||||
if (["png", "jpg", "jpeg", "gif", "svg", "webp", "ico"].includes(extension)) {
|
||||
return "imgs/[name][extname]";
|
||||
}
|
||||
if (extension === "wasm") {
|
||||
return "wasm/[name]-[hash][extname]";
|
||||
}
|
||||
return "otherassets/[name][extname]";
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
css: {
|
||||
preprocessorOptions: {
|
||||
scss: {
|
||||
quietDeps: true,
|
||||
silenceDeprecations: ["import", "color-functions", "global-builtin"],
|
||||
verbose: false,
|
||||
importers: [new NodePackageImporter()],
|
||||
},
|
||||
},
|
||||
},
|
||||
server: {
|
||||
host: "127.0.0.1",
|
||||
port: 1434,
|
||||
strictPort: true,
|
||||
fs: {
|
||||
allow: [appRoot, repositoryRoot, externalBuildRoot],
|
||||
},
|
||||
},
|
||||
preview: {
|
||||
host: "127.0.0.1",
|
||||
port: 4174,
|
||||
strictPort: true,
|
||||
},
|
||||
});
|
||||
23
crates/apps/game-snake-poc-wasm/Cargo.toml
Normal file
23
crates/apps/game-snake-poc-wasm/Cargo.toml
Normal file
@@ -0,0 +1,23 @@
|
||||
# file: crates/apps/game-snake-poc-wasm/Cargo.toml
|
||||
# version: 2
|
||||
|
||||
[package]
|
||||
name = "game-snake-poc-wasm"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
authors.workspace = true
|
||||
publish.workspace = true
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
engine-v1-common = { path = "../../engines/engine-v1-common" }
|
||||
engine-v1-platform-api = { path = "../../engines/engine-v1-platform-api" }
|
||||
game-snake-poc = { path = "../../games/game-snake-poc" }
|
||||
wasm-bindgen.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
13
crates/apps/game-snake-poc-wasm/src/lib.rs
Normal file
13
crates/apps/game-snake-poc-wasm/src/lib.rs
Normal file
@@ -0,0 +1,13 @@
|
||||
// file: crates/apps/game-snake-poc-wasm/src/lib.rs
|
||||
// version: 1
|
||||
|
||||
//! WebAssembly adapter facade for the Snake POC.
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(unreachable_pub)]
|
||||
#![warn(missing_docs)]
|
||||
|
||||
mod runtime;
|
||||
|
||||
/// Re-export of the Snake WebAssembly runtime adapter.
|
||||
pub use self::runtime::SnakeWasmGame;
|
||||
304
crates/apps/game-snake-poc-wasm/src/runtime.rs
Normal file
304
crates/apps/game-snake-poc-wasm/src/runtime.rs
Normal file
@@ -0,0 +1,304 @@
|
||||
// file: crates/apps/game-snake-poc-wasm/src/runtime.rs
|
||||
// version: 2
|
||||
|
||||
const FIXED_STEP_MILLIS: u64 = 16;
|
||||
|
||||
/// WebAssembly-owned Snake game state consumed by the direct browser host.
|
||||
#[wasm_bindgen::prelude::wasm_bindgen]
|
||||
pub struct SnakeWasmGame {
|
||||
pending_input: engine_v1_common::InputState,
|
||||
provenance: engine_v1_platform_api::RuntimeProvenance,
|
||||
runner: engine_v1_common::FixedStepRunner,
|
||||
state: game_snake_poc::SnakeState,
|
||||
}
|
||||
|
||||
#[wasm_bindgen::prelude::wasm_bindgen]
|
||||
impl SnakeWasmGame {
|
||||
/// Creates a fresh Snake POC session using the shared gameplay crate.
|
||||
#[wasm_bindgen::prelude::wasm_bindgen(constructor)]
|
||||
pub fn new() -> Self {
|
||||
return Self {
|
||||
pending_input: engine_v1_common::InputState::none(),
|
||||
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::Web,
|
||||
engine_v1_platform_api::RuntimeHost::Browser,
|
||||
),
|
||||
runner: engine_v1_common::FixedStepRunner::new(std::time::Duration::from_millis(FIXED_STEP_MILLIS)),
|
||||
state: game_snake_poc::SnakeState::new(),
|
||||
};
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
let device_class = match parse_device_class(device_class) {
|
||||
Some(value) => value,
|
||||
None => return false,
|
||||
};
|
||||
let input_profile = match parse_input_profile(input_profile) {
|
||||
Some(value) => value,
|
||||
None => return false,
|
||||
};
|
||||
self.provenance = engine_v1_platform_api::RuntimeProvenance::new(
|
||||
device_class,
|
||||
engine_v1_platform_api::ExecutionModel::Wasm,
|
||||
input_profile,
|
||||
engine_v1_platform_api::PlatformFamily::Web,
|
||||
engine_v1_platform_api::RuntimeHost::Browser,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Returns the current physical device class label.
|
||||
pub fn provenance_device_class(&self) -> String {
|
||||
return device_class_label(self.provenance.device_class()).to_string();
|
||||
}
|
||||
|
||||
/// Returns the current execution model label.
|
||||
pub fn provenance_execution_model(&self) -> String {
|
||||
return execution_model_label(self.provenance.execution_model()).to_string();
|
||||
}
|
||||
|
||||
/// Returns the current primary input profile label.
|
||||
pub fn provenance_input_profile(&self) -> String {
|
||||
return input_profile_label(self.provenance.input_profile()).to_string();
|
||||
}
|
||||
|
||||
/// Returns the current platform family label.
|
||||
pub fn provenance_platform_family(&self) -> String {
|
||||
return platform_family_label(self.provenance.platform_family()).to_string();
|
||||
}
|
||||
|
||||
/// Returns the current runtime host label.
|
||||
pub fn provenance_runtime_host(&self) -> String {
|
||||
return runtime_host_label(self.provenance.runtime_host()).to_string();
|
||||
}
|
||||
|
||||
/// Queues a logical left direction for the next deterministic update.
|
||||
pub fn left(&mut self) {
|
||||
self.queue_direction(engine_v1_common::GameAction::Left);
|
||||
return;
|
||||
}
|
||||
|
||||
/// Queues a logical right direction for the next deterministic update.
|
||||
pub fn right(&mut self) {
|
||||
self.queue_direction(engine_v1_common::GameAction::Right);
|
||||
return;
|
||||
}
|
||||
|
||||
/// Queues a logical upward direction for the next deterministic update.
|
||||
pub fn up(&mut self) {
|
||||
self.queue_direction(engine_v1_common::GameAction::Up);
|
||||
return;
|
||||
}
|
||||
|
||||
/// Queues a logical downward direction for the next deterministic update.
|
||||
pub fn down(&mut self) {
|
||||
self.queue_direction(engine_v1_common::GameAction::Down);
|
||||
return;
|
||||
}
|
||||
|
||||
/// Advances one deterministic update and consumes the queued direction.
|
||||
pub fn tick(&mut self) {
|
||||
let input = self.pending_input;
|
||||
self.pending_input = engine_v1_common::InputState::none();
|
||||
self.runner.tick(&mut self.state, input);
|
||||
return;
|
||||
}
|
||||
|
||||
/// Returns the current gameplay score.
|
||||
pub fn score(&self) -> u32 {
|
||||
return self.state.score().min(u32::MAX as u64) as u32;
|
||||
}
|
||||
|
||||
/// Returns the current Snake length.
|
||||
pub fn length(&self) -> u32 {
|
||||
return self.state.length().min(u32::MAX as usize) as u32;
|
||||
}
|
||||
|
||||
/// Returns the current scene background red channel.
|
||||
pub fn background_red(&self) -> u8 {
|
||||
return self.scene().background().red();
|
||||
}
|
||||
|
||||
/// Returns the current scene background green channel.
|
||||
pub fn background_green(&self) -> u8 {
|
||||
return self.scene().background().green();
|
||||
}
|
||||
|
||||
/// Returns the current scene background blue channel.
|
||||
pub fn background_blue(&self) -> u8 {
|
||||
return self.scene().background().blue();
|
||||
}
|
||||
|
||||
/// Returns the number of occupied rectangle slots in the current scene.
|
||||
pub fn rectangle_count(&self) -> u32 {
|
||||
let scene = self.scene();
|
||||
let mut count = 0_u32;
|
||||
for slot in scene.rectangles() {
|
||||
if slot.is_some() {
|
||||
count = count.saturating_add(1);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/// Returns one rectangle's normalized left coordinate or `-1.0` if absent.
|
||||
pub fn rectangle_x(&self, index: u32) -> f32 {
|
||||
return match self.rectangle(index) {
|
||||
Some(rectangle) => rectangle.rect().x(),
|
||||
None => -1.0,
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns one rectangle's normalized top coordinate or `-1.0` if absent.
|
||||
pub fn rectangle_y(&self, index: u32) -> f32 {
|
||||
return match self.rectangle(index) {
|
||||
Some(rectangle) => rectangle.rect().y(),
|
||||
None => -1.0,
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns one rectangle's normalized width or `0.0` if absent.
|
||||
pub fn rectangle_width(&self, index: u32) -> f32 {
|
||||
return match self.rectangle(index) {
|
||||
Some(rectangle) => rectangle.rect().width(),
|
||||
None => 0.0,
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns one rectangle's normalized height or `0.0` if absent.
|
||||
pub fn rectangle_height(&self, index: u32) -> f32 {
|
||||
return match self.rectangle(index) {
|
||||
Some(rectangle) => rectangle.rect().height(),
|
||||
None => 0.0,
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns one rectangle's red channel or zero if absent.
|
||||
pub fn rectangle_red(&self, index: u32) -> u8 {
|
||||
return match self.rectangle(index) {
|
||||
Some(rectangle) => rectangle.color().red(),
|
||||
None => 0,
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns one rectangle's green channel or zero if absent.
|
||||
pub fn rectangle_green(&self, index: u32) -> u8 {
|
||||
return match self.rectangle(index) {
|
||||
Some(rectangle) => rectangle.color().green(),
|
||||
None => 0,
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns one rectangle's blue channel or zero if absent.
|
||||
pub fn rectangle_blue(&self, index: u32) -> u8 {
|
||||
return match self.rectangle(index) {
|
||||
Some(rectangle) => rectangle.color().blue(),
|
||||
None => 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SnakeWasmGame {
|
||||
fn default() -> Self {
|
||||
return Self::new();
|
||||
}
|
||||
}
|
||||
|
||||
impl SnakeWasmGame {
|
||||
fn queue_direction(&mut self, action: engine_v1_common::GameAction) {
|
||||
self.pending_input = engine_v1_common::InputState::none().with_action(action, true);
|
||||
return;
|
||||
}
|
||||
|
||||
fn scene(&self) -> engine_v1_common::EngineScene {
|
||||
return engine_v1_common::EngineGame::scene(&self.state);
|
||||
}
|
||||
|
||||
fn rectangle(&self, requested_index: u32) -> Option<engine_v1_common::RenderRect> {
|
||||
let scene = self.scene();
|
||||
let mut occupied_index = 0_u32;
|
||||
for slot in scene.rectangles() {
|
||||
match slot {
|
||||
Some(rectangle) => {
|
||||
if occupied_index == requested_index {
|
||||
return Some(*rectangle);
|
||||
}
|
||||
occupied_index = occupied_index.saturating_add(1);
|
||||
},
|
||||
None => {},
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_device_class(label: &str) -> Option<engine_v1_platform_api::DeviceClass> {
|
||||
return match label {
|
||||
"desktop" => Some(engine_v1_platform_api::DeviceClass::Desktop),
|
||||
"phone" => Some(engine_v1_platform_api::DeviceClass::Phone),
|
||||
"tablet" => Some(engine_v1_platform_api::DeviceClass::Tablet),
|
||||
"unknown" => Some(engine_v1_platform_api::DeviceClass::Unknown),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
|
||||
fn parse_input_profile(label: &str) -> Option<engine_v1_platform_api::InputProfile> {
|
||||
return match label {
|
||||
"gamepad" => Some(engine_v1_platform_api::InputProfile::Gamepad),
|
||||
"keyboard-mouse" => Some(engine_v1_platform_api::InputProfile::KeyboardMouse),
|
||||
"mixed" => Some(engine_v1_platform_api::InputProfile::Mixed),
|
||||
"touch" => Some(engine_v1_platform_api::InputProfile::Touch),
|
||||
"unknown" => Some(engine_v1_platform_api::InputProfile::Unknown),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
|
||||
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",
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "../unit_tests/runtime.rs"]
|
||||
mod tests;
|
||||
52
crates/apps/game-snake-poc-wasm/unit_tests/runtime.rs
Normal file
52
crates/apps/game-snake-poc-wasm/unit_tests/runtime.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
// file: crates/apps/game-snake-poc-wasm/unit_tests/runtime.rs
|
||||
// version: 2
|
||||
|
||||
#[test]
|
||||
fn direction_is_queued_without_advancing_simulation() {
|
||||
let mut game = crate::SnakeWasmGame::new();
|
||||
let before_x = game.rectangle_x(1);
|
||||
let before_y = game.rectangle_y(1);
|
||||
game.up();
|
||||
assert_eq!(game.rectangle_x(1), before_x);
|
||||
assert_eq!(game.rectangle_y(1), before_y);
|
||||
game.tick();
|
||||
assert_eq!(game.rectangle_x(1), before_x);
|
||||
assert!(game.rectangle_y(1) < before_y);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scene_and_status_are_exposed_for_canvas_host() {
|
||||
let game = crate::SnakeWasmGame::new();
|
||||
assert_eq!(game.score(), 0);
|
||||
assert_eq!(game.length(), 3);
|
||||
assert_eq!(game.rectangle_count(), 4);
|
||||
assert!(game.rectangle_width(0) > 0.0);
|
||||
assert!(game.rectangle_height(0) > 0.0);
|
||||
assert_eq!(game.rectangle_x(99), -1.0);
|
||||
assert_eq!(game.rectangle_y(99), -1.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn browser_runtime_provenance_preserves_static_and_observed_dimensions() {
|
||||
let mut game = crate::SnakeWasmGame::new();
|
||||
assert_eq!(game.provenance_platform_family(), "web");
|
||||
assert_eq!(game.provenance_execution_model(), "wasm");
|
||||
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_eq!(game.provenance_device_class(), "phone");
|
||||
assert_eq!(game.provenance_input_profile(), "touch");
|
||||
assert_eq!(game.provenance_platform_family(), "web");
|
||||
assert_eq!(game.provenance_execution_model(), "wasm");
|
||||
assert_eq!(game.provenance_runtime_host(), "browser");
|
||||
}
|
||||
|
||||
#[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_eq!(game.provenance_device_class(), "desktop");
|
||||
assert_eq!(game.provenance_input_profile(), "keyboard-mouse");
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
# file: crates/games/game-reflex-poc/Cargo.toml
|
||||
# version: 3
|
||||
# version: 4
|
||||
|
||||
[package]
|
||||
name = "game-reflex-poc"
|
||||
@@ -12,7 +12,6 @@ publish.workspace = true
|
||||
|
||||
[dependencies]
|
||||
engine-v1-common = { path = "../../engines/engine-v1-common" }
|
||||
engine-v1-platform-api = { path = "../../engines/engine-v1-platform-api" }
|
||||
|
||||
[dev-dependencies]
|
||||
game-logging-lib = { path = "../../common/game-logging-lib" }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# file: crates/games/game-snake-poc/Cargo.toml
|
||||
# version: 3
|
||||
# version: 4
|
||||
|
||||
[package]
|
||||
name = "game-snake-poc"
|
||||
@@ -12,7 +12,6 @@ publish.workspace = true
|
||||
|
||||
[dependencies]
|
||||
engine-v1-common = { path = "../../engines/engine-v1-common" }
|
||||
engine-v1-platform-api = { path = "../../engines/engine-v1-platform-api" }
|
||||
|
||||
[dev-dependencies]
|
||||
game-logging-lib = { path = "../../common/game-logging-lib" }
|
||||
|
||||
85
deltas/0.3.0/0-pre.1.fix.1.md
Normal file
85
deltas/0.3.0/0-pre.1.fix.1.md
Normal file
@@ -0,0 +1,85 @@
|
||||
<!-- file: deltas/0.3.0/0-pre.1.fix.1.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta 0.3.0-0-pre.1.fix.1
|
||||
|
||||
## Base
|
||||
|
||||
Base requise : `0.3.0-0-pre.1`.
|
||||
|
||||
Ce correctif reste dans la responsabilité de cadrage de `0-pre.1`. Il ne modifie aucun gameplay, runtime, frontend ou packaging.
|
||||
|
||||
## Objet
|
||||
|
||||
Corriger deux omissions du cadrage initial :
|
||||
|
||||
- créer le plan vivant de `0.3.0` sous `docs/plans/`, avec le découpage prévisionnel souple de toute la progression de la version ;
|
||||
- formaliser les règles associées, notamment la relation plan/ROADMAP/deltas, la cible d'au moins une version complète par session et le traitement des archives fournies depuis un tag.
|
||||
|
||||
## Version
|
||||
|
||||
La version workspace passe de `0.3.0-0-pre.1` à `0.3.0-0-pre.1.fix.1`.
|
||||
|
||||
## Plan de version
|
||||
|
||||
Ajout de :
|
||||
|
||||
- `docs/plans/000-README.md` ;
|
||||
- `docs/plans/001-V0_3_0_WEB_SNAKE_POC_PLAN.md`.
|
||||
|
||||
Le plan conserve le scope et les décisions du cadrage, puis suit une trajectoire souple : baseline Snake portable, adaptation WASM, frontend Web/Vite, intégration E2E, correction/extraction conditionnelle, beta, RC et stable.
|
||||
|
||||
La numérotation est prévisionnelle. Les tranches peuvent être scindées, fusionnées ou décalées en fonction des résultats réels sans forcer une fermeture artificielle.
|
||||
|
||||
## Règles ajoutées ou précisées
|
||||
|
||||
- `0-pre.1` crée ou révise obligatoirement le plan actif de la version sous `docs/plans/` ;
|
||||
- le plan porte le découpage prévisionnel fin, `ROADMAP.md` reste macroscopique et les deltas enregistrent le livré réel ;
|
||||
- une session de développement est planifiée pour livrer au minimum une version concrète complète ; une prerelease est une tranche interne, pas une cible normale de fin de session ;
|
||||
- lorsqu'une archive est fournie comme téléchargement d'un tag du dépôt, elle est la baseline autoritaire de ce tag ; l'absence de `.git` est normale et n'est ni une anomalie ni une validation manquante ;
|
||||
- les contrôles Git nécessitant `.git` ne s'appliquent qu'à un checkout local effectivement fourni.
|
||||
|
||||
Le prompt `002-V0_3_X_START_PROMPT.md` est aligné sur ces règles : il ne demande plus de vérifier un état Git inexistant dans une archive taggée et exige le plan actif dans le résultat de `pre.1`.
|
||||
|
||||
## Fichiers ajoutés
|
||||
|
||||
- `docs/plans/000-README.md` ;
|
||||
- `docs/plans/001-V0_3_0_WEB_SNAKE_POC_PLAN.md` ;
|
||||
- `deltas/0.3.0/0-pre.1.fix.1.md`.
|
||||
|
||||
## Fichiers modifiés
|
||||
|
||||
- `Cargo.toml` ;
|
||||
- `README.md` ;
|
||||
- `docs/000-README.md` ;
|
||||
- `docs/rules/FILE_CONTRACTS.md` ;
|
||||
- `docs/rules/RULES_DOCUMENTATION.md` ;
|
||||
- `docs/rules/RULES_SESSION_PLANNING.md` ;
|
||||
- `docs/rules/VERSION_WORKFLOW.md` ;
|
||||
- `docs/rules/RULES_COMMANDS.md` ;
|
||||
- `prompts/002-V0_3_X_START_PROMPT.md`.
|
||||
|
||||
## Suppressions
|
||||
|
||||
Aucune.
|
||||
|
||||
## Validations applicables
|
||||
|
||||
Ce fix modifie uniquement le manifest de version et la documentation/règles. Les audits statiques sont exécutés lors de la préparation du delta.
|
||||
|
||||
Validation utilisateur demandée :
|
||||
|
||||
```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 deltas history
|
||||
python3 scripts/audit_distribution_layout.py
|
||||
|
||||
cargo fmt --all -- --check
|
||||
cargo check --workspace
|
||||
```
|
||||
|
||||
Clippy/tests ne sont pas rendus nécessaires par ce fix documentaire lui-même ; ils restent ceux prévus par la progression de `0.3.0`.
|
||||
|
||||
## Suite
|
||||
|
||||
Après validation de ce fix, poursuivre `0.3.0` selon `docs/plans/001-V0_3_0_WEB_SNAKE_POC_PLAN.md`, en commençant par `0-pre.2` et en visant la fermeture complète de `0.3.0` dans la session plutôt qu'un arrêt planifié sur une prerelease.
|
||||
94
deltas/0.3.0/0-pre.1.fix.2.md
Normal file
94
deltas/0.3.0/0-pre.1.fix.2.md
Normal file
@@ -0,0 +1,94 @@
|
||||
<!-- file: deltas/0.3.0/0-pre.1.fix.2.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta 0.3.0-0-pre.1.fix.2
|
||||
|
||||
## Base
|
||||
|
||||
Base requise : `0.3.0-0-pre.1.fix.1`.
|
||||
|
||||
Ce correctif reste dans la responsabilité de cadrage de `0-pre.1`. Il ne modifie aucun gameplay, runtime, frontend ou packaging.
|
||||
|
||||
## Objet
|
||||
|
||||
Compléter le plan `0.3.0` sur deux responsabilités qui doivent être visibles dès le cadrage :
|
||||
|
||||
- le POC navigateur doit posséder un véritable shell Web HTML/Vite/TypeScript autour du Canvas/WASM, avec Bootstrap 5 comme baseline de présentation du premier POC Snake ;
|
||||
- la prévision de version doit montrer explicitement la tranche finale de consolidation documentaire et de transmission avant RC/stable, au lieu de laisser cette responsabilité seulement implicite dans les règles générales.
|
||||
|
||||
## Version
|
||||
|
||||
La version workspace passe de `0.3.0-0-pre.1.fix.1` à `0.3.0-0-pre.1.fix.2`.
|
||||
|
||||
## Frontend Web
|
||||
|
||||
Le plan retient désormais explicitement pour `0-pre.4` :
|
||||
|
||||
- Vite/TypeScript comme host frontend ;
|
||||
- un document HTML responsive ;
|
||||
- Bootstrap 5 pour le layout, les états UI et les contrôles tactiles ;
|
||||
- un Canvas dédié au rendu du jeu ;
|
||||
- clavier et contrôles directionnels tactiles ;
|
||||
- séparation stricte : Bootstrap/DOM restent côté frontend, le gameplay et l'état du jeu restent dans Rust/WASM.
|
||||
|
||||
La règle durable ne rend pas Bootstrap obligatoire pour tous les futurs hosts Web : elle impose la séparation shell Web / Canvas-WASM / gameplay. Bootstrap 5 est la décision concrète du POC `0.3.0`.
|
||||
|
||||
## Consolidation de fin de version
|
||||
|
||||
Le forecast `0.3.0` ajoute `2-beta.2` comme repère prévisionnel de consolidation :
|
||||
|
||||
- réconciliation de la documentation durable et du plan actif ;
|
||||
- mise à jour de `CHANGELOG.md` ;
|
||||
- mise à jour de `ROADMAP.md` ;
|
||||
- mise à jour de l'historique applicable ;
|
||||
- vérification des deltas réellement livrés ;
|
||||
- préparation et vérification du prompt de la version/session suivante.
|
||||
|
||||
Le numéro reste souple : des fixes ou une beta supplémentaire peuvent le décaler. La responsabilité, elle, ne doit pas disparaître du plan.
|
||||
|
||||
La documentation fonctionnelle reste mise à jour au fil des tranches concernées ; cette consolidation finale sert à fermer la cohérence transversale et la transmission de session.
|
||||
|
||||
## Règles précisées
|
||||
|
||||
- `SESSION-009` exige que le forecast créé en `0-pre.1` rende explicitement visible une tranche de consolidation avant la candidate finale ;
|
||||
- `GAME-PLATFORM-020` fixe la séparation durable du host Web : shell HTML/CSS/TypeScript autour du Canvas/WASM, sans fuite du framework de présentation dans gameplay/WASM ; Bootstrap 5 est la baseline du premier POC Snake.
|
||||
|
||||
Le prompt `002-V0_3_X_START_PROMPT.md` est aligné sur les décisions déjà prises par `pre.1` : Web direct en premier host, adaptation WASM dédiée, shell Bootstrap 5 et tranche `2-beta.2` de consolidation/transmission.
|
||||
|
||||
## Fichiers ajoutés
|
||||
|
||||
- `deltas/0.3.0/0-pre.1.fix.2.md`.
|
||||
|
||||
## Fichiers modifiés
|
||||
|
||||
- `Cargo.toml` ;
|
||||
- `README.md` ;
|
||||
- `docs/plans/001-V0_3_0_WEB_SNAKE_POC_PLAN.md` ;
|
||||
- `docs/rules/RULES_PROJECT.md` ;
|
||||
- `docs/rules/RULES_SESSION_PLANNING.md` ;
|
||||
- `prompts/002-V0_3_X_START_PROMPT.md`.
|
||||
|
||||
## Suppressions
|
||||
|
||||
Aucune.
|
||||
|
||||
## Validations applicables
|
||||
|
||||
Ce fix modifie uniquement la version workspace et le cadrage documentaire/normatif. Les audits statiques sont exécutés lors de la préparation du delta.
|
||||
|
||||
Validation utilisateur demandée :
|
||||
|
||||
```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 deltas history
|
||||
python3 scripts/audit_distribution_layout.py
|
||||
|
||||
cargo fmt --all -- --check
|
||||
cargo check --workspace
|
||||
```
|
||||
|
||||
Aucun build Web n'est demandé par ce fix : Bootstrap 5 et le frontend Snake seront introduits seulement dans leur tranche d'implémentation.
|
||||
|
||||
## Suite
|
||||
|
||||
Après validation de ce fix, poursuivre `0.3.0` avec `0-pre.2` selon le plan actif. La session reste planifiée jusqu'à la stable `0.3.0`, avec consolidation documentaire/transmission explicitement réservée avant RC.
|
||||
157
deltas/0.3.0/0-pre.1.md
Normal file
157
deltas/0.3.0/0-pre.1.md
Normal file
@@ -0,0 +1,157 @@
|
||||
<!-- file: deltas/0.3.0/0-pre.1.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta 0.3.0-0-pre.1
|
||||
|
||||
## Base
|
||||
|
||||
Base déclarée : `0.2.0`.
|
||||
|
||||
L'archive de base a été inspectée avant modification. Sa version workspace est `0.2.0`. L'archive ne contient pas `.git`, donc le tag réel et la propreté Git ne peuvent pas être vérifiés dans l'environnement de génération.
|
||||
|
||||
## Objet
|
||||
|
||||
Ouvrir `0.3.0` par le cadrage obligatoire : audit réel de la baseline, revue des règles, requirements Snake, graphe de dépendances, choix du premier POC, sizing corrigé et préparation des validations.
|
||||
|
||||
Aucun gameplay, runtime SDL, Java/JNI, Tauri ou frontend existant n'est modifié dans cette tranche.
|
||||
|
||||
## Version
|
||||
|
||||
La version workspace passe de :
|
||||
|
||||
```text
|
||||
0.2.0
|
||||
```
|
||||
|
||||
à :
|
||||
|
||||
```text
|
||||
0.3.0-0-pre.1
|
||||
```
|
||||
|
||||
Les métadonnées Android restent à `0.2.0` dans cette tranche, car le chemin Android natif n'est ni modifié ni construit par le premier POC Web. Elles seront réévaluées dans la version qui réouvre effectivement ce produit Android.
|
||||
|
||||
## Audit de baseline
|
||||
|
||||
Les audits statiques officiels ont été exécutés avant modification et étaient propres :
|
||||
|
||||
```text
|
||||
General Rust rule audit: clean
|
||||
Rust export completeness audit: 0 candidate(s)
|
||||
games.sasedev workspace audit: clean
|
||||
Markdown table audit: clean (4 table(s), 158 file(s))
|
||||
Distribution layout audit: clean (19 required path(s), 1 forbidden path(s) absent)
|
||||
```
|
||||
|
||||
La revue manuelle a néanmoins détecté :
|
||||
|
||||
- README encore positionné sur `0.1.0` stable / `0.2.0` candidate ;
|
||||
- quatre lignes `( )` sous la stable `0.2.0` dans ROADMAP, en violation de `DOC-RMAP-010` ;
|
||||
- la gate `audit_rust_workspace_rules.py` qui créait un cache Python `.pyc` pendant son exécution, alors qu’un audit doit rester en lecture seule ;
|
||||
- `CMD-RC-001` encore spécifique à `0.1.0` ;
|
||||
- contradiction entre `CMD-BUILD-002` (interdiction globale) et `CMD-BUILD-004` (remplacement progressif en `0.3.x`), alors que deux orchestrateurs Python historiques existent encore ;
|
||||
- `CMD-WEB-003` décrivant sans contexte le build Python Tauri/WASM historique ;
|
||||
- dépendances `engine-v1-platform-api` déclarées mais non utilisées par les crates de jeu ;
|
||||
- `RuntimeProvenance` défini mais non branché aux launchers ;
|
||||
- `game-assets-lib` encore sans consommateur runtime ;
|
||||
- deux orchestrateurs Python de build historiques à ne pas réutiliser dans les nouveaux POC.
|
||||
|
||||
Les détails et le graphe complet sont documentés dans `docs/studies/023-V0_3_0_PLATFORM_POC_AUDIT.md`.
|
||||
|
||||
## Corrections de règles et hygiène
|
||||
|
||||
Cette tranche :
|
||||
|
||||
- corrige le README de version ;
|
||||
- ferme correctement le scope `0.2.0` dans ROADMAP ;
|
||||
- distingue ce qui a été livré de ce qui est reporté ;
|
||||
- rend `CMD-RC-001` générique à la version courante ;
|
||||
- rend `CMD-BUILD-002` cohérente avec la migration `0.3.x` : les deux orchestrateurs Python historiques sont gelés jusqu’à réactivation de leur chemin, mais aucun nouveau chemin ne peut les reprendre ;
|
||||
- qualifie explicitement `scripts/build_reflex_tauri_wasm.py` de mécanisme historique non réutilisable comme orchestration `0.3.x` ;
|
||||
- renforce `audit_project_workspace_rules.py` pour détecter le scope `( )` restant sous une version stable présente dans CHANGELOG ;
|
||||
- fait exécuter les sous-audits de `audit_rust_workspace_rules.py` avec l’interpréteur courant et `-B`, afin que la gate standard reste effectivement en lecture seule malgré l’import effectué dans l’audit de complétude des exports.
|
||||
|
||||
## Premier POC retenu
|
||||
|
||||
Le premier host de `0.3.0` devient :
|
||||
|
||||
```text
|
||||
Web navigateur direct + Snake
|
||||
```
|
||||
|
||||
Tauri Android est reporté au second host, actuellement prévu en `0.3.1`.
|
||||
|
||||
Le but est de valider d'abord la frontière Web/WASM et les capabilities directement observables sans cumuler simultanément la généralisation Snake/WASM et la complexité d'un host mobile Tauri.
|
||||
|
||||
## Forecast corrigé
|
||||
|
||||
```text
|
||||
0-pre.1 audit / règles / requirements / sizing
|
||||
0-pre.2 Snake portability baseline
|
||||
0-pre.3 adapter Snake WASM + build natif Web
|
||||
0-pre.4 navigateur direct end-to-end
|
||||
0-pre.5 seulement si un défaut réel est observé
|
||||
2-beta.1 validation large
|
||||
3-rc.1 candidate gelée
|
||||
0.3.0 release mécanique
|
||||
```
|
||||
|
||||
Aucune alpha n'est créée par cérémonial. Elle reste possible si le volume réel de stabilisation le justifie.
|
||||
|
||||
## Scope exclu de 0.3.0
|
||||
|
||||
- Tauri Android ;
|
||||
- Tauri Desktop Snake ;
|
||||
- Android multi-ABI natif ;
|
||||
- réseau realtime ;
|
||||
- WebTransport/QUIC ;
|
||||
- Uroburas ;
|
||||
- ads, billing, auth et leaderboard ;
|
||||
- ECS ou nouveau moteur.
|
||||
|
||||
## Suppressions
|
||||
|
||||
Aucune suppression de fichier appartenant à la baseline `0.2.0` n'est nécessaire.
|
||||
|
||||
## Validations exécutées dans l'environnement de génération
|
||||
|
||||
Après constitution de l'état livré, les audits statiques suivants doivent être réexécutés et leur résultat est enregistré avant packaging :
|
||||
|
||||
```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 deltas history
|
||||
python3 scripts/audit_distribution_layout.py
|
||||
```
|
||||
|
||||
Aucun build/test/smoke n'est exécuté par le générateur, conformément à `CMD-GEN-007` et `CMD-BUILD-005`.
|
||||
|
||||
## Validation utilisateur demandée
|
||||
|
||||
Cette tranche ne modifie aucun source Rust/Java/TypeScript ni aucune configuration runtime. Elle ouvre toutefois une nouvelle version `0.3.0` et modifie le manifest workspace ; la gate utilisateur retient donc les audits statiques puis une gate Cargo workspace complète, conformément à la discipline des frontières de version :
|
||||
|
||||
```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 deltas history
|
||||
python3 scripts/audit_distribution_layout.py
|
||||
|
||||
cargo fmt --all -- --check
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
cargo test --workspace --all-targets --all-features
|
||||
```
|
||||
|
||||
Aucun build de distribution, smoke Desktop, Tauri ou Android n'est requis par `pre.1`, car aucun runtime ni packaging de ces hosts n'est modifié.
|
||||
|
||||
La revue humaine doit confirmer :
|
||||
|
||||
- le choix Web direct comme premier POC ;
|
||||
- le scope corrigé de `0.3.0` ;
|
||||
- le report de Tauri Android vers le second host ;
|
||||
- le sizing `pre.2` à `pre.4` ;
|
||||
- la fermeture correcte des lignes historiques `0.2.0`.
|
||||
|
||||
## Suite après validation
|
||||
|
||||
Si cette gate est propre et le cadrage accepté, passer automatiquement à `0.3.0-0-pre.2`.
|
||||
|
||||
`pre.2` doit rester une tranche bornée de portabilité Snake et de nettoyage de dépendances ; elle ne doit pas commencer le frontend Web complet.
|
||||
102
deltas/0.3.0/0-pre.2.md
Normal file
102
deltas/0.3.0/0-pre.2.md
Normal file
@@ -0,0 +1,102 @@
|
||||
<!-- file: deltas/0.3.0/0-pre.2.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta 0.3.0-0-pre.2
|
||||
|
||||
## Base
|
||||
|
||||
Base requise : `0.3.0-0-pre.1.fix.2`.
|
||||
|
||||
Les validations utilisateur de `0-pre.1.fix.1` et `0-pre.1.fix.2` sont consignées sous `history/0.3.0/` conformément au workflow documentaire.
|
||||
|
||||
## Objet
|
||||
|
||||
Fermer la baseline Snake portable avant l'introduction de l'adapter WASM :
|
||||
|
||||
- retirer des crates de gameplay les dépendances plateforme déclarées mais inutilisées ;
|
||||
- confirmer que le gameplay Snake ne consomme que les contrats moteur indépendants de la plateforme ;
|
||||
- documenter le contrat minimal que le futur host Web devra adapter sans introduire encore de code WASM ou frontend.
|
||||
|
||||
## Version
|
||||
|
||||
La version workspace passe de `0.3.0-0-pre.1.fix.2` à `0.3.0-0-pre.2`.
|
||||
|
||||
## Nettoyage des dépendances
|
||||
|
||||
`engine-v1-platform-api` est retiré de :
|
||||
|
||||
- `game-snake-poc` ;
|
||||
- `game-reflex-poc`.
|
||||
|
||||
Ces deux crates n'utilisent aucun symbole de cette dépendance. Les launchers et adapters qui utilisent réellement des capacités plateforme conservent leur dépendance.
|
||||
|
||||
Ce nettoyage ne déplace aucune responsabilité et ne change aucun comportement de gameplay.
|
||||
|
||||
## Contrat Snake portable
|
||||
|
||||
La baseline confirmée pour Snake est :
|
||||
|
||||
- état et update via `EngineGame` ;
|
||||
- entrée via `InputState` ;
|
||||
- actions de gameplay utilisées : `Left`, `Right`, `Up`, `Down` ;
|
||||
- rendu abstrait via `EngineScene` ;
|
||||
- aucune dépendance SDL3, Web/DOM/Canvas ou `engine-v1-platform-api` dans `game-snake-poc`.
|
||||
|
||||
Le host reste responsable de traduire ses périphériques ou widgets en actions logiques. Le futur adapter WASM `0-pre.3` doit réutiliser cette frontière sans créer un modèle Web parallèle.
|
||||
|
||||
## Historique des validations précédentes
|
||||
|
||||
Ajout de :
|
||||
|
||||
- `history/0.3.0/0-pre.1.fix.1.md` ;
|
||||
- `history/0.3.0/0-pre.1.fix.2.md`.
|
||||
|
||||
Ces fichiers enregistrent uniquement les résultats effectivement fournis par l'utilisateur : audits statiques, `cargo fmt --all -- --check` et `cargo check --workspace`. Aucun Clippy, test ou smoke non exécuté n'est déclaré validé.
|
||||
|
||||
## Fichiers ajoutés
|
||||
|
||||
- `deltas/0.3.0/0-pre.2.md` ;
|
||||
- `history/0.3.0/0-pre.1.fix.1.md` ;
|
||||
- `history/0.3.0/0-pre.1.fix.2.md`.
|
||||
|
||||
## Fichiers modifiés
|
||||
|
||||
- `Cargo.toml` ;
|
||||
- `README.md` ;
|
||||
- `crates/games/game-reflex-poc/Cargo.toml` ;
|
||||
- `crates/games/game-snake-poc/Cargo.toml` ;
|
||||
- `docs/architecture/004-INPUT_AND_CONTROLS.md` ;
|
||||
- `docs/plans/001-V0_3_0_WEB_SNAKE_POC_PLAN.md`.
|
||||
|
||||
## Suppressions
|
||||
|
||||
Aucune.
|
||||
|
||||
## Validations applicables
|
||||
|
||||
Audits statiques de préparation :
|
||||
|
||||
```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 deltas history
|
||||
python3 scripts/audit_distribution_layout.py
|
||||
```
|
||||
|
||||
Validation utilisateur demandée :
|
||||
|
||||
```bash
|
||||
cargo fmt --all -- --check
|
||||
cargo check --workspace
|
||||
cargo clippy -p game-snake-poc --all-targets --all-features -- -D warnings
|
||||
cargo clippy -p game-reflex-poc --all-targets --all-features -- -D warnings
|
||||
cargo test -p game-snake-poc
|
||||
cargo test -p game-reflex-poc
|
||||
cargo tree -p game-snake-poc --edges normal
|
||||
cargo tree -p game-reflex-poc --edges normal
|
||||
```
|
||||
|
||||
Les deux `cargo tree` doivent confirmer que les crates de gameplay ne tirent plus `engine-v1-platform-api`. Aucun smoke Desktop n'est requis : ni `engine-v1-sdl`, ni le mapping SDL, ni le runner Snake ne sont modifiés dans cette tranche.
|
||||
|
||||
## Suite
|
||||
|
||||
Après validation de `0-pre.2`, ouvrir `0-pre.3` pour l'adaptation WASM minimale de Snake conformément au plan actif. Aucun frontend Bootstrap/Vite n'est introduit avant `0-pre.4`.
|
||||
118
deltas/0.3.0/0-pre.3.md
Normal file
118
deltas/0.3.0/0-pre.3.md
Normal file
@@ -0,0 +1,118 @@
|
||||
<!-- file: deltas/0.3.0/0-pre.3.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta 0.3.0-0-pre.3
|
||||
|
||||
## Base
|
||||
|
||||
Base requise : `0.3.0-0-pre.2`.
|
||||
|
||||
La validation complète de `0-pre.2` est consignée dans `history/0.3.0/0-pre.2.md`.
|
||||
|
||||
## Objet
|
||||
|
||||
Introduire l'adapter WASM minimal de Snake avant tout frontend navigateur :
|
||||
|
||||
- ajouter `game-snake-poc-wasm` comme crate d'application dédiée ;
|
||||
- réutiliser exclusivement `engine-v1-common` et `game-snake-poc` ;
|
||||
- exposer à `wasm-bindgen` les directions logiques et la scène portable ;
|
||||
- préserver la cadence de simulation en séparant événement d'entrée et `tick()` ;
|
||||
- documenter un chemin Cargo + `wasm-bindgen` direct sans orchestrateur Python ;
|
||||
- ne pas introduire Vite, Bootstrap, DOM, Tauri ou SDL3 dans cette tranche.
|
||||
|
||||
## Version
|
||||
|
||||
La version workspace passe de `0.3.0-0-pre.2` à `0.3.0-0-pre.3`.
|
||||
|
||||
## Adapter Snake WASM
|
||||
|
||||
La nouvelle crate `crates/apps/game-snake-poc-wasm` contient une façade `lib.rs` et un runtime propriétaire séparé.
|
||||
|
||||
`SnakeWasmGame` possède :
|
||||
|
||||
- un `SnakeState` issu de la crate de gameplay ;
|
||||
- un `FixedStepRunner` à pas déterministe de 16 ms ;
|
||||
- un `InputState` en attente pour la prochaine update.
|
||||
|
||||
Les appels `left()`, `right()`, `up()` et `down()` ne font pas avancer la simulation. Ils remplacent la direction logique en attente. `tick()` consomme ensuite cette entrée une fois, la remet à zéro et avance le runner d'une update. La cadence reste ainsi sous la responsabilité du futur host navigateur.
|
||||
|
||||
L'API expose également le score, la longueur, la couleur de fond et les rectangles normalisés de l'`EngineScene`. Le futur frontend `0-pre.4` peut donc dessiner le Canvas sans accéder à la structure interne de Snake.
|
||||
|
||||
## Frontières conservées
|
||||
|
||||
`game-snake-poc-wasm` ne dépend pas de :
|
||||
|
||||
- `engine-v1-platform-api` ;
|
||||
- `engine-v1-sdl` ;
|
||||
- Tauri ;
|
||||
- DOM/Canvas Rust ;
|
||||
- code frontend TypeScript.
|
||||
|
||||
La duplication limitée des getters de scène avec `game-reflex-poc-wasm` est volontairement conservée à ce stade. Une abstraction commune ne sera extraite que si les POC suivants démontrent un besoin partagé suffisamment stable.
|
||||
|
||||
## Documentation et audits
|
||||
|
||||
L'architecture du workspace mentionne désormais l'adapter Snake WASM et le contrat d'entrée précise la file directionnelle consommée par `tick()`.
|
||||
|
||||
L'audit de distribution exige maintenant `crates/apps/game-snake-poc-wasm/Cargo.toml`, portant le nombre de chemins requis de 19 à 20.
|
||||
|
||||
Le plan actif est réconcilié avec la livraison réelle de `0-pre.3`. `docs/development/009-SNAKE_WEB_WASM_BUILD.md` documente le build natif Cargo + `wasm-bindgen`, avec tous les artefacts générés sous `../builds/sasedev-games/`.
|
||||
|
||||
## Historique
|
||||
|
||||
Ajout de `history/0.3.0/0-pre.2.md` avec les résultats réellement fournis par l'utilisateur : audits, formatage, check workspace, Clippy workspace strict, tests Snake/Reflex et graphes de dépendances.
|
||||
|
||||
## Fichiers ajoutés
|
||||
|
||||
- `crates/apps/game-snake-poc-wasm/Cargo.toml` ;
|
||||
- `crates/apps/game-snake-poc-wasm/src/lib.rs` ;
|
||||
- `crates/apps/game-snake-poc-wasm/src/runtime.rs` ;
|
||||
- `crates/apps/game-snake-poc-wasm/unit_tests/runtime.rs` ;
|
||||
- `deltas/0.3.0/0-pre.3.md` ;
|
||||
- `docs/development/009-SNAKE_WEB_WASM_BUILD.md` ;
|
||||
- `history/0.3.0/0-pre.2.md`.
|
||||
|
||||
## Fichiers modifiés
|
||||
|
||||
- `Cargo.toml` ;
|
||||
- `README.md` ;
|
||||
- `docs/architecture/001-WORKSPACE_ARCHITECTURE.md` ;
|
||||
- `docs/000-README.md` ;
|
||||
- `docs/architecture/004-INPUT_AND_CONTROLS.md` ;
|
||||
- `docs/plans/001-V0_3_0_WEB_SNAKE_POC_PLAN.md` ;
|
||||
- `scripts/audit_distribution_layout.py`.
|
||||
|
||||
## Suppressions
|
||||
|
||||
Aucune.
|
||||
|
||||
## Validations applicables
|
||||
|
||||
Audits statiques de préparation :
|
||||
|
||||
```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 deltas history
|
||||
python3 scripts/audit_distribution_layout.py
|
||||
```
|
||||
|
||||
Validation utilisateur demandée :
|
||||
|
||||
```bash
|
||||
cargo fmt --all
|
||||
cargo fmt --all -- --check
|
||||
cargo check --workspace
|
||||
cargo clippy -p game-snake-poc-wasm --all-targets --all-features -- -D warnings
|
||||
cargo test -p game-snake-poc-wasm
|
||||
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
|
||||
cargo tree -p game-snake-poc-wasm --edges normal
|
||||
```
|
||||
|
||||
Le `cargo tree` doit rester limité à `engine-v1-common`, `game-snake-poc`, `wasm-bindgen` et leurs dépendances nécessaires ; aucune dépendance SDL3, Tauri ou `engine-v1-platform-api` ne doit apparaître.
|
||||
|
||||
La commande `wasm-bindgen` doit produire les bindings navigateur sans écrire d'artefact généré dans le dépôt. Aucun build Vite/Bootstrap et aucun smoke navigateur ne sont requis dans cette tranche, car le frontend appartient à `0-pre.4`.
|
||||
|
||||
## Suite
|
||||
|
||||
Après validation de `0-pre.3`, ouvrir `0-pre.4` pour le frontend Web direct Vite/TypeScript, son shell HTML Bootstrap 5, le Canvas et les contrôles clavier/tactiles.
|
||||
56
deltas/0.3.0/0-pre.4.fix.1.md
Normal file
56
deltas/0.3.0/0-pre.4.fix.1.md
Normal file
@@ -0,0 +1,56 @@
|
||||
<!-- file: deltas/0.3.0/0-pre.4.fix.1.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta 0.3.0-0-pre.4.fix.1
|
||||
|
||||
## Objectif
|
||||
|
||||
Fermer les défauts découverts pendant la validation utilisateur de `0-pre.4` sans ouvrir le scope `0-pre.5`.
|
||||
|
||||
## Corrigé
|
||||
|
||||
- suppression de `compilerOptions.baseUrl`, retiré par TypeScript 7, tout en conservant le mapping `paths` et l'alias Vite `@snake-wasm` ;
|
||||
- réintégration de `simplebar` et `resize-observer-polyfill` depuis le template KSP comme dépendances runtime du shell navigateur ;
|
||||
- ajout du Sass SimpleBar KSP-derived et activation de `data-simplebar` sur `app-main` ;
|
||||
- maintien du header et du footer fixes avec scroll interne de la zone centrale lorsque son contenu dépasse la hauteur disponible ;
|
||||
- retrait des contraintes `h-100` internes qui empêchaient le contenu du shell de prendre sa hauteur naturelle ;
|
||||
- correction du plateau Snake de `1 / 1` vers `3 / 5`, cohérente avec la grille logique `12 × 20`, afin de conserver des cellules visuellement carrées ;
|
||||
- conservation du resize haute densité via `devicePixelRatio` à l'intérieur du ratio CSS corrigé ;
|
||||
- correction de la documentation qui classait à tort SimpleBar et le polyfill parmi les dépendances propres à Tauri ;
|
||||
- ajout d'une règle durable sur le scroll shell Web et extension de l'audit de distribution au Sass SimpleBar ;
|
||||
- consignation sous `history/0.3.0/0-pre.4.md` des validations réussies et de l'échec `TS5102` ayant déclenché ce fix.
|
||||
|
||||
## Non modifié
|
||||
|
||||
- gameplay Snake ;
|
||||
- adapter WASM et cadence `tick()` ;
|
||||
- mappings clavier/pointer ;
|
||||
- lifecycle complet, assets, logging et provenance prévus pour `0-pre.5` ;
|
||||
- route de smoke : `http://127.0.0.1:1434/main.html`.
|
||||
|
||||
## Validation demandée
|
||||
|
||||
Depuis la racine :
|
||||
|
||||
```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 Web deltas history
|
||||
python3 scripts/audit_distribution_layout.py
|
||||
cargo check --workspace
|
||||
cargo clippy -p game-snake-poc-wasm --all-targets --all-features -- -D warnings
|
||||
cargo test -p game-snake-poc-wasm
|
||||
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
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Smoke navigateur sur `http://127.0.0.1:1434/main.html` : vérifier clavier, boutons pointer/tactiles, cellules non déformées, scroll SimpleBar lorsque nécessaire et fixation du header/footer.
|
||||
|
||||
## Suite
|
||||
|
||||
Après validation du fix, `0-pre.5` peut fermer lifecycle/resize, assets, logging, provenance runtime et non-régression Desktop SDL3 conformément au plan actif.
|
||||
50
deltas/0.3.0/0-pre.4.fix.2.md
Normal file
50
deltas/0.3.0/0-pre.4.fix.2.md
Normal file
@@ -0,0 +1,50 @@
|
||||
<!-- file: deltas/0.3.0/0-pre.4.fix.2.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta 0.3.0-0-pre.4.fix.2
|
||||
|
||||
## Objectif
|
||||
|
||||
Fermer les deux erreurs TypeScript découvertes pendant la validation utilisateur de `0-pre.4.fix.1`, sans modifier le gameplay ni ouvrir le scope `0-pre.5`.
|
||||
|
||||
## Corrigé
|
||||
|
||||
- `tsconfig.json` résout désormais `@snake-wasm` vers `game_snake_poc_wasm.d.ts`, généré par `wasm-bindgen`, afin que TypeScript consomme les types réels du bridge sans déclaration manuelle dupliquée ;
|
||||
- `vite.config.ts` conserve séparément l'alias runtime vers `game_snake_poc_wasm.js` ;
|
||||
- après validation de `canvas.getContext("2d")`, `game.ts` capture le contexte dans une constante `CanvasRenderingContext2D` non nullable utilisée par le callback de frame ;
|
||||
- consignation sous `history/0.3.0/0-pre.4.fix.1.md` de la gate réellement exécutée et des deux erreurs ayant déclenché ce fix ;
|
||||
- réconciliation du plan actif avec ce second fix de `0-pre.4`.
|
||||
|
||||
## Non modifié
|
||||
|
||||
- gameplay Snake ;
|
||||
- cadence et API du bridge WASM ;
|
||||
- ratio Canvas `3 / 5` ;
|
||||
- SimpleBar, header/footer fixes et shell Bootstrap ;
|
||||
- mappings clavier/pointer ;
|
||||
- lifecycle complet, assets, logging et provenance prévus pour `0-pre.5`.
|
||||
|
||||
## Validation demandée
|
||||
|
||||
Depuis la racine :
|
||||
|
||||
```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 Web deltas history
|
||||
python3 scripts/audit_distribution_layout.py
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
cargo test -p game-snake-poc-wasm
|
||||
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
|
||||
cargo tree -p game-snake-poc-wasm --edges normal
|
||||
(cd Web/game-snake-poc && npm install && npm run build && npm run dev)
|
||||
```
|
||||
|
||||
Smoke navigateur sur `http://127.0.0.1:1434/main.html` : vérifier chargement WASM, clavier, boutons pointer/tactiles, ratio du plateau et scroll SimpleBar lorsque nécessaire.
|
||||
|
||||
## Suite
|
||||
|
||||
Après validation du fix, `0-pre.5` peut fermer lifecycle/resize, assets, logging, provenance runtime et non-régression Desktop SDL3 conformément au plan actif.
|
||||
64
deltas/0.3.0/0-pre.4.fix.3.md
Normal file
64
deltas/0.3.0/0-pre.4.fix.3.md
Normal file
@@ -0,0 +1,64 @@
|
||||
<!-- file: deltas/0.3.0/0-pre.4.fix.3.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta 0.3.0-0-pre.4.fix.3
|
||||
|
||||
## Objectif
|
||||
|
||||
Aligner le scroll SimpleBar du host Snake Web sur le shell réellement utilisé par les applications Desk KSP après validation réussie du build `0-pre.4.fix.2`.
|
||||
|
||||
## Diagnostic
|
||||
|
||||
La comparaison avec `ksp-app-*-desk` confirme que le package et le Sass SimpleBar étaient présents, mais que le conteneur n'était pas structuré comme la référence :
|
||||
|
||||
- KSP garde `app-main` comme conteneur de hauteur bornée et non scrollable ;
|
||||
- un enfant `row h-100` porte la zone centrale ;
|
||||
- `data-simplebar` est attaché à `app-content app-scrollable h-100` ;
|
||||
- `app-scrollable` et `app-content` ont `height: 100%` / `max-height: 100%` ;
|
||||
- `main.ts` importe `resize-observer-polyfill` puis `simplebar` et installe le polyfill global avant l'initialisation de l'application.
|
||||
|
||||
Le point d'entrée TypeScript Snake suit déjà ce dernier contrat ; le défaut se situe donc dans la structure HTML/Sass.
|
||||
|
||||
## Corrigé
|
||||
|
||||
- `data-simplebar` est déplacé de `app-main` vers `app-content app-scrollable h-100` ;
|
||||
- ajout du conteneur `row g-0 h-100 flex-nowrap` comme dans le shell KSP ;
|
||||
- `app-main` reste borné à la hauteur disponible entre header et footer ;
|
||||
- `app-scrollable` et `app-content` portent explicitement `height: 100%` et `max-height: 100%` ;
|
||||
- la règle `GAME-PLATFORM-023` pérennise ce contrat lorsque le shell KSP/SimpleBar est réutilisé ;
|
||||
- `audit_distribution_layout.py` vérifie statiquement que `data-simplebar` reste sur la zone centrale et que le bootstrap TypeScript/Sass requis est présent ;
|
||||
- la documentation frontend et le plan `0.3.0` sont réconciliés ;
|
||||
- `history/0.3.0/0-pre.4.fix.2.md` consigne la validation réussie du build et le défaut visuel restant.
|
||||
|
||||
## Non modifié
|
||||
|
||||
- gameplay Snake ;
|
||||
- bridge WASM et cadence ;
|
||||
- ratio Canvas `3 / 5` ;
|
||||
- mapping clavier/pointer ;
|
||||
- dépendances npm ;
|
||||
- lifecycle complet, assets, logging et provenance prévus pour `0-pre.5`.
|
||||
|
||||
## Validation demandée
|
||||
|
||||
Depuis la racine :
|
||||
|
||||
```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 Web deltas history
|
||||
python3 scripts/audit_distribution_layout.py
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
cargo test -p game-snake-poc-wasm
|
||||
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 && npm run dev)
|
||||
```
|
||||
|
||||
Smoke navigateur sur `http://127.0.0.1:1434/main.html` : réduire la hauteur de fenêtre ou utiliser un viewport assez bas pour forcer le dépassement vertical, puis vérifier que seule la zone centrale défile avec SimpleBar tandis que header et footer restent fixes. Vérifier aussi que Canvas, clavier et boutons pointer restent fonctionnels.
|
||||
|
||||
## Suite
|
||||
|
||||
Après validation du scroll SimpleBar, `0-pre.5` peut ouvrir l'intégration plateforme complète prévue par le plan actif.
|
||||
60
deltas/0.3.0/0-pre.4.md
Normal file
60
deltas/0.3.0/0-pre.4.md
Normal file
@@ -0,0 +1,60 @@
|
||||
<!-- file: deltas/0.3.0/0-pre.4.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta 0.3.0-0-pre.4
|
||||
|
||||
## Objectif
|
||||
|
||||
Introduire le premier host navigateur direct Snake sans élargir encore le scope vers le lifecycle complet, les assets runtime, le logging ou la provenance de `0-pre.5`.
|
||||
|
||||
## Livré
|
||||
|
||||
- création de `Web/game-snake-poc/`, package Vite/TypeScript autonome hors workspace Cargo ;
|
||||
- reprise du template frontend des applications Desk KSP pour la structure `frontend/main.html`, `frontend/sass/`, `frontend/ts/` et le thème Bootstrap/Bootswatch Pulse ;
|
||||
- reprise uniquement des dépendances npm KSP utiles au navigateur direct : Bootstrap 5, Font Awesome, `sass-embedded`, TypeScript, Vite et types associés ;
|
||||
- exclusion volontaire des dépendances Tauri, SimpleBar et tracing spécifiques aux apps Desk ;
|
||||
- consommation des bindings `game-snake-poc-wasm` générés sous `../builds/sasedev-games/game-snake-poc-web/wasm/` ;
|
||||
- Canvas responsive prenant en compte `devicePixelRatio` ;
|
||||
- rendu de l'`EngineScene` normalisée sans dupliquer le gameplay ;
|
||||
- entrées clavier flèches, `WASD`, `ZQSD` et quatre boutons pointer/tactiles ;
|
||||
- état de chargement, score, longueur et retour d'erreur dans le shell ;
|
||||
- cache Vite et distribution frontend maintenus hors dépôt ;
|
||||
- audit de distribution étendu au host Web direct ;
|
||||
- enregistrement sous `history/0.3.0/0-pre.3.md` des validations utilisateur de `0-pre.3`.
|
||||
|
||||
## Hors périmètre
|
||||
|
||||
- lifecycle complet navigateur ;
|
||||
- assets runtime du POC ;
|
||||
- logging structuré Web ;
|
||||
- `RuntimeProvenance` ;
|
||||
- Tauri Snake ;
|
||||
- Android ;
|
||||
- extraction d'une abstraction Web commune non encore justifiée.
|
||||
|
||||
## Validation demandée
|
||||
|
||||
Depuis la racine :
|
||||
|
||||
```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 Web deltas history
|
||||
python3 scripts/audit_distribution_layout.py
|
||||
cargo check --workspace
|
||||
cargo clippy -p game-snake-poc-wasm --all-targets --all-features -- -D warnings
|
||||
cargo test -p game-snake-poc-wasm
|
||||
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
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Smoke navigateur : ouvrir `http://127.0.0.1:1434/main.html`, puis vérifier le chargement WASM, le Canvas, les quatre familles d'entrées prévues et le comportement responsive Desktop/mobile.
|
||||
|
||||
## Suite
|
||||
|
||||
`0-pre.5` ferme l'intégration plateforme du POC : lifecycle/resize complet, assets, logging, provenance runtime et non-régression Desktop SDL3.
|
||||
77
deltas/0.3.0/0-pre.5.fix.1.md
Normal file
77
deltas/0.3.0/0-pre.5.fix.1.md
Normal file
@@ -0,0 +1,77 @@
|
||||
<!-- file: deltas/0.3.0/0-pre.5.fix.1.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta 0.3.0-0-pre.5.fix.1
|
||||
|
||||
## Objectif
|
||||
|
||||
Corriger uniquement l'exposition des assets runtime du host Snake Web en développement, après validation partielle de `0-pre.5`.
|
||||
|
||||
## Défaut confirmé
|
||||
|
||||
`cargo`, WASM, `wasm-bindgen` et le build Vite passent. Sous `vite dev`, le frontend échoue néanmoins avant le démarrage du jeu lors de `fetchJson()` : les routes `common/data/runtime.json` et `game/data/game.json` ne sont pas servies comme attendu.
|
||||
|
||||
Les targets `vite-plugin-static-copy` utilisent des chemins source absolus. Le plugin conserve la structure source par défaut ; le `dest` seul ne constitue donc pas le contrat de route recherché.
|
||||
|
||||
## Correction
|
||||
|
||||
Les deux targets Vite utilisent désormais :
|
||||
|
||||
```text
|
||||
rename: { stripBase: true }
|
||||
```
|
||||
|
||||
Le contrat devient explicitement :
|
||||
|
||||
```text
|
||||
assets/common/data/runtime.json -> /common/data/runtime.json
|
||||
assets/game-snake-poc/data/game.json -> /game/data/game.json
|
||||
```
|
||||
|
||||
Ces routes doivent être identiques sous `vite dev` et dans `dist/`. Aucun asset source n'est dupliqué sous `Web/`.
|
||||
|
||||
## Garde-fou
|
||||
|
||||
`audit_distribution_layout.py` exige désormais `stripBase: true` sur les deux targets, en plus des namespaces `common/data` et `game/data`.
|
||||
|
||||
## Historique
|
||||
|
||||
`history/0.3.0/0-pre.5.md` consigne la validation partielle fournie par l'utilisateur et le défaut runtime exact.
|
||||
|
||||
## Non modifié
|
||||
|
||||
- gameplay Snake ;
|
||||
- adapter WASM/provenance ;
|
||||
- lifecycle/resize ;
|
||||
- logging frontend ;
|
||||
- SimpleBar/Canvas ;
|
||||
- runner Desktop SDL3 ;
|
||||
- ROADMAP et CHANGELOG.
|
||||
|
||||
## Validation demandée
|
||||
|
||||
Depuis la racine :
|
||||
|
||||
```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 Web deltas history
|
||||
python3 scripts/audit_distribution_layout.py
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
cargo test -p engine-v1-platform-api --all-targets --all-features
|
||||
cargo test -p game-snake-poc-wasm --all-targets --all-features
|
||||
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
|
||||
cargo tree -p game-snake-poc-wasm --edges normal
|
||||
(cd Web/game-snake-poc && npm install && npm run build && npm run dev)
|
||||
```
|
||||
|
||||
Smoke sur `http://127.0.0.1:1434/main.html` :
|
||||
|
||||
1. `Assets` doit passer de `chargement…` à `snake / engine-v1` ;
|
||||
2. Snake doit démarrer ;
|
||||
3. la provenance doit quitter `unknown / unknown` dès qu'une classe/device et une entrée sont observées ;
|
||||
4. revalider lifecycle/resize/SimpleBar/Canvas/contrôles ;
|
||||
5. terminer par `cargo run -p game-snake-poc-desktop` pour la non-régression SDL3.
|
||||
118
deltas/0.3.0/0-pre.5.md
Normal file
118
deltas/0.3.0/0-pre.5.md
Normal file
@@ -0,0 +1,118 @@
|
||||
<!-- file: deltas/0.3.0/0-pre.5.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta 0.3.0-0-pre.5
|
||||
|
||||
## Objectif
|
||||
|
||||
Fermer l'intégration plateforme du premier POC Snake Web direct après validation de `0-pre.4.fix.3` : lifecycle/resize navigateur, assets runtime, logging frontend structuré, provenance `Web/Wasm/Browser` et non-régression du runner Desktop SDL3.
|
||||
|
||||
## État précédent validé
|
||||
|
||||
`0-pre.4.fix.3` a été accepté par l'utilisateur le 2026-09-20 : build Vite propre et smoke visuel/fonctionnel conforme, y compris Canvas portrait, contrôles et scroll SimpleBar du shell KSP-derived. Le résultat est consigné sous `history/0.3.0/0-pre.4.fix.3.md`.
|
||||
|
||||
## Lifecycle et resize
|
||||
|
||||
Le host Web ne laisse plus une boucle `requestAnimationFrame` implicite posséder tout le lifecycle :
|
||||
|
||||
- `SnakeWebSession` expose `pause`, `resume`, `renderNow`, `refreshDeviceClass` et `dispose` ;
|
||||
- `visibilitychange` et `pagehide` suspendent les ticks ;
|
||||
- la reprise réinitialise l'origine temporelle et l'accumulateur afin d'éviter un rattrapage massif après un onglet caché ;
|
||||
- `pageshow` reprend et redessine ;
|
||||
- `ResizeObserver` redessine le Canvas et rafraîchit la classe d'appareil sans faire avancer la simulation ;
|
||||
- la destruction de page libère l'instance WASM.
|
||||
|
||||
Le fixed-step gameplay reste dans Rust/WASM et aucun événement lifecycle n'est ajouté à `game-snake-poc`.
|
||||
|
||||
## Assets Web
|
||||
|
||||
Le package Vite déclare `vite-plugin-static-copy` et package explicitement les deux assets-sondes depuis les sources canoniques :
|
||||
|
||||
```text
|
||||
assets/common/data/runtime.json -> common/data/runtime.json
|
||||
assets/game-snake-poc/data/game.json -> game/data/game.json
|
||||
```
|
||||
|
||||
`frontend/ts/assets.ts` charge et valide les deux JSON avant le démarrage WASM. Le shell affiche ensuite un statut d'assets afin que le smoke confirme le chargement réel. Aucune copie source durable n'est créée sous `Web/`.
|
||||
|
||||
## Logging navigateur
|
||||
|
||||
`frontend/ts/logging.ts` centralise les diagnostics Web sous forme d'événements `level / target / action / fields` vers la console du navigateur.
|
||||
|
||||
Ce logging est spécifique au frontend navigateur direct :
|
||||
|
||||
- il ne dépend pas de Tauri ;
|
||||
- il ne remplace pas `tracing` dans le code Rust ;
|
||||
- les runners natifs continuent d'utiliser `game-logging-lib`.
|
||||
|
||||
## Provenance runtime
|
||||
|
||||
`game-snake-poc-wasm` dépend désormais de `engine-v1-platform-api` et conserve une `RuntimeProvenance` réelle.
|
||||
|
||||
Dimensions fixes :
|
||||
|
||||
```text
|
||||
PlatformFamily = Web
|
||||
ExecutionModel = Wasm
|
||||
RuntimeHost = Browser
|
||||
```
|
||||
|
||||
Le host renseigne ensuite la classe `Desktop/Phone/Tablet/Unknown` et le profil d'entrée `Unknown/KeyboardMouse/Touch/Mixed` selon les capacités et inputs observés. Ces dimensions sont exposées par le bridge WASM et affichées dans le shell.
|
||||
|
||||
La crate de gameplay `game-snake-poc` reste sans dépendance plateforme.
|
||||
|
||||
## Règles et documentation
|
||||
|
||||
- `GAME-ASSET-007` fixe le packaging Web `common/` + `game/` sans copie source ;
|
||||
- `GAME-TRACE-005` distingue logging frontend navigateur et tracing Rust ;
|
||||
- `GAME-PLATFORM-024` fixe pause/reprise sans catch-up massif ;
|
||||
- `GAME-PLATFORM-025` fixe la provenance navigateur via `engine-v1-platform-api` ;
|
||||
- l'architecture assets/provenance, la documentation tracing/frontend et les gates sont réconciliées ;
|
||||
- `audit_distribution_layout.py` vérifie désormais les fichiers et branchements statiques de cette intégration.
|
||||
|
||||
## Non modifié
|
||||
|
||||
- règles de gameplay Snake ;
|
||||
- runner Snake Desktop SDL3 ;
|
||||
- moteur SDL3 ;
|
||||
- Android/Tauri ;
|
||||
- ROADMAP et CHANGELOG, réservés à la consolidation prévue par le plan.
|
||||
|
||||
## Validation demandée
|
||||
|
||||
Depuis la racine :
|
||||
|
||||
```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 Web deltas history
|
||||
python3 scripts/audit_distribution_layout.py
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
cargo test -p engine-v1-platform-api --all-targets --all-features
|
||||
cargo test -p game-snake-poc-wasm --all-targets --all-features
|
||||
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
|
||||
cargo tree -p game-snake-poc-wasm --edges normal
|
||||
(cd Web/game-snake-poc && npm install && npm run build && npm run dev)
|
||||
```
|
||||
|
||||
Smoke navigateur sur `http://127.0.0.1:1434/main.html` :
|
||||
|
||||
1. vérifier que `Assets` passe à `snake / engine-v1` avant le statut `Prêt` ;
|
||||
2. vérifier que la provenance affiche `web / browser / wasm / ... / ...` ;
|
||||
3. utiliser clavier/souris puis tactile si disponible et vérifier l'évolution du profil d'entrée (`keyboard-mouse`, `touch` ou `mixed`) ;
|
||||
4. masquer l'onglet quelques secondes puis revenir : Snake ne doit pas accélérer pour rattraper le temps caché ;
|
||||
5. redimensionner la fenêtre : Canvas et provenance device doivent rester cohérents sans saut de gameplay ;
|
||||
6. revalider SimpleBar, clavier et contrôles pointer/tactiles.
|
||||
|
||||
Puis vérifier la non-régression Desktop :
|
||||
|
||||
```bash
|
||||
cargo run -p game-snake-poc-desktop
|
||||
```
|
||||
|
||||
## Suite
|
||||
|
||||
Si cette gate ne révèle ni duplication structurante ni défaut de frontière, la tranche conditionnelle `0-pre.6` est omise et la version peut entrer directement en `2-beta.1`. Sinon, `0-pre.6` ne traite que la correction/extraction prouvée par cette validation.
|
||||
64
deltas/0.3.0/2-beta.1.md
Normal file
64
deltas/0.3.0/2-beta.1.md
Normal file
@@ -0,0 +1,64 @@
|
||||
<!-- file: deltas/0.3.0/2-beta.1.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta 0.3.0-2-beta.1
|
||||
|
||||
## Objectif
|
||||
|
||||
Entrer en beta avec un scope `0.3.0` feature-complete et exécuter une validation large du POC Snake Web direct et de son témoin Desktop SDL3, sans introduire de nouveau comportement.
|
||||
|
||||
## Baseline acceptée
|
||||
|
||||
`0.3.0-0-pre.5.fix.1` est validée : audits, check/Clippy, tests plateforme/WASM, build WASM, build Vite, assets/provenance/inputs dans le navigateur et smoke Desktop SDL3 passent. Aucun défaut structurel ne justifie `0-pre.6`, qui est donc omise.
|
||||
|
||||
## Changements
|
||||
|
||||
- passage de la version workspace à `0.3.0-2-beta.1` ;
|
||||
- passage du package frontend Snake Web au jalon `0.3.0-2-beta.1` ;
|
||||
- ajout de l'historique validé `0-pre.5.fix.1` ;
|
||||
- réconciliation du plan `0.3.0` avec l'omission de `0-pre.6` ;
|
||||
- documentation de la gate beta release Web/Desktop.
|
||||
|
||||
Aucun gameplay, bridge WASM, runtime SDL3, shell HTML/TypeScript ou contrat d'asset n'est modifié par cette tranche.
|
||||
|
||||
## Validation attendue
|
||||
|
||||
Depuis la racine :
|
||||
|
||||
```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 Web deltas history
|
||||
python3 scripts/audit_distribution_layout.py
|
||||
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
cargo test --workspace --all-targets --all-features
|
||||
```
|
||||
|
||||
Build et smoke Desktop Snake release :
|
||||
|
||||
```bash
|
||||
cargo build -p game-snake-poc-desktop --release
|
||||
../builds/sasedev-games/target/release/game-snake-poc-desktop
|
||||
```
|
||||
|
||||
Build WASM release et frontend production :
|
||||
|
||||
```bash
|
||||
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-web/wasm \
|
||||
--out-name game_snake_poc_wasm
|
||||
|
||||
(cd Web/game-snake-poc && npm install && npm run build && npm run preview)
|
||||
```
|
||||
|
||||
Ouvrir `http://127.0.0.1:4174/main.html` puis vérifier : jeu visible, clavier/pointer, ratio Canvas, SimpleBar, assets `snake / engine-v1`, provenance cohérente, resize et pause/reprise sans rattrapage massif après masquage d'onglet.
|
||||
|
||||
## Après validation
|
||||
|
||||
Si cette gate beta est propre, la tranche suivante est `0.3.0-2-beta.2` pour la consolidation documentaire et la transmission : plan, documentation durable, `CHANGELOG.md`, `ROADMAP.md`, history et prompt de la version/session suivante.
|
||||
67
deltas/0.3.0/2-beta.2.fix.1.md
Normal file
67
deltas/0.3.0/2-beta.2.fix.1.md
Normal file
@@ -0,0 +1,67 @@
|
||||
<!-- file: deltas/0.3.0/2-beta.2.fix.1.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta 0.3.0-2-beta.2.fix.1
|
||||
|
||||
## Base requise
|
||||
|
||||
`0.3.0-2-beta.2` validée mécaniquement par l'utilisateur le 2026-09-20.
|
||||
|
||||
## Objectif
|
||||
|
||||
Corriger la transmission documentaire de `2-beta.2` : rendre le prompt `0.3.1` suffisamment autonome pour limiter les rappels conversationnels et les fixes évitables, sans reproduire l'intégralité des règles KSP ni modifier le code/runtime.
|
||||
|
||||
## Changements
|
||||
|
||||
- enrichissement de `prompts/003-V0_3_1_START_PROMPT.md` avec ordre de lecture, handoff `0.3.0`, cadrage `pre.1`, invariants Tauri/Android/WASM, documentation, commandes, validations, forecast et condition de fin de session ;
|
||||
- ajout de `docs/rules/PROMPT_STRUCTURE.md`, inspiré du principe KSP de prompt autonome mais volontairement plus compact ;
|
||||
- ajout de règles explicites sur le rôle de `deltas/`/`history/`, le timing `ROADMAP`/`CHANGELOG`/prompt suivant et la séparation des validations utilisateur ;
|
||||
- ajout d'une politique `DOC-CRATE-*` pour décider utilement de `README.md`/`USAGE.md` sans créer de fichiers cérémoniels ;
|
||||
- clarification du cycle du prompt suivant : rédaction pendant la consolidation, vérification/complément à la première RC gelée ;
|
||||
- clarification du versionnement des fixes strictement documentaires : le delta porte `.fix.1` mais `workspace.package.version` et les packages runtime restent `0.3.0-2-beta.2` ;
|
||||
- ajout de `history/0.3.0/2-beta.2.md` avec les résultats réellement validés et le motif humain du fix ;
|
||||
- réconciliation du plan `0.3.0` avec ce correctif de transmission.
|
||||
|
||||
`CHANGELOG.md` et `ROADMAP.md` ne sont pas modifiés : le fix ne change ni la publication candidate ni le scope produit.
|
||||
|
||||
## Fichiers ajoutés
|
||||
|
||||
```text
|
||||
docs/rules/PROMPT_STRUCTURE.md
|
||||
history/0.3.0/2-beta.2.md
|
||||
deltas/0.3.0/2-beta.2.fix.1.md
|
||||
```
|
||||
|
||||
## Fichiers modifiés
|
||||
|
||||
```text
|
||||
RULES.md
|
||||
docs/000-README.md
|
||||
docs/plans/001-V0_3_0_WEB_SNAKE_POC_PLAN.md
|
||||
docs/rules/RULES_DOCUMENTATION.md
|
||||
docs/rules/RULES_SESSION_PLANNING.md
|
||||
docs/rules/VERSION_WORKFLOW.md
|
||||
prompts/003-V0_3_1_START_PROMPT.md
|
||||
```
|
||||
|
||||
## Fichiers supprimés
|
||||
|
||||
Aucun.
|
||||
|
||||
## Version technique
|
||||
|
||||
Ce correctif est strictement documentaire. Conformément à `VER-DOCFIX-001`, il ne modifie ni `workspace.package.version` ni la version du package Web : la version technique reste `0.3.0-2-beta.2`.
|
||||
|
||||
## Validation attendue
|
||||
|
||||
```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/npm ni smoke n'est requis pour ce fix : aucun fichier consommé par le build/runtime n'est modifié.
|
||||
|
||||
## Après validation
|
||||
|
||||
Si la revue humaine du prompt enrichi est satisfaisante, ouvrir `0.3.0-3-rc.1` et appliquer la matrice RC. La RC vérifie/complète le prompt `0.3.1`, écrit l'entrée RC du `CHANGELOG.md` et ne rouvre pas le scope fonctionnel.
|
||||
66
deltas/0.3.0/2-beta.2.fix.2.md
Normal file
66
deltas/0.3.0/2-beta.2.fix.2.md
Normal file
@@ -0,0 +1,66 @@
|
||||
<!-- file: deltas/0.3.0/2-beta.2.fix.2.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta 0.3.0-2-beta.2.fix.2
|
||||
|
||||
## Base requise
|
||||
|
||||
`0.3.0-2-beta.2.fix.1`.
|
||||
|
||||
## Objectif
|
||||
|
||||
Finaliser la gouvernance des commandes et des validations transmise au prompt `0.3.1`, afin d'éviter les gates surdimensionnées, les logs pollués et les workflows Tauri incorrects.
|
||||
|
||||
Ce correctif est strictement documentaire. Il ne modifie aucun code, manifeste runtime, dépendance, configuration de build ni version technique.
|
||||
|
||||
## Décisions consolidées
|
||||
|
||||
- un fix strictement documentaire ne modifie aucune version Cargo/npm/Gradle/Tauri/Android ou autre version consommée par le runtime/build ;
|
||||
- tout changement de code Rust, manifeste Cargo, feature ou dépendance Rust déclenche `cargo fmt --all`, `cargo fmt --all -- --check`, `cargo check --workspace` puis `cargo clippy --workspace --all-targets --all-features -- -D warnings` ;
|
||||
- les audits Python sont sélectionnés selon les fichiers réellement touchés ;
|
||||
- `cargo test -p <crate> --all-targets --all-features` est la stratégie normale ;
|
||||
- `cargo test --workspace --all-targets --all-features` est réservé à un ou quelques jalons explicitement planifiés ou à une portée transverse incertaine ;
|
||||
- `cargo tree` n'est exécuté que si les dépendances/features changent ou qu'un diagnostic de frontière le justifie ;
|
||||
- toute commande nécessitant un changement de répertoire utilise `(cd <dir> && <commande>)` ;
|
||||
- dans une app Tauri, npm sert à gérer les dépendances frontend ; les smokes passent par `cargo tauri dev` et le packaging final/prefinal par `cargo tauri build`, les hooks Tauri possédant Vite/TypeScript/WASM.
|
||||
|
||||
## Fichiers ajoutés
|
||||
|
||||
```text
|
||||
history/0.3.0/2-beta.2.fix.1.md
|
||||
deltas/0.3.0/2-beta.2.fix.2.md
|
||||
```
|
||||
|
||||
## Fichiers modifiés
|
||||
|
||||
```text
|
||||
docs/plans/001-V0_3_0_WEB_SNAKE_POC_PLAN.md
|
||||
docs/rules/PROMPT_STRUCTURE.md
|
||||
docs/rules/RULES_COMMANDS.md
|
||||
docs/rules/RULES_SESSION_PLANNING.md
|
||||
docs/rules/RULES_VALIDATION_MATRIX.md
|
||||
docs/rules/VERSION_WORKFLOW.md
|
||||
prompts/003-V0_3_1_START_PROMPT.md
|
||||
```
|
||||
|
||||
## Fichiers supprimés
|
||||
|
||||
Aucun.
|
||||
|
||||
## Version technique
|
||||
|
||||
Aucune version technique n'est modifiée. La workspace et le package Web restent `0.3.0-2-beta.2`.
|
||||
|
||||
## Validation attendue
|
||||
|
||||
Les seuls fichiers touchés sont Markdown. L'audit applicable est donc :
|
||||
|
||||
```bash
|
||||
python3 scripts/audit_markdown_tables.py docs prompts deltas history
|
||||
```
|
||||
|
||||
Aucun `cargo fmt`, `cargo check`, Clippy, test Cargo, `cargo tree`, audit de distribution, npm, Tauri ou smoke n'est requis pour ce correctif documentaire.
|
||||
|
||||
## Après validation
|
||||
|
||||
Si la revue humaine confirme ces règles, ouvrir `0.3.0-3-rc.1`. La RC appliquera la matrice finale, écrira l'entrée RC du `CHANGELOG.md` et vérifiera une dernière fois le prompt `0.3.1` sans rouvrir le scope fonctionnel.
|
||||
45
deltas/0.3.0/2-beta.2.md
Normal file
45
deltas/0.3.0/2-beta.2.md
Normal file
@@ -0,0 +1,45 @@
|
||||
<!-- file: deltas/0.3.0/2-beta.2.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta 0.3.0-2-beta.2
|
||||
|
||||
## Objectif
|
||||
|
||||
Consolider la version feature-complete après validation de `2-beta.1`, préparer le gel RC et transmettre un contexte autonome à `0.3.1`, sans modifier le comportement runtime.
|
||||
|
||||
## Baseline acceptée
|
||||
|
||||
`0.3.0-2-beta.1` est validée : audits, format/check/Clippy, 34 tests workspace, Desktop Snake release et Web/WASM release passent.
|
||||
|
||||
## Changements
|
||||
|
||||
- passage de la version workspace et du package Web à `0.3.0-2-beta.2` ;
|
||||
- ajout de `history/0.3.0/2-beta.1.md` ;
|
||||
- classement des lignes `0.3.0` réellement livrées dans `ROADMAP.md` ;
|
||||
- ajout d'une baseline architecturale consolidée du POC Snake Web direct ;
|
||||
- ajout d'une matrice RC spécifique à `0.3.0` ;
|
||||
- réconciliation de l'étude `pre.1` avec le contrat autoritaire des archives de tag ;
|
||||
- mise à jour du plan actif avec le résultat beta ;
|
||||
- ajout du prompt `003-V0_3_1_START_PROMPT.md` pour le second host Snake Tauri Android.
|
||||
|
||||
`CHANGELOG.md` est revu mais ne reçoit pas d'entrée beta : `DOC-CHG-002` et `DOC-CHG-003` réservent la synthèse publiée aux RC et stables. La matière de la future entrée RC est consolidée dans les documents durables de cette tranche.
|
||||
|
||||
## Validation attendue
|
||||
|
||||
```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 Web deltas history
|
||||
python3 scripts/audit_distribution_layout.py
|
||||
|
||||
cargo check --workspace
|
||||
(cd Web/game-snake-poc && npm install && npm run build)
|
||||
```
|
||||
|
||||
Aucun test/smoke complet n'est requis par ce delta documentaire + métadonnées : `2-beta.1` vient de valider les artefacts release, et aucun code/runtime n'est modifié.
|
||||
|
||||
## Après validation
|
||||
|
||||
Si cette consolidation est acceptée, produire `0.3.0-3-rc.1` : gel fonctionnel, entrée RC du `CHANGELOG.md`, historique `2-beta.2`, réexécution de la matrice RC et vérification finale du prompt `0.3.1`.
|
||||
88
deltas/0.3.0/3-rc.1.md
Normal file
88
deltas/0.3.0/3-rc.1.md
Normal file
@@ -0,0 +1,88 @@
|
||||
<!-- file: deltas/0.3.0/3-rc.1.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta 0.3.0-3-rc.1
|
||||
|
||||
## Base requise
|
||||
|
||||
`0.3.0-2-beta.2.fix.2`.
|
||||
|
||||
Cette base a été validée par revue humaine et audit Markdown proportionnel au correctif documentaire.
|
||||
|
||||
## Objectif
|
||||
|
||||
Créer la candidate de publication `0.3.0` sans rouvrir le scope fonctionnel.
|
||||
|
||||
## Gel RC
|
||||
|
||||
Le scope `0.3.0` est gelé. Cette tranche n'ajoute :
|
||||
|
||||
- aucune fonctionnalité ;
|
||||
- aucune capability ;
|
||||
- aucun refactor architectural ;
|
||||
- aucune dépendance ;
|
||||
- aucun changement de gameplay ou de runtime.
|
||||
|
||||
Seuls les correctifs autorisés par `VER-RC-*` pourront suivre sous `3-rc.1.fix.N`.
|
||||
|
||||
## Changements
|
||||
|
||||
- passage de `workspace.package.version` à `0.3.0-3-rc.1` ;
|
||||
- passage du package Web Snake à `0.3.0-3-rc.1` ;
|
||||
- affichage de la candidate courante dans `README.md` ;
|
||||
- création de l'entrée RC `0.3.0-3-rc.1` dans `CHANGELOG.md` ;
|
||||
- enregistrement de la validation `2-beta.2.fix.2` sous `history/0.3.0/` ;
|
||||
- réconciliation du plan `0.3.0` avec l'ouverture de la RC ;
|
||||
- revue finale de `prompts/003-V0_3_1_START_PROMPT.md` : aucune modification supplémentaire requise.
|
||||
|
||||
Les métadonnées Android historiques restent inchangées : `0.3.0` ne livre pas un nouveau host Android. Le package Tauri Reflex historique reste également hors scope.
|
||||
|
||||
## Validation RC
|
||||
|
||||
Appliquer `docs/testing/004-V0_3_0_RC_VALIDATION_MATRIX.md`.
|
||||
|
||||
### Gate workspace
|
||||
|
||||
```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 Web deltas history
|
||||
python3 scripts/audit_distribution_layout.py
|
||||
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
cargo test --workspace --all-targets --all-features
|
||||
```
|
||||
|
||||
Le test workspace complet est volontairement exécuté à ce jalon RC final. Aucun `cargo tree` n'est requis puisque les dépendances/features ne changent pas.
|
||||
|
||||
### Desktop Snake release
|
||||
|
||||
```bash
|
||||
cargo build -p game-snake-poc-desktop --release
|
||||
../builds/sasedev-games/target/release/game-snake-poc-desktop
|
||||
```
|
||||
|
||||
Critères : démarrage, rendu, contrôles et arrêt propre.
|
||||
|
||||
### Web/WASM release
|
||||
|
||||
```bash
|
||||
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-web/wasm \
|
||||
--out-name game_snake_poc_wasm
|
||||
|
||||
(cd Web/game-snake-poc && npm install && npm run build && npm run preview)
|
||||
```
|
||||
|
||||
Ouvrir `http://127.0.0.1:4174/main.html` et confirmer Canvas, inputs, SimpleBar, assets, provenance, resize, lifecycle et absence d'erreur runtime bloquante.
|
||||
|
||||
## Après validation
|
||||
|
||||
Si la gate RC est propre et qu'aucun correctif n'est nécessaire, la promotion vers `0.3.0` est mécanique : versions stables, entrée stable du `CHANGELOG.md`, historique RC et delta de release, sans nouveau scope.
|
||||
54
deltas/0.3.0/rel.001.md
Normal file
54
deltas/0.3.0/rel.001.md
Normal file
@@ -0,0 +1,54 @@
|
||||
<!-- file: deltas/0.3.0/rel.001.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta 0.3.0 — release stable
|
||||
|
||||
## Base
|
||||
|
||||
Base validée : `0.3.0-3-rc.1`.
|
||||
|
||||
## Objet
|
||||
|
||||
Promouvoir mécaniquement la candidate validée vers `0.3.0` sans introduire de nouveau comportement.
|
||||
|
||||
## Changements
|
||||
|
||||
La release stable :
|
||||
|
||||
- passe `workspace.package.version` de `0.3.0-3-rc.1` à `0.3.0` ;
|
||||
- passe le package frontend Web Snake de `0.3.0-3-rc.1` à `0.3.0` ;
|
||||
- positionne `README.md` sur la stable `0.3.0` et indique `0.3.1` comme prochaine version planifiée mais non démarrée ;
|
||||
- ajoute l'entrée stable `0.3.0` dans `CHANGELOG.md` ;
|
||||
- enregistre la validation effective de la RC dans `history/0.3.0/3-rc.1.md` ;
|
||||
- clôt le plan `0.3.0` et réconcilie la baseline architecturale avec l'état effectivement publié.
|
||||
|
||||
Les métadonnées Android et le package frontend Reflex/Tauri ne sont pas modifiés : ils n'appartiennent pas au chemin de distribution ajouté par `0.3.0`.
|
||||
|
||||
Le prompt `prompts/003-V0_3_1_START_PROMPT.md` est conservé tel que validé en RC.
|
||||
|
||||
## Frontière de release
|
||||
|
||||
Aucun changement de gameplay, de Rust source, de dépendance, de build frontend, d'architecture ou de capability n'est introduit après la RC.
|
||||
|
||||
## Validation
|
||||
|
||||
La gate RC complète a déjà été validée sur un état fonctionnellement identique. La promotion stable ne requiert donc que les gates proportionnelles au changement de version et à la documentation :
|
||||
|
||||
```bash
|
||||
python3 scripts/audit_rust_workspace_rules.py
|
||||
python3 scripts/audit_markdown_tables.py README.md CHANGELOG.md docs deltas history
|
||||
|
||||
cargo check --workspace
|
||||
|
||||
(cd Web/game-snake-poc && npm install && npm run build)
|
||||
```
|
||||
|
||||
`cargo fmt`, Clippy, la suite workspace complète, `cargo tree`, l'audit de distribution et les smokes ne sont pas répétés : cette promotion ne touche ni code Rust, ni dépendance, ni layout de distribution, et ces gates ont déjà été validées sur `0.3.0-3-rc.1` fonctionnellement identique.
|
||||
|
||||
## Publication
|
||||
|
||||
Après validation de ce delta :
|
||||
|
||||
- commit de release ;
|
||||
- tag stable `v0.3.0` ;
|
||||
- prochaine session ouverte uniquement à partir de la stable taggée `v0.3.0` et de `prompts/003-V0_3_1_START_PROMPT.md`.
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/000-README.md -->
|
||||
<!-- version: 21 -->
|
||||
<!-- version: 27 -->
|
||||
|
||||
# Documentation games.sasedev
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
- [`ideas/000-README.md`](ideas/000-README.md) — rôle des idées non engagées et règles de maturation.
|
||||
- [`studies/000-README.md`](studies/000-README.md) — rôle des études comparatives non normatives.
|
||||
|
||||
## Plans
|
||||
|
||||
- [`plans/000-README.md`](plans/000-README.md) — plans vivants des versions ; le plan actif porte notamment le découpage prévisionnel souple des prereleases.
|
||||
- [`plans/001-V0_3_0_WEB_SNAKE_POC_PLAN.md`](plans/001-V0_3_0_WEB_SNAKE_POC_PLAN.md) — plan actif de `0.3.0`, premier POC Snake Web direct.
|
||||
|
||||
## Architecture
|
||||
|
||||
- [`architecture/001-WORKSPACE_ARCHITECTURE.md`](architecture/001-WORKSPACE_ARCHITECTURE.md) — workspace, générations de moteur, jeux, runners, assets et Android.
|
||||
@@ -51,7 +56,7 @@
|
||||
|
||||
## Règles
|
||||
|
||||
Voir [`../RULES.md`](../RULES.md), notamment [`rules/RULES_DOCUMENTATION.md`](rules/RULES_DOCUMENTATION.md) pour la gouvernance documentaire, [`rules/RULES_COMMANDS.md`](rules/RULES_COMMANDS.md) pour la politique d'exécution, [`rules/RULES_VALIDATION_MATRIX.md`](rules/RULES_VALIDATION_MATRIX.md) pour la matrice des gates, [`rules/RULES_SESSION_PLANNING.md`](rules/RULES_SESSION_PLANNING.md) pour le cadrage des sessions et [`rules/RULES_SERVER_HOSTING.md`](rules/RULES_SERVER_HOSTING.md) pour la portabilité d'auto-hébergement.
|
||||
Voir [`../RULES.md`](../RULES.md), notamment [`rules/RULES_DOCUMENTATION.md`](rules/RULES_DOCUMENTATION.md) pour la gouvernance documentaire, [`rules/RULES_COMMANDS.md`](rules/RULES_COMMANDS.md) pour la politique d'exécution, [`rules/RULES_VALIDATION_MATRIX.md`](rules/RULES_VALIDATION_MATRIX.md) pour la matrice des gates, [`rules/RULES_SESSION_PLANNING.md`](rules/RULES_SESSION_PLANNING.md) pour le cadrage des sessions, [`rules/PROMPT_STRUCTURE.md`](rules/PROMPT_STRUCTURE.md) pour le contrat des prompts de reprise et [`rules/RULES_SERVER_HOSTING.md`](rules/RULES_SERVER_HOSTING.md) pour la portabilité d'auto-hébergement.
|
||||
|
||||
## Validation
|
||||
|
||||
@@ -63,11 +68,15 @@ Voir [`../RULES.md`](../RULES.md), notamment [`rules/RULES_DOCUMENTATION.md`](ru
|
||||
- [`testing/001-TEST_ARCHITECTURE.md`](testing/001-TEST_ARCHITECTURE.md) — séparation `unit_tests/` / `tests/`, tests ciblés et tracing de test.
|
||||
- [`testing/002-BETA_VALIDATION_MATRIX.md`](testing/002-BETA_VALIDATION_MATRIX.md) — matrice beta Desktop SDL3, Tauri/WASM et Android multi-appareils.
|
||||
- [`testing/003-RC_VALIDATION_MATRIX.md`](testing/003-RC_VALIDATION_MATRIX.md) — matrice RC de reproductibilité, packaging final et promotion vers `0.1.0`.
|
||||
- [`testing/004-V0_3_0_RC_VALIDATION_MATRIX.md`](testing/004-V0_3_0_RC_VALIDATION_MATRIX.md) — gate RC spécifique au POC Snake Web direct et à son témoin Desktop SDL3.
|
||||
- [`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.
|
||||
- [`development/006-ANDROID_RUST_NATIVE_BUILD.md`](development/006-ANDROID_RUST_NATIVE_BUILD.md) — build `cdylib` Rust Android, cargo-ndk, packaging `jniLibs` et symbole `SDL_main`.
|
||||
- [`development/007-ANDROID_JNI_BRIDGE.md`](development/007-ANDROID_JNI_BRIDGE.md) — frontière Java/JNI minimale, version de contrat et séparation avec l'input SDL3.
|
||||
- [`development/008-WASM_TAURI_POC.md`](development/008-WASM_TAURI_POC.md) — baseline historique Reflex Tauri/WebAssembly et génération WASM associée.
|
||||
- [`development/009-SNAKE_WEB_WASM_BUILD.md`](development/009-SNAKE_WEB_WASM_BUILD.md) — build Cargo + `wasm-bindgen` natif de l'adapter Snake pour le navigateur direct.
|
||||
- [`development/010-SNAKE_WEB_FRONTEND.md`](development/010-SNAKE_WEB_FRONTEND.md) — host Web direct Snake sous Vite/TypeScript, shell Bootstrap 5, Canvas, lifecycle, assets, provenance et contrôles clavier/tactiles.
|
||||
|
||||
## Historique validé
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/architecture/001-WORKSPACE_ARCHITECTURE.md -->
|
||||
<!-- version: 5 -->
|
||||
<!-- version: 7 -->
|
||||
|
||||
# Architecture du workspace
|
||||
|
||||
@@ -22,7 +22,8 @@ games.sasedev/
|
||||
│ ├── game-reflex-poc-desktop/
|
||||
│ ├── game-snake-poc-desktop/
|
||||
│ ├── game-reflex-poc-tauri/
|
||||
│ └── game-reflex-poc-wasm/
|
||||
│ ├── game-reflex-poc-wasm/
|
||||
│ └── game-snake-poc-wasm/
|
||||
├── assets/
|
||||
│ ├── common/
|
||||
│ ├── game-reflex-poc/
|
||||
@@ -31,6 +32,8 @@ games.sasedev/
|
||||
│ ├── common/
|
||||
│ ├── game-reflex-poc/
|
||||
│ └── game-snake-poc/
|
||||
├── Web/
|
||||
│ └── game-snake-poc/
|
||||
├── docs/
|
||||
├── deltas/
|
||||
├── prompts/
|
||||
@@ -69,15 +72,12 @@ Le runtime devra conserver une distinction logique entre ressources communes et
|
||||
|
||||
Chaque crate de jeu reste une bibliothèque. Une crate binaire Desktop séparée sous `crates/apps/` la consomme pour permettre les itérations locales rapides. Cette séparation évite d’introduire `main`, des choix de plateforme ou du code de lancement dans le gameplay réutilisable.
|
||||
|
||||
## Variante Tauri / WebAssembly
|
||||
## Adapters WebAssembly et variante Tauri
|
||||
|
||||
La variante Tauri est distincte du runner SDL3 natif.
|
||||
Les adapters WASM sont distincts des runners SDL3 natifs et ne déplacent aucune règle de gameplay hors des crates de jeu.
|
||||
|
||||
`game-reflex-poc-tauri` porte deux faces du même launcher :
|
||||
`game-reflex-poc-wasm` adapte le POC Reflex à `wasm-bindgen` pour le host Tauri/WebView existant. `game-snake-poc-wasm` adapte séparément Snake pour le premier host navigateur direct de `0.3.0`. Dans les deux cas, l'adapter expose l'état et la scène portable ; il ne possède pas les règles du jeu.
|
||||
|
||||
- une bibliothèque `wasm32-unknown-unknown` qui adapte `game-reflex-poc` à `wasm-bindgen` ;
|
||||
- un binaire natif Tauri qui héberge la WebView locale.
|
||||
`game-reflex-poc-tauri` reste le binaire natif Tauri qui héberge la WebView Reflex locale. Son frontend Vite/TypeScript pilote un Canvas et appelle l'adapter Reflex WASM. La crate Tauri suit le modèle des apps Desk KSP : façade `lib.rs`, pont `tauri.rs`, modules propriétaires séparés et frontend local à la crate.
|
||||
|
||||
Le frontend statique sous `Tauri/game-reflex-poc/frontend/` pilote un Canvas et appelle l'adaptateur WASM. Les règles Reflex restent exclusivement dans `game-reflex-poc`.
|
||||
|
||||
La crate Tauri suit le modèle des apps Desk KSP : façade `lib.rs`, pont `tauri.rs`, modules propriétaires séparés et frontend Vite/TypeScript local à la crate.
|
||||
Le host Web Snake direct réside sous `Web/game-snake-poc/`. Ce package Vite/TypeScript consomme `game-snake-poc-wasm`, reprend la structure HTML/Sass/TypeScript et le thème Bootstrap/Bootswatch des applications Desk KSP sans dépendre de Tauri, traduit clavier/tactile vers les quatre directions logiques et dessine l'`EngineScene` dans un Canvas. Il reste extérieur au workspace Cargo et ne contient aucune règle de gameplay.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/architecture/004-INPUT_AND_CONTROLS.md -->
|
||||
<!-- version: 7 -->
|
||||
<!-- version: 9 -->
|
||||
|
||||
# Abstraction des entrées et contrôles
|
||||
|
||||
@@ -97,6 +97,22 @@ Pour souris et tactile :
|
||||
|
||||
Reflex conserve son impulsion `Primary` sur `Down` et reste donc indépendant de la reconnaissance du swipe.
|
||||
|
||||
## Baseline Snake portable `0.3.0`
|
||||
|
||||
La crate `game-snake-poc` consomme uniquement le contrat générique `engine-v1-common` pour son gameplay. Elle ne dépend pas de `engine-v1-platform-api`, de SDL3, du DOM ou d'un type de périphérique concret.
|
||||
|
||||
Le contrat d'entrée Snake retenu pour le premier POC Web est volontairement minimal :
|
||||
|
||||
- `Left`, `Right`, `Up` et `Down` pilotent la direction ;
|
||||
- le rejet d'un demi-tour opposé reste une règle du gameplay Snake ;
|
||||
- `Primary`, `Secondary`, `Pause` et le pointeur normalisé ne sont pas requis par le gameplay Snake actuel ;
|
||||
- le host traduit clavier, swipe ou boutons virtuels vers les mêmes actions directionnelles ;
|
||||
- le rendu reste exposé par `EngineGame::scene` sous forme d'`EngineScene`, sans dépendance au Canvas ou à SDL3.
|
||||
|
||||
L'adapter WASM de `0-pre.3` adapte ce contrat existant plutôt que créer un second modèle d'entrée ou de rendu propre au Web. Il mémorise au plus une direction logique en attente ; `tick()` la consomme pour le prochain update puis remet l'entrée en attente à zéro. Un événement clavier ou tactile ne fait donc pas avancer la simulation à lui seul.
|
||||
|
||||
Le host Web reste responsable de transformer ses événements physiques ou widgets en appels `left`, `right`, `up` ou `down`, puis de piloter la cadence des `tick()`. Les besoins de provenance, monétisation ou autres services plateforme appartiennent au host/launcher et ne justifient pas une dépendance plateforme inutilisée dans la crate de gameplay.
|
||||
|
||||
## Requête de sortie
|
||||
|
||||
La plateforme ne décide plus directement de terminer un jeu. Elle traduit l'événement physique en `QuitRequest` :
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/architecture/005-ASSET_ARCHITECTURE.md -->
|
||||
<!-- version: 3 -->
|
||||
<!-- version: 4 -->
|
||||
|
||||
# Architecture des assets
|
||||
|
||||
@@ -92,3 +92,16 @@ assets/game/...
|
||||
```
|
||||
|
||||
Les répertoires `build/generated/` restent des artefacts jetables.
|
||||
|
||||
## Web navigateur direct
|
||||
|
||||
Le POC Snake Web valide le même espace logique sans copier les sources dans `Web/`. Vite package explicitement les assets nécessaires depuis `assets/` vers :
|
||||
|
||||
```text
|
||||
dist/common/data/runtime.json
|
||||
dist/game/data/game.json
|
||||
```
|
||||
|
||||
Le serveur Vite de développement expose les mêmes URL runtime. Le frontend charge donc `common://data/runtime.json` et `game://data/game.json` sous leurs chemins de distribution `./common/data/runtime.json` et `./game/data/game.json`, puis valide leur schéma avant de démarrer la session.
|
||||
|
||||
Cette première intégration ne transforme pas encore `game-assets-lib` en loader navigateur : la librairie Rust reste responsable de la validation/résolution de chemins physiques pour les hosts qui disposent d'un filesystem, tandis que Vite possède le packaging Web. Une abstraction commune ne sera extraite que si plusieurs hosts en ont réellement besoin.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/architecture/010-RUNTIME_PROVENANCE.md -->
|
||||
<!-- version: 1 -->
|
||||
<!-- version: 2 -->
|
||||
|
||||
# Provenance d'environnement d'exécution
|
||||
|
||||
@@ -72,3 +72,17 @@ L'identité joueur reste orthogonale. Un score pourra appartenir à un utilisate
|
||||
La provenance V1 décrit des catégories techniques générales. Elle ne requiert ni modèle précis de téléphone, ni identifiant matériel, ni adresse réseau.
|
||||
|
||||
Un besoin futur de diagnostic plus fin devra être ajouté explicitement plutôt que d'élargir silencieusement cette structure.
|
||||
|
||||
## POC Snake Web direct
|
||||
|
||||
À partir de `0.3.0-0-pre.5`, `game-snake-poc-wasm` consomme réellement `engine-v1-platform-api` et conserve une `RuntimeProvenance` pour la session navigateur. Les dimensions fixes du host sont :
|
||||
|
||||
```text
|
||||
PlatformFamily = Web
|
||||
ExecutionModel = Wasm
|
||||
RuntimeHost = Browser
|
||||
```
|
||||
|
||||
Le frontend observe la classe d'appareil à partir des capacités de pointeur et de la taille logique de l'écran sans collecter de modèle matériel. Le profil d'entrée commence à `Unknown`, devient `KeyboardMouse` ou `Touch` lors de l'utilisation réelle et passe à `Mixed` si les deux familles sont observées pendant la même session.
|
||||
|
||||
Cette provenance est affichée dans le shell et émise dans les diagnostics frontend afin de rendre le smoke vérifiable. Elle reste descriptive et ne modifie ni le gameplay ni le score.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/architecture/015-PLATFORM_POC_ARCHITECTURE.md -->
|
||||
<!-- version: 1 -->
|
||||
<!-- version: 2 -->
|
||||
|
||||
# Architecture des POC plateforme et réseau
|
||||
|
||||
@@ -11,12 +11,12 @@ Snake est le jeu-sonde principal.
|
||||
|
||||
## POC plateforme prioritaires
|
||||
|
||||
Première vague :
|
||||
Première vague, réordonnée à partir du résultat réel de `0.3.0` :
|
||||
|
||||
- Tauri Android + Snake ;
|
||||
- Web navigateur direct + Snake ;
|
||||
- Tauri Desktop + Snake ;
|
||||
- build Android multi-ABI avec outils natifs.
|
||||
- Web navigateur direct + Snake — validé par `0.3.0` ;
|
||||
- Tauri Android + Snake — prochain host prévu par `0.3.1` ;
|
||||
- Tauri Desktop + Snake — prévu ensuite pour éprouver la factorisation WebView ;
|
||||
- build Android multi-ABI avec outils natifs — tranche dédiée après les POC WebView.
|
||||
|
||||
Plateformes supplémentaires lorsque l'environnement existe : Windows SDL natif, macOS SDL natif et iOS SDL natif.
|
||||
|
||||
@@ -38,6 +38,8 @@ Un POC sert à identifier duplication, adapters manquants, capability réellemen
|
||||
|
||||
Une abstraction n'est pas extraite avant observation d'un besoin concret.
|
||||
|
||||
Le POC Web direct `0.3.0` n'a pas justifié d'extraire prématurément un adapter WASM commun entre Reflex et Snake : les deux adapters spécifiques restent acceptés. Le second host Snake doit d'abord fournir un second besoin réel avant toute factorisation.
|
||||
|
||||
## Relation avec Uroburas
|
||||
|
||||
Les résultats des POC `0.3.x` déterminent les choix techniques conservés pour la trajectoire Uroburas `0.4.x`.
|
||||
|
||||
91
docs/architecture/018-V0_3_0_WEB_SNAKE_BASELINE.md
Normal file
91
docs/architecture/018-V0_3_0_WEB_SNAKE_BASELINE.md
Normal file
@@ -0,0 +1,91 @@
|
||||
<!-- file: docs/architecture/018-V0_3_0_WEB_SNAKE_BASELINE.md -->
|
||||
<!-- version: 2 -->
|
||||
|
||||
# Baseline consolidée 0.3.0 — Snake Web direct
|
||||
|
||||
## Statut
|
||||
|
||||
Ce document consolide la baseline stable `0.3.0` du premier POC plateforme de la série `0.3.x`. La RC `0.3.0-3-rc.1` a été validée sans correctif supplémentaire ; cet état sert désormais de base au second host Snake prévu en `0.3.1`.
|
||||
|
||||
## Chaîne validée
|
||||
|
||||
Le chemin Web direct retenu est :
|
||||
|
||||
```text
|
||||
game-snake-poc
|
||||
↓
|
||||
game-snake-poc-wasm
|
||||
↓ wasm-bindgen --target web
|
||||
Web/game-snake-poc
|
||||
↓
|
||||
Vite / TypeScript / Bootstrap 5 / Canvas
|
||||
```
|
||||
|
||||
`game-snake-poc` reste indépendant de SDL3, DOM, Canvas, Tauri et des APIs plateforme. `game-snake-poc-wasm` adapte la scène et les entrées au host Web et porte la provenance runtime ; le frontend gère DOM, lifecycle navigateur, rendu Canvas et shell UI.
|
||||
|
||||
## Input et cadence
|
||||
|
||||
Les entrées navigateur sont converties vers les quatre actions Snake `Left`, `Right`, `Up`, `Down`. Une entrée ne fait pas avancer directement la simulation : la direction est mise en attente puis consommée au prochain `tick()` WASM.
|
||||
|
||||
Le host valide clavier, contrôles pointer/tactiles, resize et pause/reprise sans rattrapage massif après masquage d'onglet.
|
||||
|
||||
## Shell Web
|
||||
|
||||
Le frontend reprend les conventions utiles des applications Desk KSP sans dépendre de Tauri :
|
||||
|
||||
- Vite + TypeScript ;
|
||||
- Bootstrap 5 / Bootswatch Pulse ;
|
||||
- Font Awesome ;
|
||||
- Sass ;
|
||||
- SimpleBar et `resize-observer-polyfill` ;
|
||||
- header/footer fixes et zone centrale scrollable ;
|
||||
- Canvas conservant le ratio logique Snake `12 × 20`.
|
||||
|
||||
Le frontend reste un host : il ne contient aucune règle de gameplay.
|
||||
|
||||
## Assets
|
||||
|
||||
Les assets sources restent hors des crates sous `assets/`. Le build Web conserve les namespaces logiques :
|
||||
|
||||
```text
|
||||
assets/common/data/runtime.json → /common/data/runtime.json
|
||||
assets/game-snake-poc/data/game.json → /game/data/game.json
|
||||
```
|
||||
|
||||
Les mêmes routes sont valides en développement Vite et dans le bundle production.
|
||||
|
||||
## Provenance runtime
|
||||
|
||||
La session Web conserve `RuntimeProvenance` dans l'adapter WASM. Les dimensions fixes sont `Web / Browser / Wasm`; la classe d'appareil et le profil d'entrée sont renseignés à partir de l'environnement et des entrées réellement observées.
|
||||
|
||||
Le smoke validé expose notamment :
|
||||
|
||||
```text
|
||||
web / browser / wasm / desktop / keyboard-mouse
|
||||
```
|
||||
|
||||
## Build
|
||||
|
||||
Le chemin Web direct ne dépend d'aucun orchestrateur Python :
|
||||
|
||||
```text
|
||||
Cargo
|
||||
→ wasm-bindgen
|
||||
→ Vite/npm
|
||||
```
|
||||
|
||||
Les artefacts générés restent hors dépôt sous `../builds/sasedev-games/`.
|
||||
|
||||
## Résultat de l'extraction
|
||||
|
||||
`0.3.0` ne justifie pas encore une abstraction WASM commune entre Reflex et Snake. Les deux adapters spécifiques restent préférables à une factorisation spéculative.
|
||||
|
||||
Le prochain host Snake doit réutiliser cette baseline et fournir un second cas réel avant extraction d'une couche commune WebView/WASM.
|
||||
|
||||
## Témoin Desktop
|
||||
|
||||
Le runner `game-snake-poc-desktop` reste le témoin SDL3 natif. La beta puis la RC `0.3.0-3-rc.1` ont validé son build release et son smoke sans modification de gameplay ni de runtime SDL3.
|
||||
|
||||
## Suite
|
||||
|
||||
`0.3.1` doit éprouver Tauri Android + Snake. `0.3.2` peut ensuite tester Tauri Desktop et décider, sur deux consommateurs réels, si une factorisation WebView/frontend est justifiée.
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/development/003-TRACING_AND_DIAGNOSTICS.md -->
|
||||
<!-- version: 1 -->
|
||||
<!-- version: 2 -->
|
||||
|
||||
# Tracing et diagnostics
|
||||
|
||||
@@ -21,3 +21,9 @@ Les runners Desktop initialisent ce socle. Les futures intégrations Android pou
|
||||
## Évolution
|
||||
|
||||
Les filtres par target/niveau, fichiers rotatifs, configuration utilisateur, traces Android et éventuelle télémétrie distante seront ajoutés uniquement lorsqu’un besoin concret les justifie.
|
||||
|
||||
## Host navigateur direct
|
||||
|
||||
Le navigateur direct ne possède ni backend Rust Tauri ni plugin de relayage. Son frontend utilise donc un module TypeScript unique de diagnostics structurés qui écrit dans la console du navigateur avec `target`, `action` et champs associés. Les modules applicatifs n'émettent pas leurs propres formats parallèles.
|
||||
|
||||
Cette sortie console est un mécanisme frontend. Elle ne remplace pas `tracing` dans le code Rust : les runners natifs continuent d'initialiser `game-logging-lib`, et un futur besoin de tracing Rust directement dans WebAssembly devra être introduit explicitement plutôt que d'être simulé par le frontend.
|
||||
|
||||
53
docs/development/009-SNAKE_WEB_WASM_BUILD.md
Normal file
53
docs/development/009-SNAKE_WEB_WASM_BUILD.md
Normal file
@@ -0,0 +1,53 @@
|
||||
<!-- file: docs/development/009-SNAKE_WEB_WASM_BUILD.md -->
|
||||
<!-- version: 2 -->
|
||||
|
||||
# Build WASM du POC Snake Web direct
|
||||
|
||||
## Objectif
|
||||
|
||||
`game-snake-poc-wasm` fournit le bridge Rust/WASM du premier host navigateur direct. Cette tranche valide uniquement la production du module WebAssembly et de ses bindings JavaScript ; le frontend Vite/TypeScript et le shell Bootstrap 5 appartiennent à `0-pre.4`.
|
||||
|
||||
## Prérequis
|
||||
|
||||
À installer une fois si nécessaire :
|
||||
|
||||
```bash
|
||||
rustup target add wasm32-unknown-unknown
|
||||
cargo install wasm-bindgen-cli --locked
|
||||
```
|
||||
|
||||
Le CLI `wasm-bindgen` utilisé doit rester compatible avec la version de la crate `wasm-bindgen` résolue par Cargo.
|
||||
|
||||
## Build Rust
|
||||
|
||||
Depuis la racine du dépôt :
|
||||
|
||||
```bash
|
||||
cargo build -p game-snake-poc-wasm --target wasm32-unknown-unknown
|
||||
```
|
||||
|
||||
La configuration Cargo racine place l'artefact sous :
|
||||
|
||||
```text
|
||||
../builds/sasedev-games/target/wasm32-unknown-unknown/debug/game_snake_poc_wasm.wasm
|
||||
```
|
||||
|
||||
## Génération des bindings navigateur
|
||||
|
||||
Créer les bindings avec l'outil natif, sans orchestrateur Python :
|
||||
|
||||
```bash
|
||||
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
|
||||
```
|
||||
|
||||
Les fichiers générés restent intégralement hors du dépôt sous `../builds/sasedev-games/`. Ils ne sont ni commités ni copiés dans `crates/` par cette tranche.
|
||||
|
||||
## Frontière avec `0-pre.4`
|
||||
|
||||
`0-pre.3` s'arrête au module WASM et à ses bindings générés. Le frontend introduit en `0-pre.4` sous `Web/game-snake-poc/` les consomme ensuite via Vite/TypeScript ; il porte le document HTML Bootstrap 5, le Canvas, le clavier et les contrôles tactiles.
|
||||
|
||||
Le frontend reste responsable de la cadence d'appel à `tick()` et de la traduction des événements navigateur vers `left()`, `right()`, `up()` et `down()`.
|
||||
165
docs/development/010-SNAKE_WEB_FRONTEND.md
Normal file
165
docs/development/010-SNAKE_WEB_FRONTEND.md
Normal file
@@ -0,0 +1,165 @@
|
||||
<!-- file: docs/development/010-SNAKE_WEB_FRONTEND.md -->
|
||||
<!-- version: 5 -->
|
||||
|
||||
# Frontend du POC Snake Web direct
|
||||
|
||||
## Rôle
|
||||
|
||||
`Web/game-snake-poc/` est le premier host navigateur direct du projet. Il reste un package frontend autonome, extérieur au workspace Cargo, et consomme les bindings générés de `game-snake-poc-wasm`.
|
||||
|
||||
La séparation est volontaire :
|
||||
|
||||
```text
|
||||
game-snake-poc
|
||||
↓
|
||||
game-snake-poc-wasm
|
||||
↓ wasm-bindgen
|
||||
Web/game-snake-poc
|
||||
↓
|
||||
HTML + Sass/Bootstrap 5 + TypeScript + Canvas
|
||||
```
|
||||
|
||||
Le frontend ne réimplémente aucune règle de Snake. Il traduit uniquement les entrées navigateur, cadence les appels à `tick()` et dessine la scène portable exposée par le bridge WASM.
|
||||
|
||||
## Baseline frontend KSP
|
||||
|
||||
Le shell reprend volontairement la structure frontend utilisée par les applications Desk KSP :
|
||||
|
||||
```text
|
||||
Web/game-snake-poc/
|
||||
├── frontend/
|
||||
│ ├── main.html
|
||||
│ ├── sass/
|
||||
│ │ ├── _app.scss
|
||||
│ │ ├── _bootswatch.scss
|
||||
│ │ ├── _fontawesome.scss
|
||||
│ │ ├── _simplebar.scss
|
||||
│ │ ├── _variables.scss
|
||||
│ │ └── main.scss
|
||||
│ └── ts/
|
||||
│ ├── game.ts
|
||||
│ ├── input.ts
|
||||
│ └── main.ts
|
||||
├── package.json
|
||||
├── tsconfig.json
|
||||
└── vite.config.ts
|
||||
```
|
||||
|
||||
Les dépendances npm utiles sont alignées sur cette baseline : Bootstrap 5, Font Awesome, SimpleBar, `resize-observer-polyfill`, `sass-embedded`, TypeScript, Vite et les types nécessaires. Les dépendances réellement propres à Tauri et au tracing frontend KSP ne sont pas importées dans ce host navigateur direct. SimpleBar et le polyfill restent au contraire pertinents pour le shell Web lui-même.
|
||||
|
||||
Le thème reprend la baseline Bootstrap/Bootswatch Pulse des apps Desk KSP, avec un header, un footer et une carte de contenu adaptés au jeu. Cette réutilisation reste une convention de présentation du POC ; elle ne crée aucune dépendance entre les dépôts KSP et games.sasedev.
|
||||
|
||||
## Shell HTML et présentation
|
||||
|
||||
Le document `frontend/main.html` fournit :
|
||||
|
||||
- un header de statut inspiré du template Desk KSP ;
|
||||
- un Canvas carré responsive pour le rendu du jeu ;
|
||||
- les indicateurs de score, longueur et état de chargement ;
|
||||
- quatre boutons directionnels tactiles ;
|
||||
- une zone d'erreur de démarrage ;
|
||||
- un footer léger commun au shell ;
|
||||
- une zone centrale `app-content.app-scrollable.h-100[data-simplebar]` bornée par `app-main` entre le header et le footer fixes, suivant le même contrat de shell que les apps Desk KSP.
|
||||
|
||||
Bootstrap 5 et Font Awesome sont installés comme dépendances npm et intégrés au build Vite/Sass. Aucun CDN n'est nécessaire au POC local.
|
||||
|
||||
Le Sass spécifique reste limité au shell, au Canvas et au pavé directionnel. Le gameplay ne dépend ni de Bootstrap, ni de Font Awesome, ni du DOM.
|
||||
|
||||
## Entrées
|
||||
|
||||
Le frontend accepte :
|
||||
|
||||
- les flèches du clavier ;
|
||||
- `WASD` ;
|
||||
- `ZQSD` ;
|
||||
- les quatre boutons directionnels tactiles/pointer.
|
||||
|
||||
Une entrée appelle uniquement `left()`, `right()`, `up()` ou `down()` sur `SnakeWasmGame`. La simulation continue d'avancer exclusivement via `tick()`.
|
||||
|
||||
## Rendu Canvas
|
||||
|
||||
Le frontend lit la couleur de fond et les rectangles normalisés exposés par `game-snake-poc-wasm`. Les coordonnées sont multipliées par la taille physique courante du Canvas.
|
||||
|
||||
La grille Snake fait `12 × 20` cellules. Le shell conserve donc un ratio CSS `3 / 5` pour le plateau : une cellule normalisée garde la même largeur et la même hauteur visuelles au lieu d'être écrasée verticalement dans un Canvas carré. Le Canvas suit ensuite cette taille CSS et le `devicePixelRatio` du navigateur.
|
||||
|
||||
Le header et le footer restent fixes. `app-main` borne la hauteur utile à `100vh - header - footer` et reste lui-même non scrollable. Comme dans les apps Desk KSP, un enfant `h-100` contient `app-content app-scrollable h-100` portant `data-simplebar`; cette zone possède explicitement `height: 100%` et `max-height: 100%`. Si le plateau portrait et les contrôles dépassent la hauteur disponible, SimpleBar porte donc le scroll de cette zone centrale sans déplacer le header ni le footer. Cette tranche couvre le resize visuel nécessaire au shell ; la gestion complète du lifecycle navigateur reste prévue par `0-pre.5`.
|
||||
|
||||
## Build
|
||||
|
||||
Depuis la racine du dépôt, construire d'abord l'adapter WASM et ses bindings :
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
Puis installer et construire le frontend :
|
||||
|
||||
```bash
|
||||
cd Web/game-snake-poc
|
||||
npm install
|
||||
npm run build
|
||||
```
|
||||
|
||||
Vite place son cache et le `dist/` sous :
|
||||
|
||||
```text
|
||||
../builds/sasedev-games/game-snake-poc-web/
|
||||
```
|
||||
|
||||
Le dépôt ne reçoit donc ni bindings WASM générés, ni `dist/`, ni cache Vite.
|
||||
|
||||
## Smoke navigateur
|
||||
|
||||
Après génération du WASM :
|
||||
|
||||
```bash
|
||||
cd Web/game-snake-poc
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Ouvrir explicitement `http://127.0.0.1:1434/main.html` — le host utilise volontairement `main.html` et ne fournit pas d'`index.html` — puis vérifier :
|
||||
|
||||
1. le statut passe à `Prêt` sans erreur ;
|
||||
2. Snake est visible dans le Canvas ;
|
||||
3. les flèches clavier déplacent Snake ;
|
||||
4. `WASD` et `ZQSD` produisent les mêmes directions ;
|
||||
5. les quatre boutons tactiles/pointer fonctionnent ;
|
||||
6. le plateau conserve son ratio portrait `3 / 5` et les cellules ne sont pas écrasées ;
|
||||
7. lorsque le contenu dépasse la hauteur utile, seule la zone centrale défile via SimpleBar tandis que header et footer restent fixes ;
|
||||
8. le shell KSP-derived et le Canvas restent utilisables sur une largeur mobile et Desktop ;
|
||||
9. score et longueur restent visibles et évoluent avec l'état WASM.
|
||||
|
||||
## Lifecycle navigateur
|
||||
|
||||
`0-pre.5` ferme le lifecycle du POC. La boucle `requestAnimationFrame` est suspendue lorsque le document devient caché ou reçoit `pagehide`. La reprise sur `visibilitychange`/`pageshow` réinitialise l'origine temporelle et l'accumulateur afin de ne pas rattraper artificiellement les ticks perdus en arrière-plan.
|
||||
|
||||
Un `ResizeObserver` attaché à la zone de jeu redessine le Canvas et rafraîchit la classe d'appareil observée sans faire avancer la simulation. La destruction de page libère l'instance WASM.
|
||||
|
||||
## Assets runtime
|
||||
|
||||
Le package Vite utilise `vite-plugin-static-copy` pour exposer les deux assets de sonde depuis les sources canoniques :
|
||||
|
||||
```text
|
||||
assets/common/data/runtime.json -> dist/common/data/runtime.json
|
||||
assets/game-snake-poc/data/game.json -> dist/game/data/game.json
|
||||
```
|
||||
|
||||
Les deux targets utilisent explicitement `rename: { stripBase: true }`. Ce point est nécessaire puisque les sources sont résolues en chemins absolus : seule la basename (`runtime.json` / `game.json`) doit être placée sous le `dest` canonique, sans conserver l'arborescence du chemin source. Le serveur Vite de développement expose ainsi les mêmes routes `/common/data/runtime.json` et `/game/data/game.json` que le build de production.
|
||||
|
||||
Le frontend charge et valide les deux JSON avant le démarrage WASM. Le statut visible `Assets` permet de confirmer le chargement pendant le smoke. Aucune copie source n'est ajoutée sous `Web/`.
|
||||
|
||||
## Logging frontend
|
||||
|
||||
`frontend/ts/logging.ts` centralise les diagnostics navigateur. Les événements sont structurés par niveau, target, action et champs, puis écrits dans la console. Ce module est volontairement distinct du bridge tracing Tauri : le host Web direct ne possède pas de backend Tauri à qui relayer ses événements.
|
||||
|
||||
Le Rust natif continue d'utiliser `tracing`/`game-logging-lib`; le frontend console ne remplace pas cette façade Rust.
|
||||
|
||||
## Provenance runtime
|
||||
|
||||
`game-snake-poc-wasm` dépend de `engine-v1-platform-api` uniquement au niveau adapter et conserve une `RuntimeProvenance`. Les dimensions `Web / Wasm / Browser` sont fixes ; le host renseigne la classe `Desktop`/`Phone`/`Tablet`/`Unknown` et le profil `Unknown`/`KeyboardMouse`/`Touch`/`Mixed` à partir des capacités et entrées réellement observées.
|
||||
|
||||
Le shell affiche ces cinq dimensions afin que le smoke puisse confirmer que la provenance évolue lorsqu'un clavier/souris ou un contrôle tactile est utilisé. Le gameplay `game-snake-poc` reste sans dépendance plateforme.
|
||||
14
docs/plans/000-README.md
Normal file
14
docs/plans/000-README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
<!-- file: docs/plans/000-README.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Plans de versions games.sasedev
|
||||
|
||||
Ce répertoire contient les plans vivants des versions concrètes.
|
||||
|
||||
Un plan est créé ou révisé pendant `0-pre.1`. Il conserve le scope, les décisions utiles, les validations et surtout le découpage prévisionnel souple des tranches jusqu'à la release. Il peut évoluer lorsque les audits ou validations imposent de scinder, fusionner, reporter ou corriger une tranche.
|
||||
|
||||
Le `ROADMAP.md` reste la trajectoire macroscopique du projet ; les deltas décrivent ce qui a réellement été livré. Le plan se situe entre les deux et sert au suivi de la version en cours.
|
||||
|
||||
## Plans
|
||||
|
||||
- [`001-V0_3_0_WEB_SNAKE_POC_PLAN.md`](001-V0_3_0_WEB_SNAKE_POC_PLAN.md) — plan actif de `0.3.0`, baseline Snake et premier POC Web direct.
|
||||
146
docs/plans/001-V0_3_0_WEB_SNAKE_POC_PLAN.md
Normal file
146
docs/plans/001-V0_3_0_WEB_SNAKE_POC_PLAN.md
Normal file
@@ -0,0 +1,146 @@
|
||||
<!-- file: docs/plans/001-V0_3_0_WEB_SNAKE_POC_PLAN.md -->
|
||||
<!-- version: 17 -->
|
||||
|
||||
# Plan v0.3.0 — baseline Snake et premier POC Web direct
|
||||
|
||||
## But de la version
|
||||
|
||||
`0.3.0` ouvre la série de POC `0.3.x`. La version doit rendre Snake suffisamment portable pour servir de jeu-sonde et valider un premier host de bout en bout : le navigateur Web direct.
|
||||
|
||||
La version doit rester assez petite pour être fermée dans la session qui l'ouvre. Si une tranche devient trop lourde, elle est scindée ; si le scope global ne tient plus, la partie non indispensable est reportée à une version suivante.
|
||||
|
||||
## Base et décisions acquises
|
||||
|
||||
Base stable : `0.2.0`.
|
||||
|
||||
Décisions issues du cadrage `0-pre.1` :
|
||||
|
||||
- Snake reste le jeu-sonde principal ;
|
||||
- le premier host de `0.3.0` est Web navigateur direct ;
|
||||
- Tauri Android est reporté à `0.3.1` ;
|
||||
- le gameplay reste dans `game-snake-poc` ;
|
||||
- le chemin Web utilise Cargo, `wasm-bindgen` et Vite/TypeScript, sans orchestrateur Python ;
|
||||
- le host navigateur possède un shell HTML piloté par Vite/TypeScript, avec Bootstrap 5 pour le layout/les contrôles et un Canvas dédié au rendu du jeu ; Bootstrap ne porte aucune règle de gameplay ;
|
||||
- aucune abstraction n'est extraite avant qu'un besoin partagé réel soit observé.
|
||||
|
||||
## Scope
|
||||
|
||||
La version couvre :
|
||||
|
||||
- nettoyage de la baseline Snake et de ses dépendances de plateforme ;
|
||||
- adaptation WASM dédiée à Snake ;
|
||||
- frontend Web avec shell HTML responsive, Bootstrap 5, Canvas, clavier et contrôles directionnels tactiles ;
|
||||
- resize/lifecycle adaptés au navigateur ;
|
||||
- branchement des assets, du logging et de la provenance runtime nécessaires au POC ;
|
||||
- maintien du runner Desktop SDL3 comme témoin de non-régression ;
|
||||
- documentation des duplications observées et des extractions réellement justifiées.
|
||||
|
||||
Hors périmètre : Tauri Android/Desktop Snake, Android natif multi-ABI, réseau realtime, WebTransport/QUIC, Uroburas, ads, billing, auth, leaderboard et nouveau moteur.
|
||||
|
||||
## Prévision souple
|
||||
|
||||
Les numéros ci-dessous sont des repères de progression, pas un contrat rigide. Une découverte peut insérer un fix, scinder une tranche ou décaler les numéros suivants sans forcer la fermeture.
|
||||
|
||||
### `0-pre.1` — cadrage
|
||||
|
||||
Audit de la baseline, requirements, choix du host Web, sizing et validations prévues. Le présent plan manquant à la livraison initiale est ajouté par `0-pre.1.fix.1`.
|
||||
|
||||
### `0-pre.1.fix.1` — plan et règles de suivi
|
||||
|
||||
Créer `docs/plans/`, formaliser le caractère vivant du plan, corriger le contrat des archives taggées et rendre explicite qu'une session est planifiée pour fermer au minimum la version concrète ouverte.
|
||||
|
||||
### `0-pre.2` — baseline Snake portable
|
||||
|
||||
Nettoyer les dépendances inutiles/spécifiques au launcher, stabiliser la frontière gameplay/input et confirmer les tests Snake ainsi que le runner Desktop SDL3.
|
||||
|
||||
Livraison candidate : `engine-v1-platform-api` est retiré des crates de gameplay Snake et Reflex où il n'est pas consommé ; les launchers qui utilisent réellement les capacités plateforme conservent leur dépendance. Le contrat Snake est fixé sur `EngineGame`, `InputState`, les quatre actions directionnelles et `EngineScene`, sans SDL3, DOM, Canvas ni API plateforme dans la crate de gameplay. Aucun adapter WASM n'est introduit avant `0-pre.3`.
|
||||
|
||||
Gate : audits statiques, `cargo check --workspace`, tests ciblés Snake et vérification du graphe de dépendances des crates de gameplay. Un smoke Desktop n'est requis que si le runtime SDL ou son mapping est modifié.
|
||||
|
||||
### `0-pre.3` — adaptation Snake WASM
|
||||
|
||||
Introduire `game-snake-poc-wasm`, adapter WASM minimal dédié à Snake. La crate possède `SnakeState`, le `FixedStepRunner` et une direction logique en attente consommée au prochain `tick()`. Elle expose à `wasm-bindgen` les quatre directions, le score, la longueur et la scène normalisée nécessaire au futur Canvas, sans SDL3, Tauri, DOM, frontend ni `engine-v1-platform-api`.
|
||||
|
||||
Livraison candidate : la crate est membre du workspace et la distribution statique vérifie sa présence. Le bridge reste volontairement spécifique à Snake ; aucune abstraction commune avec `game-reflex-poc-wasm` n'est extraite avant observation d'une duplication réellement problématique.
|
||||
|
||||
Gate : audits statiques, `cargo check --workspace`, Clippy ciblé, tests de l'adapter, build `wasm32-unknown-unknown`, génération `wasm-bindgen --target web` dans `../builds/sasedev-games/` et graphe de dépendances. Aucun build Vite/Bootstrap ni smoke navigateur n'est requis avant `0-pre.4`.
|
||||
|
||||
### `0-pre.4` — frontend Web/Vite, shell Bootstrap 5 et contrôles
|
||||
|
||||
Créer `Web/game-snake-poc/`, package Vite/TypeScript autonome consommant les bindings `game-snake-poc-wasm` générés hors dépôt. Le frontend reprend le template des applications Desk KSP pour sa structure HTML/Sass/TypeScript et ses dépendances npm pertinentes : Bootstrap 5, thème Bootswatch Pulse, Font Awesome, SimpleBar, `resize-observer-polyfill` et `sass-embedded`, sans dépendances Tauri. Le rendu reste dans un Canvas et les règles de gameplay restent dans Rust/WASM. Brancher flèches clavier, `WASD`/`ZQSD`, quatre boutons directionnels tactiles/pointer, chargement/erreur, score et longueur.
|
||||
|
||||
Livraison candidate : le shell utilise `frontend/main.html`, `frontend/sass/` et `frontend/ts/` sur le modèle KSP ; SimpleBar porte le scroll de la zone centrale `app-content.app-scrollable.h-100[data-simplebar]`, bornée par `app-main` entre header et footer fixes ; le Canvas conserve le ratio logique Snake `12 / 20`, suit sa taille CSS et le `devicePixelRatio`, le frontend cadence `tick()` sans avancer la simulation au moment d'une entrée et Vite écrit `dist/`/cache uniquement sous `../builds/sasedev-games/game-snake-poc-web/`. Aucun CDN, SDL3, Tauri ni duplication de gameplay n'est introduit. Le lifecycle complet, les assets, le logging et la provenance restent réservés à `0-pre.5`.
|
||||
|
||||
Gate : audits statiques, build WASM + `wasm-bindgen`, `npm run build` du package Web direct et smoke navigateur couvrant Canvas, clavier, contrôles tactiles/pointer et comportement responsive du shell.
|
||||
|
||||
Suivi `0-pre.4.fix.1` : la validation utilisateur de `0-pre.4` a confirmé le fonctionnement clavier/pointer sous `vite dev`, mais a révélé trois défauts de candidate : `baseUrl` supprimé par TypeScript 7, omission de SimpleBar/`resize-observer-polyfill` du template repris et Canvas carré incompatible avec la grille logique `12 × 20`. Le fix retire `baseUrl`, rétablit le scroll shell KSP-derived et passe le plateau au ratio `3 / 5` avant réexécution de la gate frontend.
|
||||
|
||||
Suivi `0-pre.4.fix.2` : la validation de `fix.1` a confirmé les gates Rust/WASM et les audits, mais `npm run build` a encore révélé deux erreurs TypeScript strictes : l'alias `@snake-wasm` résolvait le JavaScript généré sans sélectionner sa déclaration `.d.ts`, et le narrowing du contexte Canvas 2D n'était pas conservé dans le callback `requestAnimationFrame`. Le fix sépare explicitement la résolution de typage (`.d.ts`) de la résolution runtime Vite (`.js`) et capture le contexte 2D validé dans une constante non nullable.
|
||||
|
||||
Suivi `0-pre.4.fix.3` : la validation de `fix.2` confirme la gate Rust/WASM, le build Vite production et le ratio Canvas corrigé. Le smoke révèle toutefois que le scroll SimpleBar ne reproduit pas encore le comportement du shell KSP. La comparaison avec `ksp-app-*-desk` montre que `data-simplebar` doit porter sur la zone centrale `app-content app-scrollable h-100`, enfant d'un `app-main` borné, et non sur `app-main` lui-même. Le fix aligne la structure HTML/Sass sur ce contrat sans initialisation manuelle spécifique.
|
||||
|
||||
Validation `0-pre.4.fix.3` : le build Vite reste propre et le smoke utilisateur confirme le comportement attendu du shell, y compris le scroll SimpleBar, le Canvas portrait et les contrôles. `0-pre.4` est donc fermé et `0-pre.5` peut porter l'intégration plateforme complète.
|
||||
|
||||
### `0-pre.5` — intégration plateforme complète
|
||||
|
||||
Fermer resize/lifecycle, assets, logging et provenance runtime du POC ; vérifier que Desktop SDL reste intact.
|
||||
|
||||
Livraison candidate : le host suspend la simulation sur `visibilitychange`/`pagehide` et reprend sans rattrapage massif ; un `ResizeObserver` redessine sans tick artificiel. Vite package `assets/common/data/runtime.json` vers `common/data/runtime.json` et `assets/game-snake-poc/data/game.json` vers `game/data/game.json`, puis le frontend charge/valide ces deux sondes avant le démarrage. Les diagnostics navigateur passent par un module TypeScript structuré local. `game-snake-poc-wasm` consomme `engine-v1-platform-api` pour une provenance `Web/Wasm/Browser`, complétée par la classe d'appareil et le profil d'entrée réellement observés. Aucun de ces contrats ne fuit dans `game-snake-poc`.
|
||||
|
||||
Gate : audits statiques, `cargo check --workspace`, Clippy workspace strict, tests `engine-v1-platform-api` et `game-snake-poc-wasm`, build WASM + `wasm-bindgen`, build Vite, smoke navigateur couvrant assets/provenance/lifecycle/resize/inputs/SimpleBar, puis smoke `game-snake-poc-desktop` pour la non-régression SDL3.
|
||||
|
||||
Suivi `0-pre.5.fix.1` : la validation de `0-pre.5` confirme les gates Rust/WASM et le build Vite production, mais le smoke `vite dev` reste bloqué sur le chargement des assets. Les targets `vite-plugin-static-copy` utilisent des sources absolues sans `rename.stripBase`, ce qui ne garantit pas les routes runtime canoniques. Le fix impose `stripBase: true` aux deux targets afin que dev et build exposent exactement `/common/data/runtime.json` et `/game/data/game.json`.
|
||||
|
||||
Validation `0-pre.5.fix.1` : les audits, `cargo check`, Clippy workspace strict, les tests plateforme/WASM, le build WASM, `wasm-bindgen`, le build Vite et le smoke navigateur passent. Les assets affichent `snake / engine-v1`, la provenance observée est `web / browser / wasm / desktop / keyboard-mouse`, les contrôles clavier/souris fonctionnent et le runner Desktop SDL3 démarre puis s'arrête proprement après 411 frames. Aucun défaut structurel supplémentaire n'est identifié.
|
||||
|
||||
### `0-pre.6` — correction/extraction seulement si prouvée
|
||||
|
||||
Tranche conditionnelle. Elle n'existe que si les POC précédents révèlent une duplication réelle, une frontière mal placée ou un défaut nécessitant une correction structurante avant stabilisation. Sinon elle est omise.
|
||||
|
||||
Décision après `0-pre.5.fix.1` : aucun besoin d'extraction/correction structurante n'est observé ; `0-pre.6` est omise et la version entre directement en beta.
|
||||
|
||||
### `2-beta.1` — validation large
|
||||
|
||||
Scope feature-complete. La tranche ne crée aucun nouveau comportement : elle bascule la version workspace et le package Web au jalon `0.3.0-2-beta.1`, enregistre la validation de `0-pre.5.fix.1` et exécute la gate large de frontière de phase. Celle-ci comprend audits, formatage/check/Clippy, tests workspace complets, build + smoke Desktop Snake en release, build WASM Snake en release, `wasm-bindgen`, build Vite production et smoke du `dist` via `npm run preview`. Aucun nouveau scope.
|
||||
|
||||
Validation : la gate est acceptée par l'utilisateur. Les audits sont propres, les tests workspace totalisent 34 tests réussis sans échec, le binaire Desktop Snake release démarre et s'arrête proprement après 144 frames, et le bundle Web/WASM release est construit puis servi par `vite preview` sans défaut remonté.
|
||||
|
||||
### `2-beta.2` — consolidation documentaire et transmission
|
||||
|
||||
Réconcilier l'état réellement validé avec la documentation durable et le plan actif, mettre à jour `ROADMAP.md`, enregistrer `2-beta.1` dans l'historique et préparer le prompt de `0.3.1` à partir de cet état. La synthèse destinée au `CHANGELOG.md` est consolidée ici, mais l'entrée n'est écrite qu'en RC conformément à `DOC-CHG-002` et `DOC-CHG-003`.
|
||||
|
||||
Livraison candidate : synthèse durable de la baseline Web Snake `0.3.0`, matrice RC spécifique, roadmap `0.3.0` classée réalisée, audit `pre.1` réconcilié avec le contrat des archives taggées et prompt `003-V0_3_1_START_PROMPT.md`. Aucun code ni comportement runtime n'est modifié.
|
||||
|
||||
Cette tranche est une responsabilité obligatoire du cycle même si son numéro doit être décalé par des fixes ou une beta supplémentaire. La documentation spécifique à une fonctionnalité reste mise à jour dans la tranche qui introduit cette fonctionnalité ; `2-beta.2` réalise la consolidation transversale, elle ne sert pas à reporter toute la documentation en fin de version.
|
||||
|
||||
Gate : cohérence docs/plan/deltas/`CHANGELOG.md`/`ROADMAP.md`/history/prompt, audits documentaires, `cargo check --workspace` pour le bump de version et `npm run build` pour confirmer la version frontend.
|
||||
|
||||
Suivi `2-beta.2.fix.1` : la gate mécanique de `2-beta.2` passe, mais la revue humaine juge le prompt `0.3.1` trop synthétique pour éviter des rappels de workflow au cours de la prochaine session. Le fix enrichit ce prompt, formalise une structure durable de prompts, précise le timing prompt/RC/CHANGELOG/ROADMAP/history et introduit une politique non cérémonielle pour `README.md`/`USAGE.md`. Le fix est strictement documentaire et conserve donc la version technique `0.3.0-2-beta.2`.
|
||||
|
||||
Suivi `2-beta.2.fix.2` : la revue du prompt enrichi valide son niveau de contexte, mais précise la gouvernance des commandes afin d'éviter des validations trop larges ou répétitives. Le fix rend obligatoires `cargo fmt`, `cargo check --workspace` et Clippy workspace strict dès que Rust ou ses dépendances changent, garde les tests ciblés comme norme, réserve le test workspace complet à quelques jalons planifiés, limite `cargo tree` aux changements/diagnostics de dépendances, sélectionne les audits Python selon les fichiers touchés, impose les sous-shells pour les changements de répertoire et rappelle que Tauri possède Vite via `cargo tauri dev/build`. Ce correctif reste strictement documentaire et ne modifie aucune version technique.
|
||||
|
||||
Validation `2-beta.2.fix.2` : l'audit Markdown ciblé passe (`5` tables, `189` fichiers) et la revue utilisateur autorise l'ouverture de la RC. Aucune autre gate n'est attribuée à ce correctif strictement documentaire.
|
||||
|
||||
### `3-rc.1` — candidate gelée
|
||||
|
||||
Reproductibilité, validation finale de la candidate et derniers défauts strictement nécessaires à la publication. Le prompt suivant préparé pendant la consolidation est vérifié/complété si l'état RC apporte une information nouvelle. Aucun nouveau POC ni nouvelle capability.
|
||||
|
||||
Livraison candidate : passage des versions techniques au jalon `0.3.0-3-rc.1`, entrée RC du `CHANGELOG.md`, enregistrement de `2-beta.2.fix.2` dans `history/`, revue finale du prompt `0.3.1` et gel explicite du scope. Le prompt est jugé suffisamment complet et ne reçoit aucun changement sémantique supplémentaire dans cette tranche.
|
||||
|
||||
Gate RC : appliquer intégralement `docs/testing/004-V0_3_0_RC_VALIDATION_MATRIX.md`. Le test workspace complet est volontairement exécuté à ce jalon final ; aucun `cargo tree` n'est requis en l'absence de changement de dépendances.
|
||||
|
||||
Validation `3-rc.1` : les audits statiques, `cargo check --workspace`, Clippy workspace strict et la suite workspace complète passent avec 34 tests réussis. Le binaire Desktop Snake release démarre puis s'arrête proprement après 926 frames. Le build WASM release, `wasm-bindgen`, le build Vite production et `vite preview` passent également. Aucun défaut nécessitant un correctif RC n'est remonté.
|
||||
|
||||
### `0.3.0` — release stable
|
||||
|
||||
Promotion mécanique de l'état RC validé. La release ne change ni gameplay, ni architecture, ni dépendance ; elle fixe les versions stables, ajoute l'entrée stable du `CHANGELOG.md`, enregistre la validation RC sous `history/0.3.0/3-rc.1.md` et clôt le plan `0.3.0`. Le prompt `0.3.1` reste inchangé après sa revue RC.
|
||||
|
||||
## Suivi et ajustements
|
||||
|
||||
Le plan est révisé lorsqu'un résultat réel modifie la trajectoire. Un changement de numérotation n'est pas un problème ; une responsabilité importante ne doit en revanche pas être comprimée artificiellement pour respecter le forecast initial.
|
||||
|
||||
La session ne doit pas être planifiée pour s'arrêter à `pre.2`, `pre.4` ou beta : ces identifiants sont des tranches de la même version. Si `0.3.0` devient trop grande, le scope non indispensable est déplacé vers `0.3.1+` afin de préserver une version complète par session.
|
||||
|
||||
## Version suivante envisagée
|
||||
|
||||
`0.3.1` reste le candidat pour le second host Snake, Tauri Android, en réutilisant la baseline Web/WASM réellement validée par `0.3.0`.
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/rules/FILE_CONTRACTS.md -->
|
||||
<!-- version: 6 -->
|
||||
<!-- version: 8 -->
|
||||
|
||||
# Contrats des fichiers principaux
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
- `docs/rules/` contient les règles durables.
|
||||
- `docs/ideas/000-README.md` est le point d'entrée des idées et variantes non engagées.
|
||||
- `docs/studies/000-README.md` est le point d'entrée des analyses comparatives non normatives préparant une décision.
|
||||
- `docs/plans/000-README.md` est le point d'entrée des plans de versions ; chaque plan actif porte le découpage prévisionnel souple et les gates de sa version.
|
||||
- `docs/architecture/` contient les décisions et descriptions d'architecture retenues.
|
||||
- `docs/objectives/` décrit les objectifs et la stratégie produit/technique.
|
||||
- `docs/games/` classe les familles de jeux, leurs contrôles et leurs évolutions.
|
||||
@@ -25,7 +26,8 @@
|
||||
- `scripts/` contient des audits en lecture seule et des outils du dépôt.
|
||||
- `assets/` contient les ressources runtime communes et spécifiques aux jeux ; aucune ressource runtime n'est placée dans une crate Rust.
|
||||
- `Android/` contient le projet Gradle multi-module et son code Java commun/spécifique.
|
||||
- `crates/apps/` contient les exécutables de développement et launchers Rust, notamment les runners Desktop par jeu.
|
||||
- `Web/` contient les hosts navigateur directs non-Tauri ; chaque `Web/<game>/` est un package frontend autonome consommant un adapter WASM versionné sous `crates/apps/`.
|
||||
- `crates/apps/` contient les exécutables de développement et launchers Rust, notamment les runners Desktop par jeu et les adapters WASM.
|
||||
|
||||
## Tauri
|
||||
|
||||
|
||||
70
docs/rules/PROMPT_STRUCTURE.md
Normal file
70
docs/rules/PROMPT_STRUCTURE.md
Normal file
@@ -0,0 +1,70 @@
|
||||
<!-- file: docs/rules/PROMPT_STRUCTURE.md -->
|
||||
<!-- version: 2 -->
|
||||
|
||||
# Structure des prompts de reprise
|
||||
|
||||
## Objet
|
||||
|
||||
Un prompt de démarrage est un contrat opératoire autonome pour la version suivante. Il doit permettre de reprendre le travail sans dépendre de la mémoire conversationnelle, tout en évitant de recopier intégralement les règles du dépôt.
|
||||
|
||||
Le prompt rappelle les invariants qui évitent les erreurs de workflow et renvoie aux documents normatifs pour leur détail exact.
|
||||
|
||||
## Contenu minimal
|
||||
|
||||
- **PROMPT-STR-001** — Le prompt identifie la baseline exacte, la version cible et l'autorité de la base fournie. Une archive annoncée comme téléchargement d'un tag est traitée selon `CMD-GIT-003`/`CMD-GIT-004` sans exiger `.git`.
|
||||
- **PROMPT-STR-002** — Le prompt fournit un ordre de lecture court des sources de vérité : `RULES.md`, `ROADMAP.md`, `CHANGELOG.md`, `docs/000-README.md`, règles directement pertinentes, plan/historique de la version précédente et documents d'architecture concernés.
|
||||
- **PROMPT-STR-003** — Le prompt distingue explicitement l'état déjà validé hérité de la baseline des validations qui devront être exécutées dans la nouvelle version.
|
||||
- **PROMPT-STR-004** — Le prompt décrit la mission, le résultat attendu, le scope inclus, le hors-périmètre et les invariants architecturaux gelés.
|
||||
- **PROMPT-STR-005** — Le prompt rappelle que `0-pre.1` est le gate de cadrage : audit, requirements, sizing, risques, validations prévues et création/révision du plan sous `docs/plans/` avant développement lourd.
|
||||
- **PROMPT-STR-006** — Le prompt contient un forecast souple jusqu'à la stable. Il réserve les responsabilités de développement, validation large, consolidation documentaire, préparation de publication/RC et release mécanique sans rendre les numéros immuables.
|
||||
- **PROMPT-STR-007** — Le prompt rappelle où se trouve la définition des commandes : `docs/rules/RULES_COMMANDS.md` pour la politique d'exécution et `docs/rules/RULES_VALIDATION_MATRIX.md` pour les IDs, dépendances et déclencheurs. Il ne recopie que les commandes indispensables à la reprise ou au premier gate.
|
||||
- **PROMPT-STR-008** — Le prompt rappelle la séparation utilisateur/générateur : les audits statiques peuvent être exécutés par le générateur, mais les builds, tests et smokes finaux restent côté utilisateur conformément à `CMD-BUILD-005` et ne sont jamais déclarés réussis sans sortie réelle.
|
||||
- **PROMPT-STR-009** — Le prompt rappelle la cadence de validation sans recopier toute la matrice : audits Python sélectionnés selon les fichiers touchés ; `cargo fmt --all`, `cargo fmt --all -- --check`, `cargo check --workspace` et Clippy workspace strict obligatoires dès que du Rust ou une dépendance Cargo change ; tests `cargo test -p ...` ciblés par défaut ; test workspace complet réservé aux rares jalons planifiés ou aux changements transverses incertains ; `cargo tree` seulement lors d'un changement/diagnostic de dépendances.
|
||||
|
||||
## Commandes avec répertoire et Tauri
|
||||
|
||||
- **PROMPT-STR-016** — Le prompt rappelle que toute commande nécessitant un `cd` est englobée dans un sous-shell, par exemple `(cd <dir> && <commande>)`, afin de ne pas modifier le répertoire courant pour les commandes suivantes.
|
||||
- **PROMPT-STR-017** — Lorsqu'une version touche Tauri, le prompt rappelle que `npm` sert à gérer les dépendances frontend mais que les builds/smokes passent par Tauri : `(cd <tauri-app> && cargo tauri dev)` pour le smoke courant et `(cd <tauri-app> && cargo tauri build)` aux phases finales de packaging prévues. Les hooks Tauri possèdent Vite/TypeScript/WASM ; `npm run dev`/`npm run build` ne deviennent pas des gates manuelles Tauri.
|
||||
|
||||
## Documentation et traçabilité à rappeler
|
||||
|
||||
- **PROMPT-STR-010** — Le prompt rappelle que `deltas/` décrit la livraison candidate et ses validations attendues, alors que `history/` enregistre uniquement le résultat d'un jalon effectivement accepté.
|
||||
- **PROMPT-STR-011** — Le prompt rappelle qu'une entrée `history/<X.Y.Z>/<jalon>.md` est créée par le delta suivant ou le fix suivant après validation, jamais avant la validation qu'elle décrit.
|
||||
- **PROMPT-STR-012** — Le prompt rappelle que `CHANGELOG.md` n'est normalement mis à jour qu'à partir de la RC puis à la stable ; les détails `pre`/`beta` restent dans `deltas/` et `history/`.
|
||||
- **PROMPT-STR-013** — Le prompt rappelle que `ROADMAP.md` reste macroscopique et n'est modifié que lorsque le scope, son ordre ou son statut évolue réellement ; le plan de version porte le découpage fin.
|
||||
- **PROMPT-STR-014** — Le prompt rappelle que la documentation propre à une fonctionnalité évolue avec la tranche qui l'introduit ; la consolidation finale réconcilie l'ensemble mais ne sert pas à repousser toute documentation à la fin.
|
||||
- **PROMPT-STR-015** — Le prompt mentionne explicitement la politique `README.md`/`USAGE.md` lorsque la version crée ou finalise une crate, une application ou un package : appliquer `DOC-CRATE-*` et décider dans le plan quels fichiers ont une valeur durable réelle.
|
||||
|
||||
## README et USAGE dans une version
|
||||
|
||||
Le prompt ne doit pas imposer mécaniquement des fichiers vides. Il doit en revanche forcer la question au cadrage puis à la consolidation :
|
||||
|
||||
```text
|
||||
nouvelle crate/package durable ?
|
||||
-> README utile pour responsabilité/frontières/points d'entrée ?
|
||||
|
||||
API ou workflow de consommation non trivial ?
|
||||
-> USAGE utile pour préconditions/commandes/exemples ?
|
||||
|
||||
simple adapter/POC déjà documenté durablement ailleurs ?
|
||||
-> document supplémentaire non obligatoire s'il n'apporte rien
|
||||
```
|
||||
|
||||
## Timing du prompt suivant
|
||||
|
||||
- **PROMPT-STR-020** — Le prompt de la version suivante est rédigé pendant la consolidation finale lorsque la cible suivante est suffisamment connue ; il n'est pas reporté à une future session.
|
||||
- **PROMPT-STR-021** — La première RC gelée vérifie et complète ce prompt à partir de l'état réellement candidat à publication ; elle ne lui attribue pas de validations futures.
|
||||
- **PROMPT-STR-022** — La stable ne doit normalement effectuer qu'une mise à jour mécanique de la base de départ ou des références devenues certaines depuis la RC.
|
||||
|
||||
## Versionnement, deltas et fixes
|
||||
|
||||
- **PROMPT-STR-030** — Le prompt rappelle le format SemVer applicable et le rôle des `.fix.N` lorsqu'une erreur est découverte dans une tranche déjà livrée.
|
||||
- **PROMPT-STR-031** — Le prompt rappelle que chaque delta indique sa base requise, son scope, les fichiers touchés, les validations attendues et l'état connu du jalon précédent.
|
||||
- **PROMPT-STR-032** — Une validation propre permet de poursuivre automatiquement vers la tranche planifiée suivante ; un échec reste dans un `.fix.N` de la tranche courante sauf décision explicite contraire.
|
||||
- **PROMPT-STR-033** — Le prompt rappelle qu'une session est dimensionnée pour fermer au minimum une version concrète jusqu'à sa stable, pas pour s'arrêter volontairement sur une prerelease.
|
||||
|
||||
## Niveau de détail attendu
|
||||
|
||||
Le prompt doit être assez complet pour éviter les rappels conversationnels récurrents, mais il ne devient pas une duplication exhaustive de `docs/rules/`.
|
||||
|
||||
Une taille de quelques centaines de lignes est acceptable lorsqu'elle porte du contexte opérationnel réel. Les listes de toutes les règles Rust ou de toutes les commandes du dépôt restent dans leurs documents normatifs ; le prompt cite les règles et reproduit seulement les garde-fous susceptibles d'être oubliés dans la version ciblée.
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/rules/RULES_COMMANDS.md -->
|
||||
<!-- version: 9 -->
|
||||
<!-- version: 13 -->
|
||||
|
||||
# Règles d'exécution des commandes
|
||||
|
||||
@@ -16,18 +16,20 @@
|
||||
- **CMD-GEN-009** — Lorsque l'utilisateur fournit une gate complète propre, le delta est considéré validé et le travail peut passer automatiquement au delta planifié suivant sauf instruction contraire.
|
||||
- **CMD-GEN-010** — Si une gate échoue, la progression vers le delta suivant est suspendue ; le correctif est livré sous le suffixe `.fix.N` du delta courant, sauf décision explicite contraire.
|
||||
- **CMD-GEN-011** — Les commandes d'audit Markdown couvrent également `history/` dès que cette arborescence existe.
|
||||
- **CMD-GEN-012** — Les audits Python sont sélectionnés selon les fichiers réellement touchés : audit Rust/workspace pour le périmètre Rust/Cargo/workspace concerné, audit Markdown pour les fichiers Markdown concernés, audit de distribution pour les changements de layout/build/packaging. Ils ne sont pas tous exécutés par habitude sur chaque delta.
|
||||
- **CMD-GEN-013** — Toute commande nécessitant un changement temporaire de répertoire est exécutée dans un sous-shell, par exemple `(cd Web/game-snake-poc && npm run build)`, afin de revenir automatiquement à la racine du workspace après la commande.
|
||||
|
||||
## Rust et Cargo
|
||||
|
||||
- **CMD-RUST-001** — Lorsqu’un delta a modifié au moins un fichier Rust, l’utilisateur exécute `cargo fmt --all` au début de la validation afin d’appliquer le formatage canonique; les changements purement produits par rustfmt constituent l’unique exception à l’incrément obligatoire de l’en-tête de version du fichier.
|
||||
- **CMD-RUST-002** — `cargo fmt --all -- --check` suit immédiatement le formatage et constitue la gate canonique de conformité rustfmt.
|
||||
- **CMD-RUST-003** — `cargo check --workspace` est la première gate de compilation globale après les audits statiques.
|
||||
- **CMD-RUST-004** — `cargo clippy --workspace --all-targets --all-features -- -D warnings` est exécuté après un `cargo check --workspace` propre pour la gate complète.
|
||||
- **CMD-RUST-005** — Les tests ciblés `cargo test -p <crate> --all-targets --all-features` sont la stratégie normale d’un delta et doivent couvrir toutes les crates directement ou transitivement affectées lorsque cela est raisonnablement déterminable.
|
||||
- **CMD-RUST-006** — `cargo test --workspace --all-targets --all-features` est une gate lourde réservée au démarrage d’une nouvelle version `X.Y.Z`, à la fin d’une phase/version, aux changements transverses importants ou lorsqu’il existe un doute raisonnable sur la portée des tests ciblés.
|
||||
- **CMD-RUST-001** — Dès qu'un delta modifie du code Rust, un manifeste Cargo, une feature ou une dépendance Rust, l'utilisateur exécute `cargo fmt --all`; les changements purement produits par rustfmt constituent l'unique exception à l'incrément obligatoire de l'en-tête de version du fichier.
|
||||
- **CMD-RUST-002** — `cargo fmt --all -- --check` suit le formatage et constitue la gate canonique de conformité rustfmt.
|
||||
- **CMD-RUST-003** — Tout delta qui touche du code Rust ou ses dépendances exécute `cargo check --workspace` après les audits statiques applicables. Un `cargo check -p <crate>` peut servir de diagnostic rapide, mais ne remplace pas cette gate workspace.
|
||||
- **CMD-RUST-004** — Tout delta qui touche du code Rust ou ses dépendances exécute ensuite `cargo clippy --workspace --all-targets --all-features -- -D warnings`. Cette gate n'est pas réservée aux seules phases finales.
|
||||
- **CMD-RUST-005** — Les tests ciblés `cargo test -p <crate> --all-targets --all-features` sont la stratégie normale d'un delta et couvrent les crates directement affectées ainsi que les consommateurs dont le contrat est réellement impacté.
|
||||
- **CMD-RUST-006** — `cargo test --workspace --all-targets --all-features` est une gate lourde exécutée seulement un petit nombre de fois explicitement prévues dans le plan de version/session, typiquement à une validation initiale si elle apporte une valeur réelle, à une validation préfinale/finale, lors d'un changement transverse important ou lorsqu'il existe un doute raisonnable sur la portée des tests ciblés. Elle n'est pas répétée à chaque delta.
|
||||
- **CMD-RUST-007** — `cargo run -p <desktop-runner>` sert aux smokes manuels Desktop et n'est pas substitué aux tests automatisés.
|
||||
- **CMD-RUST-008** — `cargo build` est utilisé lorsqu'un artefact exécutable ou une bibliothèque est réellement nécessaire ; il n'est pas lancé systématiquement en plus de `cargo check`.
|
||||
- **CMD-RUST-009** — `cargo tree` et ses variantes sont des commandes de diagnostic de dépendances, pas des gates obligatoires de chaque delta.
|
||||
- **CMD-RUST-009** — `cargo tree` et ses variantes ne sont exécutés que lorsqu'un delta modifie les dépendances/features, lorsqu'une frontière de dépendances doit être vérifiée ou lorsqu'un diagnostic explicite le justifie. Ils ne font pas partie de la validation automatique d'un delta sans changement de dépendances.
|
||||
- **CMD-RUST-010** — `cargo update` n'est jamais exécuté opportunistement. Toute mise à jour de dépendance doit appartenir à une tranche explicitement consacrée aux dépendances ou être nécessaire à la fonctionnalité en cours.
|
||||
- **CMD-RUST-011** — `cargo clean` est l'outil canonique de remise à zéro complète du cache de build Cargo et peut être utilisé périodiquement pour maîtriser la taille de `../builds/sasedev-games/target`.
|
||||
- **CMD-RUST-012** — Un nettoyage complet n'est pas exécuté à chaque delta. Il est planifié à un jalon de cycle approprié, normalement au démarrage de la première prerelease de développement lorsque l'ancien cache doit être évacué, ou au plus tard avant la validation finale RC/stable si l'accumulation disque le justifie.
|
||||
@@ -56,29 +58,35 @@
|
||||
|
||||
- **CMD-WEB-001** — Aucun gestionnaire de paquets JavaScript ni build Web n'est exécuté tant qu'un frontend Web réel n'a pas été introduit dans le dépôt.
|
||||
- **CMD-WEB-002** — Lorsqu'une cible Web existe, ses commandes de build et test sont documentées avant d'être ajoutées aux gates.
|
||||
- **CMD-WEB-003** — Le POC Tauri/WASM utilise `scripts/build_reflex_tauri_wasm.py` pour WASM et Vite/TypeScript pour le frontend local ; aucun site distant n'est requis.
|
||||
- **CMD-WEB-003** — Le POC Tauri/WASM historique `0.1.0` utilise `scripts/build_reflex_tauri_wasm.py` ; ce script reste une référence de baseline mais ne doit pas être réutilisé comme orchestrateur par un POC `0.3.x`, conformément à `CMD-BUILD-004`.
|
||||
- **CMD-WEB-004** — Les fichiers produits par `wasm-bindgen` sont générés localement et ne sont pas commités.
|
||||
- **CMD-WEB-005** — Dans une app Tauri, `npm` sert uniquement à gérer les dépendances frontend lorsque nécessaire, par exemple `npm i <package>`, `npm i -D <package>` ou leur opération inverse. Les scripts `npm run dev`, `npm run build` ou équivalents ne sont pas des gates manuelles : Vite/TypeScript/WASM sont déclenchés par les hooks Tauri configurés.
|
||||
- **CMD-WEB-006** — Le smoke normal d'une app Tauri est lancé via `(cd <tauri-app> && cargo tauri dev)`. Cette commande possède le serveur Vite et les hooks frontend nécessaires.
|
||||
- **CMD-WEB-007** — Le packaging Tauri est validé dans les phases finales prévues par le plan via `(cd <tauri-app> && cargo tauri build)`, typiquement en beta préfinale, RC ou avant release selon le scope. Il n'est pas exécuté après chaque petit delta Tauri.
|
||||
- **CMD-WEB-008** — Pour un host Web navigateur direct sous `Web/<game>/`, les commandes npm/Vite peuvent être exécutées directement, toujours dans un sous-shell lorsqu'un changement de répertoire est nécessaire, par exemple `(cd Web/<game> && npm install && npm run build)`.
|
||||
- **CMD-WEB-009** — Le build d'un host Web direct qui consomme un adapter `wasm-bindgen` exécute d'abord le build Rust/WASM et la génération des bindings hors dépôt, puis seulement le build TypeScript/Vite.
|
||||
- **CMD-WEB-010** — Un smoke navigateur manuel d'un host Web direct vérifie au minimum le chargement WASM, le Canvas, les entrées prévues par la tranche et le comportement responsive concerné.
|
||||
|
||||
## Git et fichiers générés
|
||||
|
||||
- **CMD-GIT-001** — Les commandes Git destructives (`reset --hard`, nettoyage forcé, réécriture non demandée) ne sont jamais utilisées pour remettre artificiellement le workspace en état.
|
||||
- **CMD-GIT-002** — Les fichiers générés ne sont pas commités sauf contrat explicite du dépôt ou exigence de distribution.
|
||||
|
||||
- **CMD-WEB-005** — `npm run dev` et `npm run build` du frontend Tauri sont pilotés par les hooks Tauri ; ils ne constituent pas des gates manuelles indépendantes.
|
||||
- **CMD-GIT-003** — Lorsqu'une archive fournie par l'utilisateur est déclarée comme téléchargement d'un tag du dépôt, cette archive est la baseline autoritaire de ce tag. L'absence de `.git` dans l'archive est normale et ne constitue ni une anomalie ni une validation manquante.
|
||||
- **CMD-GIT-004** — Les contrôles nécessitant le répertoire `.git` s'appliquent uniquement à un checkout Git local lorsqu'il est effectivement fourni ; sur une archive taggée, on contrôle la cohérence interne des versions et fichiers sans inventer un état Git inaccessible.
|
||||
|
||||
## Beta et packaging
|
||||
|
||||
- **CMD-BETA-001** — À l'entrée en beta, `scripts/audit_distribution_layout.py` vérifie les frontières statiques nécessaires aux runners et packagings supportés.
|
||||
- **CMD-BETA-002** — La transition alpha vers beta exécute une suite Cargo workspace complète en plus des tests ciblés.
|
||||
- **CMD-BETA-003** — Si la version touche le périmètre Tauri, au moins un build de packaging beta est lancé via `cargo tauri build`; ses hooks possèdent le build WASM et Vite/TypeScript.
|
||||
- **CMD-BETA-003** — Si la version touche le périmètre Tauri, le plan réserve au moins une validation de packaging dans une phase finale appropriée via `(cd <tauri-app> && cargo tauri build)` ; les itérations et smokes courants utilisent `cargo tauri dev`.
|
||||
- **CMD-BETA-004** — Les APK Debug servent à la validation multi-appareils beta ; la signature de publication appartient à la phase RC/stable.
|
||||
|
||||
## RC et release
|
||||
|
||||
- **CMD-RC-001** — L'entrée en RC gèle le périmètre fonctionnel de `0.1.0` ; seuls les correctifs, la reproductibilité des builds, le packaging, la documentation de livraison et les défauts de release sont admis.
|
||||
- **CMD-RC-001** — L'entrée en RC gèle le périmètre fonctionnel de la version courante ; seuls les correctifs, la reproductibilité des builds, le packaging, la documentation de livraison et les défauts de release sont admis.
|
||||
- **CMD-RC-002** — La validation d'une RC exécute `cargo test --workspace --all-targets --all-features` en plus des audits, du check et de Clippy strict.
|
||||
- **CMD-RC-003** — Les deux runners Desktop natifs sont construits en `--release` et font l'objet d'un smoke sur les binaires de release.
|
||||
- **CMD-RC-004** — Le POC Tauri est construit uniquement via `cargo tauri build`; ses hooks possèdent toujours le build WASM et Vite/TypeScript.
|
||||
- **CMD-RC-004** — Une RC Tauri est construite via `(cd <tauri-app> && cargo tauri build)` ; ses hooks possèdent toujours le build WASM et Vite/TypeScript. Les smokes interactifs restent lancés avec `(cd <tauri-app> && cargo tauri dev)`.
|
||||
- **CMD-RC-005** — Android RC revalide au minimum x86_64 sur AVD et ARM64 sur appareil réel avec les APK issus de l'état RC.
|
||||
- **CMD-RC-006** — Les secrets de signature, keystores et credentials de publication ne sont jamais commités. Leur présence est une condition externe de publication, pas une donnée du dépôt.
|
||||
- **CMD-RC-007** — Une RC n'est promue en stable que si aucun correctif `.fix.N` n'est nécessaire après la gate RC complète.
|
||||
@@ -92,7 +100,7 @@
|
||||
## Outils de build et scripts d'audit
|
||||
|
||||
- **CMD-BUILD-001** — Les scripts Python du dépôt sont autorisés pour les audits, audits complémentaires, validations et validations complémentaires.
|
||||
- **CMD-BUILD-002** — Un script Python ne pilote pas le build d'un produit, d'une plateforme ou d'un package distribué.
|
||||
- **CMD-BUILD-002** — À partir de `0.3.x`, aucun chemin de build nouveau ou modifié n’est piloté par Python. Les orchestrateurs historiques `scripts/build_reflex_tauri_wasm.py` et `scripts/build_android_rust.py` restent tolérés uniquement comme mécanismes gelés de la baseline `0.1.0` jusqu’à la tranche qui réactive leur chemin ; ils ne sont ni copiés, ni généralisés, ni utilisés pour un nouveau POC.
|
||||
- **CMD-BUILD-003** — Les builds utilisent l'outil natif approprié au périmètre : Cargo pour Rust, Gradle pour Android, Tauri CLI pour Tauri, ou l'outil officiellement retenu par la plateforme concernée.
|
||||
- **CMD-BUILD-004** — Les POC `0.3.x` doivent remplacer toute orchestration de build Python restante par des procédures explicites, reproductibles et testées avec les outils natifs.
|
||||
- **CMD-BUILD-005** — Les builds, tests unitaires, tests d'intégration et smoke tests de validation sont exécutés côté utilisateur ; les scripts d'audit peuvent vérifier statiquement leur préparation mais ne les simulent pas.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/rules/RULES_DOCUMENTATION.md -->
|
||||
<!-- version: 6 -->
|
||||
<!-- version: 8 -->
|
||||
|
||||
# Règles de documentation
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
- **DOC-CAT-006** — Les documents spécialisés existants (`games/`, `engine/`, `monetization/`, `services/`, `development/`, `testing/`, `validation/`) conservent leur rôle fonctionnel et ne servent pas de dépôt générique d'idées.
|
||||
- **DOC-CAT-007** — Une information peut mûrir de `idea` vers `study`, puis vers une décision d'architecture ou une réservation de capability ; ce passage est explicite et n'est jamais déduit de la seule présence d'un texte.
|
||||
- **DOC-CAT-008** — Une étude peut conclure à `retained`, `deferred`, `rejected` ou `needs-poc` sans créer automatiquement une capability, une crate ou une entrée de roadmap.
|
||||
- **DOC-CAT-009** — `docs/plans/` contient les plans vivants des versions concrètes. Un plan détaille le scope, les décisions, les validations et surtout le découpage prévisionnel souple des prereleases ; il ne remplace ni `ROADMAP.md` ni les deltas.
|
||||
|
||||
## Nomenclature documentaire
|
||||
|
||||
@@ -40,6 +41,14 @@
|
||||
- **DOC-NAME-007** — Dans un répertoire documentaire destiné à contenir plusieurs fichiers Markdown, le point d'entrée porte le nom `000-README.md` afin d'être trié en premier.
|
||||
- **DOC-NAME-008** — Un nouveau répertoire documentaire multi-fichiers ne crée pas de `README.md` concurrent à `000-README.md`.
|
||||
|
||||
## Documentation des crates, applications et packages
|
||||
|
||||
- **DOC-CRATE-001** — Toute nouvelle crate, application ou package frontend évalue explicitement pendant son cadrage puis sa consolidation finale si un `README.md` ou un `USAGE.md` apporte une information durable utile ; ces fichiers ne sont jamais créés uniquement pour satisfaire une cérémonie.
|
||||
- **DOC-CRATE-002** — Un `README.md` local décrit la responsabilité, les frontières, les dépendances structurantes et les principaux points d'entrée lorsqu'un composant devient durable ou réutilisable et que ces informations ne sont pas suffisamment couvertes par une documentation centrale.
|
||||
- **DOC-CRATE-003** — Un `USAGE.md` est ajouté lorsqu'une API, un binaire, une application ou un package possède un workflow de consommation/opérateur, des préconditions, des commandes, de la configuration ou des exemples suffisamment non triviaux pour mériter un guide stable.
|
||||
- **DOC-CRATE-004** — Un adapter ou POC très petit peut rester documenté uniquement par les documents d'architecture/développement existants lorsque cela couvre réellement son contrat ; l'absence de `README.md`/`USAGE.md` doit alors être un choix de valeur documentaire, pas un oubli.
|
||||
- **DOC-CRATE-005** — `README.md` et `USAGE.md` restent durables et ne contiennent pas de journal de release ; les changements de version appartiennent à `CHANGELOG.md`, `deltas/` et `history/`.
|
||||
|
||||
## Listes de tâches et d'état
|
||||
|
||||
- **DOC-TASK-001** — Toute liste Markdown qui représente durablement des tâches, objectifs ou éléments suivis utilise les marqueurs `( )`, `(x)`, `(d)` et `(c)` plutôt que les task lists Markdown `[ ]` / `[x]`.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/rules/RULES_PROJECT.md -->
|
||||
<!-- version: 11 -->
|
||||
<!-- version: 16 -->
|
||||
|
||||
# Règles spécifiques games.sasedev
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
- **GAME-WS-006** — Les dépendances tierces communes sont centralisées sous `[workspace.dependencies]` et consommées avec `workspace = true` lorsqu'elles sont partagées.
|
||||
- **GAME-WS-007** — Un jeu est prioritairement une crate `lib`; lorsqu’un lancement Desktop est nécessaire, une crate `bin` séparée sous `crates/apps/` dépend de cette lib et ne duplique pas son gameplay.
|
||||
- **GAME-WS-008** — Les runners Desktop sont nommés `<game>-desktop` et restent indépendants des frontends Android.
|
||||
- **GAME-WS-009** — Les hosts Web navigateur directs résident sous `Web/<game>/`, hors du workspace Cargo ; ils consomment un adapter WASM dédié et ne contiennent ni crate Rust ni règle de gameplay.
|
||||
|
||||
## Générations du moteur
|
||||
|
||||
@@ -30,6 +31,7 @@
|
||||
- **GAME-ASSET-004** — Chaque jeu peut posséder `assets/<game>/` pour ses ressources spécifiques.
|
||||
- **GAME-ASSET-005** — Le packaging de chaque plateforme assemble les assets communs et spécifiques sans créer de copie source durable dans une crate.
|
||||
- **GAME-ASSET-006** — Les chemins logiques d'assets doivent éviter les collisions entre espace commun et espace jeu.
|
||||
- **GAME-ASSET-007** — Un host Web direct package les assets runtime communs et spécifiques depuis `assets/` vers les namespaces de distribution `common/` et `game/` sans créer de copie source durable sous `Web/`; le smoke doit charger au moins un asset de chaque namespace lorsqu'une tranche déclare l'intégration assets complète.
|
||||
|
||||
## Android
|
||||
|
||||
@@ -63,6 +65,7 @@
|
||||
- **GAME-TRACE-002** — `tracing-subscriber` compose les subscribers applicatifs et de test ; une librairie métier ne configure pas silencieusement le subscriber global.
|
||||
- **GAME-TRACE-003** — `tracing-appender` est utilisé lorsque l’écriture non bloquante ou les fichiers de logs deviennent nécessaires ; le guard associé reste vivant pendant toute la durée utile.
|
||||
- **GAME-TRACE-004** — La configuration de logging commune réside dans une crate transverse et ne doit pas être dupliquée par jeu.
|
||||
- **GAME-TRACE-005** — Un host navigateur direct peut émettre ses diagnostics frontend dans la console du navigateur via un module TypeScript structuré dédié ; ce mécanisme ne remplace pas `tracing` dans le code Rust et ne doit pas importer le bridge tracing Tauri lorsqu'aucun host Tauri n'est présent.
|
||||
|
||||
- **GAME-PLATFORM-009** — Une adaptation WebAssembly réutilisable est une crate dédiée distincte de la crate Tauri.
|
||||
- **GAME-PLATFORM-010** — Dans une app Tauri, `lib.rs` reste une façade/reexport ; `tauri.rs` assemble Tauri et expose les commandes qui délèguent aux modules propriétaires.
|
||||
@@ -82,6 +85,12 @@
|
||||
- **GAME-PLATFORM-017** — Téléphone, tablette et futures classes de device sont des dimensions distinctes de l'OS et du backend technique.
|
||||
- **GAME-PLATFORM-018** — SDL3 reste le backend natif de référence du POC, mais l'architecture de jeu ne doit pas assimiler une plateforme à SDL ni empêcher un adapter différent lorsque la plateforme l'exige.
|
||||
- **GAME-PLATFORM-019** — Une plateforme réservée n'est ni implémentée ni planifiée tant qu'une ligne ROADMAP ou un delta ne l'engage explicitement.
|
||||
- **GAME-PLATFORM-020** — Un host Web navigateur possède un shell HTML/CSS/TypeScript explicite autour du Canvas/WASM. Le framework de présentation éventuel reste une dépendance frontend et ne fuit ni dans la crate de gameplay ni dans le bridge WASM ; pour le premier POC Snake `0.3.0`, Bootstrap 5 est la baseline de présentation retenue.
|
||||
- **GAME-PLATFORM-021** — Les dépendances de présentation nécessaires au runtime Web versionné sont déclarées dans le package frontend et intégrées au build Vite ; un CDN externe n'est pas requis pour exécuter le POC local et ne devient une dépendance de distribution qu'après décision explicite.
|
||||
- **GAME-PLATFORM-022** — SimpleBar et `resize-observer-polyfill` sont des dépendances de shell Web, pas des dépendances Tauri. Lorsqu'un host conserve header et footer fixes, la zone centrale bornée à la hauteur disponible peut les utiliser pour fournir un scroll interne personnalisé sans déplacer les éléments fixes.
|
||||
- **GAME-PLATFORM-023** — Lorsqu'un host Web reprend le shell KSP avec SimpleBar, `app-main` borne la hauteur disponible et reste non scrollable ; `data-simplebar` appartient à l'enfant central `app-content app-scrollable h-100`, dont `height` et `max-height` valent `100%`. Le polyfill `ResizeObserver` est installé avant l'initialisation applicative et le package `simplebar` est importé par le point d'entrée TypeScript.
|
||||
- **GAME-PLATFORM-024** — Un host navigateur à simulation fixed-step suspend ses ticks lorsque le document devient caché ou passe en `pagehide`, puis reprend avec une nouvelle origine temporelle sans rattrapage massif au retour ; le resize peut redessiner la scène sans avancer la simulation.
|
||||
- **GAME-PLATFORM-025** — La provenance d'un host navigateur est construite via `engine-v1-platform-api` avec `PlatformFamily::Web`, `ExecutionModel::Wasm` et `RuntimeHost::Browser`; la classe d'appareil et le profil d'entrée restent des dimensions observées par le host, sans identification matérielle fine.
|
||||
|
||||
## Version d'en-tête des fichiers
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/rules/RULES_SESSION_PLANNING.md -->
|
||||
<!-- version: 1 -->
|
||||
<!-- version: 5 -->
|
||||
|
||||
# Règles de cadrage des versions, sessions et prompts
|
||||
|
||||
@@ -13,6 +13,11 @@ Ces règles imposent un découpage suffisamment petit pour qu'une version puisse
|
||||
- **SESSION-002** — Cette tranche couvre au minimum l'audit de la base, le brainstorming/recherche de requirements, le sizing, les dépendances, les validations prévues et le découpage prévisionnel.
|
||||
- **SESSION-003** — Une première implémentation peut être incluse dans `0-pre.1` uniquement si elle est petite, cohérente et n'empêche pas le cadrage d'être terminé.
|
||||
- **SESSION-004** — Si le sizing montre que l'objectif global ne peut raisonnablement pas être terminé dans la session, il est scindé en plusieurs versions avant le développement lourd.
|
||||
- **SESSION-005** — `0-pre.1` crée ou révise obligatoirement le plan de la version sous `docs/plans/`. Ce plan est un livrable du cadrage, pas une note optionnelle.
|
||||
- **SESSION-006** — Le plan de version contient au minimum l'objectif et le scope, les décisions acquises, les dépendances/risques utiles, les validations attendues, les hors-périmètre et une prévision souple des tranches jusqu'à la release stable.
|
||||
- **SESSION-007** — La prévision du plan n'est pas un calendrier figé : une tranche peut être scindée, fusionnée, déplacée ou complétée par un fix lorsque les résultats réels le justifient. Le plan actif est alors réconcilié et le delta explique le changement.
|
||||
- **SESSION-008** — `ROADMAP.md` reste macroscopique, le plan porte le découpage prévisionnel fin de la version et les deltas enregistrent ce qui a réellement été livré.
|
||||
- **SESSION-009** — Le forecast créé en `0-pre.1` rend explicitement visible une tranche de consolidation avant la candidate finale ; cette tranche couvre au minimum la réconciliation de la documentation durable, `CHANGELOG.md`, `ROADMAP.md`, l'historique applicable et le prompt de la version/session suivante, même si son numéro exact reste prévisionnel.
|
||||
|
||||
## Taille des tranches
|
||||
|
||||
@@ -21,12 +26,14 @@ Ces règles imposent un découpage suffisamment petit pour qu'une version puisse
|
||||
- **SESSION-012** — Plusieurs micro-tranches sans valeur de validation indépendante peuvent être regroupées.
|
||||
- **SESSION-013** — Le découpage suit des unités fonctionnelles complètes et validables ; une fonctionnalité ne doit pas être volontairement coupée au milieu uniquement pour respecter un numéro de prerelease.
|
||||
- **SESSION-014** — Chaque tranche livre son delta et ses validations proportionnelles avant la tranche suivante.
|
||||
- **SESSION-015** — Le plan créé en `0-pre.1` identifie explicitement le ou les rares jalons où `cargo test --workspace --all-targets --all-features` apporte une valeur globale (initial si nécessaire, préfinal/final ou changement transverse). Les autres tranches privilégient les tests `cargo test -p ...` ciblés.
|
||||
|
||||
## Une version par session
|
||||
|
||||
- **SESSION-020** — Une session de développement vise une version complète, de son cadrage jusqu'à sa release ou à sa candidate de publication selon le scope décidé.
|
||||
- **SESSION-021** — Une session ne doit pas être planifiée de façon à s'arrêter normalement au milieu d'une version.
|
||||
- **SESSION-022** — Si de nouvelles informations rendent la version trop grande, le scope restant est replanifié explicitement vers une version suivante au lieu de prolonger indéfiniment la session.
|
||||
- **SESSION-020** — Une session de développement est dimensionnée pour livrer au minimum une version concrète complète, de son cadrage jusqu'à sa release stable.
|
||||
- **SESSION-021** — Une prerelease est une tranche interne de progression et ne constitue pas une cible normale de fin de session ; la session ne doit pas être planifiée pour s'arrêter au milieu de la version ouverte.
|
||||
- **SESSION-022** — Si de nouvelles informations rendent la version trop grande, le scope restant est replanifié explicitement vers une ou plusieurs versions suivantes au lieu de prolonger indéfiniment la version courante.
|
||||
- **SESSION-023** — Le découpage prévisionnel doit donc permettre de suivre toute la progression de la version dans la même session, tout en restant assez souple pour insérer des fixes ou déplacer du scope sans forcer artificiellement la fermeture.
|
||||
|
||||
## Dernières tranches
|
||||
|
||||
@@ -43,6 +50,7 @@ Ces règles imposent un découpage suffisamment petit pour qu'une version puisse
|
||||
- **PROMPT-006** — Le prompt contient suffisamment de contexte pour reprendre la version sans dépendre de la mémoire conversationnelle ni relire toute l'histoire du dépôt.
|
||||
- **PROMPT-007** — Le prompt précise la condition de fin de session et les livrables attendus.
|
||||
- **PROMPT-008** — Si `pre.1` invalide le sizing prévu par le prompt, le nouveau découpage est documenté immédiatement avant le développement lourd.
|
||||
- **PROMPT-009** — Tout nouveau prompt de version applique `docs/rules/PROMPT_STRUCTURE.md`; le présent document fixe le cycle de session tandis que `PROMPT_STRUCTURE.md` fixe le contenu opératoire à rappeler.
|
||||
|
||||
## Relation avec VERSION_WORKFLOW
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/rules/RULES_VALIDATION_MATRIX.md -->
|
||||
<!-- version: 2 -->
|
||||
<!-- version: 4 -->
|
||||
|
||||
# Matrice normative des commandes et validations
|
||||
|
||||
@@ -14,30 +14,46 @@ Les commandes ciblées restent la norme pendant l'implémentation ; les gates wo
|
||||
## Matrice
|
||||
|
||||
| ID | Commande / action | Dépend de | Déclencheur principal | Phase minimale typique |
|
||||
|-----------|------------------------------------------------------------------------------------|-------------------------------------|--------------------------------------------|------------------------|
|
||||
| `CMD-001` | `cargo fmt --all` | — | source Rust modifié | `pre` |
|
||||
| `CMD-002` | `cargo fmt --all -- --check` | `CMD-001` si formatage requis | source Rust modifié | `pre` |
|
||||
| `CMD-010` | `python3 scripts/audit_rust_workspace_rules.py` | — | Rust/workspace/règles Rust | `pre` |
|
||||
| `CMD-011` | `python3 scripts/audit_markdown_tables.py ...` | — | Markdown/règles/docs | `pre` |
|
||||
| `CMD-012` | `python3 scripts/audit_distribution_layout.py` | — | layout/build/distribution | `pre` |
|
||||
| `CMD-020` | `cargo check -p <crate>` | `CMD-002`, `CMD-010` | crate Rust ciblée | `pre` |
|
||||
| `CMD-021` | `cargo test -p <crate> --all-targets --all-features` | `CMD-020` | comportement/API crate | `pre` |
|
||||
| `CMD-022` | tests des crates consommatrices impactées | `CMD-021` | API publique/contrat partagé modifié | `pre` |
|
||||
| `CMD-023` | `cargo check --workspace` | audits applicables | changement transverse / gate globale | selon portée |
|
||||
| `CMD-024` | `cargo clippy --workspace --all-targets --all-features -- -D warnings` | `CMD-023` | gate complète | alpha/beta/RC |
|
||||
| `CMD-025` | `cargo test --workspace --all-targets --all-features` | `CMD-024` | changement transverse / frontière de phase | beta/RC |
|
||||
|-----------|------------------------------------------------------------------------------------|---------------------------------|----------------------------------------------------|------------------------|
|
||||
| `CMD-001` | `cargo fmt --all` | — | Rust ou dépendance Cargo modifiée | `pre` |
|
||||
| `CMD-002` | `cargo fmt --all -- --check` | `CMD-001` | Rust ou dépendance Cargo modifiée | `pre` |
|
||||
| `CMD-010` | `python3 scripts/audit_rust_workspace_rules.py` | — | Rust/Cargo/workspace/règles Rust concernés | `pre` |
|
||||
| `CMD-011` | `python3 scripts/audit_markdown_tables.py ...` | — | Markdown concerné | `pre` |
|
||||
| `CMD-012` | `python3 scripts/audit_distribution_layout.py` | — | layout/build/distribution concerné | `pre` |
|
||||
| `CMD-020` | `cargo check -p <crate>` | audits applicables | diagnostic ciblé facultatif | `pre` |
|
||||
| `CMD-021` | `cargo test -p <crate> --all-targets --all-features` | `CMD-023`, `CMD-024` | comportement/API crate | `pre` |
|
||||
| `CMD-022` | tests ciblés des crates consommatrices impactées | `CMD-021` | API publique/contrat partagé modifié | `pre` |
|
||||
| `CMD-023` | `cargo check --workspace` | `CMD-002`, audits applicables | Rust ou dépendance Cargo modifiée | `pre` |
|
||||
| `CMD-024` | `cargo clippy --workspace --all-targets --all-features -- -D warnings` | `CMD-023` | Rust ou dépendance Cargo modifiée | `pre` |
|
||||
| `CMD-025` | `cargo test --workspace --all-targets --all-features` | `CMD-024` | gate rare planifiée / portée transverse incertaine | selon plan |
|
||||
| `CMD-026` | `cargo tree -p <crate> --edges normal` ou variante ciblée | — | dépendances/features modifiées ou diagnostic | selon portée |
|
||||
| `CMD-030` | build Desktop `--release` ciblé | gates Rust applicables | runner/distribution Desktop touché | beta |
|
||||
| `CMD-031` | smoke Desktop release | `CMD-030` | runtime Desktop touché | beta |
|
||||
| `CMD-040` | `cargo tauri build` | gates Rust/frontend applicables | périmètre Tauri touché | beta |
|
||||
| `CMD-041` | smoke Tauri release | `CMD-040` | runtime Tauri touché | beta |
|
||||
| `CMD-040` | `(cd <tauri-app> && cargo tauri dev)` | gates Rust/frontend applicables | smoke interactif Tauri | `pre`/beta |
|
||||
| `CMD-041` | `(cd <tauri-app> && cargo tauri build)` | gates Rust/frontend applicables | packaging Tauri final/prefinal | beta/RC |
|
||||
| `CMD-042` | build Rust `wasm32-unknown-unknown` + `wasm-bindgen --target web` | gates Rust de l'adapter | adapter WASM/Web direct touché | `pre` |
|
||||
| `CMD-043` | `(cd Web/<game> && npm install && npm run build)` | `CMD-042` si frontend avec WASM | frontend Web direct touché | `pre` |
|
||||
| `CMD-044` | smoke navigateur du host Web direct | `CMD-043` | Canvas/input/responsive Web touchés | `pre`/beta |
|
||||
| `CMD-050` | build Rust Android ABI ciblé | gates Rust applicables | Android/JNI/backend natif touché | pre/beta |
|
||||
| `CMD-051` | Gradle `assembleDebug` application ciblée | `CMD-050` lorsque Rust natif change | Android/app/manifest/Java touché | pre/beta |
|
||||
| `CMD-051` | `(cd Android && ./gradlew :<app>:assembleDebug)` | `CMD-050` si Rust natif change | Android/app/manifest/Java touché | pre/beta |
|
||||
| `CMD-052` | install + smoke AVD | `CMD-051` | Android concerné | beta |
|
||||
| `CMD-053` | install + smoke appareil réel | `CMD-051` | Android concerné | beta/RC |
|
||||
| `CMD-060` | `cargo clean --dry-run --verbose` | — | contrôle disque / préparation nettoyage | maintenance |
|
||||
| `CMD-061` | `cargo clean` | décision explicite de nettoyage | accumulation disque / jalon de cycle | maintenance |
|
||||
| `CMD-062` | `cargo clean -p <package>` ou nettoyage par `--release` / `--profile` / `--target` | — | nettoyage ciblé suffisant | maintenance |
|
||||
|
||||
## Sélection proportionnelle
|
||||
|
||||
Les audits `CMD-010` à `CMD-012` sont sélectionnés selon les fichiers touchés ; ils ne forment pas un trio obligatoire.
|
||||
|
||||
Dès que du Rust ou une dépendance Cargo change, la séquence minimale obligatoire est `CMD-001` → `CMD-002` → audits applicables → `CMD-023` → `CMD-024`. Les tests `CMD-021`/`CMD-022` restent ciblés par défaut.
|
||||
|
||||
`CMD-025` est planifié seulement à un ou quelques jalons de la version/session, par exemple un état initial lorsqu'une baseline globale doit être confirmée, une validation préfinale/finale, ou un changement dont la portée transverse ne peut pas être bornée avec confiance.
|
||||
|
||||
`CMD-026` est ajouté lorsqu'un graphe de dépendances/features a changé ou doit être diagnostiqué ; il est omis des validations ordinaires sans changement de dépendances.
|
||||
|
||||
Toute commande avec changement de répertoire utilise un sous-shell, comme le montrent `CMD-040`, `CMD-041`, `CMD-043` et `CMD-051`.
|
||||
|
||||
## Dépendances entre crates
|
||||
|
||||
Lorsqu'une crate `A` change :
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/rules/VERSION_WORKFLOW.md -->
|
||||
<!-- version: 3 -->
|
||||
<!-- version: 6 -->
|
||||
|
||||
# Versionnement, maturité et livraisons
|
||||
|
||||
@@ -98,9 +98,16 @@ La promotion `rc` puis stable d'une version de conception exige une validation h
|
||||
|
||||
## Prompt de la version suivante
|
||||
|
||||
- **VER-PROMPT-001** — Le prompt de démarrage de la version suivante n'est pas créé à un numéro arbitraire de RC.
|
||||
- **VER-PROMPT-002** — Sa génération devient recommandée après validation de la première RC dont le périmètre est effectivement gelé.
|
||||
- **VER-PROMPT-001** — Le prompt de démarrage de la version suivante est rédigé pendant la consolidation finale lorsque la cible suivante est suffisamment connue ; il ne dépend pas d'une future session pour exister.
|
||||
- **VER-PROMPT-002** — La première RC dont le périmètre est effectivement gelé vérifie et complète ce prompt à partir de l'état réellement candidat à publication.
|
||||
- **VER-PROMPT-003** — Le prompt peut être complété pendant les fixes RC ou la release stable, mais ne doit pas contenir de résultats futurs présentés comme déjà validés.
|
||||
- **VER-PROMPT-004** — La structure et les rappels opératoires obligatoires du prompt sont définis par `docs/rules/PROMPT_STRUCTURE.md`.
|
||||
|
||||
## Correctifs strictement documentaires
|
||||
|
||||
- **VER-DOCFIX-001** — Un `.fix.N` limité à la documentation, aux prompts, aux deltas, à `history/` ou aux règles non consommées par le build/runtime ne modifie aucune version technique : ni `workspace.package.version`/`Cargo.toml`, ni `package.json`, ni Gradle/Android, ni `tauri.conf.json`, ni autre métadonnée de version consommée par un build ou une distribution. L'identité du correctif est portée uniquement par le delta et son archive.
|
||||
- **VER-DOCFIX-002** — Une prerelease non-fix (`pre.N`, `alpha.N`, `beta.N`, `rc.N`) synchronise sa version technique selon le workflow de phase même lorsque son contenu est principalement documentaire.
|
||||
- **VER-DOCFIX-003** — Dès qu'un correctif touche du code, une configuration exécutable, un manifeste consommé par le build/runtime ou un artefact distribué, la version technique suit l'identifiant `.fix.N`.
|
||||
|
||||
## Phases de développement
|
||||
|
||||
@@ -111,10 +118,10 @@ PLAN → IMPLEMENT → INTEGRATE → VALIDATE → CANDIDATE → RELEASE
|
||||
```
|
||||
|
||||
- **VER-PHASE-001** — Ces phases structurent le travail mais n'imposent pas une prerelease distincte pour chacune.
|
||||
- **VER-PHASE-002** — `0-pre.1` est obligatoirement la tranche de cadrage de la version : audit de la base, brainstorming/recherche de requirements, sizing, planification, dépendances, validations attendues et découpage prévisionnel.
|
||||
- **VER-PHASE-002** — `0-pre.1` est obligatoirement la tranche de cadrage de la version : audit de la base, brainstorming/recherche de requirements, sizing, planification, dépendances, validations attendues et création/révision du plan actif sous `docs/plans/` avec son découpage prévisionnel souple.
|
||||
- **VER-PHASE-003** — `0-pre.1` peut aussi contenir une première implémentation strictement bornée si le cadrage montre qu'elle tient naturellement dans la même tranche, mais le cadrage ne doit jamais être sauté.
|
||||
- **VER-PHASE-004** — Une version doit être dimensionnée pour que l'ensemble de son développement puisse être terminé dans une seule session de travail. Si ce n'est pas réaliste, son objectif est découpé en plusieurs versions/sessions avant le développement lourd.
|
||||
- **VER-PHASE-005** — Le plan établi en `0-pre.1` est vivant : il peut regrouper, scinder, reporter ou reclasser des tranches lorsque l'information réelle le justifie, sans réécrire les deltas déjà livrés.
|
||||
- **VER-PHASE-005** — Le plan établi en `0-pre.1` est vivant : il peut regrouper, scinder, reporter ou reclasser des tranches lorsque l'information réelle le justifie, sans réécrire les deltas déjà livrés. Il reste la référence de suivi prévisionnel de la version jusqu'à sa clôture.
|
||||
- **VER-PHASE-006** — Une tranche `pre.N`, `alpha.N`, `beta.N`, `rc.N` ou leur fix vise normalement un delta réalisable en environ 15 à 30 minutes. Une tranche sensiblement plus lourde est découpée avant exécution ; une tranche trop petite peut être regroupée avec une tranche adjacente cohérente.
|
||||
- **VER-PHASE-007** — Le découpage privilégie des unités fonctionnelles complètes et validables, pas des coupures arbitraires au milieu d'une fonctionnalité.
|
||||
- **VER-PHASE-008** — Chaque tranche ferme son propre scope, produit son delta et ses validations proportionnelles avant l'ouverture de la tranche suivante.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/studies/000-README.md -->
|
||||
<!-- version: 8 -->
|
||||
<!-- version: 9 -->
|
||||
|
||||
# Études
|
||||
|
||||
@@ -53,3 +53,7 @@ Ces documents étudient les POC à réaliser ; ils ne lancent encore aucune impl
|
||||
- [`020-UROBURAS_CRATE_DECOMPOSITION_STUDY.md`](020-UROBURAS_CRATE_DECOMPOSITION_STUDY.md) — proposition de familles de crates et dépendances sans monolithe jeu.
|
||||
- [`021-UROBURAS_SERVER_REFERENCE_STACK.md`](021-UROBURAS_SERVER_REFERENCE_STACK.md) — stack serveur de référence Actix/Tokio/tokio-tungstenite/Maud/Fluent/Lettre et gRPC/Tonic conditionnel.
|
||||
- [`022-UROBURAS_IMPLEMENTATION_DEPENDENCY_ORDER.md`](022-UROBURAS_IMPLEMENTATION_DEPENDENCY_ORDER.md) — ordre d'implémentation recommandé pour le Mode 1 avant les modes multijoueurs.
|
||||
|
||||
## Étude de cadrage 0.3.0
|
||||
|
||||
- [`023-V0_3_0_PLATFORM_POC_AUDIT.md`](023-V0_3_0_PLATFORM_POC_AUDIT.md) — audit réel de la baseline `0.2.0`, requirements Snake, graphe de dépendances, choix du premier POC et sizing corrigé de `0.3.0`.
|
||||
|
||||
354
docs/studies/023-V0_3_0_PLATFORM_POC_AUDIT.md
Normal file
354
docs/studies/023-V0_3_0_PLATFORM_POC_AUDIT.md
Normal file
@@ -0,0 +1,354 @@
|
||||
<!-- file: docs/studies/023-V0_3_0_PLATFORM_POC_AUDIT.md -->
|
||||
<!-- version: 2 -->
|
||||
|
||||
# 0.3.0 — audit de baseline et cadrage du premier POC plateforme
|
||||
|
||||
## Statut
|
||||
|
||||
Étude de cadrage pour `0.3.0-0-pre.1`.
|
||||
|
||||
Elle décrit l'état observé de la stable `0.2.0`, les requirements réellement nécessaires à Snake, le premier POC retenu et le sizing corrigé. Elle ne transforme pas encore les extractions candidates en architecture durable.
|
||||
|
||||
## Base inspectée
|
||||
|
||||
Base déclarée : tag stable `v0.2.0`, fourni sous forme d'archive `games-v0.2.0.zip`.
|
||||
|
||||
L'intégrité ZIP est propre. L'archive est fournie explicitement comme téléchargement du tag stable `v0.2.0` et constitue donc la baseline autoritaire de ce tag conformément à `CMD-GIT-003`. L'absence de `.git` dans une archive de tag est normale et ne constitue pas une validation manquante ; les contrôles Git locaux ne s'appliquent que lorsqu'un checkout Git est effectivement fourni.
|
||||
|
||||
La version workspace observée avant modification est `0.2.0`.
|
||||
|
||||
## Audits officiels exécutés sur la baseline
|
||||
|
||||
Les audits en lecture seule suivants passent sur la baseline telle que livrée :
|
||||
|
||||
```text
|
||||
General Rust rule audit: clean
|
||||
Rust export completeness audit: 0 candidate(s)
|
||||
games.sasedev workspace audit: clean
|
||||
Markdown table audit: clean (4 table(s), 158 file(s))
|
||||
Distribution layout audit: clean (19 required path(s), 1 forbidden path(s) absent)
|
||||
```
|
||||
|
||||
Ces résultats valident uniquement les contrôles mécaniques réellement couverts par les scripts. La revue manuelle des règles a détecté des écarts supplémentaires.
|
||||
|
||||
## Écarts de baseline détectés
|
||||
|
||||
### README de version obsolète
|
||||
|
||||
`README.md` annonce encore `0.1.0` comme stable et `0.2.0` comme candidate alors que l'archive est la stable `0.2.0`.
|
||||
|
||||
Correction dans `0-pre.1` : afficher `0.2.0` comme stable de référence et `0.3.0-0-pre.1` comme version de développement.
|
||||
|
||||
### ROADMAP stable non fermé
|
||||
|
||||
`ROADMAP.md` conserve quatre lignes `( )` sous `0.2.0`. Cela contredit `DOC-RMAP-010`, qui interdit du scope encore planifié sous une version stable clôturée.
|
||||
|
||||
La revue du contenu `0.2.0` montre que :
|
||||
|
||||
- layering et dépendances ont été couverts par les études puis l'architecture consolidée ;
|
||||
- matrice plateforme et pressure tests ont été produits ;
|
||||
- la composition Rust statique a été retenue ;
|
||||
- le manifest produit/jeu et l'architecture physique définitive des crates ne sont volontairement pas figés ;
|
||||
- la trajectoire `0.3.x` puis `0.4.x` a été définie.
|
||||
|
||||
Correction dans `0-pre.1` : fermer les lignes réellement livrées et marquer explicitement le manifest/shape physique définitif comme reporté.
|
||||
|
||||
### Effet de bord de la gate d'audit Python
|
||||
|
||||
Le ZIP `v0.2.0` ne contient aucun `__pycache__` ni fichier `.pyc`. En revanche, l'exécution de `scripts/audit_rust_workspace_rules.py` sur la baseline crée `scripts/__pycache__/audit_rust_general_rules.cpython-313.pyc` : `audit_rust_export_completeness.py` importe `audit_rust_general_rules.py` dans un sous-processus Python standard.
|
||||
|
||||
Cela contredit l'intention de `CMD-GEN-006`, selon laquelle les audits sont des contrôles en lecture seule. Correction dans `0-pre.1` : le wrapper exécute désormais ses trois sous-audits avec l'interpréteur courant et `-B`, ce qui supprime cet effet de bord sans modifier les audits eux-mêmes. Une réexécution complète confirme qu'aucun cache Python n'est créé.
|
||||
|
||||
### Règle RC encore spécifique à 0.1.0
|
||||
|
||||
`CMD-RC-001` parle encore du gel fonctionnel de `0.1.0`. La règle est générale et doit viser la version courante.
|
||||
|
||||
Correction dans `0-pre.1` : formulation générique.
|
||||
|
||||
### Build Python historique et cohérence normative
|
||||
|
||||
La revue des règles révèle une contradiction dans `0.2.0` : `CMD-BUILD-002` interdisait globalement qu’un script Python pilote un build, tandis que `CMD-BUILD-004` demandait précisément aux POC `0.3.x` de remplacer les orchestrateurs Python encore présents. La baseline conserve effectivement deux chemins historiques qui les utilisent.
|
||||
|
||||
Deux scripts historiques pilotent encore des builds :
|
||||
|
||||
- `scripts/build_reflex_tauri_wasm.py` ;
|
||||
- `scripts/build_android_rust.py`.
|
||||
|
||||
Le premier est encore appelé par les hooks Tauri Reflex. Le second orchestre `cargo ndk`, l'extraction SDL3 depuis l'AAR et le staging `jniLibs`.
|
||||
|
||||
Ils appartiennent à la baseline validée `0.1.0`, mais un POC `0.3.x` ne doit pas les reprendre comme mécanisme de build. `CMD-BUILD-002` est rendue cohérente avec cette migration : les deux orchestrateurs sont explicitement tolérés uniquement comme baseline gelée jusqu’à la réactivation du chemin concerné. `CMD-WEB-003` qualifie également le script Tauri/WASM comme historique. Les remplacements sont réalisés lorsque le chemin concerné devient actif : Web direct en `0.3.0`, Tauri Android/Desktop dans les versions correspondantes et Android natif multi-ABI dans sa tranche dédiée.
|
||||
|
||||
## Contraintes de l'environnement courant
|
||||
|
||||
L'environnement d'inspection dispose de :
|
||||
|
||||
```text
|
||||
Python 3.13.5
|
||||
Node.js v22.16.0
|
||||
npm 10.9.2
|
||||
OpenJDK 21
|
||||
```
|
||||
|
||||
Il ne dispose pas de :
|
||||
|
||||
```text
|
||||
cargo
|
||||
rustc
|
||||
rustup
|
||||
gradle
|
||||
wasm-bindgen
|
||||
cargo-ndk
|
||||
Tauri CLI
|
||||
```
|
||||
|
||||
L'archive ne contient pas de Gradle Wrapper et ne vend pas l'AAR SDL3, conformément à la baseline Android actuelle.
|
||||
|
||||
Conséquence : seuls les audits statiques et inspections de fichiers sont exécutables ici. Les builds, tests et smokes restent à exécuter par l'utilisateur conformément à `CMD-BUILD-005`.
|
||||
|
||||
## Inventaire Snake et hosts existants
|
||||
|
||||
### Gameplay Snake
|
||||
|
||||
`game-snake-poc` possède déjà :
|
||||
|
||||
- un état déterministe indépendant de SDL, Android, Tauri et Web ;
|
||||
- des directions sémantiques `Left/Right/Up/Down` via `InputState` ;
|
||||
- une cadence de déplacement interne ;
|
||||
- collision mur/corps ;
|
||||
- score et nourriture ;
|
||||
- rendu sous forme de `EngineScene` normalisée.
|
||||
|
||||
Le jeu ne consomme aucun symbole de `engine-v1-platform-api`, bien que cette dépendance soit encore déclarée dans son manifest. La même déclaration inutilisée existe dans `game-reflex-poc`. Cette dette est à nettoyer avant le premier adapter Web.
|
||||
|
||||
### Desktop SDL3
|
||||
|
||||
`engine-v1-sdl` fournit déjà :
|
||||
|
||||
- fenêtre redimensionnable ;
|
||||
- clavier directionnel ;
|
||||
- pointeur normalisé ;
|
||||
- swipe tactile/souris ;
|
||||
- quit par fermeture, Escape et Back plateforme ;
|
||||
- rendu de rectangles normalisés ;
|
||||
- boucle fixed-step de 16 ms utilisée par les runners.
|
||||
|
||||
Le runner Snake Desktop compose correctement gameplay, SDL, logging et capacité plateforme désactivée. Il reste la baseline de non-régression pour `0.3.0`.
|
||||
|
||||
### Android SDL3 / Java / JNI
|
||||
|
||||
La baseline possède :
|
||||
|
||||
- `SaseGameActivity` commune dérivée de `SDLActivity` ;
|
||||
- un bridge JNI versionné ;
|
||||
- un `cdylib` Rust commun sélectionnant Reflex ou Snake par feature ;
|
||||
- tactile transporté par SDL3 ;
|
||||
- observation Back Android 16 non consommatrice ;
|
||||
- staging Gradle des assets ;
|
||||
- configuration NDK centralisée.
|
||||
|
||||
Le chemin build Rust Android reste toutefois orchestré par Python et n'est pas réutilisé par le premier POC `0.3.0`.
|
||||
|
||||
### Référence Tauri/WASM Reflex
|
||||
|
||||
La référence Reflex valide déjà plusieurs conventions utiles :
|
||||
|
||||
- crate WASM distincte de la crate Tauri ;
|
||||
- `lib.rs` Tauri limité à la façade/réexport ;
|
||||
- `tauri.rs` propriétaire de l'assemblage et des commandes ;
|
||||
- frontend Vite/TypeScript dans la crate Tauri ;
|
||||
- tracing frontend relayé vers Rust ;
|
||||
- canvas redimensionné selon le viewport et le device pixel ratio.
|
||||
|
||||
Les APIs WASM et le frontend restent cependant Reflex-specific. Elles sont des références à adapter, pas du code générique à copier aveuglément.
|
||||
|
||||
## Graphe de dépendances local observé
|
||||
|
||||
```text
|
||||
engine-v1-common
|
||||
|
||||
engine-v1-platform-api
|
||||
|
||||
engine-v1-sdl
|
||||
-> engine-v1-common
|
||||
|
||||
game-snake-poc
|
||||
-> engine-v1-common
|
||||
-> engine-v1-platform-api [déclarée, non utilisée]
|
||||
|
||||
game-reflex-poc
|
||||
-> engine-v1-common
|
||||
-> engine-v1-platform-api [déclarée, non utilisée]
|
||||
|
||||
game-snake-poc-desktop
|
||||
-> game-snake-poc
|
||||
-> engine-v1-common
|
||||
-> engine-v1-platform-api
|
||||
-> engine-v1-sdl
|
||||
-> game-logging-lib
|
||||
|
||||
game-android-entrypoint
|
||||
-> engine-v1-common
|
||||
-> engine-v1-sdl
|
||||
-> game-logging-lib
|
||||
-> game-snake-poc / game-reflex-poc via features
|
||||
|
||||
game-reflex-poc-wasm
|
||||
-> engine-v1-common
|
||||
-> game-reflex-poc
|
||||
|
||||
game-reflex-poc-tauri Rust
|
||||
-> engine-v1-platform-api
|
||||
-> game-logging-lib
|
||||
|
||||
frontend Reflex Tauri
|
||||
-> bindings générés game-reflex-poc-wasm
|
||||
|
||||
game-assets-lib
|
||||
-> aucun consommateur runtime actuel
|
||||
```
|
||||
|
||||
Le graphe confirme que gameplay Snake et host peuvent être séparés sans créer un nouveau moteur.
|
||||
|
||||
## Requirements du premier POC Snake
|
||||
|
||||
| Besoin | Baseline réelle | Décision 0.3.0 |
|
||||
|--------------------------------|-------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------|
|
||||
| Input clavier | SDL oui ; Web Snake absent | adapter clavier Web vers `GameAction` |
|
||||
| Boutons directionnels tactiles | absent | quatre contrôles virtuels Web vers `GameAction` |
|
||||
| Viewport / resize | SDL oui ; Reflex Web oui | réutiliser le principe canvas responsive sans coupler Snake à Tauri |
|
||||
| Lifecycle | quit minimal ; pas de lifecycle Web générique | pause des ticks sur `visibilitychange`, reprise contrôlée, sortie/navigation host-specific |
|
||||
| Runtime provenance | type présent mais non consommé | instancier une provenance Browser/WASM et refléter le profil d'input réellement utilisé |
|
||||
| Assets | sources + resolver/staging présents ; aucun runtime ne charge actuellement les JSON | valider le packaging/chargement de `common` et `game` dans le POC Web |
|
||||
| Logging | tracing natif ; bridge Tauri Reflex | logging Web local distinct de Tauri, sans dupliquer la logique gameplay |
|
||||
| WASM bridge | Reflex-specific | créer un adapter Snake dédié ; n'extraire un bridge générique qu'après duplication réellement observée |
|
||||
| Tauri bridge | Reflex Desktop uniquement | hors scope `0.3.0` |
|
||||
| Android packaging | SDL/Java/JNI existant | hors scope `0.3.0` |
|
||||
| Multi-ABI | script historique supportant plusieurs ABI | hors scope `0.3.0`, remplacement natif prévu plus tard |
|
||||
|
||||
## Duplications et extractions candidates
|
||||
|
||||
Duplications déjà visibles :
|
||||
|
||||
- runners Desktop Reflex/Snake très proches ;
|
||||
- activities Android spécifiques volontairement minimales ;
|
||||
- future exposition de `EngineScene` en WASM susceptible de répéter l'adapter Reflex ;
|
||||
- shell frontend Canvas/input susceptible d'être commun au Web direct et à Tauri.
|
||||
|
||||
Décision : ne pas extraire un runner générique, un bridge WASM générique ou un shell Web commun dans `pre.1`. Le premier second consommateur réel décide de l'extraction.
|
||||
|
||||
## Choix du premier POC
|
||||
|
||||
Le premier POC de `0.3.0` est :
|
||||
|
||||
```text
|
||||
Web navigateur direct + Snake
|
||||
```
|
||||
|
||||
Le choix initial Tauri Android est reporté au second host, actuellement `0.3.1`.
|
||||
|
||||
Raisons :
|
||||
|
||||
- le Web direct exerce déjà WASM, keyboard/touch, resize, lifecycle, assets et provenance ;
|
||||
- la référence Reflex fournit un précédent WASM/Canvas sans imposer Tauri ;
|
||||
- Tauri Android ajouterait simultanément un nouveau gameplay WASM, un nouveau host mobile Tauri, le lifecycle mobile, le packaging Android Tauri et les plugins ;
|
||||
- la baseline Web obtenue devient ensuite un point de comparaison et de réutilisation pour Tauri Android ;
|
||||
- ce découpage réduit le risque de créer trop tôt une abstraction Tauri/Web commune sur la seule base de Reflex.
|
||||
|
||||
## Scope corrigé de 0.3.0
|
||||
|
||||
Inclus :
|
||||
|
||||
- correction des écarts de baseline détectés en `pre.1` ;
|
||||
- nettoyage host-neutral de Snake ;
|
||||
- maintien du runner Desktop SDL3 ;
|
||||
- adapter WASM Snake dédié ;
|
||||
- frontend Web direct Vite/TypeScript minimal ;
|
||||
- clavier + boutons directionnels tactiles ;
|
||||
- canvas responsive ;
|
||||
- lifecycle navigateur minimal ;
|
||||
- logging Web ;
|
||||
- chargement d'assets de preuve ;
|
||||
- provenance Browser/WASM ;
|
||||
- build Web avec outils natifs ;
|
||||
- audit de duplication et décisions d'extraction après POC.
|
||||
|
||||
Exclus :
|
||||
|
||||
- Tauri Android ;
|
||||
- Tauri Desktop Snake ;
|
||||
- remplacement du build Android natif multi-ABI ;
|
||||
- publicité, billing, auth ou leaderboard ;
|
||||
- réseau realtime ;
|
||||
- WebTransport/QUIC ;
|
||||
- logique Uroburas ;
|
||||
- ECS, physique ou nouveau moteur.
|
||||
|
||||
## Sizing corrigé
|
||||
|
||||
Le forecast initial est réduit et réordonné afin que `0.3.0` reste une version de session unique.
|
||||
|
||||
### `0-pre.1` — audit, règles, requirements et sizing
|
||||
|
||||
- audit complet de la baseline ;
|
||||
- correction des incohérences documentaires/règles détectées ;
|
||||
- choix Web direct ;
|
||||
- forecast corrigé ;
|
||||
- aucune implémentation gameplay/host lourde.
|
||||
|
||||
### `0-pre.2` — Snake portability baseline
|
||||
|
||||
- supprimer les dépendances de plateforme inutiles des crates jeu concernées ;
|
||||
- confirmer les actions sémantiques nécessaires à Snake ;
|
||||
- conserver Desktop SDL3 comme non-régression ;
|
||||
- préciser le contrat minimal attendu par l'adapter WASM.
|
||||
|
||||
### `0-pre.3` — adapter Snake WASM + build natif Web
|
||||
|
||||
- crate WASM Snake dédiée ;
|
||||
- exposition input/update/scene strictement nécessaire ;
|
||||
- procédure Cargo + `wasm-bindgen` reproductible sans Python ;
|
||||
- tests ciblés de l'adapter lorsqu'ils sont possibles hors navigateur.
|
||||
|
||||
### `0-pre.4` — POC navigateur direct de bout en bout
|
||||
|
||||
- frontend Vite/TypeScript ;
|
||||
- rendu Canvas ;
|
||||
- clavier ;
|
||||
- boutons tactiles ;
|
||||
- resize ;
|
||||
- visibility lifecycle ;
|
||||
- logging ;
|
||||
- assets ;
|
||||
- provenance ;
|
||||
- build et smoke navigateur réels côté utilisateur.
|
||||
|
||||
### `0-pre.5` — uniquement si le POC révèle un défaut réel
|
||||
|
||||
Cette tranche n'est pas créée artificiellement. Elle corrige une frontière, une duplication ou un bug observé.
|
||||
|
||||
### `2-beta.1` — validation large du scope retenu
|
||||
|
||||
Alpha n'est pas planifiée par défaut. Si `pre.4` est fonctionnellement complet, la beta valide le workspace affecté, le build Web de production et le smoke du POC.
|
||||
|
||||
### `3-rc.1` — candidate gelée
|
||||
|
||||
Documentation durable, commandes reproductibles, décisions d'extraction/report, ROADMAP et préparation de la version suivante. Aucun nouveau scope.
|
||||
|
||||
### `0.3.0` — promotion mécanique
|
||||
|
||||
Aucune nouvelle fonctionnalité.
|
||||
|
||||
## Critères de sortie de 0.3.0
|
||||
|
||||
`0.3.0` peut être clôturée lorsque :
|
||||
|
||||
- Snake Desktop SDL3 reste fonctionnel ;
|
||||
- Snake fonctionne réellement dans un navigateur direct ;
|
||||
- clavier et boutons tactiles produisent les mêmes actions sémantiques ;
|
||||
- resize et visibility lifecycle ont été exercés ;
|
||||
- assets et provenance sont observables ;
|
||||
- le chemin Web ne dépend d'aucun script Python de build ;
|
||||
- les duplications avec Reflex/Tauri sont documentées ;
|
||||
- seules les abstractions prouvées nécessaires ont été extraites ;
|
||||
- les validations applicables ont été exécutées par l'utilisateur ;
|
||||
- aucune logique Uroburas ni réseau realtime n'a été introduite.
|
||||
67
docs/testing/004-V0_3_0_RC_VALIDATION_MATRIX.md
Normal file
67
docs/testing/004-V0_3_0_RC_VALIDATION_MATRIX.md
Normal file
@@ -0,0 +1,67 @@
|
||||
<!-- file: docs/testing/004-V0_3_0_RC_VALIDATION_MATRIX.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Matrice RC 0.3.0 — Snake Web direct
|
||||
|
||||
## Objet
|
||||
|
||||
La RC `0.3.0` gèle le premier POC Snake Web direct. Elle ne crée aucune fonctionnalité et vérifie que l'état validé en beta reste reproductible avant promotion mécanique vers la stable.
|
||||
|
||||
## Gate statique et workspace
|
||||
|
||||
```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 Web deltas history
|
||||
python3 scripts/audit_distribution_layout.py
|
||||
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
cargo test --workspace --all-targets --all-features
|
||||
```
|
||||
|
||||
## Desktop Snake release
|
||||
|
||||
```bash
|
||||
cargo build -p game-snake-poc-desktop --release
|
||||
../builds/sasedev-games/target/release/game-snake-poc-desktop
|
||||
```
|
||||
|
||||
Critères : démarrage, rendu, contrôles et arrêt propre.
|
||||
|
||||
## Web/WASM release
|
||||
|
||||
```bash
|
||||
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-web/wasm \
|
||||
--out-name game_snake_poc_wasm
|
||||
|
||||
(cd Web/game-snake-poc && npm install && npm run build && npm run preview)
|
||||
```
|
||||
|
||||
Ouvrir `http://127.0.0.1:4174/main.html`.
|
||||
|
||||
Critères :
|
||||
|
||||
- Canvas au ratio attendu ;
|
||||
- clavier et contrôles pointer/tactiles ;
|
||||
- SimpleBar ;
|
||||
- assets `snake / engine-v1` ;
|
||||
- provenance Web/WASM cohérente ;
|
||||
- resize ;
|
||||
- pause/reprise sans rattrapage massif ;
|
||||
- aucune erreur runtime bloquante.
|
||||
|
||||
## Artefacts et dépôt
|
||||
|
||||
Les artefacts Rust/WASM/Vite restent sous `../builds/sasedev-games/`. Aucun `node_modules`, `dist`, cache WASM ou artefact Cargo n'est livré dans le dépôt.
|
||||
|
||||
## Promotion
|
||||
|
||||
La promotion vers `0.3.0` est mécanique lorsque `3-rc.1` est validée sans défaut nécessitant une modification fonctionnelle. Tout correctif de release reste limité par `VER-RC-*`.
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/validation/001-VALIDATION_GATES.md -->
|
||||
<!-- version: 5 -->
|
||||
<!-- version: 8 -->
|
||||
|
||||
# Gates de validation
|
||||
|
||||
@@ -24,7 +24,7 @@ Les audits et gates de compilation restent ensuite :
|
||||
|
||||
```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 deltas history
|
||||
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates Android Web deltas history
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
```
|
||||
@@ -58,4 +58,47 @@ Si une commande échoue, ne pas avancer de prerelease. Produire un correctif du
|
||||
|
||||
Le build Android n'est pas encore une gate : le projet Gradle exécutable et l'intégration SDL3/NDK restent planifiés pour une prerelease dédiée. Dès leur introduction, les tâches ciblées par module sont documentées avant d'être rendues obligatoires.
|
||||
|
||||
La cible Web suit la même règle : aucune gate Web n'est inventée avant l'existence de son build réel.
|
||||
Le host navigateur direct Snake possède désormais une gate réelle. Lorsqu'il est touché, construire d'abord l'adapter WASM et ses bindings hors dépôt, puis le 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
|
||||
```
|
||||
|
||||
Le smoke direct utilise ensuite `npm run dev` et `http://127.0.0.1:1434/main.html`. Pour le POC Snake feature-complete, vérifier aussi : assets `common` + `game` chargés avant le statut `Prêt`, provenance `Web/Wasm/Browser` visible et mise à jour par l'input, pause sans rattrapage lors d'un masquage d'onglet, reprise propre, resize sans tick artificiel, SimpleBar, clavier et contrôles pointer/tactiles.
|
||||
|
||||
Lorsque `0-pre.5` touche la frontière plateforme du bridge WASM, exécuter également `cargo test -p engine-v1-platform-api`, `cargo test -p game-snake-poc-wasm`, puis un smoke `cargo run -p game-snake-poc-desktop` pour confirmer la non-régression SDL3. Les frontends Tauri restent pilotés par leurs hooks Tauri et ne reprennent pas cette gate manuelle.
|
||||
|
||||
## Gate beta du POC Snake Web
|
||||
|
||||
À l’entrée en `2-beta.1`, le scope `0.3.0` est feature-complete. La gate de frontière de phase ajoute aux audits/check/Clippy la suite Cargo workspace complète :
|
||||
|
||||
```bash
|
||||
cargo test --workspace --all-targets --all-features
|
||||
```
|
||||
|
||||
Le témoin Desktop Snake est construit et fumé en release :
|
||||
|
||||
```bash
|
||||
cargo build -p game-snake-poc-desktop --release
|
||||
../builds/sasedev-games/target/release/game-snake-poc-desktop
|
||||
```
|
||||
|
||||
Le host Web beta utilise également un module WASM release avant le build Vite :
|
||||
|
||||
```bash
|
||||
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-web/wasm \
|
||||
--out-name game_snake_poc_wasm
|
||||
(cd Web/game-snake-poc && npm install && npm run build && npm run preview)
|
||||
```
|
||||
|
||||
Le smoke production ouvre `http://127.0.0.1:4174/main.html` et vérifie les mêmes contrats fonctionnels que le smoke `vite dev` : Canvas, inputs, SimpleBar, assets, provenance, lifecycle et resize. Le smoke `vite dev` déjà validé reste utile après un correctif touchant le plugin de dev, mais n’est pas requis à chaque beta si aucun chemin dev n’a changé.
|
||||
|
||||
29
history/0.3.0/0-pre.1.fix.1.md
Normal file
29
history/0.3.0/0-pre.1.fix.1.md
Normal file
@@ -0,0 +1,29 @@
|
||||
<!-- file: history/0.3.0/0-pre.1.fix.1.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Historique 0.3.0-0-pre.1.fix.1
|
||||
|
||||
## Statut
|
||||
|
||||
Correctif de cadrage validé par l'utilisateur le 2026-09-20 avant ouverture de `0-pre.1.fix.2`.
|
||||
|
||||
## Validation utilisateur
|
||||
|
||||
Les commandes exécutées ont validé :
|
||||
|
||||
```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), 171 file(s))
|
||||
Distribution layout audit: clean (19 required path(s), 1 forbidden path(s) absent)
|
||||
cargo fmt --all -- --check: clean
|
||||
cargo check --workspace: clean
|
||||
```
|
||||
|
||||
## Contenu accepté
|
||||
|
||||
- création de `docs/plans/` et du plan vivant `0.3.0` ;
|
||||
- prévision souple des tranches jusqu'à la stable ;
|
||||
- contrat explicite des archives issues d'un tag comme baseline autoritaire sans `.git` ;
|
||||
- règle de session dimensionnée pour fermer au minimum la version concrète ouverte.
|
||||
29
history/0.3.0/0-pre.1.fix.2.md
Normal file
29
history/0.3.0/0-pre.1.fix.2.md
Normal file
@@ -0,0 +1,29 @@
|
||||
<!-- file: history/0.3.0/0-pre.1.fix.2.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Historique 0.3.0-0-pre.1.fix.2
|
||||
|
||||
## Statut
|
||||
|
||||
Dernier correctif de cadrage `0-pre.1` validé par l'utilisateur le 2026-09-20 avant ouverture de `0-pre.2`.
|
||||
|
||||
## Validation utilisateur
|
||||
|
||||
Les commandes exécutées ont validé :
|
||||
|
||||
```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), 172 file(s))
|
||||
Distribution layout audit: clean (19 required path(s), 1 forbidden path(s) absent)
|
||||
cargo fmt --all -- --check: clean
|
||||
cargo check --workspace: clean
|
||||
```
|
||||
|
||||
## Contenu accepté
|
||||
|
||||
- shell Web HTML/Vite/TypeScript explicite autour du Canvas/WASM ;
|
||||
- Bootstrap 5 retenu comme baseline de présentation du premier POC Snake Web ;
|
||||
- séparation durable frontend / Canvas-WASM / gameplay ;
|
||||
- tranche prévisionnelle explicite de consolidation documentaire, `CHANGELOG.md`, `ROADMAP.md`, history et prompt suivant avant RC.
|
||||
38
history/0.3.0/0-pre.2.md
Normal file
38
history/0.3.0/0-pre.2.md
Normal file
@@ -0,0 +1,38 @@
|
||||
<!-- file: history/0.3.0/0-pre.2.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Historique 0.3.0-0-pre.2
|
||||
|
||||
## Statut
|
||||
|
||||
Baseline Snake portable validée par l'utilisateur le 2026-09-20 avant ouverture de `0-pre.3`.
|
||||
|
||||
## Validation utilisateur
|
||||
|
||||
La validation a été exécutée après `cargo clean` et reformatage canonique. Les gates suivantes ont passé :
|
||||
|
||||
```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), 175 file(s))
|
||||
Distribution layout audit: clean (19 required path(s), 1 forbidden path(s) absent)
|
||||
cargo fmt --all -- --check: clean
|
||||
cargo check --workspace: clean
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings: clean
|
||||
cargo test -p game-snake-poc: 5 passed, 0 failed
|
||||
cargo test -p game-reflex-poc: 4 passed, 0 failed
|
||||
```
|
||||
|
||||
Les graphes de dépendances validés sont :
|
||||
|
||||
```text
|
||||
game-snake-poc -> engine-v1-common
|
||||
game-reflex-poc -> engine-v1-common
|
||||
```
|
||||
|
||||
Aucune des deux crates de gameplay ne tire donc `engine-v1-platform-api` après le nettoyage `0-pre.2`.
|
||||
|
||||
## Suite
|
||||
|
||||
`0-pre.3` introduit l'adapter WASM Snake minimal sans frontend Vite/Bootstrap, conformément au plan actif.
|
||||
43
history/0.3.0/0-pre.3.md
Normal file
43
history/0.3.0/0-pre.3.md
Normal file
@@ -0,0 +1,43 @@
|
||||
<!-- file: history/0.3.0/0-pre.3.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Historique 0.3.0-0-pre.3
|
||||
|
||||
## Statut
|
||||
|
||||
Adapter Snake WASM validé par l'utilisateur le 2026-09-20 avant ouverture de `0-pre.4`.
|
||||
|
||||
## Validation utilisateur
|
||||
|
||||
Les gates suivantes ont passé sur `0.3.0-0-pre.3` :
|
||||
|
||||
```text
|
||||
cargo fmt --all: clean
|
||||
cargo fmt --all -- --check: clean
|
||||
cargo check --workspace: clean
|
||||
cargo clippy -p game-snake-poc-wasm --all-targets --all-features -- -D warnings: clean
|
||||
cargo test -p game-snake-poc-wasm: 2 passed, 0 failed
|
||||
cargo build -p game-snake-poc-wasm --target wasm32-unknown-unknown: clean
|
||||
wasm-bindgen --target web: clean
|
||||
General Rust rule audit: clean
|
||||
Rust export completeness audit: 0 candidate(s)
|
||||
games.sasedev workspace audit: clean
|
||||
Markdown table audit: clean (5 table(s), 178 file(s))
|
||||
Distribution layout audit: clean (20 required path(s), 1 forbidden path(s) absent)
|
||||
```
|
||||
|
||||
Le graphe de dépendances validé de `game-snake-poc-wasm` contient uniquement les dépendances fonctionnelles attendues :
|
||||
|
||||
```text
|
||||
game-snake-poc-wasm
|
||||
├── engine-v1-common
|
||||
├── game-snake-poc
|
||||
│ └── engine-v1-common
|
||||
└── wasm-bindgen
|
||||
```
|
||||
|
||||
Aucune dépendance SDL3, Tauri ou `engine-v1-platform-api` n'est présente dans l'adapter WASM Snake.
|
||||
|
||||
## Suite
|
||||
|
||||
`0-pre.4` introduit le host navigateur direct Vite/TypeScript avec shell HTML Bootstrap 5, Canvas et contrôles clavier/tactiles.
|
||||
46
history/0.3.0/0-pre.4.fix.1.md
Normal file
46
history/0.3.0/0-pre.4.fix.1.md
Normal file
@@ -0,0 +1,46 @@
|
||||
<!-- file: history/0.3.0/0-pre.4.fix.1.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Historique 0.3.0-0-pre.4.fix.1
|
||||
|
||||
## Statut
|
||||
|
||||
Validation partielle le 2026-09-20 : les gates Rust/WASM et les audits sont propres, mais `npm run build` échoue encore sur deux erreurs TypeScript strictes. La tranche déclenche `0-pre.4.fix.2`.
|
||||
|
||||
## Validation utilisateur
|
||||
|
||||
Les validations suivantes ont passé sur `0.3.0-0-pre.4.fix.1` :
|
||||
|
||||
```text
|
||||
cargo fmt --all: clean
|
||||
cargo fmt --all -- --check: clean
|
||||
General Rust rule audit: clean
|
||||
Rust export completeness audit: 0 candidate(s)
|
||||
games.sasedev workspace audit: clean
|
||||
Markdown table audit: clean (5 table(s), 183 file(s))
|
||||
Distribution layout audit: clean (27 required path(s), 1 forbidden path(s) absent)
|
||||
cargo check --workspace: clean
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings: clean
|
||||
cargo test -p game-snake-poc-wasm: 2 passed, 0 failed
|
||||
cargo build -p game-snake-poc-wasm --target wasm32-unknown-unknown: clean
|
||||
wasm-bindgen --target web: clean
|
||||
cargo tree -p game-snake-poc-wasm --edges normal: expected dependencies only
|
||||
npm install: 5 packages added, 49 packages audited, 0 vulnerability
|
||||
```
|
||||
|
||||
`npm install` a aussi signalé que le script d'installation de `@parcel/watcher@2.6.0` n'était pas encore couvert par `allowScripts`. Ce warning n'a pas interrompu l'installation et n'est pas traité comme l'échec de cette tranche.
|
||||
|
||||
## Défauts observés
|
||||
|
||||
`npm run build` a échoué avec deux erreurs :
|
||||
|
||||
```text
|
||||
TS7016: Could not find a declaration file for module '@snake-wasm'.
|
||||
TS2345: CanvasRenderingContext2D | null is not assignable to CanvasRenderingContext2D.
|
||||
```
|
||||
|
||||
Le premier défaut vient du mapping TypeScript vers le fichier JavaScript généré par `wasm-bindgen` au lieu de sa déclaration `.d.ts`. Le second vient du narrowing du résultat de `canvas.getContext("2d")` qui n'est pas conservé jusque dans le callback de frame sous la configuration TypeScript courante.
|
||||
|
||||
## Suite
|
||||
|
||||
`0-pre.4.fix.2` corrige strictement ces deux erreurs puis rejoue `npm run build` et le smoke navigateur avant ouverture de `0-pre.5`.
|
||||
52
history/0.3.0/0-pre.4.fix.2.md
Normal file
52
history/0.3.0/0-pre.4.fix.2.md
Normal file
@@ -0,0 +1,52 @@
|
||||
<!-- file: history/0.3.0/0-pre.4.fix.2.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Historique 0.3.0-0-pre.4.fix.2
|
||||
|
||||
## Statut
|
||||
|
||||
Validation technique réussie le 2026-09-20 pour les gates Rust/WASM et le build frontend production. Le smoke navigateur confirme aussi le ratio Canvas corrigé, mais le comportement SimpleBar reste incorrect ou absent et déclenche `0-pre.4.fix.3`.
|
||||
|
||||
## Validation utilisateur
|
||||
|
||||
Les validations suivantes ont passé sur `0.3.0-0-pre.4.fix.2` :
|
||||
|
||||
```text
|
||||
cargo fmt --all: clean
|
||||
cargo fmt --all -- --check: clean
|
||||
General Rust rule audit: clean
|
||||
Rust export completeness audit: 0 candidate(s)
|
||||
games.sasedev workspace audit: clean
|
||||
Markdown table audit: clean (5 table(s), 185 file(s))
|
||||
Distribution layout audit: clean (27 required path(s), 1 forbidden path(s) absent)
|
||||
cargo check --workspace: clean
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings: clean
|
||||
cargo test -p game-snake-poc-wasm: 2 passed, 0 failed
|
||||
cargo build -p game-snake-poc-wasm --target wasm32-unknown-unknown: clean
|
||||
wasm-bindgen --target web: clean
|
||||
cargo tree -p game-snake-poc-wasm --edges normal: expected dependencies only
|
||||
npm install: 49 packages audited, 0 vulnerability
|
||||
npm run build: clean
|
||||
npm run dev: Vite started on 127.0.0.1:1434
|
||||
manual smoke: page displayed correctly
|
||||
manual smoke: Canvas height/ratio correct
|
||||
```
|
||||
|
||||
Le build Vite production a généré `main.html`, les fonts, le WASM, le CSS et le JavaScript sous `../builds/sasedev-games/game-snake-poc-web/dist/`.
|
||||
|
||||
`npm install` continue de signaler le warning non bloquant relatif au script d'installation de `@parcel/watcher@2.6.0`; aucune vulnérabilité npm n'est signalée.
|
||||
|
||||
## Défaut restant
|
||||
|
||||
Le scroll personnalisé SimpleBar n'est pas observé comme attendu pendant le smoke. La comparaison avec les apps `ksp-app-*-desk` confirme un écart structurel :
|
||||
|
||||
- KSP borne la hauteur via `app-main`;
|
||||
- `data-simplebar` est attaché à `app-content app-scrollable h-100`;
|
||||
- cette zone centrale porte explicitement `height: 100%` et `max-height: 100%`;
|
||||
- le point d'entrée TypeScript importe `resize-observer-polyfill` et `simplebar`, puis installe le polyfill global avant l'initialisation applicative.
|
||||
|
||||
Le frontend Snake avait placé `data-simplebar` directement sur `app-main` et la zone `app-content` utilisait seulement `min-height: 100%`.
|
||||
|
||||
## Suite
|
||||
|
||||
`0-pre.4.fix.3` aligne la structure HTML/Sass sur le shell KSP sans modifier le gameplay, le bridge WASM, le Canvas ni les contrôles.
|
||||
29
history/0.3.0/0-pre.4.fix.3.md
Normal file
29
history/0.3.0/0-pre.4.fix.3.md
Normal file
@@ -0,0 +1,29 @@
|
||||
<!-- file: history/0.3.0/0-pre.4.fix.3.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Historique 0.3.0-0-pre.4.fix.3
|
||||
|
||||
## Statut
|
||||
|
||||
Correctif SimpleBar validé par l'utilisateur le 2026-09-20. La tranche `0-pre.4` est fermée et `0-pre.5` peut ouvrir l'intégration plateforme complète.
|
||||
|
||||
## Validation utilisateur
|
||||
|
||||
La sortie fournie sur `0.3.0-0-pre.4.fix.3` confirme au minimum :
|
||||
|
||||
```text
|
||||
npm install: 49 packages audités, 0 vulnérabilité
|
||||
npm run build: clean
|
||||
npm run dev: Vite démarré sur 127.0.0.1:1434
|
||||
cargo tree -p game-snake-poc-wasm --edges normal: dépendances attendues
|
||||
manual smoke: page et Canvas corrects
|
||||
manual smoke: comportement SimpleBar conforme au shell KSP-derived
|
||||
```
|
||||
|
||||
Le build Vite production a généré `main.html`, fonts, WASM, CSS et JavaScript sous `../builds/sasedev-games/game-snake-poc-web/dist/`.
|
||||
|
||||
Le warning npm non bloquant relatif au script d'installation de `@parcel/watcher@2.6.0` reste présent et n'a pas empêché le build.
|
||||
|
||||
## Suite
|
||||
|
||||
`0-pre.5` ferme lifecycle/resize, assets, logging et provenance runtime du host Web, puis vérifie la non-régression du runner Snake Desktop SDL3.
|
||||
50
history/0.3.0/0-pre.4.md
Normal file
50
history/0.3.0/0-pre.4.md
Normal file
@@ -0,0 +1,50 @@
|
||||
<!-- file: history/0.3.0/0-pre.4.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Historique 0.3.0-0-pre.4
|
||||
|
||||
## Statut
|
||||
|
||||
Candidate Web fonctionnelle en smoke navigateur mais non validée comme tranche fermée le 2026-09-20 : la gate `npm run build` a échoué et a déclenché `0-pre.4.fix.1`.
|
||||
|
||||
## Validation utilisateur
|
||||
|
||||
Les validations suivantes ont passé sur `0.3.0-0-pre.4` :
|
||||
|
||||
```text
|
||||
cargo fmt --all: clean
|
||||
cargo fmt --all -- --check: clean
|
||||
General Rust rule audit: clean
|
||||
Rust export completeness audit: 0 candidate(s)
|
||||
games.sasedev workspace audit: clean
|
||||
Markdown table audit: clean (5 table(s), 181 file(s))
|
||||
Distribution layout audit: clean (26 required path(s), 1 forbidden path(s) absent)
|
||||
cargo check --workspace: clean
|
||||
cargo clippy -p game-snake-poc-wasm --all-targets --all-features -- -D warnings: clean
|
||||
cargo test -p game-snake-poc-wasm: 2 passed, 0 failed
|
||||
cargo build -p game-snake-poc-wasm --target wasm32-unknown-unknown: clean
|
||||
wasm-bindgen --target web: clean
|
||||
npm install: 43 packages added, 0 vulnerability
|
||||
npm run dev: Vite started on 127.0.0.1:1434
|
||||
manual smoke: keyboard controls clean
|
||||
manual smoke: on-page pointer controls clean
|
||||
```
|
||||
|
||||
La page de smoke est volontairement `http://127.0.0.1:1434/main.html`; l'absence d'`index.html` rend la racine `/` non navigable et n'est pas considérée comme un défaut de cette tranche.
|
||||
|
||||
## Défauts observés
|
||||
|
||||
`npm run build` a échoué sous TypeScript 7 avec :
|
||||
|
||||
```text
|
||||
TS5102: Option 'baseUrl' has been removed. Please remove it from your configuration.
|
||||
```
|
||||
|
||||
Deux écarts visuels/structurels ont aussi été confirmés pendant le smoke :
|
||||
|
||||
- SimpleBar et `resize-observer-polyfill` avaient été omis à tort alors qu'ils appartiennent au shell Web KSP-derived et doivent porter le scroll de la zone centrale entre header et footer fixes ;
|
||||
- le Canvas carré déformait la grille Snake `12 × 20`, produisant des cellules visuellement écrasées en hauteur.
|
||||
|
||||
## Suite
|
||||
|
||||
`0-pre.4.fix.1` corrige ces trois points puis rejoue la gate frontend avant ouverture de `0-pre.5`.
|
||||
59
history/0.3.0/0-pre.5.fix.1.md
Normal file
59
history/0.3.0/0-pre.5.fix.1.md
Normal file
@@ -0,0 +1,59 @@
|
||||
<!-- file: history/0.3.0/0-pre.5.fix.1.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Historique 0.3.0-0-pre.5.fix.1
|
||||
|
||||
## Statut
|
||||
|
||||
Intégration plateforme du POC Snake Web validée par l'utilisateur le 2026-09-20. Aucun défaut structurel supplémentaire n'est identifié ; `0-pre.6` conditionnelle est omise et la version peut entrer en `2-beta.1`.
|
||||
|
||||
## Validation utilisateur
|
||||
|
||||
Les gates suivantes ont passé sur `0.3.0-0-pre.5.fix.1` :
|
||||
|
||||
```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), 191 file(s))
|
||||
Distribution layout audit: clean (31 required path(s), 1 forbidden path(s) absent)
|
||||
cargo fmt --all -- --check: clean
|
||||
cargo check --workspace: clean
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings: clean
|
||||
cargo test -p engine-v1-platform-api --all-targets --all-features: 3 passed, 0 failed
|
||||
cargo test -p game-snake-poc-wasm --all-targets --all-features: 4 passed, 0 failed
|
||||
cargo build -p game-snake-poc-wasm --target wasm32-unknown-unknown: clean
|
||||
wasm-bindgen --target web: clean
|
||||
cargo tree -p game-snake-poc-wasm --edges normal: frontière attendue
|
||||
npm install: 64 packages audités, 0 vulnérabilité
|
||||
npm run build: clean, 30 modules transformés, 2 assets copiés
|
||||
npm run dev: Vite démarré sur 127.0.0.1:1434
|
||||
```
|
||||
|
||||
Le warning npm non bloquant relatif au script d'installation de `@parcel/watcher@2.6.0` reste présent.
|
||||
|
||||
## Smoke Web accepté
|
||||
|
||||
Le navigateur confirme :
|
||||
|
||||
```text
|
||||
Provenance: web / browser / wasm / desktop / keyboard-mouse
|
||||
Assets: snake / engine-v1
|
||||
controls: clavier et contrôles souris fonctionnels
|
||||
```
|
||||
|
||||
Le chargement des assets est donc réparé en dev et le bridge expose la provenance attendue. Les tests lifecycle/resize plus larges restent repris dans la gate beta afin de consolider le comportement feature-complete.
|
||||
|
||||
## Non-régression Desktop SDL3
|
||||
|
||||
Le smoke `cargo run -p game-snake-poc-desktop` passe :
|
||||
|
||||
```text
|
||||
desktop SDL3 runner started game="snake"
|
||||
SDL3 runtime started title=Snake POC width=405 height=720
|
||||
SDL3 runtime stopped frames=411
|
||||
```
|
||||
|
||||
## Suite
|
||||
|
||||
La tranche conditionnelle `0-pre.6` est omise. `2-beta.1` ouvre une validation large sans nouveau scope fonctionnel.
|
||||
51
history/0.3.0/0-pre.5.md
Normal file
51
history/0.3.0/0-pre.5.md
Normal file
@@ -0,0 +1,51 @@
|
||||
<!-- file: history/0.3.0/0-pre.5.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Historique 0.3.0-0-pre.5
|
||||
|
||||
## Statut
|
||||
|
||||
Validation technique partielle fournie par l'utilisateur le 2026-09-20. Les gates Rust/WASM et le build Vite passent, mais le smoke navigateur est bloqué par le chargement des assets runtime ; `0-pre.5` nécessite donc `0-pre.5.fix.1`.
|
||||
|
||||
## Validations réussies
|
||||
|
||||
La sortie utilisateur confirme :
|
||||
|
||||
```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), 189 file(s))
|
||||
Distribution layout audit: clean (31 required path(s), 1 forbidden path(s) absent)
|
||||
cargo fmt --all -- --check: clean
|
||||
cargo check --workspace: clean
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings: clean
|
||||
cargo test -p engine-v1-platform-api --all-targets --all-features: 3 passed
|
||||
cargo test -p game-snake-poc-wasm --all-targets --all-features: 4 passed
|
||||
cargo build -p game-snake-poc-wasm --target wasm32-unknown-unknown: clean
|
||||
wasm-bindgen --target web: clean
|
||||
cargo tree -p game-snake-poc-wasm --edges normal: frontière attendue
|
||||
npm install: 64 packages audités, 0 vulnérabilité
|
||||
npm run build: clean, 30 modules transformés, 2 assets collectés
|
||||
npm run dev: Vite démarré sur 127.0.0.1:1434
|
||||
```
|
||||
|
||||
Le warning npm relatif au script d'installation de `@parcel/watcher@2.6.0` reste non bloquant.
|
||||
|
||||
Le smoke `cargo run -p game-snake-poc-desktop` n'a pas été exécuté dans cette tentative, le smoke Web étant déjà bloqué par les assets.
|
||||
|
||||
## Défaut observé
|
||||
|
||||
Le shell démarre, mais les sondes visibles restent :
|
||||
|
||||
```text
|
||||
Provenance: web / browser / wasm / unknown / unknown
|
||||
Assets: chargement…
|
||||
Impossible de démarrer Snake : fetchJson@http://127.0.0.1:1434/ts/assets.ts:4:9
|
||||
```
|
||||
|
||||
Le build production copie les deux assets, mais le serveur de développement ne les expose pas aux routes attendues par `fetchJson()`. Les targets de `vite-plugin-static-copy` partent de chemins absolus sans suppression explicite du préfixe source.
|
||||
|
||||
## Suite
|
||||
|
||||
`0-pre.5.fix.1` impose `rename: { stripBase: true }` aux deux targets afin de rendre les routes runtime identiques en `vite dev` et dans `dist/`, puis rejoue le smoke assets/provenance/lifecycle avant toute entrée en beta.
|
||||
52
history/0.3.0/2-beta.1.md
Normal file
52
history/0.3.0/2-beta.1.md
Normal file
@@ -0,0 +1,52 @@
|
||||
<!-- file: history/0.3.0/2-beta.1.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Historique 0.3.0-2-beta.1
|
||||
|
||||
## Statut
|
||||
|
||||
Gate beta feature-complete validée par l'utilisateur le 2026-09-20. Aucun défaut fonctionnel ou de packaging n'est remonté ; la version peut entrer dans la consolidation `2-beta.2`.
|
||||
|
||||
## Gate workspace
|
||||
|
||||
Les validations suivantes passent :
|
||||
|
||||
```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), 193 file(s))
|
||||
Distribution layout audit: clean (31 required path(s), 1 forbidden path(s) absent)
|
||||
cargo fmt --all -- --check: clean
|
||||
cargo check --workspace: clean
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings: clean
|
||||
cargo test --workspace --all-targets --all-features: 34 passed, 0 failed
|
||||
```
|
||||
|
||||
## Desktop Snake release
|
||||
|
||||
Le build release passe et le smoke SDL3 se ferme proprement :
|
||||
|
||||
```text
|
||||
desktop SDL3 runner started game="snake"
|
||||
SDL3 runtime started title=Snake POC width=405 height=720
|
||||
SDL3 runtime stopped frames=144
|
||||
```
|
||||
|
||||
## Web/WASM release
|
||||
|
||||
Le module Snake WASM release compile, `wasm-bindgen --target web` termine sans erreur, puis le frontend passe :
|
||||
|
||||
```text
|
||||
npm install: 64 packages audités, 0 vulnérabilité
|
||||
npm run build: clean, 30 modules transformés, 2 assets copiés
|
||||
npm run preview: Vite démarré sur 127.0.0.1:4174
|
||||
```
|
||||
|
||||
Le warning npm non bloquant relatif au script d'installation de `@parcel/watcher@2.6.0` reste présent.
|
||||
|
||||
L'utilisateur accepte le résultat de la gate beta sans défaut supplémentaire remonté.
|
||||
|
||||
## Suite
|
||||
|
||||
`0.3.0-2-beta.2` consolide documentation durable, roadmap, historique, matrice RC et prompt `0.3.1`, sans nouveau comportement.
|
||||
38
history/0.3.0/2-beta.2.fix.1.md
Normal file
38
history/0.3.0/2-beta.2.fix.1.md
Normal file
@@ -0,0 +1,38 @@
|
||||
<!-- file: history/0.3.0/2-beta.2.fix.1.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Historique 0.3.0-2-beta.2.fix.1
|
||||
|
||||
## Statut
|
||||
|
||||
Revue humaine effectuée le 2026-09-20. Le niveau de détail du prompt `0.3.1` est jugé globalement satisfaisant, mais la politique de commandes doit encore être précisée avant RC ; `2-beta.2.fix.2` est donc ouvert.
|
||||
|
||||
## Résultat de revue
|
||||
|
||||
Éléments acceptés :
|
||||
|
||||
```text
|
||||
prompt de reprise autonome sans reproduire toute la documentation KSP
|
||||
timing du prompt suivant / RC / CHANGELOG / ROADMAP clarifié
|
||||
rôle de deltas/ et history/ clarifié
|
||||
politique README.md / USAGE.md jugée adaptée
|
||||
fix strictement documentaire sans bump des versions runtime confirmé
|
||||
```
|
||||
|
||||
Précisions demandées avant RC :
|
||||
|
||||
```text
|
||||
cargo fmt/check workspace/Clippy strict obligatoires dès que Rust ou ses dépendances changent
|
||||
audits Python sélectionnés selon les fichiers touchés
|
||||
tests cargo ciblés privilégiés
|
||||
test workspace complet limité à quelques jalons planifiés ou aux portées transverses incertaines
|
||||
cargo tree uniquement lors de changements/diagnostics de dépendances
|
||||
commandes nécessitant cd exécutées dans un sous-shell
|
||||
Tauri : npm seulement pour gérer les dépendances ; smoke via cargo tauri dev ; packaging final via cargo tauri build
|
||||
```
|
||||
|
||||
Aucune sortie d'audit ou de build spécifique à `2-beta.2.fix.1` n'a été fournie dans cette revue ; aucune gate mécanique supplémentaire n'est donc déclarée PASS ici.
|
||||
|
||||
## Suite
|
||||
|
||||
`2-beta.2.fix.2` formalise ces règles et met à jour le prompt `0.3.1` sans toucher aux versions techniques.
|
||||
35
history/0.3.0/2-beta.2.fix.2.md
Normal file
35
history/0.3.0/2-beta.2.fix.2.md
Normal file
@@ -0,0 +1,35 @@
|
||||
<!-- file: history/0.3.0/2-beta.2.fix.2.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Historique 0.3.0-2-beta.2.fix.2
|
||||
|
||||
## Statut
|
||||
|
||||
Correctif documentaire validé par l'utilisateur le 2026-09-20. Le workflow de commandes et le prompt `0.3.1` sont acceptés ; la RC `0.3.0-3-rc.1` peut être ouverte.
|
||||
|
||||
## Validation utilisateur
|
||||
|
||||
La gate proportionnelle au scope strictement documentaire a été exécutée :
|
||||
|
||||
```text
|
||||
python3 scripts/audit_markdown_tables.py docs prompts deltas history
|
||||
Markdown table audit: clean (5 table(s), 189 file(s))
|
||||
```
|
||||
|
||||
Aucune gate Cargo, npm, Gradle, Tauri, distribution ou smoke n'était applicable à ce correctif, qui ne modifiait ni code, ni dépendance, ni manifeste runtime/build.
|
||||
|
||||
## Décision
|
||||
|
||||
Les règles suivantes sont considérées consolidées pour la suite :
|
||||
|
||||
```text
|
||||
fmt/check/Clippy workspace lorsque Rust ou ses dépendances changent
|
||||
tests Cargo ciblés par défaut
|
||||
test workspace complet seulement aux jalons planifiés ou portées incertaines
|
||||
cargo tree uniquement pour dépendances/features ou diagnostic explicite
|
||||
audits Python sélectionnés selon les fichiers touchés
|
||||
sous-shell obligatoire pour les commandes avec changement de répertoire
|
||||
Tauri : npm pour dépendances, cargo tauri dev pour smoke, cargo tauri build pour packaging final
|
||||
```
|
||||
|
||||
Le prompt `prompts/003-V0_3_1_START_PROMPT.md` est jugé suffisamment autonome pour la transmission.
|
||||
51
history/0.3.0/2-beta.2.md
Normal file
51
history/0.3.0/2-beta.2.md
Normal file
@@ -0,0 +1,51 @@
|
||||
<!-- file: history/0.3.0/2-beta.2.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Historique 0.3.0-2-beta.2
|
||||
|
||||
## Statut
|
||||
|
||||
Consolidation `2-beta.2` validée par l'utilisateur le 2026-09-20. Les audits, le check workspace et le build frontend de production passent ; aucun défaut mécanique n'est remonté.
|
||||
|
||||
Une revue humaine du prompt `0.3.1` relève toutefois qu'il est trop court pour servir de contrat de reprise suffisamment autonome. La correction appartient à `2-beta.2` puisqu'elle concerne la consolidation/transmission et ouvre `2-beta.2.fix.1`.
|
||||
|
||||
## Gate documentaire et workspace
|
||||
|
||||
Les validations suivantes passent :
|
||||
|
||||
```text
|
||||
cargo fmt --all -- --check: clean
|
||||
General Rust rule audit: clean
|
||||
Rust export completeness audit: 0 candidate(s)
|
||||
games.sasedev workspace audit: clean
|
||||
Markdown table audit: clean (5 table(s), 198 file(s))
|
||||
Distribution layout audit: clean (31 required path(s), 1 forbidden path(s) absent)
|
||||
cargo check --workspace: clean
|
||||
```
|
||||
|
||||
## Frontend
|
||||
|
||||
Le package Web Snake est confirmé cohérent avec le jalon beta :
|
||||
|
||||
```text
|
||||
npm install: 64 packages audités, 0 vulnérabilité
|
||||
npm run build: clean
|
||||
Vite: 30 modules transformés
|
||||
vite-plugin-static-copy: 2 items copiés
|
||||
```
|
||||
|
||||
Le warning npm non bloquant relatif au script d'installation de `@parcel/watcher@2.6.0` reste présent.
|
||||
|
||||
## Revue humaine
|
||||
|
||||
Le contenu de consolidation est accepté mécaniquement, mais le prompt `prompts/003-V0_3_1_START_PROMPT.md` doit être enrichi avant la RC afin de rappeler de manière autonome :
|
||||
|
||||
- le timing du prompt suivant, du `CHANGELOG.md` et du `ROADMAP.md` ;
|
||||
- le rôle respectif de `deltas/` et `history/` ;
|
||||
- où se trouvent les définitions de commandes et leur matrice ;
|
||||
- la politique `README.md` / `USAGE.md` des crates et applications ;
|
||||
- le workflow de validation/fix et la condition de fin de session.
|
||||
|
||||
## Suite
|
||||
|
||||
`0.3.0-2-beta.2.fix.1` corrige uniquement la transmission documentaire et les règles associées. Aucun changement code/build/runtime n'est attendu.
|
||||
41
history/0.3.0/3-rc.1.md
Normal file
41
history/0.3.0/3-rc.1.md
Normal file
@@ -0,0 +1,41 @@
|
||||
<!-- file: history/0.3.0/3-rc.1.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Historique 0.3.0-3-rc.1
|
||||
|
||||
## Statut
|
||||
|
||||
Validé par l'utilisateur le 2026-09-20 puis retenu pour promotion mécanique vers `0.3.0`.
|
||||
|
||||
## Gate workspace
|
||||
|
||||
La gate RC complète a passé :
|
||||
|
||||
- `cargo fmt --all` ;
|
||||
- `cargo fmt --all -- --check` ;
|
||||
- audits Rust général, exports, workspace, Markdown et distribution propres ;
|
||||
- `cargo check --workspace` ;
|
||||
- `cargo clippy --workspace --all-targets --all-features -- -D warnings` ;
|
||||
- `cargo test --workspace --all-targets --all-features` avec 34 tests réussis et aucun échec.
|
||||
|
||||
## Desktop Snake release
|
||||
|
||||
`game-snake-poc-desktop` a été construit en `--release`, exécuté avec SDL3 puis arrêté proprement.
|
||||
|
||||
Le runtime observé s'est terminé après 926 frames.
|
||||
|
||||
## Web / WASM release
|
||||
|
||||
`game-snake-poc-wasm` a été construit en `--release` pour `wasm32-unknown-unknown`, puis traité avec `wasm-bindgen --target web`.
|
||||
|
||||
Le frontend `game-snake-poc-web` a ensuite passé :
|
||||
|
||||
- `npm install` sans vulnérabilité signalée ;
|
||||
- `npm run build` ;
|
||||
- démarrage de `npm run preview` sur `http://127.0.0.1:4174/`.
|
||||
|
||||
Le build Vite a copié les deux assets canoniques et produit le bundle WASM/CSS/JavaScript de release.
|
||||
|
||||
## Conclusion
|
||||
|
||||
La RC conserve le scope gelé de `0.3.0`. Aucun défaut fonctionnel, de compilation ou de packaging nécessitant un `.fix.N` n'a été remonté après la gate RC ; la promotion stable peut donc rester mécanique.
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: prompts/002-V0_3_X_START_PROMPT.md -->
|
||||
<!-- version: 2 -->
|
||||
<!-- version: 4 -->
|
||||
|
||||
# Prompt de démarrage — `0.3.0` / série `0.3.x` POC plateforme et réseau
|
||||
|
||||
@@ -12,7 +12,7 @@ Avant toute modification :
|
||||
1. lire `RULES.md`, `ROADMAP.md`, `CHANGELOG.md` et `docs/000-README.md` ;
|
||||
2. lire les règles de session, commandes et validation ;
|
||||
3. lire les architectures consolidées `012` à `016` ;
|
||||
4. vérifier l'état Git/workspace ;
|
||||
4. lorsque la base est une archive téléchargée depuis le tag fourni, la traiter comme snapshot autoritaire sans exiger `.git` ; vérifier sa cohérence workspace/version ;
|
||||
5. exécuter les audits applicables à la base ;
|
||||
6. confirmer la version workspace avant `0.3.0-0-pre.1`.
|
||||
|
||||
@@ -128,7 +128,7 @@ Objectif :
|
||||
- requirements ;
|
||||
- graphe de dépendances ;
|
||||
- choix du premier POC ;
|
||||
- forecast corrigé ;
|
||||
- plan actif sous `docs/plans/` avec forecast corrigé ;
|
||||
- commandes prévues ;
|
||||
- critères de sortie.
|
||||
|
||||
@@ -150,65 +150,51 @@ Validation candidate :
|
||||
- Desktop SDL toujours fonctionnel ;
|
||||
- dependency audit ciblé.
|
||||
|
||||
### `0-pre.3` — adapters/capabilities minimaux
|
||||
### `0-pre.3` — adaptation Snake WASM
|
||||
|
||||
Objectif candidat :
|
||||
Décision issue de `pre.1` :
|
||||
|
||||
- extraire uniquement ce que le premier POC prouve nécessaire ;
|
||||
- éviter duplication bridge/frontend ;
|
||||
- préparer input/resize/lifecycle/runtime provenance ;
|
||||
- documenter les duplications provisoires.
|
||||
- introduire la crate/adaptation WASM minimale de Snake ;
|
||||
- générer les bindings avec `wasm-bindgen` ;
|
||||
- conserver le gameplay dans `game-snake-poc` ;
|
||||
- ne pas généraliser avant qu'un second consommateur ne le justifie.
|
||||
|
||||
Cette tranche peut être fusionnée avec `pre.2`.
|
||||
### `0-pre.4` — frontend Web/Vite + shell Bootstrap 5
|
||||
|
||||
### `0-pre.4` — premier POC de bout en bout
|
||||
Décision issue de `pre.1` : le premier host est Web navigateur direct + Snake.
|
||||
|
||||
Préférence initiale :
|
||||
Le frontend doit fournir :
|
||||
|
||||
```text
|
||||
Tauri Android + Snake
|
||||
```
|
||||
- un document HTML responsive piloté par Vite/TypeScript ;
|
||||
- Bootstrap 5 comme baseline de présentation/layout et pour les contrôles UI ;
|
||||
- un Canvas dédié au rendu du jeu ;
|
||||
- clavier et boutons directionnels tactiles ;
|
||||
- états de chargement/erreur utiles au POC.
|
||||
|
||||
Alternative si `pre.1` la juge plus rationnelle :
|
||||
Le framework HTML/CSS reste strictement côté frontend : Rust/WASM conserve le gameplay et l'état du jeu.
|
||||
|
||||
```text
|
||||
Web navigateur direct + Snake
|
||||
```
|
||||
### `0-pre.5` — intégration plateforme complète
|
||||
|
||||
Le POC doit couvrir :
|
||||
Fermer les besoins de bout en bout du POC :
|
||||
|
||||
- build avec outil natif ;
|
||||
- lancement ;
|
||||
- rendu ;
|
||||
- contrôles ;
|
||||
- resize/orientation selon host ;
|
||||
- lifecycle ;
|
||||
- logging ;
|
||||
- resize/lifecycle ;
|
||||
- assets ;
|
||||
- runtime provenance.
|
||||
- logging ;
|
||||
- runtime provenance ;
|
||||
- non-régression du runner Desktop SDL3.
|
||||
|
||||
Compiler seul ne suffit pas.
|
||||
Compiler seul ne suffit pas : le smoke navigateur fait partie de la validation.
|
||||
|
||||
### `0-pre.5` — corrections/généralisation issues du POC
|
||||
### `0-pre.6` — correction/extraction conditionnelle
|
||||
|
||||
Créer seulement si le POC révèle un besoin réel :
|
||||
Créer seulement si les tranches précédentes révèlent un besoin réel :
|
||||
|
||||
- supprimer duplication avérée ;
|
||||
- corriger frontières mal placées ;
|
||||
- ajouter tests nécessaires ;
|
||||
- documenter ce qui reste spécifique.
|
||||
|
||||
### `1-alpha.1` — intégration éventuelle
|
||||
|
||||
À utiliser seulement si le volume de code nouveau justifie une phase distincte.
|
||||
|
||||
Objectif :
|
||||
|
||||
- stabiliser interfaces Snake/capabilities/host ;
|
||||
- fermer les défauts structurels ;
|
||||
- aucun nouveau scope.
|
||||
|
||||
Sinon, ne pas créer cette tranche artificiellement.
|
||||
Sinon, omettre cette tranche.
|
||||
|
||||
### `2-beta.1` — validation large
|
||||
|
||||
@@ -220,6 +206,18 @@ Objectif :
|
||||
- documentation des commandes ;
|
||||
- vérification qu'aucune abstraction spéculative n'a été ajoutée.
|
||||
|
||||
### `2-beta.2` — consolidation documentaire et transmission
|
||||
|
||||
Responsabilité obligatoire, même si sa numérotation finale glisse :
|
||||
|
||||
- réconcilier la documentation durable avec l'état validé ;
|
||||
- mettre à jour `CHANGELOG.md` et `ROADMAP.md` ;
|
||||
- mettre à jour l'historique applicable ;
|
||||
- réconcilier le plan avec les deltas réellement livrés ;
|
||||
- préparer et vérifier le prompt de la version/session suivante.
|
||||
|
||||
Cette tranche consolide la documentation ; elle ne reporte pas à la fin la documentation spécifique qui devait accompagner les tranches fonctionnelles.
|
||||
|
||||
### `3-rc.1` — candidate
|
||||
|
||||
Scope gelé.
|
||||
|
||||
593
prompts/003-V0_3_1_START_PROMPT.md
Normal file
593
prompts/003-V0_3_1_START_PROMPT.md
Normal file
@@ -0,0 +1,593 @@
|
||||
<!-- file: prompts/003-V0_3_1_START_PROMPT.md -->
|
||||
<!-- version: 3 -->
|
||||
|
||||
# Prompt de démarrage `0.3.1` — second host Snake Tauri Android
|
||||
|
||||
## 1. Base exacte et autorité de la reprise
|
||||
|
||||
Partir uniquement de la version stable/taggée :
|
||||
|
||||
```text
|
||||
v0.3.0
|
||||
```
|
||||
|
||||
Si ce prompt est lu avant la publication effective de `0.3.0`, ne pas ouvrir `0.3.1`. Terminer d'abord la RC puis la release stable `0.3.0`.
|
||||
|
||||
Lorsqu'une archive est fournie comme téléchargement du tag `v0.3.0`, elle constitue la baseline autoritaire même si elle ne contient pas `.git`. Appliquer `CMD-GIT-003` et `CMD-GIT-004` : vérifier la cohérence interne des versions et des fichiers, ne pas inventer un état Git inaccessible.
|
||||
|
||||
Version cible :
|
||||
|
||||
```text
|
||||
0.3.1
|
||||
```
|
||||
|
||||
Première tranche obligatoire :
|
||||
|
||||
```text
|
||||
0.3.1-0-pre.1
|
||||
```
|
||||
|
||||
`0-pre.1` est un gate de lecture, audit, requirements, sizing, validation et planification. Ne pas commencer directement par le scaffold Android/Tauri ou par la copie du POC Reflex.
|
||||
|
||||
## 2. Sources de vérité — ordre de lecture obligatoire
|
||||
|
||||
Lire intégralement, dans cet ordre :
|
||||
|
||||
```text
|
||||
RULES.md
|
||||
ROADMAP.md
|
||||
CHANGELOG.md
|
||||
docs/000-README.md
|
||||
```
|
||||
|
||||
Puis lire les règles directement pertinentes :
|
||||
|
||||
```text
|
||||
docs/rules/RULES_GENERAL.md
|
||||
docs/rules/RULES_RUST.md
|
||||
docs/rules/RULES_PROJECT.md
|
||||
docs/rules/RULES_DOCUMENTATION.md
|
||||
docs/rules/FILE_CONTRACTS.md
|
||||
docs/rules/VERSION_WORKFLOW.md
|
||||
docs/rules/RULES_COMMANDS.md
|
||||
docs/rules/RULES_VALIDATION_MATRIX.md
|
||||
docs/rules/RULES_SESSION_PLANNING.md
|
||||
docs/rules/PROMPT_STRUCTURE.md
|
||||
```
|
||||
|
||||
Le prompt résume les garde-fous nécessaires à `0.3.1`; les règles restent normatives en cas de détail absent ici.
|
||||
|
||||
Lire ensuite la transmission `0.3.0` :
|
||||
|
||||
```text
|
||||
docs/plans/001-V0_3_0_WEB_SNAKE_POC_PLAN.md
|
||||
docs/architecture/015-PLATFORM_POC_ARCHITECTURE.md
|
||||
docs/architecture/018-V0_3_0_WEB_SNAKE_BASELINE.md
|
||||
docs/testing/004-V0_3_0_RC_VALIDATION_MATRIX.md
|
||||
history/0.3.0/
|
||||
deltas/0.3.0/
|
||||
```
|
||||
|
||||
Enfin auditer les implémentations réellement concernées :
|
||||
|
||||
```text
|
||||
crates/games/game-snake-poc/
|
||||
crates/apps/game-snake-poc-wasm/
|
||||
Web/game-snake-poc/
|
||||
crates/apps/game-snake-poc-desktop/
|
||||
crates/apps/game-reflex-poc-tauri/
|
||||
crates/apps/game-reflex-poc-wasm/
|
||||
Android/
|
||||
assets/
|
||||
```
|
||||
|
||||
Ne pas déduire l'état d'une crate depuis ce prompt lorsque le code stable `0.3.0` dit autre chose.
|
||||
|
||||
## 3. État hérité attendu de `0.3.0`
|
||||
|
||||
La stable `0.3.0` doit avoir validé au minimum :
|
||||
|
||||
```text
|
||||
Snake gameplay indépendant des hosts
|
||||
runner Desktop SDL3 fonctionnel
|
||||
adapter Snake WASM dédié
|
||||
host navigateur direct Vite/TypeScript
|
||||
shell HTML Bootstrap 5 / Bootswatch / SimpleBar
|
||||
Canvas respectant le ratio logique Snake
|
||||
clavier + contrôles pointer/tactiles
|
||||
lifecycle navigateur fixed-step sans catch-up massif
|
||||
assets common/game packagés depuis assets/
|
||||
logging frontend structuré
|
||||
RuntimeProvenance Web / Browser / Wasm
|
||||
build WASM release + wasm-bindgen
|
||||
build Vite production + preview
|
||||
```
|
||||
|
||||
Cette liste est un handoff attendu, pas une validation à réexécuter aveuglément au premier instant. Confirmer l'état réel de la stable puis définir les non-régressions nécessaires à `0.3.1`.
|
||||
|
||||
## 4. Mission de `0.3.1`
|
||||
|
||||
`0.3.1` doit produire le second host Snake : Tauri Android.
|
||||
|
||||
Le but est de vérifier que la baseline Web/WASM de `0.3.0` peut être réutilisée dans un WebView mobile Tauri sans recopier le gameplay, sans dupliquer inutilement le bridge WASM et sans créer un framework abstrait avant preuve d'un besoin partagé.
|
||||
|
||||
Résultat attendu :
|
||||
|
||||
```text
|
||||
Snake exécutable dans un host Tauri Android
|
||||
build Android piloté par les outils Tauri/Android natifs retenus
|
||||
lifecycle mobile cohérent
|
||||
input tactile et comportement WebView cohérents
|
||||
assets accessibles dans le package final
|
||||
logging Rust/Tauri/frontend cohérent
|
||||
RuntimeProvenance distincte du navigateur direct
|
||||
non-régression du host Web direct 0.3.0
|
||||
non-régression Desktop SDL3 si une frontière partagée change
|
||||
```
|
||||
|
||||
## 5. `0.3.1-0-pre.1` — cadrage obligatoire
|
||||
|
||||
Avant tout développement lourd, produire un audit réel de la stable `0.3.0` et de l'environnement disponible.
|
||||
|
||||
### 5.1 Baseline Snake
|
||||
|
||||
Auditer :
|
||||
|
||||
```text
|
||||
game-snake-poc
|
||||
game-snake-poc-wasm
|
||||
Web/game-snake-poc
|
||||
game-snake-poc-desktop
|
||||
engine-v1-common
|
||||
engine-v1-platform-api
|
||||
assets communs et Snake
|
||||
```
|
||||
|
||||
Identifier explicitement :
|
||||
|
||||
- ce qui est réutilisable tel quel ;
|
||||
- ce qui est spécifique au navigateur direct ;
|
||||
- ce qui appartient déjà à l'adapter WASM ;
|
||||
- ce qui deviendrait réellement partagé entre navigateur et WebView Tauri ;
|
||||
- toute duplication prouvée avant extraction.
|
||||
|
||||
### 5.2 Référence Tauri existante
|
||||
|
||||
Auditer intégralement :
|
||||
|
||||
```text
|
||||
crates/apps/game-reflex-poc-tauri/
|
||||
crates/apps/game-reflex-poc-wasm/
|
||||
docs/development/008-WASM_TAURI_POC.md
|
||||
```
|
||||
|
||||
Le POC Reflex est une référence technique de structure, de bridge Tauri, de frontend et de logging. Il n'est pas un template à copier aveuglément si sa baseline historique contredit les règles `0.3.x`.
|
||||
|
||||
Vérifier notamment :
|
||||
|
||||
```text
|
||||
src/lib.rs comme façade/reexports
|
||||
src/tauri.rs comme assemblage Tauri et pont Web/Rust
|
||||
modules propriétaires séparés
|
||||
tauri.conf.json / capabilities / permissions
|
||||
hooks frontend Vite
|
||||
tauri-plugin-tracing / @fltsci/tauri-plugin-tracing
|
||||
organisation frontend HTML/Sass/TypeScript
|
||||
```
|
||||
|
||||
### 5.3 Android existant
|
||||
|
||||
Auditer `Android/` et les documents Android existants pour distinguer :
|
||||
|
||||
```text
|
||||
baseline Android SDL3/Java/JNI
|
||||
host Tauri Android de 0.3.1
|
||||
```
|
||||
|
||||
Ils peuvent partager des contraintes plateforme, SDK/NDK ou documentation, mais ne doivent pas être confondus ni couplés artificiellement.
|
||||
|
||||
### 5.4 Toolchains réelles
|
||||
|
||||
Inventorier ce qui est réellement disponible dans l'environnement utilisateur :
|
||||
|
||||
```text
|
||||
Rust targets Android nécessaires
|
||||
Tauri CLI/version réellement utilisée
|
||||
Android SDK
|
||||
Android NDK
|
||||
Java/JDK
|
||||
Gradle/tooling éventuellement piloté par Tauri
|
||||
adb
|
||||
émulateur/AVD éventuel
|
||||
appareil réel éventuel
|
||||
Node/npm
|
||||
```
|
||||
|
||||
Ne pas déclarer un smoke appareil/émulateur possible avant de confirmer qu'une cible est effectivement accessible.
|
||||
|
||||
### 5.5 Sizing et plan
|
||||
|
||||
Créer ou réviser obligatoirement le plan de `0.3.1` sous :
|
||||
|
||||
```text
|
||||
docs/plans/
|
||||
```
|
||||
|
||||
Le plan doit contenir :
|
||||
|
||||
- objectif et scope ;
|
||||
- décisions acquises ;
|
||||
- risques/dépendances utiles ;
|
||||
- hors-périmètre ;
|
||||
- validations prévues ;
|
||||
- découpage prévisionnel souple jusqu'à `0.3.1` stable ;
|
||||
- tranche de validation large ;
|
||||
- tranche de consolidation documentaire ;
|
||||
- RC gelée ;
|
||||
- release stable mécanique.
|
||||
|
||||
Si le sizing montre que Tauri Android complet ne tient pas raisonnablement dans une session, réduire ou scinder le scope avant l'implémentation lourde.
|
||||
|
||||
## 6. Contraintes architecturales gelées
|
||||
|
||||
Préserver les frontières suivantes :
|
||||
|
||||
```text
|
||||
game-snake-poc
|
||||
gameplay et règles de jeu
|
||||
|
||||
engine-v1-common
|
||||
contrats moteur portables
|
||||
|
||||
engine-v1-platform-api
|
||||
provenance/capabilities plateforme
|
||||
|
||||
game-snake-poc-wasm
|
||||
adaptation WASM Snake
|
||||
|
||||
host Web direct / host Tauri
|
||||
lifecycle, DOM/WebView, inputs physiques, packaging et UI
|
||||
```
|
||||
|
||||
Règles spécifiques :
|
||||
|
||||
- `game-snake-poc` reste indépendant de Tauri, Android, DOM, Canvas et providers ;
|
||||
- ne pas copier le gameplay dans TypeScript, Java ou le backend Tauri ;
|
||||
- conserver `game-snake-poc-wasm` comme adapter WASM tant qu'un besoin réel ne justifie pas une extraction ;
|
||||
- ne pas généraliser `Web/game-snake-poc` avant observation du second consommateur ;
|
||||
- une extraction commune Web/WebView n'est autorisée que si deux consommateurs réels prouvent sa valeur ;
|
||||
- `lib.rs` d'une app Tauri reste une façade/reexport ;
|
||||
- `tauri.rs` assemble Tauri et délègue aux modules propriétaires ;
|
||||
- les traces frontend Tauri utilisent le bridge tracing prévu par les règles, pas des `console.*` applicatifs dispersés ;
|
||||
- ne pas réintroduire d'orchestrateur Python de build ;
|
||||
- ne pas utiliser `scripts/build_reflex_tauri_wasm.py` pour le nouveau chemin `0.3.x` ;
|
||||
- ne pas introduire réseau realtime, Uroburas, ads, billing ou leaderboard dans `0.3.1`.
|
||||
|
||||
## 7. Frontend Tauri et commandes Web
|
||||
|
||||
Le frontend Tauri peut reprendre les conventions de shell déjà éprouvées dans les applications Desk KSP et dans le POC existant lorsque cela reste pertinent :
|
||||
|
||||
```text
|
||||
Vite
|
||||
TypeScript
|
||||
HTML/Sass
|
||||
Bootstrap 5 / thème retenu
|
||||
Font Awesome
|
||||
SimpleBar + ResizeObserver si le layout le nécessite
|
||||
```
|
||||
|
||||
Pour une application Tauri, `npm` sert seulement à gérer les dépendances frontend lorsqu'une dépendance doit être ajoutée/retirée (`npm i`, `npm i -D`, etc.). Ne pas utiliser `npm run dev` ou `npm run build` comme gates Tauri manuelles : les hooks Tauri possèdent Vite/TypeScript/WASM.
|
||||
|
||||
Le smoke courant utilise :
|
||||
|
||||
```bash
|
||||
(cd <tauri-app> && cargo tauri dev)
|
||||
```
|
||||
|
||||
Le packaging est réservé aux phases finales prévues par le plan :
|
||||
|
||||
```bash
|
||||
(cd <tauri-app> && cargo tauri build)
|
||||
```
|
||||
|
||||
Ne pas traiter le host Tauri comme le host navigateur direct de `0.3.0` : le mode de lancement, le packaging, les permissions et les smokes sont différents.
|
||||
|
||||
## 8. Provenance attendue
|
||||
|
||||
Le host Tauri Android doit produire une provenance distincte du navigateur direct.
|
||||
|
||||
`0-pre.1` doit auditer les enums/contrats réels de `engine-v1-platform-api` avant de fixer les valeurs exactes, mais préserver les dimensions :
|
||||
|
||||
```text
|
||||
platform family
|
||||
runtime host
|
||||
execution model
|
||||
device class
|
||||
input profile
|
||||
```
|
||||
|
||||
Ne pas ajouter une identification matérielle fine uniquement pour ce POC.
|
||||
|
||||
## 9. Documentation des crates/packages
|
||||
|
||||
Pendant `0-pre.1`, appliquer `DOC-CRATE-*` à tout composant créé ou finalisé.
|
||||
|
||||
La question doit être explicitement tranchée pour la nouvelle app Tauri :
|
||||
|
||||
```text
|
||||
README.md ?
|
||||
responsabilité / frontières / architecture locale / points d'entrée
|
||||
|
||||
USAGE.md ?
|
||||
prérequis / commandes / installation / lancement / smoke opérateur
|
||||
```
|
||||
|
||||
Ne pas créer des fichiers vides ou redondants. Si la documentation centrale couvre réellement un petit adapter, le plan peut documenter pourquoi un fichier local séparé n'apporte rien.
|
||||
|
||||
Lors de la consolidation finale, refaire cette revue pour chaque crate/package considéré durable dans `0.3.1`.
|
||||
|
||||
## 10. Deltas, history et état validé
|
||||
|
||||
Ne pas confondre :
|
||||
|
||||
```text
|
||||
deltas/<X.Y.Z>/
|
||||
décrit la livraison candidate
|
||||
base requise
|
||||
fichiers ajoutés/modifiés/supprimés
|
||||
décisions
|
||||
validations à exécuter
|
||||
validations non exécutées
|
||||
|
||||
history/<X.Y.Z>/
|
||||
décrit un jalon effectivement validé
|
||||
résultats réellement fournis par l'utilisateur
|
||||
défauts acceptés/corrigés
|
||||
état transmis au jalon suivant
|
||||
```
|
||||
|
||||
Une entrée `history/` n'est jamais pré-écrite pour le delta courant. Après validation utilisateur, le delta suivant ou son fix crée l'entrée historique du jalon accepté conformément à `DOC-HIST-*`.
|
||||
|
||||
Les anciens fichiers de `deltas/` et `history/` restent immuables sur le fond.
|
||||
|
||||
## 11. CHANGELOG, ROADMAP, plan et prompt suivant
|
||||
|
||||
Appliquer ces responsabilités sans les mélanger :
|
||||
|
||||
### Plan
|
||||
|
||||
`docs/plans/` porte le suivi fin et vivant de `0.3.1`. Il est créé/révisé en `0-pre.1` puis réconcilié lorsqu'un résultat réel modifie la trajectoire.
|
||||
|
||||
### ROADMAP
|
||||
|
||||
`ROADMAP.md` reste macroscopique. Le modifier lorsqu'un scope est ajouté, réalisé, reporté ou annulé ; ne pas ajouter une ligne pour chaque prerelease/fix.
|
||||
|
||||
### CHANGELOG
|
||||
|
||||
`CHANGELOG.md` est une synthèse de publication. Les `pre`, `alpha`, `beta` et fixes ne créent normalement pas d'entrée. Écrire la synthèse candidate à partir de la RC, puis la synthèse stable lors de la release.
|
||||
|
||||
### Prompt de la version suivante
|
||||
|
||||
Rédiger le prompt suivant pendant la consolidation finale de `0.3.1` lorsque la cible `0.3.2` est suffisamment connue. La première RC gelée vérifie/complète le prompt à partir de l'état réellement candidat à publication.
|
||||
|
||||
Ne jamais présenter dans ce prompt futur une validation RC/stable qui n'a pas encore été exécutée.
|
||||
|
||||
## 12. Commandes et matrice de validation
|
||||
|
||||
Ne pas inventer une procédure de commandes parallèle dans le prompt.
|
||||
|
||||
Sources normatives :
|
||||
|
||||
```text
|
||||
docs/rules/RULES_COMMANDS.md
|
||||
docs/rules/RULES_VALIDATION_MATRIX.md
|
||||
```
|
||||
|
||||
`RULES_COMMANDS.md` définit quand utiliser les audits, Cargo, Web, Android, Tauri et les smokes.
|
||||
|
||||
`RULES_VALIDATION_MATRIX.md` définit les IDs `CMD-*`, leurs dépendances et leurs déclencheurs.
|
||||
|
||||
Chaque delta sélectionne les commandes proportionnelles à son scope. Une commande non exécutée n'est jamais déclarée PASS.
|
||||
|
||||
Les audits Python sont choisis selon les fichiers touchés : ne pas exécuter systématiquement les trois audits si un seul est pertinent.
|
||||
|
||||
Dès qu'un delta touche du code Rust, un manifeste Cargo, une feature ou une dépendance Rust, la base obligatoire est :
|
||||
|
||||
```bash
|
||||
cargo fmt --all
|
||||
cargo fmt --all -- --check
|
||||
# audits Python applicables au scope
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
```
|
||||
|
||||
Les tests normaux sont ciblés :
|
||||
|
||||
```bash
|
||||
cargo test -p <crate> --all-targets --all-features
|
||||
```
|
||||
|
||||
Ajouter les tests ciblés des consommateurs uniquement lorsque leur contrat est affecté. `cargo test --workspace --all-targets --all-features` reste une gate rare, planifiée un petit nombre de fois dans la version/session (initiale si utile, préfinale/finale, ou portée transverse incertaine).
|
||||
|
||||
Ne lancer `cargo tree` que si les dépendances/features changent ou qu'un diagnostic de frontière le justifie. Ne pas le mettre automatiquement dans chaque log de validation.
|
||||
|
||||
Toute commande nécessitant un changement de répertoire est englobée dans un sous-shell :
|
||||
|
||||
```bash
|
||||
(cd <répertoire> && <commande>)
|
||||
```
|
||||
|
||||
Pour Tauri, utiliser `cargo tauri dev` pour les smokes et réserver `cargo tauri build` aux phases finales de packaging ; `npm` n'est utilisé directement que pour gérer les dépendances frontend.
|
||||
|
||||
## 13. Qui exécute quoi
|
||||
|
||||
Le générateur peut exécuter les audits statiques en lecture seule afin de préparer un delta.
|
||||
|
||||
Les validations de build/runtime restent côté utilisateur :
|
||||
|
||||
```text
|
||||
cargo check workspace + Clippy workspace strict lorsqu'un delta touche Rust/dépendances
|
||||
tests cargo ciblés par défaut
|
||||
test workspace complet seulement aux jalons planifiés/portées incertaines
|
||||
(cd <tauri-app> && cargo tauri dev) pour les smokes Tauri
|
||||
(cd <tauri-app> && cargo tauri build) pour les validations finales de packaging Tauri
|
||||
Gradle/SDK/NDK lorsque le chemin Tauri les invoque
|
||||
installation émulateur/appareil
|
||||
smoke mobile
|
||||
smoke Web direct de non-régression
|
||||
smoke Desktop SDL3 si requis
|
||||
```
|
||||
|
||||
Ne jamais annoncer un build ou un smoke comme réussi uniquement parce que le code paraît correct.
|
||||
|
||||
Une gate utilisateur propre permet de passer automatiquement à la tranche planifiée suivante sauf instruction contraire. Une gate en échec reste normalement dans un `.fix.N` de la tranche courante.
|
||||
|
||||
## 14. Forecast initial souple
|
||||
|
||||
Le forecast suivant est une hypothèse à confirmer ou corriger en `0-pre.1`.
|
||||
|
||||
### `0-pre.1` — audit / requirements / sizing / plan
|
||||
|
||||
- audit stable `0.3.0` ;
|
||||
- audit Reflex Tauri/WASM ;
|
||||
- audit environnement Tauri Android ;
|
||||
- matrice réutilisation vs duplication ;
|
||||
- stratégie de build/smoke ;
|
||||
- positionnement explicite des rares gates `cargo test --workspace --all-targets --all-features` dans le plan ;
|
||||
- plan `0.3.1` ;
|
||||
- décision README/USAGE attendue pour les nouveaux composants.
|
||||
|
||||
### `0-pre.2` — host Tauri Android Snake minimal
|
||||
|
||||
- nouvelle app Tauri Android au bon emplacement ;
|
||||
- consommation de l'adapter WASM Snake existant ou adaptation minimale justifiée ;
|
||||
- premier build natif reproductible ;
|
||||
- aucune généralisation prématurée.
|
||||
|
||||
### `0-pre.3` — lifecycle / input / assets / provenance / logging
|
||||
|
||||
- lifecycle WebView/mobile ;
|
||||
- tactile/input ;
|
||||
- assets ;
|
||||
- provenance ;
|
||||
- tracing Rust/Tauri/frontend ;
|
||||
- erreurs de runtime visibles et sûres.
|
||||
|
||||
### `0-pre.4` — extraction conditionnelle
|
||||
|
||||
Créer uniquement si le second host révèle une duplication partagée réelle entre navigateur direct et Tauri WebView.
|
||||
|
||||
Sinon omettre la tranche.
|
||||
|
||||
### `2-beta.1` — validation large
|
||||
|
||||
- workspace complet ;
|
||||
- `(cd <tauri-app> && cargo tauri build)` pour le packaging Tauri Android ;
|
||||
- smoke via `(cd <tauri-app> && cargo tauri dev)` puis émulateur/appareil disponible ;
|
||||
- non-régression Web direct ;
|
||||
- non-régression Desktop SDL3 lorsque nécessaire ;
|
||||
- vérification dépendances/package/distribution.
|
||||
|
||||
### `2-beta.2` — consolidation documentaire
|
||||
|
||||
- documentation durable ;
|
||||
- README/USAGE réellement nécessaires ;
|
||||
- plan réconcilié ;
|
||||
- history ;
|
||||
- ROADMAP selon le scope réellement livré ;
|
||||
- préparation du prompt `0.3.2` ;
|
||||
- matière de CHANGELOG prête sans créer une entrée beta artificielle.
|
||||
|
||||
### `3-rc.1` — candidate gelée
|
||||
|
||||
- scope fonctionnel gelé ;
|
||||
- entrée RC du `CHANGELOG.md` ;
|
||||
- matrice RC ;
|
||||
- reproductibilité packaging ;
|
||||
- prompt `0.3.2` vérifié/complété ;
|
||||
- seulement bugs/release blockers ensuite.
|
||||
|
||||
### `0.3.1` — stable
|
||||
|
||||
Release mécanique de la RC validée : versions finales, synthèse stable, delta/release et tag selon le workflow applicable.
|
||||
|
||||
La numérotation est révisable. Les responsabilités ne doivent pas être fusionnées uniquement pour raccourcir artificiellement la version.
|
||||
|
||||
## 15. Hors-périmètre explicite
|
||||
|
||||
Ne pas ouvrir dans `0.3.1` sans décision de replanification :
|
||||
|
||||
```text
|
||||
Tauri Desktop Snake comme nouveau produit
|
||||
refonte générale engine-v1
|
||||
engine-v2
|
||||
Android SDL3 multi-ABI supplémentaire
|
||||
nouveau framework frontend générique
|
||||
serveur realtime
|
||||
WebSocket/WebTransport/QUIC gameplay
|
||||
Uroburas
|
||||
ads/billing
|
||||
leaderboard/auth
|
||||
refactor massif de Reflex
|
||||
mise à niveau opportuniste des dépendances
|
||||
```
|
||||
|
||||
Une dépendance peut être mise à jour uniquement si elle est nécessaire au chemin `0.3.1` et que le delta le documente.
|
||||
|
||||
## 16. Packaging et fichiers générés
|
||||
|
||||
Respecter :
|
||||
|
||||
```text
|
||||
../builds/sasedev-games/
|
||||
```
|
||||
|
||||
pour les sorties Cargo/Tauri/Vite et caches concernés.
|
||||
|
||||
Ne pas livrer :
|
||||
|
||||
```text
|
||||
node_modules/
|
||||
dist/
|
||||
target/
|
||||
bindings wasm générés
|
||||
caches
|
||||
secrets
|
||||
lockfiles interdits par les règles du dépôt
|
||||
```
|
||||
|
||||
Le ZIP d'un delta contient uniquement les fichiers ajoutés/modifiés par la tranche plus son document de delta, et les suppressions éventuelles utilisent le manifest contractuel prévu.
|
||||
|
||||
## 17. Première séquence de travail de la session
|
||||
|
||||
À l'ouverture de `0.3.1` :
|
||||
|
||||
1. vérifier que la base fournie correspond réellement à la stable `0.3.0` ;
|
||||
2. lire les sources de vérité dans l'ordre indiqué ;
|
||||
3. lire le dernier `history/0.3.0` et le delta/release stable ;
|
||||
4. exécuter les audits statiques applicables à la baseline ;
|
||||
5. auditer `game-reflex-poc-tauri` et le chemin Tauri Android disponible ;
|
||||
6. auditer `game-snake-poc-wasm` et le host Web direct ;
|
||||
7. inventorier SDK/NDK/Tauri/adb/AVD/appareil réellement accessibles ;
|
||||
8. produire requirements, risques, hors-périmètre et sizing ;
|
||||
9. créer le plan `0.3.1` sous `docs/plans/` ;
|
||||
10. seulement ensuite ouvrir le premier delta de développement.
|
||||
|
||||
## 18. Condition de fin de session
|
||||
|
||||
La session est dimensionnée pour fermer `0.3.1` jusqu'à sa stable.
|
||||
|
||||
Une prerelease n'est pas une cible normale de fin de session. Si le sizing ou une contrainte externe rend l'objectif trop grand, reporter explicitement le scope non indispensable vers `0.3.2+` plutôt que prolonger indéfiniment `0.3.1`.
|
||||
|
||||
La stable doit arriver avec :
|
||||
|
||||
```text
|
||||
scope validé
|
||||
builds/smokes applicables validés
|
||||
documentation durable réconciliée
|
||||
history complet des jalons acceptés
|
||||
ROADMAP cohérente
|
||||
CHANGELOG RC/stable cohérent
|
||||
prompt de la version suivante prêt et vérifié
|
||||
delta/release mécanique sans nouveau scope
|
||||
```
|
||||
@@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env python3
|
||||
# file: scripts/audit_distribution_layout.py
|
||||
# version: 1
|
||||
# version: 7
|
||||
|
||||
"""Audit the static distribution layout expected by the 0.1.0 beta."""
|
||||
"""Audit the static distribution layout expected by supported POCs."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -29,6 +29,18 @@ REQUIRED_PATHS = (
|
||||
"crates/apps/game-reflex-poc-tauri/frontend/index.html",
|
||||
"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",
|
||||
"Web/game-snake-poc/package.json",
|
||||
"Web/game-snake-poc/tsconfig.json",
|
||||
"Web/game-snake-poc/vite.config.ts",
|
||||
"Web/game-snake-poc/frontend/main.html",
|
||||
"Web/game-snake-poc/frontend/sass/_simplebar.scss",
|
||||
"Web/game-snake-poc/frontend/sass/main.scss",
|
||||
"Web/game-snake-poc/frontend/ts/main.ts",
|
||||
"Web/game-snake-poc/frontend/ts/assets.ts",
|
||||
"Web/game-snake-poc/frontend/ts/lifecycle.ts",
|
||||
"Web/game-snake-poc/frontend/ts/logging.ts",
|
||||
"Web/game-snake-poc/frontend/ts/provenance.ts",
|
||||
"Android/game-reflex-poc/build.gradle",
|
||||
"Android/game-snake-poc/build.gradle",
|
||||
"scripts/build_android_rust.py",
|
||||
@@ -39,6 +51,91 @@ REQUIRED_PATHS = (
|
||||
)
|
||||
|
||||
|
||||
def audit_snake_web_shell(root: pathlib.Path) -> list[str]:
|
||||
"""Validate the KSP-derived bounded SimpleBar shell contract."""
|
||||
|
||||
violations: list[str] = []
|
||||
html_path = root / "Web/game-snake-poc/frontend/main.html"
|
||||
app_scss_path = root / "Web/game-snake-poc/frontend/sass/_app.scss"
|
||||
main_ts_path = root / "Web/game-snake-poc/frontend/ts/main.ts"
|
||||
if not html_path.exists() or not app_scss_path.exists() or not main_ts_path.exists():
|
||||
return violations
|
||||
html = html_path.read_text(encoding="utf-8")
|
||||
app_scss = app_scss_path.read_text(encoding="utf-8")
|
||||
main_ts = main_ts_path.read_text(encoding="utf-8")
|
||||
required_html = (
|
||||
'<main class="app-main container-fluid p-0">',
|
||||
'<div class="row g-0 h-100 flex-nowrap">',
|
||||
'<section class="col app-content app-scrollable h-100" data-simplebar>',
|
||||
)
|
||||
for fragment in required_html:
|
||||
if fragment not in html:
|
||||
violations.append(f"DIST-LAYOUT-003: Snake Web shell missing required HTML contract: {fragment}")
|
||||
if '<main class="app-main container-fluid p-0" data-simplebar>' in html:
|
||||
violations.append("DIST-LAYOUT-004: data-simplebar must be attached to the bounded app-content zone, not app-main")
|
||||
required_scss = (
|
||||
".app-scrollable {",
|
||||
"height: 100%;",
|
||||
"max-height: 100%;",
|
||||
)
|
||||
for fragment in required_scss:
|
||||
if fragment not in app_scss:
|
||||
violations.append(f"DIST-LAYOUT-005: Snake Web shell missing required Sass contract: {fragment}")
|
||||
required_ts = (
|
||||
'import ResizeObserver from "resize-observer-polyfill";',
|
||||
'import "simplebar";',
|
||||
').ResizeObserver = ResizeObserver;',
|
||||
)
|
||||
for fragment in required_ts:
|
||||
if fragment not in main_ts:
|
||||
violations.append(f"DIST-LAYOUT-006: Snake Web shell missing SimpleBar bootstrap contract: {fragment}")
|
||||
return violations
|
||||
|
||||
|
||||
|
||||
def audit_snake_web_integration(root: pathlib.Path) -> list[str]:
|
||||
"""Validate assets, lifecycle, logging and provenance wiring for the Snake Web POC."""
|
||||
|
||||
violations: list[str] = []
|
||||
package_path = root / "Web/game-snake-poc/package.json"
|
||||
vite_path = root / "Web/game-snake-poc/vite.config.ts"
|
||||
main_path = root / "Web/game-snake-poc/frontend/ts/main.ts"
|
||||
lifecycle_path = root / "Web/game-snake-poc/frontend/ts/lifecycle.ts"
|
||||
provenance_path = root / "Web/game-snake-poc/frontend/ts/provenance.ts"
|
||||
wasm_manifest_path = root / "crates/apps/game-snake-poc-wasm/Cargo.toml"
|
||||
wasm_runtime_path = root / "crates/apps/game-snake-poc-wasm/src/runtime.rs"
|
||||
if not all(path.exists() for path in (package_path, vite_path, main_path, lifecycle_path, provenance_path, wasm_manifest_path, wasm_runtime_path)):
|
||||
return violations
|
||||
|
||||
package = package_path.read_text(encoding="utf-8")
|
||||
vite = vite_path.read_text(encoding="utf-8")
|
||||
main = main_path.read_text(encoding="utf-8")
|
||||
lifecycle = lifecycle_path.read_text(encoding="utf-8")
|
||||
provenance = provenance_path.read_text(encoding="utf-8")
|
||||
wasm_manifest = wasm_manifest_path.read_text(encoding="utf-8")
|
||||
wasm_runtime = wasm_runtime_path.read_text(encoding="utf-8")
|
||||
|
||||
required_fragments = (
|
||||
(package, '"vite-plugin-static-copy"', "DIST-LAYOUT-007: Snake Web package must declare static asset packaging"),
|
||||
(vite, 'dest: "common/data", rename: { stripBase: true }', "DIST-LAYOUT-008: common Web assets must retain the common/data namespace without absolute source prefixes"),
|
||||
(vite, 'dest: "game/data", rename: { stripBase: true }', "DIST-LAYOUT-009: game Web assets must retain the game/data namespace without absolute source prefixes"),
|
||||
(main, 'loadSnakeWebAssets()', "DIST-LAYOUT-010: Snake Web startup must load runtime asset probes"),
|
||||
(main, 'bindBrowserLifecycle(session, stage)', "DIST-LAYOUT-011: Snake Web startup must bind browser lifecycle"),
|
||||
(lifecycle, '"visibilitychange"', "DIST-LAYOUT-012: Snake Web lifecycle must observe visibility changes"),
|
||||
(lifecycle, '"pagehide"', "DIST-LAYOUT-013: Snake Web lifecycle must observe pagehide"),
|
||||
(lifecycle, 'ResizeObserver', "DIST-LAYOUT-014: Snake Web lifecycle must observe resize"),
|
||||
(provenance, '"keyboard-mouse"', "DIST-LAYOUT-015: Snake Web provenance must distinguish keyboard/mouse input"),
|
||||
(provenance, '"touch"', "DIST-LAYOUT-016: Snake Web provenance must distinguish touch input"),
|
||||
(wasm_manifest, 'engine-v1-platform-api = { path = "../../engines/engine-v1-platform-api" }', "DIST-LAYOUT-017: Snake WASM adapter must consume the platform provenance API"),
|
||||
(wasm_runtime, 'PlatformFamily::Web', "DIST-LAYOUT-018: Snake WASM provenance must declare Web platform family"),
|
||||
(wasm_runtime, 'ExecutionModel::Wasm', "DIST-LAYOUT-019: Snake WASM provenance must declare WASM execution"),
|
||||
(wasm_runtime, 'RuntimeHost::Browser', "DIST-LAYOUT-020: Snake WASM provenance must declare browser host"),
|
||||
)
|
||||
for content, fragment, message in required_fragments:
|
||||
if fragment not in content:
|
||||
violations.append(message)
|
||||
return violations
|
||||
|
||||
def main() -> int:
|
||||
"""Validate that every static distribution boundary exists."""
|
||||
|
||||
@@ -48,12 +145,15 @@ def main() -> int:
|
||||
root = pathlib.Path(arguments.root).resolve()
|
||||
missing: list[str] = []
|
||||
forbidden_present: list[str] = []
|
||||
contract_violations: list[str] = []
|
||||
for relative in REQUIRED_PATHS:
|
||||
if not (root / relative).exists():
|
||||
missing.append(relative)
|
||||
for relative in FORBIDDEN_PATHS:
|
||||
if (root / relative).exists():
|
||||
forbidden_present.append(relative)
|
||||
contract_violations.extend(audit_snake_web_shell(root))
|
||||
contract_violations.extend(audit_snake_web_integration(root))
|
||||
if missing:
|
||||
for relative in missing:
|
||||
print(f"DIST-LAYOUT-001: missing required path: {relative}", file=sys.stderr)
|
||||
@@ -64,6 +164,11 @@ def main() -> int:
|
||||
print(f"DIST-LAYOUT-002: generated path must stay outside repository: {relative}", file=sys.stderr)
|
||||
print(f"Distribution layout audit: {len(forbidden_present)} violation(s)", file=sys.stderr)
|
||||
return 1
|
||||
if contract_violations:
|
||||
for violation in contract_violations:
|
||||
print(violation, file=sys.stderr)
|
||||
print(f"Distribution layout audit: {len(contract_violations)} violation(s)", file=sys.stderr)
|
||||
return 1
|
||||
print(f"Distribution layout audit: clean ({len(REQUIRED_PATHS)} required path(s), {len(FORBIDDEN_PATHS)} forbidden path(s) absent)")
|
||||
return 0
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# file: scripts/audit_project_workspace_rules.py
|
||||
# version: 5
|
||||
# version: 6
|
||||
|
||||
"""Audit mechanically verifiable games.sasedev workspace boundaries."""
|
||||
|
||||
@@ -92,6 +92,18 @@ def main() -> int:
|
||||
for java_path in sorted(root.rglob("*.java")):
|
||||
if not java_path.is_relative_to(root / "Android"):
|
||||
errors.append(f"GAME-ANDROID-001: Java source outside Android/: {java_path.relative_to(root).as_posix()}")
|
||||
|
||||
changelog_text = (root / "CHANGELOG.md").read_text(encoding="utf-8")
|
||||
stable_versions = set(re.findall(r"^## ([0-9]+\.[0-9]+\.[0-9]+)(?: \u2014.*)?$", changelog_text, re.MULTILINE))
|
||||
roadmap_text = (root / "ROADMAP.md").read_text(encoding="utf-8")
|
||||
roadmap_sections = re.split(r"(?=^## )", roadmap_text, flags=re.MULTILINE)
|
||||
for section in roadmap_sections:
|
||||
heading = re.match(r"^## ([0-9]+\.[0-9]+\.[0-9]+)(?: \u2014.*)?$", section.splitlines()[0] if section.splitlines() else "")
|
||||
if heading is None or heading.group(1) not in stable_versions:
|
||||
continue
|
||||
for line in section.splitlines()[1:]:
|
||||
if line.startswith("- ( )"):
|
||||
errors.append(f"DOC-RMAP-010: stable version {heading.group(1)} retains planned scope: {line}")
|
||||
if errors:
|
||||
for error in errors:
|
||||
print(error, file=sys.stderr)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# file: scripts/audit_rust_workspace_rules.py
|
||||
# version: 1
|
||||
# version: 2
|
||||
|
||||
"""Run all Rust normalization and games.sasedev workspace audits."""
|
||||
|
||||
@@ -20,9 +20,9 @@ def main() -> int:
|
||||
arguments = parser.parse_args()
|
||||
script_dir = pathlib.Path(__file__).resolve().parent
|
||||
commands = [
|
||||
["python3", str(script_dir / "audit_rust_general_rules.py"), "--root", arguments.root],
|
||||
["python3", str(script_dir / "audit_rust_export_completeness.py"), "--root", arguments.root],
|
||||
["python3", str(script_dir / "audit_project_workspace_rules.py"), "--root", arguments.root],
|
||||
[sys.executable, "-B", str(script_dir / "audit_rust_general_rules.py"), "--root", arguments.root],
|
||||
[sys.executable, "-B", str(script_dir / "audit_rust_export_completeness.py"), "--root", arguments.root],
|
||||
[sys.executable, "-B", str(script_dir / "audit_project_workspace_rules.py"), "--root", arguments.root],
|
||||
]
|
||||
for command in commands:
|
||||
completed = subprocess.run(command, check=False)
|
||||
|
||||
Reference in New Issue
Block a user