LifePlay-Revival/Docs/Migration/etat/ST/STE/STE-ORG5-V1-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

20 KiB
Raw Blame History

Fiche STE-ORG5-V1 — Niveau N2 — Modèle prévu (modèle de l'agent lp-validator) | utilisé claude-sonnet-5-5 — Agent lp-validator — Skills lp-validate, sk-recount, sk-protocol (debug-verification préchargé)

STE-ORG5-V1-VAL : VAL statique, sans compilation, du bonus d'orgasme ORG5 V-min (2026-10-14)

Périmètre : lecture seule, sans compilation, éditeur, MCP, commandlet ni jeu. Seul fichier écrit : ce livrable. Aucun refus du crochet (commandes Bash sans >, sans python -c, sans heredoc). Tout verdict sur la compilation reste « probable ».

1. Fiches amont relues

  • Fiche fiches\STE-ORG5-V1.md (lue en entier) ; livrable IMPL STE-ORG5-I1-IMPL.md (lu en entier : § 1.4, § 2 écarts E1-E10, § 5 points VAL-1 à VAL-13) ; SPEC STE-ORG5-SPEC.md (lue en entier, dont « Décisions de l'utilisateur » l. 291-294 et « Règle commune ORG4 / ORG5 » l. 296-300). La fiche fiches\STE-ORG5-I1.md n'a pas été relue : ses consignes sont reprises par la fiche V1 (§ 3 et § 4), qui fait foi ici.
  • Code lu en entier : Source\LifePlay\LPBonusRewardSubsystem.h (119 lignes) et .cpp (667 lignes).
  • Dumps relus : L6f_dump_Person.txt:20-29 (QueryStat), :555-570 (isPlayer, ModifyStat) ; L6f_dump_GI.txt:19622-19673 (Overlaps), :21245-21255 et GI__EventGraph_P2.txt:14299-14306 (CurrentTags), :23421-23503 (IsInterestedIn), :23548-23554 (appel QueryStat(Stat, WithoutBuff, RNG) par un autre sous-graphe) ; Person__EventGraph.txt:15904-15913 (remise à 0), :16112-16125 (IncrementInt de Sex_OrgasmCounts).
  • Moteur 5.8 relu : KismetMathLibrary.h:180-184, 796, 836, 4581-4583 ; GenericPlatformMemory.h:221 ; Ticker.h:21, 45, 66 ; Class.h:790 ; Field.h:903 ; UObjectBaseUtility.h:633-657 ; KismetArrayLibrary.cpp:338-353 ; RandomStream.h:105-108, 209-214 ; TextProperty.h (présent).

2. Points à confirmer des IMPL

Id Point Verdict Preuve / raison
VAL-1 build LifePlay code 0 ; UHT accepte FLPBonusStat / FLPBonusPending / TOptional reporté (BUILD COMMUN-6) ; lecture : probable Structures C++ simples hors USTRUCT, membres non UPROPERTY dans un UCLASS : usage permis ; generated.h en dernier include (.h:42) ; Misc/Optional.h inclus (.h:39)
VAL-2 pas de C4456 / C4458 / C4996 ; FCeil (UE_INL_API) se lie lecture : PASS-STATIC probable ; édition de liens reporté (BUILD) Aucun nom local ne masque un membre (membres TickHandle, Rng, LastCounts, Pending, Warned ; paramètre InRng ; boucles sans imbrication du même nom) ; FCeil : KismetMathLibrary.h:796, UE_INL_API = vide si KISMET_MATH_INLINE_ENABLED (corps .inl inclus :4581-4583), sinon ENGINE_API (:181-183) : lié dans les deux cas ; module Engine en dépendance publique (LifePlay.Build.cs:17)
VAL-3 FMemory_Alloca_Aligned(ParmsSize, Alignment) sans avertissement lecture : probable ; reporté (BUILD) Macro GenericPlatformMemory.h:221 : (Size==0) ? 0 : (Alignment <= 16 ? FMemory_Alloca(Size) : (void*)…) ; arguments : deux int32 simples (pas d'effet d'évaluation double, pas de problème de parenthèses) ; appelée dans le cadre de l'appelant (.cpp:558, 593, 628), jamais dans FScopedParms ; le précédent (LPDirectControlSubsystem.cpp:426) utilise FMemory_Alloca sans alignement : la variante alignée est nouvelle dans le module
VAL-4 table 20 clés / 20 listes ; RewardChange ; Pick PASS-STATIC Voir § 3, lignes C2, C3, C4
VAL-5 aucun widget créé PASS (Grep) Grep UUserWidget|SNew|AddViewportWidgetContent|CreateWidget|GEngine|GetWorld dans les deux fichiers : aucune correspondance (seul SaveConfig apparaît, dans le commentaire .h:28). Les avertissements Bonus : … ne comptent pas comme lignes de récompense : le motif de récompense de 7.7 est <stat> <±valeur> ; réserve : LogStats -Pattern 'Bonus :' compte aussi avertissements et lignes réglage (E8), à filtrer à la lecture
VAL-6 journal de démarrage : 1 contrôle formule OK, 0 Error, 1 réglage … faux reporté (J1, journal de jeu) ; lecture : PASS-STATIC Initialize (.cpp:175-194) émet exactement une ligne OK ou Error, puis une ligne réglage ; valeurs recalculées à la main (§ 3, C5) : la formule est juste, donc OK attendu. Réserve : un ULPBonusRewardSubsystem par UGameInstance ; en éditeur, un par session PIE : plusieurs lignes possibles, normales
VAL-7 pas d'avertissement pas de propriete … / signature inattendue … reporté (J1) ; incertain Types non lus chez nous : CurrentTags (tableau de chaînes : estimé, voir D2), Name_First, RNG (VAL-8). Le code avertit une fois par cause et abandonne sans plantage (§ 3, C6)
VAL-8 Person.QueryStat.RNG booléen incertain, reporté à la compilation / en jeu L6f_dump_Person.txt:25 : RNG -> VariableSet_1.RngActual, type non porté par le dump. Indice : L6f_dump_GI.txt:23552 appelle QueryStat avec RNG = 'false' (littéral booléen d'un autre sous-graphe), donc probablement booléen. Si faux : QueryStat avertit une fois (.cpp:584-589) et aucune récompense n'est appliquée (jamais de plantage)
VAL-9 IsInterestedIn sans effet de bord ; ordre WhoIsInterested = PNJ PASS-STATIC L6f_dump_GI.txt:23421-23503 lu en entier : lectures de IsMale, Genital (de WhoInterests), Interested_Men/Women/Trans (de WhoIsInterested), NPCsRespectPlayerSex, PlayerCharacter ; variable InterestedToReturn positionnée à des constantes, retour par FunctionResult ; aucune écriture sur GI ni sur Person (seul l'ensemble InterestedToReturn, variable locale à la fonction, estimé). Ordre : les préférences (Interested_*) sont lues sur WhoIsInterested, le sexe/genre sur WhoInterests : « le PNJ s'intéresse au joueur » = (Person, Player), ordre du code (.cpp:520). Branche K2Node_CallFunction_34711 (appel récursif inversé) : sortie non reliée à l'exécution principale (nœud orphelin de la lecture ; non tracé jusqu'au bout)
VAL-10 journal J1 par orgasme, valeur conforme reporté (J1) Critère 7.7 ; la valeur suit la formule vérifiée en C5
VAL-11 désactivation en jeu empaqueté (config = Game) reporté (J1) ; incertain Voir § 6 case 3 : lecture du moteur non aboutie (aucune occurrence de {SAVED}/Config dans Core\Private\Misc) ; seul DefaultGame.ini avant cuisson est établi comme voie sûre
VAL-12 règle commune ORG4 / ORG5 PASS-STATIC Voir § 3, C2 (dernière ligne) ; vérification en jeu reportée à J1 (V6)
VAL-13 git status = entrée + 2 ?? PASS Voir § 3, C1

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

# Contrôle Preuve Verdict
C1 Périmètre git -C 'D:/Game/LifePlay-master 5.8' status --porcelain -- Content Source Config → 11 M (Content/BPs/GI, PC, Person, Room.uasset ; Source/LifePlay/LPDebugSubsystem.cpp/.h, LPDirectControlSubsystem.cpp/.h, LPOutdoorRoomSubsystem.cpp/.h, LifePlay.cpp) et 6 ?? (LPBonusRewardSubsystem.cpp/.h, LPCameraModeSubsystem.cpp/.h, LPSaveRelaunch.cpp/.h) = état d'entrée de l'IMPL § 3 (11 M, 4 ??) + exactement les deux ?? de la fiche. Aucune ligne Config ; LifePlay.Build.cs absent de la sortie (inchangé) ; HEAD 0745917. Build.cs:17 : Core, CoreUObject, Engine en dépendance publique ; Slate/UMG non utilisés : suffisant PASS (l'attribution des 11 M à d'autres lots repose sur l'IMPL ; aucun n'est un fichier du lot)
C2 Conformité SPEC : table, tirage, H1, règle commune Table (.cpp:207-228, relue ligne à ligne contre SPEC § 1.2) : 20 clés dans l'ordre, tags identiques (ex. likes_oral 6 tags, likes_handjob 3, fitness / prone_to_orgasm- {Penetration, Foreplay, Cum}, masochist / likes_rough / masochist- {Aggressive, AggressiveFM}, clés 1, 3, 4 vides). Les offsets Cursor.uexp:4643-6408 ne sont pas rejoués (pas d'accès au désassembleur) : la table est comparée à la SPEC, non à l'asset de l'auteur. Tirage (Pick, .cpp:287-332) : mélange Fisher-Yates identique à KismetArrayLibrary.cpp:344-351 (RandRange(i, LastIndex) bornes incluses, RandomStream.h:209-214), SetNum(min(20,10)), filtre Overlaps(PositionTags, Entry.Tags, true) dans l'ordre de l'auteur (SPEC E6b : Overlaps(Tags.Strings, tags, true)), attractiontoplayer refusée si !bAttractionAllowed, sortie à 3 (NotEqual(countBR, 3)), - final retiré avec drapeau de signe ; condition attractiontoplayer (.cpp:488-525) : NON isPlayer, IsInterestedIn(Person, PlayerCharacter), SexPersons contient le joueur (SPEC E6c). Application : première récompense (Stats[0]), QueryStat(Stat,false,false).Value puis ModifyStat(Stat,Change,false,false) (.cpp:473-483, 596-597, 632-633), conforme à la décision Q-ORG5-1. Overlaps (.cpp:269-285) = L6f_dump_GI.txt:19622-19673 : IfEmptyThenTrue ET (len A = 0 OU len B = 0) → vrai ; sinon un élément de A dans B ; sinon faux. H1 : Poll compare Sex_OrgasmCounts à LastCounts : premier passage = mémorisation, hausse = 1 attente armée (une par hausse, remplacée si une autre arrive dans les 0,2 s), baisse = resynchronisation sans récompense, SexOn faux = mémoire vidée ; Person__EventGraph.txt:16118-16125 (incrément dans Cum) et :15908-15911 (remise à 0 avec l'énergie) cohérents. Règle commune : Endsex sans Cum n'incrémente pas le compteur donc 0 ligne ORG5 ; un incrément = au plus une attente = au plus une récompense appliquée. Toute personne : boucle sur tout SexPersons (PNJ compris), attractiontoplayer réservée aux PNJ PASS-STATIC
C3 Formule RewardChange (.cpp:232-241) Ordre : Abs → MapRangeClamped(0,100,0,1.9) → 2 - m → × 10 → FCeil → entier en réel → / 10 → × signe, identique à SPEC § 1.3 (Cursor.uexp:8339-8521) ; fonctions UKismetMathLibrary elles-mêmes (.h:796, 836), en double PASS-STATIC
C4 21 points de la formule, calculés à la main (sans exécution : aucun script permis par la fiche) v = ceil((2 - 1,9·x/100)·10)/10 : x = 0 → 20 → 2,0 ; 1 → 19,81 → 2,0 ; 5 → 19,05 → 2,0 ; 10 → 18,1 → 1,9 ; 20 → 16,2 → 1,7 ; 25 → 15,25 → 1,6 ; 30 → 14,3 → 1,5 ; 40 → 12,4 → 1,3 ; 45 → 11,45 → 1,2 ; 50 → 10,5 → 1,1 ; 55 → 9,55 → 1,0 ; 60 → 8,6 → 0,9 ; 70 → 6,7 → 0,7 ; 75 → 5,75 → 0,6 ; 80 → 4,8 → 0,5 ; 90 → 2,9 → 0,3 ; 95 → 1,95 → 0,2 ; 99 → 1,19 → 0,2 ; 100 → 1,9 exact, 2 − 1,9 = 0,10000000000000009 (soustraction exacte en IEEE double), × 10 = 1,0000000000000009 > 1 → ceil 2 → 0,2 ; 120 → fixé à 1,9 → 0,2 ; −30 → x
C5 CheckFormula (.cpp:243-267) 8 cas : 0, 10, 25, 50, 75, 90, 100 (+50 négatif) → 2,0 ; 1,9 ; 1,6 ; 1,1 ; 0,6 ; 0,3 ; 0,2 ; −1,1, tolérance 1e-9, valeurs égales à ma table (C4) PASS-STATIC
C6 Réflexion : noms, types, retours (contre dumps) QueryStat(Stat, WithoutBuff, RNG) → Value, Bonus (Person:20-29) : code exige Stat chaîne, WithoutBuff / RNG booléens, Value réel en sortie (.cpp:579-583), noms exacts ; ModifyStat(Stat, Change, DifficultyAdjusted, NoDisplay) → Value (Person:561-570) : code exige Stat, Change réel d'entrée, deux booléens (.cpp:614-618), noms exacts ; IsInterestedIn(WhoIsInterested, WhoInterests) → Interested (GI:23421-23443) : noms exacts, Interested booléen en sortie (.cpp:538-547). Paramètres cherchés par nom, pas par position : l'ordre et la taille de la structure viennent de Function->ParmsSize / GetMinAlignment (Class.h:790). Propriétés : SexOn (booléen), SexPersons (tableau d'objets), PlayerCharacter (objet), CurrentTags (tableau de chaînes), Sex_OrgasmCounts (entier, macro IncrementInt), isPlayer (booléen), Name_First (texte ou chaîne). Introuvable ou type inattendu : WarnOnce (un avertissement par cause), abandon ou clé refusée, aucun plantage. Le type du retour Bonus de QueryStat n'est pas contrôlé : sans importance (non lu) PASS-STATIC ; types réels non lus : voir D2
C7 Sûreté IsValid(Person) avant lecture (.cpp:375) et avant OnOrgasm (.cpp:443) ; TWeakObjectPtr pour l'attente et la mémoire des compteurs ; GetGameInstance() testé (.cpp:337, :462) ; ObjectProperty valeur nulle : IsValid(Player) (.cpp:510) ; Persons peut contenir des nuls : filtrés ; pas de monde requis ; pas de check, ensure, GEngine ni appel de débogage (Grep) donc rien de spécifique au Shipping ; Deinitialize retire la minuterie (.cpp:198). Paramètres de ProcessEvent : mémoire mise à zéro, initialisée puis détruite (FScopedParms, même séquence que LPDirectControlSubsystem.cpp:426-455). Coût : 10 Hz ; hors scène : 1 recherche de propriété par tick ; en scène : SexPersons + 1 recherche par personne + une copie de tableau d'objets ; IsInterestedIn (Blueprint) seulement à l'orgasme d'un PNJ avec le joueur présent ; négligeable (estimé) PASS-STATIC (D1 : chaîne Printf construite à chaque tick même quand l'avertissement est déjà émis)
C8 Compilation probable (lecture) Includes suffisants : Containers/Ticker.h, Math/RandomStream.h, Misc/Optional.h, Subsystems/GameInstanceSubsystem.h (.h) ; Engine/GameInstance.h, HAL/PlatformTime.h, Kismet/KismetMathLibrary.h, LifePlay.h, UObject/TextProperty.h (présent), UObject/UnrealType.h (.cpp). UCLASS + GENERATED_BODY présents sur les deux classes, LIFEPLAY_API sur les deux. LogLifePlay : LifePlay.h:9 DECLARE_LOG_CATEGORY_EXTERN(LogLifePlay, Log, All). FTSTicker::AddTicker(FTickerDelegate, float) Ticker.h:45, RemoveTicker statique :66 (appel par l'instance : comme LPColorGradeSubsystem.cpp:76, 81). IsA(TObjectPtr<UClass>) : le gabarit UObjectBaseUtility.h:633-639 convertit en const UClass*. FField::GetAuthoredName Field.h:903. Table : liste d'initialisation de FLPBonusStat (agrégat) : valide. Avertissements : aucun masquage C4456 / C4458 relevé ; conversions double / float explicites (static_cast<float>) ; aucun float vers double implicite dans UE_LOG (arguments double pour %f / %g, int32 pour %d) ; conditionnelle TEXT(", sortie") : TEXT("") de types const TCHAR[n] différents : décroissance en pointeur, admise. Fonctions de l'espace de noms nommé LPBonusReward : noms uniques dans le module (Grep BonusReward|FLPBonus|namespace LPBonus dans Source : seuls les deux fichiers) donc pas de collision en build unitaire PASS-STATIC (compilation : reportée à BUILD)
C9 Consignes Grep SaveConfig|TryUpdateDefaultConfigFile|GConfig|FFileHelper|Saved : une seule occurrence, dans le commentaire .h:28 ; UCLASS(config = Game) (.h:45) ; UPROPERTY(config) lecture seule par GetDefault ; aucune lecture de journal, aucune accroche cachée, aucun nœud Blueprint, aucune écriture de fichier ; Config\ inchangé (C1). En-tête .h:1-10 : origine « reconstruit d'après LifePlay 2023.04 de Vinfamy », licence MIT (SPDX-License-Identifier: MIT), renvoi à Licenses/Vinfamy_License.txt ; .cpp:1-4 : rappel d'origine et de licence. Le texte du fichier Licenses n'a pas été relu par moi (confiance à la SPEC § 4.2 R8 qui cite Licenses\Vinfamy_License.txt:1) PASS-STATIC
C10 CR / LF od -An -v -tx1 <f> | tr ' ' '\n' | grep -c '^0d$' : LPBonusRewardSubsystem.h CR=0 LF=119 first3= 2f 2f 20 ; LPBonusRewardSubsystem.cpp CR=0 LF=667 first3= 2f 2f 20 (pas de BOM). Comparaison : LPUserSettings.h i/lf w/lf (git ls-files --eol), mêmes trois premiers octets. Grep Users|C:\\ dans les deux fichiers : 0 PASS
C11 Fichiers non ASCII Le .cpp contient des accents dans cinq formats de journal (contrôle, réglage, désactivé, récompense), sans BOM : même pratique que LPDirectControlSubsystem.cpp:449 (« », // en tête sans BOM) déjà compilé en 5.8 (estimé, build antérieur du module) PASS-STATIC

4. Diff lu en entier

  • Deux fichiers neufs, non suivis par git (pas de diff contre STE-ORG5-avant : aucun fichier existant touché). Lus en entier : .h 119 lignes, .cpp 667 lignes (comptes od : LF = 119 et 667). Aucun fichier existant modifié par le lot (C1). Aucun script de modification : les fichiers portent l'horodatage de l'écriture de l'IMPL (2026-10-14, 01:25 et 01:26).
  • Ajouts hors SPEC relevés (tous annoncés dans l'IMPL E1-E10, aucun caché) : CheckFormula publique statique, FLPBonusPending, Poll, FirePending, AttractionAllowed, IsInterestedIn, PersonName, WarnOnce, ligne de journal réglage, huit cas de formule au lieu de sept.
  • Écarts IMPL à la SPEC relus : E1 (config Game, conforme à la consigne de Big Boss), E2 (niveau Log), E3 (attente survivant à la fin de scène : conforme à l'auteur), E4 (temps réel), E5-E6 (condition attractiontoplayer évaluée avant le tirage : équivalent car IsInterestedIn sans effet de bord, VAL-9), E7-E10 : acceptés, aucun ne contredit une décision de l'utilisateur.

5. Verdict

PASS-STATIC : aucun défaut bloquant. Deux défauts mineurs (D1, D2) et trois incertitudes reportées (VAL-7/8 types réels, VAL-11 désactivation empaquetée), à lever à la compilation (BUILD COMMUN-6) et en jeu (J1). ORG5 peut entrer dans le build COMMUN-6.

Défauts :

# Gravité Constat Correctif proposé (non appliqué)
D1 mineur Les appels WarnOnce(Key, FString::Printf(...)) construisent le message à chaque appel, même quand la clé est déjà dans Warned : si SexOn, SexPersons ou Sex_OrgasmCounts est introuvable, une chaîne est formatée à 10 Hz (.cpp:350, 366, 382, 402). Aucun effet fonctionnel, coût négligeable tester Warned.Contains(Key) avant de construire le message (macro ou surcharge WarnOnce(Key, TFunctionRef)), ou le laisser en l'état pour l'alpha
D2 mineur (risque fonctionnel faible) Le type de GI.CurrentTags n'est pas lu : le code exige TArray<FString> (ReadStrings, .cpp:162-172). Si le tableau est de FName ou de FText, ReadStrings échoue et aucun orgasme n'est récompensé (avertissement unique GI.CurrentTags). Indices pour des chaînes : GI__EventGraph_P2.txt:14305 compare à un littéral 'Vaginal', L6f_dump_GI.txt:21245 branche l'élément sur un SwitchString, la SPEC cite StringArray(Strings = GI.CurrentTags) À lever à J1 par l'absence d'avertissement GI.CurrentTags ; si présent : accepter FNameProperty / FTextProperty dans ReadStrings

6. Points à confirmer par l'utilisateur (cases)

  • 1. Build COMMUN-6 : code 0, module LifePlay recompilé, 0 erreur, 0 nouvel avertissement sur les deux fichiers (VAL-1, VAL-2, VAL-3).
  • 2. J1 : journal sans Bonus : pas de propriete … ni signature inattendue … (VAL-7, VAL-8, D2) ; par orgasme une ligne orgasme de puis une ligne récompense ou aucune récompense éligible (VAL-10) ; Endsex sans Cum : aucune ligne ORG5 (VAL-12).
  • 3. Désactivation d'un jeu empaqueté : décider où écrire bDisabled=True (DefaultGame.ini avant cuisson établi ; couche Saved\Config\…\Game.ini non établie) (VAL-11). Non vérifié ici : la recherche du chemin de couche dans Core\Private\Misc n'a donné aucune occurrence de {SAVED}/Config.
  • 4. Acceptation de D1 en l'état pour l'alpha.

Non rejoué par cette VAL : compilation et UHT, LPTestStringCompat, CompileAllBlueprints, comportement en jeu, offsets Cursor.uexp de la table, texte du fichier Licenses.

Tours : 11 / 40

Constats

  • Fichiers à commiter : A Docs/Migration/etat/ST/STE/STE-ORG5-V1-VAL.md (dépôt du jeu, branche ue5.8). Aucun autre fichier écrit ; aucun fichier source modifié.
  • À verser : lp-validate § 1 — pour un fichier neuf non suivi, git status --porcelain -- Content Source Config avant / après suffit comme contrôle de périmètre ; compter les CR par od -An -v -tx1 <f> | tr ' ' '\n' | grep -c '^0d$'. ue-cpp-build — FMemory_Alloca_Aligned (5.8, GenericPlatformMemory.h:221) renvoie 0 si Size == 0 : le tampon peut être nul pour une fonction sans paramètre.