LifePlay-Revival/Docs/Migration/etat/sandbox/S1/S1-CART.md
edujiro5972 04b053554f Sandbox addon : brancher le jeu sur LifePlay-Sandbox (plugin LPSandbox).
Charge le plugin via AdditionalPluginDirectories, conserve ShowCouple et les commandlets anim côté jeu, et documente les lots S0–S8 (CHG-212 à CHG-220).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-06 21:10:53 +02:00

193 lines
17 KiB
Markdown

# S1-CART — Cartographie et classification des chemins Sandbox
- **Date :** 2026-10-06
- **Fiche :** S1-T3 | **Agent :** A-CART | **Rôle :** Cartographie & Audit de conformité S1
- **Modèle prévu :** `gemini-3.8-flash-high` | **Modèle utilisé :** `gemini-3.8-flash-high`
- **Référence spécification :** `Docs/Migration/etat/sandbox/S1/S1-SPEC.md`
- **Référence implémentation :** `Docs/Migration/etat/sandbox/S1/S1-IMPL.md`
---
## 1. Périmètre et méthode
### Fichiers audités
- `Source/LifePlay/LPPairSandbox.cpp`
- `Source/LifePlay/LPAnimRedirect.cpp`
- `Source/LifePlay/LPSandboxConfig.h`
- `Source/LifePlay/LPSandboxConfig.cpp`
- *(En-têtes associés pour traçabilité : `LPPairSandbox.h`, `LPAnimRedirect.h`)*
### Motifs recherchés
1. `/Game/Heavy`
2. `/Game/BPs/Person`
3. `vin_Base`
4. `Quaternius`
### Grille de classification
- **OK default** : Hit localisé dans `LPSandboxConfig.*` (valeur par défaut conforme au contrat `S1-SPEC.md` ou lecture de clé ini), ou appel dynamique via `FLPSandboxConfig::Get().<Champ>` dans le code exécutable.
- **DETTE (hors contrat volontaire)** : Identifiant C++ interne (méthode, membre, classe), chaîne de log, texte informatif UI Slate ou commentaire explicitement exclu du contrat d'externalisation ini par `S1-SPEC.md`.
- **OUBLI** : Littéral de chemin restant en dur dans le code d'exécution qui aurait dû passer par la configuration `FLPSandboxConfig`.
---
## 2. Inventaire et classification des hits
### 2.1. Motif `/Game/Heavy`
| Fichier | Ligne | Extrait / Contexte | Classification | Justification |
|---|---:|---|---|---|
| `LPSandboxConfig.h` | 16 | `FString BridgetMesh = TEXT("/Game/Heavy/Daz/Bridget/bridget_gp.bridget_gp");` | **OK default** | Default contractuel clé `BridgetMesh` (`[Sandbox.Assets]`) |
| `LPSandboxConfig.h` | 17 | `FString MichaelMesh = TEXT("/Game/Heavy/Daz/Michael/michael.michael");` | **OK default** | Default contractuel clé `MichaelMesh` (`[Sandbox.Assets]`) |
| `LPSandboxConfig.h` | 19 | `FString DazIdleFemale = TEXT("/Game/Heavy/Daz/Anims/Idle_F_Daz.Idle_F_Daz");` | **OK default** | Default contractuel clé `DazIdleFemale` (`[Sandbox.Assets]`) |
| `LPSandboxConfig.h` | 20 | `FString DazIdleMale = TEXT("/Game/Heavy/Daz/Anims/idle_Daz.idle_Daz");` | **OK default** | Default contractuel clé `DazIdleMale` (`[Sandbox.Assets]`) |
| `LPSandboxConfig.h` | 21 | `FString FurnitureWallMaterial = TEXT("/Game/Heavy/New2/Furniture/Materials/FntWall.FntWall");` | **OK default** | Default contractuel clé `FurnitureWallMaterial` (`[Sandbox.Assets]`) |
| `LPSandboxConfig.h` | 24 | `FString FurnitureRoot = TEXT("/Game/Heavy/New2/Furniture");` | **OK default** | Default contractuel clé `FurnitureRoot` (`[Sandbox.Roots]`) |
| `LPSandboxConfig.h` | 25 | `FString DazAnimRoot = TEXT("/Game/Heavy/Daz/Anims");` | **OK default** | Default contractuel clé `DazAnimRoot` (`[Sandbox.Roots]`) |
| `LPSandboxConfig.h` | 36 | `FString SkyCubemap = TEXT("/Game/Heavy/New2/Buildings/Mats/urban_street_03_1k.urban_street_03_1k");` | **OK default** | Default contractuel clé `SkyCubemap` (`[Sandbox.Sky]`) |
| `LPSandboxConfig.cpp` | - | *Aucun littéral brut* (lecture des clés ini par nom de clé) | **OK default** | Respecte le contrat |
| `LPPairSandbox.cpp` | 858 | `*FLPSandboxConfig::Get().FurnitureRoot` | **OK default** | Consommateur config (ancien l.857 `/Game/Heavy/New2/Furniture`) |
| `LPPairSandbox.cpp` | 878 | `*FLPSandboxConfig::Get().FurnitureWallMaterial` | **OK default** | Consommateur config (ancien l.877 `.../FntWall.FntWall`) |
| `LPPairSandbox.cpp` | 1002 | `*FLPSandboxConfig::Get().SkyCubemap` | **OK default** | Consommateur config (ancien l.1001 `urban_street_03_1k`) |
| `LPPairSandbox.cpp` | 1079 | `FLPSandboxConfig::Get().DazIdleFemale` | **OK default** | Consommateur config (ancien l.1078 `Idle_F_Daz`) |
| `LPPairSandbox.cpp` | 1080 | `FLPSandboxConfig::Get().DazIdleMale` | **OK default** | Consommateur config (ancien l.1079 `idle_Daz`) |
| `LPPairSandbox.cpp` | 1530 | `*FLPSandboxConfig::Get().BridgetMesh` | **OK default** | Consommateur config (ancien l.1529 `bridget_gp`) |
| `LPPairSandbox.cpp` | 2611 | `*FLPSandboxConfig::Get().DazAnimRoot` | **OK default** | Consommateur config (ancien l.2610 `/Game/Heavy/Daz/Anims`) |
| `LPPairSandbox.cpp` | 3028 | `FLPSandboxConfig::Get().BridgetMesh` | **OK default** | Consommateur config (ancien l.3026 `bridget_gp`) |
| `LPPairSandbox.cpp` | 3031 | `FLPSandboxConfig::Get().MichaelMesh` | **OK default** | Consommateur config (ancien l.3030 `michael`) |
| `LPPairSandbox.cpp` | 3108 | `*FLPSandboxConfig::Get().DazAnimRoot` | **OK default** | Consommateur config (ancien l.3106 `/Game/Heavy/Daz/Anims`) |
| `LPAnimRedirect.cpp` | - | *Aucun hit* | - | Conforme |
**Bilan `/Game/Heavy` :** 8 `OK default` (définitions `LPSandboxConfig.h`), 10 `OK default` (consommations `LPPairSandbox.cpp`), 0 DETTE, 0 OUBLI.
---
### 2.2. Motif `/Game/BPs/Person`
| Fichier | Ligne | Extrait / Contexte | Classification | Justification |
|---|---:|---|---|---|
| `LPSandboxConfig.h` | 15 | `FString PersonBP = TEXT("/Game/BPs/Person.Person_C");` | **OK default** | Default contractuel clé `PersonBP` (`[Sandbox.Assets]`) |
| `LPSandboxConfig.cpp` | 46 | `SandboxCfgReadString(File, TEXT("Sandbox.Assets"), TEXT("PersonBP"), PersonBP);` | **OK default** | Lecture ini de la clé `PersonBP` |
| `LPPairSandbox.cpp` | 845 | `LoadObject<UClass>(nullptr, *FLPSandboxConfig::Get().PersonBP);` | **OK default** | Consommateur config dans `Build` (ancien l.844) |
| `LPPairSandbox.cpp` | 1090 | `LoadObject<UClass>(nullptr, *FLPSandboxConfig::Get().PersonBP);` | **OK default** | Consommateur config dans `ConfigureCapsule` (ancien l.1089) |
| `LPAnimRedirect.cpp` | - | *Aucun hit* | - | Conforme |
*(Note : les occurrences de `PersonClass`, `PersonCap`, `struct FPerson` dans `LPPairSandbox.cpp` sont des symboles C++ / AST interne de script, sans aucun littéral de chemin).*
**Bilan `/Game/BPs/Person` :** 2 `OK default` (`LPSandboxConfig.*`), 2 `OK default` (`LPPairSandbox.cpp`), 0 DETTE, 0 OUBLI.
---
### 2.3. Motif `vin_Base`
| Fichier | Ligne | Extrait / Contexte | Classification | Justification |
|---|---:|---|---|---|
| `LPSandboxConfig.h` | 30 | `FString ModuleRoot = TEXT("Modules/vin_Base");` | **OK default** | Default contractuel clé `ModuleRoot` (`[Sandbox.Content]`) |
| `LPSandboxConfig.h` | 31 | `FString WorldFile = TEXT("Modules/vin_Base/World/work___vin01.lpworld");` | **OK default** | Default contractuel clé `WorldFile` (`[Sandbox.Content]`) |
| `LPSandboxConfig.h` | 32 | `FString ChatAction = TEXT("Modules/vin_Base/Interactions/chat.lpaction");` | **OK default** | Default contractuel clé `ChatAction` (`[Sandbox.Content]`) |
| `LPSandboxConfig.cpp` | 59-61 | *Lectures `ModuleRoot`, `WorldFile`, `ChatAction`* | **OK default** | Lectures ini des clés |
| `LPPairSandbox.cpp` | 623 | `FPaths::Combine(..., FLPSandboxConfig::Get().ModuleRoot)` | **OK default** | Consommateur config dans `LoadActions` (ancien l.622) |
| `LPPairSandbox.cpp` | 833 | `FPaths::Combine(..., FLPSandboxConfig::Get().WorldFile)` | **OK default** | Consommateur config dans `Build` (ancien l.832) |
| `LPPairSandbox.cpp` | 1046 | `FPaths::Combine(..., FLPSandboxConfig::Get().ChatAction)` | **OK default** | Consommateur config dans `LoadChat` (ancien l.1045) |
| `LPAnimRedirect.cpp` | - | *Aucun hit* | - | Conforme |
**Bilan `vin_Base` :** 3 `OK default` (`LPSandboxConfig.h`), 3 `OK default` (`LPPairSandbox.cpp`), 0 DETTE, 0 OUBLI.
---
### 2.4. Motif `Quaternius`
| Fichier | Ligne | Extrait / Contexte | Classification | Justification |
|---|---:|---|---|---|
| `LPSandboxConfig.h` | 18 | `FString QuaterniusMannequinMesh = TEXT("/Game/Quaternius/UAL/UAL1_Standard.UAL1_Standard");` | **OK default** | Default contractuel clé `QuaterniusMannequinMesh` |
| `LPSandboxConfig.h` | 26 | `FString QuaterniusRoot = TEXT("/Game/Quaternius");` | **OK default** | Default contractuel clé `QuaterniusRoot` |
| `LPSandboxConfig.h` | 27 | `FString QuaterniusUALRoot = TEXT("/Game/Quaternius/UAL");` | **OK default** | Default contractuel clé `QuaterniusUALRoot` |
| `LPSandboxConfig.h` | 33 | `FString QuaterniusUALDisk = TEXT("Quaternius/UAL");` | **OK default** | Default contractuel clé `QuaterniusUALDisk` |
| `LPSandboxConfig.cpp` | 49 | `SandboxCfgReadString(..., TEXT("QuaterniusMannequinMesh"), ...);` | **OK default** | Lecture ini clé `QuaterniusMannequinMesh` |
| `LPSandboxConfig.cpp` | 56 | `SandboxCfgReadString(..., TEXT("QuaterniusRoot"), ...);` | **OK default** | Lecture ini clé `QuaterniusRoot` |
| `LPSandboxConfig.cpp` | 57 | `SandboxCfgReadString(..., TEXT("QuaterniusUALRoot"), ...);` | **OK default** | Lecture ini clé `QuaterniusUALRoot` |
| `LPSandboxConfig.cpp` | 62 | `SandboxCfgReadString(..., TEXT("QuaterniusUALDisk"), ...);` | **OK default** | Lecture ini clé `QuaterniusUALDisk` |
| `LPAnimRedirect.cpp` | 23 | `*FLPSandboxConfig::Get().QuaterniusUALRoot` | **OK default** | Formatage dynamique `ClipPath` via config |
| `LPAnimRedirect.h` | 4 | `// Les fichiers restent dans /Game/Quaternius/UAL.` | **DETTE** | Commentaire d'en-tête informatif (aucun impact runtime) |
| `LPPairSandbox.h` | 240 | `void LoadQuaternius();` | **DETTE** | Déclaration méthode C++ interne |
| `LPPairSandbox.h` | 261 | `FString QuaterniusMesh;` | **DETTE** | Déclaration membre C++ interne de cache |
| `LPPairSandbox.h` | 262 | `TMap<FString, FString> QuaterniusClips;` | **DETTE** | Déclaration membre C++ interne de cache |
| `LPPairSandbox.cpp` | 1529 | `*FLPSandboxConfig::Get().QuaterniusMannequinMesh` | **OK default** | Consommateur config dans `BeginMeasure` |
| `LPPairSandbox.cpp` | 1890 | `// Clips du mannequin ... les 43 clips Quaternius.` | **DETTE** | Commentaire de documentation interne |
| `LPPairSandbox.cpp` | 1895 | `FLPSandboxConfig::Get().QuaterniusUALDisk` | **OK default** | Consommateur config dans `GetMeasureClips` |
| `LPPairSandbox.cpp` | 2773 | `LoadQuaternius();` | **DETTE** | Appel méthode C++ interne |
| `LPPairSandbox.cpp` | 2958 | `void ALPPairSandboxCharacter::LoadQuaternius()` | **DETTE** | Définition méthode C++ interne |
| `LPPairSandbox.cpp` | 2960 | `QuaterniusMesh.Reset();` | **DETTE** | Utilisation membre C++ interne |
| `LPPairSandbox.cpp` | 2961 | `QuaterniusClips.Reset();` | **DETTE** | Utilisation membre C++ interne |
| `LPPairSandbox.cpp` | 2963 | `FLPSandboxConfig::Get().QuaterniusRoot` | **OK default** | Scan synchronous via clé config |
| `LPPairSandbox.cpp` | 2965 | `*FLPSandboxConfig::Get().QuaterniusUALRoot` | **OK default** | Recherche assets via clé config |
| `LPPairSandbox.cpp` | 2977 | `QuaterniusMesh = Data.GetSoftObjectPath().ToString();` | **DETTE** | Assignation membre C++ interne |
| `LPPairSandbox.cpp` | 2986 | `QuaterniusClips.Add(Name, Data.GetSoftObjectPath().ToString());` | **DETTE** | Assignation membre C++ interne |
| `LPPairSandbox.cpp` | 2990 | `if (!QuaterniusClips.Contains(TEXT("Walk_Loop")))` | **DETTE** | Consultation membre C++ interne |
| `LPPairSandbox.cpp` | 2994 | `UE_LOG(LogLifePlay, Warning, TEXT("Sandbox Quaternius : ..."), ...);` | **DETTE** | Tag de log console informatif |
| `LPPairSandbox.cpp` | 3024 | `FString Path = QuaterniusMesh;` | **DETTE** | Lecture membre C++ interne |
| `LPPairSandbox.cpp` | 3035 | `LoadQuaternius();` | **DETTE** | Appel méthode C++ interne |
| `LPPairSandbox.cpp` | 3036 | `Path = QuaterniusMesh;` | **DETTE** | Lecture membre C++ interne |
| `LPPairSandbox.cpp` | 3479 | `LoadQuaternius();` | **DETTE** | Appel méthode C++ interne |
| `LPPairSandbox.cpp` | 3482 | `QuaterniusClips.GetKeys(ClipNames);` | **DETTE** | Lecture membre C++ interne |
| `LPPairSandbox.cpp` | 3883 | `TEXT("MC et PNJ jouent le meme clip Quaternius...")` | **DETTE** | Texte UI Slate explicatif (hors contrat ini) |
**Bilan `Quaternius` :** 13 `OK default` (4 en `.h`, 4 en `.cpp`, 5 consommateurs), 19 `DETTE` (identifiants C++, logs, Slate UI, commentaires), 0 OUBLI.
---
## 3. Matrice de couverture contractuelle `S1-SPEC.md`
Vérification des 19 clés définies dans `Docs/Migration/etat/sandbox/S1/S1-SPEC.md` :
| Clé | Section | Valeur Default contractuelle | Statut Implémentation | Statut Littéral Résiduel |
|---|---|---|---|---|
| `PersonBP` | `Sandbox.Assets` | `/Game/BPs/Person.Person_C` | Implémenté (`FLPSandboxConfig`) | Aucun littéral durci restant |
| `BridgetMesh` | `Sandbox.Assets` | `/Game/Heavy/Daz/Bridget/bridget_gp.bridget_gp` | Implémenté (`FLPSandboxConfig`) | Aucun littéral durci restant |
| `MichaelMesh` | `Sandbox.Assets` | `/Game/Heavy/Daz/Michael/michael.michael` | Implémenté (`FLPSandboxConfig`) | Aucun littéral durci restant |
| `QuaterniusMannequinMesh` | `Sandbox.Assets` | `/Game/Quaternius/UAL/UAL1_Standard.UAL1_Standard` | Implémenté (`FLPSandboxConfig`) | Aucun littéral durci restant |
| `DazIdleFemale` | `Sandbox.Assets` | `/Game/Heavy/Daz/Anims/Idle_F_Daz.Idle_F_Daz` | Implémenté (`FLPSandboxConfig`) | Aucun littéral durci restant |
| `DazIdleMale` | `Sandbox.Assets` | `/Game/Heavy/Daz/Anims/idle_Daz.idle_Daz` | Implémenté (`FLPSandboxConfig`) | Aucun littéral durci restant |
| `FurnitureWallMaterial` | `Sandbox.Assets` | `/Game/Heavy/New2/Furniture/Materials/FntWall.FntWall` | Implémenté (`FLPSandboxConfig`) | Aucun littéral durci restant |
| `FurnitureRoot` | `Sandbox.Roots` | `/Game/Heavy/New2/Furniture` | Implémenté (`FLPSandboxConfig`) | Aucun littéral durci restant |
| `DazAnimRoot` | `Sandbox.Roots` | `/Game/Heavy/Daz/Anims` | Implémenté (`FLPSandboxConfig`) | Aucun littéral durci restant |
| `QuaterniusRoot` | `Sandbox.Roots` | `/Game/Quaternius` | Implémenté (`FLPSandboxConfig`) | Aucun littéral durci restant |
| `QuaterniusUALRoot` | `Sandbox.Roots` | `/Game/Quaternius/UAL` | Implémenté (`FLPSandboxConfig`) | Aucun littéral durci restant |
| `ModuleRoot` | `Sandbox.Content` | `Modules/vin_Base` | Implémenté (`FLPSandboxConfig`) | Aucun littéral durci restant |
| `WorldFile` | `Sandbox.Content` | `Modules/vin_Base/World/work___vin01.lpworld` | Implémenté (`FLPSandboxConfig`) | Aucun littéral durci restant |
| `ChatAction` | `Sandbox.Content` | `Modules/vin_Base/Interactions/chat.lpaction` | Implémenté (`FLPSandboxConfig`) | Aucun littéral durci restant |
| `QuaterniusUALDisk` | `Sandbox.Content` | `Quaternius/UAL` | Implémenté (`FLPSandboxConfig`) | Aucun littéral durci restant |
| `SkyCubemap` | `Sandbox.Sky` | `/Game/Heavy/New2/Buildings/Mats/urban_street_03_1k.urban_street_03_1k` | Implémenté (`FLPSandboxConfig`) | Aucun littéral durci restant |
| `SkyIntensity` | `Sandbox.Sky` | `0.6` | Implémenté (`FLPSandboxConfig`) | Aucun littéral durci restant |
| `MeasureOutputRoot` | `Sandbox.Output` | `Measurement` | Implémenté (`FLPSandboxConfig`) | Aucun littéral durci restant |
| `Mode` | `Sandbox.Mode` | `Pair` | Implémenté (`FLPSandboxConfig`) | Aucun littéral durci restant |
---
## 4. Analyse des DETTES et éléments hors contrat
Conformément à la section 1 de `S1-SPEC.md`, les éléments suivants ont été laissés hors contrat de façon volontaire et justifiée :
1. **Symboles C++ internes :** Les identifiants `LoadQuaternius()`, `QuaterniusMesh`, `QuaterniusClips` sont des noms de symboles internes au monolithe `ALPPairSandboxCharacter`. Leur renommage relève du refactoring / renommage de pipeline et non de la configuration de chemins.
2. **Textes d'interface utilisateur (UI Slate) :** La ligne 3883 de `LPPairSandbox.cpp` contient une aide contextuelle pour les développeurs (`MC et PNJ jouent le meme clip Quaternius...`). Elle ne référence aucun asset UE et n'impacte pas le pipeline d'import/redirection.
3. **Logs d'information console :** Les chaînes de logging (`UE_LOG(LogLifePlay, Warning, TEXT("Sandbox Quaternius : corps %s..."))`) servent au diagnostic développeur.
4. **Littéraux Engine & Poses conventionnelles :** Les chemins `/Engine/BasicShapes/Cube.Cube` (l.877), `/Engine/EngineSky/BP_Sky_Sphere.BP_Sky_Sphere_C` (l.1025) ainsi que les noms de poses conventionnels (`Idle_Loop`, `Walk_Loop`, `A_TPose`, préfixes `B_`/`M_`) restent en dur comme stipulé au contrat.
5. **Observation périphérique hors périmètre :** `Source/LifePlay/LPInteractionSandbox.cpp` contient encore des chemins en dur (`/Game/Heavy/...`, `Modules/vin_Base/...`). Ce fichier correspond à l'ancienne sandbox d'interaction legacy (marquée comme obsolète dans `S0-CART.md`) et ne fait pas partie du périmètre S1 défini par `S1-SPEC.md` (qui se concentre sur `LPPairSandbox` et `LPAnimRedirect`).
---
## 5. Synthèse et critère Done
### Synthèse quantitative
- **Hits totaux audités sur les 4 motifs :** 47
- **OK default :** 28 (initialiseurs dans `LPSandboxConfig.h`, parsers dans `LPSandboxConfig.cpp`, consommations via `FLPSandboxConfig::Get()` dans `LPPairSandbox.cpp` et `LPAnimRedirect.cpp`)
- **DETTE (hors contrat volontaire) :** 19 (symboles C++, logs, aide Slate UI, commentaires)
- **OUBLI :** 0
### Critère Done
> **Critère Done : aucun OUBLI bloquant non justifié.**
- **Résultat :** **ATTEINT (100% CONFORME)**.
- Aucun littéral de chemin d'asset ou de fichier disque correspondant aux motifs recherchés n'est resté en dur dans `Source/LifePlay/LPPairSandbox.cpp` ou `Source/LifePlay/LPAnimRedirect.cpp`.
- Tous les chemins passent sans exception par la configuration centralisée `FLPSandboxConfig::Get()`.