LifePlay-Revival/Docs/Migration/etat/OUTC/OUTC-SPEC.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

18 KiB

OUTC-SPEC : scripts de contrôle de la copie partagée (CopieEtat, Verrou, Numero, GitEtat) (2026-10-11)

Fiche OUTC-SPEC — Niveau N2 — Modèle prévu opus | utilisé claude-opus-5-5 — Agent orchestrateur (session OUTC) — Skills lp-lot, sk-orchestrate

Source : décision E2 de l'utilisateur (« approuvé », 2026-10-11) sur la recommandation R2 de Docs\Migration\etat\EVAL\EVAL-RAPPORT.md (§ 6 M1, M4, M5 ; § 8 R2). Mesures de référence : EVAL-STATS.md § 7, EVAL-T6-INV.md (72 h : 538 empreintes improvisées, 452 relevés de processus, 1 794 appels d'état git, 1 085 appels de verrou et tickets).

1. Objectif mesurable

Quatre scripts pwsh 7 sous Tools\ de la copie 5.8 qui remplacent les contrôles mécaniques faits à la main par les sessions principales et par Big Boss, chacun avec une ligne de synthèse, une sortie JSON (-Json) et des codes de sortie documentés et prouvés (0 conforme, 1 alerte ou occupé, 2 erreur d'usage ou chemin introuvable) :

Script Remplace Appelé par
Tools\CopieEtat.ps1 md5sum / Get-FileHash, Get-Process / tasklist, git status de 3 dépôts, recherche des dossiers parasites session de lot (jointe à BUILD-DEMANDE et BUILD-FIN), Big Boss (une relance)
Tools\Verrou.ps1 mkdir / New-Item / lecture de qui.txt du verrou (sk-repo § 2) gardien, Numero.ps1, orchestrateurs
Tools\Numero.ps1 lectures du journal, du registre, des docs et de NUMEROS.md puis ajout manuel d'une ligne (lp-repo § 7) orchestrateur, rédacteur, gardien
Tools\GitEtat.ps1 git status, git diff --name-status, git ls-files --eol, comptes de CR, pour 3 dépôts tout agent, Big Boss, gardien (étape 2 et 6 de sk-repo § 4)

2. Fichiers touchés, ordre

Trois fiches IMPL indépendantes (fichiers disjoints), en parallèle :

Fiche Fichiers (copie 5.8, dépôt jeu)
OUTC-T1 A Tools\CopieEtat.ps1, M Tools\UeState.ps1 (ajout -Copie, -Json), M Tools\FileCheck.ps1 (ajout -Json)
OUTC-T2 A Tools\Verrou.ps1, A Tools\Numero.ps1
OUTC-T3 A Tools\GitEtat.ps1

Règles communes : fichiers neufs en LF, sans BOM, ASCII seul (commentaires sans accents, comme UeState.ps1 et FileCheck.ps1, lisibles aussi par Windows PowerShell 5.1) ; UeState.ps1 et FileCheck.ps1 restent en LF (git ls-files --eol : i/lf w/lf). En-tête d'aide <# .SYNOPSIS .DESCRIPTION .PARAMETER .EXAMPLE #> au style des scripts existants, codes de sortie listés dans .DESCRIPTION. $ErrorActionPreference = 'Stop'. Racine du projet par défaut : Split-Path $PSScriptRoot -Parent. Aucun script n'écrit dans git (lecture seule : status, diff, ls-files, show, rev-parse, cat-file). Aucune suppression de fichier ou de dossier.

Correspondance des dépôts (commune à CopieEtat et GitEtat ; à coder une fois par script, pas de module partagé) :

Copie (-Copie, défaut racine du projet) Addon Modules
nom qui finit par 5.8 (D:\Game\LifePlay-master 5.8) D:\Game\LifePlay-Sandbox-5.8 --git-dir=D:\Game\LifePlay_ModulesGit\5.8.git --work-tree=<copie>\Content\Modules
nom qui finit par 5.5 D:\Game\LifePlay-Sandbox --git-dir=D:\Game\LifePlay_ModulesGit\5.5.git --work-tree=<copie>\Content\Modules
autre -Addon et -ModulesGitDir obligatoires, sinon code 2

Piège Modules (lp-paths l. 68) : jamais sans --git-dir, sinon git remonte au dépôt du jeu.

3. Interfaces

3.1 Tools\CopieEtat.ps1 (OUTC-T1)

.\Tools\CopieEtat.ps1 -Lot <LOT> -Assets <chemins> [-Copie <racine>] [-Reference <json>] [-Autorise <chemins>]
                      [-Addon <racine>] [-ModulesGitDir <git-dir>] [-Json] [-Sortie <fichier.json>]
  • -Assets : chemins relatifs à la copie (ex. Content\LifePlay\GI.uasset) ; 0 à n.
  • Contrôles, dans cet ordre :
    1. Processus : appelle Tools\UeState.ps1 -Copie <copie> -Json (paramètres ajoutés par T1, voir ci-dessous) ; ne retient que les processus dont la ligne de commande ou le chemin de l'exécutable cite la racine de la copie (piège P9, sk-orchestrate § 3) : un éditeur d'une autre copie ou un build empaqueté hors copie n'est pas une alerte, mais il est listé dans le JSON (autres). Alerte PROC si au moins un processus de la copie.
    2. Assets : appelle Tools\FileCheck.ps1 <assets> -ProjectRoot <copie> -Json ; MD5, taille, date. Alerte ASSET_ABSENT (introuvable). Avec -Reference (JSON d'une sortie précédente de CopieEtat, typiquement celle de BUILD-DEMANDE) : alerte ASSET_MODIFIE si le MD5 diffère, sauf si l'asset figure dans -Autorise. Avec -Lot et un manifeste D:\Game\LifePlay_Backup_5.5\<LOT>\manifest.csv présent : colonne instantane (identique / modifie / pas sauvegarde) dans le JSON, sans alerte (information).
    3. Git : git status --porcelain=v1 --untracked-files=all sur : jeu -- Content Config Source ; addon -- Config Content Source Plugins/LPSandbox/Source Plugins/LPSandbox/Content ; Modules (tout le dépôt). Alerte GIT pour toute entrée qui n'est ni un asset déclaré, ni dans -Autorise, ni (avec -Reference) déjà présente avec le même code dans la référence. Dépôt introuvable → code 2.
    4. Parasites : sous <copie>\Docs\Migration\etat\, tout dossier nommé etat ou Migration à n'importe quelle profondeur, et tout dossier Docs qui contient un sous-dossier Migration (ex. etat\Docs\Migration\etat\…, etat\U58\etat\…). Un dossier Docs sans Migration n'est pas un parasite : etat\publication\PUB2\neutral\Docs\Modding est une copie de publication légitime (relevé du 2026-10-11, find -type d). Alerte PARASITE par dossier trouvé (le plus haut seulement, pas ses descendants). Parcours limité aux dossiers (pas de lecture de fichiers).
  • Sortie console : une ligne de synthèse en premier : COPIE <OK|ALERTE> lot=<LOT> copie=<nom> proc=<n> assets=<n> absents=<n> modifies=<n> git=<jeu>/<addon>/<modules> hors_declares=<n> parasites=<n> alertes=<liste|aucune> puis une ligne par alerte (ALERTE <type> : <détail>). Avec -Json : le JSON seul sur la sortie standard (champs synthese, horodatage, lot, copie, processus{copie[],autres[]}, assets[], git{jeu[],addon[],modules[]}, parasites[], alertes[], code). -Sortie écrit le JSON dans un fichier (UTF-8 sans BOM, LF) en plus de la sortie console normale ; c'est ce fichier qui est joint à BUILD-DEMANDE / BUILD-FIN et relu par -Reference.
  • Codes : 0 aucune alerte ; 1 au moins une alerte ; 2 usage, copie, dépôt ou -Reference introuvable.
  • Durée visée : < 30 s sur la copie 5.8 (pas de parcours de Content\).

Ajouts rétrocompatibles (sans paramètre nouveau, sortie octet pour octet identique à avant, codes inchangés) :

  • UeState.ps1 -Copie <racine> : ne garde que les processus dont la ligne de commande ou l'exécutable cite la racine (comparaison insensible à la casse, \ et / acceptés, guillemets ignorés) ; -Json : tableau JSON (Kind, Id, Name, Start, Copy, CommandLine) et ligne de compte dans un champ compte, sans texte autour. -WaitExit combinable avec -Copie (attente des seuls processus de la copie).
  • FileCheck.ps1 -Json : les lignes (Fins, CRLF, LF, CR, BOM, MD5, Sauv, Contenu, Alerte, Fichier) plus Taille et Modifie (date ISO) et les comptes, en JSON seul ; codes inchangés.

3.2 Tools\Verrou.ps1 (OUTC-T2)

.\Tools\Verrou.ps1 -Prendre <ticket> [-Session <texte>] [-Racine <dossier VERROU>]
.\Tools\Verrou.ps1 -Rendre [-Ticket <ticket>] [-Racine …]
.\Tools\Verrou.ps1 -Etat [-Json] [-Racine …]

Racine par défaut : <projet>\Docs\Migration\etat\REPO\VERROU. Algorithme sk-repo § 2 à l'identique :

  1. k = plus grand numéro parmi les sous-dossiers <k> et <k>-libre (numérique, pas alphabétique).
  2. -Prendre : <k> sans <k>-libre → occupé : affiche <k>\qui.txt, VERROU OCCUPE k=<k> par <qui> depuis <min> min, code 1. Sinon [IO.Directory]::CreateDirectory est interdit (il réussit si le dossier existe) : création par New-Item -ItemType Directory sans -Force (échoue si le dossier existe) ; échec → occupé, code 1 ; réussite → écrit <k+1>\qui.txt au format en usage (<ticket>, session <session>, AAAA-MM-JJ HH:MM, une ligne, LF), affiche VERROU PRIS k=<k+1> ticket=<ticket>, code 0.
  3. -Rendre : le verrou tenu est <k> sans <k>-libre ; aucun → VERROU DEJA LIBRE k=<k>, code 1. Avec -Ticket : si qui.txt ne commence pas par ce ticket → refus, code 1 (on ne rend pas le verrou d'un autre). Sinon New-Item <k>-libre (même règle), VERROU RENDU k=<k>, code 0.
  4. -Etat : VERROU LIBRE k=<k> (code 0) ou VERROU OCCUPE k=<k> par <qui> depuis <min> min (code 1) ; au-delà de 30 min, suffixe ANCIEN (signaler, ne pas forcer). Aucun forçage possible : pas de paramètre -Forcer.
  • Rien n'est jamais supprimé ni renommé. Code 2 : racine introuvable, paramètres incohérents (zéro ou plusieurs actions).

3.3 Tools\Numero.ps1 (OUTC-T2)

.\Tools\Numero.ps1 -Reserver CHG|ERR|DOC -Lot <LOT> -Demandeur <texte> [-Nombre <n>] [-Copie55 <racine>]
                   [-Fichier <NUMEROS.md>] [-Racine <dossier VERROU>] [-Json]
.\Tools\Numero.ps1 -Dernier CHG|ERR|DOC        # lecture seule, sans verrou : maxima par source
  • -Reserver : prend le verrou par Verrou.ps1 -Prendre NUMERO-<LOT> (même -Racine) ; occupé → code 1, rien écrit. Calcule le maximum entre : copie 5.8 (Docs\Journal_Modifications.md motif ^\| CHG-(\d+) ; Docs\Registre_Erreurs.md motif ^\| ERR-(\d+) ; Docs\NN_*.md pour DOC), copie 5.5 (-Copie55, défaut D:\Game\LifePlay-master 5.5 : Docs\Migration\Journal_Modifications.md, Docs\Migration\Registre_Erreurs.md, Docs\Migration\NN_*.md ; absente → avertissement, pas d'échec), et NUMEROS.md (colonne Numéro des lignes du type, y compris les plages 058 à 086 : la borne haute compte). Réserve max+1 (ou max+1 … max+n avec -Nombre, une ligne par numéro).
  • Ajoute à la fin du tableau de NUMEROS.md la ligne | CHG | 325 | <LOT> | <Demandeur> ; verrou <k> ; max lus : 5.8=<a> 5.5=<b> registre=<c> | AAAA-MM-JJ | réservé | (CHG et ERR sur 3 chiffres, DOC sur 2) en conservant les fins de ligne du fichier : NUMEROS.md est en CRLF (piège DOCSTAT) ; écriture par ajout d'octets UTF-8 sans BOM avec le séparateur détecté dans le fichier, après contrôle que le fichier se termine par un saut de ligne (sinon en ajouter un du même type). Aucune réécriture du reste du fichier : MD5 du préfixe inchangé (vérifié par le script après écriture : les n premiers octets d'avant sont identiques, sinon code 2 et message).
  • Rend le verrou dans un finally (même en cas d'erreur).
  • Sortie : NUMERO RESERVE CHG-325 lot=<LOT> verrou=<k> ; -Json : {type, numeros[], lot, verrou, maxima{}}.
  • Codes : 0 réservé ; 1 verrou occupé ; 2 erreur (fichier introuvable, contrôle du préfixe en échec).

3.4 Tools\GitEtat.ps1 (OUTC-T3)

.\Tools\GitEtat.ps1 [-Depot jeu,addon,modules] [-Chemin <filtres>] [-Copie <racine>] [-Addon <racine>]
                    [-ModulesGitDir <git-dir>] [-Json] [-Tous]
  • Pour chaque dépôt : branche (branch --show-current), HEAD court, puis une ligne par fichier modifié, indexé ou non suivi (status --porcelain=v1 --untracked-files=all), filtrée par -Chemin si donné : <depot> <XY> <name-status> <eol index>/<eol arbre> CR:<arbre>/<HEAD> <chemin>
    • name-status : de git diff --name-status HEAD -- <chemin> (M, A, D, R100…, ? pour non suivi) ;
    • eol : de git ls-files --eol -- <chemin> (i/lf w/crlf …, - si non suivi ou supprimé) ;
    • CR : nombre d'octets \r dans le fichier de l'arbre et dans le blob HEAD:<chemin> (git cat-file -p), - s'il n'existe pas ; binaire (octet nul dans les 8 000 premiers octets) → bin.
  • Alerte FINS (ligne suffixée ALERTE FINS) : fichier texte suivi dont le CR passe de 0 à > 0 ou de > 0 à 0 entre HEAD et l'arbre, ou fichier mixte (CR > 0 et LF seuls > 0) qui ne l'était pas dans HEAD.
  • Synthèse : GIT <OK|ALERTE> jeu=<branche>@<head> <n> fichiers ; addon=… ; modules=… ; alertes_fins=<n>.
  • -Tous : ajoute les fichiers suivis non modifiés pour les -Chemin donnés (contrôle d'EOL d'un fichier propre, ex. NUMEROS.md) ; sans -Chemin, -Tous est refusé (code 2).
  • Codes : 0 aucune alerte ; 1 au moins une alerte FINS ; 2 dépôt introuvable ou usage.
  • Le comptage des CR se fait par octets ([IO.File]::ReadAllBytes ; flux de git cat-file), jamais par grep -c $'\r$' (faux sous Git Bash, mémoire eol-check-etat-lf).

4. Repli, risques, questions

  • Repli : Tools\Restore.ps1 -Lot OUTC (proposé, jamais lancé sans accord) : retire les 4 scripts neufs et rend UeState.ps1 et FileCheck.ps1 d'avant (MD5 A47107D5…, CA9CBA16…, manifeste D:\Game\LifePlay_Backup_5.5\OUTC).
  • R1 : régression de UeState.ps1 / FileCheck.ps1, appelés par Build.ps1 et cités de 60 à 161 fois → VAL compare la sortie sans paramètre nouveau avant / après (copie sauvegardée lancée en parallèle).
  • R2 : Verrou.ps1 testé sur le vrai VERROU pendant qu'un gardien travaille → tous les essais de VAL et d'IMPL sur une racine de test (-Racine dans le scratchpad), le vrai verrou seulement en -Etat (lecture).
  • R3 : Numero.ps1 qui casse le CRLF de NUMEROS.md → essais sur une copie de NUMEROS.md (-Fichier), contrôle par FileCheck.ps1 et MD5 du préfixe ; la seule écriture réelle est la réservation du CHG d'OUTC à la DOC.
  • R4 : parasites — l'arbre etat\ ne contient aujourd'hui aucun dossier parasite au sens du § 3.1 (relevé du 2026-10-11) : la preuve de l'alerte se fait sur une racine de test (-Copie vers une arborescence factice) ou sur un dossier parasite créé puis laissé dans le scratchpad, jamais dans la copie.
  • Q1 (tranchée par l'orchestrateur) : une modification git déjà là au départ n'est pas une alerte si elle est déclarée (-Assets, -Autorise) ou présente dans la -Reference ; sinon CopieEtat serait toujours en alerte pendant qu'un lot a des fichiers en cours.

5. Interdits

Aucune commande git qui écrit ; aucune suppression ; aucun lancement d'éditeur, de commandlet ou de build ; aucun essai d'écriture sur le vrai VERROU ni sur le vrai NUMEROS.md (sauf la réservation finale du CHG d'OUTC par l'orchestrateur) ; ne modifier ni skills ni agents (lot DOC séparé, décision E5) ; ne pas toucher d'autre fichier de Tools\ que ceux du § 2.

6. Valeurs moteur

Sans objet : outillage pwsh, aucune API moteur.

7. Critères de VAL (commande → attendu)

# Commande Attendu
V1 git ls-files --eol / FileCheck.ps1 sur les 6 fichiers LF, pas de BOM, ASCII (aucun octet > 0x7F dans les 4 neufs)
V2 UeState.ps1 et FileCheck.ps1 Tools\UeState.ps1 sans paramètre neuf, version neuve vs copie de D:\Game\LifePlay_Backup_5.5\OUTC sorties identiques (hors horodatage), mêmes codes
V3 CopieEtat.ps1 -Lot OUTC -Assets <2 assets réels> -Sortie <f> sur la copie 5.8 (essai réel, BUILD-GO) 1 ligne de synthèse, JSON valide (ConvertFrom-Json), code 0 si rien ne tourne et état déclaré ; MD5 = FileCheck.ps1
V4 V3 relancé avec -Reference <f> code 0, modifies=0
V5 code 1 prouvé : asset absent ; -Reference à MD5 falsifié ; fichier non déclaré dans -Copie factice ou état réel non déclaré ; parasite dans une copie factice code 1 et alerte du bon type, à chaque cas
V6 code 2 : -Copie inexistante ; -Reference introuvable code 2
V7 Verrou.ps1 sur racine de test : Prendre (0), Prendre encore (1), Etat (1), Rendre -Ticket autre (1), Rendre (0), Rendre encore (1), Etat (0) ; dossier k+1 créé par un tiers entre la lecture et le New-Item (simulé) → 1 ; -Etat sur le vrai VERROU codes et dossiers attendus ; vrai verrou lu sans écriture (liste des dossiers identique avant / après)
V8 Numero.ps1 -Reserver CHG -Lot TEST -Fichier <copie de NUMEROS.md> -Racine <test> deux fois, puis -Nombre 2 numéros consécutifs ; préfixe du fichier identique (MD5) ; CRLF conservé (FileCheck : CRLF, 0 LF seul) ; verrou rendu (k-libre présent) ; verrou occupé → code 1 sans écriture
V9 GitEtat.ps1 sur les 3 dépôts, puis -Chemin Docs/Migration/etat/REPO/NUMEROS.md -Tous une ligne par fichier, comptes égaux à git status --porcelain de chaque dépôt ; NUMEROS : i/crlf w/crlf, CR arbre = CR HEAD
V10 code 1 de GitEtat.ps1 : fichier de test dans un dépôt jetable hors des dépôts du projet (git init et git commit autorisés dans le scratchpad seulement, -Copie/-Addon/-ModulesGitDir vers lui) passé de LF à CRLF ALERTE FINS, code 1
V11 relecture des 6 diffs en entier aucune ligne hors périmètre ; aucune commande git d'écriture, aucun Remove-Item

8. Compléments du 2026-10-11 (après envoi des fiches)

Demandes de Big Boss (premier utilisateur de CopieEtat), transmises à OUTC-T1 vers 06:30. Ce sont des informations, sans alerte sauf mention :

  1. Processus 7z (7z.exe, 7za.exe, 7zG.exe), avec le chemin et l'heure de lancement, requête faite dans CopieEtat. La sortie par défaut d'UeState reste inchangée. Un 7z dont la ligne de commande cite la copie donne l'alerte PROC.
  2. git status --porcelain de tout l'arbre du jeu, séparé hors Docs / Docs (jeu_hors_docs=<n> jeu_docs=<n>).
  3. HEAD court et branche des 3 dépôts (head=<jeu>/<addon>/<modules>).
  4. Dernier verrou, lu sans écrire (verrou=<k>:<libre|occupe>, avec qui.txt s'il est occupé).
  5. Charge CPU (cpu=<n>%, moyenne de Win32_Processor.LoadPercentage).
  6. UeState et FileCheck : versions préparées hors place, puis remplacées en une seule écriture (ils servent à d'autres lots pendant OUTC).
  7. Fiche OUTC-T6 : Tools\EtatDir.ps1. Un -EtatDir relatif ne crée plus de dossier parasite, et la règle OUT[A-Z]?\d* est ajoutée (OUTC-T6-IMPL.md).

Ajouts à la VAL : V3 vérifie que les éléments 1 à 5 apparaissent dans la synthèse et dans le JSON. V12 : points P1 à P3 de OUTC-T6-IMPL.md.

Tours : sans objet (fiche de l'orchestrateur)