LifePlay-Revival/Docs/Migration/etat/ST/STB/STB-GIB-DATA-INV.md
edujiro5972 8084622450 LifePlay UE 5.8 : état de développement au 2026-10-19
Tickets : REP1-T4

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 22:57:42 +02:00

110 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Fiche STB-GIB-DATA — Niveau N1 — Modèle prévu modèle de l'agent lp-inventory (non nommé dans la fiche) | utilisé Sonnet 5.5 (claude-sonnet-5-5) — Agent lp-inventory — Skills sk-protocol, sk-recount, lp-paths
# STB-GIB-DATA-INV : lignes de données fautives de Clothes4.txt (K1) et de Modules/MorphTags (K2) (2026-10-09)
Abréviations : `EG` = `D:\Game\LifePlay-master 5.5\Docs\Migration\etat\ST\STA\dumps\GI__EventGraph.txt` ; `LOG` = `D:\Game\LifePlay_Build_5.8_Development_U8_essai\Windows\LifePlay\Saved\Logs\LifePlay.log` ; `MOD` = `D:\Game\LifePlay-master 5.8\Content\Modules` (dépôt local, copie 5.8) ; `SP` = scratchpad de session (`%USERPROFILE%\AppData\Local\Temp\claude\D--Game-LifePlay-master-5-8\87a0d630-8082-4d24-9a2d-960932aa8255\scratchpad`, volatil).
## 1. Commandes exactes
Fichiers lus (identification, preuve dump:ligne) :
- Read `EG` offsets 28080-28171, 28170-28249, 28250-28379, 28680-28819 ; Grep `Clothes4` sur `EG` (-n) ; Grep `MorphTags|GetAllFilesFromFolder|PopulateEachMorphTags|Lines_PopEaMorTag` sur `EG` (-n) ; Grep `MorphTagFiles` sur `...\etat\ST\STA` (1 résultat, le DIAG).
- Octets du dump : `python -I SP\dumpbytes.py EG` (ligne 28707 et 28150 = `Delimiter = '` + `\r`).
- Code lu : `Source\LifePlay\LPStringCompat.cpp:5-27` (ParseIntoArray) ; `Plugins\ModdingExtra\Source\ModdingExtra\Private\ModdingExtraBPLibrary.cpp:181-232` (LoadTxt = cache `FLPDataCache` ou `FFileHelper::LoadFileToString(ProjectContentDir + nom)`).
- Journal : Grep sur `LOG` de `Attempted to access index 3 from array CallFunc_ParseIntoArray_ReturnValue_3 of length 3!`, `... index 1 ... _29 of length 1!`, `... _28 of length 1!`, `GI_C:PopulateAllMorphTags$`, `STARTUPCHECK - Person BeginPlay` (-n, offsets pour premier/dernier).
- Disque : `ls -la MOD`, `ls -la MOD\MorphTags`, `md5sum` de `Clothes4.txt` (copie 5.8 et build U8 essai).
- Script de lecture (SP, python -I, lecture seule) : `analyse.py` (charge le fichier comme LoadFileToString : BOM retiré, UTF-8 ; découpe en lignes puis sur `': '` avec CullEmpty = true, algorithme de `LPStringCompat.cpp:13-24`, deux modèles de délimiteur de lignes : A = `\n`, B = `\r\n`), `k1.py`, `k1b.py` (exporte `SP\k1_bad_Clothes4.tsv`), `k2.py` (exporte `SP\k2_bad_<fichier>.txt`), `uasset.py` / `uasset2.py` (recherche de chaînes dans `Content\BPs\GI.uasset`).
- Recomptes par seconde méthode (Grep, regex) :
- K1 lignes à 3 champs : Grep `^(?:[^:]|:[^ ])*: (?:[^:]|:[^ ])*: (?:[^:]|:[^ ])*$` count sur `MOD\Clothes4.txt` ; lignes à 4 champs ou plus : même motif avec 3 `: ` suivis de `: ` ; total : Grep `^` count.
- K2 lignes non vides sans `: ` : Grep `^[^:\r\n](?:[^:]|:[^ ])*$` count sur `MOD\MorphTags` ; contrôle des numéros de ligne en mode content -n sur `trueBodies.txt` et `falseBodies.txt`.
- Contrôle d'intégrité : `git status --porcelain` dans `MOD` (0 ligne) et dans la copie 5.8 (voir § 3).
## 2. Comptes bruts
### 2.1 K1 — populateClothes4, fichier lu : `Modules/Clothes4.txt`
Preuve dump (établi) : `EG:28699-28703` `ModdingExtraBPLibrary::LoadTxt`, `FileNameA = 'Modules/Clothes4.txt'` (nœud `CallFunction_1065`, dans l'événement `K2Node_CustomEvent_98`, `EG:28696-28698`) → `EG:28704-28709` `ParseIntoArray` (`CallFunction_3047`) séparateur de lignes (retour à la ligne, voir § 4), `CullEmptyStrings = 'true'` (`EG:28708`) → `Lines_PopClothes4` (`EG:28710`) → boucle `MacroInstance_71` (`EG:28716-28722`) → `EG:28743-28748` `CallFunction_1061` séparateur `': '`, `CullEmptyStrings = 'true'` (`EG:28747`) → `GetArrayItem_62..65` index 0, 1, 2, 3 (`EG:28749-28751`, `28764-28766`, `28773-28775`, `28793-28795`). Index 0 sert de nom de maillage (`'/Game/Heavy/Clothes4/'` + nom, `EG:28753-28756`), index 1 est comparé à `'true'` (`EG:28768-28772`), index 2 est découpé sur `', '` (`EG:28777-28782`), index 3 est découpé sur `', '` puis testé contre `'sports'` et `'formal'` (`EG:28783-28802`). Aucun autre fichier n'est lu par ce nœud (Grep `Clothes4` sur `EG` : 5 lignes, toutes dans ce bloc).
Fichier : `MOD\Clothes4.txt`, 39931 octets, sans BOM, 956 CRLF = 956 LF = 956 CR (aucun CR ou LF isolé), 957 lignes physiques (la dernière sans fin de ligne), 0 ligne vide (script : 957 lignes après CullEmpty = 957 physiques). Copie du build U8 essai identique (md5 `4c14ef29e24e40417290ee0bdf801ab0` des deux).
Répartition par nombre de champs (script, modèles A et B identiques) : `{3 champs : 570, 4 champs : 387}`, total 957. Recompte Grep : 3 champs = 570, 4 champs ou plus = 387, lignes = 957 (570 + 387 = 957).
Journal : `LOG` contient 570 avertissements `index 3 ... _3 of length 3!`, tous de longueur 3 (570 avec « length 3 », 570 avec « index 3 »), en une seule rafale continue `LOG:1021-6150` (570 × 9 lignes = 5130 ; 1021 + 5130 = 6151), horodatée 16:43:06.252 à 16:43:06.290, pile `Person_C:ReceiveBeginPlay → ExecuteUbergraph_Person → GI_C:populateClothes4 → ExecuteUbergraph_GI` (`LOG:1021-1028`). Aucun avertissement K1 aux 12 `Person BeginPlay` suivants (`LOG:6212-6234`, 16:43:17).
**Lignes fautives K1 : 570 = 570 lignes à 3 champs × 1 passage = 570 avertissements. Égalité exacte.**
Liste exhaustive `MOD\Clothes4.txt:<ligne>` (numéros de ligne physique, 93 plages ; le contenu de chacune des 570 lignes est dans `SP\k1_bad_Clothes4.tsv`, colonnes fichier, ligne, nombre de champs, contenu tronqué à 120 caractères) :
3 ; 8-9 ; 12 ; 15-16 ; 18-21 ; 27 ; 30-34 ; 36-44 ; 58 ; 60 ; 64-68 ; 70-72 ; 74 ; 77-78 ; 81 ; 83-87 ; 89-95 ; 97-100 ; 103 ; 106-108 ; 110-114 ; 122-123 ; 127-133 ; 135-142 ; 144-145 ; 147-151 ; 153-156 ; 162-167 ; 169-171 ; 173-177 ; 183 ; 192 ; 194-196 ; 203-205 ; 209-215 ; 217-218 ; 222-223 ; 225-228 ; 237 ; 239-246 ; 248-253 ; 258-261 ; 263 ; 284 ; 287 ; 292-296 ; 304 ; 306-317 ; 323-332 ; 417 ; 442-445 ; 448-449 ; 453-473 ; 475 ; 477 ; 479-483 ; 485-486 ; 488 ; 491-493 ; 496-506 ; 508 ; 510-515 ; 517 ; 520-521 ; 523 ; 525 ; 527-529 ; 531-534 ; 549 ; 552-559 ; 561-563 ; 565-567 ; 576-577 ; 579 ; 585 ; 589-597 ; 599-611 ; 613-620 ; 622-630 ; 632-644 ; 650-656 ; 659-670 ; 672-697 ; 703-726 ; 730-733 ; 736-741 ; 743-767 ; 771-775 ; 780-781 ; 786-788 ; 792-890 ; 897-900 ; 926-957.
Exemples (premières lignes fautives, contenu exact) : `3: London-Look-Vest_1_F: false: Top` ; `8: Cutout-Shoulder-Shirt_1_F: false: Top` ; `9: Ruffle-Skirt_1_F: false: Bottom` ; `12: Summer-Dress_1_F: false: Top, Bottom` ; `15: Brynn-Pants_1_F: false: Bottom` ; `16: Floral-Fiesta-Panty_1_F: false: Bottom_Under`. Toutes ont la forme `<nom>: <true|false>: <types>` ; la dernière ligne du fichier (957) est fautive.
Structure des 570 : champ 2 = `false` pour 380, `true` pour 190 ; champ 3 (types) : une seule valeur pour 527, deux ou plus (`, `) pour 43 ; 37 valeurs distinctes de types (Top 133, Bottom 112, Foot 50, Outerwear 40, Neck 37, Wrist 32, `Top, Bottom` 31, ...). Aucune ligne à 1 ou 2 champs.
Le 4e champ est donc un champ facultatif : les 387 lignes qui le portent donnent 20 jetons distincts (ParUn 163, Sports 93, Uniform 48, Formal 40, Heels 37, 0.8 29, Home 27, Ethnic 21, Asian 13, ...) ; aucun jeton neutre du type « aucun ».
### 2.2 K2 — PopulateEachMorphTags, fichiers lus : `Modules/MorphTags/<Filename>.txt`
Preuve dump (établi) : événement `K2Node_CustomEvent_91`, paramètre `Filename` (`EG:28138-28141`) → `CallFunction_1031` `LoadTxt`, `FileNameA` = concaténation `'Modules/MorphTags/'` + `Filename` + `'.txt'` (`EG:28142-28146`, `28153-28158`) → `CallFunction_1032` `ParseIntoArray` en lignes, `CullEmptyStrings = 'true'` (`EG:28147-28152`) → `Lines_PopEaMorTag` (`EG:28159-28164`) → `CallFunction_1011` `StartsWith(Filename, 'true', IgnoreCase)` (`EG:28172-28177`) → `IfThenElse_202` (`EG:28178-28182`). Branche vraie : `MacroInstance_65` (`EG:28165-28171`) → `CallFunction_1016` `': '`, CullEmpty `true` (`EG:28183-28188`) → `GetArrayItem_57` index 0 (`EG:28189-28192`) et `GetArrayItem_58` index 1 (`EG:28193-28196`) → `Map_Add(MorphTags_true)` (`EG:28200-28206`). Branche fausse : `MacroInstance_64` (`EG:28207-28213`) → `CallFunction_1012` `': '`, CullEmpty `true` (`EG:28214-28219`) → `GetArrayItem_55` index 0 / `GetArrayItem_56` index 1 (`EG:28220-28227`) → `Map_Add(MorphTags_false)` (`EG:28231-28237`).
Appelant : `K2Node_CustomEvent_93` (`EG:28265-28267`) vide les tables puis boucle `MorphTagFiles` (`MacroInstance_66`, `EG:28268-28277`) et appelle `PopulateEachMorphTags(Filename)` (`CallFunction_1022`, `EG:28278-28282`).
Liste des fichiers : le dump ne contient pas le contenu de la variable `MorphTagFiles` (valeur par défaut). Recherche d'octets dans `Content\BPs\GI.uasset` : tableau de 6 chaînes consécutives `falseBodies, falseFaces, falseSexies, trueBodies, trueFaces, trueSexies` à l'offset 28280219 (`SP\uasset2.py`). Rattachement à `MorphTagFiles` : **estimé** (voir § 4) ; il est confirmé par les comptes ci-dessous.
Fichiers `MOD\MorphTags\` (9 fichiers, tous sans BOM, CRLF = LF, aucun CR isolé) :
| Fichier | Lu par la boucle | Lignes physiques | Lignes vides physiques | Champs (modèle B) | Lignes à 1 champ |
|---|---|---|---|---|---|
| falseBodies.txt | oui | 28 | aucune | {1 : 12, 2 : 16} | 12 |
| falseFaces.txt | oui | 264 | aucune | {2 : 264} | 0 |
| falseSexies.txt | oui | 29 | 29 | {1 : 28} | 28 |
| trueBodies.txt | oui | 22 | 21, 22 | {1 : 12, 2 : 8} (20 lignes) | 12 |
| trueFaces.txt | oui | 140 | aucune | {2 : 140} | 0 |
| trueSexies.txt | oui | 8 | aucune | {1 : 8} | 8 |
| AllMorphTags.txt, allClothingMorphs.txt, trueTopSimplify.txt | non (hors liste) | 17, 59, 1070 | 11, 12, 17 ; aucune ; aucune | 1 champ partout | sans objet (non lus par ce chemin) |
Recompte Grep (`^[^:\r\n](?:[^:]|:[^ ])*$`, count) : falseSexies 28, trueSexies 8, trueBodies 12, falseBodies 12, falseFaces et trueFaces absents (0). Égal au script.
Journal : `LOG` contient 60 avertissements K2, tous « index 1 ... of length 1 » : 40 sur `_29` (`LOG:6243-6906`, 17 lignes chacun, 6243 + 39 × 17 = 6906) puis 20 sur `_28` (`LOG:6923-7246`), contigus, horodatés 16:43:17.377 à 16:43:17.384, pile `LoadSettings → PopulateRaws → PopulateAllMorphTags → PopulateEachMorphTags` (`LOG:6247-6258`). `GI_C:PopulateAllMorphTags$` = 60 occurrences (une par avertissement), soit une seule exécution de `PopulateAllMorphTags`.
Rapprochement : fichiers « false » lus en premier dans l'ordre de la liste : falseBodies 12 + falseSexies 28 = **40** ; fichiers « true » : trueBodies 12 + trueSexies 8 = **20** ; 40 puis 20 = ordre du journal, 1 passage. Total 60 = 60.
**Lignes fautives K2 (60), `MOD\MorphTags\<fichier>:<ligne>:<contenu>`, toutes un nom de morph sans `': '` (donc 1 champ)** :
- falseBodies.txt (12) : 5 `FBMEmaciated` ; 6 `FBMThin` ; 8 `FBMStephanie8` ; 19 `FBMVoluptuous` ; 20 `CTRLFitness` ; 21 `FBMFitnessSize` ; 23 `CTRLBodybuilder` ; 24 `FBMBodybuilderSize` ; 25 `FBMPearFigure` ; 26 `FBMBodySize` ; 27 `FBMHeavy` ; 28 `CTRLWeight`.
- trueBodies.txt (12) : 1 `CTRLFitness` ; 2 `FBMFitnessSize` ; 10 `CTRLBodybuilder` ; 11 `FBMBodybuilderSize` ; 13 `FBMLithe` ; 14 `FBMThin` ; 15 `FBMEmaciated` ; 16 `FBMStocky` ; 17 `FBMPortly` ; 18 `FBMBodySize` ; 19 `FBMHeavy` ; 20 `CTRLWeight`.
- falseSexies.txt (28) : 1 `PBMBreastsShape08` ; 2 `PBMBreastsShape07` ; 3 `PBMBreastsShape06` ; 4 `PBMBreastsShape05` ; 5 `PBMBreastsShape04` ; 6 `PBMBreastsShape03` ; 7 `PBMBreastsShape02` ; 8 `PBMBreastsShape01` ; 9 `PBMBreastsPerkSide` ; 10 `PBMBreastsHeavy` ; 11 `PBMBreastsGone` ; 12 `PBMBreastsDiameter` ; 13 `CTRLBreastsNatural` ; 14 `CTRLBreastsImplants` ; 15 `PBMBreastsSize` ; 16 `PBMBreastsSmall` ; 17 `PBMBreastsUnderCurve` ; 18 `GrowingBreasts` ; 19 `sfd_tg_breastsizer` ; 20 `Aging Breast Sag` ; 21 `PBMNipplesSize` ; 22 `sfd_tg_nippsize` ; 23 `PBMNipplesLarge` ; 24 `PBMNipplesDiameter` ; 25 `PBMNipplesDepth` ; 26 `PBMAreolaePerk` ; 27 `PBMAreolaeDiameter` ; 28 `PBMAreolaeDepth`.
- trueSexies.txt (8) : 1 `Penis length` ; 2 `Penis size` ; 3 `Plums size` ; 4 `Plums high-low` ; 5 `Foreskin01` ; 6 `Foreskin02` ; 7 `Foreskin03` ; 8 `Foreskin04`.
Les lignes correctes ont la forme `<morph>: <tag>[, <tag>]` (`falseBodies.txt:1` `sfd_tg_tgbody05a: teen` ; `falseFaces.txt:2` `Ailene: white, square`).
Fins de ligne et BOM : aucun BOM dans les 9 fichiers ; les lignes vides (`falseSexies.txt:29`, `trueBodies.txt:21-22`) ne produisent aucun avertissement : elles sont éliminées par CullEmpty si le séparateur de lignes est `\r\n` (modèle B), ce que confirment les comptes (§ 4).
## 3. Écarts au compte attendu de la fiche
- K1 : attendu « 570 en 1 rafale ? » → 570 lignes à 3 champs × 1 passage = 570, 1 rafale. Pas d'écart. La « cause 3 champs estimée » du GIUBER devient établie : 570 lignes ont exactement 3 champs (index 3 hors bornes, longueur 3).
- K2 : attendu 60 → 60 = 40 + 20, égalité exacte avec 12 + 28 et 12 + 8. La « nature des lignes incertaine » devient établie pour les 60 : noms de morph sans `': '`, aucune ligne vide ni CR en cause. L'attribution `_28` / `_29` aux branches (incertaine dans le GIUBER) se tranche par les comptes et l'ordre : `_29` (40, premier) = branche fausse, `CallFunction_1012` / `GetArrayItem_56` ; `_28` (20, ensuite) = branche vraie, `CallFunction_1016` / `GetArrayItem_58` (estimé fort, voir § 4).
- Ce que la fiche ne prévoyait pas : (a) le 4e champ de `Clothes4.txt` est facultatif dans les données (387 lignes sur 957 le portent) ; le défaut est la lecture sans test de la longueur, pas une ligne corrompue ; (b) de même, les 60 lignes MorphTags sont des morphs volontairement sans étiquette.
- Écarts de méthode (à signaler selon `sk-protocol` § 7) : deux commandes shell de reconnaissance ont utilisé `head` / `grep` en tube (`ls ... | head -50`, `ls ... | grep -i`) ; elles ne servent qu'à lister des dossiers, aucun chiffre du livrable n'en dépend (tous recomptés par Grep). `git status --porcelain` de la copie 5.8 montre `M Source/LifePlay/LPStringCompat.cpp` et `M Source/LifePlay/LPStringCompat.h` (+5 lignes chacun : ajout de `ULPStringCompat::GetStringAtOrEmpty`) : modification qui n'est pas la mienne (j'ai ouvert ces fichiers en lecture seule ; l'état initial de la session était propre), probablement une autre session ; `ParseIntoArray` (lignes 5-27) est inchangé. Dépôt `MOD` : `git status --porcelain` = 0 ligne. Aucun fichier de données ou de projet modifié par cette fiche.
### Correction de données proposée (non appliquée)
Règle valable pour chaque ligne listée, car le défaut est le même partout :
- K1 (570 lignes de `Clothes4.txt`, liste § 2.1 et `SP\k1_bad_Clothes4.tsv`) : ajouter un 4e champ non vide `: <jeton>` en fin de ligne. Un 4e champ vide (`: ` final) ne marche pas : CullEmpty supprime le champ vide final (`LPStringCompat.cpp:15, 21`), la ligne resterait à 3 champs. Aucun jeton neutre n'existe dans les données (20 jetons, tous porteurs de sens) : le choix du jeton inerte (il serait ajouté au tableau d'étiquettes du vêtement et lu ailleurs) est une décision de conception. Ligne 957 (dernière, sans fin de ligne) : ajouter le jeton sans casser l'absence de fin de ligne.
- K2 (60 lignes, liste § 2.2) : ajouter `: <étiquette>` en choisissant dans le vocabulaire existant (`AllMorphTags.txt` : white, asian, latin, arab, indian, black, feminine, teen, old, fantasy, round, oval, square, oblong ; autres valeurs des lignes correctes : ethnic, ...). Chaque ligne exige un choix de sens (que représente un morph de poids ou de taille sans étiquette ?) que je ne peux pas établir.
- Avis de l'inventaire (estimé, décision à l'orchestrateur) : modifier 630 lignes de données du dépôt local `Content/Modules` (non poussé, joueurs et mods ayant leurs propres fichiers au même format) est plus lourd et moins sûr que la garde côté Blueprint (`Length > 3` / `Length >= 2`, ou lecture par `GetStringAtOrEmpty`, déjà en cours de rédaction dans le jeu 5.8) ; les mods tiers au même format continueraient de déclencher les avertissements. C'est la question Q1 du GIUBER.
## 4. Établi / estimé / incertain
**Établi** (source) :
- Fichier lu par K1 = `Modules/Clothes4.txt` (`EG:28701`) ; fichiers lus par K2 = `Modules/MorphTags/<Filename>.txt` (`EG:28155-28158`), branche selon `StartsWith(Filename, 'true')` (`EG:28172-28177`). CullEmpty est vrai pour les trois niveaux de découpe de chaque chaîne (`EG:28151, 28187, 28218, 28708, 28747`).
- 570 lignes de `Clothes4.txt` ont exactement 3 champs (script `k1.py`, Grep regex, 570 / 387 / 957) ; `LOG` 570 avertissements `index 3 ... length 3`, 1 rafale (`LOG:1021-6150`).
- 60 lignes de 4 fichiers `MorphTags` n'ont pas de `': '` (script `k2.py` ; Grep 28 + 8 + 12 + 12 = 60 ; numéros de ligne revérifiés en mode content sur `trueBodies.txt` et `falseBodies.txt`) ; `LOG` 60 avertissements, 1 exécution de `PopulateAllMorphTags`.
- Aucun BOM, aucun CR ou LF isolé dans `Clothes4.txt` ni dans les 9 fichiers `MorphTags` ; `Clothes4.txt` sans ligne vide ; la copie du build U8 essai est identique pour `Clothes4.txt` (md5).
- Bornes : `Attempted to access index N from array ... of length L` est l'effet de `GetArrayItem` (DIAG 0.6), pas d'un autre nœud.
**Estimé** (raisonnement) :
- Séparateur de lignes de `CallFunction_1032` / `3047` = `\r\n` (modèle B), non lisible directement dans le dump (le texte du séparateur contient un saut de ligne et le dump coupe la ligne : `EG:28150`, `28707` finissent par `'\r`). Raison : le modèle B donne 20 + 40 = 60 ; le modèle A (`\n`, CR en fin de ligne conservé) donnerait 21 + 40 (la ligne `trueBodies.txt:21` serait un `\r` non vide) = 61, contraire au journal. Pour K1, A et B donnent le même résultat (aucune ligne vide).
- `_29` = branche fausse (40), `_28` = branche vraie (20) : seule l'attribution cohérente avec les comptes par fichier et avec l'ordre dans `LOG`.
- La liste de `MorphTagFiles` = les 6 noms trouvés à l'offset 28280219 de `GI.uasset` : appuyé par l'égalité exacte des comptes (12 + 28, 12 + 8, 0 pour les deux fichiers Faces), non par la lecture de la propriété elle-même. Les trois autres fichiers du dossier (AllMorphTags, allClothingMorphs, trueTopSimplify) ne passent pas par ce chemin.
- `populateClothes4` = `K2Node_CustomEvent_98` : le nom d'événement n'est pas dans le dump (DIAG 0.7) ; rattachement par la pile du journal et par `'/Game/Heavy/Clothes4/'` et `Lines_PopClothes4`.
- Une seule exécution de `populateClothes4` dans cette session : un seul bloc contigu de 570 ; la raison pour laquelle les `Person BeginPlay` suivants ne la relancent pas n'est pas établie.
- UE4 lisait un index hors bornes sans avertissement et renvoyait la valeur par défaut (chaîne vide) : raisonnement du DIAG, non rejoué ici ; il explique pourquoi les données « tolérantes » n'avaient jamais été signalées.
**Incertain** (essai qui trancherait) :
- Valeur réelle du séparateur de lignes : lecture du champ `Delimiter` de `CallFunction_1032` / `3047` dans l'éditeur (ou dump corrigé, voir Q2 du DIAG qui demande l'impression des noms d'événements) ; les comptes ci-dessus le contraignent déjà.
- Valeur par défaut exacte de `MorphTagFiles` : dump de `GI` CDO (`LPDumpCDO` avec `Props=MorphTagFiles`), commandlet exclu par la fiche.
- Mods ou sauvegardes : seuls les modules de base `Content\Modules\` ont été lus ; aucun `Mods\` ni autre dossier de modules (fiche : copie 5.8 uniquement).
- Les 12 lignes de `Clothes4.txt` avec espaces en fin (lignes 62, 193, 225, 295, 369, 437, 623, 711, 731, 746, 835, 855) portent des jetons `Sports `, `ParUn `, `Asian ` avec espace final ; hors sujet des avertissements, mais le test `Array_Contains 'sports'` (`EG:28783-28787`) peut les manquer : à confirmer avant toute correction de données.
## Constats
- Les 630 lignes (570 + 60) ne sont pas des erreurs de saisie : ce sont des lignes à champ final facultatif. Le défaut est la lecture sans test de longueur.
- Aucun fichier du dépôt `Content\Modules` n'a été modifié ; aucun commit ; aucun UE ni commandlet lancé.
- Fichiers de travail (hors dépôt, volatils) : `SP\analyse.py`, `k1.py`, `k1b.py`, `k2.py`, `dumpbytes.py`, `uasset.py`, `uasset2.py`, `k1_bad_Clothes4.tsv` (570 lignes), `k2_bad_<fichier>.txt`.