LifePlay-Revival/Docs/Migration/etat/ST/STG/STG-SF5m-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

14 KiB

Fiche STG-SF5m-VAL — Niveau N1 — Modèle prévu (agent lp-validator) | utilisé claude-sonnet-5-5 — Agent lp-validator — Skills sk-protocol, sk-recount, debug-verification, lp-validate

STG-SF5m-VAL : validation statique de S-F5m / S-F5n (relevage des personnes enfoncées contre un décor solide) (2026-10-14)

Copie D:\Game\LifePlay-master 5.8, branche ue5.8. Lecture seule, hors ce livrable. Pas de build, pas d'UE, jeu non lancé, aucune commande git qui écrit. Verdict : PASS-STATIC (rien compilé, rien exécuté en jeu), avec réserves R1 à R4 (§ 5).

1. Fiches amont relues

  • STG-SF5m-IMPL.md (en entier, 73 lignes), STG-SF5m.diff (en entier, 139 lignes), STG-COMMUN8-DIAG.md § A.3 et § A.4 (l. 34-78), STG-SF5k-VAL.md (l. 1-60 : références des API et gardes déjà relues). STG-SF5j-VAL.md : présent, non relu en entier (les gardes S-F5j sont relues ici directement dans le code, § 3 cmd 5).
  • Écart de forme (E1) : l'IMPL ne suit pas le gabarit IMPL (lp-doc/gabarits.md) : pas de section « Écarts à la SPEC », « Ce qui n'a pas été fait » est en § 3 et non en § 4, les points à confirmer sont en § 4 (le gabarit les met en § 5), « Fichiers à commiter » est en § 7 (avec M/A, sans le dépôt précisé). Les trois points à confirmer existent et sont repris au § 2.

2. Points à confirmer des IMPL

Id Point (IMPL § 4) Résultat
P1 Rue, arrivée au bord contre une façade : relevage en moins de 2 s ; journal releve de … puis ecarte de … (… S-F5m), ou une seule ligne « aucun point libre » reporté (COMMUN-9, essai en jeu). Statique : chemin de code et journal conformes (§ 3 cmd 3 et 4)
P2 Rue, arrivée ordinaire : relevage en place comme COMMUN-6, sans ligne S-F5m reporté (COMMUN-9). Statique : PASS-STATIC, TryPlace reproduit l'ancienne boucle et bMoved reste faux (§ 3 cmd 3)
P3 Plage ou forêt : rien de changé reporté (COMMUN-9). Statique : PASS-STATIC, LiftSunkPersons n'est appelée que sous if (bOutdoor) (LPOutdoorRoomSubsystem.cpp:175-182), aucun autre appelant
— Compilation BLOCKED-NONCOMPILE : à la charge du BUILD COMMUN-9

3. Critères rejoués (commande → résultat brut)

Cmd 1. MD5, instantané, fins de ligne, ASCII (md5sum, FileCheck.ps1 -Lot STG-SF5m -OnlyChanged, LC_ALL=C grep -c -P, git ls-files --eol).

9dcf0a35a1418bcb52e1a6a5b7d0f58f *LPOutdoorRoomSubsystem.cpp
60fce1de305f4133738193d82cd05f05 *LPOutdoorRoomSubsystem.h
90f9324be06a4eab10e105aa9d78f137 *…/STG-SF5m/Source/LifePlay/LPOutdoorRoomSubsystem.cpp
f9ed4d2df44af11163c0e3fbb3b4a4ca *…/STG-SF5m/Source/LifePlay/LPOutdoorRoomSubsystem.h
Fins CRLF  LF CR BOM MD5 ...                                   Alerte Fichier
LF      0 510  0 -   9DCF0A35A1418BCB52E1A6A5B7D0F58F  modifie   Source\LifePlay\LPOutdoorRoomSubsystem.cpp
LF      0  82  0 -   60FCE1DE305F4133738193D82CD05F05  modifie   Source\LifePlay\LPOutdoorRoomSubsystem.h
fichiers=2 LF=2 alertes=0 introuvables=0 ; exit 0
non-ASCII cpp:0 h:0 ; CR cpp:0 h:0 IMPL:0 ; 'C:.Users' dans l'IMPL : 0
i/lf    w/lf    attr/-text    Source/LifePlay/LPOutdoorRoomSubsystem.cpp

