LifePlay-Revival/Docs/Migration/etat/ST/STE/STE-H3d-IMPL.md

194 lines
15 KiB
Markdown
Raw Normal View History

Fiche STE-H3d-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-H3d-IMPL : garde G13, variante b, dans GI:CallFunctionReturnBool, par MCP (2026-10-13)
**Résultat : réussi, côté éditeur.** 3 nœuds créés, 1 coupure, 6 liens, tous relus conformes à `STE-H3d-SPEC.md` § 2.2
(variante b). Compilation de GI (avertissements en erreurs) sans diagnostic dans le journal ; `/Game/BPs/GI` seul enregistré.
La preuve en jeu (build empaqueté + `LogStats`) n'est pas de mon ressort (`lp-mcp` § 1 règle 5).
BUILD-GO de Big Boss : « REPRISE … GO pour STE-H3d IMPL » (2026-10-13). SPEC approuvée par l'utilisateur, variante b (Q-H3d-1).
Éditeur headless PID 21728, port 8000, lancé par l'orchestrateur ; connexion `unreal-mcp` partagée avec la session qui m'a lancé.
Journal de l'éditeur : `D:\Game\LifePlay-master 5.8\Saved\Logs\STE-H3d-headless-20261013-124535.log` (heures UTC = locale − 2 h).
| Mesure | Avant | Après |
|---|---|---|
| MD5 `Content\BPs\GI.uasset` | `6a957cb2a654fd1a06ff25cec9727955` (entrée de fiche) | `c4817b847ecf246c859647577647d6e9` (2026-10-13 12:51:23 +0200) |
| Nœuds de `CallFunctionReturnBool` (`find_nodes title:""`) | 591 | 594 |
| `git status --short -- Content` | (vide) | ` M Content/BPs/GI.uasset` |
## 1. Fichiers modifiés
Un seul : `Content\BPs\GI.uasset`, graphe de fonction `/Game/BPs/GI.GI:CallFunctionReturnBool`, par `save_assets` seulement.
**Empreintes** (Git Bash, copie 5.8) : `md5sum Content/BPs/GI.uasset "/d/Game/LifePlay_Backup_5.5/STE-H3d/Content/BPs/GI.uasset"`
- entrée : `6a957cb2a654fd1a06ff25cec9727955` pour les deux (GI = instantané, conforme à la fiche) ;
- après `save_assets` : GI `c4817b847ecf246c859647577647d6e9`, instantané inchangé `6a957cb2a654fd1a06ff25cec9727955`.
**Comptes : 591 avant, 594 après** (établi). `find_nodes {graph:{refPath:"/Game/BPs/GI.GI:CallFunctionReturnBool"}, title:""}` rend la
liste en ligne ; comptée dans la transcription de l'agent
(`%USERPROFILE%\.claude\projects\D--Game-LifePlay-master-5-8\36e41eab-6dbf-4c01-adea-9fe53389b8ce\subagents\agent-ade150d2a51ea3487.jsonl`),
par tubes, sans fichier écrit :
```
pat='GI\.GI:CallFunctionReturnBool\.K2Node_[A-Za-z]*_[0-9]*'
ligne 57 : total 591, uniques 591 (avant écriture)
ligne 138 : total 594, uniques 594 (après le 6e lien)
-- presents dans une seule liste :
GI.GI:CallFunctionReturnBool.K2Node_CallArrayFunction_5
GI.GI:CallFunctionReturnBool.K2Node_IfThenElse_2
GI.GI:CallFunctionReturnBool.K2Node_VariableSet_52
-- absents de la liste apres :
0
```
### 1.1 P4 : nœuds existants relus avant écriture (`get_node_infos`, deux appels)
Préfixe des `refPath` : `/Game/BPs/GI.GI:CallFunctionReturnBool.K2Node_`. Tous conformes à la colonne « Avant » de la SPEC § 2.2.
| Nœud | type_id relu, position | Liens et indices relevés |
|---|---|---|
| `SwitchString_77` | `Utilitaires|ContrôleDeFlux|Switch|Allumerlachaîne`, (976, -400) | sortie `isCreatureType` (57) → `CallFunction_21.execute` (0), seul lien |
| `CallFunction_21` | `Scène|GetVariable`, (1904, 6240) | in `execute` 0 ← `SwitchString_77` (57) ; `self` 1 vide ; `Name` 2 ← `VariableGet_18330` ; out `then` 0 → `VariableSet_23.execute` (0) seul ; `Variable` 1 → `BreakStruct_956.Variable` (0) |
| `BreakStruct_956` | `Utilitaires|Structure|BreakVariable`, (2208, 6256) | out `Person_24_4B712C904750AD4CE1580DBEBD9E7396` (6) → `GetArrayItem_2346.Array` (0), seul lien ; autres sorties sans lien |
| `GetArrayItem_2346` | `Utilitaires|Matrice|Get(unecopie)`, (2512, 6400) | `Array` 0 ← `BreakStruct_956` (6) ; `Dimension 1` 1 = `0` ; `Output` 0 → `CallFunction_27.Actor` (1), **seul consommateur** |
| `VariableGet_21` | `|GetActualParameters`, (2432, 6224) | `ActualParameters` 0 → `GetArrayItem_21.Array` (0) |
| `GetArrayItem_21` | `Utilitaires|Matrice|Get(uneréférence)`, (2608, 6208) | `Array` 0 ← `VariableGet_21` ; `Dimension 1` = `0` ; `Output` 0 → `CallFunction_27.Animal` (0) |
| `CallFunction_27` | `|isCreatureType`, (2800, 6352) | **pur** (aucune broche d'exécution) ; in `Animal` 0 ← `GetArrayItem_21` ; `Actor` 1 ← `GetArrayItem_2346` ; out `True` 0 → `VariableSet_23.BoolToReturn` (1) |
| `VariableSet_23` | `|SetBoolToReturn`, (3008, 6160) | in `execute` 0 ← `CallFunction_21.then` seul ; `BoolToReturn` 1 ← `CallFunction_27.True` ; out `then` 0 → `IfThenElse_8994.execute` (0) ; `Output_Get` 1 sans lien |
| `IfThenElse_8994` | `Utilitaires|ContrôleDeFlux|Branche`, (3712, 400) | in `execute` 0 ← 76 sources dont `VariableSet_23` ; `Condition` 1 ← `VariableGet_11872` ; out `then` 0 → `FunctionResult_0`, `else` 1 → `FunctionResult_1` |
Arrêts de G13 vérifiés : aucun lien différent ; `GetArrayItem_2346` n'a qu'un consommateur ; `CallFunction_27` est pur. P5
(`find_node_types` d'`isCreatureType`) relève de la variante a : sans objet ici.
### 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`, puis le nœud
relu par `get_node_infos`.
| SPEC | Nœud réel | Filtre → réponse | type_id de création | Type relu | Broches (index) | Position |
|---|---|---|---|---|---|---|
| G13-I IsValidIndex | `CallArrayFunction_5` | `IsValidIndex` → 4 : `Élémentstypiquesframework|Liste|IsValidIndex`, `Utilitaires|Tableau|IsValidIndex`, `Fournisseursdetransformation|Exécutiond'animation|IsValidIndex`, `Hiérarchiedel'armatureU|IsValidIndex` | `Utilitaires|Tableau|IsValidIndex` | idem | in `TargetArray` 0, `IndexToTest` 1 = **`0`** ; out `ReturnValue` 0 | 2512, 6560 |
| G13-B Branche | `IfThenElse_2` | `ContrôleDeFlux|Branche` → 1 | `Utilitaires|ContrôleDeFlux|Branche` | idem | in `execute` 0, `Condition` 1 ; out `then` 0, `else` 1 | 2800, 6560 |
| G13-S Set BoolToReturn | `VariableSet_52` | `BooltoReturn` → `Variables|Pardéfaut|ObtenirBooltoReturn`, `Variables|Pardéfaut|DéfinirBooltoReturn` | `Variables|Pardéfaut|DéfinirBooltoReturn` | `|SetBoolToReturn` (comme `VariableSet_23`) | in `execute` 0, `BoolToReturn` 1 = **`false`** ; out `then` 0, `Output_Get` 1 | 3008, 6560 |
Aucun `set_pin_value` : `IndexToTest` = `0` et `BoolToReturn` = `false` sont les valeurs par défaut, relues avant et après câblage.
### 1.3 Coupure et liens (un appel MCP par message, réponse `null` pour chacun)
Coupure : `break_pins` `CallFunction_21.then` (out 0) / `VariableSet_23.execute` (in 0). Relue : `CallFunction_21.then` → `IfThenElse_2`
seul ; `VariableSet_23.execute` ← `IfThenElse_2` seul.
| # | Sortie | Entrée | Relu (`get_node_infos` des 3 nouveaux et des 9 de P4, après le 6e lien) |
|---|---|---|---|
| 1 | `CallFunction_21.then` (0) | `IfThenElse_2.execute` (0) | oui, seul lien de `then` et seule entrée d'`execute` |
| 2 | `BreakStruct_956.Person_24_4B712C904750AD4CE1580DBEBD9E7396` (6) | `CallArrayFunction_5.TargetArray` (0) | oui ; `Person_24_…` relié à `GetArrayItem_2346.Array` **et** `CallArrayFunction_5.TargetArray` ; `TargetArray` typé « Matrice de Person Référence d'objets » après câblage (« Matrice de Caractère de remplacements » avant) |
| 3 | `CallArrayFunction_5.ReturnValue` (0) | `IfThenElse_2.Condition` (1) | oui |
| 4 | `IfThenElse_2.then` (0) | `VariableSet_23.execute` (0) | oui, seule entrée |
| 5 | `IfThenElse_2.else` (1) | `VariableSet_52.execute` (0) | oui, seule entrée |
| 6 | `VariableSet_52.then` (0) | `IfThenElse_8994.execute` (0) | oui |
Inchangés à la relecture : `SwitchString_77` (84 sorties, `isCreatureType` (57) → `CallFunction_21`), `CallFunction_21.Name` / `.Variable`,
`GetArrayItem_2346` (`Output` → `CallFunction_27.Actor` seul, `Dimension 1` = 0), `GetArrayItem_21`, `VariableGet_21`, `CallFunction_27`
(`True` → `VariableSet_23.BoolToReturn`), `VariableSet_23.BoolToReturn` et `.then`, `IfThenElse_8994.Condition`, `.then`, `.else`.
`IfThenElse_8994.execute` : sources comparées entre la lecture P4 et la relecture (transcription, lignes 69 et 134) :
```
ligne 69 : refs 77 (dont 1 = pin_id du noeud)
ligne 134 : refs 78 (dont 1 = pin_id du noeud)
-- difference entre la 1re et la 2e lecture :
K2Node_VariableSet_52
```
soit 76 → 77 sources, seul ajout `VariableSet_52`.
### 1.4 Compilation et enregistrement
- `compile_blueprint {blueprint:{refPath:"/Game/BPs/GI.GI"}, warnings_as_errors:true}` → `null`. Journal ligne 2345,
`10.50.49:045` UTC : `LogBlueprint: Compiling Blueprint '/Game/BPs/GI.GI'` ; ligne 2346 : `LogUObjectHash: Compacting …`. Lignes
2345-2379 lues en entier (`tail -n +2345 <journal> | grep -v 'Dispatching toolset tool'`) : aucune ligne Error ni Warning.
- `save_assets {asset_paths:["/Game/BPs/GI"]}` (toolset `editor_toolset.toolsets.asset.AssetTools`) → `true`. Journal ligne 2353,
`10.51.13:203` UTC : `Cmd: OBJ SAVEPACKAGE PACKAGE="/Game/BPs/GI" …Content/BPs/GI.uasset SILENT=true` ; ligne 2356 : déplacement du
`.tmp` vers `Content/BPs/GI.uasset` ; validation de contenu sur 1 ressource (`AssetCheck: /Game/BPs/GI`), sans échec listé.
`grep -n SAVEPACKAGE <journal>` → une seule ligne (2353).
- Les 17 lignes Error / Warning entre 2240 et 2344 sont des messages de connexion (`LogHttpConnection … socket_send_failure`,
`WriteBytes sent -1/279`, `LogModelContextProtocol … server/discover`, `Unknown session id`), toutes entre `10.47.47` et `10.47.51`,
avant mes écritures : sans lien avec la compilation.
### 1.5 Comportement et garde `Accessed None` (`lp-mcp` § 1 règle 4)
- Garde par `IsValidIndex(Person, 0)` + Branche, sans AND / OR / Select. « `Person` vide » est un **état normal** : variable
`CurrentCompanion` sans compagnon, évaluée par `isCreatureType` des scènes `meet_new_person_pet` / `meet_new_person_horse`
(SPEC § 1.2).
- `Person` à au moins 1 élément : `then` → `VariableSet_23`, chemin d'origine inchangé (même nœud, mêmes entrées).
- `Person` vide : `else` → `VariableSet_52` (`BoolToReturn = false`) → `IfThenElse_8994`. Valeur identique à l'existant
(`isCreatureType(None, …)` = false : dump P1 `dumps\GI__isCreatureType_P1.txt`, SPEC « Décisions » ; non rejoué ici), sans
`Array_Get` hors limites ni `Accessed None … property Actor` (effet voulu de la variante b).
## 2. Écarts à la SPEC
- **Graphe** : aucun. 3 nœuds, 1 coupure, 6 liens, 594 nœuds, `BoolToReturn` = false, `IndexToTest` = 0, conformes au paragraphe
« Variante b » du § 2.2.
- **Préalables P2-P3** (MD5, gel, `Snapshot.ps1`, `load_asset`) : MD5 contrôlés, instantané pris par l'orchestrateur (fiche,
rubrique 3) ; `load_asset {asset_path:"/Game/BPs/GI"}` fait par moi → `{"refPath":"/Game/BPs/GI.GI"}`.
- **Positions des nœuds** : choisies par moi (la SPEC ne les fixe pas), effet visuel seulement.
- **`CallFunction_27` sans broche `self`** dans `get_node_infos`, alors que le dump P1 montre `self (vide)` : broche masquée
(estimé), sans lien dans les deux sources ; pas un écart de liens.
- **Procédure** : un seul appel MCP par message, partout. Lectures hors liste, sans écriture : `STE-H10-GI2-IMPL.md` (noms des
toolsets) et `dumps\GI__CallFunctionReturnBool_P1.txt` (comparaison). Un Read du journal entier a échoué (fichier > 256 Ko),
repris par `tail -n +N | grep`.
## 3. Instantané
Non relancé, sur consigne de la fiche. Instantané du lot STE-H3d, pris par l'orchestrateur :
`D:\Game\LifePlay_Backup_5.5\STE-H3d\Content\BPs\GI.uasset`, MD5 `6a957cb2a654fd1a06ff25cec9727955` (relu au début et à la fin de la
fiche) ; manifeste `D:\Game\LifePlay_Backup_5.5\STE-H3d\manifest.csv` (non relu).
Retour arrière proposé, jamais lancé : éditeur fermé, sur décision de l'orchestrateur,
`.\Tools\Restore.ps1 -Lot STE-H3d -Only Content\BPs\GI.uasset -WhatIf`, puis sans `-WhatIf` ; MD5 attendu ensuite
`6a957cb2a654fd1a06ff25cec9727955`. Attention (SPEC § 3) : cet état contient l'écriture CAM B1 non commitée ; le retour la garde.
Entrée de journal (`sk-change-safety`) : `2026-10-13 12:51 | G13 variante b, GI:CallFunctionReturnBool (+3 nœuds, 1 coupure, 6 liens) |
Content/BPs/GI.uasset | retour arrière : Restore.ps1 -Lot STE-H3d -Only Content\BPs\GI.uasset | instantané : LifePlay_Backup_5.5\STE-H3d |
vérification : 591 → 594, relecture conforme, MD5 c4817b84…`.
## 4. Ce qui n'a pas été fait
- `LPDumpFunction` et `CompileAllBlueprints` éditeur fermé : VAL (`lp-mcp` § 1 règle 3, SPEC § 7).
- Build empaqueté, parcours de jeu, `LogStats` : hors rôle (`lp-mcp` § 1 règle 5).
- Fermeture de l'éditeur, `UeState.ps1`, `BUILD-FIN` : orchestrateur.
- `hyper_blueprint_debug_inspect` : absent du serveur ; remplacé par la compilation avertissements en erreurs + journal (fiche).
- G14, variante a, `set_pin_value`, `delete_node` : interdits ou hors fiche.
## 5. Points à confirmer en VAL
- `LPDumpFunction -BP=GI -Fn=CallFunctionReturnBool -Pins -Exec` → **594** nœuds ; `CallFunction_21.then` → `IfThenElse_2.execute` seul.
- `IfThenElse_2.Condition` ← `CallArrayFunction_5.ReturnValue` ; `CallArrayFunction_5.TargetArray` ← `BreakStruct_956.Person_24_…`.
- `CallArrayFunction_5.IndexToTest` = 0.
- `IfThenElse_2.then` → `VariableSet_23.execute` ; `VariableSet_23` inchangé (`BoolToReturn` ← `CallFunction_27.True`, `then` → `IfThenElse_8994`).
- `IfThenElse_2.else` → `VariableSet_52` (`BoolToReturn` = false) → `IfThenElse_8994.execute`.
- `GetArrayItem_2346` toujours relié à `BreakStruct_956.Person_24_…` et à `CallFunction_27.Actor`.
- `python Tools\DiffRemplacementNoeuds.py` contre `dumps\GI__CallFunctionReturnBool_P1.txt` : aucun autre écart.
- `Content\BPs\GI.uasset` = `c4817b847ecf246c859647577647d6e9` (2026-10-13 12:51:23 +0200) ; `git status --short -- Content` = GI seul.
- `CompileAllBlueprints` éditeur fermé : BP `/Game/` 0 erreur, rien de nouveau sur GI.
- En jeu (SPEC § 7.3) : `Person_24_.*of length 0` ≤ 1 ; `isCreatureType:64X` = 0 ; paire F2 + `property Actor` = 0 ; non-régression des
`CHECKING: …meet_new_person` et des chemins avec compagnon (chemin `then` d'origine).
## 6. Fichiers à commiter
Dépôt du jeu, copie 5.8, branche `ue5.8` (ticket au gardien) :
- `A Docs/Migration/etat/ST/STE/STE-H3d-IMPL.md` (ce livrable).
- `M Content/BPs/GI.uasset` (MD5 `c4817b847ecf246c859647577647d6e9`, 2026-10-13 12:51:23 +0200 ; contient aussi CAM B1, non commité), après
la VAL.
- Aucun autre `.uasset` : `git status --short -- Content` = ` M Content/BPs/GI.uasset` seul.
Tours : 41 / 45
## Constats
- `get_node_infos` accepte plusieurs nœuds par appel (10 en une réponse) : une relecture complète tient en deux appels, `SwitchString_77`
et `IfThenElse_8994` à part (réponses longues).
- `find_node_types` filtré sur `IsValidIndex` rend 4 `type_id` ; celui des tableaux est `Utilitaires|Tableau|IsValidIndex`. Sa broche
`TargetArray` est « Matrice de Caractère de remplacements » avant câblage et prend le type du tableau relié.
- La Branche créée a `Condition` = `true` par défaut ; le Set de variable créé porte la valeur par défaut `false`.
- Comparer les sources d'une broche d'exécution très chargée sans fichier : dans la transcription de l'agent,
`grep -o 'name[^a-z]*else.*name[^a-z]*execute' | grep -o 'K2Node_[A-Za-z]*_[0-9]*' | sort -u`, puis `comm -3` des deux lectures.
- Le journal headless dépasse 256 Ko après le chargement : Read sans `limit` échoue ; lire par `tail -n +N <journal> | grep -v 'Dispatching toolset tool'`.
- Le journal contient un chemin `C:/Users/…` (DDC) : ne pas le recopier dans un livrable.