LifePlay-Revival/Docs/Migration/etat/CAM/CAM-B2p-G-PC-IMPL.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

18 KiB
Raw Blame History

Fiche CAM-B2p-G-PC — Niveau N3 — Modèle prévu non précisé par la fiche | utilisé claude-opus-5-5 — Agent lp-mcp-bp — Skills sk-protocol, sk-change-safety, lp-mcp, lp-lot

CAM-B2p-G-PC-IMPL : C3 dans le cycle C du sexe (G-d) et panneau des positions (G-g), PC (2026-10-14)

Résultat : réussi en deux temps.

  • Premier passage : arrêt au premier refus, à l'étape 7 de G-g (13:48), sans contournement.
  • Reprise : sur l'option A, retenue par l'orchestrateur (amendement B2p-G-PC-a de la fiche). G-d et G-g ont été appliqués et relus conformes, puis compilés en mode strict sans diagnostic. Le PC a été enregistré seul.
  • MD5 : PC F45BE57A39D13D3EB19D0B543153AB0B → B07F16A9EC04CA297A8504F126D406E1 (2026-10-14 13:52) ; Room, GI et Person sont inchangés.
  • Éditeur : laissé ouvert (pid 18468).

Fiche : CAM-B2p-G-PC-FICHE.md, avec l'amendement B2p-G-PC-a (l. 69-79). Préfixe des nœuds : /Game/BPs/PC.PC:EventGraph.. Outils : editor_toolset.toolsets.asset.AssetTools (AT) et editor_toolset.toolsets.blueprint.BlueprintTools (BT). Un seul appel MCP par message : 46 appels au total, et 46 lignes Dispatching toolset tool au journal de l'éditeur.

1. Fichiers modifiés

  • Content/BPs/PC.uasset : enregistré par AT.save_assets ["/Game/BPs/PC"] (13:52) ; 3 404 786 → 3 424 059 octets.
  • Ce livrable.

1.1 Contrôles d'entrée

Contrôle Résultat
MD5 avant écriture (md5sum, 2026-10-14 ≈ 13:44) PC f45be57a39d13d3eb19d0b543153ab0b, Room 931387479e2d15f80bc4f36398907712, GI 32fc0a970ab194626e8dc07df3a9633d, Person 8668a47c627f7a5254910cf0ac33b12a : conformes ; PC revérifié avant la reprise : f45be57a…
Instantané D:\Game\LifePlay_Backup_5.5\CAM-B2p-G-PC\manifest.csv : "Content\BPs\PC.uasset","True","3404786","F45BE57A39D13D3EB19D0B543153AB0B","2026-10-14T13:42:48"
Journal éditeur au départ Saved\Logs\portage\CAM-B2p-G-PC-editeur_20261014-134248.log : 2 260 lignes, 43 lignes `error
Action de InputAction_3 type `Entrée

1.2 État attendu relu avant écriture (appels 2 et 3) : conforme

