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

12 KiB

Fiche STG-C6b-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-C6b-VAL : validation statique du correctif C6-b, Scene_C comptée comme menu seulement si elle montre quelque chose (2026-10-14)

Verdict : PASS-STATIC (lecture et recomptes, aucune compilation, aucune exécution, aucun UE). Aucune écriture hors de ce livrable.

1. Fiches amont relues

  • Docs\Migration\etat\ST\STG\STG-C6b-IMPL.md (86 lignes, lu en entier).
  • Docs\Migration\etat\ST\STG\STG-C6b.diff (117 lignes, lu en entier).
  • D:\Game\LifePlay_Backup_5.5\STG-C6b\manifest.csv et les deux fichiers de l'instantané.
  • Docs\Migration\etat\BOSS\COMMUN-3-TESTS.md l. 25 (D10).
  • Pas d'autre IMPL amont dans cette fiche (le correctif entre avec M1e, déjà dans l'instantané).

2. Points à confirmer des IMPL

Point (IMPL § 5) Résultat
Fenêtre A rejouée : ligne C6-b : boite Scene_C … sans contenu visible, ZQSD marche reporté (essai en jeu au prochain build commun, hors périmètre statique)
D10 : boîte de scène visible, ZQSD sans effet, M1e : marche coupee par le menu Scene_C reporté (essai en jeu). Raisonnement statique au point 3.4 : PASS-STATIC sous réserve du risque R1
Structure réelle de /Game/UI/Scene (IMPL § 3, « estimé, non mesuré ») reporté, non lisible sans UE ; voir R1

3. Critères rejoués

3.1 MD5 (établi)

Commande : md5sum sur les fichiers actuels et sur l'instantané ; manifeste lu.

44ace47d29424101b4127ba12e789beb *Source/LifePlay/LPDirectControlSubsystem.cpp
ad60a24fb3e3075299c1f4ec5f087011 *D:/Game/LifePlay_Backup_5.5/STG-C6b/Source/LifePlay/LPDirectControlSubsystem.cpp
acff924ae6e03548546ef3fb2e430eb8 *Source/LifePlay/LPDirectControlSubsystem.h
979ae0ada261655cbbe9aefd6969e833 *D:/Game/LifePlay_Backup_5.5/STG-C6b/Source/LifePlay/LPDirectControlSubsystem.h
manifest.csv : cpp "AD60A24FB3E3075299C1F4EC5F087011" (46073 o) ; h "979AE0ADA261655CBBE9AEFD6969E833" (3082 o)
Élément IMPL Recompté Verdict
cpp actuel 44ACE47D… 44ace47d29424101b4127ba12e789beb confirmé
h actuel ACFF924A… acff924ae6e03548546ef3fb2e430eb8 confirmé
cpp instantané AD60A24F… ad60a24fb3e3075299c1f4ec5f087011 confirmé
h instantané 979AE0AD… 979ae0ada261655cbbe9aefd6969e833 confirmé

3.2 Diff régénéré et périmètre (établi)

