454 lines
45 KiB
Markdown
454 lines
45 KiB
Markdown
|
|
# ETAT2-T1-CART — cartographie du petit lot ETAT2 (scripts, gabarits, etat/ 5.8, sources de mods)
|
|||
|
|
|
|||
|
|
Fiche ETAT2-T1 — Niveau N3 — Modèle prévu lp-cart | utilisé Opus 5.5 (`claude-opus-5-5`, identifiant donné par l'environnement de l'agent) — Agent lp-cart — Skills lp-paths, lp-commandlets, lp-build (non chargé : cité par la fiche, non présent dans le contexte), sk-protocol (+ ue-cpp-build chargé, non utilisé)
|
|||
|
|
|
|||
|
|
Date : 2026-10-09, relevés entre 14:45 et 15:05. Lecture seule partout sauf ce fichier. Aucun lancement de commandlet ni de compilation, aucune commande git d'écriture, aucun commit.
|
|||
|
|
Preuve : « établi » = commande rejouable ou `fichier:ligne` ; « estimé » = déduit (raisonnement donné) ; « incertain » = à trancher (essai nommé).
|
|||
|
|
Abréviations : `R5` = `D:\Game\LifePlay-master 5.5\Docs\Migration\etat` ; `R8` = `D:\Game\LifePlay-master 5.8\Docs\Migration\etat` ; `A55` = checkout addon `D:\Game\LifePlay-Sandbox` ; `A58` = worktree addon `D:\Game\LifePlay-Sandbox-5.8`.
|
|||
|
|
|
|||
|
|
## 0. Environnement (établi)
|
|||
|
|
|
|||
|
|
| Élément | Valeur | Commande |
|
|||
|
|
|---|---|---|
|
|||
|
|
| Jeu 5.5 | branche `main`, HEAD `1825884`, arbre propre | `git -C "D:\Game\LifePlay-master 5.5" status --porcelain` → vide |
|
|||
|
|
| Jeu 5.8 | **clone séparé** (pas un worktree : `git rev-parse --git-common-dir` = `.git` dans les deux), branche `ue5.8`, HEAD `fc63060`, `main` ancêtre de `ue5.8` (9 commits d'avance, 0 de retard) | `git merge-base --is-ancestor main ue5.8` ; `git log --oneline main..ue5.8 \| wc -l` = 9 |
|
|||
|
|
| Jeu 5.8 : session concurrente | **active** : 8 fichiers modifiés non commités (`.gitignore`, docs 29, Journal, Registre, `LifePlay.uproject`, 3 fichiers `Source/LifePlayEditorTools`) ; lot `STM` (doc 29 l. 186, projet ST) ; CHG-260 écrit mais non commité (`Journal_Modifications.md:1134`) ; derniers écrits : `R8\STM_Build_20261009-144519.txt` (14:48), `Saved\Logs\portage\STM_EditorHeadless_20261009-145312.log` (14:56) | `git -C "…5.8" diff --stat` ; `ls -lt` |
|
|||
|
|
| Addon actif pour les skills | `A55`, branche `lot/DC3-atelier`, HEAD `6295829` ; les jonctions `.claude\skills` des **deux** copies du jeu pointent vers `A55\Tools\claude\skills` | `pwsh … (Get-Item '…\.claude\skills').Target` |
|
|||
|
|
| Addon 5.8 | `A58`, branche `ue5.8`, HEAD `ce2e269` ; `lot/DC3-atelier` et `ue5.8` ont divergé (aucune n'est ancêtre de l'autre) | `git merge-base --is-ancestor` (deux sens, sans sortie) |
|
|||
|
|
| Skills de `A58` | **non chargés** (aucune jonction) et en retard : `lp-paths` sans la section « Sources binaires des mods » (`A55 lp-paths:48-54`), `lp-validate` sans `:75-78`, `lp-build` d'U3 | `diff -r A55\Tools\claude\skills A58\Tools\claude\skills` |
|
|||
|
|
| Journal des CHG | tenu sur `ue5.8` seulement (CHG-252 à 260) ; `main` s'arrête à CHG-251 | `grep CHG-258` Journal 5.8 l. 1136 |
|
|||
|
|
| PowerShell | 7.6.6 | `pwsh -NoProfile -Command $PSVersionTable.PSVersion` |
|
|||
|
|
|
|||
|
|
## 1. Inventaire chiffré
|
|||
|
|
|
|||
|
|
### 1.1 Points d'appel sous `etat` dans les scripts (établi)
|
|||
|
|
|
|||
|
|
Commande : `grep -n -i "etat" Tools/*.ps1` dans chaque copie, puis lecture intégrale des 5 scripts concernés ; `grep -rn -i -w etat Tools` (sous-dossiers) : aucun autre script. Scripts du jeu : 24 fichiers (5.5) et 26 (5.8) sous `Tools` (`find Tools -type f \( -name '*.ps1' -o -name '*.py' -o -name '*.bat' -o -name '*.cmd' \) | wc -l`).
|
|||
|
|
|
|||
|
|
**Copie 5.5 (`main`)**
|
|||
|
|
|
|||
|
|
| Script:ligne | Opération | Chemin construit | Paramètres existants |
|
|||
|
|
|---|---|---|---|
|
|||
|
|
| `RunCommandlet.ps1:8` | aide | `Docs\Migration\etat\<Lot>_<Commandlet>_<horodatage>.txt` | — |
|
|||
|
|
| `RunCommandlet.ps1:28` (+ `:29` `New-Item`, `:59` `Set-Content`) | **écriture racine** | `<ProjectRoot>\Docs\Migration\etat\<Lot>_<Commandlet>_<yyyyMMdd-HHmmss>.txt` | `-Lot` (obligatoire), `-Commandlet`, `-Args`, `-ProjectRoot`, `-Engine` (défaut `UE_5.5` en dur, `:20`) |
|
|||
|
|
| `ReimportCorrectif.ps1:13` | aide | `Docs/Migration/etat/<Id>_*` | — |
|
|||
|
|
| `ReimportCorrectif.ps1:34` | dossier `$etat` = **racine** | `<ProjectRoot>\Docs\Migration\etat` | `-Id`, `-ProjectRoot` (`:30`, dernier paramètre) |
|
|||
|
|
| `ReimportCorrectif.ps1:44, 60, 69, 84, 87` | 5 appels `RunCommandlet.ps1 -Lot $Id` → écritures racine indirectes | `<Id>_<Commandlet>_<stamp>.txt` | — |
|
|||
|
|
| `ReimportCorrectif.ps1:48` | écriture | `$etat\<Id>_dump_<avant\|apres>_<bp>_<fn>.txt` | `-Graphs` |
|
|||
|
|
| `ReimportCorrectif.ps1:50` | **`Remove-Item` par motif** | `$etat\<Id>_LPDumpFunction_*.txt` | — |
|
|||
|
|
| `ReimportCorrectif.ps1:62` | écriture | `$etat\<Id>_dryrun.txt` | — |
|
|||
|
|
| `ReimportCorrectif.ps1:64` | **`Remove-Item` par motif** | `$etat\<Id>_<Commandlet>_*.txt` | `-Commandlet` |
|
|||
|
|
| `ReimportCorrectif.ps1:70` | écriture | `$etat\<Id>_application.txt` | — |
|
|||
|
|
| `ReimportCorrectif.ps1:71` | **`Remove-Item` par motif** | `$etat\<Id>_<Commandlet>_*.txt` | — |
|
|||
|
|
| `ReimportCorrectif.ps1:77-78` | lecture | `$etat\<Id>_dump_avant\|apres_<bp>_<fn>.txt` | — |
|
|||
|
|
| `ReimportCorrectif.ps1:80` | écriture | `$etat\<Id>_diff_<bp>_<fn>.txt` | — |
|
|||
|
|
| `CheckIntegrity.ps1:25` (lu `:78-79` par `-Ref427`, écrit `:49-50` par `-InitRef427`) | lecture (écriture unique en L0) | `<ProjectRoot>\Docs\Migration\etat\L0_ref427.csv` (**resté à la racine**, décision ETAT-T2) | `-Ref427`, `-InitRef427` |
|
|||
|
|
| `AssetHeaders.ps1:13` | exemple d'aide seulement | `-Csv Docs\Migration\etat\headers_BPs.csv` | `-Csv` |
|
|||
|
|
|
|||
|
|
**Copie 5.8 (`ue5.8`)**
|
|||
|
|
|
|||
|
|
| Script:ligne | Opération | Chemin construit | Paramètres existants |
|
|||
|
|
|---|---|---|---|
|
|||
|
|
| `RunCommandlet.ps1:8` | aide | idem 5.5 | — |
|
|||
|
|
| `RunCommandlet.ps1:36` (+ `:37`, `:67`) | **écriture racine** | idem 5.5 | `-Lot`, `-Commandlet`, `-Args`, `-ProjectRoot`, `-Engine` (défaut vide → `Tools\Engine.ps1`, `:29-30`) |
|
|||
|
|
| `Build.ps1:7` | aide | `Docs\Migration\etat\<Lot>_Build_<horodatage>.txt` | — |
|
|||
|
|
| `Build.ps1:52` | **écriture racine** (mode `-FromLog`) | `<ProjectRoot>\Docs\Migration\etat\<Lot>_BuildLog_<stamp>.txt` | `-Lot` (obligatoire), `-FromLog` |
|
|||
|
|
| `Build.ps1:61` (+ `:71` `New-Item`, `:127` `Set-Content`) | **écriture racine** | `<ProjectRoot>\Docs\Migration\etat\<Lot>_Build_<stamp>.txt` | `-Lot`, `-Target`, `-Config`, `-Platform`, `-ExtraArgs`, `-ProjectRoot`, `-Engine` (dernier, `:40`) |
|
|||
|
|
| `ReimportCorrectif.ps1:13, 35, 45/61/70/85/88, 49, 51, 63, 65, 71, 72, 78-79, 81` | identique à 5.5 décalé de +1 ligne (seul l'en-tête diffère : `:15`, exemple `:18-20`) | idem | idem (`-ProjectRoot` `:31`, dernier) |
|
|||
|
|
| `CheckIntegrity.ps1:28` | **ne lit plus `etat`** : référence `$BackupRoot\ref_modules_<version>.csv` ; `-Ref427`/`-InitRef427` retirés en U2 | — | `-InitRef` |
|
|||
|
|
| `AssetHeaders.ps1:13` | exemple d'aide | idem 5.5 | `-Csv` |
|
|||
|
|
| `Engine.ps1` | aucune référence à `etat` ; se présente comme « point unique du moteur … et des dossiers de sortie » (`:3`) | — | — |
|
|||
|
|
|
|||
|
|
**Appelants externes** : `AnimPipeline.ps1` de l'addon appelle le `RunCommandlet.ps1` du jeu avec `-Lot AP7` en dur (`A58\Tools\anim\AnimPipeline.ps1:120,123` ; `A55\…:118,121`) → avec la convention proposée, ses résumés iraient dans `etat\anim\AP7\` (cohérent). Aucun script de l'addon n'écrit sous `etat` (`grep -rn -i etat` : seulement `etat.json` d'`AnimPipeline`, sans rapport).
|
|||
|
|
|
|||
|
|
**Corrections à la proposition ETAT-T1 § 4** (établi) : (1) `CheckIntegrity.ps1` 5.8 ne lit pas `L0_ref427.csv` (voir ci-dessus) : seule la copie 5.5 en dépend ; (2) `modele-sequencage.md:123` (mémoire) dit déjà `etat/<projet>/<P#>/` : rien à changer ; (3) le nettoyage par motif de `ReimportCorrectif.ps1` ne supprime que les résumés `LPDumpFunction` et ceux de la commandlet du correctif, pas ceux de `LPCheckMeshAssignment` ni `CompileAllBlueprints` (`:84`, `:87` sans `Remove-Item` derrière).
|
|||
|
|
|
|||
|
|
**Constat de risque inter-copies** (établi, `Build.ps1:55`) : `Get-Process -Name 'UnrealEditor', 'UnrealEditor-Cmd'` sans filtre de chemin : un commandlet lancé dans la copie 5.5 fait sortir en code 3 un `Build.ps1` lancé au même moment dans la copie 5.8 (et inversement pour un éditeur). Conséquence pour le plan : pas d'essai réel de commandlet en 5.5 pendant la session STM.
|
|||
|
|
|
|||
|
|
### 1.2 Gabarits `etat` des skills (établi)
|
|||
|
|
|
|||
|
|
Commande : `grep -rn -E "etat[\\/]" <addon>\Tools\claude\skills` → `A55` : 26 lignes dans 9 fichiers ; `A58` : 23 lignes dans 9 fichiers (`grep -rn … | wc -l`, `grep -rl … | wc -l`). Skills utilisateur `%USERPROFILE%\.claude\skills` : 0 fichier. Mémoire : 1 gabarit racine (`lifeplay-build-pitfalls.md:15`).
|
|||
|
|
|
|||
|
|
Lignes qui annoncent encore la **racine** (à changer) dans `A55` : `lp-build:33`, `lp-build:118-119`, `lp-commandlets:22`, `lp-lot:50-51`, `lp-paths:32`, `lp-validate:50` (6 passages). Lignes figées sur le projet `U58` alors que les projets ST (doc 29 l. 62) et OB (doc 30 l. 42) arrivent : `lp-build:115`, `lp-validate:14`, `lp-validate:83` (3). Section à compléter par le script de (d) : `lp-paths:49-51`. Déjà conformes : `lp-doc/gabarits.md:3,5`, `lp-doc:39`, `lp-env:8`, `lp-lot:3,48-49`, `lp-paths:33,52-53`, `lp-ue-compat:15-16`, `lp-validate:23,62,71`. Dans `A58` les mêmes passages sont aux lignes `lp-build:32,110,113`, `lp-validate:79` (texte plus ancien).
|
|||
|
|
|
|||
|
|
Docs NN (gabarits, pas l'historique) : `03_Plan_Migration_Tests.md:107` (5.5) / `:109` (5.8) `Docs/Migration/etat/<lot>_run_<date>.log` ; `09_Commandes_Utiles.md:60` / `:61` `-CSV=Docs/Migration/etat/streetmap.csv` (commande `grep -rn -E "etat[\\/]+(<|\$|\{)[A-Za-z]" Docs --exclude-dir=etat`, plus `grep -n etat 09_*`).
|
|||
|
|
|
|||
|
|
### 1.3 `etat/` des deux copies (établi)
|
|||
|
|
|
|||
|
|
| Mesure | R5 | R8 | Commande |
|
|||
|
|
|---|---|---|---|
|
|||
|
|
| Fichiers à la racine | **5** (`ETAT-INVENTAIRE-PROPOSITION.md`, `ETAT-T2-REORG.md`, `INVENTAIRE.md`, `L0_ref427.csv`, `MAPPING.csv`) | **333** (316 `.txt`, 16 `.csv`, 1 `.md`) | `find . -maxdepth 1 -type f \| wc -l` ; recompte `Get-ChildItem -File` = 333 |
|
|||
|
|
| Fichiers au total | 616 | **472** | `find . -type f \| wc -l` ; recompte PowerShell 472 |
|
|||
|
|
| Fichiers en sous-dossiers | 611 | 139 (sandbox 70, VQ 12, U58 12 = UA 8 + U0 4, PUB2 11, L4-CX-B02_essai1_rejete 10, PROP 9, SK 6, commit_plan 5, PUB1 4) | `for d in */; do find "$d" -type f \| wc -l; done` |
|
|||
|
|
|
|||
|
|
R5 n'a reçu **aucun** nouveau fichier à la racine depuis ETAT-T2 (les scripts 5.5 n'ont pas servi). R8 est passé de 316 (ETAT-T1) à 333 fichiers à la racine (+17 : U7, U7-VAL, U7b, STM).
|
|||
|
|
|
|||
|
|
Classement de la racine R8 (commande de classement d'ETAT-T1 étendue aux préfixes `U<n>[b][-X]`, `UA`, `STM`) : `AP2=2 AP3=5 AP4=7 AP5=18 AP6=5 AP7=51 COMMIT-CART=1 DC2=4 DC3=1 DOC-MOD=4 L0=8 L1=2 L2=1 L4-CX-B01=7 L4-CX-B02b=10 L4-CX-B03=5 L4-CX-B04=10 L4-CX-B07=12 L4-CX-B08=4 L5-diag=21 L6e=2 L6e-CX-B09=11 L6e-CX-B09b=3 L6e-CX-B09c=1 L6f=13 L7a=8 L7b=6 L7d=9 L7h=8 L7i=19 L7j=4 L7l=2 PairCol=10 PawnDyn=4 PawnGlobal=3 STM=2 STUDIO-EST=6 U2=1 U3=2 U3-T2=1 U3-VAL=2 U4=2 U4-T7=1 U5=13 U7=10 U7-VAL=4 U7b=8` (somme 333).
|
|||
|
|
|
|||
|
|
Confrontation à `R5\MAPPING.csv` et MD5 (script dans le dossier temporaire de session : pour chaque fichier R8, recherche de `ancien_chemin_relatif`, puis `md5sum` R8 contre `R5\<nouveau_chemin_relatif>`) :
|
|||
|
|
|
|||
|
|
| Groupe R8 | Fichiers | État |
|
|||
|
|
|---|---|---|
|
|||
|
|
| Racine présente dans `MAPPING.csv` | **283** | 283 MD5 identiques à R5 (0 différent) |
|
|||
|
|
| `L0_ref427.csv` (racine) | 1 | identique à `R5\L0_ref427.csv` |
|
|||
|
|
| Racine propre à R8 (hors `MAPPING.csv`, absente de R5 par nom : `find R5 -name`) | **49** | AP7 3, U2 1, U3 5 (U3 2 + U3-T2 1 + U3-VAL 2), U4 3 (U4 2 + U4-T7 1), U5 13, U7 14 (U7 10 + U7-VAL 4), U7b 8, STM 2 |
|
|||
|
|
| Sous-dossiers | 139 | **139/139 MD5 identiques** à leurs homologues R5 (PUB1/PUB2/commit_plan → `publication\…`, essai 1 → `portage55\L4-CX-B02\essai1_rejete\`, autres même chemin) |
|
|||
|
|
|
|||
|
|
Contrôles : 283 + 1 + 49 = 333 ; 333 + 139 = 472. Couverture : 313 des 317 lignes de `MAPPING.csv` ont une source dans R8 ; les 4 absentes sont `AP7_LPAnimEval_20261008-175103.txt`, `…-181017.txt`, `U1_LPAuditBlueprintCalls_20261008-145127.txt`, `…-145335.txt` (fichiers propres à R5, déjà notés en ETAT-T1). Recompte PowerShell des 49 : `U*`/`STM` 46 + AP7 du 08/10 ≥ 18:47 3.
|
|||
|
|
|
|||
|
|
Citations des 49 fichiers propres à R8 : **60 occurrences, 34 noms distincts, dans 21 fiches de `R5\U58\`** (U2-T4-BUILD, U2-VAL, U3-T2-BUILD, U3-T3-TEST, U3-T3b-TEST, U3-VAL, U4-T4-BUILD, U4-T6-VAL, U4-VAL, U5-T1-CART, U5-T2-AVANT, U5-T3-RESAVE, U5-VAL, U7-T8-BUILD, U7-T8b-BUILD, U7-T10-BUILD, U7-T13-BUILD, U7-T14-BUILD, U7-VAL, U7b-T5-IMPL, U7b-T6-VAL), surtout sous la forme `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\<fichier>` (36) ; 0 citation dans les Docs NN des deux copies (`grep -rnoFf uniq49.txt Docs --exclude-dir=etat`). Commande : `grep -rhoFf uniq49.txt R5/U58 | wc -l` (60) et `| sort -u | wc -l` (34).
|
|||
|
|
|
|||
|
|
### 1.4 Sources de mods hors git (établi)
|
|||
|
|
|
|||
|
|
| Mesure | `A55` | `A58` | Commande |
|
|||
|
|
|---|---|---|---|
|
|||
|
|
| Règle git | `.gitignore:38` `/ModSources/*/Content/` | idem `:38` | `grep -n ModSources .gitignore` |
|
|||
|
|
| `ModSources/<id>/Content` | freeanims 20, quaternius 84, pocolov 70 = **174 fichiers, 88 888 626 octets** | identique | `find <id>/Content -type f` ; `Get-ChildItem … Measure-Object Length -Sum` |
|
|||
|
|
| Comparaison chemin + MD5 | — | **174/174 identiques** (copie U7-T15 faite) | `md5sum` des deux arbres, `diff -q` |
|
|||
|
|
| Fichiers suivis par git sous `ModSources` | 25 / 89 / 15 | 25 / 89 / 15 | `git ls-files ModSources` |
|
|||
|
|
| Résidus de cuisson `ModSources/*/Saved` (ignorés par `.gitignore:6`) | 417 | 417 | `find ModSources -path '*/Saved/*' -type f \| wc -l` |
|
|||
|
|
| Points de reparse sous `ModSources` | 0 | 0 | `Get-ChildItem -Recurse -Attributes ReparsePoint` |
|
|||
|
|
| Racine du jeu de l'atelier | `Config\LPSandbox.ini:46` `GameRoot=..\LifePlay-master 5.5` | `:46` `..\LifePlay-master 5.8` | `grep -n GameRoot` |
|
|||
|
|
|
|||
|
|
Mécanisme à respecter (établi, `A58\Tools\ModSource.ps1:25-45`) : `Mount-ModSource` **déplace** `ModSources\<id>` vers `<jeu>\Mods\<id>` pendant un travail (`BuildMod.ps1:239`, remis par `:305`) : un mod monté n'a plus de `ModSources\<id>\<id>.uplugin`. `Mods\` des deux jeux : vides (`ls`). Report ouvert : doc 21 (5.8) l. 217 et ERR-046 (Registre 5.8 l. 53, « Ouvert : transfert hors git à documenter / scripter »).
|
|||
|
|
|
|||
|
|
## 2. Convention proposée pour les scripts (une seule) et diffs (non appliqués)
|
|||
|
|
|
|||
|
|
### 2.1 Convention
|
|||
|
|
|
|||
|
|
Un fichier commun **`Tools\EtatDir.ps1`** (nouveau, texte identique sur `main` et `ue5.8`), dot-sourcé par les trois scripts, avec une fonction `Resolve-LPEtatDir <ProjectRoot> <Lot> [<EtatDir>] [-NoCreate]` :
|
|||
|
|
1. `-EtatDir` non vide (paramètre ajouté aux trois scripts) : dossier imposé (absolu, ou relatif à `Docs\Migration\etat`).
|
|||
|
|
2. Sinon : table versionnée lot → projet (première règle qui correspond, sensible à la casse) ; le groupe capturé donne le dossier du lot, rôle et tâche retirés (`U7-VAL` → `U58\U7`, `U3-T2` → `U58\U3`, `AP5-PD` → `anim\AP5`, `L6e-CX-B09b` → `portage55\L6e`, conforme au rangement d'ETAT-T2).
|
|||
|
|
3. Lot hors table : `etat\<Lot>\` + avertissement (jamais la racine, jamais d'échec ; cohérent avec les dossiers à plat existants `SK\`, `PROP\`, `ETAT2\`). Variante à décider (D2).
|
|||
|
|
4. Garde : lot limité à `[A-Za-z0-9._-]` (pas de `..\`, pas de caractère générique) ; refus si le dossier résolu contient `* ? [ ]` → les `Remove-Item` par motif ne peuvent pas être élargis par le nom de dossier.
|
|||
|
|
5. Chaque copie écrit dans **son** `etat` (`$ProjectRoot` inchangé) : la 5.8 dans `R8\<projet>\<lot>\`, la 5.5 dans `R5\<projet>\<lot>\`.
|
|||
|
|
|
|||
|
|
La table est dans le script (et non dans `etat\`, ignoré par git, donc absent d'un nouveau clone).
|
|||
|
|
|
|||
|
|
### 2.2 Texte proposé de `Tools\EtatDir.ps1` (ASCII, comme les scripts existants)
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
<#
|
|||
|
|
.SYNOPSIS
|
|||
|
|
Dossier des preuves d'un lot : Docs\Migration\etat\<projet>\<lot>\ (lot ETAT2). A dot-sourcer, pas a lancer.
|
|||
|
|
|
|||
|
|
.DESCRIPTION
|
|||
|
|
Usage : . "$PSScriptRoot\EtatDir.ps1" ; $dir = Resolve-LPEtatDir $ProjectRoot $Lot $EtatDir
|
|||
|
|
-EtatDir non vide : dossier impose (absolu, ou relatif a Docs\Migration\etat).
|
|||
|
|
Sinon : premiere regle de $LPEtatRules qui correspond au lot (casse comprise) ; groupe 1 = dossier du lot.
|
|||
|
|
Lot hors table : Docs\Migration\etat\<Lot>\ avec un avertissement (jamais la racine de etat\).
|
|||
|
|
Cree le dossier s'il manque, sauf -NoCreate. Index des projets : Docs\Migration\etat\INVENTAIRE.md (hors git).
|
|||
|
|
#>
|
|||
|
|
# Ordre significatif : STUDIO-EST avant ST* ; PROP, SK et ETAT* sont des dossiers a plat.
|
|||
|
|
$LPEtatRules = @(
|
|||
|
|
@{ Re = '^(STUDIO-EST|PawnGlobal|PawnDyn)(?:-|$)'; Proj = 'post-v1' }
|
|||
|
|
@{ Re = '^(U\d+[a-z]?|UA)(?:-|$)'; Proj = 'U58' }
|
|||
|
|
@{ Re = '^(AP\d+)(?:-|$)'; Proj = 'anim' }
|
|||
|
|
@{ Re = '^(L4-CX-B\d+[a-z]?|L5-diag|L\d+[a-z]?)(?:-|$)'; Proj = 'portage55' }
|
|||
|
|
@{ Re = '^(S\d+|SB\d+|DC\d+|PairCol|DOC-MOD)(?:-|$)'; Proj = 'sandbox' }
|
|||
|
|
@{ Re = '^(VQ\d+)(?:-|$)'; Proj = 'VQ' }
|
|||
|
|
@{ Re = '^(PUB\d+)(?:-|$)'; Proj = 'publication' }
|
|||
|
|
@{ Re = '^(ST[A-Z]?\d*[a-z]?)(?:-|$)'; Proj = 'ST' }
|
|||
|
|
@{ Re = '^(OB[A-Z]?\d*[a-z]?)(?:-|$)'; Proj = 'OB' }
|
|||
|
|
@{ Re = '^(PROP|SK|ETAT\d*)(?:-|$)'; Proj = '' }
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
function Resolve-LPEtatDir([string]$ProjectRoot, [string]$Lot, [string]$EtatDir = '', [switch]$NoCreate) {
|
|||
|
|
if ($Lot -cnotmatch '^[A-Za-z0-9][A-Za-z0-9._-]*$') { throw "EtatDir.ps1 : lot '$Lot' invalide (lettres, chiffres, . _ - seulement)" }
|
|||
|
|
$base = Join-Path $ProjectRoot 'Docs\Migration\etat'
|
|||
|
|
if ($EtatDir) {
|
|||
|
|
$dir = if ([IO.Path]::IsPathRooted($EtatDir)) { $EtatDir } else { Join-Path $base $EtatDir }
|
|||
|
|
} else {
|
|||
|
|
$dir = $null
|
|||
|
|
foreach ($r in $LPEtatRules) {
|
|||
|
|
if ($Lot -cmatch $r.Re) {
|
|||
|
|
$dir = if ($r.Proj) { Join-Path $base (Join-Path $r.Proj $Matches[1]) } else { Join-Path $base $Matches[1] }
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (-not $dir) {
|
|||
|
|
$dir = Join-Path $base $Lot
|
|||
|
|
Write-Warning "EtatDir.ps1 : lot '$Lot' hors table, preuves dans $dir (ajouter une regle a Tools\EtatDir.ps1)"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if ($dir -match '[\*\?\[\]]') { throw "EtatDir.ps1 : caractere generique dans $dir" }
|
|||
|
|
if (-not $NoCreate) { New-Item -ItemType Directory -Force $dir | Out-Null }
|
|||
|
|
$dir
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Table d'essai attendue (VAL, avec `-NoCreate`, aucun effet disque) : `U7-VAL`→`U58\U7` ; `U3-T2`→`U58\U3` ; `U7b`→`U58\U7b` ; `UA`→`U58\UA` ; `AP5-PD`→`anim\AP5` ; `AP7`→`anim\AP7` ; `L4-CX-B02`→`portage55\L4-CX-B02` ; `L6e-CX-B09b`→`portage55\L6e` ; `L5-diag`→`portage55\L5-diag` ; `L0`→`portage55\L0` ; `S2-T2`→`sandbox\S2` ; `DOC-MOD`→`sandbox\DOC-MOD` ; `STUDIO-EST`→`post-v1\STUDIO-EST` ; `STM`→`ST\STM` ; `STA-T1`→`ST\STA` ; `OBA-T1`→`OB\OBA` ; `SK-T1`→`SK` ; `ETAT2`→`ETAT2` ; `PROP`→`PROP` ; `O2`→`O2` + avertissement ; `..\x` → erreur ; `-EtatDir ETAT2\essai` → `ETAT2\essai`. (Estimé : les expressions ont été vérifiées à la main sur ces cas, pas exécutées.)
|
|||
|
|
|
|||
|
|
### 2.3 Diffs proposés (non appliqués)
|
|||
|
|
|
|||
|
|
Choix de placement (estimé, pour qu'un `cherry-pick` du commit `main` sur `ue5.8` passe sans conflit par fusion à trois voies) : ne toucher que des lignes et voisinages identiques dans les deux branches. `RunCommandlet.ps1` : nouveau paramètre inséré **entre `$Args` et `$ProjectRoot`** (contexte identique dans les deux branches ; la fin du bloc `param` diffère : `$Engine` 5.5 `:20` contre 5.8 `:25`) et dot-source placé juste avant `$sum` (le voisinage de `$ErrorActionPreference` diffère, `Engine.ps1` en 5.8). Effet sur l'appel positionnel : tous les appelants connus passent des paramètres nommés (`ReimportCorrectif.ps1` ×5, `AnimPipeline.ps1`, exemples d'aide) — établi par les `grep` du § 1.1.
|
|||
|
|
|
|||
|
|
**`Tools/RunCommandlet.ps1`** (5.5 ; en 5.8, mêmes hunks aux lignes 8, 23-24, 36)
|
|||
|
|
```diff
|
|||
|
|
@@ -5,6 +5,7 @@
|
|||
|
|
.DESCRIPTION
|
|||
|
|
Journal complet : Saved\Logs\portage\<Lot>_<Commandlet>_<horodatage>.log
|
|||
|
|
Resume (lignes Error/Warning dedoublonnees, lignes de la commandlet) :
|
|||
|
|
- Docs\Migration\etat\<Lot>_<Commandlet>_<horodatage>.txt
|
|||
|
|
+ Docs\Migration\etat\<projet>\<lot>\<Lot>_<Commandlet>_<horodatage>.txt (dossier deduit du lot par
|
|||
|
|
+ Tools\EtatDir.ps1 ; -EtatDir l'impose)
|
|||
|
|
Retourne le code de sortie de la commandlet.
|
|||
|
|
@@ -17,5 +18,6 @@ param(
|
|||
|
|
[Parameter(Mandatory)][string]$Commandlet,
|
|||
|
|
[string]$Args = '',
|
|||
|
|
+ [string]$EtatDir = '',
|
|||
|
|
[string]$ProjectRoot = (Split-Path $PSScriptRoot -Parent),
|
|||
|
|
@@ -27,3 +29,4 @@
|
|||
|
|
$log = Join-Path $ProjectRoot "Saved\Logs\portage\$name.log"
|
|||
|
|
-$sum = Join-Path $ProjectRoot "Docs\Migration\etat\$name.txt"
|
|||
|
|
+. "$PSScriptRoot\EtatDir.ps1"
|
|||
|
|
+$sum = Join-Path (Resolve-LPEtatDir $ProjectRoot $Lot $EtatDir) "$name.txt"
|
|||
|
|
New-Item -ItemType Directory -Force (Split-Path $log -Parent), (Split-Path $sum -Parent) | Out-Null
|
|||
|
|
```
|
|||
|
|
(Le lot est validé avant le lancement de la commandlet : `Resolve-LPEtatDir` précède `Start-Process`.)
|
|||
|
|
|
|||
|
|
**`Tools/ReimportCorrectif.ps1`** (5.5 ; 5.8 = mêmes hunks, lignes +1 sauf `:13`)
|
|||
|
|
```diff
|
|||
|
|
@@ -13 +13,2 @@
|
|||
|
|
- Les preuves vont dans Docs/Migration/etat/<Id>_*. Ne commite pas : la validation reste humaine
|
|||
|
|
+ Les preuves vont dans Docs/Migration/etat/<projet>/<lot>/<Id>_* (Tools\EtatDir.ps1 ; -EtatDir l'impose).
|
|||
|
|
+ Ne commite pas : la validation reste humaine
|
|||
|
|
@@ -29,3 +30,4 @@ param(
|
|||
|
|
[string]$DryRunArgs = '-DryRun',
|
|||
|
|
- [string]$ProjectRoot = (Split-Path $PSScriptRoot -Parent)
|
|||
|
|
+ [string]$ProjectRoot = (Split-Path $PSScriptRoot -Parent),
|
|||
|
|
+ [string]$EtatDir = ''
|
|||
|
|
)
|
|||
|
|
@@ -34 +36,3 @@
|
|||
|
|
-$etat = Join-Path $ProjectRoot 'Docs\Migration\etat'
|
|||
|
|
+. "$PSScriptRoot\EtatDir.ps1"
|
|||
|
|
+# Dossier du lot, transmis tel quel a RunCommandlet : resumes, preuves et nettoyages ci-dessous dans ce seul dossier
|
|||
|
|
+$etat = Resolve-LPEtatDir $ProjectRoot $Id $EtatDir
|
|||
|
|
@@ -44 @@
|
|||
|
|
- & "$PSScriptRoot\RunCommandlet.ps1" -Lot $Id -Commandlet LPDumpFunction -Args "-BP=$bp -Fn=$fn -Pins" | Out-Null
|
|||
|
|
+ & "$PSScriptRoot\RunCommandlet.ps1" -Lot $Id -Commandlet LPDumpFunction -Args "-BP=$bp -Fn=$fn -Pins" -EtatDir $etat | Out-Null
|
|||
|
|
@@ -60 @@
|
|||
|
|
-& "$PSScriptRoot\RunCommandlet.ps1" -Lot $Id -Commandlet $Commandlet -Args $DryRunArgs | Out-Null
|
|||
|
|
+& "$PSScriptRoot\RunCommandlet.ps1" -Lot $Id -Commandlet $Commandlet -Args $DryRunArgs -EtatDir $etat | Out-Null
|
|||
|
|
@@ -69 @@
|
|||
|
|
-& "$PSScriptRoot\RunCommandlet.ps1" -Lot $Id -Commandlet $Commandlet -Args $ApplyArgs | Out-Null
|
|||
|
|
+& "$PSScriptRoot\RunCommandlet.ps1" -Lot $Id -Commandlet $Commandlet -Args $ApplyArgs -EtatDir $etat | Out-Null
|
|||
|
|
@@ -84 @@
|
|||
|
|
-& "$PSScriptRoot\RunCommandlet.ps1" -Lot $Id -Commandlet LPCheckMeshAssignment | Out-Null
|
|||
|
|
+& "$PSScriptRoot\RunCommandlet.ps1" -Lot $Id -Commandlet LPCheckMeshAssignment -EtatDir $etat | Out-Null
|
|||
|
|
@@ -87 @@
|
|||
|
|
-& "$PSScriptRoot\RunCommandlet.ps1" -Lot $Id -Commandlet CompileAllBlueprints | Out-Null
|
|||
|
|
+& "$PSScriptRoot\RunCommandlet.ps1" -Lot $Id -Commandlet CompileAllBlueprints -EtatDir $etat | Out-Null
|
|||
|
|
```
|
|||
|
|
Les trois `Remove-Item` (`:50`, `:64`, `:71`) **ne changent pas de texte**. Portée avant : `etat\<Id>_<Cmd>_*.txt` à la racine (où s'accumulaient tous les lots) ; après : le même motif dans le seul dossier `etat\<projet>\<lot>\` où `RunCommandlet` vient d'écrire (même `$etat`, transmis par `-EtatDir`) ; non récursif ; le préfixe `${Id}_` reste. Portée strictement plus étroite, pas élargie. Les anciens résumés restés à la racine (lots déjà faits) ne sont plus atteignables par ces motifs. Remarque (hors ETAT2) : ces suppressions contredisent `lp-commandlets:22` (« Ne jamais supprimer ») et la règle « rm KO » de la mémoire : décision D5.
|
|||
|
|
|
|||
|
|
**`Tools/Build.ps1`** (5.8 seulement ; absent de `main` : `ls Tools`)
|
|||
|
|
```diff
|
|||
|
|
@@ -6,2 +6,3 @@
|
|||
|
|
Journal complet : Saved\Logs\portage\<Lot>_Build_<horodatage>.log
|
|||
|
|
- Resume : Docs\Migration\etat\<Lot>_Build_<horodatage>.txt
|
|||
|
|
+ Resume : Docs\Migration\etat\<projet>\<lot>\<Lot>_Build_<horodatage>.txt (dossier deduit du lot par
|
|||
|
|
+ Tools\EtatDir.ps1 ; -EtatDir l'impose)
|
|||
|
|
@@ -39,3 +40,4 @@ param(
|
|||
|
|
[string]$ProjectRoot = (Split-Path $PSScriptRoot -Parent),
|
|||
|
|
- [string]$Engine = ''
|
|||
|
|
+ [string]$Engine = '',
|
|||
|
|
+ [string]$EtatDir = ''
|
|||
|
|
)
|
|||
|
|
@@ -47,2 +49,4 @@
|
|||
|
|
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
|
|||
|
|
+. "$PSScriptRoot\EtatDir.ps1"
|
|||
|
|
+$etatDir = Resolve-LPEtatDir $ProjectRoot $Lot $EtatDir -NoCreate # lot valide avant toute compilation
|
|||
|
|
$argLine = ...
|
|||
|
|
@@ -52 @@
|
|||
|
|
- $sum = Join-Path $ProjectRoot "Docs\Migration\etat\${Lot}_BuildLog_$stamp.txt"
|
|||
|
|
+ $sum = Join-Path $etatDir "${Lot}_BuildLog_$stamp.txt"
|
|||
|
|
@@ -61 @@
|
|||
|
|
- $sum = Join-Path $ProjectRoot "Docs\Migration\etat\${Lot}_Build_$stamp.txt"
|
|||
|
|
+ $sum = Join-Path $etatDir "${Lot}_Build_$stamp.txt"
|
|||
|
|
```
|
|||
|
|
(`:71` `New-Item -ItemType Directory -Force (Split-Path $sum -Parent)` existe déjà et crée le dossier après le contrôle de l'éditeur : une sortie en code 3 ne crée rien.)
|
|||
|
|
|
|||
|
|
**`Tools/AssetHeaders.ps1:13`** (deux copies, cosmétique) : `-Csv Docs\Migration\etat\headers_BPs.csv` → `-Csv Docs\Migration\etat\<projet>\<lot>\headers_BPs.csv`.
|
|||
|
|
|
|||
|
|
**`Tools/CheckIntegrity.ps1`** : **aucun changement** (5.5 `:25` lit `etat\L0_ref427.csv`, resté à la racine ; 5.8 ne lit pas `etat`).
|
|||
|
|
|
|||
|
|
**Docs NN** (sur `ue5.8`, branche où vivent les docs à jour, étape DOC) : `03_Plan_Migration_Tests.md:109` → `Docs/Migration/etat/<projet>/<lot>/<lot>_run_<date>.log` ; `09_Commandes_Utiles.md:61` → `-CSV=Docs/Migration/etat/<projet>/<lot>/streetmap.csv`.
|
|||
|
|
|
|||
|
|
## 3. Gabarits des skills : texte proposé (addon `A55`, branche `lot/DC3-atelier`, actif par jonction)
|
|||
|
|
|
|||
|
|
| Fichier:ligne (A55) | Texte actuel (extrait) | Texte proposé |
|
|||
|
|
|---|---|---|
|
|||
|
|
| `lp-build/SKILL.md:33` | `` `<copie>\Docs\Migration\etat\<lot>_Build_<horodatage>.txt` `` | `` `<copie>\Docs\Migration\etat\<projet>\<lot>\<Lot>_Build_<horodatage>.txt` `` (dossier déduit du lot par `Tools\EtatDir.ps1`, `-EtatDir` pour l'imposer) |
|
|||
|
|
| `lp-build/SKILL.md:115` | `` …\etat\U58\<lot>\<LOT>-Tn-BUILD.md `` | `` …\etat\<projet>\<lot>\<LOT>-Tn-BUILD.md `` (U58, ST, OB…) |
|
|||
|
|
| `lp-build/SKILL.md:118-119` | « 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). » |
|
|||
|
|
| `lp-commandlets/SKILL.md:21-22` | « … résumé … : `Docs\Migration\etat\<Lot>_<Commandlet>_<horodatage>.txt`. Ne jamais supprimer. » | « … résumé … : `Docs\Migration\etat\<projet>\<lot>\<Lot>_<Commandlet>_<horodatage>.txt` (`Tools\EtatDir.ps1` ; `-EtatDir` impose un dossier). Ne jamais supprimer. » |
|
|||
|
|
| `lp-lot/SKILL.md:50-51` | « Résumés automatiques de `Build.ps1` / `RunCommandlet.ps1` : `<copie>\Docs\Migration\etat\`, cités par leur chemin complet. » | « Résumés automatiques de `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. » |
|
|||
|
|
| `lp-paths/SKILL.md:32` | `` `Docs\Migration\etat\` (résumés `.txt`) `` | `` `Docs\Migration\etat\<projet>\<lot>\` (résumés `.txt`, `Tools\EtatDir.ps1`) `` |
|
|||
|
|
| `lp-paths/SKILL.md:49-51` | « … Avant `BuildMod`, le copier depuis `D:\Game\LifePlay-Sandbox\ModSources\<id>\Content` (copie, MD5 contrôlés ; U7-T15). État actuel : … » | « … 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 : `A58` identique à `A55` (174 fichiers). » |
|
|||
|
|
| `lp-validate/SKILL.md:14` | `` (`…\Docs\Migration\etat\U58\<lot>\`) `` | `` (`…\Docs\Migration\etat\<projet>\<lot>\`) `` |
|
|||
|
|
| `lp-validate/SKILL.md:50` | `` `<copie>\Docs\Migration\etat\<lot>_LPTestStringCompat_<horodatage>.txt` `` | `` `<copie>\Docs\Migration\etat\<projet>\<lot>\<Lot>_LPTestStringCompat_<horodatage>.txt` `` |
|
|||
|
|
| `lp-validate/SKILL.md:83` | `` …\etat\U58\<lot>\<LOT>-VAL.md `` | `` …\etat\<projet>\<lot>\<LOT>-VAL.md `` |
|
|||
|
|
| `lp-paths/SKILL.md:43` (facultatif) | `` `Docs/Migration/etat/**/*.txt` `` | `` `Docs/Migration/etat/` (tout le dossier, `.gitignore:74` ; `:53` pour les `.txt`) `` |
|
|||
|
|
|
|||
|
|
Hors addon (orchestrateur) : mémoire `lifeplay-build-pitfalls.md:15` (`etat\<Lot>_<Commandlet>_<horodatage>.txt` → `etat\<projet>\<lot>\…`). Portage vers la branche `ue5.8` de l'addon (`A58`, non chargée) : décision D11.
|
|||
|
|
|
|||
|
|
## 4. Mapping proposé pour `R8` (copie 5.8)
|
|||
|
|
|
|||
|
|
Méthode : celle d'ETAT-T1/T2 (préfixe → projet/lot, `MAPPING.csv` réutilisé), plus un fichier `R8\MAPPING-58.csv` de mêmes colonnes (`ancien_chemin_relatif;nouveau_chemin_relatif;projet;lot;doc_NN;CHG`).
|
|||
|
|
|
|||
|
|
| Groupe | Fichiers | Cible dans R8 | Source du mapping |
|
|||
|
|
|---|---|---|---|
|
|||
|
|
| Racine identique à R5 | 283 | même `nouveau_chemin_relatif` que `MAPPING.csv` (portage55 165, anim 85, sandbox 19, post-v1 13, publication 1 `COMMIT-CART.md`, U58 0) | lignes de `MAPPING.csv` |
|
|||
|
|
| Dossiers `PUB1`, `PUB2`, `commit_plan`, `L4-CX-B02_essai1_rejete` | 30 | `publication\PUB1|PUB2|commit_plan\`, `portage55\L4-CX-B02\essai1_rejete\` (déplacement de dossier, comme ETAT-T2) | lignes de `MAPPING.csv` |
|
|||
|
|
| AP7 du 08/10 (18:47, 19:04, 19:23) | 3 | `anim\AP7\` | nouvelles lignes |
|
|||
|
|
| U2 | 1 | `U58\U2\` | nouvelles |
|
|||
|
|
| U3 (+ U3-T2, U3-VAL) | 5 | `U58\U3\` | nouvelles |
|
|||
|
|
| U4 (+ U4-T7) | 3 | `U58\U4\` | nouvelles |
|
|||
|
|
| U5 (dont `U5_streetmap_58.csv`, `U5_streetmap_apres.csv`) | 13 | `U58\U5\` | nouvelles |
|
|||
|
|
| U7 (+ U7-VAL) | 14 | `U58\U7\` | nouvelles |
|
|||
|
|
| U7b | 8 | `U58\U7b\` | nouvelles |
|
|||
|
|
| **STM** (session en cours) | 2 au relevé, en croissance | **exclus** tant que STM est ouvert ; ensuite `ST\STM\` | nouvelles, après clôture |
|
|||
|
|
| `L0_ref427.csv` | 1 | reste à la racine (aucun lecteur sur `ue5.8`) | décision D8 |
|
|||
|
|
| Sous-dossiers en place (`sandbox` 70, `VQ` 12, `SK` 6, `PROP` 9, `U58\UA` 8, `U58\U0` 4) | 109 | inchangés | — |
|
|||
|
|
|
|||
|
|
Comptes : déplacements = 283 + 30 + 47 = **360** (+ STM ensuite) ; contrôle racine 283 + 47 + 2 (STM) + 1 (L0) = 333. Après : racine R8 = `L0_ref427.csv` + `MAPPING-58.csv` (+ STM tant qu'exclus) ; total 472 + 1. Projets après : portage55 175, anim 88 (85 + 3), sandbox 89, post-v1 13, publication 21, U58 56 (12 + 44), VQ 12, SK 6, PROP 9, + `ST\STM` (2+).
|
|||
|
|
Exclusions : tout fichier `STM_*` et tout fichier de R8 plus récent que le début de la session STM (premier journal `STM_Build_20261009-144519`, 14:45:19) ; règle de contrôle avant déplacement : `find R8 -maxdepth 1 -newermt '2026-10-09 14:45'` doit ne lister que des `STM_*`.
|
|||
|
|
Références cassées par ce déplacement : les 60 citations (34 noms, 21 fiches `R5\U58\…`) des fichiers propres à R8 et les citations historiques communes (Journal, docs) → parade `MAPPING-58.csv` + `MAPPING.csv`, sans réécrire les fiches (traces), comme ETAT-T2.
|
|||
|
|
|
|||
|
|
## 5. Transfert des sources de mods : `Tools\SyncModSources.ps1` (addon, proposé)
|
|||
|
|
|
|||
|
|
Emplacement : `Tools\SyncModSources.ps1` de l'addon (nouveau fichier ; `lot/DC3-atelier` puis `ue5.8`). Spécification : à blanc par défaut ; ne lit que `ModSources\<id>\Content` (ni `Saved\` résidus de cuisson, ni `Module\` / `.uplugin` suivis par git) ; ne supprime rien ; un fichier cible différent n'est remplacé qu'avec `-Overwrite`, après **déplacement** vers `D:\Game\LifePlay_Backup_5.5\<Lot>\…` ; refus si éditeur ouvert ou mod monté. Codes : 0 conforme ou copie contrôlée ; 1 écarts (à blanc, ou `DIFFERENT` laissés sans `-Overwrite`) ; 2 refus ; 3 MD5 faux après copie.
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
<#
|
|||
|
|
.SYNOPSIS
|
|||
|
|
Copie controlee (MD5) des sources de mods hors git ModSources\<id>\Content d'un checkout de l'addon vers un
|
|||
|
|
autre (ERR-046 : /ModSources/*/Content/ ignore par git, .gitignore:38, absent d'un nouveau worktree). A blanc par defaut.
|
|||
|
|
.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.
|
|||
|
|
.EXAMPLE
|
|||
|
|
.\Tools\SyncModSources.ps1 -Target D:\Game\LifePlay-Sandbox-5.8
|
|||
|
|
.\Tools\SyncModSources.ps1 -Target D:\Game\LifePlay-Sandbox-5.8 -Id lpr_hair_pocolov -Apply
|
|||
|
|
#>
|
|||
|
|
param(
|
|||
|
|
[string]$Source = 'D:\Game\LifePlay-Sandbox',
|
|||
|
|
[Parameter(Mandatory)][string]$Target,
|
|||
|
|
[string[]]$Id = @(),
|
|||
|
|
[switch]$Apply,
|
|||
|
|
[switch]$Overwrite,
|
|||
|
|
[string]$Lot = 'SYNC-MODSOURCES',
|
|||
|
|
[string]$BackupRoot = 'D:\Game\LifePlay_Backup_5.5'
|
|||
|
|
)
|
|||
|
|
$ErrorActionPreference = 'Stop'
|
|||
|
|
function Stop-Sync([string]$Why) { Write-Host "SyncModSources : refus : $Why"; exit 2 }
|
|||
|
|
$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 (-not $Id) { $Id = @(Get-ChildItem -LiteralPath (Join-Path $src 'ModSources') -Directory | Where-Object { Test-Path -LiteralPath (Join-Path $_.FullName 'Content') } | ForEach-Object Name) }
|
|||
|
|
if (-not $Id) { Stop-Sync "aucun ModSources\<id>\Content dans $src" }
|
|||
|
|
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
|
|||
|
|
$hash = { param($dir) $h = @{}; if (Test-Path -LiteralPath $dir) { Get-ChildItem -LiteralPath $dir -Recurse -File -Force | ForEach-Object { $h[$_.FullName.Substring($dir.Length + 1)] = (Get-FileHash -LiteralPath $_.FullName -Algorithm MD5).Hash } }; $h }
|
|||
|
|
$rows = [System.Collections.Generic.List[object]]::new()
|
|||
|
|
foreach ($m in $Id) {
|
|||
|
|
foreach ($root in $src, $dst) {
|
|||
|
|
if (-not (Test-Path -LiteralPath (Join-Path $root "ModSources\$m\$m.uplugin"))) { Stop-Sync "$root\ModSources\$m\$m.uplugin absent (mod monte, ou checkout sans ce mod)" }
|
|||
|
|
}
|
|||
|
|
$sc = Join-Path $src "ModSources\$m\Content"; $tc = Join-Path $dst "ModSources\$m\Content"
|
|||
|
|
if (-not (Test-Path -LiteralPath $sc)) { Stop-Sync "$sc absent" }
|
|||
|
|
$hs = & $hash $sc; $ht = & $hash $tc
|
|||
|
|
foreach ($k in (@($hs.Keys) + @($ht.Keys) | Sort-Object -Unique)) {
|
|||
|
|
$st = if (-not $ht.ContainsKey($k)) { 'NOUVEAU' } elseif (-not $hs.ContainsKey($k)) { 'EN_TROP' } elseif ($hs[$k] -eq $ht[$k]) { 'IDENTIQUE' } else { 'DIFFERENT' }
|
|||
|
|
$rows.Add([pscustomobject]@{ Mod = $m; Rel = $k; Etat = $st; MD5Source = $hs[$k]; MD5Cible = $ht[$k]; Action = '' })
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if ($Apply) {
|
|||
|
|
foreach ($r in @($rows | Where-Object { $_.Etat -eq 'NOUVEAU' -or ($_.Etat -eq 'DIFFERENT' -and $Overwrite) })) {
|
|||
|
|
$from = Join-Path $src "ModSources\$($r.Mod)\Content\$($r.Rel)"; $to = Join-Path $dst "ModSources\$($r.Mod)\Content\$($r.Rel)"
|
|||
|
|
if ($r.Etat -eq 'DIFFERENT') {
|
|||
|
|
$bk = Join-Path $BackupRoot "$Lot\$stamp\$(Split-Path $dst -Leaf)\ModSources\$($r.Mod)\Content\$($r.Rel)"
|
|||
|
|
New-Item -ItemType Directory -Force (Split-Path $bk -Parent) | Out-Null
|
|||
|
|
Move-Item -LiteralPath $to -Destination $bk
|
|||
|
|
}
|
|||
|
|
New-Item -ItemType Directory -Force (Split-Path $to -Parent) | Out-Null
|
|||
|
|
Copy-Item -LiteralPath $from -Destination $to
|
|||
|
|
$r.MD5Cible = (Get-FileHash -LiteralPath $to -Algorithm MD5).Hash
|
|||
|
|
$r.Action = if ($r.MD5Cible -eq $r.MD5Source) { 'copie OK' } else { 'copie MD5 KO' }
|
|||
|
|
}
|
|||
|
|
$rep = Join-Path $BackupRoot "$Lot\sync_$stamp.csv"
|
|||
|
|
New-Item -ItemType Directory -Force (Split-Path $rep -Parent) | Out-Null
|
|||
|
|
$rows | Export-Csv -LiteralPath $rep -NoTypeInformation -Encoding UTF8
|
|||
|
|
Write-Host "rapport : $rep"
|
|||
|
|
}
|
|||
|
|
$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 }
|
|||
|
|
exit 0
|
|||
|
|
```
|
|||
|
|
Résultat attendu aujourd'hui (établi par le § 1.4) : `-Target D:\Game\LifePlay-Sandbox-5.8` à blanc → 3 mods, `IDENTIQUE` 20 + 84 + 70 = 174, 0 autre, code 0.
|
|||
|
|
|
|||
|
|
## 6. Plan en étapes (ordre, niveaux, filets)
|
|||
|
|
|
|||
|
|
Filets communs : `Tools\Snapshot.ps1 -Lot <lot> -Path <fichiers>` avant toute écriture (manifeste MD5, `Existed=False` pour un fichier nouveau ; `Restore.ps1` pour revenir) ; tag git local `ETAT2-avant` sur chaque branche touchée avant le premier commit ; rien n'est poussé ; aucune suppression (déplacement vers `D:\Game\LifePlay_Backup_5.5\<lot>\`).
|
|||
|
|
|
|||
|
|
**Phase A — possible tout de suite (ne touche ni la copie 5.8 ni `A58`)**
|
|||
|
|
|
|||
|
|
| # | Fiche | Niveau / modèle | Contenu | Critère de sortie |
|
|||
|
|
|---|---|---|---|---|
|
|||
|
|
| A1 | ETAT2-T2-IMPL (jeu 5.5, `main`) | N2 / Sonnet | `Snapshot.ps1 -Lot ETAT2 -Path Tools\RunCommandlet.ps1,Tools\ReimportCorrectif.ps1,Tools\AssetHeaders.ps1,Tools\EtatDir.ps1` ; tag `ETAT2-avant` ; créer `EtatDir.ps1` (§ 2.2) ; appliquer les diffs § 2.3 ; pas de commit | `git diff --stat` = 3 modifiés + 1 nouveau |
|
|||
|
|
| A2 | ETAT2-T3-VAL (5.5) | N2 / Sonnet | analyse syntaxique (`[System.Management.Automation.Language.Parser]::ParseFile`, 0 erreur ×4) ; table § 2.2 avec `-NoCreate` (22 cas) ; `git diff -U0 \| Select-String Remove-Item` = 0 ligne ; `Select-String -- '-EtatDir \$etat'` = 5 dans `ReimportCorrectif.ps1` ; racine `R5` toujours 5 fichiers. **Essai réel de commandlet reporté en phase B** (`Build.ps1:55`, § 1.1) sauf accord (D13) | PASS / FAIL chiffré |
|
|||
|
|
| A3 | commit `main` (orchestrateur, N0) | — | un seul commit « ETAT2 : preuves des scripts dans etat/<projet>/<lot>/ (Tools/EtatDir.ps1) » ; n° CHG réservé (D14), entrée de Journal écrite en B5 | `git log -1` |
|
|||
|
|
| A4 | ETAT2-T4-IMPL (addon `A55`, `lot/DC3-atelier`) | N2 / Sonnet | `Snapshot.ps1 -Lot ETAT2-addon -ProjectRoot D:\Game\LifePlay-Sandbox -Path <11 skills + Tools\SyncModSources.ps1>` ; tag `ETAT2-avant` ; texte § 3 ; script § 5 | `git -C A55 diff --stat` |
|
|||
|
|
| A5 | ETAT2-T5-VAL (addon) | N2 / Sonnet | relecture caractère par caractère des passages § 3 ; `SyncModSources.ps1 -Target A58` à blanc = 174 `IDENTIQUE`, code 0 (lecture seule de `A58`) ; essai positif dans `D:\Game\LifePlay_Backup_5.5\ETAT2\sync-test\` (copie des seuls `ModSources\<id>\<id>.uplugin`) : à blanc 174 `NOUVEAU`, code 1 → `-Apply` 174 copiés, MD5 174/174 → à blanc 174 `IDENTIQUE`, code 0 ; un fichier altéré à la main dans la cible d'essai → `DIFFERENT` 1, code 1 → `-Apply -Overwrite` : ancien déplacé dans `Backup_5.5\SYNC-MODSOURCES\…`, code 0 | PASS / FAIL |
|
|||
|
|
| A6 | commit addon (orchestrateur) | — | commit sur `lot/DC3-atelier` ; pin du jeu mis à jour en B5 (doc 21 vit sur `ue5.8`) | `git log -1` |
|
|||
|
|
|
|||
|
|
A1-A3 et A4-A6 sont indépendants (deux dépôts) et peuvent être menés en parallèle.
|
|||
|
|
|
|||
|
|
**Porte G-STM-FIN (avant toute action en phase B)** : la session STM a commité (CHG-260 dans `git log` de `ue5.8`) ; `git -C "D:\Game\LifePlay-master 5.8" status --porcelain` vide ; aucun processus `UnrealEditor`, `UnrealEditor-Cmd` ; `find R8 -maxdepth 1 -newermt <fin de session>` vide ; accord de l'utilisateur.
|
|||
|
|
|
|||
|
|
**Phase B — après la fin de la session STM**
|
|||
|
|
|
|||
|
|
| # | Fiche | Niveau / modèle | Contenu | Critère |
|
|||
|
|
|---|---|---|---|---|
|
|||
|
|
| B1 | ETAT2-T6-IMPL (jeu 5.8, `ue5.8`) | N2 / Sonnet | `Snapshot.ps1 -Lot ETAT2-58 -Path Tools\RunCommandlet.ps1,Tools\ReimportCorrectif.ps1,Tools\Build.ps1,Tools\AssetHeaders.ps1,Tools\EtatDir.ps1` ; tag `ETAT2-avant` ; `git fetch "D:\Game\LifePlay-master 5.5" main:refs/remotes/c55/main` puis `git cherry-pick <commit A3>` (attendu sans conflit, § 2.3) ; second commit `Build.ps1` | cherry-pick sans conflit, sinon arrêt et rapport |
|
|||
|
|
| B2 | ETAT2-T7-VAL (5.8) | N2 / Sonnet | mêmes contrôles qu'A2 ; `Build.ps1 -Lot ETAT2 -FromLog Saved\Logs\portage\U7_Build_20261009-103224.log` → `R8\ETAT2\ETAT2_BuildLog_*.txt` (ni compilation ni moteur) ; `RunCommandlet.ps1 -Lot ETAT2 -Commandlet LPTestStringCompat` → `R8\ETAT2\…` avec `3120 cas`, `compat … : 0`, code 0 ; idem en 5.5 → `R5\ETAT2\…` ; racine R8 inchangée pendant l'essai | PASS / FAIL |
|
|||
|
|
| B3 | ETAT2-T8-REORG (R8) | N1 / Sonnet (comme ETAT-T2) | `Snapshot.ps1 -Lot ETAT2-R8 -Path Docs\Migration\etat -Recurse` dans la copie 5.8 (lancé par `pwsh -Command`, piège ETAT-T2 n° 1) → manifeste attendu 472 + STM + essais B2 ; générer `R8\MAPPING-58.csv` à blanc (360 lignes + STM ; 0 doublon de cible) ; déplacements internes (D9) ; MD5 de chaque fichier déplacé contre le manifeste ; recompte (racine = `L0_ref427.csv` + `MAPPING-58.csv`) | MD5 360/360 (+ STM) OK |
|
|||
|
|
| B4 | ETAT2-T9 (addon `A58`, `ue5.8`) | N1 | selon D11 : `git cherry-pick` des commits A6 (skills + script) sur `ue5.8` | sans conflit, sinon arrêt |
|
|||
|
|
| B5 | ETAT2-DOC (orchestrateur, N0) | — | Journal `ue5.8` (CHG réservé), Registre ERR-046 → « corrigé (script SyncModSources) », doc 21 l. 217 coché + pin addon, docs 03:109 et 09:61, `R5\INVENTAIRE.md` § 4 (conventions) et § 6 (R8 réorganisée), mémoire `lifeplay-build-pitfalls.md:15` ; commits par phase, rien poussé | relecture |
|
|||
|
|
|
|||
|
|
Dépendances : A3 avant B1 (cherry-pick) ; A6 avant B4 ; B1-B2 avant B3 (les scripts 5.8 cessent d'écrire à la racine avant qu'on la vide) ; B3 avant B5.
|
|||
|
|
|
|||
|
|
## 7. Décisions à soumettre à l'utilisateur (liste fermée, recommandation en premier)
|
|||
|
|
|
|||
|
|
- **D1 Convention** : (a) `Tools\EtatDir.ps1` (table lot → projet) + `-EtatDir` ; (b) `-EtatDir` seul, défaut racine ; (c) `-EtatDir` obligatoire.
|
|||
|
|
- **D2 Lot hors table** : (a) `etat\<Lot>\` + avertissement ; (b) racine + avertissement (rétrocompatible strict) ; (c) erreur bloquante.
|
|||
|
|
- **D3 Documents des lots ETAT** : (a) `etat\ETAT2\` à plat (comme ce livrable), `ETAT-INVENTAIRE-PROPOSITION.md` et `ETAT-T2-REORG.md` laissés à la racine ; (b) ces deux documents déplacés dans `etat\ETAT\` (`INVENTAIRE.md`, `MAPPING.csv` restent à la racine).
|
|||
|
|
- **D4 Branches du jeu** : (a) un commit `main` puis `cherry-pick` sur `ue5.8` + commit `Build.ps1` ; (b) éditions séparées par branche ; (c) `ue5.8` seulement (`main` reçoit à la fusion V2.0).
|
|||
|
|
- **D5 `Remove-Item` de `ReimportCorrectif.ps1`** : (a) inchangés en ETAT2 (portée réduite au dossier du lot) ; (b) remplacés par un déplacement vers `Backup_5.5\<Id>\` dans un lot séparé.
|
|||
|
|
- **D6 `etat` 5.8** : (a) réorganisé comme R5 avec `MAPPING-58.csv` (360 déplacements) ; (b) les 422 doublons (283 + 139, MD5 identiques à R5) déplacés vers `Backup_5.5\ETAT2-R8\`, seuls les 49 propres à R8 rangés ; (c) laissé tel quel.
|
|||
|
|
- **D7 Les 49 fichiers propres à R8** : (a) restent dans R8 ; (b) copiés aussi dans `R5\U58\<lot>\`.
|
|||
|
|
- **D8 `L0_ref427.csv` de R8** : (a) reste à la racine (symétrie avec R5) ; (b) vers `portage55\L0\` (aucun lecteur sur `ue5.8`).
|
|||
|
|
- **D9 Mode de déplacement dans R8** : (a) `Move-Item` interne après instantané, comme ETAT-T2 ; (b) copie puis archivage des originaux dans `Backup_5.5`.
|
|||
|
|
- **D10 Transfert des sources de mods** : (a) script `Tools\SyncModSources.ps1` + ligne `lp-paths` ; (b) section de skill seule (commandes manuelles).
|
|||
|
|
- **D11 Skills de la branche `ue5.8` de l'addon** : (a) mettre à jour `lot/DC3-atelier` (actif) en phase A, porter sur `ue5.8` en B4 ; (b) les deux en phase A ; (c) `lot/DC3-atelier` seulement.
|
|||
|
|
- **D12 Gabarits figés sur `U58`** (`lp-build:115`, `lp-validate:14`, `:83`) : (a) généraliser en `<projet>` ; (b) laisser.
|
|||
|
|
- **D13 Essais réels en 5.5 pendant STM** : (a) non, essais statiques en A2, essais réels en B2 ; (b) oui, `LPTestStringCompat` 5.5 (16 s environ en 5.8) avec accord, au risque d'un code 3 dans un `Build.ps1` de la session STM.
|
|||
|
|
- **D14 Numéro de CHG** : (a) premier numéro libre après la clôture de STM, entrée écrite en B5 ; (b) numéro réservé maintenant auprès de la session STM.
|
|||
|
|
|
|||
|
|
## 8. Compte rendu sk-protocol
|
|||
|
|
|
|||
|
|
[sk-protocol] Skills présents dans le contexte : sk-protocol, lp-paths, lp-commandlets, ue-cpp-build (lp-build cité par la fiche mais non chargé).
|
|||
|
|
1. **Résultat** : réussi — cartographie complète, convention unique, diffs, mapping 5.8 et script proposés ; rien modifié hors de ce fichier.
|
|||
|
|
2. **Preuves** : lignes citées § 1 (`grep -n` rejoués, lecture intégrale de `RunCommandlet`, `ReimportCorrectif`, `CheckIntegrity`, `Build`, `Engine`, `ModSource`) ; MD5 R8/R5 et addon (`md5sum`, scripts du dossier temporaire de session).
|
|||
|
|
3. **Chiffres** : R5 racine 5 / total 616 ; R8 racine 333 / total 472 / sous-dossiers 139 (deux méthodes) ; R8 = 283 + 1 + 49 racine, 139/139 identiques ; 360 déplacements proposés ; 49 = AP7 3, U2 1, U3 5, U4 3, U5 13, U7 14, U7b 8, STM 2 ; 60 citations / 34 noms / 21 fiches ; ModSources 174/174 identiques, 88 888 626 octets.
|
|||
|
|
4. **Incertitudes** : expressions de `EtatDir.ps1` et absence de conflit au `cherry-pick` estimées, non exécutées (essais A2, B1) ; la session STM ajoutera des fichiers `STM_*` après ce relevé.
|
|||
|
|
5. **Écarts** : `lp-build` non préchargé ; dossier `R5\ETAT2\` créé ; fichier écrit : `D:\Game\LifePlay-master 5.5\Docs\Migration\etat\ETAT2\ETAT2-T1-CART.md` ; fichiers temporaires dans le dossier temporaire de session seulement.
|
|||
|
|
6. **Suite** : l'orchestrateur doit faire trancher D1-D14, puis lancer A1/A4 (5.5 et addon) ; la phase B attend la porte G-STM-FIN ; état : cartographie livrée, aucun script ni dossier `etat` modifié.
|