16 packaging D9 ACTEE : absence explicite, pas crate separee -- et le draft disait « l execution echoue » sans dire comment, ce qui est toute la question. Mesure sur les trois chargeurs (from_file, from_file_nearest, from_file_with_format, gpu.rs) : TextureError n a AUCUNE variante IO, les trois font map_err(Decode(ImageError::IoError(e))). Le message vaut donc failed to decode image: No such file or directory (os error 2) -- faux diagnostic (ce n est pas un decodage) qui ne nomme pas le chemin. Les 14 exemples a medias paniqueraient la-dessus sur le tarball. Famille 6.12 (deux representations du meme echec), version type qui ment sur la nature. Remede : UN endroit (le chargeur, variante NotFound { path } + Display qui nomme le chemin), pas 14 helpers. Verrou a trois jambes (existant -> Ok ; absent -> type attendu ET Display nomme le chemin ; present mais illegitime -> reste Decode, sinon la separation n est pas demontree, 13.12). Moment : au commit qui pose exclude = [examples/assets] dans packaging-crate, pas avant -- ecrire aujourd hui un chemin que rien n exerce serait creer la famille membre documente et jamais appele. La couche 3 ne peut pas trancher (pas d affichage, 12.15) : c est le verrou du chargeur qui porte la propriete.

