LifePlay-Revival/Docs/Migration/etat/CAM/CAM-B2b-IMPL-F7.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

17 KiB
Raw Blame History

Fiche CAM-B2b-F7 — Niveau N3 — Modèle prévu opus | utilisé claude-opus-5-5 (Opus 5.5) — Agent lp-mcp-bp — Skills sk-protocol, sk-change-safety, lp-mcp, lp-lot

CAM-B2b-F7-IMPL : pilotage de C2 par DownUp (B2b-6, fin), relecture globale, compilation stricte, enregistrement de Room (2026-10-13)

Consignes : CAM-B2b-FICHES.md § « Rubriques communes » (l. 23-63) et § « F7 » (l. 134-142). Seul DownUp restait à faire : RotateCamera a été traité en F6b. SPEC : CAM-SPEC.md § « CAM-B2b », ligne B2b-6 (l. 380). Modèle suivi : CAM-B2b-IMPL-F6b.md, partie RotateCamera (même schéma).

Contexte : UE-GO de Big Boss B2b du 2026-10-13, cité par l'orchestrateur. Éditeur headless PID 10708, port 8000, connexion unreal-mcp partagée (MCPA-T1). Room chargé, F1 à F6b en mémoire. Un seul call_tool par message. 24 appels MCP :

  • 3 get_node_infos, 6 create_node, 1 break_pins, 9 connect_pins et 3 set_pin_value ;
  • 1 compile_blueprint et 1 save_assets.

Aucun delete_node, write_graph_dsl ni ProgrammaticToolset. Aucune écriture par HyperAIStudio.

1. Fichiers modifiés

  • Content/BPs/Room.uasset : enregistré par save_assets (§ 1.8). Il contient F1 à F7. MD5 avant a5fa970e… (= instantané) ; après e0517c63541f249bd9dbda5c39815ba5. Taille passée de 6 060 745 à 6 318 319 octets.
  • Graphe /Game/BPs/Room.Room:EventGraph, événement DownUp (CE8, x 5520, y 3952) : nœuds neufs en x 5700-6550, y 4250-4550.
  • Aucun autre asset n'a été ouvert en écriture ni enregistré (§ 3).

1.1 Lecture avant écriture (get_node_infos groupé, 3 nœuds existants)

La lecture est conforme aux faits de la fiche :

  • K2Node_CustomEvent_8 (AddEvent|Custom|DownUp) :
    • then out 1 → IfThenElse_8.execute 0 ;
    • AxisValue out 2 (Float (double-précision)) → CommutativeAssociativeBinaryOperator_3.0, _5.0 et _8.0.
  • K2Node_IfThenElse_8 : execute ← CE8.1 ; Condition ← CommutativeAssociativeBinaryOperator_17.0 ; then 0 → IfThenElse_17.0 ; else 1 libre.
  • K2Node_PromotableOperator_8 (Utilitaires|Equal(Object)) : A ← CallFunction_439.0, B ← VariableGet_268.0 ; out 0 (Booléen) → IfThenElse_91.1, _96.1, _97.1, _98.1 et _99.1.

1.2 Nœuds créés (préfixe refPath : /Game/BPs/Room.Room:EventGraph.)

Rôle refPath (suffixe) type_id demandé → relu Broches relues Position
Branche C2 K2Node_IfThenElse_100 Utilitaires|ContrôleDeFlux|Branche → idem execute 0, Condition 1 ; then 0, else 1 5750, 4250
Obtenir C2Height K2Node_VariableGet_296 Variables|Pardéfaut|ObtenirC2Height → |GetC2Height C2Height out 0 (double) 5700, 4450
AxisValue × 3 K2Node_PromotableOperator_35 Utilitaires|Opérateurs|Multiplier → Math|Flottant|float*float A 0, B 1 ; out 0 (double) 5900, 4550
C2Height + produit K2Node_PromotableOperator_36 Utilitaires|Opérateurs|Ajouter → Math|Flottant|float+float A 0, B 1 ; out 0 (double) 6100, 4450
Clamp K2Node_CallFunction_511 Math|Flottant|Clamp(Float) → idem Value 0, Min 1, Max 2 ; ReturnValue out 0 (double) 6300, 4500
Définir C2Height K2Node_VariableSet_71 Variables|Pardéfaut|DéfinirC2Height → |SetC2Height execute 0, C2Height 1 ; then 0, Output_Get 1 6550, 4400

