15 KiB
Fiche STG-B7av — Niveau N1 — Modèle prévu (agent lp-validator) | utilisé claude-sonnet-5-5 — Agent lp-validator — Skills lp-validate, lp-commandlets, sk-protocol, sk-recount, debug-verification
STG-B7a-VAL : validation statique de B7-a (GI.Show) et du filtre CLOSE (LPDebugSubsystem.cpp) (2026-10-13)
Verdict global : PASS-STATIC. Partie I (GI.Show) : PASS-STATIC (dump et compilation rejoués, aucune exécution en jeu). Partie II (filtre CLOSE) : PASS-STATIC (lecture seule, rien compilé). Aucun FAIL. Réserves en § 6.
1. Fiches amont relues
Docs\Migration\etat\ST\STG\fiches\STG-B7a.md(gestes, critères),STG-B7a-IMPL.md(nœuds, liens, MD5, V1-V5),STG-C5-CART.md(cité par la fiche : cause B7 ; non redémontré ici, la VAL contrôle l'IMPL contre la fiche),STG-CLOSE.patch,STG-TACHES.md(lignes STG-B2P, STG-C2a, STG-SF4b-I pour le contexte et les références 25 / 3 / 55 / 420),STG-B2P-VAL.mdetSTG-B1-VAL.md(référence CompileAllBlueprints),dumps\GI__Show.txt(départ, 84 nœuds).- Rien n'est cru sur parole : dump, MD5, diff et compilation sont rejoués ci-dessous.
2. Points à confirmer des IMPL
| Id | Point | Verdict | Preuve |
|---|---|---|---|
| V1 | Dump GI.Show : 84 + 7 = 91 nœuds, liens du § 1.3 de l'IMPL, IfThenElse_3.else → IfThenElse_6 |
PASS | § 3 b : === GI :: Show (91 noeuds) === (journal l. 1931) ; 7 ajoutés, 0 retiré ; 4 nœuds existants aux liens modifiés = liste de la fiche ; liens des 7 nœuds = tableau IMPL § 1.3 |
| V2 | PromotableOperator_0 = Less_DoubleDouble (B = 70) ; PromotableOperator_1 = NotEqual_ObjectObject |
PASS | dump : appel KismetMathLibrary::Less_DoubleDouble(), B = '70.0' ; appel KismetMathLibrary::NotEqual_ObjectObject() (l'estimé E1 de l'IMPL est établi) |
| V3 | CallFunction_28 = Person_C::moveToPersonStand, self ← personne montrée, Person ← PlayerCharacter, Distance = 100 |
PASS | dump : appel Person_C::moveToPersonStand(), self -> GetArrayItem_10739.Output, Person -> VariableGet_4.PlayerCharacter, Distance = '100.0' |
| V4 | CompileAllBlueprints éditeur fermé : aucun message nouveau sur GI |
PASS | § 3 c : La compilation de GI a réussi ! [en 4 228 ms] (journal l. 142 du résumé) ; 0 ligne d'erreur sous /Game/ ; 25 / 55 / 420 = référence |
| V5 | En jeu : personne à moins de 70 cm, SexOn faux, autre que le joueur → placée à 100 ; aucun Accessed None nouveau ; branche then d'IfThenElse_3 inchangée |
reporté (STG-B7a-V5) | exige un build empaqueté + LogStats ; interdit par la fiche (pas de jeu, pas de build). La non-régression du then est établie par le dump seulement (§ 3 b) |
3. Critères rejoués
a. (I-a) MD5 et état
Au départ (avant tout commandlet) et à la fin (après dump, CompileAllBlueprints), md5sum :
e64b5b37c9ef0db7735de0d6e3bd7c1c *Content/BPs/GI.uasset
8668a47c627f7a5254910cf0ac33b12a *Content/BPs/Person.uasset
ca2a9a0baaca4130fd5c318797f008ae *Content/BPs/Room.uasset
ff69a2ee950e52e95f4f21635fcb5cef *Source/LifePlay/LPDebugSubsystem.cpp
= attendus (GI E64B5B37…, Person 8668A47C…, Room CA2A9A0B…, .cpp ff69a2ee…) : PASS. Départ = fin (deux relevés identiques).
pwsh -NoProfile -File Tools/UeState.ps1 au départ et à la fin : processus=0 editeur=0 compilation=0 shaders=0 jeu=0, code 0 : PASS.
Le MD5 de départ de GI 0E6AEDCC… (instantané Backup_5.5\STG-B7a, manifeste cité par l'IMPL) n'est plus vérifiable que par
l'IMPL (le fichier d'avant n'existe plus dans la copie) : repris de l'IMPL, estimé.
b. (I-b, I-c) Dump LPDumpFunction -BP=GI -Fn=Show -Pins -Exec
Commande : pwsh -NoProfile -File 'D:\Game\LifePlay-master 5.8\Tools\RunCommandlet.ps1' -Lot STG-B7av -Commandlet LPDumpFunction -Args "-BP=GI -Fn=Show -Pins -Exec" -EtatDir 'D:\Game\LifePlay-master 5.8\Docs\Migration\etat\ST\STG'
Sortie : code=0 duree=51s erreurs=0 avertissements=465 ; journal Saved\Logs\portage\STG-B7av_LPDumpFunction_20261013-192844.log ;
résumé etat\ST\STG\STG-B7av_LPDumpFunction_20261013-192844.txt. Pas de demande de recompilation de modules.
Comparaison avec le dump de départ par un script de lecture seule (Python -I, dossier temporaire de session, rien écrit dans le projet) :
base nodes 84 new nodes 91
added: ['K2Node_CallFunction_27', 'K2Node_CallFunction_28', 'K2Node_CommutativeAssociativeBinaryOperator_3', 'K2Node_IfThenElse_6', 'K2Node_PromotableOperator_0', 'K2Node_PromotableOperator_1', 'K2Node_VariableGet_17']
removed: []
changed existing: 4
Les 4 nœuds existants modifiés (broche : avant → après), seuls écarts parmi les 84 nœuds et leurs broches :
| Nœud | Broche | Avant | Après (ajout) |
|---|---|---|---|
IfThenElse_3 |
else |
(vide) |
-> IfThenElse_6.execute |
CallFunction_10 |
Dist |
-> CallFunction_12.A |
+ PromotableOperator_0.A |
GetArrayItem_10739 |
Output |
4 liens | + PromotableOperator_1.A, + CallFunction_28.self |
VariableGet_4 |
PlayerCharacter |
-> VariableGet_14.self, CallFunction_10.To |
+ PromotableOperator_1.B, + CallFunction_28.Person |
= la liste de la fiche (I-b) : PASS. Les 7 nouveaux nœuds (types et broches relevés du dump) : IfThenElse_6 (Branch),
CommutativeAssociativeBinaryOperator_3 (BooleanAND, entrées A, B, C : 3), PromotableOperator_0 (Less_DoubleDouble),
CallFunction_27 (Not_PreBool), PromotableOperator_1 (NotEqual_ObjectObject), VariableGet_17 (SexOn, self vide = GI),
CallFunction_28 (moveToPersonStand) : PASS.
Logique (I-c), lue dans le dump :
IfThenElse_3.else -> IfThenElse_6.execute;IfThenElse_6.Condition <- AND_3.ReturnValue;AND_3.A <- Less(Dist, 70.0)avecDist <- CallFunction_10.Dist;AND_3.B <- Not(SexOn);AND_3.C <- NotEqual(GetArrayItem_10739.Output, PlayerCharacter): PASS.IfThenElse_6.then -> CallFunction_28.execute;CallFunction_28:self <- GetArrayItem_10739.Output,Person <- PlayerCharacter,Distance = 100.0;IfThenElse_6.else (vide);CallFunction_28.then (vide): PASS.- Branche
thend'origine inchangée :IfThenElse_3.thennon listé parmi les écarts (reste-> CallFunction_13.execute) ;CallFunction_13,CallFunction_11(moveToPerson),CallFunction_5(TalkDirty) : aucun écart de broche : PASS. - Aucune lecture d'objet pouvant être nul ajoutée :
LesslitDist(déjà calculé pargetDistancesurGetArrayItem_10739.Output, même chemin,CallFunction_10précèdeIfThenElse_3) ;SexOnest une variable de GI (selfvide) ;NotEqual_ObjectObjectcompare deux références sans les déréférencer ;moveToPersonStandvise la même cible quegetDistance. Aucune nouvelle lecture surPlayerCharacteren dehors de l'argumentPersondemoveToPersonStandet duNotEqual: PASS-STATIC. Remarque :moveToPersonStandreçoitPlayerCharacteréventuellement nul ; ce cas est couvert par le garde G-B1a (IsValid(Person)) de STG-B2P (STG-B2P-VAL.md), établi pour Person, non rejoué ici.
c. (I-d) CompileAllBlueprints
Commande : pwsh -NoProfile -File 'D:\Game\LifePlay-master 5.8\Tools\RunCommandlet.ps1' -Lot STG-B7av -Commandlet CompileAllBlueprints -EtatDir 'D:\Game\LifePlay-master 5.8\Docs\Migration\etat\ST\STG'
Sortie : code=3 duree=196s erreurs=25 avertissements=55 ; journal Saved\Logs\portage\STG-B7av_CompileAllBlueprints_20261013-192940.log ;
résumé etat\ST\STG\STG-B7av_CompileAllBlueprints_20261013-192940.txt.
Recompte par une seconde méthode (Grep sur le journal) : La compilation de .* a réussi = 420 ; Error:.*(/Game/|GI\b) = 0. Lignes de
La compilation de GI a réussi ! [en 4 228 ms], Person … réussi [en 2 835 ms], Room … réussi [en 1 227 ms].
Les 25 lignes d'erreur (16 signatures) portent toutes sur /Engine/CC_Shaders/Utilities/CR_FaceExpRig (trois « Could not find graph function data for
node » : GetMinCurveValue, GetMultiplyCurveValue, ModeIndexConversion, plus structures inconnues) ; six lignes « Script Msg: … @@ » n'indiquent pas
de chemin (estimé : même Control Rig, même source, mêmes quantités que la référence).
Référence STG-B2P-VAL.md / STG-B1-VAL.md : code 3, 25 lignes, 3 erreurs, 55 avertissements, 420 réussites : identique (le « 3 » est lu comme
les trois nœuds distincts ci-dessus, déduit de la signature, la référence ne le définit pas). Verdict (I-d) : PASS.
4. Diff lu en entier
Partie I : GI.uasset
Binaire : pas de diff texte. Contrôle par dump (§ 3 b) : 84 → 91 nœuds, 7 ajoutés, 4 nœuds aux liens modifiés, 0 retiré. git status --short :
M Content/BPs/GI.uasset, M Content/BPs/Person.uasset, M Content/BPs/Room.uasset ; Person et Room étaient déjà M avant la fiche (Person par STG-B2P,
Room par CAM) et leurs MD5 sont ceux attendus : aucun asset non annoncé modifié par B7-a.
Partie II : Source/LifePlay/LPDebugSubsystem.cpp
Commande : git diff --no-index --numstat D:/Game/LifePlay_Backup_5.5/STG-CLOSE/Source/LifePlay/LPDebugSubsystem.cpp Source/LifePlay/LPDebugSubsystem.cpp
Sortie : 14 0 {…/STG-CLOSE/Source => Source}/LifePlay/LPDebugSubsystem.cpp (14 ajouts, 0 retrait).
MD5 de l'instantané : 57880954408614d93d0a1e39d724abee (= 57880954… annoncé) ; fichier actuel ff69a2ee950e52e95f4f21635fcb5cef (= ff69a2ee…).
Deux hunks : @@ -326,6 +326,14 @@ (fonction SeatPlace, 8 lignes) et @@ -491,6 +499,12 @@ (test avant Radii, 6 lignes) = 14. Le diff est identique,
ligne à ligne, à STG-CLOSE.patch (lu en entier). Rien d'autre dans le fichier ne diffère de l'instantané.
Fins de ligne : cat -A du diff : chaque ligne ajoutée finit par ^M$ ; Tools\FileCheck.ps1 Source/LifePlay/LPDebugSubsystem.cpp :
Fins CRLF LF CR BOM MD5 ...
CRLF 765 0 0 - FF69A2EE950E52E95F4F21635FCB5CEF Source\LifePlay\LPDebugSubsystem.cpp
fichiers=1 CRLF=1 alertes=0 introuvables=0
CRLF conservé (765 CRLF, 0 LF seul, 0 CR seul, pas de BOM) : PASS.
Logique (lecture de LPDebugSubsystem.cpp l. 329-335 et 502-507) :
SeatPlace:currentAnimation(nom de l'objet lu parReadObjectName), découpé sur-;Parts.Num() >= 4 ? Parts[2] : FString(): place = 3e champ defnt_xxx-<sexe>-<place>-<desc>.ReadObjectNamedéfinie l. 316, avantSeatPlace(même espace de noms) : PASS-STATIC.- Test :
FntA != "-"(A occupe un meuble)&&mêmeOccupyingFntpour B&&SeatPlace(A) != SeatPlace(B)→continue(la paire n'est ni comptée, ni écriteCLOSE). Même place → la condition est fausse → paire gardée (cas K8 : deux personnages sur la même place restent signalés) : PASS-STATIC. Meuble différent, ou sans meuble (-) → paire gardée : PASS-STATIC. - Placement : après le test
IsHiddenet avantRadii/Gap: une paire exclue n'entre pas dansMinGapniClose: conforme à l'objet du filtre. - API :
FString::ParseIntoArray(TArray<FString>&, const TCHAR*, bool bInCullEmpty = true) const,Engine\Source\Runtime\Core\Public\Containers\UnrealString.h.inl:1746(moteur 5.8 installé) ; appel sur une valeur temporaire permis (méthodeconst) : PASS-STATIC.bInCullEmptyvaut vrai : un champ vide compte pour 0 (voir R2). - Compilation : non faite (interdit). Le verdict d'API et de syntaxe est par lecture ; la compilation reste à prouver par BUILD.
5. Verdict
| Partie | Verdict |
|---|---|
| I-a MD5 et UeState | PASS |
| I-b dump 84 → 91, 7 nouveaux, rien retiré, 4 nœuds modifiés | PASS |
| I-c logique | PASS-STATIC |
| I-d CompileAllBlueprints | PASS |
| Partie I | PASS-STATIC (V5 reporté) |
| II diff 14 lignes, CRLF, logique, API | PASS-STATIC (non compilé) |
| Global | PASS-STATIC |
6. Points à confirmer par l'utilisateur et réserves
- STG-B7a-V5 : essai en jeu (build empaqueté) : partenaire à moins de 70 cm hors
SexOnse place à 100 cm ; aucunAccessed Nonenouveau dansShow. - Compilation du filtre CLOSE : à confier à BUILD (
Tools/Build.ps1) avant le prochain paquet ;LPDebugSubsystem.cppn'a pas été compilé. - R1 (estimé, sans effet bloquant) :
moveToPersonStandest appelé avecPerson = PlayerCharacter; siPlayerCharacterest nul, leNotEquallaisse passer et la fonction cible reçoit unPersonvide : couvert par G-B1a (STG-B2P), établi à la VAL B2P, non rejoué sur ce chemin. - R2 (estimé) : si un seul des deux personnages a un
currentAnimationvide ou non conforme (moins de 4 champs,SeatPlacevide) et l'autre une place, sur le même meuble, la paire est exclue du compteCLOSEalors qu'elle pourrait se chevaucher réellement. Le fichier d'origine ne gère pas ce cas ; effet limité à la mesure M1. - R3 : pas d'exécution en jeu de B7-a (collision de la capsule du joueur lors du placement à 100 cm non étudiée ici).
7. Commandes, fichiers écrits, fichiers à commiter
Fichiers produits par mes commandlets et mon livrable (aucun fichier de Source/, Content/, Config/ modifié) :
Docs/Migration/etat/ST/STG/STG-B7a-VAL.md(A)Docs/Migration/etat/ST/STG/STG-B7av_LPDumpFunction_20261013-192844.txt(A)Docs/Migration/etat/ST/STG/STG-B7av_CompileAllBlueprints_20261013-192940.txt(A)- Journaux (non suivis par git) :
Saved\Logs\portage\STG-B7av_LPDumpFunction_20261013-192844.log,…\STG-B7av_CompileAllBlueprints_20261013-192940.log. - Script de comparaison de lecture seule :
cmp_show.pydans le dossier temporaire de session (non versé).
Aucune commande git qui écrit. Fichiers à commiter : trois A ci-dessus (le gardien du dépôt).
Trace : D:\Game\LifePlay-master 5.8\Saved\Logs\portage\STG-B7av_LPDumpFunction_20261013-192844.log et …\STG-B7av_CompileAllBlueprints_20261013-192940.log — Fiche STG-B7av — 2026-10-13 19:28-19:36
Commande : voir § 3 b et § 3 c
Environnement: copie D:\Game\LifePlay-master 5.8, branche ue5.8, HEAD 0745917, moteur UE 5.8 ; UeState 0 avant et après
Attendu : dump 91 nœuds (7 ajoutés, 4 modifiés) ; CompileAllBlueprints 0 erreur /Game/, 25 / 3 / 55 / 420, code 3
Obtenu : 91 nœuds, 7 ajoutés, 0 retiré, 4 modifiés ; code 3, 25 lignes d'erreur (toutes CR_FaceExpRig), 55 avertissements, 420 réussites
Lecture : code 3 de CompileAllBlueprints = erreurs CC_Shaders seules ; LPDumpFunction n'imprime pas les valeurs de classe
Tours : 17 / 40
Constats
- À verser :
lp-commandlets— le titre=== GI :: Show (91 noeuds) ===apparaît deux fois dans le journal (fluxLogLPDumpet copieLogInit: Display:) : comparer sur la première occurrence ; le dump de départdumps\GI__Show.txtclasse les nœuds dans le même ordre que le dump actuel, mais seul un script par nœud et par broche détecte un lien modifié.
Note de l'orchestrateur (2026-10-13) : dans la section Constats, la ligne « À verser » affirme que le dump de départ et le dump actuel classent les nœuds dans le même ordre. Le validateur l'a signalé lui-même comme non vérifié (le début des deux fichiers suggère le contraire) : seule la première moitié (titre « (91 noeuds) » présent deux fois dans le journal) est établie.