This commit is contained in:
Jérôme Bousquié committed 2026-11-04 15:03:24 +01:00
1 parent c56f9af1c2
commit 3cda919710
1 file changed
+6 -1
+6 -1
View File
@@ -109,9 +109,14 @@ Exception, la seule partie de `docs/` à déplacer dans la source : le **contrat
- le verrou `the_license_field_and_the_license_text_agree` (`lib/tests/doc_consistency.rs`, binaire passé de 24 à **25** verrous) confronte **deux sources** — le champ et le texte — plus la ligne de titulaire. Il n'est pas une existence (une existence est un décor) et il a été **vu ROUGE sous deux mutations** : `license = "Apache-2.0"` en gardant le texte MIT, et `Copyright (c)` vidé de son titulaire. Les deux ont été défaites par leur inverse exact, pas par `git checkout` (6.19 : l'implémentation n'était pas encore commitée).
Limite écrite : ce verrou vit dans un binaire **exclu** du paquet (`doc_consistency` porte les instruments du dépôt). Il ne tourne donc pas sur le tarball ; ce qui le garantit là-bas, c'est la couche 3 du § 6. Écrire le contraire serait une fausse preuve (6.19).
**D9 — Les exemples : livrer le code, exclure les médias, rendre l'absence explicite.** Mesures : 50 `.rs` + `.wgsl` = **0,6 MiB** ; les médias = **18 Mo** (31 fichiers, `BoomBox.glb` seul = 10,7 MiB) ; **14 exemples / 15 sites** ouvrent `examples/assets/…` via `CARGO_MANIFEST_DIR`. Position : les exemples **restent dans le paquet** — ils sont la surface documentaire de cette bibliothèque (bandeaux, manifeste des promesses, oracles lus par **40 sites** de verrous via `example_const` / `example_has_*`) et ils ne coûtent presque rien. Ce qui sort, ce sont les médias. Conséquence assumée : sur le tarball, les 14 exemples concernés compilent mais échouent à l'exécution. Ce n'est pas acceptable en l'état, parce que le mode de défaillance habituel de ce dépôt est le silence : il faut une **commodité partagée** qui, quand le fichier manque, affiche le chemin cherché, dise que l'asset n'est pas dans le paquet et nomme où le trouver (le dépôt). Un helper, pas 14 `if path.exists()` divergents (gotcha 6.7 : le même défaut apparaît le jour où le code est dupliqué).
**D9 — Les exemples : livrer le code, exclure les médias, rendre l'absence explicite.** Mesures : 50 `.rs` + `.wgsl` = **0,6 MiB** ; les médias = **18 Mo** (31 fichiers, `BoomBox.glb` seul = 10,7 MiB) ; **14 exemples / 15 sites** ouvrent `examples/assets/…` via `CARGO_MANIFEST_DIR`. Position : les exemples **restent dans le paquet** — ils sont la surface documentaire de cette bibliothèque (bandeaux, manifeste des promesses, oracles lus par **40 sites** de verrous via `example_const` / `example_has_*`) et ils ne coûtent presque rien. Ce qui sort, ce sont les médias. Conséquence assumée : sur le tarball, les 14 exemples concernés compilent mais échouent à l'exécution. Ce n'est pas acceptable en l'état, parce que le mode de défaillance habituel de ce dépôt est le silence : il faut rendre l'absence **explicite** : le chemin cherché, le motif, et où le trouver. Le lieu exact de cette commodité est précisé au paragraphe « actée » ci-dessous — c'est le **chargeur**, pas un helper recopié dans les exemples (gotcha 6.7 : le même défaut apparaît le jour où le code est dupliqué).
L'alternative — une crate `wsg-examples` séparée — n'est **pas** gratuite, et son coût est mesuré : **15 fichiers de test** nomment une sous-arborescence `examples/` et **40 sites** lisent les constantes des exemples. Déménager les exemples hors de `lib/` casse ces 15 fichiers et oblige à redéclarer les 50 `[[example]]` dans un autre package. À reconsidérer seulement si quelqu'un veut *exécuter* les démos depuis crates.io ; d'ici là, D1 + l'absence explicite est moins cher et garde les verrous en place.
**Actée le 2026-11-04 : absence explicite, pas crate séparée.** Le draft disait « l'exécution échoue » sans dire **comment** — et le comment est toute la question. Mesuré sur les trois chargeurs de fichier (`from_file`, `from_file_nearest`, `from_file_with_format`, `lib/src/resources/texture/gpu.rs`) : `TextureError` n'a **aucune** variante d'IO, et les trois font `map_err(|e| TextureError::Decode(image::ImageError::IoError(e)))`. Le message rendu vaut donc « failed to decode image: No such file or directory (os error 2) » — un **faux diagnostic** (ce n'est pas un échec de décodage) qui **ne nomme pas le chemin cherché**. Sur le tarball, les 14 exemples paniqueraient là-dessus : c'est exactement la famille « deux représentations du même échec » consignée en 6.12, version type qui ment sur la nature de l'erreur.
Le remède n'est donc **pas** 14 helpers côté exemples : c'est **un** endroit, le chargeur — séparer l'IO du décodage (variante `NotFound { path }`) avec un `Display` qui nomme le chemin. Une ligne de type plutôt que quatorze branches, et la doctrine 6.7 est respectée : un seul endroit, appelé, pas un code copié.
Verrou (deux jambes, headless) : chemin existant → `Ok` ; chemin absent → le **type** est celui attendu **et** le `Display` nomme le chemin. Troisième jambe obligatoire : un fichier **illégitime mais présent** doit rester une erreur de décodage — sinon la séparation IO / décodage n'est pas démontrée (un verrou qui ne confronte pas les deux branches est un verrou d'égalité, 13.12).
**Le moment compte** : ce fix s'écrit au commit qui pose `exclude = ["examples/assets"]` dans la branche `packaging-crate`, pas avant. Sur `main`, les 50 exemples trouvent leurs médias ; écrire un chemin de code que rien n'exerce, c'est créer soit‑même la famille « membre documenté et jamais appelé » que ce dépôt passe des heures à fermer. Et la couche 3 du § 6 ne peut pas trancher : lancer un exemple suppose un affichage, et il est mesuré (12.15) que la boucle winit ne reçoit ici aucun `RedrawRequested`. C'est donc le verrou du chargeur qui porte la propriété, pas l'artefact.
**D10 — Le nom : la question est rouverte, et elle coûte zéro.** Le § 10 posait « le nom `wsg-lib` ne bouge pas ». Cargo dissocie le nom de *package* du nom de *lib* : `[package] name = "wsg"` avec `[lib] name = "wsg_lib"` est valide, donc le nom que l'utilisateur taperait (`wsg`, mesuré libre sur crates.io au § 1) est gratuit. Aucun verrou du dépôt ne dépend du nom de package ; `wsg_lib::` reste l'identifiant de compilation. La décision se prend avec les métadonnées (D8), pas après.
## 4. Le périmètre cible