Comme en F3 à F6b, les opérateurs naissent avec un type_id trompeur et des broches Caractère de remplacement :

  • PO35 : Utilitaires|Gestiondutemps|Seconds*FrameRate ;
  • PO36 : …|FrameNumber+Int.

À la relecture finale, ils sont typés float*float et float+float, en double précision. À la création, le Clamp avait Min 0.0 et Max 1.0. PO8 est réutilisé sans copie (nœud pur).

1.3 Lien coupé (break_pins, 1, {"returnValue":null})

# Sortie Entrée
C1 CustomEvent_8.then 1 IfThenElse_8.execute 0

Aucun autre lien n'a été coupé, et rien d'autre n'a été touché dans DownUp.

1.4 Liens faits (connect_pins, 9, tous {"returnValue":null})

# Sortie Entrée
L1 CustomEvent_8.then 1 IfThenElse_100.execute 0
L2 IfThenElse_100.else 1 IfThenElse_8.execute 0
L3 PromotableOperator_8.0 IfThenElse_100.Condition 1
L4 CustomEvent_8.AxisValue 2 PromotableOperator_35.A 0
L5 VariableGet_296.0 (C2Height) PromotableOperator_36.A 0
L6 PromotableOperator_35.0 PromotableOperator_36.B 1
L7 PromotableOperator_36.0 CallFunction_511.Value 0
L8 CallFunction_511.0 VariableSet_71.C2Height 1
L9 IfThenElse_100.then 0 VariableSet_71.execute 0

VariableSet_71.then reste libre : c'est la fin de l'événement côté C2, comme dans F6a et F6b.

1.5 Valeurs (set_pin_value, 3, tous {"returnValue":null}, relues)

Broche Avant (relu à la création) Après (relu)
PromotableOperator_35.B 1 (neuf, "", joker) 3.0 (Float (double-précision))
CallFunction_511.Min 1 0.0 -40.0
CallFunction_511.Max 2 1.0 150.0

PO35.B a été posé après L4, qui type l'opérateur. La Condition de la Branche 100 garde sa valeur par défaut true, sans effet puisque la broche est liée (L3).

1.6 Relecture globale (get_node_infos groupé, 23 nœuds)

Nœuds relus : les 6 nœuds créés, IfThenElse_8, PO8, CE1, CE4, CE8, CE19, CE55, CallFunction_459, _467, _474, _499, _505, VariableSet_61, _62, _66, CustomEvent_49 et CallFunction_494. Chaque lien a été comparé au rapport de la fiche qui l'a posé :

DownUp (F7)

  • Les 9 liens L1 à L9 apparaissent des deux côtés, et les 3 valeurs sont relues.
  • IfThenElse_8 : execute ← IfThenElse_100.1 ; Condition ← CommutativeAssociativeBinaryOperator_17 ; then → IfThenElse_17 ; else libre.
  • CE8.AxisValue → CABO_3.0, _5.0, _8.0, plus PO35.0.

PO8 : sortie → IfThenElse_91, _96, _97, _98, _99 et _100 (6 branches).

Événements de déplacement (F6a, F6b)

  • CE1 CircleCamera : then → IfThenElse_96 ; DeltaSeconds → CABO_26.1, _16.1, _27.1, plus PO28.1 (F6a L1, L5).
  • CE4 LeftRight : then → IfThenElse_97 ; AxisValue → CABO_47.0, _13.0, _24.0, plus PO29.0 (F6a L8, L11).
  • CE19 RotateCamera : then → IfThenElse_99 ; DeltaSeconds → CABO_45.1, _12.1, _15.1, plus PO33.0 (F6b L10, L13).
  • CE55 ScrollDownUp : then → IfThenElse_98 ; Values → CABO_2.0, CF_26.2, CABO_20.0, _10.0, _22.0, plus PO31.0 (F6b L1, L4).

