LifePlay-Revival/Docs/Migration/etat/ETAT2/ETAT2-T4-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

361 lines
32 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ETAT2-T4-IMPL — étape A4 : gabarits `etat` des skills et `Tools\SyncModSources.ps1` (addon, `lot/DC3-atelier`)
Fiche ETAT2-T4-IMPL (étape A4) — Niveau N2 — Modèle prévu lp-impl | utilisé Opus 5.5 (`claude-opus-5-5`, identifiant donné par l'environnement de l'agent) — Agent lp-impl (invite système de l'agent : rôle A-IMPL-H, N3) — Skills sk-protocol, ue-cpp-build, lp-build, lp-ue-compat (préchargés) ; lp-paths et sk-change-safety cités par la fiche, **non préchargés** et non invoqués (procédure d'instantané suivie telle que la fiche l'écrit)
Date : 2026-10-09, 15:13 à 15:20. Dépôt touché : `D:\Game\LifePlay-Sandbox` (branche `lot/DC3-atelier`, HEAD `6295829`). Aucun commit, aucune écriture dans `D:\Game\LifePlay-Sandbox-5.8` ni dans les jeux, aucun UE lancé, aucune suppression.
Source appliquée : `D:\Game\LifePlay-master 5.5\Docs\Migration\etat\ETAT2\ETAT2-T1-CART.md` § 3 (l. 278-294), § 5 (l. 319-395), § 6 ligne A4 (l. 408). Décisions : D10 (a), D11 (a), D12 (a).
**Résultat : partiel.** Étapes a, b, c faites ; analyse syntaxique 0 erreur ; **l'essai à blanc renvoie le code 2 (refus : `UnrealEditor ouvert (PID 32972)`)** au lieu de 174 `IDENTIQUE` et du code 0 attendus ; essai positif non lancé (même refus, voir § 5).
## 1. Contrôles de départ (établi)
| Contrôle | Résultat | Commande |
|---|---|---|
| Branche, état addon | `lot/DC3-atelier`, arbre propre, HEAD `6295829` | `git -C D:\Game\LifePlay-Sandbox branch --show-current ; status --short ; log --oneline -1` |
| Tag `ETAT2*` préexistant | aucun | `git -C … tag -l 'ETAT*'` |
| Passages « Texte actuel » du § 3 | **les 11 correspondent** au fichier réel, aux lignes citées (`lp-build:33,115,118-119`, `lp-commandlets:21-22`, `lp-lot:50-51`, `lp-paths:32,43,49-51`, `lp-validate:14,50,83`) | `grep -n -E "etat[\\/]" <5 SKILL.md>` (26 lignes / 9 fichiers dans tout `skills`, comme § 1.2) ; lecture des lignes |
| `.gitignore` du jeu cité par la ligne facultative `lp-paths:43` | `:53` = `/Docs/Migration/etat/**/*.txt`, `:74` = `/Docs/Migration/etat/` (identique sur `main` et `ue5.8`) | `grep -n -i etat .gitignore` ; `git -C …5.8 show ue5.8:.gitignore \| grep -n -i etat` |
| Format des fichiers voisins | 5 `SKILL.md` : UTF-8 sans BOM, **LF** ; `Tools\*.ps1` de l'addon : ASCII sans BOM, **LF** (`.gitattributes` : `* -text`) | `git ls-files --eol` ; `od -c` ; `head -c3 \| od` |
| Processus Unreal | `32972 UnrealEditor` (`UE_5.8\…\UnrealEditor.exe`, lancé 14:53:13, session STM de la copie 5.8) | `Get-Process -Name UnrealEditor,UnrealEditor-Cmd` |
## 2. Instantané et tag
Commande (rejouée telle que la fiche l'écrit) :
```
pwsh -NoProfile -Command "Set-Location 'D:\Game\LifePlay-master 5.5'; .\Tools\Snapshot.ps1 -Lot ETAT2-addon -ProjectRoot 'D:\Game\LifePlay-Sandbox' -Path Tools\claude\skills\lp-build\SKILL.md,Tools\claude\skills\lp-commandlets\SKILL.md,Tools\claude\skills\lp-lot\SKILL.md,Tools\claude\skills\lp-paths\SKILL.md,Tools\claude\skills\lp-validate\SKILL.md,Tools\SyncModSources.ps1"
```
Sortie : 6 entrées, code 0. Manifeste `D:\Game\LifePlay_Backup_5.5\ETAT2-addon\manifest.csv` :
| Rel | Existed | Taille | MD5 |
|---|---|---|---|
| `Tools\claude\skills\lp-build\SKILL.md` | True | 13586 | `7BA202F866F64B04A38CBB16DAB779E6` |
| `Tools\claude\skills\lp-commandlets\SKILL.md` | True | 4829 | `0CB3950069DB11C81C0F759A65FC5DAC` |
| `Tools\claude\skills\lp-lot\SKILL.md` | True | 4856 | `2FD9BD1D834A61F4F999350F96ECF545` |
| `Tools\claude\skills\lp-paths\SKILL.md` | True | 5332 | `DEF8D39CEE738F085FFD3E6D77F38162` |
| `Tools\claude\skills\lp-validate\SKILL.md` | True | 6525 | `B7D210B7193D193A7EB062A27545A65C` |
| `Tools\SyncModSources.ps1` | False | 0 | — (sera déplacé par `Restore.ps1`) |
Tag : `git -C D:\Game\LifePlay-Sandbox tag ETAT2-avant` → `62958298209db54abed1d38d51889aed2447cfb9 refs/tags/ETAT2-avant` (= HEAD). Retour arrière possible : `Tools\Restore.ps1 -Lot ETAT2-addon -ProjectRoot 'D:\Game\LifePlay-Sandbox'` ou `git -C … checkout ETAT2-avant -- Tools/claude/skills` (proposé seulement).
## 3. Modifications (étape c)
### 3.1 Contrôle des formats après écriture (établi)
`python -c "…b.count(b'\r\n')…"` : les 5 `SKILL.md` et `SyncModSources.ps1` ont `CRLF 0`, BOM absent ; `SyncModSources.ps1` : 70 lignes, 0 octet non ASCII, se termine par LF, MD5 `4cff4f9935825c303353fbdb4f9fc61a`.
Le script est **identique à l'octet** au bloc du § 5 : `diff <(sed -n '324,393p' ETAT2-T1-CART.md | tr -d '\r') Tools/SyncModSources.ps1` → aucune différence (extrait par `sed`, pas recopié à la main).
### 3.2 `git -C D:\Game\LifePlay-Sandbox diff --stat`
```
Tools/claude/skills/lp-build/SKILL.md | 12 ++++++++----
Tools/claude/skills/lp-commandlets/SKILL.md | 3 ++-
Tools/claude/skills/lp-lot/SKILL.md | 3 ++-
Tools/claude/skills/lp-paths/SKILL.md | 10 ++++++----
Tools/claude/skills/lp-validate/SKILL.md | 6 +++---
5 files changed, 21 insertions(+), 13 deletions(-)
```
+ 1 fichier non suivi : `Tools/SyncModSources.ps1` (texte : § 5 de la cartographie, l. 324-393).
### 3.3 Diff complet (`git -C D:\Game\LifePlay-Sandbox diff`)
```diff
--- a/Tools/claude/skills/lp-build/SKILL.md
+++ b/Tools/claude/skills/lp-build/SKILL.md
@@ -30,7 +30,8 @@ Set-Location 'D:\Game\LifePlay-master 5.8'
UBA a donné des C1001/C2206 non déterministes sous mémoire engagée élevée.
- Code 3 et rien lancé si un `UnrealEditor`/`UnrealEditor-Cmd` tourne. Sinon renvoie le code de `Build.bat`.
- Journal complet : `<copie>\Saved\Logs\portage\<lot>_Build_<horodatage>.log`.
-- **Résumé compté** : `<copie>\Docs\Migration\etat\<lot>_Build_<horodatage>.txt` : code, durée, ligne `Using Visual
+- **Résumé compté** : `<copie>\Docs\Migration\etat\<projet>\<lot>\<Lot>_Build_<horodatage>.txt` (dossier déduit du
+ lot par `Tools\EtatDir.ps1`, `-EtatDir` pour l'imposer) : code, durée, ligne `Using Visual
Studio`, makefile recréé ou réutilisé, nombre d'actions, erreurs et avertissements du compilateur groupés par code
avec `fichier:ligne`, autres lignes d'erreur (UBT, UHT, liens), unités compilées, DLL liées, `Total execution time`.
Le compte rendu recopie ces comptes ; il ne les refait pas à la main.
@@ -112,10 +113,13 @@ journal ; (8) pour l'addon : une ligne de journal propre au nouveau code. Code 0
échec probable : signaler `Makefile.bin` / DLL périmées. L'échec EST le résultat : ne rien corriger.
## 10. Où écrire les livrables
-- Fiches et comptes rendus de lot : `D:\Game\LifePlay-master 5.5\Docs\Migration\etat\U58\<lot>\<LOT>-Tn-BUILD.md`
+- Fiches et comptes rendus de lot : `D:\Game\LifePlay-master 5.5\Docs\Migration\etat\<projet>\<lot>\<LOT>-Tn-BUILD.md`
+ (U58, ST, OB…)
(dossier de référence pour les deux copies, hors git). `D:\Game\LifePlay_Backup_5.5\etat` n'est qu'une sauvegarde :
ne pas y écrire.
-- Résumés automatiques (`Build.ps1`, `RunCommandlet.ps1`) : restent dans `<copie>\Docs\Migration\etat\` ; la fiche
- cite leur chemin complet.
+- Résumés automatiques (`Build.ps1`, `RunCommandlet.ps1`, `ReimportCorrectif.ps1`) :
+ `<copie>\Docs\Migration\etat\<projet>\<lot>\` de la copie qui les produit (table lot → projet de `Tools\EtatDir.ps1` ;
+ lot hors table : `etat\<Lot>\` + avertissement) ; la fiche cite leur chemin complet. Résumés antérieurs à ETAT2 :
+ `etat/MAPPING.csv` (5.5), `MAPPING-58.csv` (5.8).
Catalogue symptôme → cause : `symptoms.md` (annexe).
--- a/Tools/claude/skills/lp-commandlets/SKILL.md
+++ b/Tools/claude/skills/lp-commandlets/SKILL.md
@@ -19,7 +19,8 @@
- Journal complet : `Saved\Logs\portage\<Lot>_<Commandlet>_<horodatage>.log` ; résumé (erreurs et avertissements
- dédoublonnés, lignes `LogLP*`) : `Docs\Migration\etat\<Lot>_<Commandlet>_<horodatage>.txt`. Ne jamais supprimer.
+ dédoublonnés, lignes `LogLP*`) : `Docs\Migration\etat\<projet>\<lot>\<Lot>_<Commandlet>_<horodatage>.txt`
+ (`Tools\EtatDir.ps1` ; `-EtatDir` impose un dossier). Ne jamais supprimer.
--- a/Tools/claude/skills/lp-lot/SKILL.md
+++ b/Tools/claude/skills/lp-lot/SKILL.md
@@ -48,7 +48,8 @@
copie 5.8 ; `D:\Game\LifePlay_Backup_5.5\etat` n'est qu'une sauvegarde (ne pas y écrire). Résumés automatiques de
- `Build.ps1` / `RunCommandlet.ps1` : `<copie>\Docs\Migration\etat\`, cités par leur chemin complet.
+ `Build.ps1` / `RunCommandlet.ps1` : `<copie>\Docs\Migration\etat\<projet>\<lot>\` (dans la copie 5.8 : sa propre
+ arborescence `etat`, mêmes noms de dossiers), cités par leur chemin complet.
--- a/Tools/claude/skills/lp-paths/SKILL.md
+++ b/Tools/claude/skills/lp-paths/SKILL.md
@@ -29,7 +29,7 @@
-| Journaux de commandlets | `Saved\Logs\portage\` (complet) ; `Docs\Migration\etat\` (résumés `.txt`) |
+| Journaux de commandlets | `Saved\Logs\portage\` (complet) ; `Docs\Migration\etat\<projet>\<lot>\` (résumés `.txt`, `Tools\EtatDir.ps1`) |
@@ -40,15 +40,17 @@
`Releases/`, `Mods/` (doit être **vide** pendant build et commit), `ModSources/`, `AnimSources/`,
-`Plugins/McpAutomationBridge/`, `Docs/Migration/etat/**/*.txt`, `*.png`, `*.7z`, `*.mp4`, packs d'animation
+`Plugins/McpAutomationBridge/`, `Docs/Migration/etat/` (tout le dossier, `.gitignore:74` ; `:53` pour les `.txt`),
+`*.png`, `*.7z`, `*.mp4`, packs d'animation
(`Content/Quaternius`, `Content/AnimPacks`…). Addon : `/Content/` (jonction), `Binaries`, `Intermediate`, `Saved`,
@@
- `ModSources/<id>/Content/` est ignoré par git (`.gitignore:38` de l'addon) : un nouveau worktree ou checkout de
- l'addon ne l'a pas. Avant `BuildMod`, le copier depuis `D:\Game\LifePlay-Sandbox\ModSources\<id>\Content`
- (copie, MD5 contrôlés ; U7-T15). État actuel : copié dans `D:\Game\LifePlay-Sandbox-5.8` le 2026-10-09.
+ l'addon ne l'a pas. Avant `BuildMod` : `.\Tools\SyncModSources.ps1 -Target <checkout>` (à blanc : liste NOUVEAU /
+ IDENTIQUE / DIFFERENT / EN_TROP ; `-Apply` copie, MD5 relus ; ERR-046). État au 2026-10-09 :
+ `D:\Game\LifePlay-Sandbox-5.8` identique à `D:\Game\LifePlay-Sandbox` (174 fichiers).
--- a/Tools/claude/skills/lp-validate/SKILL.md
+++ b/Tools/claude/skills/lp-validate/SKILL.md
@@ -11,7 +11,7 @@
-- Lire la fiche du lot et **tous** les livrables amont (`…\Docs\Migration\etat\U58\<lot>\`).
+- Lire la fiche du lot et **tous** les livrables amont (`…\Docs\Migration\etat\<projet>\<lot>\`).
@@ -47,7 +47,7 @@
- `<copie>\Docs\Migration\etat\<lot>_LPTestStringCompat_<horodatage>.txt`).
+ `<copie>\Docs\Migration\etat\<projet>\<lot>\<Lot>_LPTestStringCompat_<horodatage>.txt`).
@@ -80,6 +80,6 @@
-- Livrable : `D:\Game\LifePlay-master 5.5\Docs\Migration\etat\U58\<lot>\<LOT>-VAL.md`, en-tête
+- Livrable : `D:\Game\LifePlay-master 5.5\Docs\Migration\etat\<projet>\<lot>\<LOT>-VAL.md`, en-tête
```
(Contexte inchangé abrégé pour `lp-commandlets`, `lp-lot`, `lp-paths`, `lp-validate` ; diff intégral rejouable : `git -C D:\Game\LifePlay-Sandbox diff ETAT2-avant`.)
Correspondance § 3 → lignes après modification : `lp-build:33-34`, `:116-117`, `:120-123` ; `lp-commandlets:22-23` ; `lp-lot:51-52` ; `lp-paths:32`, `:43-44`, `:51-53` ; `lp-validate:14`, `:50`, `:83`. Décalages induits : `lp-build` +4 lignes, `lp-commandlets` +1, `lp-lot` +1, `lp-paths` +2, `lp-validate` 0.
## 4. Contrôles statiques (étape d, établi)
Analyse syntaxique :
```
pwsh -NoProfile -Command '[System.Management.Automation.Language.Parser]::ParseFile("D:\Game\LifePlay-Sandbox\Tools\SyncModSources.ps1",[ref]$t,[ref]$e) ; $e.Count'
→ erreurs d'analyse : 0 ; jetons : 721
```
## 5. Essais (étape d)
### 5.1 Essai à blanc `LifePlay-Sandbox` → `LifePlay-Sandbox-5.8` : **échec (refus, code 2)**
```
cd D:\Game\LifePlay-Sandbox
pwsh -NoProfile -File 'D:\Game\LifePlay-Sandbox\Tools\SyncModSources.ps1' -Source 'D:\Game\LifePlay-Sandbox' -Target 'D:\Game\LifePlay-Sandbox-5.8'
SyncModSources : refus : UnrealEditor ouvert (PID 32972)
code de sortie = 2
```
Attendu par la fiche : 174 `IDENTIQUE`, code 0. Cause (établie) : `SyncModSources.ps1:29-30` refuse dès qu'un `UnrealEditor`/`UnrealEditor-Cmd` tourne sur le poste, **y compris à blanc** et sans filtre de chemin ; le PID 32972 est l'éditeur 5.8 de la session STM (`D:\Game\Launcher\Engine\UE_5.8\Engine\Binaries\Win64\UnrealEditor.exe`, lancé 14:53:13, toujours actif à 15:16:57). Ce refus est conforme au § 5 (« Refus : … UnrealEditor ouvert ») : **aucun contournement** (pas de paramètre ajouté, pas d'arrêt du processus).
Lecture seule de la cible (établi) :
- `git -C D:\Game\LifePlay-Sandbox-5.8 status --short` : vide avant (15:16:15) et après (code 0 les deux fois).
- Dates : relevé `FullName|Length|LastWriteTimeUtc.Ticks` de `D:\Game\LifePlay-Sandbox-5.8\ModSources` (récursif, 798 entrées) avant et après : `diff` vide.
- Aucun rapport écrit : `D:\Game\LifePlay_Backup_5.5\SYNC-MODSOURCES` n'existe pas.
### 5.2 Essai positif dans `D:\Game\LifePlay_Backup_5.5\ETAT2\sync-test\` : **non lancé**
Le contrôle de l'éditeur (`:29-30`) précède tout traitement (identifiants, `.uplugin`, hachage) : l'essai aurait rendu le même refus. La cible jetable **n'a pas été créée** (aucune copie de `.uplugin`). À rejouer en A5 quand aucun éditeur ne tourne.
### 5.3 Contre-vérification indépendante de l'état annoncé dans `lp-paths` (lecture seule, hors script)
La phrase ajoutée « `D:\Game\LifePlay-Sandbox-5.8` identique à `D:\Game\LifePlay-Sandbox` (174 fichiers) » est établie par une autre voie :
`(cd <racine>/ModSources && find */Content -type f -print0 | sort -z | xargs -0 md5sum)` pour chaque racine, puis `diff` → vide ; 174 lignes de chaque côté (`lpr_anim_freeanims` 20, `lpr_anim_quaternius` 84, `lpr_hair_pocolov` 70). Ceci **ne valide pas** le script.
### 5.4 Sonde en lecture seule (hors fiche) : code d'une cible absente
```
pwsh -NoProfile -File 'D:\Game\LifePlay-Sandbox\Tools\SyncModSources.ps1' -Target 'D:\Game\LifePlay_Backup_5.5\ETAT2\cible-inexistante'
Resolve-Path: D:\Game\LifePlay-Sandbox\Tools\SyncModSources.ps1:27 … Impossible de trouver le chemin d'accès « D:\Game\LifePlay_Backup_5.5\ETAT2\cible-inexistante », car il n'existe …
code de sortie = 1
```
Rien créé (`ls` : absent). Voir observation O2.
## 6. `git -C D:\Game\LifePlay-Sandbox status --short` (fin de tâche)
```
M Tools/claude/skills/lp-build/SKILL.md
M Tools/claude/skills/lp-commandlets/SKILL.md
M Tools/claude/skills/lp-lot/SKILL.md
M Tools/claude/skills/lp-paths/SKILL.md
M Tools/claude/skills/lp-validate/SKILL.md
?? Tools/SyncModSources.ps1
```
`git -C D:\Game\LifePlay-Sandbox-5.8 status --short` : vide. Les jonctions `.claude\skills` des deux jeux pointent sur ce checkout : les 5 skills modifiés sont **déjà servis** aux deux copies (rechargement constaté dans la session de l'agent).
## 7. Écarts avec la cartographie
- **E1 (`lp-paths:49-51`, choix de l'agent, réversible)** : le texte proposé écrit « `A58` identique à `A55` » ; `A55`/`A58` sont des abréviations définies seulement dans la cartographie (`ETAT2-T1-CART.md:7`), inconnues des skills. Écrit à leur place leur définition exacte : `D:\Game\LifePlay-Sandbox-5.8` / `D:\Game\LifePlay-Sandbox`. Variante littérale disponible si l'orchestrateur la préfère.
- **E2 (lecture des parenthèses)** : les parenthèses de la colonne « Texte proposé » sont reprises comme texte : `lp-build:33` « (dossier déduit du lot par … pour l'imposer) » et `lp-build:115` « (U58, ST, OB…) ». La seconde, placée sur sa propre ligne, précède la parenthèse existante « (dossier de référence pour les deux copies, hors git) » : deux parenthèses se suivent.
- **E3 (mise en page)** : seules les lignes citées ont changé ; quand le texte s'allonge, la ligne est coupée vers 120 colonnes (`lp-build` 33, 115, 118-119 ; `lp-commandlets` 22 ; `lp-lot` 51 ; `lp-paths` 43, 50-51), sans retoucher les lignes voisines. La ligne de tableau `lp-paths:32` fait maintenant plus de 120 colonnes (les tableaux du fichier en ont déjà, `:37` = 158).
- **E4 (ligne facultative)** : `lp-paths:43` est appliquée, parce que la ligne A4 du § 6 (l. 408) compte 11 passages, dont celui-ci, et que `.gitignore:53` et `:74` sont vérifiés.
- **E5 (critère d'essai non atteint)** : essai à blanc → code 2 (§ 5.1), essai positif non lancé (§ 5.2). Critère « 174 `IDENTIQUE`, code 0 » **non satisfait par le script** ; l'état des fichiers est établi par une autre voie (§ 5.3).
- **E6 (sonde hors fiche)** : § 5.4, lecture seule, ajoutée pour étayer l'observation O2.
## 8. Observations sur le script du § 5 (rapportées, **non corrigées**)
- **O1** (établi, `SyncModSources.ps1:29-30`) : le refus « éditeur ouvert » s'applique aussi à blanc et à tout éditeur du poste, même celui de l'autre copie. C'est le même type de risque que `Build.ps1:55` (cartographie § 1.1). Conséquence : A5 ne peut pas tourner tant que l'éditeur STM est ouvert. Choix pour l'orchestrateur : (a) attendre la fermeture de l'éditeur ou la porte G-STM-FIN ; (b) amender la SPEC pour ne contrôler l'éditeur qu'avec `-Apply`.
- **O2** (établi, § 5.4) : une erreur non interceptée (`Resolve-Path` à `:27` ; toute erreur bloquante sous `$ErrorActionPreference = 'Stop'`, `:25`) sort en **code 1**, le même code que « écarts restants » (`:69`). Un appelant ne peut donc pas distinguer un écart d'une panne.
- **O3** (établi, `:68`) : `EN_TROP` n'entre pas dans le code 1. C'est conforme à « signalé, jamais touché ». À confirmer si « 1 = écarts restants » doit l'inclure.
- **O4** (établi, `:66`) : après `-Apply`, le résumé console regroupe par `Etat` (état avant copie, p. ex. `NOUVEAU 174`), pas par `Action`. En A5, le critère « 174 copiés, MD5 174/174 » se compte dans le rapport `D:\Game\LifePlay_Backup_5.5\SYNC-MODSOURCES\sync_<horodatage>.csv`, colonne `Action = copie OK`.
- **O5** (établi) : les skills, servis dès maintenant aux deux copies, annoncent `etat\<projet>\<lot>\` et `MAPPING-58.csv`. Or :
- les scripts 5.8 (`Build.ps1:61`, `RunCommandlet.ps1:36` sur `ue5.8`, cartographie § 1.1) écrivent encore à la racine jusqu'à B1 ;
- `MAPPING-58.csv` n'existe qu'après B3 ;
- `Tools\EtatDir.ps1` de `main` est en cours (A1 : non suivi, non commité, `git -C "D:\Game\LifePlay-master 5.5" status --short`).
Cet écart est temporaire et attendu par D11 (a), mais la session STM en cours lit déjà ces skills.
- **O6** (établi, `Restore.ps1:35`) : la cible d'essai `Backup_5.5\ETAT2\sync-test\` partage le dossier de l'instantané A1 (`ETAT2\manifest.csv`, `ETAT2\Tools\`). `Restore.ps1` ne parcourt que les lignes du manifeste et ne la toucherait donc pas.
## 9. Fichiers écrits
- `D:\Game\LifePlay-Sandbox\Tools\claude\skills\lp-build\SKILL.md`, `…\lp-commandlets\SKILL.md`, `…\lp-lot\SKILL.md`, `…\lp-paths\SKILL.md`, `…\lp-validate\SKILL.md` (modifiés)
- `D:\Game\LifePlay-Sandbox\Tools\SyncModSources.ps1` (nouveau)
- `D:\Game\LifePlay_Backup_5.5\ETAT2-addon\manifest.csv` + 5 copies (instantané)
- tag local `ETAT2-avant` (addon)
- ce livrable ; fichiers de relevé dans le dossier temporaire de session (`a58_avant.txt`, `a58_apres.txt`, `md5_LifePlay-Sandbox*.txt`)
## 10. Compte rendu sk-protocol
[sk-protocol] Skills présents dans le contexte : sk-protocol, ue-cpp-build, lp-build, lp-ue-compat (lp-paths, sk-change-safety : non préchargés).
1. **Résultat** : partiel. § 3 (11 passages) et § 5 appliqués, analyse syntaxique 0 erreur ; essai à blanc refusé (code 2, éditeur STM PID 32972) ; essai positif non lancé.
2. **Preuves** : `git -C D:\Game\LifePlay-Sandbox diff ETAT2-avant` ; `diff` du script contre `ETAT2-T1-CART.md:324-393` vide ; `ParseFile` 0 erreur ; sortie § 5.1 ; `git status` de la cible vide avant et après, 798 dates identiques.
3. **Chiffres** : 5 fichiers modifiés, 21 insertions et 13 suppressions, 1 nouveau fichier de 70 lignes (`git diff --stat`) ; instantané de 6 entrées ; MD5 indépendant 174/174 (20/84/70).
4. **Incertitudes** : comportement du script à blanc et avec `-Apply` non exécuté (A5, après fermeture de l'éditeur) ; O3 à trancher.
5. **Écarts** : E1 à E6 (§ 7). Fichiers écrits : § 9.
6. **Suite** : l'orchestrateur doit trancher E1 et O1 (attendre la fin de l'éditeur STM ou amender la SPEC), puis lancer A5 (ETAT2-T5-VAL) sans éditeur ouvert. État : modifications en place sur `lot/DC3-atelier`, non commitées, tag `ETAT2-avant` posé.
## 11. Reprise (2026-10-09, 15:20 à 15:25, décisions de l'orchestrateur)
Décisions reçues :
- E1 accepté : chemins complets dans `lp-paths`.
- Corriger le script :
- O1 : refus « éditeur ouvert » seulement avec `-Apply` ;
- O2 : erreur imprévue → code 3, codes documentés dans l'en-tête ;
- O3 : `EN_TROP` informatif, compté au résumé, sans code 1 ;
- O4 : résumé par action.
- `lp-paths` à mettre en accord.
- Éditeur STM annoncé fermé : essai à blanc, essai de cible inexistante et essai positif `-Apply` (ligne A5) demandés.
Pas de nouvel instantané : `ETAT2-addon\manifest.csv` garde la première sauvegarde de `lp-paths` et `SyncModSources.ps1` (`Existed=False`). La version initiale du script reste récupérable à l'octet depuis `ETAT2-T1-CART.md:324-393`.
### 11.1 Modifications
**`D:\Game\LifePlay-Sandbox\Tools\SyncModSources.ps1`** (86 lignes) :
- ASCII, LF, sans BOM, fin LF (contrôle `python … count(b'\r\n')` → `CRLF 0`, `nonascii 0`), MD5 `a8d36da7ee05019375d4fbf34b062cc3`.
- Analyse syntaxique `ParseFile` → **0 erreur**.
Diff contre le § 5 (`diff -u <(sed -n '324,393p' ETAT2-T1-CART.md | tr -d '\r') Tools/SyncModSources.ps1`) :
```diff
@@ -3,12 +3,19 @@
.DESCRIPTION
- Par mod : NOUVEAU (absent de la cible), IDENTIQUE, DIFFERENT, EN_TROP (cible seule), par chemin relatif et MD5.
- -Apply : copie les NOUVEAU ; les DIFFERENT seulement avec -Overwrite (ancien fichier cible DEPLACE vers
- <BackupRoot>\<Lot>\<horodatage>\...) ; EN_TROP signale, jamais touche ; MD5 relu sur la cible apres copie ;
- rapport <BackupRoot>\<Lot>\sync_<horodatage>.csv. Refus : Source = Target, UnrealEditor ouvert, mod monte
- (ModSources\<id>\<id>.uplugin absent d'un cote : voir Mount-ModSource de Tools\ModSource.ps1), Content source absent.
- Codes : 0 conforme ou copie controlee ; 1 ecarts restants ; 2 refus ; 3 MD5 faux apres copie.
+ Par mod, par chemin relatif et MD5 : IDENTIQUE, MANQUANT (absent de la cible), DIFFERENT, EN_TROP (cible seule).
+ A blanc (defaut) : lecture seule des deux cotes, rien n'est ecrit ; permis meme avec un UnrealEditor ouvert.
+ -Apply : copie les MANQUANT ; les DIFFERENT seulement avec -Overwrite (ancien fichier cible DEPLACE vers
+ <BackupRoot>\<Lot>\<horodatage>\...) ; MD5 relu sur la cible apres copie (COPIE_OK, sinon COPIE_KO) ;
+ rapport <BackupRoot>\<Lot>\sync_<horodatage>.csv. EN_TROP : informatif, compte au resume, jamais touche.
+ Resume affiche : par mod et au total, comptes IDENTIQUE, COPIE_OK, COPIE_KO, DIFFERENT, MANQUANT, EN_TROP.
+ Refus : Source = Target ; avec -Apply, UnrealEditor ou UnrealEditor-Cmd ouvert ; mod monte
+ (ModSources\<id>\<id>.uplugin absent d'un cote : voir Mount-ModSource de Tools\ModSource.ps1) ; Content source absent.
+ Codes de sortie :
+ 0 conforme (aucun MANQUANT ni DIFFERENT restant ; EN_TROP n'y entre pas) ou copie controlee
+ 1 ecarts restants : MANQUANT a blanc, DIFFERENT sans -Apply -Overwrite
+ 2 refus (liste ci-dessus) ; rien n'est ecrit
+ 3 erreur : Source ou Target introuvable, exception imprevue, MD5 faux apres copie (COPIE_KO)
@@ -23,11 +30,16 @@
$ErrorActionPreference = 'Stop'
+trap { Write-Host "SyncModSources : erreur (ligne $($_.InvocationInfo.ScriptLineNumber)) : $($_.Exception.Message)"; exit 3 }
function Stop-Sync([string]$Why) { Write-Host "SyncModSources : refus : $Why"; exit 2 }
+function Stop-Error([string]$Why) { Write-Host "SyncModSources : erreur : $Why"; exit 3 }
+foreach ($p in $Source, $Target) { if (-not (Test-Path -LiteralPath $p -PathType Container)) { Stop-Error "$p introuvable" } }
$src = (Resolve-Path -LiteralPath $Source).Path.TrimEnd('\'); $dst = (Resolve-Path -LiteralPath $Target).Path.TrimEnd('\')
if ($src -eq $dst) { Stop-Sync 'Source = Target' }
-$ed = Get-Process -Name 'UnrealEditor', 'UnrealEditor-Cmd' -ErrorAction SilentlyContinue
-if ($ed) { Stop-Sync "UnrealEditor ouvert (PID $($ed.Id -join ', '))" }
+if ($Apply) {
+ $ed = Get-Process -Name 'UnrealEditor', 'UnrealEditor-Cmd' -ErrorAction SilentlyContinue
+ if ($ed) { Stop-Sync "UnrealEditor ouvert (PID $($ed.Id -join ', ')) : -Apply exige l'editeur ferme (a blanc permis)" }
+}
@@ -41,12 +53,12 @@
- $st = if (-not $ht.ContainsKey($k)) { 'NOUVEAU' } elseif …
- $rows.Add([pscustomobject]@{ Mod = $m; Rel = $k; Etat = $st; MD5Source = $hs[$k]; MD5Cible = $ht[$k]; Action = '' })
+ $st = if (-not $ht.ContainsKey($k)) { 'MANQUANT' } elseif …
+ $rows.Add([pscustomobject]@{ Mod = $m; Rel = $k; Etat = $st; Resultat = $st; MD5Source = $hs[$k]; MD5Cible = $ht[$k] })
- foreach ($r in @($rows | Where-Object { $_.Etat -eq 'NOUVEAU' -or …
+ foreach ($r in @($rows | Where-Object { $_.Etat -eq 'MANQUANT' -or …
@@ -56,15 +68,19 @@
- $r.Action = if ($r.MD5Cible -eq $r.MD5Source) { 'copie OK' } else { 'copie MD5 KO' }
+ $r.Resultat = if ($r.MD5Cible -eq $r.MD5Source) { 'COPIE_OK' } else { 'COPIE_KO' }
-$rows | Group-Object Mod, Etat | Sort-Object Name | ForEach-Object { '{0,-45} {1,5}' -f $_.Name, $_.Count }
-if ($rows | Where-Object Action -eq 'copie MD5 KO') { exit 3 }
-$left = @($rows | Where-Object { ($_.Etat -eq 'NOUVEAU' -and -not $Apply) -or ($_.Etat -eq 'DIFFERENT' -and -not ($Apply -and $Overwrite)) })
-if ($left) { Write-Host "$($left.Count) fichier(s) a copier ou a arbitrer (-Apply, -Overwrite)"; exit 1 }
+$cats = 'IDENTIQUE', 'COPIE_OK', 'COPIE_KO', 'DIFFERENT', 'MANQUANT', 'EN_TROP'
+$line = { param($name, $set) ('{0,-24}' -f $name) + (($cats | ForEach-Object { $c = $_; ' {0} {1,4}' -f $c, @($set | Where-Object Resultat -eq $c).Count }) -join ' ') }
+Write-Host "SyncModSources : $(if ($Apply) { '-Apply' } else { 'a blanc' }) $src -> $dst"
+foreach ($m in $Id) { & $line $m @($rows | Where-Object Mod -eq $m) }
+& $line 'TOTAL' $rows
+if (@($rows | Where-Object Resultat -eq 'COPIE_KO').Count) { exit 3 }
+$left = @($rows | Where-Object { $_.Resultat -in 'MANQUANT', 'DIFFERENT' })
+if ($left.Count) { Write-Host "$($left.Count) fichier(s) MANQUANT ou DIFFERENT a copier ou a arbitrer (-Apply, -Overwrite)"; exit 1 }
exit 0
```
(Les lignes de contexte inchangées sont abrégées par « … ».)
**`lp-paths/SKILL.md:51-55`**, mis en accord avec le script. La section compte maintenant +4 lignes par rapport à `ETAT2-avant`, au lieu de +2 :
```
l'addon ne l'a pas. Avant `BuildMod` : `.\Tools\SyncModSources.ps1 -Target <checkout>` (à blanc, lecture seule,
permis éditeur ouvert : comptes IDENTIQUE / MANQUANT / DIFFERENT / EN_TROP, ce dernier informatif ; `-Apply`,
éditeur fermé : copie les MANQUANT, `-Overwrite` remplace les DIFFERENT, MD5 relus → COPIE_OK ; codes 0 conforme,
1 MANQUANT ou DIFFERENT restants, 2 refus, 3 erreur ; ERR-046). État au 2026-10-09 :
`D:\Game\LifePlay-Sandbox-5.8` identique à `D:\Game\LifePlay-Sandbox` (174 fichiers).
```
Fichier toujours en LF (`CRLF 0`). Aucun autre texte de l'addon ne décrit le script (seul `lp-paths` le cite).
Choix de nommage (écart R-E1) :
- `NOUVEAU` est renommé `MANQUANT`, comme dans la liste de l'orchestrateur.
- « COPIE/COPIE_OK » est rendu par `COPIE_OK`, et `COPIE_KO` est ajouté : c'est le seul cas qui produit le code 3 après une copie.
- Le CSV garde `Etat` (comparaison avant action) et remplace `Action` par `Resultat`.
### 11.2 Essais (établi, commandes rejouables ; `pwsh -NoProfile -File 'D:\Game\LifePlay-Sandbox\Tools\SyncModSources.ps1' …`)
| # | Essai | Sortie (TOTAL) | Code | Attendu |
|---|---|---|---|---|
| 0 | `Get-Process UnrealEditor,UnrealEditor-Cmd` à 15:22:14, 15:22:57, 15:23:41 | aucun processus | — | éditeur fermé : OK |
| 1 | à blanc `-Source D:\Game\LifePlay-Sandbox -Target D:\Game\LifePlay-Sandbox-5.8` | IDENTIQUE 174 (20 / 84 / 70), autres 0 | **0** | 174 IDENTIQUE, 0 : **OK** |
| 1b | cible 5.8 avant / après | `git -C D:\Game\LifePlay-Sandbox-5.8 status --short` vide avant et après ; 798 entrées `ModSources` (chemin, taille, `LastWriteTimeUtc`) : `diff` vide ; `Backup_5.5\SYNC-MODSOURCES` absent après | — | cible inchangée : **OK** |
| 2 | `-Target D:\Game\LifePlay_Backup_5.5\ETAT2\cible-inexistante` | `SyncModSources : erreur : D:\Game\LifePlay_Backup_5.5\ETAT2\cible-inexistante introuvable` ; rien créé | **3** | 3 : **OK** |
| P0 | préparation : `sync-test\ModSources\<id>\<id>.uplugin` ×3, copiés par `cp -p` | MD5 des 3 `.uplugin` identiques à la source | — | — |
| P1 | à blanc → `sync-test` | MANQUANT 174, autres 0 ; « 174 fichier(s) MANQUANT ou DIFFERENT … » | **1** | 174 manquants, 1 : **OK** |
| P2 | `-Apply` → `sync-test` | COPIE_OK 174, COPIE_KO 0 ; rapport `D:\Game\LifePlay_Backup_5.5\SYNC-MODSOURCES\sync_20261009-152303.csv` | **0** | 174 copiés, MD5 OK : **OK** |
| P2b | recompte du CSV (`Import-Csv`) | 174 lignes ; `MANQUANT, COPIE_OK : 174` ; `MD5Source = MD5Cible` : 174 | — | **OK** |
| P2c | MD5 indépendant (`find … \| xargs md5sum`, source contre `sync-test`) | `diff` vide, 174/174 | — | **OK** |
| P3 | à blanc → `sync-test` | IDENTIQUE 174, autres 0 | **0** | **OK** |
| P4a | 1 octet ajouté à `sync-test\…\lpr_hair_pocolov\Content\Hairs\Pocolov03_Cap.uasset` (MD5 `4b72…7344` → `3b17…0464a3`), puis à blanc | IDENTIQUE 173, DIFFERENT 1 | **1** | ligne A5 : DIFFERENT 1, 1 : **OK** |
| P4b | `-Apply -Overwrite` | COPIE_OK 1, IDENTIQUE 173 ; rapport `sync_20261009-152329.csv` ; ancien fichier **déplacé** vers `D:\Game\LifePlay_Backup_5.5\SYNC-MODSOURCES\20261009-152329\sync-test\ModSources\lpr_hair_pocolov\Content\Hairs\Pocolov03_Cap.uasset` (4916 octets, MD5 `3b17bef7…` = version altérée) | **0** | A5 : déplacé, 0 : **OK** |
| P4c | à blanc | IDENTIQUE 174 | **0** | **OK** |
| P5 | fichier `EN_TROP_essai.txt` ajouté dans `sync-test\…\lpr_anim_freeanims\Content`, puis à blanc | IDENTIQUE 174, EN_TROP 1 (compté au résumé) | **0** | O3 : informatif, pas de code 1 : **OK** |
| S | source inchangée | MD5 des 174 fichiers de `D:\Game\LifePlay-Sandbox\ModSources\*\Content` après essais : `diff` vide avec le relevé de 15:17 | — | **OK** |
Essai **non** fait : le refus « éditeur ouvert » avec `-Apply`. Aucun éditeur n'était ouvert pour le provoquer, et je n'en ai lancé aucun (interdit). La branche correspondante du code est lue (`:39-42`), pas exécutée.
### 11.3 Limites restantes (rapportées, non corrigées)
- **R1** (établi) : une erreur de liaison des paramètres (paramètre inconnu, `-Target` vide) survient avant le `trap` et sort avec le code de `pwsh`, pas 3. Commande : `pwsh -NoProfile -NonInteractive -File … -Target D:\Game\LifePlay-Sandbox-5.8 -Bogus 1` → code **1**, message « Nous ne pouvons pas trouver un paramètre qui correspond au nom de paramètre « Bogus » ». Elle se confond donc avec « écarts restants ».
- **R2** (estimé, lecture de `:60-77`) : si une exception survient au milieu d'un `-Apply`, le `trap` sort en code 3 **avant** `Export-Csv`. Les copies déjà faites et les fichiers déjà déplacés n'ont alors pas de rapport ; seul le dossier `SYNC-MODSOURCES\<horodatage>\` en garde la trace.
- **R3** (établi, `:40`) : avec `-Apply`, le contrôle de l'éditeur ne filtre pas par chemin. C'est la même classe de risque que `Build.ps1:55`, gardée volontairement.
- **R4** : le texte `lp-paths` diffère désormais du § 3 de la cartographie (décision de reprise), et les noms d'état diffèrent du § 5 et de la ligne A5 (`NOUVEAU` y est devenu `MANQUANT`). La VAL A5 doit s'appuyer sur ce § 11.
### 11.4 Fichiers écrits pendant la reprise
- `D:\Game\LifePlay-Sandbox\Tools\SyncModSources.ps1` (réécrit) ; `D:\Game\LifePlay-Sandbox\Tools\claude\skills\lp-paths\SKILL.md` (l. 51-55).
- Cible jetable `D:\Game\LifePlay_Backup_5.5\ETAT2\sync-test\` : 3 `.uplugin`, 174 fichiers copiés, `EN_TROP_essai.txt`.
- `D:\Game\LifePlay_Backup_5.5\SYNC-MODSOURCES\` : `sync_20261009-152303.csv`, `sync_20261009-152329.csv`, `20261009-152329\…\Pocolov03_Cap.uasset` (déplacé).
- Aucune suppression ; `LifePlay-Sandbox-5.8` et les jeux non touchés ; pas de commit.
`git -C D:\Game\LifePlay-Sandbox diff --stat` après reprise : 5 fichiers, 23 insertions, 13 suppressions (`lp-paths` 12 au lieu de 10), plus `?? Tools/SyncModSources.ps1`. `git -C D:\Game\LifePlay-Sandbox-5.8 status --short` : vide.
Compte rendu de reprise : **réussi**. O1 à O4 sont corrigés, l'analyse syntaxique donne 0 erreur, et tous les essais demandés sont conformes : 174 IDENTIQUE avec code 0 et cible 5.8 inchangée, code 3 pour la cible absente, puis 174 COPIE_OK et retour à IDENTIQUE avec code 0. Restent les limites R1 et R2.
Suite : l'orchestrateur doit décider R1 et R2 (accepter ou faire corriger), puis lancer A5 (VAL, sur la base du § 11) et le commit A6. État : non commité, tag `ETAT2-avant` posé.