10 KiB
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, MD5E281ACE2…).
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
SexOnest 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.LineTraceSingleByChannelconst ;GetBoneLocationconst. 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é avantGetBoneName(0)(l. 527). PASS-STATIC. - Trace : le
Queryignore tous lesPerson_C(l. 370, 375) ;bTraceComplexvrai (l. 374). - Shadowing. Réglage :
Source/LifePlay.Target.cs:11etLifePlayEditor.Target.cs:11BuildSettingsVersion.V7;CppCompileWarnings.cs:90-93du moteur : shadow = Error pour V2 et plus (cible), /we4456 /we4458 /we4459.LifePlay.Build.csne le modifie pas (grepShadow|Warningsans 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,Singlel. 407,GIState,Scene,Keys,Player…) vivent dans des portées déjà fermées (boucle l. 378-419, bloc l. 421-491,ifl. 350-361) : pas de masquage, niPerson(boucle précédente close), niSingle(l. 407 dans uniffermé). Aucun des 16 noms ne masque un autre dans le bloc (Boneboucle,BoneNamecorps 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
- É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. - 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). - R3 : l'ordre des inclusions n'a pas été compilé ;
UAnimationAssetest supposé fourni parAnimSingleNodeInstance.h(estimé, non établi par compilation). - Non mesuré : compilation (P4), comportement en jeu, valeur des Z.
LPTestStringCompat,Build.ps1 -FromLoget 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
constsurSingle) 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