ComputeC2Target et ComputeRoomBox (F2, F3, F5)

  • 494 |ComputeRoomBox : execute ← CE47.1 ; then → 459.0 (F3 L1, L2).
  • 459 (trace de Desired) :
    • execute ← 494, then → IfThenElse_90, ReturnValue → IfThenElse_90.1, OutHit → 460 ;
    • Start ← 455, End ← 495 (F3 L6), ActorsToIgnore ← MakeArray_5 ;
    • Radius 20.0 (F3), TraceChannel TraceTypeQuery2.
  • VariableSet_61 : execute ← IfThenElse_90.0 ; C2Target ← 496 (F3 L11) ; then → IfThenElse_95 (F5 L1).
  • VariableSet_62 : execute ← IfThenElse_90.1 ; C2Target ← 495 (F3 L7) ; then → IfThenElse_95 (F5 L2).
  • 505 (trace du repli) :
    • execute ← IfThenElse_95.0, then → VariableSet_66, OutHit → 506, ReturnValue → 507.2 ;
    • Start ← 455, End ← 504, ActorsToIgnore ← MakeArray_5 ;
    • Radius 20.0, TraceTypeQuery2 (F5 L14 à L18, L24, L29).
  • VariableSet_66 : execute ← 505 ; C2Target ← 508 (F5 L28) ; then libre.
  • CE49 ComputeRoomBox : then → VariableSet_64 (F2 L21).

Poursuite (F4)

  • 467 |ComputeC2Target : execute ← IfThenElse_93.1 ; then → 499 (F4 L1).
  • 499 (trace de la poursuite) :
    • execute ← 467, then → 474, OutHit → 500, ReturnValue → 501.2 ;
    • Start ← 455, End ← 468, ActorsToIgnore ← MakeArray_5 ;
    • Radius 20.0, TraceTypeQuery2 (F4 L1 à L6, L12).
  • 474 : execute ← 499 (F4 L2) ; self ← VariableGet_268 ; NewLocation ← 502 Safe (F4 L16) ; NewRotation ← 469 ; bSweep false.

Aucune divergence. Chaîne obtenue pour DownUp : CE8 → Branche 100 (GetViewTarget(PC) == CamRoom).

  • Vrai : Définir C2Height (71) := Clamp(C2Height + AxisValue × 3, −40, 150), puis fin.
  • Faux : IfThenElse_8, chaîne d'origine inchangée.

1.7 Compilation

compile_blueprint {blueprint:{refPath:"/Game/BPs/Room.Room"}, warnings_as_errors:true} a renvoyé {"returnValue":null}, sans exception : c'est le critère de la fiche.

Deux contrôles n'ont pas été faits :

  • hyper_blueprint_debug_inspect, absent du serveur le 2026-10-10 (mémoire unreal-mcp-reconnect, non revérifié) ;
  • le journal de l'éditeur, faute du chemin -abslog : il n'est pas dans Saved\Logs, dont la fin de la liste ne montre que UnrealPak*.log, cef3.log et portage.

1.8 Enregistrement

editor_toolset.toolsets.asset.AssetTools / save_assets {"asset_paths":["/Game/BPs/Room"]} a renvoyé {"returnValue":true}. Il a été appelé une seule fois, pour Room seul, après la compilation stricte.

2. Écarts à la SPEC

  • Aucun écart de câblage. La ligne B2b-6 (CAM-SPEC.md:380) et la fiche (CAM-B2b-FICHES.md:137) sont réalisées telles quelles pour DownUp. Seul le lien CE8.then → IfThenElse_8 a été coupé.
  • Formule : C2Height := Clamp(C2Height + AxisValue × 3, −40, 150). A de PO36 = C2Height, B = produit, relu.
  • Typage : AxisValue est en double précision, comme Clamp(Float) : aucune conversion implicite.
  • Relecture : la liste de la fiche (l. 139) a été élargie, à la demande de l'orchestrateur, à 499, 505, VariableSet_66, CE49 et 494, plus IfThenElse_8 et PO8.
  • Garde Accessed None : aucune IsValid ajoutée, car ni la fiche ni la SPEC n'en demandent, et les nœuds neufs ne lisent que des flottants. PO8 (→ 439 GetViewTarget, self ← VariableGet_262 ; → VariableGet_268 CamRoom) est désormais évalué à chaque appel de DownUp. Même réserve qu'en F6a et F6b. PO8 alimente maintenant 6 branches.
  • Comportement : quand C2 n'est pas la vue, il est identique à l'ancien (else → IfThenElse_8). Quand C2 est la vue, la chaîne d'origine n'est plus exécutée : c'est le changement voulu par la SPEC.
  • Positions : choisies près de CE8, sans prescription (cosmétique). Elles chevauchent visuellement les nœuds CircleCamera de F6a (x 5650-6050, y 4250-4450), sans effet sur le graphe.

