14 KiB
Fiche STG-M1e-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-M1e-VAL : validation statique de la mesure M1e (2026-10-14)
VAL statique : sans UE, sans compilation, rien écrit hors de ce livrable. Copie D:\Game\LifePlay-master 5.8, branche ue5.8.
Moteur lu : D:\Game\Launcher\Engine\UE_5.8\Engine\Source\Runtime (5.8.3, lp-env). Instantané : D:\Game\LifePlay_Backup_5.5\STG-M1e\.
1. Fiches amont relues
| Fiche | Relue |
|---|---|
STG-M1e-IMPL.md (toute la fiche, 74 lignes) |
oui |
STG-M1e.diff (224 lignes, en entier) |
oui |
manifest.csv de l'instantané STG-M1e |
oui (4 fichiers, MD5 avant concordants avec IMPL § 2) |
STG-COMMUN6-DIAG.md |
non relu en entier : motif repris de IMPL § 1 et § 4 (la VAL porte sur le code, pas sur le diagnostic) |
2. Points à confirmer des IMPL
L'IMPL n'a pas de section « Points à confirmer » (voir écart E1). Les sept contrôles de la fiche VAL en tiennent lieu.
| Id | Point | Résultat |
|---|---|---|
| P1 | MD5 actuels = IMPL § 5 ; Keyboard inchangé | PASS |
| P2 | Diff = IMPL § 3, rien d'autre | PASS-STATIC |
| P3 | Marche inchangée, MenuReason = ancien MenuOnScreen |
PASS-STATIC |
| P4 | Témoin sans consommation, enregistré / retiré | PASS-STATIC |
| P5 | Compilabilité par lecture (en-têtes UE 5.8) | PASS-STATIC, aucune erreur probable trouvée |
| P6 | Fins de ligne, ASCII | PASS |
| P7 | Livrable de l'IMPL (en-tête complet, LF, pas de C:\Users) |
PASS partiel : LF et chemins conformes, en-tête et sections hors gabarit (E1) |
3. Critères rejoués
P1 — MD5 (établi)
Commande : md5sum LPDirectControlSubsystem.cpp LPDirectControlSubsystem.h LPKeyboardSubsystem.cpp LPKeyboardSubsystem.h (dans Source/LifePlay)
ad60a24fb3e3075299c1f4ec5f087011 *LPDirectControlSubsystem.cpp
979ae0ada261655cbbe9aefd6969e833 *LPDirectControlSubsystem.h
5d60d3f8ffe721698820fe68e55f938c *LPKeyboardSubsystem.cpp
eed95e9860b26c5a7327ce4e3f90d8c8 *LPKeyboardSubsystem.h
Recoupé par Tools\FileCheck.ps1 : AD60A24F…5F087011, 979AE0AD…E969E833, 5D60D3F8…8E55F938C, EED95E98…C8D3, identiques à IMPL § 5 et § 2.
Les copies de l'instantané donnent baaa3982583b70a56602cbfe95bf4fa4 (.cpp), 77ae7007c77403f05c6697771029cc8c (.h), 5d60d3f8… et eed95e98… (Keyboard) = IMPL § 2 et manifest.csv.
diff -q instantané contre copie sur LPKeyboardSubsystem.cpp et .h : aucune sortie, code 0 (identiques).
P2 — diff contre l'instantané (établi pour la concordance, estimé pour l'absence d'autre changement)
Je régénère le diff moi-même (diff -u <instantané> <copie> | tail -n +3 | tr -d '\r' | md5sum) et le compare au fichier STG-M1e.diff (mêmes lignes, sans les deux lignes d'en-tête horodatées) :
CPP bccf14a6ed29181e35a57aaa9f7f7d2a *- (régénéré) | bccf14a6ed29181e35a57aaa9f7f7d2a *- (STG-M1e.diff l. 3-201)
H fa35a50f8e2b5c9ccccc2c23c649f9ab *- (régénéré) | fa35a50f8e2b5c9ccccc2c23c649f9ab *- (STG-M1e.diff l. 204-224)
Le fichier .diff livré est donc exactement le diff réel. Comptes : .cpp 111 lignes ajoutées, 8 retirées (grep -c '^+[^+]' et '^-[^-]'). Seuls deux fichiers changent par rapport à l'instantané ; le diff est lu en entier (§ 4).
Les lignes du diff correspondent à IMPL § 3 : include, MenuReason, IsMoveKey / SlateMoveKeys / FMoveKeyWitness, Initialize / Deinitialize, appel dans Tick, WitnessMoveKeys, déclarations du .h. Un seul ajout non cité dans § 3 : le commentaire de ScenePlaying (l. 459) qui renomme MenuOnScreen en MenuReason (commentaire, sans effet).
P3 — comportement de la marche (établi par lecture)
- Ordre des tests (
.cppl. 622-666), identique à l'ancien : (1)GInul ; (2)ULPKeyboardSubsystem::IsMenuOpen(); (3) boucleTObjectIterator<UUserWidget>avec les mêmes filtres (CDO, autre GameInstance, hors viewport, Collapsed / Hidden) et comparaison àMenuClasses; (4) Slate non initialisé ; (5) widget focalisé « Editable ». Les lignes de contexte du diff (non modifiées) le montrent ; seules les lignes de retour changent. - Retours :
falsedevientFString()aux étapes 1 et 4 et en fin de fonction ;truedevientTEXT("clavier")(étape 2),ClassName(étape 3),"focus " + type(étape 5). - Vide ⇔ false : les trois retours non vides sont non vides par construction.
ClassNameégale un élément deMenuClasses(l. 54-58 : dix littéraux non vides) ;"clavier"et"focus "+…sont non vides. Toutes les sorties qui valaientfalsesont vides. DoncbMenuBlocks = !MenuWhy.IsEmpty()(l. 810) vaut exactement l'ancienne valeur, dans la même brancheMenuDelay >= 0.25f(cadence inchangée). - Plus aucun appel à
MenuOnScreendans ce fichier :Grep MenuOnScreendansLPDirectControlSubsystem.cpp= 0 résultat. Les lecteurs debMenuBlocks(l. 825, 998) sont inchangés. - Hors du fichier :
LPCameraModeSubsystem.cpp:120a sa propre copieLPCameraModeLocal::MenuOnScreen(espace de noms nommé, non modifié) etLPDebugSubsystem.cpp:433ne cite le nom que dans un commentaire. Aucun appel croisé. - Effets de bord ajoutés :
WitnessMoveKeysne modifie nibMenuBlocks, ni l'entrée, ni le contrôleur ; il lit et journalise (UE_LOGDisplay).IsPressed,InputEnabled,IsMoveInputIgnored,IgnoreInputsont des lectures.
P4 — témoin FMoveKeyWitness (établi par lecture)
HandleKeyDownEventetHandleKeyUpEvent:return falsesur tous les chemins (.cppl. 696-709 du diff) ;Tickest vide. Jamais d'évènement consommé.- Enregistrement :
Initialize(l. 772-776), une fois, siFSlateApplication::IsInitialized();RegisterInputPreProcessor(MoveWitness)avec unTSharedPtr<IInputProcessor>(surcharge à un argument, sans ambiguïté). - Retrait :
Deinitialize(l. 793-798) :UnregisterInputPreProcessorsi valide et Slate initialisé, puisMoveWitness.Reset()etSlateMoveKeys().Reset(). Aucun retour anticipé dansDeinitializeavant ce bloc. - Pas de double enregistrement :
Initializen'est appelé qu'une fois par instance de sous-système, un seul témoin par instance (le membreMoveWitness). Fuite : leTSharedPtrest le seul propriétaire côté jeu, libéré auReset. Cas Slate déjà détruit àDeinitialize: pas de désinscription (inutile), leResetlibère quand même le témoin. - Établi : le moteur inscrit les pré-processeurs dans une liste qu'il possède ; aucun test d'exécution (PIE, double Initialize) n'a été rejoué. Réserve : pas de preuve par l'exécution (estimé).
- État statique
SlateMoveKeys()partagé par toutes les instances (une seule GameInstance en jeu) ; remis à zéro auDeinitializeet à la perte d'activité de la fenêtre.
P5 — compilabilité par lecture, en-têtes UE 5.8 (établi pour chaque signature, compilation non rejouée)
| Élément | Moteur 5.8 | Usage dans le code | Verdict |
|---|---|---|---|
IInputProcessor::Tick |
IInputProcessor.h:23 virtual void Tick(const float, FSlateApplication&, TSharedRef<ICursor>) = 0; |
override identique, corps vide | conforme (seule pure virtuelle) |
HandleKeyDownEvent / HandleKeyUpEvent |
IInputProcessor.h:26, 29 virtual bool …(FSlateApplication&, const FKeyEvent&) |
override identique | conforme |
RegisterInputPreProcessor |
SlateApplication.h:1544 bool …(TSharedPtr<IInputProcessor>) (non const) |
Get().RegisterInputPreProcessor(MoveWitness) |
conforme |
UnregisterInputPreProcessor |
SlateApplication.h:1574 void …(TSharedPtr<IInputProcessor>) |
idem | conforme |
IsActive |
SlateApplication.h:1611 virtual bool IsActive() const override |
Get().IsActive() |
conforme |
GetKeyboardFocusedWidget |
SlateApplication.h:1653 TSharedPtr<SWidget> … const |
affecté à const TSharedPtr<SWidget> |
conforme |
APlayerController::InputEnabled |
PlayerController.h:2142 bool InputEnabled() const |
appelé sur const APlayerController* |
conforme |
IsMoveInputIgnored |
Controller.h:368 virtual bool … const (hérité par le contrôleur) |
idem | conforme |
PlayerInput |
PlayerController.h:370 TObjectPtr<UPlayerInput> PlayerInput |
PC->PlayerInput->IsPressed(Key) |
conforme |
UPlayerInput::IsPressed |
PlayerInput.h:745 bool IsPressed(FKey) const |
idem | conforme |
UGameViewportClient::IgnoreInput |
GameViewportClient.h:773 virtual bool IgnoreInput() override (non const) |
Viewport pointeur non const (GetGameViewportClient() const rend UGameViewportClient*, GameInstance.h:295) |
conforme (le commentaire du code le dit) |
FKey::ToString |
InputCoreTypes.h:90 FString ToString() const |
*Key.ToString() |
conforme |
UInputSettings::GetAxisMappings |
InputSettings.h:318 const TArray<FInputAxisKeyMapping>& … const |
boucle const FInputAxisKeyMapping& |
conforme |
APlayerController::GetViewTarget |
PlayerController.h:1911 AActor* … const |
GetNameSafe(PC->GetViewTarget()) |
conforme |
Includes présents (.cpp l. 22, 26-27, 31-33) : Engine/GameViewportClient.h, Framework/Application/IInputProcessor.h (ajouté), SlateApplication.h, GameFramework/InputSettings.h, PlayerController.h, PlayerInput.h. ForwardAxis / RightAxis (l. 50-51) et ScenePlaying (l. 461) sont déclarés avant leur usage, dans le même espace de noms anonyme (ouvert l. 48, fermé l. 766). LogLifePlay vient de LifePlay.h. TArray::IsEmpty, Last, AddUnique, Remove, Reset existent. Le .h déclare TSharedPtr<class IInputProcessor> avec déclaration avancée : valable, le suppresseur est capturé à la création du TSharedPtr dans le .cpp. Expression ternaire des Why : trois FString, type homogène ; PC ? *GetNameSafe(…) : TEXT("-") : deux const TCHAR*, temporaire vivant jusqu'à la fin de l'expression de UE_LOG.
Collisions de noms (build unity) : Grep sur Source de IsMoveKey|SlateMoveKeys|FMoveKeyWitness|MenuReason|MoveWitness|MenuWhy|MoveLogDelay|WitnessMoveKeys : toutes les occurrences sont dans LPDirectControlSubsystem.cpp/.h. MenuOnScreen subsiste seulement dans LPCameraModeSubsystem.cpp (espace de noms LPCameraModeLocal) : sans collision. Aucun nom nouveau n'est partagé avec un autre fichier du module.
Signalé, non bloquant : TSharedRef<ICursor> en paramètre dans le Tick du témoin repose sur ICursor déclaré par IInputProcessor.h / SlateApplication.h (inclus) ; estimé sans risque, seule la compilation tranchera.
P6 — fins de ligne et ASCII (établi)
Tools\FileCheck.ps1 -Path … : LPDirectControlSubsystem.cpp CRLF 1416, LF seul 0, CR seul 0 ; .h CRLF 88, LF 0, CR 0 ; Keyboard .cpp CRLF 958 / LF 0, .h CRLF 68 / LF 0 ; sans BOM ; alertes=0. git ls-files --eol : i/crlf w/crlf pour les deux fichiers modifiés.
Non ASCII : grep -cP '[^\x00-\x7F]' donne 2 lignes dans le .cpp actuel et 2 dans le .cpp de l'instantané (l. 450 et l. 509, préexistantes), 0 dans le .h ; grep -nP '^\+.*[^\x00-\x7F]' STG-M1e.diff : 0 ligne. Aucun caractère non ASCII ajouté.
P7 — livrable de l'IMPL (établi)
FileCheck : STG-M1e-IMPL.md LF 74, CRLF 0 ; STG-M1e.diff LF 224, CRLF 0 (le diff, sans CR : cohérent avec la comparaison faite après tr -d '\r'). grep -c 'C:.Users' : 0. L. 1 : « Fiche STG-M1e-IMPL — Niveau N3 — Modèle prévu … | utilisé … » présente. Écarts de gabarit : voir E1.
4. Diff lu en entier
STG-M1e.diff lu en entier (224 lignes) : .cpp 6 blocs (include ; commentaire ScenePlaying ; MenuReason et témoin ; Initialize / Deinitialize ; Tick ; WitnessMoveKeys), .h 2 blocs (déclaration, membres). 111 lignes ajoutées et 8 retirées au .cpp. Régénéré indépendamment contre l'instantané (§ P2). LPKeyboardSubsystem : 0 différence.
Remarques de lecture, sans écart de code : la ligne touche … vue par Slate utilise Key = SlateMoveKeys().Last() seulement ; MenuWhy est rafraîchi toutes les 0,25 s (les lignes de transition peuvent arriver jusqu'à 0,25 s après le menu, normal) ; le commentaire de LPDebugSubsystem.cpp:433 cite encore MenuOnScreen (commentaire, hors périmètre, fichier non touché par M1e).
5. Verdict
PASS-STATIC. Points 1 à 6 conformes avec preuve ; la compilation n'a pas été rejouée (consigne du GO), le comportement à l'exécution non plus. Point 7 conforme sur LF et chemins ; écart documentaire E1 sur le gabarit de l'IMPL (n'affecte pas le code).
Écarts :
- E1 (documentaire, mineur) :
STG-M1e-IMPL.mdne suit pas le gabarit IMPL delp-doc/gabarits.md: pas de seconde ligne d'en-tête « Agent … Skills … » (sk-protocol§ 4), pas de ligne# STG-M1e-IMPL : titre (date), sections propres (1 à 7) au lieu de « 1. Fichiers modifiés, 2. Écarts à la SPEC, 3. Instantané, 4. Ce qui n'a pas été fait, 5. Points à confirmer en VAL, 6. Fichiers à commiter » ; ni « Points à confirmer » ni ligneTours : n / budget(Grep Tours: 0). Le contenu de l'écart au DIAG (§ 1) et de la fiche existe mais hors des intitulés. À corriger par l'auteur ou à accepter par l'orchestrateur. - N1 (information) : un commentaire modifié (
ScenePlaying,.cppl. 459) n'est pas listé dans IMPL § 3.
Non rejoué : compilation (consigne), LPTestStringCompat, exécution en éditeur ou en jeu, comportement réel du témoin (touche vue par Slate, absence de consommation constatée à l'exécution, Deinitialize en PIE).
6. Points à confirmer par l'utilisateur
- Accepter ou faire reprendre le gabarit de l'IMPL (E1).
- Compilation au prochain build commun : le résultat tranche P5 (la lecture ne la remplace pas).
- À l'essai : relever les lignes
M1e :selon le tableau de IMPL § 4 ; vérifier au journal que le témoin ne perturbe pas la marche (comparaison avec un essai sans M1e, non faite ici).
Fichiers à commiter : Docs/Migration/etat/ST/STG/STG-M1e-VAL.md (A). Fichiers modifiés par cette VAL : ce seul livrable.
Tours : 9 / 30