LifePlay-Revival/Docs/Migration/etat/ST/STB/STB-VAL.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

113 lines
30 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-VAL — Niveau N1 — Modèle prévu sonnet (modèle de l'agent lp-validator) | utilisé claude-sonnet-5-5 — Agent lp-validator — Skills lp-validate, lp-build
# STB-VAL : validation statique et rejouée du lot STB (corrections Blueprint et C++ après G-ST) (2026-10-09)
Copie `D:\Game\LifePlay-master 5.8`, branche `ue5.8`. Base de comparaison : `9f59fa6` (STB-T0, dernier commit avant les corrections ; aucun tag `STB-avant` n'existe, `git tag` relu). Fin des commandes : 21:56. [sk-protocol] skills présents : sk-protocol, sk-recount, debug-verification, lp-validate.
Observation de contexte (établi, `git log`) : pendant la validation, HEAD est passé de `7049121` à `12d86d2` (deux commits `EDIT3` d'une autre session : `fe0cdd8`, `12d86d2`, trois fichiers Docs/Migration, aucun fichier Content, Source ou Config : `git diff 7049121 HEAD --stat`). Le diff STB lu est donc `9f59fa6..7049121`.
## 1. Fiches amont relues
- `Docs/Migration/Journal_Modifications.md` lignes 1134-1145 (CHG-292 à CHG-281), lues en entier : elles tiennent lieu de fiches IMPL (STB-TACHES.md : « fiche IMPL non écrite : le CHG en tient lieu » pour GIA ; PEA, PEB, MEN, SMS, ROO, GIC, SEX, MAP sans fiche IMPL non plus). Aucun livrable IMPL au gabarit n'existe pour le lot : section 5 du gabarit IMPL absente partout, remplacée par les mentions « à confirmer / preuve en jeu » du journal (voir § 2).
- `etat\ST\STB\STB-TACHES.md` (relu : aucun point amont à reprendre pour STB-VAL).
- `etat\ST\STB\STB-T0-BUILD.md`, `STB-GIB-BUILD.md` (code 0, `LPTestStringCompat` 3120 / 0 / 60, l.59-65), `STB-GIB-DATA-INV.md`, `STB-MAP-BUILD.md` (relu en entier : code 0, MSVC 14.50.35717, 2 unités, 0 erreur, 0 avertissement compilateur). `STB-T0-BUILD.md` et `STB-GIB-DATA-INV.md` : présence confirmée, contenu non relu ligne à ligne (hors périmètre des critères de la fiche).
- Dumps de référence d'avant lot : `etat\ST\STA\dumps\` (comptes de nœuds relus par Grep sur la ligne `=== … (n noeuds) ===`).
- Écart de gabarit amont (à signaler, sans bloquer) : les fiches BUILD STB-MAP, STB-GIB suivent le gabarit BUILD (sections 1 à 7). Aucune fiche IMPL, donc aucune section « Points à confirmer en VAL » à reprendre ; voir § 2 pour ce que les CHG demandent.
## 2. Points à confirmer des IMPL (tirés des lignes CHG)
| Point (source) | Verdict | Preuve ou report |
|---|---|---|
| CHG-281 : « Preuve en jeu à faire (STB-JEU : `array Floats_3` → résidu R02 seulement) » | reporté STB-JEU | Effet à l'exécution ; non vérifiable sans jeu (interdit fiche § 6). La présence des 2 appels est PASS (§ 3, tableau). |
| CHG-281 : appels dans les événements `LoadSettings` et `PopulateRaws` (ordre : après `loadAverageAttractiveness`, avant `SetSquirtMult` ; après `PopulateBeautyStandardsDefault`, avant `FillPregnancyMorphs`) | PASS-STATIC | Chaînes d'exécution lues dans `dumps/GI__EventGraph.txt:28727-28730`, `30052-30059`, `27975-27977`, `28577-28580`, `17263-17265`. L'appartenance des nœuds aux événements nommés (`CustomEvent_3270` l.8645, `CustomEvent_642` l.1723) n'a pas été suivie nœud par nœud : estimé (chaîne cohérente). |
| CHG-286 : `OnInitialized` avant l'évaluation des liaisons (`SynchronizeProperties` avant `Construct`) | PASS-STATIC pour le câblage, reporté STB-JEU pour l'ordre d'exécution | Câblage : `dumps/MainMenu__EventGraph.txt:1875-1894`. L'ordre d'exécution moteur n'est pas rejoué. |
| CHG-287 : « Effet en jeu à confirmer en STB-JEU » | reporté STB-JEU | Donnée : `Content/Modules/Clothes4.txt` 39 919 octets (ls), 956 CRLF, 0 LF seul, 0 ligne finissant par espace (Grep ` +\r?$` : 0 résultat), `FileCheck` 0 alerte. Établi (cohérent avec CHG-287). |
| CHG-289 : risque voisin non traité (`len = 0`, aucun préréglage pour l'amenity) | reporté (non traité par conception, hors lot) | Aucune garde ajoutée ; `dumps/Room__pickPresetWorld.txt` : aucun test de `len` hors du chemin existant. |
| CHG-290 : conditionnels R06-R08, R10 « à trancher, D11 / E4 / E5 » | reporté (décision orchestrateur) | Non traités, annoncés comme tels. |
| CHG-292 : comportement des saccades (R29) après retrait du composant | reporté STB-JEU | Code lu et compilé (§ 3, § 4) ; effet de performance non mesuré. |
## 3. Critères rejoués (commande → résultat)
### 3.1 Compilation et test (preuve fraîche, cette session)
| Critère | Commande | Résultat | Verdict |
|---|---|---|---|
| Éditeur fermé avant | `.\Tools\UeState.ps1` | `processus=0 editeur=0 compilation=0 shaders=0 jeu=0`, code 0 (aussi avant les commandlets de dump et avant LPTestStringCompat) | PASS |
| Tous les Blueprints compilent | `.\Tools\RunCommandlet.ps1 -Lot STB-VAL -Commandlet CompileAllBlueprints -Args ''` | `code=0 duree=208s erreurs=0 avertissements=0`. Journal `Saved\Logs\portage\STB-VAL_CompileAllBlueprints_20261009-213128.log`, résumé `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\ST\STB\STB-VAL_CompileAllBlueprints_20261009-213128.txt` | PASS |
| Recompte du précédent | Grep `a réussi` (count) sur le journal : 418 ; Grep `Loading and Compiling` : 418 ; Grep `Error:\|Warning:\|Avertissement\|Erreur\|a échoué\|Fatal\|Ensure\|Assertion` : 0 | Référence la plus récente `etat\ST\STM\STM-T4c_CompileAllBlueprints_20261009-162345.txt` (code 0, 0 erreur, 0 avertissement, 228 s) : `a réussi` = 418 par le même Grep. Écart : 0, nouvelles erreurs : 0, connues : 0 | PASS |
| Blueprints modifiés compilés | Grep `compilation de (GI\|Person\|Room\|StreetMap_Static\|MainMenu\|SexInterface\|MapMarkers) a r` | 7 lignes sur 7 (l.1971 MapMarkers, 2010 GI, 2013 Person, 2017 Room, 2020 StreetMap_Static, 2799 MainMenu, 2802 SexInterface) | PASS |
| Sémantique des chaînes | `.\Tools\RunCommandlet.ps1 -Lot STB-VAL -Commandlet LPTestStringCompat -Args ''` | `code=0 duree=16s erreurs=0 avertissements=2` ; ligne `=== 3120 cas : compat != herite(UE4) : 0 ; moteur != herite(UE4) : 60 ===` (`etat\ST\STB\STB-VAL_LPTestStringCompat_20261009-214222.txt:9,92`). Les « 2 avertissements » sont cette ligne même (journalisée en `Warning`, vue deux fois : `LogLPTestStringCompat` et sa copie `LogInit`). Grep `Condition failed` dans le journal : 0 (les 20 de la culture française annoncés par la fiche § 5 ne figurent pas dans ce journal ; pas une régression) | PASS (3120 / 0 / 60 = attendu) |
| Recompte du build STB-MAP, sans recompiler | `.\Tools\Build.ps1 -Lot STB-VAL -FromLog '…\Saved\Logs\portage\STB-MAP_Build_20261009-212857.log'` | `code=-1 duree=0s erreurs=0 avertissements=0 autres=20 unites=2` (le code -1 est celui d'une relecture de journal : aucun code dans le journal ; `Result: Succeeded` l.51 et `Total execution time: 28.84 seconds` l.52 lus). Chaîne : MSVC `14.50.35717` (l.34). Unités : `[1/5] Compile LPMapMarkersGuardSubsystem.cpp`, `[2/5] Module.LifePlay.cpp`, 2 liens (l.41-45). Conforme au livrable BUILD (2 unités, 0 / 0 / 20 autres). Les 20 lignes : `Plugin 'HyperAIStudio' does not list plugin …`, préexistantes (BUILD § 4) | PASS |
| DLL à jour | `ls -l --time-style=full-iso` | `UnrealEditor-LifePlay.dll` 1 248 768 octets, 21:29:25, postérieure à `LPMapMarkersGuardSubsystem.cpp` (21:27:58) et à `LPStringCompat.*` (20:52) ; `LifePlayEditorTools.dll` 20:54:26 | PASS |
| Aucune modification du dépôt par la VAL | `git status --short` (vide avant et après toutes les commandes) | 0 ligne | PASS |
### 3.2 Gardes dans les graphes (dumps frais : `LPDumpFunction -BP=<BP> -Fn=<Fn> -Pins -Exec`, un à la fois)
Dumps produits (copies des résumés `RunCommandlet`, nommés `<BP>__<Fn>.txt`) dans `D:\Game\LifePlay-master 5.5\Docs\Migration\etat\ST\STB\dumps\` ; les lignes citées sont celles de la **première** copie du dump (la fin du fichier répète les mêmes lignes préfixées `LogInit: Display:`). Résumés d'origine : `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\ST\STB\STB-VAL_LPDumpFunction_<horodatage>.txt` (horodatages : Consolidate 214306, clearVariable 214358, determinePersonVars 214454, clearScenePersons 214546, pickPresetWorld 214637, standIdle 214725, assignHome 214817, SearchByAmenitySafe 214908, findNearbyBuilding 214959, LoadSettings 215051, GI EventGraph 215151, Person EventGraph 215300, MainMenu 215405, StreetMap_Static EventGraph 215502, SexInterface 215600). Les 14 dumps utiles : code 0, 0 erreur ; `GI__LoadSettings` : code 1 attendu (voir Écart 1).
Comptes de nœuds (ligne `=== … ===`, dump frais contre STA) : clearVariable 30 → 32 (+2), clearScenePersons 50 → 56 (+6), determinePersonVars 112 → 114 (+2), standIdle 89 → 93 (+4), assignHome 78 → 82 (+4 : 5 créés, 1 supprimé), pickPresetWorld 34 → 37 (+3), SearchByAmenitySafe 47 → 50 (+3), MainMenu EventGraph 394 → 398 (+4), StreetMap_Static EventGraph 1248 → 1252 (+4), SexInterface EventGraph 84 → 86 (+2), Person EventGraph 3677 → 3684 (+7 : 12 créés dont 4 dans standIdle, 1 supprimé), GI EventGraph 6201 → 6216 (+15), ConsolidateBeautyStandards 16 → 16 (inchangé). Chaque différence égale le nombre de nœuds créés moins supprimés annoncé par les CHG. `findNearbyBuilding` : 63 nœuds, sans dump STA (pas de comparaison de compte).
| CHG | Nœuds attendus (journal) | Constaté dans le dump frais (liaisons d'exécution) | Verdict | Preuve (dump:ligne) |
|---|---|---|---|---|
| 281 | `CallFunction_391` (`ConsolidateBeautyStandards`) dans `LoadSettings` après `loadAverageAttractiveness`, avant `SetSquirtMult` ; `CallFunction_406` dans `PopulateRaws` après `PopulateBeautyStandardsDefault`, avant `FillPregnancyMorphs` | `CallFunction_1055 (loadAverageAttractiveness).then → CallFunction_391.execute` ; `391.then → VariableSet_353 (SquirtMult)` ; `CallFunction_1037 (PopulateBeautyStandardsDefault).then → CallFunction_406.execute` ; `406.then → CallFunction_41 (FillPregnancyMorphs)` ; `41.execute ← 406.then` | OK | `GI__EventGraph.txt:28727-28730`, `30052-30059`, `27975-27977`, `28577-28580`, `17263-17265` |
| 282 (clearVariable) | `IfThenElse_3` sur `IsValidIndex(Person, 0)` (`CallArrayFunction_0`) entre `GetVariable` et la suite ; tableau vide → fin | `CallFunction_0 (GetVariable).then → IfThenElse_3.execute` (avant lot : `→ IfThenElse_1`, STA `GI__clearVariable.txt:7`) ; `IfThenElse_3.Condition ← CallArrayFunction_0.ReturnValue` (`Array_IsValidIndex`, `TargetArray` = `Person`, `IndexToTest 0`) ; `then → IfThenElse_1.execute` ; `else` (vide) | OK | `GI__clearVariable.txt:126`, `271-280` |
| 282 (FocusOnMapMarkers) | `IfThenElse_205` sur `IsValidIndex(MapMarkers.WidgetComponents, 0)` (`CallArrayFunction_115`) : vrai → `SetInputModeGameAndUI` existant ; faux → nouveau `CallFunction_412` sans widget, même contrôleur et options | `CustomEvent_183 ('FocusOnMapMarkers').then → IfThenElse_205.execute` ; `Condition ← CallArrayFunction_115` (`WidgetComponents`, index 0) ; `then → CallFunction_967.execute` ; `else → CallFunction_412.execute` (`SetInputMode_GameAndUIEx`, `InWidgetToFocus` vide, `PlayerController ← PC`, `DoNotLock`, `bHideCursorDuringCapture true`, `bFlushInput false`). Seule lecture de `WidgetComponents` dans le graphe : `GetArrayItem_497` (l.13311), derrière la garde | OK | `GI__EventGraph.txt:13304-13306`, `30060-30078`, `13310-13314` |
| 283 (Blueprint) | `GetArrayItem_65` → `CallFunction_423` ; `GetArrayItem_56` et `_58` → `CallFunction_426` et `_429` (`GetStringAtOrEmpty`) | `423` (`Index 3`), `426` et `429` (`Index 1`) présents, `LPStringCompat::GetStringAtOrEmpty()` ; les 3 `GetArrayItem` supprimés : 0 occurrence en frais, 3 en STA (`GI__EventGraph.txt` STA) | OK | `GI__EventGraph.txt:30079-30093` |
| 283 (C++) | `GetStringAtOrEmpty(Array, Index)` : élément ou chaîne vide | `git diff 9f59fa6 7049121 -- Source/LifePlay/LPStringCompat.{h,cpp}` : fonction `BlueprintPure`, `Array.IsValidIndex(Index) ? Array[Index] : FString()` ; fins de ligne LF inchangées (`FileCheck` : 0 alerte) ; `LPTestStringCompat` 3120 / 0 / 60 | OK | diff (+5 / +5 lignes) |
| 284 (standIdle) | `IfThenElse_7` sur `IsValid(Near)` (`CallFunction_18`) entre `SetDest` et `SetNearVec` ; non valide → boucle `ForEachLoopWithBreak` ; `IfThenElse_8` sur `IsValidIndex(Room.Standspots_Occupied, Array Index)` (`CallArrayFunction_2`) entre le corps de boucle et la macro `IsValid` ; hors bornes → `Knot_1` | `VariableSet_3 (Dest).then → IfThenElse_7` ; `Condition ← CallFunction_18 (IsValid, Object = Near)` ; `then → VariableSet_6 (NearVec)` ; `else → MacroInstance_1 (ForEachLoopWithBreak).Exec` ; `MacroInstance_1.LoopBody → IfThenElse_8` ; `Condition ← CallArrayFunction_2` (`Standspots_Occupied`, `IndexToTest ← Array Index`) ; `then → MacroInstance_3 (IsValid).exec` ; `else → Knot_1 → VariableSet_4` ; `Knot_1` reçoit aussi `MacroInstance_3.Is Not Valid` et `IfThenElse_3.else` | OK | `Person__standIdle.txt:293-294`, `308-315`, `329-330`, `447-448`, `539-557` |
| 284 (EventGraph, Headtrack) | `SelectVector` pur (`CallFunction_998`) supprimé ; cascade avant `SetActorRotation` (`CallFunction_442`) : `IsValid(HeadtrackStatic)` → `HeadtrackAimLocation` ; sinon `IsValid(HeadtrackTarget)` → `HeadtrackAimLocation` ; sinon rotation sautée vers `VariableSet_230` ; variable `HeadtrackAimLocation` lue par `FindLookAtRotation` | `CallFunction_998` : 0 occurrence en frais, 1 en STA (`Person__EventGraph.txt:18986`) ; `IfThenElse_147 (CallFunction_999).then → VariableSet_231 (HeadtrackAimLocation ← CallFunction_1000).then → CallFunction_442` ; `else → IfThenElse_148 (CallFunction_420 = IsValid(HeadtrackTarget)).then → VariableSet_233 (← CallFunction_451).then → 442` ; `else → VariableSet_230` ; `VariableGet_72 (HeadtrackAimLocation) → CallFunction_438.Target` (l.13018) | OK | `Person__EventGraph.txt:19390-19418`, `13026-13030`, `13018` |
| 284 (OccupyingFnt) | `IfThenElse_149` sur `IsValid(OccupyingFnt)` avant `IfThenElse_75` ; faux → rien | `IfThenElse_149.Condition ← CallFunction_462 (IsValid, Object = OccupyingFnt)` ; `then → IfThenElse_75.execute` ; `else` (vide) | OK | `Person__EventGraph.txt:19419-19427` |
| 285 | `BooleanAND` (`Prefix == 'F'` ET `FamilyLiveWiths[SaveSlot]`) supprimé ; cascade `IfThenElse_4` (`Prefix == 'F'`) → `IfThenElse_10` (`IsValidIndex(FamilyLiveWiths, SaveSlot)`, `CallArrayFunction_0`) → `IfThenElse_1` ; chaque cas faux vers `IfThenElse_3` ; `IfThenElse_11` sur `IsValidIndex(Buildings, 0)` (`CallArrayFunction_5`) entre `SearchByAmenitySafe` et `Map_Add(AI_Homes)` | STA : `BooleanAND_2` (A = `CallFunction_5`, B = `GetArrayItem_0`) alimentait `IfThenElse_1` (`Person__assignHome.txt:93-97` STA) ; frais : `IfThenElse_1.Condition ← GetArrayItem_0.Output` directement ; `IfThenElse_4 (Condition ← CallFunction_5).then → IfThenElse_10.execute`, `else → IfThenElse_3` ; `IfThenElse_10 (Condition ← CallArrayFunction_0 : FamilyLiveWiths, IndexToTest ← SaveSlot).then → IfThenElse_1`, `else → IfThenElse_3` ; `IfThenElse_1.else → IfThenElse_3` ; `CallFunction_0 (SearchByAmenitySafe).then → IfThenElse_11.execute` ; `IfThenElse_11.Condition ← CallArrayFunction_5 (Buildings, IndexToTest 0)`, `then → CallFunction_16.execute`, `else` (vide). Le `BooleanAND_1` restant (`Prefix` et `CallFunction_3`) est celui de STA l.51 | OK | `Person__assignHome.txt:194-198`, `260-264`, `458-482`, `129-130`, `170-174` |
| 286 | `Event On Initialized` (`Event_0`) → `Cast To GI` (`DynamicCast_1`, objet `GetGameInstance`) → `Set GI` (`VariableSet_27`) ; `Event Construct` conserve son affectation | `Event_0 ('OnInitialized').then → DynamicCast_1.execute` ; `Object ← CallFunction_66 (GetGameInstance)` ; `DynamicCast_1.then → VariableSet_27 (GI ← AsGI)` ; `then` vide ; `Event_1 ('Construct').then → DynamicCast_0` conservé (affectation de `Construct` supposée inchangée : estimé) | OK (câblage) | `MainMenu__EventGraph.txt:1875-1894`, `121-123` |
| 288 (SearchByAmenitySafe) | `IsValid(CurrentCityExpansion)` `CallFunction_8` ; `IfThenElse_7` après `IfThenElse_5.then` : valide → `VariableSet_3`, sinon `IfThenElse_2` ; `IfThenElse_8` après `IfThenElse_5.else` : valide → `IfThenElse_6`, sinon `FunctionResult_0` | `IfThenElse_5.then → IfThenElse_7.execute`, `else → IfThenElse_8.execute` (l.272-273) ; `CallFunction_8` (`Object ← GI.CurrentCityExpansion`) alimente `IfThenElse_7` et `_8` ; `IfThenElse_7 : then → VariableSet_3, else → IfThenElse_2` ; `IfThenElse_8 : then → IfThenElse_6, else → FunctionResult_0` | OK | `StreetMap_Static__SearchByAmenitySafe.txt:269-273`, `294-296`, `318-331` |
| 288 (findNearbyBuilding) | `IsValid` `CallFunction_7` ; `IfThenElse_8` sur `IfThenElse_0.else` : valide → `VariableSet_2`, sinon `IfThenElse_4` | `IfThenElse_0.else → IfThenElse_8.execute` (l.152) ; `CallFunction_7 (Object ← CurrentCityExpansion).ReturnValue → IfThenElse_8.Condition` ; `then → VariableSet_2.execute` ; `else → IfThenElse_4.execute` ; `IfThenElse_4.execute ← IfThenElse_8.else` | OK | `StreetMap_Static__findNearbyBuilding.txt:148-153`, `285-289`, `385-393` |
| 288 (PlayBGA) | `CallFunction_144` `IsValid(BGA)` ; `IfThenElse_38` après `IfThenElse_22.then` : non valide → `SwitchString_3` ; `IfThenElse_39` après `IfThenElse_22.else` : valide → `Stop` `CallFunction_134`, sinon fin ; `IfThenElse_40` devant `Stop` `CallFunction_124` (entrées `SwitchString_3.Default` et `IfThenElse_21.then`) : non valide → `SpawnSound2D` `CallFunction_110` | `IfThenElse_22.then → IfThenElse_38`, `.else → IfThenElse_39` ; `IfThenElse_38 : then → IfThenElse_23, else → SwitchString_3.execute` ; `IfThenElse_39 : then → CallFunction_134, else` vide ; `IfThenElse_40.execute ← SwitchString_3.Default, IfThenElse_21.then ; then → CallFunction_124, else → CallFunction_110` ; `CallFunction_144 (Object ← BGA)` alimente 38, 39, 40 ; `Stop` 134 et 124 ciblent `BGA` | OK | `StreetMap_Static__EventGraph.txt:5540-5547`, `5562-5568`, `5580-5583`, `5600-5604`, `5620-5624`, `6080-6098` |
| 289 | `IfThenElse_1` sur `IsValidIndex(BuildingPoints, 1)` (`CallArrayFunction_0`) entre `VariableSet_1` (`len`) et `VariableSet_2` ; vrai → chemin existant ; faux → `VariableSet_0` = `Strings[0]` (`GetArrayItem_3`) → `PrintString` → `FunctionResult_0` | `VariableSet_1.then → IfThenElse_1.execute` ; `Condition ← CallArrayFunction_0` (`BreakStruct_0.BuildingPoints`, `IndexToTest 1`) ; `then → VariableSet_2.execute` ; `else → VariableSet_0.execute` ; `VariableSet_0.string ← GetArrayItem_3.Output` (STA : `GetArrayItem_3`, `Dimension 1 = 0`, tableau `Strings`) ; `VariableSet_0.then → CallFunction_10 (PrintString).execute` ; `PrintString.then → FunctionResult_0` | OK | `Room__pickPresetWorld.txt:128-130`, `191-193`, `206-210`, `278-292` |
| 290 (determinePersonVars) | `IfThenElse_7` sur `IsValid(currentMatchRace)` (`CallFunction_32`) entre l'entrée et `getRace` ; non valide → `VariableSet_27` (`Dice`), `getRace` et `getEthnicity` sautés | `FunctionEntry_0.then → IfThenElse_7.execute` ; `Condition ← CallFunction_32 (Object ← currentMatchRace)` ; `then → CallFunction_18 (getRace)` (→ `CallFunction_28 (getEthnicity)` → `VariableSet_27`) ; `else → VariableSet_27.execute` (`Dice ← RandomFloat`) | OK | `GI__determinePersonVars.txt:122`, `142-145`, `558-565`, `587-595` |
| 290 (clearScenePersons) | `CumOn(['Clear'])` `CallFunction_4` réduit à `PlayerCharacter` ; `IfThenElse_6` sur `IsValid(Companion)` → nouveau `CumOn` `CallFunction_6` ; `IfThenElse_7` sur `IsValid(Interacting)` → nouveau `CumOn` `CallFunction_15` ; avant `CallFunction_5` | `CallFunction_4 (self ← PlayerCharacter, Wheres = MakeArray ['Clear']).then → IfThenElse_6` ; `IfThenElse_6 (Condition ← CallFunction_16 : Object = Companion) : then → CallFunction_6 (self ← Companion), else → IfThenElse_7` ; `CallFunction_6.then → IfThenElse_7` ; `IfThenElse_7 (Condition ← CallFunction_17 : Object = Interacting) : then → CallFunction_15 (self ← Interacting), else → CallFunction_5 (secondScreen)` ; `CallFunction_15.then → CallFunction_5` ; le même `MakeArray_1` alimente les trois `CumOn` | OK | `GI__clearScenePersons.txt:268-269`, `311-317`, `340-367` |
| 290 (EventGraph, clearDaily) | `clearDaily` `CallFunction_864` réduit à `PlayerCharacter` ; `IfThenElse_206` sur `IsValid(Interacting)` (`CallFunction_432`) → nouveau `clearDaily` `CallFunction_435` ; les deux chemins vers `MacroInstance_53` | `864 (self ← PlayerCharacter).then → IfThenElse_206` ; `Condition ← CallFunction_432 (Object ← Interacting)` ; `then → CallFunction_435 (self ← Interacting)` ; `else → MacroInstance_53.exec` ; `435.then → MacroInstance_53.exec` | OK | `GI__EventGraph.txt:26309-26314`, `26343-26347`, `30094-30106` |
| 290 (PlayIdle partenaire) | `PlayIdle` `CallFunction_866` derrière `IfThenElse_207` (même `IsValid`) | `IfThenElse_207.execute ← CallFunction_865.then ; Condition ← CallFunction_432 ; then → CallFunction_866.execute ; else` vide ; `866 (self ← Interacting)` | OK | `GI__EventGraph.txt:26325-26330`, `30107-30111` |
| 290 (PlayDaily) | `PlayDaily` `CallFunction_863` réduit à `PlayerCharacter` ; `IfThenElse_208` sur `IsValid(Interacting)` (`CallFunction_438`) → nouveau `PlayDaily` `CallFunction_441` (même `Anim`) ; deux chemins vers `IfThenElse_511` | `863 (self ← PlayerCharacter, Anim ← BreakStruct_103).then → IfThenElse_208` ; `Condition ← CallFunction_438 (Object ← Interacting)` ; `then → CallFunction_441 (self ← Interacting, Anim ← BreakStruct_103 : même broche)` ; `else → IfThenElse_511` ; `441.then → IfThenElse_511` ; `IfThenElse_511.execute ← IfThenElse_208.else, CallFunction_441.then` | OK | `GI__EventGraph.txt:26304-26308`, `30112-30125`, `6642-6646` |
| 290 (PerTick) | `IfThenElse_209` sur l'`IsValid(Interacting)` existant (`CallFunction_952`) avant `VariableSet_339` ; non valide → nouveau `VariableSet_392` = `SelectInt(12, 3, nuit)` (`CallFunction_445`, condition `CallFunction_950`), sans lire `Interacting.Valid` | `IfThenElse_209 (Condition ← CallFunction_952) : then → VariableSet_339 (PerTick ← CallFunction_949), else → VariableSet_392` ; `392.PerTick ← CallFunction_445 (SelectInt A = 12, B = 3, bPickA ← CallFunction_950 = InRange(CurrentTime, 0.0, 5.0))` ; `392.then → MacroInstance_39` (comme `339`) ; `BooleanAND_91` (lecture de `Interacting.Valid`) n'alimente que `BooleanOR_89` du chemin « valide » | OK | `GI__EventGraph.txt:27392-27428`, `30126-30142` |
| 291 | `IfThenElse_2` sur `IsValidIndex(GI.SexPersons, Array Index)` (`CallArrayFunction_2`) entre `LoopBody` de la boucle (`MacroInstance_1`) et la macro `IsValid` (`MacroInstance_2`) ; hors bornes → `VariableSet_1` | `MacroInstance_1 (ForEachLoop).LoopBody → IfThenElse_2.execute` ; `Condition ← CallArrayFunction_2` (`TargetArray` = `SexPersons`, `IndexToTest ← Array Index`) ; `then → MacroInstance_2.exec` ; `else → VariableSet_1.execute` (`Person` vide) ; `MacroInstance_2.Is Not Valid → VariableSet_1` conservé | OK | `SexInterface__EventGraph.txt:354-374`, `545-554` |
| 292 | `LPMapMarkersGuardSubsystem.cpp` : création par `NewObject` du composant `LPFocusWidgetComponent` retirée (22 → 3 lignes en fin de `Guard`) ; `.h` : commentaire mis à jour ; garde conservée pour retrait des entrées détruites, reconstitution et remise à zéro de `Vector2Ds` | `git diff 9f59fa6 7049121` lu en entier : `-` 22 lignes (création du composant, `AddValue`, journal), `+` 2 lignes de commentaire ; fonction `Guard` relue l.80-129 : boucle de retrait l.89-96, `ClearArrayProp(Vector2Ds)` l.104, reconstitution l.106-125, plus de `NewObject` ; `bLoggedOnce` encore utilisé l.119-121 ; build code 0, 0 avertissement (recompté § 3.1) ; fins de ligne CRLF conservées (`FileCheck` : `.cpp` CRLF 129 / LF 0, `.h` CRLF 31 / LF 0 ; référence avant lot 149 et 30 CRLF par `git show`, sans LF seul) | OK | `Source/LifePlay/LPMapMarkersGuardSubsystem.cpp:80-129` |
Bilan du tableau : 12 CHG (281 à 292), 22 lignes de contrôle, 22 OK, 0 écart.
## 4. Diff lu en entier
- Base `9f59fa6`, arrivée `7049121` : `git diff --stat` = 11 fichiers, 27 insertions, 24 suppressions ; `git rev-list --count 9f59fa6..7049121` = 12 commits (les 12 annoncés par la fiche : `ba4335d`, `cac5b2d`, `959bd8b`, `fcdaf24`, `ee2821a`, `2aa6f64`, `8a61361`, `281207f`, `17bf1c7`, `cdecfcc`, `476effb`, `7049121`), `git log --name-only` relu commit par commit : aucun fichier non annoncé (8a61361 = journal seul).
- Fichiers : 6 `.uasset` (`GI`, `Person`, `Room`, `StreetMap_Static`, `MainMenu`, `SexInterface`) ; `Journal_Modifications.md` (+12 lignes = CHG-281 à CHG-292) ; `LPMapMarkersGuardSubsystem.cpp` (+2 / −22), `.h` (+3 / −2) ; `LPStringCompat.cpp` (+5), `.h` (+5).
- Lus en entier : les 4 fichiers C++ (diff texte), le journal (12 lignes). Les 6 `.uasset` sont binaires : relus **par dump de graphe** (§ 3.2), pas par diff texte.
- Fins de ligne : `.\Tools\FileCheck.ps1 -Path …` : `LPMapMarkersGuardSubsystem.cpp` CRLF (129, LF 0), `.h` CRLF (31, LF 0), `LPStringCompat.cpp` LF (68, CRLF 0), `.h` LF (61, CRLF 0), `Journal_Modifications.md` LF (1270, CRLF 0), `Clothes4.txt` CRLF (956, LF 0) : `fichiers=… alertes=0`, code 0. Aucun BOM.
- Garde de version : aucun `UE_VERSION_OLDER_THAN` ajouté par le diff. `.uproject` inchangé.
- Fichier modifié par script : aucun indice (diff C++ propre, nombres de lignes cohérents avec les CHG).
Inventaire de ce que la VAL a produit (aucune modification de code, d'asset, de doc validée ni de config ; `git status --short` vide avant et après) :
- Dossier créé : `D:\Game\LifePlay-master 5.5\Docs\Migration\etat\ST\STB\dumps\` (15 fichiers copiés des résumés `RunCommandlet` par `cp -n`, sans modification de contenu).
- Résumés et journaux produits par les commandes, dossiers ignorés par git : `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\ST\STB\STB-VAL_*.txt` (CompileAllBlueprints, LPTestStringCompat, 15 LPDumpFunction, BuildLog `STB-VAL_BuildLog_20261009-213151.txt`) ; `D:\Game\LifePlay-master 5.8\Saved\Logs\portage\STB-VAL_*.log`.
- Ce livrable : `D:\Game\LifePlay-master 5.5\Docs\Migration\etat\ST\STB\STB-VAL.md`.
- Éditeur et jeu non lancés ; aucun build ; aucun commit.
## 5. Verdict
**PASS** pour les critères de la fiche § 8 (verdict global **VALIDÉ**) :
- `CompileAllBlueprints` : code 0, 0 erreur, 0 avertissement, 418 / 418 compilations réussies, égal à la référence STM-T4c (aucune nouvelle, aucune connue).
- `LPTestStringCompat` : 3120 / 0 / 60, code 0.
- Les 12 CHG (281 à 292) : chaque garde annoncée constatée dans un dump frais (22 lignes OK sur 22).
Nuance de portée (à ne pas confondre avec une preuve d'exécution) : la présence et le câblage des gardes sont **établis** par dumps rejoués ; leur **effet en jeu** (rafale `Floats_3`, ordre `OnInitialized` / liaisons, saccades R29, effet des espaces finaux de `Clothes4.txt`) n'est pas validé ici : reporté à STB-JEU.
Écarts et observations (numérotés) :
1. `LPDumpFunction -BP=GI -Fn=LoadSettings` : code 1, `LogLPDump: Error: Fonction 'LoadSettings' introuvable dans GI. Relancer sans -Fn pour lister.` (`dumps/GI__LoadSettings_ECHEC-fonction-introuvable.txt:7`). Explication établie : `LoadSettings` est un événement personnalisé de l'EventGraph (`GI__EventGraph.txt:8645`), pas une fonction ; la fiche prévoyait « graphe contenant l'appel ». Remplacé par le dump de `GI EventGraph` (code 0). Arrêt non déclenché (code ≠ 0 expliqué). Rien n'a été contourné.
2. HEAD a avancé pendant la VAL (`7049121` → `12d86d2`, deux commits Docs `EDIT3`, voir en-tête) : aucun impact sur le code ni les assets validés ; la ligne CHG relue (1134-1145) est celle de l'arbre au moment des dumps.
3. Les dumps livrés sont les résumés bruts de `RunCommandlet` (en-tête, agrégat des lignes, sortie, puis seconde copie `LogInit: Display:` des mêmes lignes), non filtrés au format `LogLPDump: Warning:` seul des dumps STA ; les numéros de ligne cités visent la première copie.
4. Comparaison aux dumps STA : par **compte de nœuds** et par lecture ciblée des nœuds du CHG, pas par `diff` textuel complet des fichiers (les graphes de 6 216 et 3 684 nœuds ne se comparent pas utilement en texte à cause des numéros de nœud). `GI__ConsolidateBeautyStandards` : seul le compte (16 = 16) a été comparé.
5. `Build.ps1 -FromLog` renvoie `code=-1` (pas de code dans un journal relu) ; le code 0 vient du livrable BUILD et de `Result: Succeeded` (journal l.51), pas de la relecture elle-même.
6. Gabarit amont : aucune fiche IMPL au gabarit pour GIA, PEA, PEB, MEN, SMS, ROO, GIC, SEX, MAP (le CHG en tient lieu, STB-TACHES.md) ; `STB-T0-BUILD.md` et `STB-GIB-DATA-INV.md` : sections non vérifiées une à une.
7. Le journal de LPTestStringCompat ne contient aucune ligne `Condition failed` (la fiche § 5 en attendait 20 préexistantes en culture française) : constat neutre, pas une régression.
## 6. Points à confirmer par l'utilisateur
- [ ] STB-JEU : rafale `array Floats_3` disparue (CHG-281) et résidu R02 éventuel.
- [ ] STB-JEU : plus de lecture hors bornes et plus d'erreurs « Accès à None » aux endroits corrigés (CHG-282, 284, 285, 288, 289, 290, 291), comparés à `STA-T1`.
- [ ] STB-JEU : `MainMenu` affecte bien `GI` avant les liaisons de `SpinBox` (CHG-286, R13 / R14).
- [ ] STB-JEU : disparition des saccades R29 sans composant de focus créé par la garde (CHG-292) ; ouverture de la carte (`FocusOnMapMarkers`) sans crash ni perte de focus clavier.
- [ ] STB-JEU : effet du retrait des 12 espaces finaux de `Clothes4.txt` (CHG-287, fichier hors dépôt).
- [ ] Décision orchestrateur : R06-R08 et R10 (CHG-290) restent à trancher ; risque `len = 0` de `pickPresetWorld` (CHG-289) non traité.
- [ ] Décision orchestrateur : consigner dans lp-build § 7 les 20 lignes UBT `does not list plugin` comme connues (proposition de STB-MAP-BUILD § 4).
## Constats
- Durées des commandlets : CompileAllBlueprints 208 s (STM-T4c : 228 s), LPTestStringCompat 16 s, LPDumpFunction 47 à 66 s chacun (15 dumps, un à la fois).
- Pic et tours : non mesurés par cette fiche (voir `Tools/FicheStats.py` à la clôture du lot).