3. Instantané

L'orchestrateur l'a fait avant F1 (D:\Game\LifePlay_Backup_5.5\CAM-B2b\) ; il n'a pas été refait, selon la consigne. Mesures avant et après save_assets :

date -Iseconds; md5sum "/d/Game/LifePlay-master 5.8/Content/BPs/Room.uasset"; grep -i "Room.uasset" "/d/Game/LifePlay_Backup_5.5/CAM-B2b/manifest.csv"; git -C "D:\Game\LifePlay-master 5.8" status --short -- Content Source Config
2026-10-13T16:10:25+02:00
a5fa970e821dc2d0d9bf220fd43b9de6 */d/Game/LifePlay-master 5.8/Content/BPs/Room.uasset
"Content\BPs\Room.uasset","True","6060745","A5FA970E821DC2D0D9BF220FD43B9DE6","2026-10-13T15:25:45"
 M Content/BPs/Person.uasset
 M Content/BPs/Room.uasset
 M Source/LifePlay/LPDebugSubsystem.cpp
 M Source/LifePlay/LPDebugSubsystem.h

(save_assets → true)

date -Iseconds; md5sum "/d/Game/LifePlay-master 5.8/Content/BPs/Room.uasset"; stat -c '%s %y' "/d/Game/LifePlay-master 5.8/Content/BPs/Room.uasset"; git -C "D:\Game\LifePlay-master 5.8" status --short -- Content Source Config; md5sum "/d/Game/LifePlay-master 5.8/Content/BPs/Person.uasset"
2026-10-13T16:10:34+02:00
e0517c63541f249bd9dbda5c39815ba5 */d/Game/LifePlay-master 5.8/Content/BPs/Room.uasset
6318319 2026-10-13 16:10:30.045597500 +0200
 M Content/BPs/Person.uasset
 M Content/BPs/Room.uasset
 M Source/LifePlay/LPDebugSubsystem.cpp
 M Source/LifePlay/LPDebugSubsystem.h
b239e1035cb028b78fbd4bb9f0c5f70a */d/Game/LifePlay-master 5.8/Content/BPs/Person.uasset

stat -c '%n %s %y' ".../Content/BPs/Person.uasset" ".../Content/BPs/Room.uasset"
/d/Game/LifePlay-master 5.8/Content/BPs/Person.uasset 20808711 2026-10-13 14:35:14.930487700 +0200
/d/Game/LifePlay-master 5.8/Content/BPs/Room.uasset 6318319 2026-10-13 16:10:30.045597500 +0200

Lecture des mesures :

  • Le MD5 de Room diffère de l'instantané A5FA970E : l'enregistrement a bien eu lieu.
  • Person.uasset date de 14:35:14, avant B2b : ce n'est pas l'enregistrement de F7. LPDebugSubsystem.* viennent d'autres lots ; aucun n'a été touché.
  • Room figurait déjà en M avant l'enregistrement, avec le MD5 de l'instantané. L'instantané de 15:25 diffère donc déjà de HEAD. Estimé : enregistrement d'un lot antérieur (B2) non encore commité. À trancher par le gardien avant le commit.

Retour arrière, sur décision de l'orchestrateur et jamais lancé ici :

  1. fermer l'éditeur ;
  2. .\Tools\Snapshot.ps1 -Lot CAM-B2b-retour -Path Content\BPs\Room.uasset ;
  3. .\Tools\Restore.ps1 -Lot CAM-B2b -Only Content\BPs\Room.uasset -WhatIf, puis sans -WhatIf.

Retour attendu à l'octet : MD5 A5FA970E…, 6 060 745 octets.

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

  • hyper_blueprint_debug_inspect et journal de l'éditeur : non consultés (§ 1.7).
  • CompileAllBlueprints, éditeur fermé : il revient à l'orchestrateur (lp-mcp § 1, règle 3).
  • IfThenElse_96, _97, _98, _99 n'ont pas été relus ici. Leurs else → IfThenElse_26, _9, _10, _25 sont établis par les relectures finales de F6a et F6b, pas par celle de F7. CallFunction_473 (Start ← 502, F4 L17) n'a pas été relu non plus.
  • Comportement à l'exécution : non mesuré (aucune PIE, aucun build), seulement déduit du câblage.
  • Preuve en jeu (build empaqueté + LogStats), V5 et V6 : hors rôle ; c'est la suite de l'orchestrateur.
  • Fermeture de l'éditeur : non faite, selon la consigne. PID 10708 reste ouvert.

