0.3.0-0-pre.4-fix.3

This commit is contained in:
2026-09-20 13:40:19 +02:00
parent 023825b89b
commit 86b8af3b61
10 changed files with 200 additions and 19 deletions

View File

@@ -1,5 +1,5 @@
# file: Cargo.toml
# version: 65
# version: 66
[workspace]
resolver = "3"
@@ -20,7 +20,7 @@ members = [
]
[workspace.package]
version = "0.3.0-0-pre.4.fix.2"
version = "0.3.0-0-pre.4.fix.3"
edition = "2024"
license = "MIT"
repository = "https://git.sasedev.com/Sasedev/games"

View File

@@ -1,5 +1,5 @@
<!-- file: README.md -->
<!-- version: 33 -->
<!-- version: 34 -->
# games.sasedev
@@ -26,7 +26,7 @@ Workspace expérimental puis productif pour des jeux multiplateformes principale
Version stable de référence : `0.2.0`.
Version de développement : `0.3.0-0-pre.4.fix.2`.
Version de développement : `0.3.0-0-pre.4.fix.3`.
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.

View File

@@ -1,5 +1,5 @@
<!-- file: Web/game-snake-poc/frontend/main.html -->
<!-- version: 2 -->
<!-- version: 3 -->
<!DOCTYPE html>
<html lang="fr">
@@ -31,9 +31,10 @@
</nav>
</header>
<main class="app-main container-fluid p-0" data-simplebar>
<section class="app-content">
<div class="container-fluid px-3 px-md-4 py-3 py-md-4">
<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">
@@ -91,8 +92,9 @@
<p id="startup-error" class="alert alert-danger mt-3 mb-0" role="alert" hidden></p>
</div>
</div>
</div>
</section>
</div>
</section>
</div>
</main>
<footer class="app-footer bg-dark text-light">

View File

@@ -1,5 +1,5 @@
// file: Web/game-snake-poc/frontend/sass/_app.scss
// version: 2
// version: 3
$app-header-height: 72px;
$app-footer-height: 42px;
@@ -47,8 +47,20 @@ body {
overflow: hidden;
}
.app-main > .row {
flex-wrap: nowrap;
min-width: 0;
}
.app-scrollable {
height: 100%;
max-height: 100%;
}
.app-content {
min-height: 100%;
min-width: 0;
height: 100%;
max-height: 100%;
}
.app-logo {

View 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.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/development/010-SNAKE_WEB_FRONTEND.md -->
<!-- version: 2 -->
<!-- version: 3 -->
# Frontend du POC Snake Web direct
@@ -59,7 +59,7 @@ Le document `frontend/main.html` fournit :
- quatre boutons directionnels tactiles ;
- une zone d'erreur de démarrage ;
- un footer léger commun au shell ;
- une zone `app-main` scrollable par SimpleBar entre le header et le footer fixes.
- 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.
@@ -82,7 +82,7 @@ Le frontend lit la couleur de fond et les rectangles normalisés exposés par `g
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. Si le plateau portrait et les contrôles dépassent la hauteur disponible, `app-main` reste borné à `100vh - header - footer` et SimpleBar porte le scroll interne. Cette tranche couvre le resize visuel nécessaire au shell ; la gestion complète du lifecycle navigateur reste prévue par `0-pre.5`.
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

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/001-V0_3_0_WEB_SNAKE_POC_PLAN.md -->
<!-- version: 8 -->
<!-- version: 9 -->
# Plan v0.3.0 — baseline Snake et premier POC Web direct
@@ -69,7 +69,7 @@ Gate : audits statiques, `cargo check --workspace`, Clippy ciblé, tests de l'ad
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 interne de `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`.
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.
@@ -77,6 +77,8 @@ Suivi `0-pre.4.fix.1` : la validation utilisateur de `0-pre.4` a confirmé le fo
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.
### `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.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/rules/RULES_PROJECT.md -->
<!-- version: 14 -->
<!-- version: 15 -->
# Règles spécifiques games.sasedev
@@ -86,6 +86,7 @@
- **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.
## Version d'en-tête des fichiers

View 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.

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env python3
# file: scripts/audit_distribution_layout.py
# version: 4
# version: 5
"""Audit the static distribution layout expected by supported POCs."""
@@ -47,6 +47,47 @@ 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 main() -> int:
"""Validate that every static distribution boundary exists."""
@@ -56,12 +97,14 @@ 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))
if missing:
for relative in missing:
print(f"DIST-LAYOUT-001: missing required path: {relative}", file=sys.stderr)
@@ -72,6 +115,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