Nœud Lu
IfThenElse_23 Condition ← VariableGet_51 (`
IfThenElse_44 execute ← 23 then et CustomEvent_5 then [1] ; Condition ← CallFunction_139 ; then → VariableSet_25 (POVOn vrai) ; else → VariableSet_30 (POVOn faux)
IfThenElse_123 Condition ← VariableGet_233 (`
IfThenElse_15 Condition ← VariableGet_22 (`
CustomEvent_11 `AddEvent
InputAction_3 InputActionPause ; Pressed [0] → IfThenElse_63
IfThenElse_40 execute ← 63 else ; Condition ← CallFunction_125 ; then → CallFunction_277 ; else → IfThenElse_41
CallFunction_277 `

2. Écarts à la SPEC

  1. Refus à l'étape 7 (premier passage) : appel 33 :
    BT.create_node {type_id:"Variables|Sex|ObtenirSexOn"}
    → The node could not be created / Variables|Sex|ObtenirSexOn does not exist
    
    • Ce type n'existe que sous contexte : find_node_types ne le rend qu'avec context_pins = la sortie d'un Get GI.
    • Or create_node transmet un contexte vide : create_node_from_name(type_id, pos, [], declaring_class), dans D:\Game\Launcher\Engine\UE_5.8\Engine\Plugins\Experimental\Toolsets\EditorToolset\Content\Python\editor_toolset\toolsets\blueprint.py:912.
    • J'ai arrêté. L'orchestrateur a retenu l'option A (amendement B2p-G-PC-a).
    • Conséquence : la Condition de S est prise sur le getter existant VariableGet_22, et le Get GI VariableGet_387, créé pour rien, a été supprimé.
  2. Vérification des types : un seul find_node_types par type, juste avant le premier create_node de ce type. Les créations suivantes du même type ne l'ont pas refait : Branche ×3 (appel 6), DéfinirSexC3 ×2 (appel 5).
  3. Contrôles groupés : les nœuds créés ont été contrôlés par des get_node_infos groupés (appels 14 et 34), toujours avant tout lien vers eux.
  4. Ligne Warning au journal de l'éditeur : une seule, due au refus de l'appel 33. Rien de nouveau depuis.
  5. delete_node et relecture : après delete_node, get_node_infos résout encore VariableGet_387 par son chemin. C'est attendu : UEdGraph::RemoveNode retire le nœud du tableau Nodes sans détruire l'objet (Engine\Source\Runtime\Engine\Private\EdGraph\EdGraph.cpp:261-281). L'absence dans le graphe est donc prouvée autrement : par find_nodes, qui parcourt list_all_nodes (blueprint.py:709), voir § Reprise.

3. Instantané, appels et relectures

  • Instantané : lot CAM-B2p-G-PC, D:\Game\LifePlay_Backup_5.5\CAM-B2p-G-PC\manifest.csv (PC F45BE57A…).
  • Retour arrière : .\Tools\Restore.ps1 -Lot CAM-B2p-G-PC -Only Content\BPs\PC.uasset, éditeur fermé. Il est proposé, pas lancé.

3.1 Appels MCP (46, un à la fois)

# Outil Objet Retour
1 AT.load_asset /Game/BPs/PC /Game/BPs/PC.PC
2-3 BT.get_node_infos état attendu (16 nœuds) conforme
4 BT.add_variable {blueprint:/Game/BPs/PC.PC, name:"SexC3", type_name:"bool"} null
5 BT.find_node_types SexC3 `Variables
6 BT.find_node_types `ContrôleDeFlux Branche`
7-10 BT.create_node Branche, ObtenirSexC3, DéfinirSexC3, Branche IfThenElse_132, VariableGet_385, VariableSet_39, IfThenElse_133
11 BT.find_node_types POVOn `Variables
12-13 BT.create_node ObtenirPOVOn, DéfinirSexC3 VariableGet_386, VariableSet_58
14 BT.get_node_infos 132, 385, 39, 133, 386, 58 conformes, aucun lien
15 BT.set_pin_value 58 [1] = true null
16-23 BT.connect_pins 8 liens G-d null ×8
24 BT.get_node_infos relecture G-d conforme
25-26 BT.break_pins 123.then ↛ 35, 15.then ↛ 10 null ×2
27 BT.find_node_types LeftMouseSexOn `Appelerunefonction
28-29 BT.create_node appel LeftMouseSexOn, Branche CallFunction_408, IfThenElse_134
30 BT.find_node_types `Variables Pardéfaut
31 BT.create_node ObtenirGI VariableGet_387 (supprimé à l'appel 37)
32 BT.find_node_types SexOn, contexte = sortie de 387 `Variables
33 BT.create_node `Variables Sex
34 BT.get_node_infos état G-g à l'arrêt 408, 134, 387 sans lien ; 40 → 277 intact
35 BT.get_node_infos reprise : 22, 134, 387, 408, 40, 277 conforme à l'attendu de la reprise
36 BT.connect_pins 22 [O0] → 134 [I1] null
37 BT.delete_node VariableGet_387 null
38-40 BT.connect_pins 40 [O0] → 134 [I0] ; 134 [O1] → 277 [I0] ; 134 [O0] → 408 [I0] null ×3
41 BT.get_node_infos relecture finale, 19 nœuds conforme (§ 3.3)
42 BT.get_node_infos VariableGet_387 objet encore résolu, sans lien (§ 2.5)
43 BT.find_nodes {title:"GI", node_class:K2Node_VariableGet} 111 nœuds, VariableGet_387 absent (6044, 2873, 232 et 50 présents)
44 AT.is_dirty /Game/BPs/PC true
45 BT.compile_blueprint {blueprint:/Game/BPs/PC.PC, warnings_as_errors:true} null ; aucune ligne Error/Warning
46 AT.save_assets ["/Game/BPs/PC"] true ; une ligne Saving Package: /Game/BPs/PC

3.2 Variable, nœuds créés, liens (PinID {direction, index_id, node})

Variable de membre SexC3

  • Type : booléen. Défaut : faux, valeur par défaut du type, non relue sur le CDO.
  • Nœuds Get et Set : |GetSexC3 et |SetSexC3, sans broche cible (self = le PC).

Nœuds créés et gardés (8)

Nœud Rôle
K2Node_IfThenElse_132 branche A
K2Node_VariableGet_385 Get SexC3
K2Node_VariableSet_39 S0, SexC3 = faux
K2Node_IfThenElse_133 branche B
K2Node_VariableGet_386 Get POVOn, self
K2Node_VariableSet_58 S1, SexC3 = vrai
K2Node_IfThenElse_134 branche S
K2Node_CallFunction_408 appel `

Nœud créé puis supprimé : K2Node_VariableGet_387 (Get GI).

Liens G-d

  1. VariableGet_385 {EGPD_Output,0} → IfThenElse_132 {EGPD_Input,1}
  2. IfThenElse_23 {EGPD_Output,0} → IfThenElse_132 {EGPD_Input,0} (remplace 23.then → 44)
  3. IfThenElse_132 {EGPD_Output,0} → VariableSet_39 {EGPD_Input,0}
  4. VariableSet_39 {EGPD_Output,0} → IfThenElse_44 {EGPD_Input,0}
  5. IfThenElse_132 {EGPD_Output,1} → IfThenElse_133 {EGPD_Input,0}
  6. VariableGet_386 {EGPD_Output,0} → IfThenElse_133 {EGPD_Input,1}
  7. IfThenElse_133 {EGPD_Output,0} → IfThenElse_44 {EGPD_Input,0}
  8. IfThenElse_133 {EGPD_Output,1} → VariableSet_58 {EGPD_Input,0}

Valeurs : VariableSet_58 {EGPD_Input,1} = true ; VariableSet_39 {EGPD_Input,1} = false.

Coupures G-g

  • IfThenElse_123 {EGPD_Output,0} ↛ CallFunction_35 {EGPD_Input,0}
  • IfThenElse_15 {EGPD_Output,0} ↛ IfThenElse_10 {EGPD_Input,0}

Liens G-g

  1. VariableGet_22 {EGPD_Output,0} → IfThenElse_134 {EGPD_Input,1}. Ce lien s'ajoute à 22 → 15 [1].
  2. IfThenElse_40 {EGPD_Output,0} → IfThenElse_134 {EGPD_Input,0}. Il remplace 40 → 277.
  3. IfThenElse_134 {EGPD_Output,1} → CallFunction_277 {EGPD_Input,0}
  4. IfThenElse_134 {EGPD_Output,0} → CallFunction_408 {EGPD_Input,0}

3.3 Relecture finale (appel 41) : conforme

Nœud Relu
IfThenElse_23 execute ← CallFunction_211 ; Condition ← VariableGet_51 ; then → 132 ; else → 131
IfThenElse_44 execute ← CustomEvent_5 [1], VariableSet_39 [0], IfThenElse_133 [0] ; Condition ← CallFunction_139 ; then → VariableSet_25 ; else → VariableSet_30
CustomEvent_5 SwitchCamera ; then [1] → 44 ; OutputDelegate → CallFunction_198 [1]
IfThenElse_132 (A) execute ← 23 ; Condition ← 385 ; then → 39 ; else → 133
IfThenElse_133 (B) execute ← 132 else ; Condition ← 386 ; then → 44 ; else → 58
VariableGet_385 / 386 SexC3 → 132 [1] / POVOn → 133 [1]
VariableSet_39 (S0) execute ← 132 then ; SexC3 = false ; then → 44
VariableSet_58 (S1) execute ← 133 else ; SexC3 = true ; then vide
IfThenElse_123 then vide ; else → IfThenElse_0 ; execute ← IfThenElse_110 ; Condition ← VariableGet_233
IfThenElse_15 then vide ; else → CallFunction_160 ; execute ← IfThenElse_19 ; Condition ← VariableGet_22
IfThenElse_10 execute ← CustomEvent_11 [1] seul ; then → CallFunction_1524 ; else → CallFunction_154 ; Condition ← CallFunction_79
CallFunction_35 execute vide (orphelin, voulu par l'étape 5 ; nœud d'origine, pas créé ici)
IfThenElse_40 execute ← 63 else ; Condition ← CallFunction_125 ; then → 134 ; else → IfThenElse_41
CallFunction_277 execute ← 134 else ; then → VariableSet_0
IfThenElse_63 execute ← InputAction_3 ; Condition ← VariableGet_175 ; then vide ; else → 40 (non touché ; son « then vide » n'a pas été relu avant écriture)
VariableGet_22 self ← VariableGet_6044 ; SexOn → 15 [1] et 134 [1]
IfThenElse_134 (S) execute ← 40 then ; Condition ← 22 ; then → 408 ; else → 277
CallFunction_408 execute ← 134 then ; then vide ; self non relié

Aucun autre lien modifié parmi les nœuds relus. Aucun nœud que j'ai créé n'est orphelin : 387 est absent du graphe, selon l'appel 43.

4. Ce qui n'a pas été fait

  • La preuve en jeu (build empaqueté + LogStats) et la VAL (V5 et V6), éditeur fermé : elles ne relèvent pas de cette fiche.
  • Le défaut de SexC3 sur le CDO n'a pas été relu.

5. Points à confirmer en VAL

  • V5 : diff du dump du PC contre CAM-B2kmn-VAL_LPDumpFunction_20261014-011816.txt. Seules différences attendues :
    • variable SexC3 ;
    • les 8 nœuds du § 3.2 (sans VariableGet_387) ;
    • coupures 123.then ↛ 35 et 15.then ↛ 10 ;
    • les 8 liens G-d et les 4 liens G-g du § 3.2.
  • IfThenElse_63.then : vide après écriture, à comparer au dump de référence (non relu avant écriture, non touché).
  • CallFunction_35 : exécution non reliée après la coupure. Attendu : aucun diagnostic (V6).
  • Défaut de SexC3 = faux.
  • V6 : CompileAllBlueprints = référence.
  • La taille du PC croît de 19 273 octets. Que l'objet supprimé VariableGet_387 ait été écrit ou non comme export orphelin reste incertain : il n'est plus dans Nodes, et la suppression suit le même chemin que dans l'éditeur. Sans effet attendu ; le dump ne le montrerait pas.
  • Comportement en jeu, preuve par le build empaqueté :
    • Scene → C → C3 → C → POV 1 → … → Scene ;
    • pendant le sexe, Espace bascule le panneau des positions au lieu de mettre en pause ;
    • les clics courts gauche et droit ne le basculent plus ;
    • hors sexe, Espace met toujours en pause.

6. Fichiers à commiter (dépôt du jeu, branche ue5.8)

  • M Content/BPs/PC.uasset
  • A Docs/Migration/etat/CAM/CAM-B2p-G-PC-IMPL.md

Mesuré

$ md5sum Content/BPs/PC.uasset Content/BPs/Room.uasset Content/BPs/GI.uasset Content/BPs/Person.uasset   (avant, ≈ 13:44)
f45be57a39d13d3eb19d0b543153ab0b *Content/BPs/PC.uasset
931387479e2d15f80bc4f36398907712 *Content/BPs/Room.uasset
32fc0a970ab194626e8dc07df3a9633d *Content/BPs/GI.uasset
8668a47c627f7a5254910cf0ac33b12a *Content/BPs/Person.uasset
$ md5sum (mêmes fichiers, après save_assets, 2026-10-14 13:52) ; ls -l Content/BPs/PC.uasset
b07f16a9ec04ca297a8504f126d406e1 *Content/BPs/PC.uasset
931387479e2d15f80bc4f36398907712 *Content/BPs/Room.uasset
32fc0a970ab194626e8dc07df3a9633d *Content/BPs/GI.uasset
8668a47c627f7a5254910cf0ac33b12a *Content/BPs/Person.uasset
-rw-r--r-- 1 <compte> 197609 3424059 Oct 14 13:52 Content/BPs/PC.uasset
$ wc -l ; grep -c "Dispatching toolset tool" ; grep -n "Saving Package"   (journal de l'éditeur, après l'appel 46)
2407 Saved/Logs/portage/CAM-B2p-G-PC-editeur_20261014-134248.log
46
2378:[2026.10.14-11.52.07:434][589]LogFileHelpers: Saving Package: /Game/BPs/PC
$ tail -n +2348 | grep -nE "Error|Warning|error|warning"   (depuis la reprise : compilation et enregistrement)
(aucune ligne)
$ extrait de la compilation
[2026.10.14-11.51.55:967][138]LogBlueprint: Compiling Blueprint '/Game/BPs/PC.PC'
[2026.10.14-11.51.57:058][138]LogUObjectHash: Compacting FUObjectHashTables data took   4.59ms
$ tail -n +2261 | grep -nE "Error|Warning|error|warning"   (lignes nouvelles de toute la fiche, extrait utile)
83:[2026.10.14-11.47.28:843][104]LogScript: Warning: The node could not be created / Variables|Sex|ObtenirSexOn does not exist
$ git status --short -- Content/BPs/
 M Content/BPs/GI.uasset
 M Content/BPs/PC.uasset
 M Content/BPs/Person.uasset
 M Content/BPs/Room.uasset

Lecture de ces sorties :

  • GI, Person et Room étaient déjà marqués M au début de la session. Leurs MD5 n'ont pas bougé : ils n'ont pas été modifiés ici.
  • Les 4 lignes LogModelContextProtocol: Error de 11:44:31-32 (Unknown session id, server/discover) viennent de la poignée de main du client MCP. Elles précèdent le premier appel.

Reprise (amendement B2p-G-PC-a, 2026-10-14 13:49-13:52)

Étape de la consigne Fait Preuve
1. Relecture de 22, 134, 387, 408, 40, 277 conforme : 22 → 15 [1] seul ; 387, 134, 408 sans lien ; 40.then → 277 appel 35
2. 22.SexOn → 134.Condition fait appel 36, relu (41)
3. delete_node 387 fait appel 37 ; absent de find_nodes (43)
4. 40 → 134 (remplace 40 → 277) ; 134.else → 277 ; 134.then → 408 fait appels 38-40, relus (41)
5. Relecture complète (19 nœuds) conforme appel 41, § 3.3
6. is_dirty ; compilation stricte ; enregistrement du PC seul ; une seule ligne Saving Package ; MD5 true ; null, sans diagnostic ; true ; ligne 2378 seule ; PC b07f16a9…, les trois autres inchangés appels 44-46, § Mesuré

Tours : 63 / 60. La reprise n'a pas reçu de nouveau budget écrit : 44 tours au premier passage, 19 à la reprise, sous le plafond de 75.

Constats

  • Get d'un membre d'une autre classe : find_node_types avec context_pins rend des type_id de membres d'une autre classe (ici Variables|Sex|ObtenirSexOn de GI) que create_node ne sait pas créer (contexte vide, blueprint.py:912). Pour un tel Get, la fiche doit prévoir la reprise d'un getter existant, qui marche : une sortie de données alimente plusieurs entrées.
  • Preuve d'une suppression : après delete_node, get_node_infos résout encore le nœud par son chemin, car RemoveNode ne le retire que de Nodes. La preuve d'absence passe par find_nodes, filtré par titre et classe (node_class:{refPath:"/Script/BlueprintGraph.K2Node_VariableGet"} accepté).
  • Variable ajoutée : add_variable rend null ; find_node_types "<Var>" (Get et Set) prouve qu'elle existe.
  • Types vérifiés :
    • appel d'un événement personnalisé du PC : Appelerunefonction|<Nom> ;
    • AT.is_dirty {asset_path:"/Game/BPs/PC"} rend true / false.