16 KiB
Fiche MAPDL1-REX-2026-10-22 — Niveau N2 — Modèle prévu opus medium | utilisé claude-opus-5-5 — Agent session « Medium · MAPDL1 » — Skills sk-protocol, lp-lot, lp-city
MAPDL1 : retour d'expérience pour les skills et les agents (2026-10-22)
Demande de l'utilisateur, citée mot pour mot par Big Boss : « je souhaite aussi leur retour d'expérience pour enrichir les skills et agents ».
Cette fiche ne touche ni les skills ni les agents : Big Boss les posera après l'accord de l'utilisateur.
Chaque leçon donne quatre choses :
- Fait : ce qui a été observé, avec sa preuve (fichier:ligne, ou livrable du lot) ;
- Règle : ce qu'il faut retenir ;
- Où : le skill et sa section, ou l'agent ;
- Texte : un texte prêt à coller.
Priorités :
- P1 : évite une perte de données, une build cassée ou une donnée fausse ;
- P2 : évite des tours ou des allers-retours ;
- P3 : confort.
P1
R1. Le Move du moteur supprime la destination
- Fait :
IFileManager::Move(Dest, Src, Replace=true, …)supprime d'abord la destination (Engine/Source/Runtime/Core/Private/HAL/FileManagerGeneric.cpp:303). E5 a donc choisiMove(…, false, false, false, true)(LPCityMapsDownload.cpp:109) pour ne jamais rien supprimer. Vu en relecture, avant tout dégât. - Règle : dans un code qui « ne supprime jamais »,
Replaceest toujoursfalse. On écarte d'abord la destination existante par un déplacement horodaté. - Où :
lp-ue-compat, nouvelle section « API de fichiers » ; rappel danssk-change-safety. - Texte : «
IFileManager::MoveavecbReplace=truesupprime la destination avant de déplacer (FileManagerGeneric.cpp:303). Pour une pose sans suppression :Move(Dest, Src, /*Replace*/false, /*EvenIfReadOnly*/false, /*Attributes*/false, /*bDoNotRetryOrError*/true), après avoir déplacé l'ancienne destination dans un dossier horodaté. Source : MAPDL1-E5. »
R2. OpenSSL dans un module du jeu : conflit de UI
- Fait : E2 bis a échoué sur une erreur unique,
openssl/ossl_typ.h(144,22): error C2365: 'UI' : redéfinition ; la précédente définition était 'espace de noms'(MAPDL1-E2B-BUILD.md). La correction est la parade du moteur,#define UI UI_STavant les en-têtes et#undef UIaprès (BuildPatchServices/Private/Common/Crypto.cpp:6-12). E2 ter a ensuite rendu code 0. - Règle : on n'inclut jamais
openssl/*.hsans cet encadrement. Avant de lancer la build, on cherche par Grep tous les fichiers qui incluent OpenSSL : une seule build doit suffire. - Où :
lp-ue-compat(ruptures connues) etue-cpp-build(C2365). - Texte : « OpenSSL :
#define UI UI_ST/THIRD_PARTY_INCLUDES_START/#include "openssl/evp.h"/THIRD_PARTY_INCLUDES_END/#undef UI. Sans cela : C2365'UI'(le typedef d'OpenSSL heurte l'espace de nomsUId'UE). Modèle :Engine/Source/Runtime/Online/BuildPatchServices/Private/Common/Crypto.cpp:6-12. »
R3. Height d'un UStreetMap est en centimètres
- Fait :
StreetMap.h:304annonce des « meters », mais l'import écrit des centimètres (StreetMapFactory.cpp:387). Le GeoJSON de S7 en tient compte :height_m = Height / 100(MAPDL1-S7-IMPL.md§ 2). - Règle : toute lecture de
FStreetMapBuilding::Heightpasse en centimètres, quel que soit le commentaire. - Où :
lp-city§ 2, tableau des pièges de géométrie. - Texte : «
FStreetMapBuilding::Heightest en cm, malgré le commentaire « meters » (Public/StreetMap.h:304; écrit en cm parStreetMapImporting/StreetMapFactory.cpp:387) | établi, MAPDL1-S7 ».
R4. Une session compile le code posé par une autre
- Faits :
- La build de l'éditeur de COM31 a rendu
Target is up to date, avec 0 unité. La ligne R-1 avait en effet déjà été compilée à 18:23 par la build de la 1.7.4 de Paris : la DLL de l'éditeur était plus récente que la source (MAPDL1-COM31-BUILD.md).lp-buildery a vu un « échec probable » et s'est arrêté. - W1 et W2, posés par MAPDL1 sans être compilés, ont été compilés par le build de la 1.7.7 de STM1 (
STM1-155, code 0). - MAPDL1 et STM1 se sont échangé leurs listes de fichiers : aucun recouvrement.
- La build de l'éditeur de COM31 a rendu
- Règles :
- (a) Avant d'appeler « échec » un
Target is up to date, on compare la date de la DLL ou de l'exe à celle de la dernière source modifiée. - (b) Tout code posé non compilé est annoncé aux autres sessions, avec ses MD5 : leur build le compilera, et une casse doit revenir à son auteur.
- (c) Avant d'écrire dans
Source\, chaque session publie sa liste de fichiers et attend le signal de Big Boss.
- (a) Avant d'appeler « échec » un
- Où :
lp-build§ 8 pour (a) ;lp-lot/boss.mdpour (b) et (c) ; agentlp-builderpour (a). - Texte (lp-builder) : «
Target is up to dateavec 0 unité n'est pas un échec si la DLL ou l'exe est plus récent que la source modifiée : une autre session a déjà compilé. Relève les deux dates (Get-Item), rapporte, et continue la fiche si elle le prévoit. » - Texte (boss.md) : « Code posé non compilé : son auteur l'annonce à Big Boss et aux sessions qui compilent (fichiers et MD5). La première build qui le compile rapporte toute erreur à l'auteur. Écriture dans
Source\: liste des fichiers échangée entre les sessions, puis signal de Big Boss. »
R5. Reprise à l'identique d'une ancienne carte UE4
- Faits :
- Les cartes « NEW Maps » de Mega sont des UStreetMap UE4 cuits, non versionnés (legacy −7, ue4 = 0, drapeaux 0x80000000), avec des propriétés étiquetées. On les lit hors moteur (
LireCarteUE4.py) et on les reprend par réflexion (LPImportLegacyStreetMap,MAPDL1-P1-IMPL). - Le maillage
LPBuildCityStatic -Flatpasse la comparaison avec Londres (1,59 %). Le réglage par défaut et-Unlitéchouent (58 %). -Unlitréduit le nombre de sommets, pas celui des triangles.- Formule des triangles classiques :
3·Pb − 2·B, écart observé de 0 à −0,18 %. - Poids de la 3D classique : environ 20 octets par triangle dans l'archive (
MAPDL1-AUTO-FIN§ 2). - Un asset pilote laissé sous
Content\a cassé la cuisson des packs (DirectoriesToAlwaysCookcouvre/Game).
- Les cartes « NEW Maps » de Mega sont des UStreetMap UE4 cuits, non versionnés (legacy −7, ue4 = 0, drapeaux 0x80000000), avec des propriétés étiquetées. On les lit hors moteur (
- Règles :
- reprise par réflexion, sans conversion ;
-Flatpour le maillage statique repris ;- aucun asset de travail sous
Content\entre deux sessions ; - fourchettes de contrôle tirées de la formule.
- Où :
lp-city, nouvelle section « 9. Reprise d'une ancienne carte LifePlay (Mega) » ;lp-commandlets, table des cartes, avec une ligneLPImportLegacyStreetMap. - Texte (lp-city § 9) : « Ancienne carte Mega = UStreetMap UE4 cuit, non versionné (legacy −7, ue4 = 0, drapeaux 0x80000000), propriétés étiquetées. Lecture hors moteur :
Tools\LireCarteUE4.py --totaux; reprise :LPImportLegacyStreetMap(réflexion,-DryRun) ; chaîne :RepriseCarte.ps1(Lire, Creer, Importer, Classic, ODbL). Maillage statique :-Flat(Londres 1,59 % ; défaut et-Unlit58 %). Triangles classiques ≈3·Pb − 2·B(écart de 0 à −0,18 %) ; environ 20 o par triangle dans l'archive. Jamais d'asset de travail sousContent\(cuisson cassée, MAPDL1-P1). Les données (sans lat/lon ni identifiants OSM) se livrent en GeoJSON en plan local (SPEC-07). »
P2
R6. Exécutants haiku et chemins sous Git Bash
- Faits :
- EXEC-1 s'est arrêté sur un code 64 : le chemin du script, qui contient une espace, n'était pas entre guillemets dans Git Bash (
MAPDL1-AUTO-EXEC-1.md). - Avec un chemin absolu entre guillemets et des barres obliques, le lot 1 est passé (5 villes sur 5) sans aucune décision à prendre (
AUTO-FIN§ 2). Snapshot.ps1ne pose pas de code de sortie : il faut$global:LASTEXITCODE = 0avant l'appel.- Un
ifà un seul élément devient un scalaire : il faut@(if …)(JOURNAL-BROUILLON, 14:15).
- EXEC-1 s'est arrêté sur un code 64 : le chemin du script, qui contient une espace, n'était pas entre guillemets dans Git Bash (
- Règles :
- une brève pour haiku donne chaque commande en entier, avec un chemin absolu entre guillemets et des
/; - elle ne laisse aucun choix ;
- elle donne le code attendu et l'arrêt sur tout écart.
- une brève pour haiku donne chaque commande en entier, avec un chemin absolu entre guillemets et des
- Où :
sk-windows-shell; agentlp-builder;sk-orchestrate(fiche pour un modèle réduit). - Texte (sk-windows-shell) : « Git Bash et chemin avec espace :
pwsh -NoProfile -File "D:/Game/LifePlay-master 5.8/Tools/X.ps1"(guillemets,/). Sans guillemets : code 64.Tools\Snapshot.ps1ne pose pas de code :$global:LASTEXITCODE = 0avant l'appel. PowerShell : unifqui rend un seul élément est un scalaire ; écrire@(if …). »
R7. Dépassement du budget de tours (S7 : 62 pour 40)
-
Fait :
lp-impl(sonnet) a utilisé 62 tours pour 40 (MAPDL1-S7-IMPL.md). Causes déclarées :- débogage de commandes inline ;
- l'unité de
Height; - des essais ajoutés hors de la fiche (un vrai passage d'ODbL en plus du
-ABlancdemandé).
La fiche couvrait 3 outils liés physiquement, l'écriture en place et 3 villes d'essai, au niveau N3 avec 40 tours.
-
Règles :
- une fiche qui touche 3 outils avec des essais mesurés reçoit 60 tours ;
- les commandes répétées passent par un script ponctuel
Saved\<lot>\dès le 2e essai, pas en inline ; - aucun essai hors de la fiche sans le noter comme écart avant de le lancer.
-
Où :
sk-orchestrate(barème du budget) ; agentlp-impl;sk-protocol§ 8. -
Texte (lp-impl) : « Une commande longue ou répétée (pwsh inline, chemins avec
\) passe par un script ponctuelSaved\<lot>\dès le 2e essai. Un essai que la fiche ne demande pas ne se lance pas ; on le propose dans le compte rendu. » -
Texte (sk-orchestrate) : « Budget : 3 fichiers ou plus, plus des essais mesurés = 60 tours (N3), pas 40. »
R8. Mise en page Slate : contrôle obligatoire hors de la zone qui défile ; habillage des chemins
- Faits :
- Dans COM31, la case d'accord était dans la même
SScrollBox(plafonnée parSBox::MaxDesiredHeight) que la licence dépliée : elle passait sous le cadre (cas B2,TESTS-02§ E). AutoWrapTextne coupe qu'entre deux mots : un chemin sans espace dépasse (B8).- Correctifs W1 :
- la case et les messages sortent de la zone qui défile ;
.WrappingPolicy(ETextWrappingPolicy::AllowPerCharacterWrapping)(STextBlock.h:121,TextLayout.h:72) ;- la hauteur de la zone suit le viewport (
UWidgetLayoutLibrary::GetViewportScale).
- Dans COM31, la case d'accord était dans la même
- Règles :
- les contrôles obligatoires (case d'accord, boutons) et les messages ne vont jamais dans une zone qui défile ;
- tout texte qui peut contenir un chemin ou une URL reçoit
AllowPerCharacterWrapping; - une fenêtre se vérifie en 1280×720.
- Où : agent
lp-impl(rubrique Slate et UMG) ;lp-ue-compat(API Slate 5.8). - Texte : « Slate : les contrôles obligatoires et les messages hors de la
SScrollBox(plafonnée parSBox::MaxDesiredHeight, qui peut suivre le viewport :MaxDesiredHeight_Lambda+UWidgetLayoutLibrary::GetViewportScale). Chemin ou URL :.WrappingPolicy(ETextWrappingPolicy::AllowPerCharacterWrapping), carAutoWrapTextne coupe qu'entre deux mots. Vérifier en 1280×720. Source : MAPDL1, essai COM31 (B2, B8). »
R9. Fichier partiel vide après un échec réseau
- Fait :
CreateFileWriter(…, FILEWRITE_Append)crée le fichier, et son dossier, avant le premier octet. L'échec voulu de B5 (DNS) a laisséSaved\Downloads\lpm_city_manila\…zip.partde 0 octet dans un dossier visible (B9). Correctif W2 :- le
.partest écrit à côté du zip ; - à l'échec et à l'annulation, un
.partvide est déplacé dans_rejet\(SetAsideEmptyPart), sans aucunDelete.
- le
- Règle : un téléchargement qui échoue sans recevoir d'octet ne laisse ni fichier ni dossier visible. On le range (déplacement), on ne le supprime pas.
- Où : agent
lp-impl;lp-ue-compat(HTTP). - Texte : « HTTP en flux (
SetResponseBodyReceiveStream) : le.partexiste dès l'ouverture. À l'échec ou à l'annulation, s'il fait 0 octet, le déplacer dans_rejet\; pas de sous-dossier par téléchargement. Source : MAPDL1 W2. »
R10. Le cahier d'essai se calcule comme le code
- Fait : le cahier attendait « Download (21 MB) » pour 22 075 120 octets. Le jeu affiche 22, car il arrondit au-dessus (
LPCityMapsSubsystem.cpp:734). C'est le cahier qui avait tort (TESTS-02A1). - Règle : une valeur attendue se calcule par la formule du code, qu'on cite, et non de tête.
- Où :
lp-doc(gabarit FIT) ; agentlp-writer. - Texte : « Valeur attendue d'un affichage : la calculer par la formule du code, avec fichier:ligne (arrondi, unités). Exemple : 22 075 120 o → « 22 MB » (Mo arrondi au-dessus). »
P3
R11. Crochet ecriture-gardien et agents de lecture
- Fait observé dans MAPDL1 : une commande Bash de
lp-validator(E3 bis) a été refusée par le crochet, à cause d'un accent grave dans le texte. C'était un faux positif, sans effet ; l'agent l'a relancée sans ce caractère (MAPDL1-E3B-VAL.md, compte rendu). - Non observé dans MAPDL1 : le blocage des agents de collecte que cite Big Boss. Big Boss le complète avec ses propres preuves.
- Règle : pour un agent sans Edit, pas d'accent grave ni de
>dans les commandes du shell. Les recherches passent par Grep ou Read. - Où :
sk-protocol§ 7 (agents sans Edit) ;hooks\cas-v2.jsonl(cas d'essai). - Texte : « Agent sans Edit : aucune commande shell avec accent grave,
>ni->, même dans du texte cité ; le crochetecriture-gardienles refuse (faux positif, MAPDL1-E3B). Reformuler, ou passer par Grep et Read. »
R12. Outils liés physiquement : écriture en place
- Fait :
IndexCartes,LireCarteUE4,RepriseCarteetRecetteCartesont des liens physiques entre le jeu et l'addon. Ils ont été écrits par[IO.File]::WriteAllBytes, qui tronque le même fichier. Les MD5 sont identiques des deux côtés etfsutilmontre 2 liens (S6-1-IMPL,S7-IMPL). La mémoire du projet le disait déjà ; les fiches l'ont rappelé à chaque fois. - Règle : la règle est déjà en mémoire ; il faut l'écrire dans le skill.
- Où :
lp-paths(Outils du jeu) ; agentslp-impletlp-writer. - Texte : « Beaucoup de fichiers de
Tools\sont liés physiquement à l'addon : Edit et Write rompent le lien. Vérifier parfsutil hardlink list; écrire en place par[IO.File]::WriteAllBytes(<Tools>, [IO.File]::ReadAllBytes(<brouillon>)); relire les 2 liens et les 2 MD5. »
R13. EtatDir.ps1 ne connaît pas un nouveau lot
- Fait :
Build.ps1a écrit ses résumés dansetat\MAPDL1-E2B\,etat\MAPDL1-E2T\etetat\MAPDL1-COM31\, à la racine d'etat\. Ils ont été déplacés à la clôture (MAPDL1-BILAN§ 6). - Règle : à l'ouverture d'un lot, on ajoute sa règle à
EtatDir.ps1, ou on passe-EtatDirà chaqueBuild.ps1et à chaqueRunCommandlet.ps1. - Où :
lp-lot(Avant toute modification) ; agentlp-builder(passer-EtatDirsi la fiche le donne). - Texte : « Nouveau lot : règle dans
Tools\EtatDir.ps1, ou-EtatDir <etat>\<projet>\<lot>sur chaqueBuild.ps1/RunCommandlet.ps1. Sinon, les résumés vont à la racine d'etat\(MAPDL1). »
R14. Avertissement préexistant à séparer d'un effet nouveau
- Fait :
Accessed None … property GI in /Game/UI/CityMenu.CityMenu_Capparaît 5 fois dans l'essai COM31. Il figure déjà dans les 6 derniers journaux de COM30, sans E1 (TESTS-02§ E). - Règle : avant d'attribuer un avertissement à un lot, on le compte dans les journaux de la build précédente.
- Où :
lp-validate§ 3 ; agentlp-validator. - Texte : « Avertissement en jeu : le compter dans les journaux de la build d'avant (
Saved\Logs\*.log) avant de l'attribuer au lot. Exemple : CityMenuGI(Accessed None), préexistant à MAPDL1. »
Fichiers
- A
Docs/Migration/etat/REL/MAPDL1/MAPDL1-REX-2026-10-22.md - Aucun skill ni agent n'est modifié.