5. Points à confirmer en VAL

  1. Vue autre que C2 : DownUp prend else → IfThenElse_8, avec la chaîne d'origine inchangée (Condition ← CABO_17, then → IfThenElse_17). Établi par le câblage ; à confirmer en jeu (hauteur de l'ancienne caméra identique).

  2. Vue C2 : DownUp ajoute AxisValue × 3 à C2Height, borné à [−40, 150]. L'effet passe par ComputeC2Target (F3) au prochain appel. Signe et gain sont à juger à l'essai.

  3. LogStats : aucun Accessed None nouveau sur CallFunction_439 / VariableGet_262. PO8 est évalué à chaque DownUp, probablement à chaque image tant que l'axe est actif (estimé, appelant non lu).

  4. Cas limite (estimé, déjà noté en F6a et F6b) : si GetViewTarget et CamRoom valent tous deux None, PO8 vaut true, et DownUp écrit C2Height au lieu de piloter l'ancienne caméra.

  5. V5 (CAM-SPEC.md:382) : pour les 5 événements, then → nouvelle branche et else → branche d'origine :

    • CE1 → 96, else → 26 ;
    • CE4 → 97, else → 9 ;
    • CE19 → 99, else → 25 ;
    • CE8 → 100, else → 8 ;
    • CE55 → 98, else → 10.

    Également : SphereTraceSingle 3 (459, 499, 505), Vector_BoundedToBox ≥ 4, ComputeRoomBox 1.

  6. Valeurs sérialisées, à relire par dump (LPDumpFunction) sur le fichier enregistré :

    • PO35.B = 3.0 ; 511 Min −40.0, Max 150.0 ;
    • celles de F1 à F6b, déjà listées dans leurs IMPL (par exemple PO31.B 15.0, 509 [−75, 125], PO33.B 3.0, 510 [−40, 150], Radius 20 de 459, 499 et 505).
  7. Compilation : jugée sur la seule absence d'exception de compile_blueprint {warnings_as_errors:true}. À recontrôler par CompileAllBlueprints, éditeur fermé, avec 0 erreur et 0 avertissement nouveau sur Room.

  8. État git de Room : il était déjà M avant F7 (§ 3). Le gardien doit établir ce que contient le diff par rapport à HEAD (B2 et B2b ?) avant le commit.

6. Fichiers à commiter

Dépôt du jeu, branche ue5.8 :

  • A Docs/Migration/etat/CAM/CAM-B2b-IMPL-F7.md
  • M Content/BPs/Room.uasset, après VAL (V5, V6), avec la réserve du point 8 du § 5.

Content/BPs/Person.uasset et Source/LifePlay/LPDebugSubsystem.* n'appartiennent pas à ce lot : ne pas les joindre.

Tours : 30 / 50 (ce Write et la remise du compte rendu compris ; 24 appels MCP, un par message)

Constats

  • Le schéma F6b se rejoue tel quel pour DownUp : 6 créations, 1 coupure, 9 liaisons et 3 valeurs, plus 2 lectures groupées, soit 21 appels pour l'événement.
  • Les index de broches sont identiques à F6b (Branche, Clamp(Float), |SetC2Height) ; |GetC2Height → out 0.
  • Dans le graphe, les numéros des nœuds créés suivent ceux de F6b : IfThenElse_100, VariableGet_296, PromotableOperator_35 et _36, CallFunction_511, VariableSet_71.
  • save_assets sur /Game/BPs/Room renvoie {"returnValue":true} (booléen) ; les écritures de graphe renvoient null.
  • À verser : lp-mcp § 3 — save_assets {asset_paths:["/Game/BPs/X"]} (toolset editor_toolset.toolsets.asset.AssetTools) renvoie true. Avant d'enregistrer, mesurer le MD5 et git status : un asset peut déjà être M du fait d'un lot antérieur, ce qui change ce que le gardien commitera.