Commande : diff -u <instantané> <actuel> pour le cpp puis le h, lignes d'en-tête ---/+++ (horodatages) neutralisées, comparé à STG-C6b.diff sans CR : sortie DIFF-IDENTIQUE. Recompte indépendant : grep -c '^+[^+]' du diff = 66 ; grep -c '^-[^-]' = 0. Conforme à l'IMPL § 2 (66 ajoutées, 0 retirée). Lu en entier : 4 includes ; 3 fonctions (ShownUpToRoot, ShowsContent, EmptySceneSeen) ; EmptySceneSeen() = false; en tête de MenuReason ; bloc Scene_C dans la boucle ; journalisation dans WitnessMoveKeys ; membre bLoggedEmptyScene dans le .h. Rien d'autre que l'IMPL § 2 (aucun ajout non demandé). Limite : l'instantané ne contient que les deux fichiers ; « rien d'autre n'a changé » est établi pour ces deux fichiers (diff identique), non pour le reste de l'arbre (les autres fichiers modifiés de git status viennent d'autres lots, non comparés ici).

3.3 Seule Scene_C est filtrée (établi, lecture de LPDirectControlSubsystem.cpp l. 689-715)

  • Le filtre est if (ClassName == TEXT("Scene_C") && !ShowsContent(Widget)) (l. 707) : les 9 autres classes de MenuClasses (l. 58-62) passent à return ClassName; (l. 712) comme avant.
  • Panneau Clavier (l. 682-688) : placé avant la boucle, inchangé ; focus de saisie (l. 716-724) : après la boucle, inchangé.
  • break (l. 711) est dans for (const TCHAR* Menu : MenuClasses) ; il sort de cette boucle seulement. La boucle TObjectIterator (l. 689) continue : le widget suivant est examiné. Scene_C figurant en dernier de MenuClasses, le break ne saute aucune autre classe pour ce widget.
  • Seul effet de bord hors filtre : EmptySceneSeen() = false; (l. 677) à chaque appel, et la ligne de journal ; aucun effet sur la valeur renvoyée. MenuReason n'est appelé que par Tick (l. 869), toutes les 0,25 s, avant WitnessMoveKeys (l. 872), d'où la lecture de l'indicateur à jour.
  • Note : si un widget Scene_C vide et un autre menu sont présents, l'indicateur reste levé alors que le menu coupe : seulement un message de journal (inexact mais sans effet sur la marche).

3.4 D10 par le code (estimé, raisonnement)

Une boîte avec un UTextBlock ou URichTextBlock non vide, ou un UButton (ou sous-classe : IsA), visible jusqu'à la racine : ForEachWidget parcourt tous les widgets de l'arbre (pas de court-circuit autre que bShown), bContent vrai, ShownUpToRoot vrai, donc ShowsContent vrai, MenuReason renvoie Scene_C. Cas de prudence confirmés dans le code (l. 641) : WidgetTree nul, Widget nul ou Depth > 8 renvoient vrai (compté comme menu). Une fois bShown vrai il n'est plus réécrit (retour anticipé l. 652). Cas qui change : Scene_C Visible sans bouton ni texte non vide visible jusqu'à la racine, ou opacité de rendu du widget racine ≤ 0,01 (fenêtre A), ce que vise le correctif.

Risques (« une vraie boîte ignorée ») :

# Cas Estimation
R1 Boîte dont le seul contenu est dans un widget non couvert : UEditableText, UMultiLineEditableText, UImage seul, UCheckBox, UComboBox/liste, widget C++ propre Faible. Une boîte de dialogue de scène a des boutons de choix (UButton) ou un texte. Le focus de saisie reste couvert par la branche « focus » inchangée si un champ éditable a le focus. Non mesuré : la structure de /Game/UI/Scene n'est pas lue (comme dit en IMPL § 3).
R2 UWidget::IsVisible() renvoie faux si le widget Slate n'est pas construit (Widget.cpp l. 395-403 : GetCachedWidget() invalide donne false) : un contenu pas encore construit est vu comme absent Faible, transitoire (au plus 1 cycle de 0,25 s), identique à l'effet de bord annoncé en IMPL § 3.
R3 Texte non vide mais rendu invisible par autre chose que visibilité/opacité (alpha de couleur à 0, hors écran, Image de fond seule) Faible à moyen pour la fenêtre A (la boîte vide pourrait ne pas être reconnue : la marche resterait coupée, sans ligne C6-b) ; ne casse pas D10 (échec sûr : comme avant).
R4 Texte lié par binding (TextDelegate) : GetText() évalue le binding, non vérifié Faible ; un binding vide donne « vide ».

Aucun de ces cas ne crée un faux « marche libre » pour une boîte qui montre du texte ou un bouton ; le risque pour D10 est limité aux boîtes sans bouton ni texte (R1), estimé faible.

3.5 Compilabilité par lecture des en-têtes UE 5.8 (établi, D:\Game\Launcher\Engine\UE_5.8\Engine\Source\Runtime\UMG)

Élément Source lue Résultat
UWidgetTree::ForEachWidget(TFunctionRef<void(UWidget*)>) const Public/Blueprint/WidgetTree.h l. 78 OK, appelable via const UUserWidget* ; la lambda (UWidget* Child) convient
UWidget::IsVisible() const Public/Components/Widget.h l. 582 OK
UWidget::GetRenderOpacity() const Widget.h l. 598 OK (aussi sur const UUserWidget*)
UWidget::GetParent() const -> UPanelWidget* Widget.h l. 769 OK, Node = Node->GetParent() convertit UPanelWidget* en const UWidget* ; UPanelWidget est un UWidget, déclaré complet par l'include de UserWidget.h / WidgetTree.h (hypothèse : Components/PanelWidget.h est tiré par WidgetTree.h ; sinon C2036/C2440, voir point à confirmer au build)
UTextBlock::GetText() const Components/TextBlock.h l. 95 OK
URichTextBlock::GetText() const Components/RichTextBlock.h l. 196 OK
UUserWidget::WidgetTree Blueprint/UserWidget.h l. 1524 TObjectPtr<UWidgetTree> WidgetTree; sous public: (l. 1521) OK, Widget->WidgetTree et ->ForEachWidget sur un const UUserWidget* : operator-> d'un TObjectPtr const rend UWidgetTree*, appelable
Child->IsA<UButton>() Components/Button.h présent OK (UObject::IsA<T>() const)
Includes ajoutés Blueprint/WidgetTree.h, Components/Button.h, Components/RichTextBlock.h, Components/TextBlock.h existent tous OK
Module UMG Source\LifePlay\LifePlay.Build.cs l. 38 : { "Slate", "SlateCore", "UMG" } OK
Lambda récursive ShowsContent est appelée dans la lambda de son propre corps : le nom est déjà déclaré (déclarateur vu) et la fonction est dans un espace de noms anonyme (l. 52), non capturée OK
Argument par défaut int32 Depth = 0 l. 639, première déclaration, un seul appel avec 1 argument (l. 707) et un avec 2 (l. 660) OK
Collisions de noms Grep de `ShownUpToRoot ShowsContent

Limite : lecture seule des en-têtes ; la compilation reste à faire (BUILD). const UWidget* appelant GetParent() : méthode const, OK.

3.6 Fins de ligne, ASCII, livrable IMPL (établi)

Commande Python -I (comptes d'octets) :

cpp : LF=1483 CRLF=1483 CR=1483
h   : LF=90 CRLF=90 CR=90
IMPL.md : LF=86 CRLF=0 CR=0
  • cpp et h : tous CRLF, zéro LF isolé, zéro CR isolé.
  • Non-ASCII du cpp : 2 lignes (l. 454 « %s » et l. 513), même nombre dans l'instantané (2) et dans HEAD (1 ligne seule en HEAD : l. 513 absente ou ajoutée par un lot précédent, avant C6-b) ; le diff ne contient aucun non-ASCII ajouté (grep -P '^\+.*[^\x00-\x7F]' vide). Le correctif n'ajoute rien de non-ASCII : confirmé.
  • STG-C6b-IMPL.md : LF pur (CRLF=0), C:\Users : 0 occurrence (grep -c), en-tête complet (Fiche, Niveau, Modèle prévu | utilisé, Agent, Skills).
  • Tools\FileCheck.ps1 appelé par pwsh avec arguments positionnels / -Files : paramètres rejetés (« Impossible de trouver un paramètre positionnel », « Split-Path … chaîne vide ») ; contrôle remplacé par le comptage d'octets ci-dessus (même objet).

4. Diff lu en entier

2 fichiers (LPDirectControlSubsystem.cpp, .h), 66 lignes ajoutées, 0 retirée, conforme à l'IMPL § 2. Régénéré et identique au fichier .diff.

5. Verdict

PASS-STATIC.

6. Points à confirmer par l'utilisateur

  • Essai en jeu, fenêtre A rejouée : ligne C6-b : boite Scene_C … sans contenu visible puis ZQSD marche (reporté, prochain build commun).
  • Essai D10 : boîte de scène visible, ZQSD sans effet, M1e : marche coupee par le menu Scene_C, sans ligne C6-b (reporté).
  • Compilation LifePlayEditor 5.8 : 0 erreur (BUILD) ; vérifier en particulier UPanelWidget complet pour GetParent() (voir 3.5).

Écarts

  1. IMPL hors gabarit : ses sections (Instantané, Changements, D10, Pas fait, Points à confirmer, MD5, Retour arrière, Fichiers à commiter) ne suivent pas l'ordre IMPL de gabarits.md (1 Fichiers modifiés, 2 Écarts à la SPEC, 3 Instantané, 4 Pas fait, 5 Points à confirmer, 6 Fichiers à commiter) ; pas de section « Écarts à la SPEC » ni mention « Hors gabarit ». Mineur, sans effet sur le code.
  2. IMPL § 4 : la ligne WALK … menus=[…] de LPDebugSubsystem compte toujours Scene_C sans filtre (annoncé par l'IMPL) : à garder en tête à la lecture des journaux.
  3. Note sur le texte 3.6 : l'IMPL ne cite pas le non-ASCII existant du cpp (2 lignes, hérité).

Non rejoué

Compilation, LPTestStringCompat, ouverture de l'éditeur, essais en jeu (D10, fenêtre A), structure de /Game/UI/Scene.

Tours : 7 / 30