99 lines
10 KiB
Markdown
99 lines
10 KiB
Markdown
|
|
# STG-M1d-VAL : validation statique du bloc COUPLE de LPDebugSubsystem (2026-10-14)
|
||
|
|
|
||
|
|
Fiche STG-M1d-VAL — Niveau N1 — Modèle prévu lp-validator (sonnet) | utilisé claude-sonnet-5-5 — Agent lp-validator — Skills sk-protocol, sk-recount, debug-verification, lp-validate
|
||
|
|
|
||
|
|
Lot STG, copie `D:\Game\LifePlay-master 5.8`, branche ue5.8. Lecture seule sauf ce livrable. Pas de build, pas d'UE, rien lancé.
|
||
|
|
|
||
|
|
## 1. Fiches amont relues
|
||
|
|
|
||
|
|
- `Docs\Migration\etat\ST\STG\STG-M1d-IMPL.md` (IMPL, points à confirmer § 4).
|
||
|
|
- `Docs\Migration\etat\ST\STG\STG-C54-DIAG.md` § 5 (mesure M1d : os le plus bas, bassin, surface sous le bassin, animation et position dans le cycle) : le bloc répond à ce § 5.
|
||
|
|
- Instantané `D:\Game\LifePlay_Backup_5.5\STG-M1d\` (`manifest.csv` : `LPDebugSubsystem.cpp`, 29622 octets, MD5 `E281ACE2…`).
|
||
|
|
|
||
|
|
## 2. Points à confirmer de l'IMPL (§ 4)
|
||
|
|
|
||
|
|
| Id | Point | Résultat | Preuve |
|
||
|
|
|---|---|---|---|
|
||
|
|
| P1 | diff limité au bloc M1d | PASS-STATIC | § 3 et § 4 : 1 hunk, +50 / -0, bloc M1d seul |
|
||
|
|
| P2 | API UE 5.8 | **FAIL** (un appel non compilable) | `UAnimSingleNodeInstance::GetLength()` non const, voir écart 1 ; le reste PASS-STATIC (tableau § 5) |
|
||
|
|
| P3 | aucun effet de bord, lecture seule | PASS-STATIC | § 6 |
|
||
|
|
| P4 | compilation au build COMMUN-6 | reporté (non mesurable sans build) ; **annoncé en échec** par P2 | écart 1 |
|
||
|
|
|
||
|
|
## 3. Critères rejoués (commande, sortie brute)
|
||
|
|
|
||
|
|
MD5 (`certutil -hashfile … MD5`) :
|
||
|
|
```
|
||
|
|
LPDebugSubsystem.cpp : 31e2a3c5ff4a3feb5d9d5bf1c1b0afb0 (attendu 31E2A3C5FF4A3FEB5D9D5BF1C1B0AFB0 : conforme)
|
||
|
|
LPDebugSubsystem.h : 78d3a07957d81e0b39c5d9a81e5e03d3 (attendu 78D3A079… : conforme, inchangé)
|
||
|
|
```
|
||
|
|
Fins de ligne (`.\Tools\FileCheck.ps1 Source/LifePlay/LPDebugSubsystem.cpp,Source/LifePlay/LPDebugSubsystem.h`) :
|
||
|
|
```
|
||
|
|
CRLF 819 0 0 - 31E2A3C5FF4A3FEB5D9D5BF1C1B0AFB0 Source\LifePlay\LPDebugSubsystem.cpp
|
||
|
|
CRLF 53 0 0 - 78D3A07957D81E0B39C5D9A81E5E03D3 Source\LifePlay\LPDebugSubsystem.h
|
||
|
|
fichiers=2 CRLF=2 alertes=0 introuvables=0 exit=0
|
||
|
|
```
|
||
|
|
`git ls-files --eol` : `i/crlf w/crlf` pour le `.cpp`. CRLF homogène (LF seul = 0, CR seul = 0).
|
||
|
|
|
||
|
|
Diff instantané → actuel :
|
||
|
|
`git diff --no-index --numstat --ignore-cr-at-eol <instantané>\…\LPDebugSubsystem.cpp Source/LifePlay/LPDebugSubsystem.cpp` → `50 0` ; `-U0 … | grep -c '^@@'` → `1`.
|
||
|
|
|
||
|
|
## 4. Diff lu en entier
|
||
|
|
|
||
|
|
Un seul hunk, `@@ -492,0 +493,50 @@`, 50 lignes ajoutées (l. 493 à 541 du fichier actuel, dont la ligne vide finale), 0 supprimée : le bloc M1d, inséré entre la fin du bloc `GIState` (l. 491) et le commentaire « Paires de personnages visibles » (l. 543). Aucun autre changement. P1 : PASS-STATIC. (Le diff contre HEAD montre 318 lignes, ce sont les lots antérieurs non commités : hors périmètre.)
|
||
|
|
|
||
|
|
## 5. API UE 5.8 (en-têtes `D:\Game\Launcher\Engine\UE_5.8\Engine\Source\Runtime\Engine\`)
|
||
|
|
|
||
|
|
| Appel du bloc | Déclaration lue | Const sur l'objet utilisé | Verdict |
|
||
|
|
|---|---|---|---|
|
||
|
|
| `Body->GetNumBones()` (`const USkeletalMeshComponent*`) | `Classes/Components/SkinnedMeshComponent.h:1144` `int32 GetNumBones() const` | oui | OK |
|
||
|
|
| `Body->GetBoneName(int32)` | `SkinnedMeshComponent.h:1165` `FName GetBoneName(int32) const` | oui | OK |
|
||
|
|
| `Body->GetBoneIndex(FName)` | `SkinnedMeshComponent.h:1156` `int32 GetBoneIndex(FName) const` | oui | OK |
|
||
|
|
| `Body->GetBoneLocation(FName)` | `SkinnedMeshComponent.h:2014` `FVector GetBoneLocation(FName, EBoneSpaces::Type Space = EBoneSpaces::WorldSpace) const` | oui ; espace par défaut = monde | OK |
|
||
|
|
| `Body->GetSingleNodeInstance()` | `Classes/Components/SkeletalMeshComponent.h:1539` `UAnimSingleNodeInstance* GetSingleNodeInstance() const` | oui | OK (retourne un pointeur non const) |
|
||
|
|
| `Single->GetAnimationAsset()` | `Classes/Animation/AnimSingleNodeInstance.h:78` `virtual UAnimationAsset* GetAnimationAsset() const` | oui | OK |
|
||
|
|
| `Single->GetCurrentTime()` | `AnimSingleNodeInstance.h:114` `float GetCurrentTime() const` | oui | OK |
|
||
|
|
| **`Single->GetLength()`** | `AnimSingleNodeInstance.h:67` `ENGINE_API float GetLength();` (**non const** ; définition `Private/Animation/AnimSingleNodeInstance.cpp:425` `float UAnimSingleNodeInstance::GetLength()`) | **non** : `Single` est déclaré `const UAnimSingleNodeInstance*` (cpp l. 532) | **ERREUR** C2662 attendue |
|
||
|
|
| `Under.GetComponent()->GetReadableName()` | `Classes/Components/ActorComponent.h:1219` `virtual FString GetReadableName() const` (héritée par `UPrimitiveComponent`) | oui | OK |
|
||
|
|
| `Under.ImpactPoint.Z` | `Classes/Engine/HitResult.h:53` `FVector_NetQuantize ImpactPoint` | n/a | OK (double) |
|
||
|
|
| `World->LineTraceSingleByChannel(Under, …, ECC_Visibility, Query)` | `Classes/Engine/World.h:2161` `bool … const` | oui | OK ; `Query` est un `FCollisionQueryParams` (cpp l. 374) |
|
||
|
|
| `TNumericLimits<double>::Max()` | déjà utilisé l. 544 et 575 du même fichier, mêmes inclusions | n/a | OK |
|
||
|
|
| `ECollisionEnabled::NoCollision` | enum utilisé l. 416 (`ECollisionEnabled::Type`) | n/a | OK |
|
||
|
|
|
||
|
|
Visibilité : `World` (cpp l. 341), `Persons` (l. 363, `TArray<ACharacter*>`), `Query` (l. 374) sont déclarés au niveau fonction avant le bloc (l. 493) ; le bloc est dans la même fonction `WritePersonsDump`. `Persons` est parcouru en `const ACharacter*` : `IsHidden`, `GetCapsuleComponent`, `GetMesh` sont const. `UAnimSingleNodeInstance` : `Animation/AnimSingleNodeInstance.h` est inclus (l. 20) ; `UAnimationAsset` arrive par ce même en-tête.
|
||
|
|
|
||
|
|
Printf (cpp l. 534 à 538) : 12 spécificateurs (`%s %s %.2f %.2f %.1f %.1f %s %.1f %s %s %.1f %.1f`) pour 12 arguments : nom (`*FString`), `Playing ? *Playing->GetName() : TEXT("-")` (`const TCHAR*` des deux côtés), `GetCurrentTime()`/`0.0` (float/double promu en double, `%f` correct), `GetLength()`/`0.0` (idem), `Body->GetComponentLocation().Z` (double), `Lowest` (double), `*LowestBone.ToString()`, `Pelvis.Z`, `*PelvisBone.ToString()`, `*GetReadableName()` ou `TEXT("-")` (`const TCHAR*`), `ImpactPoint.Z` ou `0.0` (double), `Lowest - ImpactPoint.Z` ou `0.0` (double). Compte et types conformes. Le `*FString` temporaire d'un ternaire vit jusqu'à la fin de l'expression complète : même schéma déjà utilisé l. 397 et 399.
|
||
|
|
|
||
|
|
## 6. Logique
|
||
|
|
|
||
|
|
- Actif seulement si `SexOn` est vrai : `CoupleSexOn && GetPropertyValue_InContainer(CoupleGI)` (l. 497-498) ; propriété absente = bloc sauté. PASS-STATIC.
|
||
|
|
- Lecture seule : aucune affectation à un objet du jeu ; seules des variables locales et `Lines.Add`. `LineTraceSingleByChannel` const ; `GetBoneLocation` const. P3 PASS-STATIC.
|
||
|
|
- Personnes cachées ou capsule autre que `NoCollision` : `continue` (l. 504-507) ; pointeurs nuls testés (`Cap`, `Body`) avant usage ; `GetNumBones() == 0` écarté avant `GetBoneName(0)` (l. 527). PASS-STATIC.
|
||
|
|
- Trace : le `Query` ignore tous les `Person_C` (l. 370, 375) ; `bTraceComplex` vrai (l. 374).
|
||
|
|
- Shadowing. Réglage : `Source/LifePlay.Target.cs:11` et `LifePlayEditor.Target.cs:11` `BuildSettingsVersion.V7` ; `CppCompileWarnings.cs:90-93` du moteur : shadow = Error pour V2 et plus (cible), /we4456 /we4458 /we4459. `LifePlay.Build.cs` ne le modifie pas (grep `Shadow|Warning` sans résultat). Variables du bloc : `CoupleGI`, `CoupleSexOn`, `Person`, `Cap`, `Body`, `Lowest`, `LowestBone`, `Bone`, `BoneName`, `BoneZ`, `PelvisBone`, `Pelvis`, `Under`, `bUnder`, `Single`, `Playing`. Variables visibles de la fonction à cet endroit : `Reason`, `bFile` (paramètres), `World`, `Lines`, `Persons`, `Ignored`, `Query`. Les autres noms de la fonction (`GI`, `Room…`, `It`, `Loc`, `Capsule`, `Move`, `Mesh`, `Single` l. 407, `GIState`, `Scene`, `Keys`, `Player`…) vivent dans des portées déjà fermées (boucle l. 378-419, bloc l. 421-491, `if` l. 350-361) : pas de masquage, ni `Person` (boucle précédente close), ni `Single` (l. 407 dans un `if` fermé). Aucun des 16 noms ne masque un autre dans le bloc (`Bone` boucle, `BoneName` corps de boucle, distincts). Déclaration globale masquée (C4459) : les noms précédents de l'espace de noms anonyme (l. 44-48) ne sont pas repris ; non recherché dans le reste du module (réserve R2). Verdict : aucun masquage relevé ; le réglage (Error) rendrait un masquage bloquant, donc le contrôle compte.
|
||
|
|
|
||
|
|
## 7. Verdict
|
||
|
|
|
||
|
|
**FAIL** (statique). Une erreur de compilation établie par lecture des en-têtes : `Single->GetLength()` (cpp l. 535) appelé sur `const UAnimSingleNodeInstance*`, méthode non const. Message attendu : MSVC C2662 « impossible de convertir le pointeur 'this' de 'const UAnimSingleNodeInstance' en 'UAnimSingleNodeInstance &' ». Le reste du bloc est conforme (P1, P3, MD5, CRLF, printf, visibilité, shadowing).
|
||
|
|
|
||
|
|
Correctif pour l'IMPL (non appliqué, je ne corrige pas) : déclarer `Single` sans `const` (`UAnimSingleNodeInstance* Single = Body->GetSingleNodeInstance();`, la méthode retourne déjà un pointeur non const, l. 1539). `GetAnimationAsset`/`GetCurrentTime` restent appelables. Après correction : nouvelle VAL statique du MD5 et de la ligne, puis build COMMUN-6 (P4).
|
||
|
|
|
||
|
|
## 8. Écarts et réserves
|
||
|
|
|
||
|
|
1. **Écart 1 (bloquant)** : `GetLength()` non const sur pointeur const (ci-dessus). L'IMPL § 4 P2 ne le signalait pas ; le texte « GetLength » y figure sans mention de constness.
|
||
|
|
2. R2 : C4459 (global masqué) non exploré hors du fichier ; d'autres fichiers du module n'entrent pas dans ce `.cpp`, risque faible (noms de l'espace de noms anonyme seulement).
|
||
|
|
3. R3 : l'ordre des inclusions n'a pas été compilé ; `UAnimationAsset` est supposé fourni par `AnimSingleNodeInstance.h` (estimé, non établi par compilation).
|
||
|
|
4. Non mesuré : compilation (P4), comportement en jeu, valeur des Z. `LPTestStringCompat`, `Build.ps1 -FromLog` et G-U3 : sans objet (aucun build).
|
||
|
|
|
||
|
|
Aucun chemin `C:\Users` ni nom de compte dans ce livrable.
|
||
|
|
|
||
|
|
## 9. Points à confirmer par l'utilisateur
|
||
|
|
|
||
|
|
- [ ] Faire corriger l'IMPL (suppression du `const` sur `Single`) puis refaire une VAL statique.
|
||
|
|
- [ ] Build COMMUN-6 seulement après cette correction.
|
||
|
|
|
||
|
|
## 10. Fichiers à commiter
|
||
|
|
|
||
|
|
A : `Docs/Migration/etat/ST/STG/STG-M1d-VAL.md` (ce livrable). Aucun autre fichier modifié par moi (`LPDebugSubsystem.cpp` : à commiter par le gardien seulement après correction, build et nouvelle VAL).
|
||
|
|
|
||
|
|
Tours : 8 / 25
|