Les MD5 actuels égalent l'IMPL § 5 (9DCF0A35… / 60FCE1DE…) ; l'instantané égale 90F9324B… / F9ED4D2D… (IMPL § 1). Fichiers en LF, 0 CR, ASCII pur, aucune alerte FileCheck. IMPL en LF (0 CR), en-tête complet (modèle, agent, skills), sans C:\Users. (La commande FileCheck sur l'IMPL et le .diff comme arguments positionnels a échoué : paramètre inconnu ; l'IMPL a été contrôlé par grep à la place, le .diff n'est pas un fichier source.)

Cmd 2. Diff régénéré = STG-SF5m.diff (git diff --no-index --numstat ; puis lignes +/- hors en-têtes, empreinte).

80  5  …/STG-SF5m/Source/LifePlay/LPOutdoorRoomSubsystem.cpp => LPOutdoorRoomSubsystem.cpp
2   0  …/STG-SF5m/Source/LifePlay/LPOutdoorRoomSubsystem.h   => LPOutdoorRoomSubsystem.h
lignes +/- régénérées : 416c8126b17fe63f310d0ab5591af8eb
lignes +/- de STG-SF5m.diff : 416c8126b17fe63f310d0ab5591af8eb

Numstat conforme (80/5 et 2/0), lignes ajoutées/retirées identiques au .diff livré. Diff lu en entier : seuls hunks, .cpp (LiftSunkPersons uniquement : nettoyage de UnplacedLogged, retrait en fin d'épisode, lambda TryPlace, bloc S-F5m, journal, retrait au relevé) et .h (commentaire + membre UnplacedLogged) ; correspond exactement à l'IMPL § 2. Aucun ajout non demandé. Les 5 retraits sont : for (const FVector& Candidate…) d'origine, continue;, bPlaced = true; break; de l'ancienne boucle, et if (Near) (devenu else if (Near)).

Cmd 3. Équivalence de l'ancienne boucle (lecture …/STG-SF5m/…cpp:405-432 contre …cpp:414-444 actuel).

Élément Avant Après (TryPlace) Verdict
Start / End FloorTop + HalfHeight + LiftProbe / - 2.0 en (Candidate.X, Y) (lignes inchangées, hors hunk) idem, l. 418-419 identique
Remise de Hit, TargetZ par défaut Hit = FHitResult(); TargetZ = FloorTop + HalfHeight + 2.0 idem, l. 420-421 identique
Balayage SweepSingleByChannel(… Query, Responses) idem, l. 422 identique
bStartPenetrating continue (point suivant) return false (point suivant dans la boucle appelante) équivalent
Sol trouvé TargetZ = Hit.Location.Z + 1.0 idem, l. 432 identique
Sortie Target = FVector(X, Y, TargetZ); bPlaced = true; break; Target = …; return true; puis bPlaced = true; break; (l. 439-443) équivalent
Hit et Target après la boucle lus par la ligne « releve de » (Hit.GetComponent(), Target.Z) Hit, Target capturés par référence ; Hit est remis à zéro à chaque appel, donc après un succès il décrit le dernier balayage, comme avant identique
Ordre des points d'origine inchangé : S-F5k (Candidates : ±50 cm si Near) puis Location en dernier (l. 396-407). InPlace n'est écrit que si Candidate.Equals(Location) ; Location est toujours ajouté à Candidates (l. 407), donc InPlace est toujours renseigné quand le point sur place échoue (il n'échoue que par bStartPenetrating). Quand un point d'origine aboutit : même Target, même relevage, mêmes lignes de journal, bMoved faux ; seul changement : UnplacedLogged.Remove(Person) (l. 493, sans effet si absent). Aucun changement de comportement hors cas « tous les points d'origine en recouvrement » (avant : personne sautée sans ligne ; maintenant : S-F5m).

Cmd 4. S-F5m / S-F5n (lecture LPOutdoorRoomSubsystem.cpp:449-508).

Exigence Constat Verdict
S-F5n en premier, seulement après échec des origines if (!bPlaced) l. 450 ; premier ajout Escapes l. 455-458 PASS-STATIC
Normale horizontale, profondeur + 2 Push = InPlace.Normal; Push.Z = 0.0, condition InPlace.bStartPenetrating && Push.SizeSquared() > 0.01, point Location + Push.GetSafeNormal() * (PenetrationDepth + 2.0) ; la garde écarte une normale verticale ou nulle (donc InPlace vide, bStartPenetrating faux) PASS-STATIC
Petit axe vers le centre, grand axe ±, petit axe opposé Long/Short choisis comme S-F5k (échelle Y ≥ X → grand axe = droite) ; Inward = signe de (Room - Location)·Short ; ordre Short*Inward, +Long, -Long, -Short*Inward (l. 468-471) = DIAG A.4 PASS-STATIC
Cinq points au plus, ordre respecté, une seule action boucle l. 472-480, break au premier succès ; un seul SetActorLocation (l. 494) ; TInlineAllocator<5> couvre 1 + 4 PASS-STATIC
Ligne « ecarte … S-F5m » contre « S-F5k » if (bMoved) S-F5m sinon else if (Near) S-F5k (l. 498-507) : une seule des deux ; la ligne « releve de » reste écrite avant PASS-STATIC
Ligne « aucun point libre » une fois par épisode Contains puis Add puis log (l. 484-490) ; retrait si relevé (l. 493), si Bottom >= FloorTop - SunkDepth (l. 361-365), si l'acteur est détruit (nettoyage l. 338-344, avant la boucle). Pas de spam : une personne non relevée n'entre pas dans Seen (l. 371-375), son compte repart à 1 : réessai toutes les 3 examens (≈ 1,5 s), mais la ligne est écrite une fois PASS-STATIC

Cmd 5. Gardes inchangées, rien hors extérieur (lecture …cpp:325-380, diff). Cachée / classe Person_C / sans collision / OccupyingFnt / UsedInScene (l. 350-353), SexOn (l. 329), seuil SunkDepth 15 cm et mouvement (l. 359), examens immobiles 3 ou 4 (l. 369-375), PlayerBusy (l. 377) : aucune ligne modifiée par le diff (seul l'ajout du Remove dans la branche l. 361-365, qui reste suivie de continue). Le seul déplacement ajouté est dans LiftSunkPersons, appelée uniquement en extérieur (l. 175-182). PASS-STATIC.

Cmd 6. Compilabilité (statique, moteur D:\Game\Launcher\Engine\UE_5.8\Engine\Source\Runtime).

Élément Source Verdict
FHitResult::Normal est FVector_NetQuantizeNormal, dérivé de FVector ; copie dans FVector Push Engine/Classes/Engine/HitResult.h:61 ; Engine/Classes/Engine/NetSerialization.h:540 PASS-STATIC
PenetrationDepth est float ; static_cast<double> HitResult.h:91 PASS-STATIC
TSet::Contains(KeyInitType), Remove(KeyInitType) (int32), Add(const&) / Add(&&), CreateIterator, RemoveCurrent, operator-> Core/Public/Containers/SparseSet.h.inl:960, 905, 415-419, 1710, 1666, 1522 (Set.h n'inclut que CompactSet/SparseSet) PASS-STATIC
Contains/Add/Remove(ACharacter*) : conversion implicite vers TWeakObjectPtr<AActor> même conversion déjà compilée par SunkPersons.Find(Person) (SF5j/SF5k, builds antérieurs) PASS-STATIC (estimé : même conversion, sauf Add qui prend un temporaire)
Logged->IsValid() TWeakObjectPtr::IsValid() : CoreUObject/Public/UObject/WeakObjectPtr.h:300 ; usage voisin .cpp:274-275 PASS-STATIC
FVector::Equals, SizeSquared, GetSafeNormal, Dist2D, OneVector API usuelle, utilisée déjà dans le fichier (Dist2D l. 390 ; GetSafeNormal l. 402) PASS-STATIC
Lambda [&] : Hit, Target, InPlace, World, Capsule, Query, Responses, FloorTop, HalfHeight, Location déclarés avant le lambda (l. 356-415) ; LiftProbe (namespace constexpr) sans capture .cpp:356-422 PASS-STATIC
TArray<FVector, TInlineAllocator<5>> même forme que TInlineAllocator<3> l. 396 PASS-STATIC
Masquage (C4458/C4456/C4457) : Scale déclaré dans if (Near) (l. 399, bloc fermé l. 406) puis dans if (!bPlaced) (l. 459) : portées sœurs, pas de masquage ; Long, Short, Push, Escapes, Inward, bLongIsY, bMoved, InPlace, TryPlace absents des membres de la classe (.h:56-81) et du namespace anonyme (.cpp:25-51) lecture PASS-STATIC
Collision unity : tout est local à la fonction ; aucun nouveau symbole de namespace diff PASS-STATIC
C4244 : opérations en double partout (Inward, LiftSpacing double) ; UE_LOG %.1f avec double lecture PASS-STATIC
Format des UE_LOG : %s%s %.1f %s, arguments const TCHAR*/*FString, même motif que la ligne « releve de » existante .cpp:487-489, 500-501 PASS-STATIC
Aucune compilation lancée : le résultat de l'unité LifePlay reste à prouver par le BUILD COMMUN-9.

4. Diff lu en entier

STG-SF5m.diff (139 lignes) lu en entier, plus le code final LPOutdoorRoomSubsystem.cpp:325-510 et .h (en entier). Deux fichiers : .cpp +80 / -5, .h +2 / -0. Recompte indépendant : git diff --no-index --numstat (méthode distincte du diff de l'IMPL) = 80/5 et 2/0 ; empreinte des lignes +/- identique à celle du .diff livré.

5. Verdict

PASS-STATIC. MD5 conformes, diff conforme à l'IMPL, équivalence de l'ancienne boucle établie par lecture, S-F5m/S-F5n conformes à STG-COMMUN8-DIAG.md § A.4, gardes intactes, API relues dans le moteur 5.8. Non rejoué : compilation, exécution, essais en jeu (reportés à COMMUN-9).

Réserves et risques (aucun n'est un FAIL) :

  • R1 (estimé) : cloison ou rue. Chaque point de repli n'est validé que par la descente de la capsule (pas de test de ligne de vue ni de limite de rue). Un point à 50 cm peut être de l'autre côté d'une cloison mince ou hors du trottoir (grand axe ±) ; S-F5n (profondeur + 2 cm) est moins exposé. Atténuation : l'ordre place le petit axe vers le centre en premier, et la façade n'est essayée qu'en dernier.
  • R2 (estimé) : « centre » = origine de Room. Inward utilise Room->GetActorLocation() ; si l'origine n'est pas le centre géométrique de la rue, le sens « vers le centre » peut être faux ; les trois autres points restent essayés.
  • R3 (estimé) : normale de dépénétration. Sur un décor en collision complexe, la normale d'un recouvrement initial peut être verticale ou la profondeur nulle ; dans le premier cas S-F5n est sauté (garde SizeSquared() > 0.01), dans le second le point n'est décalé que de 2 cm et peut encore chevaucher (le balayage échoue alors et on passe au point suivant). Le coût est un balayage inutile.
  • R4 (établi, mineur) : épisode non remis à zéro hors extérieur. UnplacedLogged n'est pas vidé au Reset() de SunkPersons (l. 331) ni quand la pièce redevient intérieure ; une entrée ne part que si la personne remonte au-dessus du seuil ou est détruite. Conséquence : une personne restée enfoncée d'un lieu à l'autre ne reloguerait pas ; sans effet sur le déplacement. Coût : au plus 5 balayages supplémentaires par personne enfoncée et par réessai (≈ 1,5 s), négligeable. Les points ±Long déjà essayés par S-F5k (quand Near) sont réessayés une fois pour rien.

6. Points à confirmer par l'utilisateur

  • COMMUN-9 : essai en jeu « rue, arrivée au bord contre une façade » (IMPL P1) : relevage en moins de 2 s, ligne ecarte … (depart dans …, S-F5m) ou une seule ligne « aucun point libre ».
  • COMMUN-9 : essai « rue, arrivée ordinaire » (P2) et « plage ou forêt » (P3) : aucune ligne S-F5m.
  • Le point écarté ne se retrouve ni de l'autre côté d'une cloison ni hors de la rue (R1, R2).
  • BUILD COMMUN-9 : 0 erreur, aucun avertissement nouveau sur LPOutdoorRoomSubsystem.cpp (C4458, C4244).
  • Forme de l'IMPL (E1) : accepter l'écart au gabarit ou faire compléter.

Fichiers à commiter

Aucun (seul livrable écrit : Docs/Migration/etat/ST/STG/STG-SF5m-VAL.md, A).

Tours : 11 / 25