19 KiB
Fiche STE-H3g-I — Niveau N3 — Modèle prévu opus (xhigh) | utilisé claude-opus-5-5 — Agent lp-mcp-bp — Skills sk-protocol, sk-change-safety, lp-mcp, lp-lot
STE-H3g-IMPL : garde G16 (GI:EventGraph, UpdateDefaultHair) écrite par MCP (2026-10-13)
Copie D:\Game\LifePlay-master 5.8, branche ue5.8, HEAD 0745917. SPEC : STE-H3g-SPEC.md § 2.0, 2.1, 2.3, 3, 4, 7 (G16 seule ; G15 non écrite, décision Q-H3g-1 = c).
UE-GO de Big Boss reçu (fiche, rubrique 3). Éditeur headless lancé et fermé par l'agent (lp-mcp § 2). Un appel MCP par message, outils Epic seulement (aucun hyper_*, aucun execute_tool_script).
1. Fichiers modifiés
Un seul : Content\BPs\GI.uasset, graphe /Game/BPs/GI.GI:EventGraph, enregistré par save_assets {asset_paths:["/Game/BPs/GI"]} → true.
Empreintes (Git Bash, copie 5.8, md5sum Content/BPs/GI.uasset Content/BPs/Person.uasset Content/BPs/Room.uasset "/d/Game/LifePlay_Backup_5.5/STE-H3g/Content/BPs/GI.uasset") :
| Fichier | Avant (17:53) | Après (18:07, éditeur fermé) |
|---|---|---|
Content/BPs/GI.uasset |
c4817b847ecf246c859647577647d6e9 |
0e6aedcccd1a6522282f9a423843ce45 |
instantané D:\Game\LifePlay_Backup_5.5\STE-H3g\Content\BPs\GI.uasset |
c4817b847ecf246c859647577647d6e9 |
c4817b847ecf246c859647577647d6e9 (inchangé) |
Content/BPs/Person.uasset (autre lot, non ouvert) |
8668a47c627f7a5254910cf0ac33b12a |
8668a47c627f7a5254910cf0ac33b12a |
Content/BPs/Room.uasset (autre lot, non ouvert) |
ca2a9a0baaca4130fd5c318797f008ae |
ca2a9a0baaca4130fd5c318797f008ae |
git status --short -- Content : avant M Person, M Room ; après M Content/BPs/GI.uasset, M Content/BPs/Person.uasset, M Content/BPs/Room.uasset.
Comptes de GI:EventGraph (find_nodes {graph:{refPath:"/Game/BPs/GI.GI:EventGraph"}, title:""}, sortie enregistrée par le client puis comptée par grep -o 'GI\.GI:EventGraph\.K2Node_[A-Za-z]*_[0-9]*') :
6 247 → 6 251 nœuds K2Node (+4, exactement les 4 nouveaux) ; avec les 2 commentaires (EdGraphNode_Comment_0, _1) que find_nodes ne liste pas : 6 249 → 6 253, compte du dump. Voir § 2 E1.
1.1 P4 : nœuds existants relus avant écriture (get_node_infos, deux appels de 8 nœuds)
Préfixe des refPath : /Game/BPs/GI.GI:EventGraph.K2Node_. Les 16 nœuds de la SPEC § 2.0 P4 retrouvés, tous conformes à la colonne « Avant » (§ 2.3.1).
| Nœud | type_id relu, position | Liens et indices relevés |
|---|---|---|
CustomEvent_5 |
`AddEvent | Custom |
IfThenElse_104 |
`Utilitaires | ContrôleDeFlux |
IfThenElse_65 / _66 |
Branche, (-9648, 9504) / (-9712, 9744) | Condition ← CallFunction_235 ; then 0 → CallFunction_662 / _661 ; else 1 → CallFunction_259 / _287 |
CallFunction_259 / _287 |
` | LoadHairMeshIfNeeded` |
CallFunction_662 / _661 |
`Composants | Maillagesurfacé |
MacroInstance_5 / _4 |
`Utilities | Array |
CallFunction_5654 |
` | TurnMaterialDynamic`, (-8176, 9552) |
CallFunction_237 |
` | FitMorphableHair`, (-7856, 9648) |
BreakStruct_12 / _13 |
`Utilitaires | Structure |
VariableGet_1147 / _64 |
` | GetMaterials`, (-9312, 9440) / (-8976, 9904) |
1.2 Nœuds créés (correspondance SPEC → nom réel → type_id)
Chaque type_id vérifié par find_node_types {graph, type_id_filter, context_pins:[]} juste avant son create_node (4 appels), nœuds relus par get_node_infos avant tout câblage.
| SPEC | Nœud réel (refPath /Game/BPs/GI.GI:EventGraph.K2Node_…) |
Filtre → réponse | type_id de création = relu | Broches (index) | Position |
|---|---|---|---|---|---|
| G16a-V IsValid | CallFunction_715 |
`Utilitaires | IsValid→ 5 :…IsValidSoftObjectReference, …IsValidSoftClassReference, …IsValidInterface, …IsValidClass, Utilitaires |
IsValid` | `Utilitaires |
| G16a-B Branche | IfThenElse_219 |
`ContrôleDeFlux | Branche→ 1 :Utilitaires |
ContrôleDeFlux | Branche` |
| G16b-V IsValid | CallFunction_720 |
idem G16a-V (5) | `Utilitaires | IsValid` | idem |
| G16b-B Branche | IfThenElse_220 |
idem G16a-B (1) | `Utilitaires | ContrôleDeFlux | Branche` |
Aucun set_pin_value, aucun delete_node.
1.3 Coupures et liens (un appel MCP par message, réponse null pour chacun)
| # | Geste | Sortie (index) | Entrée (index) |
|---|---|---|---|
| C1 | break_pins |
CallFunction_662.then (0) |
MacroInstance_5.Exec (0) |
| 1 | connect_pins |
BreakStruct_12.SkeletalMesh_2_93573D9945CD4136090CCBA1F1188DAC (0) |
CallFunction_715.Object (0) |
| 2 | connect_pins |
CallFunction_662.then (0) |
IfThenElse_219.execute (0) |
| 3 | connect_pins |
CallFunction_715.ReturnValue (0) |
IfThenElse_219.Condition (1) |
| 4 | connect_pins |
IfThenElse_219.then (0) |
MacroInstance_5.Exec (0) |
| 5 | connect_pins |
IfThenElse_219.else (1) |
CallFunction_5654.execute (0) |
| C2 | break_pins |
CallFunction_661.then (0) |
MacroInstance_4.Exec (0) |
| 6 | connect_pins |
BreakStruct_13.SkeletalMesh_2_93573D9945CD4136090CCBA1F1188DAC (0) |
CallFunction_720.Object (0) |
| 7 | connect_pins |
CallFunction_661.then (0) |
IfThenElse_220.execute (0) |
| 8 | connect_pins |
CallFunction_720.ReturnValue (0) |
IfThenElse_220.Condition (1) |
| 9 | connect_pins |
IfThenElse_220.then (0) |
MacroInstance_4.Exec (0) |
| 10 | connect_pins |
IfThenElse_220.else (1) |
CallFunction_5654.execute (0) |
Relecture (get_node_infos de 20 nœuds en deux appels : les 4 nouveaux + les 16 de P4 + CallFunction_2917 / _2918), conforme au § 2.3.2 :
CallFunction_662.then→IfThenElse_219.executeseul ;MacroInstance_5.Exec←IfThenElse_219.thenseul ; idemCallFunction_661.then→IfThenElse_220seul,MacroInstance_4.Exec←IfThenElse_220.thenseul.IfThenElse_219:Condition←CallFunction_715.ReturnValue;else→CallFunction_5654.execute.IfThenElse_220:Condition←CallFunction_720.ReturnValue;else→CallFunction_5654.execute.CallFunction_715.Object←BreakStruct_12(0) ;CallFunction_720.Object←BreakStruct_13(0).BreakStruct_12.SkeletalMesh_2_…→VariableGet_1147(0),CallFunction_662.NewMesh(2),CallFunction_715.Object(0) ;BreakStruct_13.SkeletalMesh_2_…→VariableGet_64,CallFunction_661.NewMesh,CallFunction_720.Object.CallFunction_5654.execute: 4 sources :MacroInstance_4(3),MacroInstance_5(3),IfThenElse_219(1),IfThenElse_220(1).- Inchangés :
SetSkinnedAssetAndUpdate×2 (execute,self,NewMesh,bReinitPose = true),MacroInstance_4/_5(Array,LoopBody,Array Element,Array Index,Completed),VariableGet_1147/_64,CallFunction_5654.then→CallFunction_237,CustomEvent_5,IfThenElse_104/_65/_66,CallFunction_259/_287,CallFunction_2917/_2918.
1.4 Compilation et enregistrement
Journal : D:\Game\LifePlay-master 5.8\Saved\Logs\STE-H3g-headless-20261013-175345.log (heures UTC = locale − 2 h).
compile_blueprint {blueprint:{refPath:"/Game/BPs/GI.GI"}, warnings_as_errors:true}→null. Journal l. 2332,16.06.47:036:LogBlueprint: Compiling Blueprint '/Game/BPs/GI.GI'; l. 233316.06.51:737:LogUObjectHash: Compacting ….tail -n +2330 <journal> | grep -c -E 'Error|Warning'→0.hyper_blueprint_debug_inspectnon utilisé (absent du serveur, H3dI:156 ; fiche).save_assets {asset_paths:["/Game/BPs/GI"]}(editor_toolset.toolsets.asset.AssetTools) →true. Journal l. 2340,16.07.00:306:Cmd: OBJ SAVEPACKAGE PACKAGE="/Game/BPs/GI" FILE="…/Content/BPs/GI.uasset" SILENT=true;16.07.04:595: déplacement du.tmpversContent/BPs/GI.uasset;AssetCheck: /Game/BPs/GI(1 ressource validée), sans échec listé.grep -n SAVEPACKAGE <journal>→ 2 lignes : 2274 (autosave, § 2 E4) et 2340 (seul enregistrement dansContent).- Éditeur : lancé 17:54:02 (PID 36020),
Stop-Process -Id 36020à 18:07:12 ;Tools\UeState.ps1à 18:07:24 →processus=0 editeur=0 compilation=0 shaders=0 jeu=0(code 0).
1.5 Garde Accessed None (lp-mcp § 1 règle 4) et comportement
IsValidjustifié : « maillage vide » est un état normal ici : l'entrée deHairstyleTablelue parGetArrayItem_4/_6peut rendreSkeletalMesh_2 = None(observé 2 fois dans HJ:16058, 16086), et l'utilisateur a décidé de garder « pas de coiffure, comme aujourd'hui » (décision Q1, SPEC § 1).- Cascade de Branche seule, aucun AND / OR / Select.
SetSkinnedAssetAndUpdate(HairSM, None)reste appelé avant la garde (la coiffure est toujours vidée). - Maillage valide :
then→ boucle, chemin d'origine (établi par construction). Maillage None :else→CallFunction_5654→CallFunction_237, sans lectureMaterials(estimé identique à l'exécution actuelle, voir R-H3g-4 ci-dessous).
1.6 Réponse au point amont R-H3g-4 (successeurs des boucles)
Établi (relecture get_node_infos du jour) : MacroInstance_5 et _4 n'ont, en exécution, que deux sorties reliées : LoopBody (0) → CallFunction_2918 / _2917 (Rendu|Matériau|SetMaterial, dont la sortie then (0) n'a aucun lien) et Completed (3) → CallFunction_5654.execute seul. Aucun autre successeur que CallFunction_5654 après la boucle ; le corps de boucle s'arrête à SetMaterial.
Donc l'else des gardes (→ CallFunction_5654) reproduit la suite d'exécution actuelle dès que la boucle fait 0 itération. Le « 0 itération sur tableau effacé » reste estimé (macro ForEachLoop non lue, SPEC § 6) ; s'il était faux, la seule différence serait des SetMaterial sur HairSM sans maillage.
2. Écarts à la SPEC
- E1 (compte) :
find_nodes title:""rend 6 247 nœuds avant écriture, pas 6 249. Les 2 manquants sont les commentaires du graphe, quefind_nodesne liste pas : le dump compteEdGraphNode_Comment_0et_1(GEV, premier listing : 6 249 noms dont 6 247K2Node_*) ;diffdes nomsK2Node_*du dump et de la liste MCP → aucune différence (code 0) ;get_node_infossur les deux commentaires →'EdGraphNode_Comment' object has no attribute 'get_node_title'(objets résolus, non K2). Le graphe est donc celui du dump (MD5 identique en plus). J'ai poursuivi : l'écart est dans la méthode de comptage, pas dans l'état. Après : 6 251 parfind_nodes= 6 253 au sens du dump (à confirmer par le dump de VAL, § 5). - E2 (attente MCP) :
Wait-HyperAIStudioMCP.ps1 -Port 8000 -UrlPath /mcp -TimeoutSeconds 540→ code 1, sans sortie, après 540 s (17:54 → 18:03), alors que le serveur écoutait depuis15.54.14:094UTC (journal l. 1903-1906 :Starting MCP server on port 8000,Created new HttpListener on 127.0.0.1:8000;Get-NetTCPConnection -LocalPort 8000→ propriétaire 36020) ;get_current_levela répondu/Game/Scenes/CentralLondon. Cause du code 1 non instruite. - E3 (lecture hors liste) : un
get_node_infossur les deux commentaires (E1) a laisséLogScript: Warning: 'EdGraphNode_Comment' object has no attribute 'get_node_title'au journal (16.04.18, avant la compilation) ; lecture seule. - E4 (autosave) : l'éditeur a écrit
Saved\Autosaves\Game\BPs\GI_Auto1.uassetà16.05.07UTC (l. 2274, pendant le câblage). Déplacé (pas supprimé) versD:\Game\LifePlay_Backup_5.5\STE-H3g\autosave\GI_Auto1.uasset(52 611 967 octets, MD54740351cdf4d3733f990922f87367723) ; plus aucunGI_Auto*sousSaved\Autosaves. Les autres autosaves (Person_Auto1,Room_Auto1-4,TestStatic_Auto1,UI\MainMenu_Auto1) préexistaient et n'ont pas été touchés. - E5 (P5) :
get_node_infosdes nouveaux nœuds fait par paire (après les deux créations de chaque garde), avant tout câblage, au lieu d'un appel après chaque création. - E6 (budget) : 53 tours pour un budget ≈ 50 (plafond 60).
- Aucun autre : 4 nœuds, 2 coupures, 10 liens exactement selon § 2.3.2 ; G15 non écrite ; aucun autre graphe ni asset ouvert en écriture ; Person et Room ni chargés ni enregistrés.
3. Instantané
Pris par l'orchestrateur avant la fiche (pas de Snapshot.ps1 relancé) : D:\Game\LifePlay_Backup_5.5\STE-H3g\Content\BPs\GI.uasset, MD5 c4817b847ecf246c859647577647d6e9 = GI de départ, relu identique après l'enregistrement. Manifeste D:\Game\LifePlay_Backup_5.5\STE-H3g\manifest.csv non relu par l'agent.
Retour arrière (proposé, non lancé ; décision de l'orchestrateur, éditeur fermé) : .\Tools\Restore.ps1 -Lot STE-H3g -Only Content\BPs\GI.uasset -WhatIf, puis sans -WhatIf ; MD5 attendu c4817b847ecf246c859647577647d6e9. Après commit : git revert du commit du ticket STE-H3g.
Entrée de journal (sk-change-safety) : 2026-10-13 | G16 (2 IsValid + 2 Branche) dans GI:EventGraph | Content/BPs/GI.uasset | retour arrière : Restore.ps1 -Lot STE-H3g -Only Content\BPs\GI.uasset | instantané : D:\Game\LifePlay_Backup_5.5\STE-H3g\ | vérification : 6 247 → 6 251 K2Node (+4), relecture conforme, compilation 0 / 0, MD5 0e6aedcc…
4. Ce qui n'a pas été fait
- G15 (
isSameAs) : non écrite (décision Q-H3g-1 = c) ;isSameAsnon chargé en lecture ni en écriture. - Dumps
LPDumpFunctionaprès IMPL,CompileAllBlueprints,LPTestStringCompat, build et journal de jeu : à la VAL / au BUILD (SPEC § 7). - Cause du maillage None (piste
Daz) : hors périmètre (SPEC § 2.3.3, R-H3g-7). - Gel annoncé aux autres sessions et
BUILD-FIN: à l'orchestrateur.
5. Points à confirmer en VAL
- Dump
-BP=GI -Fn=EventGraph -Pins -Exec→(6253 noeuds); liens du § 7.1 de la SPEC avec les noms réels : G16a-V =CallFunction_715, G16a-B =IfThenElse_219, G16b-V =CallFunction_720, G16b-B =IfThenElse_220. DiffRemplacementNoeuds.pysur EventGraph (avant =dumps\GI__EventGraph_P2.txt) : seuls ces 4 nœuds, 2 coupures, 10 liens.isSameAsreste à 11 nœuds (G15 abandonnée : le « 15 » de la SPEC § 7.1 ne s'applique plus) ;GetVariable53,Action:EventGraph363,CallFunctionReturnBool594 inchangés.CompileAllBlueprintséditeur fermé : BP/Game/0 erreur ;LPTestStringCompat3120 / 0 / 60.- MD5 de GI =
0e6aedcccd1a6522282f9a423843ce45au départ de la VAL ; Person8668a47c…et Roomca2a9a0b…inchangés. - Journal de jeu (build, même ligne de commande que HJ) :
SkeletalMesh_2_93573D2 → 0,UpdateDefaultHair4 → 0 ;Person_24_.*of length 0(2) etisSameAs(3) attendus inchangés (G15 non écrite) ; preuve de parcours rejoué de la SPEC § 7.4 (G16). - R-H3g-4 : 0 itération sur tableau effacé reste estimé (§ 1.6) ; aucune autre suite d'exécution que
CallFunction_5654(établi). - Code 1 de
Wait-HyperAIStudioMCP.ps1alors que le serveur répondait (E2) : à instruire hors lot.
6. Fichiers à commiter
Dépôt jeu, branche ue5.8, ticket au gardien :
- M
Content/BPs/GI.uasset - A
Docs/Migration/etat/ST/STE/STE-H3g-IMPL.mdNe pas inclureContent/BPs/Person.uassetniContent/BPs/Room.uasset(autres lots,Mpréexistants).
Tours : 53 / 50 (plafond 60)
Constats
Commandes et sorties brutes (extraits) :
- Entrée :
md5sum Content/BPs/GI.uasset Content/BPs/Person.uasset Content/BPs/Room.uasset <instantané GI>→c4817b847ecf246c859647577647d6e9,8668a47c627f7a5254910cf0ac33b12a,ca2a9a0baaca4130fd5c318797f008ae,c4817b847ecf246c859647577647d6e9;git rev-parse --short HEAD→0745917;Tools/UeState.ps1→processus=0 editeur=0 compilation=0 shaders=0 jeu=0. - Lancement :
Start-Process UnrealEditor.exe "<copie>\LifePlay.uproject" -RenderOffScreen -unattended -nosplash -NoSound -ModelContextProtocolStartServer -ModelContextProtocolPort=8000 "-abslog=<copie>\Saved\Logs\STE-H3g-headless-20261013-175345.log"→PID=36020,17:54:02. Aucune demande de recompilation de modules :grep -i -E "modules are missing|rebuild|out of date|built with a different"→ aucune ligne utile (le seul « Took … seconds » relevé concerne la configuration). - Comptes (
grep -o 'GI\.GI:EventGraph\.K2Node_[A-Za-z]*_[0-9]*' <sortie find_nodes>, sorties enregistrées par le client sous%USERPROFILE%\.claude\projects\D--Game-LifePlay-master-5-8\36e41eab-6dbf-4c01-adea-9fe53389b8ce\tool-results\mcp-unreal-mcp-call_tool-1791907424673.txt(avant) et…-1791907595179.txt(après)) :
avant: total 6247, uniques 6247
apres: total 6251, uniques 6251, refPath 6251
-- presents dans une seule liste :
> GI.GI:EventGraph.K2Node_CallFunction_715
> GI.GI:EventGraph.K2Node_CallFunction_720
> GI.GI:EventGraph.K2Node_IfThenElse_219
> GI.GI:EventGraph.K2Node_IfThenElse_220
- Dump :
head -n 30176 GI__EventGraph_P2.txt | grep -E '^ [A-Za-z]' | awk '{print $1}' | sort -u | wc -l→6249; nonK2Node_→EdGraphNode_Comment_0,EdGraphNode_Comment_1;K2Node_→6247;diffavec la liste MCP avant → code 0. - Lignes Error / Warning du journal avant la compilation (l. 1990-2329) : sessions MCP (
Unknown session id … client should reinitialize,Call to unknown method "server/discover", 16.03.25-16.03.26, reconnexion du client), E3 (16.04.18),LogHttp: Warning: HTTP request timed out … generate_204(16.05.09) ; 20LogAutomationTest: Error: Condition failedau démarrage (l. 1730-1747…, 15.54.13, tests du moteur au chargement). Aucune liée à GI. - Lecture seule de Person et Room respectée : ni
load_asset, nisave_assets; MD5 identiques.