# Retours d'expérience

Ces cinq entrées racontent des erreurs et des frictions que le projet a mesurées en pilotant GIMP, Inkscape et Blender depuis un modèle : le fait observé, le mécanisme, la correction et la façon de la vérifier. Elles s'adressent à qui écrit des scripts pour ces applications, ou des guides qui les décrivent.

Les entrées sont classées par date. Chaque chiffre renvoie à une ligne d'un guide du dépôt ou d'une page de ce site, que l'entrée nomme. Cette page n'existe qu'en français.

## 12 octobre 2026 : une commande `-b` de GIMP rend la main, et le pont s'arrête avec elle

- **Fait :** au premier lancement de GIMP avec son interface, le pont chargé par une commande `-b` seule, la fenêtre s'est ouverte mais le port 9301 est resté fermé. La sortie disait `batch command executed successfully` et `ss -ltn` ne listait aucun socket en écoute.
- **Mécanisme :** une commande `-b` qui se termine rend la main, et le processus du greffon `python-fu-eval`, celui qui exécute le pont, s'arrête avec elle ; GIMP lui-même reste ouvert. Ce greffon n'a pas de boucle bloquante qui le garde en vie.
- **Correction :** le pont fournit `serve_main_thread()`, qui fait tourner la boucle principale de GLib dans le fil d'exécution qui l'appelle, jusqu'à `stop()`, jusqu'à la durée passée en paramètre ou jusqu'à Ctrl+C. Les commandes des guides l'appellent à la fin du `-b`. Règle de méthode retenue : vérifier un nom d'API sur le processus vivant avant de l'employer (`Gimp.FillType.FOREGROUND`, `layer.fill`, `Gegl.Color.new('blue')`), jamais sur la mémoire du modèle.
- **Vérification :** la section `Started without the interface` de `docs/modules/gimp.md` décrit le mécanisme et le port 9301 qui se ferme dès que la commande rend la main. La page [Compatibilité](https://libremodular.davalan.fr/fr/compatibility/index.md#gimp) relève le port ouvert environ 6 s après le démarrage de GIMP quand la commande appelle `serve_main_thread()`.

## 20 octobre 2026 : une API change de nom entre deux versions, et trois appels échouent sans message

- **Fait :** l'exemple du guide de GIMP fonctionne, mais le reste de l'API Python de GIMP 3.0 a été renommé par rapport à GIMP 2.10. `Gimp.Image.new` prend un type de base (`Gimp.ImageBaseType.RGB`) et non un `Gimp.ImageType` ; les couleurs sont des `Gegl.Color` et `Gimp.RGBA` n'existe plus ; `Gimp.ChannelOp` est devenu `Gimp.ChannelOps` ; `Gimp.BucketFillType` est devenu `Gimp.FillType` ; `Gimp.File.load` est devenu `Gimp.file_load`. Dans Inkscape 1.4, `inkex.Circle.new(64, 64)` donne `cx="64.0" cy="0.0" r="64.0"`, un cercle collé au bord supérieur du document, et `inkex.Path` n'a aucune méthode de segment. Trois appels de GIMP échouent sans lever d'erreur : `image.insert_layer` avec un calque d'une autre image ne fait rien, et `image.get_layers()` reste vide ; `layer.edit_bucket_fill` a laissé un calque entièrement transparent, l'image aplatie valant `srgba(0,0,0,0)` ; `layer.scale` avec une hauteur négative (`-1`) ne fait rien.
- **Mécanisme :** la documentation d'un module est écrite d'après une exécution sur une version, tandis que le script qu'un modèle écrit de mémoire vise une autre version. Le pont ne voit rien : l'application répond par une `AttributeError` ou une `TypeError`, et un modèle qui ne connaît pas les nouveaux noms conclut que l'API est cassée. Les échecs sans message sont les plus coûteux, parce que le résultat est faux sans que rien le dise.
- **Correction :** le guide de chaque module porte les renommages de la version sur laquelle il a été éprouvé, ainsi que les pièges qui ne lèvent pas d'erreur. Devant une `AttributeError` sur une API qu'on croit connaître, lire `dir()` dans l'application vivante plutôt que de conclure.
- **Suite, le 21 octobre 2026 :** le guide donnait `layer.fill` pour remplacer `edit_bucket_fill`. En jouant la recette de la page [GIMP](https://libremodular.davalan.fr/fr/applications/gimp/index.md), un script est resté sans erreur et a exporté une seule couleur : `layer.fill` ignore la sélection. Sur une ellipse sélectionnée, un calque transparent rempli par `layer.fill` a montré un alpha de 1,0 dans son coin, et 0,0 avec `layer.edit_fill`, qui respecte la sélection.
- **Vérification :** la section `GIMP 3.0 API: renamed calls and silent failures` de `docs/modules/gimp.md` ; la section `inkex 1.4: traps that raise no error` de `docs/modules/inkscape.md` ; les scripts et les réponses de la page [GIMP](https://libremodular.davalan.fr/fr/applications/gimp/index.md).

## 20 octobre 2026 : Blender en Workbench, quatre réglages qui donnent un rendu faux sans erreur

- **Fait :** pour un rendu piloté par `bpy`, jugé au pixel, dans le moteur de rendu Workbench et lancé par `blender -b`, quatre réglages donnent un rendu faux sans message. `scene.display.shading.color_type = "OBJECT"` lit `object.color`, blanc par défaut : tout est blanc. `material.diffuse_color` est en linéaire : écrire la valeur sRGB de `#c4553a` rend `#E39C83`. Le fond reste le gris du thème, `srgba(64,64,64,1)`, même quand une couleur de monde est assignée : `background_type = "WORLD"` ne change rien et `"CUSTOM"` échoue en mode arrière-plan. Un biseau posé après `obj.scale` est écrasé par l'échelle. Enfin, un PNG transparent se lit comme une image blanche dans un visionneur qui compose sur du blanc.
- **Mécanisme :** chaque réglage paraît correct là où l'œil regarde (l'étiquette `OBJECT`, la couleur assignée, la valeur `WORLD`, la largeur du biseau), aucun ne lève d'erreur, et l'échec se réduit à un rendu faux. Le modèle écrit d'après sa mémoire de l'API de Blender, qui reste celle d'anciennes versions ; seul l'histogramme du PNG rendu a fourni la donnée qui contredit.
- **Correction :** pour tout rendu `bpy` travaillé au pixel, employer `color_type = "MATERIAL"` et convertir les couleurs de sRGB en linéaire avant de les assigner ; composer le fond après le rendu transparent (`magick render.png -background "#f4efe8" -alpha remove -alpha off`), sans l'attendre du moteur de rendu ; appliquer l'échelle au maillage (`bpy.ops.object.transform_apply(scale=True)`) avant tout biseau ; prouver la couleur réelle par un histogramme (`magick render.png +dither -colors 6 -format %c histogram:info:`) et juger l'image composée, pas le PNG transparent.
- **Vérification :** la liste de `docs/modules/blender.md` pour le moteur Workbench, mesurée dans Blender 4.3.2. Dans le moteur de rendu par défaut, le même genre de piège existe : la transformation de vue `AgX` a rendu `#103759` pour une couleur de monde écrite `#1c385c`, et la page [Blender](https://libremodular.davalan.fr/fr/applications/blender/index.md) montre le script, la réponse `ok` et la correction.

## 20 octobre 2026 : un guide affirmait un rendu possible sans l'avoir essayé

- **Fait :** le guide du module Blender disait qu'un script pouvait encore faire un rendu volontaire dans le répertoire de travail ; la mesure en `blender -b` a conclu l'inverse : `bpy.ops.render.render` bloquait jusqu'au délai de 30 s.
- **Mécanisme :** la phrase avait été écrite d'après l'API publique, sans exécution.
- **Gravité :** un lecteur du guide perdait 30 s et la connexion du pont à chaque rendu.
- **Correction :** une capacité n'entre dans un guide de module qu'avec la version et le mode où elle a été jouée ; sinon le guide dit « non essayé ».
- **Vérification :** `git show a714b22 -- docs/modules/blender.md` du dépôt de code retire la phrase `A script can still render on purpose` ; la section `Rendering` du même guide la remplace. L'entrée suivante corrige la conclusion de cette mesure.

## 20 octobre 2026 : le blocage du rendu est intermittent, et un premier essai réussi ne prouve rien

- **Fait :** la première mesure donnait le blocage du rendu comme constant en `blender -b` et l'attribuait au fil d'exécution réseau du pont. Rejoué avec l'ancienne amorce, qui se contente de dormir, le même rendu a réussi aux deux premiers essais, est resté sans retour à un essai (le Hub a répondu `timeout` au bout de 30 s, puis `busy`), et a réussi 20 fois de plus, sous charge comprise : 22 réussites sur 23 essais. Avec l'amorce qui appelle `serve_main_thread()` : 11 rendus sur 11.
- **Mécanisme :** Blender ne garantit pas `bpy.ops` hors de son fil principal ; le rendu y réussit presque toujours et peut ne jamais revenir. La condition exacte de l'échec n'a pas été isolée : l'écran, la charge et le moteur ont été écartés comme condition suffisante. Une hypothèse écrite avant la mesure (« cela dépend de l'écran ») a dû être retirée des fiches.
- **Gravité :** un défaut intermittent se déclare « non reproduit » à la première réussite, ou « dépend de l'environnement » à la première explication plausible ; les deux conclusions étaient fausses.
- **Correction :** pour un défaut signalé une seule fois, mesurer sa fréquence (nombre d'essais, nombre d'échecs) avant d'écrire une condition ; ne corriger que par la cause que la documentation de l'application confirme, ici exécuter dans le fil principal ; relever le nombre d'essais plutôt qu'un « reproduit » ou un « non reproduit ».
- **Vérification :** la section `Rendering` de `docs/modules/blender.md` donne les 11 rendus et les 22 réussites sur 23 ; `tests/bridges/test_blender_adapter.py` couvre le passage du script au fil principal par `serve_main_thread()`. La page [Compatibilité](https://libremodular.davalan.fr/fr/compatibility/index.md#blender) relève 30,5 s et 31,2 s pour le premier rendu d'un profil neuf, avec un délai de 120 s.

