LifePlay-Revival/Docs/Migration/etat/OUTC/OUTC-VAL-B.md

111 lines
22 KiB
Markdown
Raw Normal View History

Fiche OUTC-T4b — Niveau N1 — Modèle prévu sonnet | utilisé claude-sonnet-5-5 — Agent lp-validator — Skills sk-protocol, sk-recount, debug-verification, lp-validate (préchargés) ; sk-windows-shell non invoqué
# OUTC-VAL-B : validation indépendante de Verrou.ps1, Numero.ps1 et GitEtat.ps1 (2026-10-11)
Périmètre T4b (fiche `fiches\OUTC-T4.md`, § Découpage) : `Tools\Verrou.ps1`, `Tools\Numero.ps1`, `Tools\GitEtat.ps1` ; critères V1, V7, V8, V9, V10, V11 d'`OUTC-SPEC.md` § 7. Les 4 autres scripts (V2-V6, V12) relèvent de `OUTC-VAL-A.md`. Sorties brutes : `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\OUTC\OUTC-VAL-B_essais.txt` (ignoré par git, `.gitignore:75`). Essais et scripts d'essai : scratchpad `…\scratchpad\OUTC-T4b\` (`lib.ps1`, `d0_v1.ps1` à `d6_v10.ps1`, `w.ps1`, `w2.ps1`, bases `v7*`, `v8*`, `v10*`). Mesures faites sur pwsh 7.6.6, git 2.56.0.windows.2, copie 5.8 branche `ue5.8`.
## 1. Fiches amont relues
Relues en entier : `fiches\OUTC-T4.md`, `OUTC-SPEC.md` (§ 1 à 8), `OUTC-T2-IMPL.md` (Verrou, Numero), `OUTC-T3-IMPL.md` (GitEtat), puis les trois scripts en entier (Read : `Verrou.ps1` 228 lignes, `Numero.ps1` 291, `GitEtat.ps1` 412). Non relus (hors T4b) : `OUTC-T1-IMPL.md`, `OUTC-T6-IMPL.md`, `_essais.txt` d'IMPL (les critères sont rejoués, pas recopiés). Écart de l'orchestrateur accepté : E1 de T2 (`CreateDirectoryW` à la place de `New-Item`), vérifié ci-dessous (V7).
Empreintes des fichiers validés (relevées au départ, identiques à celles des IMPL) : `Verrou.ps1` `788B21F30155200A497C3919FB3CBA29` (11 010 o), `Numero.ps1` `8803E6A42DAD21292DFE3024732BF589` (13 849 o), `GitEtat.ps1` `F50A0C23C809CBC446C5D1E3E979BEB3` (20 220 o). Aucun script modifié par moi.
## 2. Points à confirmer des IMPL
| Id | Point (IMPL § 5) | Verdict | Preuve |
|---|---|---|---|
| T2-1 | E1 : `CreateDirectoryW` (recommandé) ou retour à `New-Item` ; rejouer l'essai d'atomicité | PASS | 8 tours × 8 processus + 5 tours × 12 processus : un seul code 0 par tour (13/13) ; threads : `CreateDirectoryW` 60/60 tours à 1 succès, `New-Item` 10/60 seulement (essais l. 315-444). Confirme le choix, décision déjà prise par l'orchestrateur |
| T2-2 | V7 rejoué (Prendre 0, Prendre 1, Etat 1, Rendre autre 1, Rendre 0, Rendre 1, Etat 0) | PASS | V7-1 à V7-8 |
| T2-3 | V7 course : `-TestCourse` rend 1 pour `-Prendre` et `-Rendre`, `qui.txt` du tiers non écrasé | PASS | V7-17, V7-17b, V7-17c |
| T2-4 | V8 rejoué : numéros consécutifs, préfixe identique, CRLF, verrou rendu, occupé = 1 sans écriture | PASS | V8-2 à V8-4 (essais l. 604-760) |
| T2-5 | Format de la ligne ajoutée (statut `réservé` avec accents, date avec heure) convient au gardien et à `lp-repo` § 7 | reporté (gardien / orchestrateur) | Format conforme à la SPEC § 3.3 (regex sur les 7 lignes ajoutées, UTF-8 sans BOM) ; l'acceptation par le gardien n'est pas du ressort de la VAL |
| T2-6 | `-Rendre` sans `-Ticket` (E5) acceptable, ou exiger `-Ticket` | reporté (décision) | Comportement relevé : rend le verrou tenu quel qu'en soit le titulaire (V7 `-Rendre` simultanés : un 0, sept 1 ; V7-7 sur libre : 1). La SPEC § 3.2 ne demande le contrôle qu'avec `-Ticket` : conforme à la lettre |
| T2-7 | Coût ≈ 640 ms d'`Add-Type` par appel acceptable | reporté (décision) ; mesure | `-Etat` 0,5-0,7 s ; `-Prendre` / `-Rendre` 1,1-1,4 s ; `Numero -Reserver` 1,0-1,4 s (champ `duree` des essais) |
| T2-8 | À la DOC, `Numero -Reserver` réel sans `-Fichier` ni `-Racine` écrit dans le vrai `NUMEROS.md` / vrai `VERROU` | reporté (DOC T5) | Non rejoué (interdit). Défauts lus dans le code : `Numero.ps1` l. 70 (`-Fichier`), `Verrou.ps1` l. 65 (`-Racine`) |
| T3-1 | V9 : une ligne par fichier, comptes égaux à `git status --porcelain` | PASS | V9-1, V9-2 |
| T3-2 | V9 NUMEROS : `i/crlf w/crlf`, CR arbre = CR HEAD | PASS | V9-3 : `CR:45/45` (le fichier est désormais committé : HEAD jeu `7bceea6`), comptes indépendants 45/45 ; V9-4 README `13/13` |
| T3-3 | V10 : dépôt jetable avec `.gitattributes` `* -text` → `ALERTE FINS`, code 1 | PASS | V10-1, V10-3 ; sans l'attribut : voir Constats 6 |
| T3-4 | V11 : fichier neuf, aucun `Remove-Item`, aucune commande git d'écriture | PASS-STATIC | § 4 |
| T3-5 | Décision de l'orchestrateur sur les écarts 1 (format eol), 2 (point pour le blanc), 3 (synthèse en tête), 5 (garde-fou 500), 6 (virgule) | reporté (orchestrateur) | Les écarts sont observés et sans effet sur les codes ; aucun n'a fait échouer un critère V9 / V10 |
| T3-6 | Durée visée : 5,3 s pour les 3 dépôts | PASS | 3,6 s (JSON) et 3,8 s (texte) sur les 3 dépôts réels ; 2,0 s avec `-Chemin … -Tous` |
| T3-7 | `FileCheck.ps1 Tools\GitEtat.ps1` : `LF`, BOM `-`, 0 alerte, MD5 | PASS | V1 : MD5 `F50A0C23…` identique |
| T3-8 | P1 : suppression de `explo\b.txt` dans le scratchpad (contraire à la fiche) | reporté (orchestrateur) | Hors périmètre de la VAL ; consigné par l'IMPL |
## 3. Critères rejoués (commande → code → attendu → verdict)
Toutes les commandes sont `pwsh -NoProfile -File <script> …` (code relevé par `$LASTEXITCODE`). Les `Check` du pilote d'essai sont dans le fichier d'essais ; les numéros de ligne renvoient à ce fichier.
| # | Commande (abrégée) | Code relevé | Attendu | Verdict |
|---|---|---|---|---|
| V1 | Octets lus par `[IO.File]::ReadAllBytes` sur les 3 fichiers ; `FileCheck.ps1 Tools\<s>.ps1 -ProjectRoot …` ×3 ; analyse syntaxique `Parser.ParseFile` ; `git ls-files --eol -o` | FileCheck 0, 0, 0 | LF, pas de BOM, ASCII | **PASS** : CR=0, LF=228 / 291 / 412, octets > 0x7F = 0, NUL = 0, BOM faux, 0 erreur de syntaxe ; `FileCheck` : `LF`, `CRLF=0`, alertes 0 ; git : `w/lf` ×3, non suivis (`??`) (l. 1-52) |
| V7a | `Verrou.ps1 -Etat / -Prendre T4B-A -Session … / -Prendre T4B-B / -Etat / -Rendre -Ticket AUTRE-TICKET / -Rendre -Ticket T4B / -Rendre -Ticket T4B-A / -Rendre / -Etat -Racine <test>` | 0, 0, 1, 1, 1, 1, 0, 1, 0 | 0, 1, 1, 1, 0, 1, 0 (+ préfixe refusé) | **PASS** : dossiers `1 1-libre 2 2-libre 3` puis `… 3-libre` ; `qui.txt` d'une ligne, LF seul, sans BOM, `T4B-A, session VAL B essai, 2026-10-11 HH:MM` ; `qui.txt` inchangé après le refus (MD5) (V7-1 à V7-8, l. 176-220) |
| V7b | `-Etat -Json` ; `-Prendre` sans `-Session` ; `-Rendre -Ticket T4B-R1` (R10 tenu) ; `-Ticket t4b-r10` ; tri `9 9-libre 10` ; racine vide ; verrou daté de 45 min ; `-Prendre` sur verrou ancien | 0, 0, 1, 0, 1, 0/1/0, 1, 1 | idem SPEC § 3.2 | **PASS** : JSON valide ; `session non precisee` ; R1 ne rend pas R10 ; k=10 (tri numérique) ; `ANCIEN (signaler, ne pas forcer)` ; rien forcé (V7-9 à V7-15b) |
| V7c | Codes 2 : aucune action ; deux actions ; racine introuvable ; `-Ticket` avec `-Etat` ; `-Prendre ' '` | 2 ×5 | 2 | **PASS** ; dossiers inchangés, aucun dossier créé (V7-16) |
| V7d | Course simulée : `-Prendre T4B-C -TestCourse` ; `-Etat` ; `-Rendre -TestCourse` | 1, 1, 1 | 1, `qui.txt` du tiers conservé | **PASS** : `qui.txt` = `TIERS-TEST…`, aucun `T4B-C` (V7-17 à 17c). Le crochet `-TestCourse` crée par `New-Item` (usage d'essai, voir Constats 3) |
| V7e | **Atomicité entre processus** : `w.ps1` aligne N processus sur un instant commun puis lance `Verrou.ps1 -Prendre <ticket unique>` dans le même processus : 8 tours × 8 (`v7d`), 5 tours × 12 (`v7e`, `w2.ps1`) | par tour : un 0, le reste 1 (13 tours / 13) ; aucun autre code | un seul gagnant | **PASS** : 13 gagnants pour 124 processus (64 + 60), 111 refus (code 1), 0 code 2 ; à chaque tour un seul nouveau dossier `k+1`, son `qui.txt` = celui du gagnant ; sur les 5 tours de `w2.ps1` : `start_ms` max 3 ms, `dur_ms` min 444 ms, les processus se chevauchent (tous ont lu `k` avant la création du premier, car `Add-Type` précède `CreateDirectoryW`) (l. 315-437) |
| V7f | `-Rendre` simultanés ×8 sur un verrou tenu | un 0, sept 1 | un seul `k-libre` | **PASS** (l. 391-399) |
| V7g | Contre-preuve E1 en threads (8 threads sur barrière, 60 tours) | — | `CreateDirectoryW` : 1 succès partout ; `New-Item` : non atomique | **PASS** : `CreateDirectoryW` 60/60 tours à exactement 1 succès ; `New-Item` 10/60 (plusieurs succès dans 50 tours : 2 à 8) (l. 439-444). L'écart E1 est justifié |
| V7h | **Vrai VERROU**, `Verrou.ps1 -Etat` et `-Etat -Json` sans `-Racine` | 1 et 1 (occupé : `ticket STE-R7, gardien lp-gardien`, k=98 à l'essai ; l'orchestrateur indique k=99 ensuite, EVAL-R1) | lecture sans écriture | **PASS** : liste des dossiers identique avant et après chaque appel (195 / 195, 0 différence). Entre le départ (188 dossiers, l. 3) et la fin (195) : 8 dossiers `95 … 98` apparus, créés par un gardien tiers (`qui.txt` relus : aucun ticket de mes essais, `T4B`, `CONC`, `TEST` absents ; l. 831-841) |
| V8a | `Numero.ps1 -Dernier CHG / ERR / DOC -Fichier <copie>` ; `-Json` | 0 ×4 | maxima corrects, aucun verrou créé | **PASS** : `max=327 (5.8=326 5.5=297 registre=327)`, ERR `88` (86 / 88), DOC `33` (28 / 33), égaux à un calcul indépendant (Select-String / regex / split), racine de test inchangée (l. 604-660) |
| V8b | `-Reserver CHG -Lot TEST -Demandeur … -Fichier <copie> -Racine <test>` ×2, puis `-Nombre 2`, puis ERR, DOC, CHG `-Json` | 0 ×6 | numéros consécutifs, préfixe identique, CRLF | **PASS** : CHG-328, CHG-329, CHG-330 CHG-331, ERR-089, DOC-34, CHG-332 ; verrous 3 à 8 ; `k-libre` présent après chaque appel ; préfixe de 12 601 octets : MD5 `CD7800199276A0AB4F2019D4044816DF` avant = après ; taille 12 601 → 13 415 ; 7 lignes ajoutées, 7 CRLF, 0 LF seul, finit par CRLF, sans BOM, toutes au format SPEC ; `FileCheck` de la copie : `CRLF`, LF seul 0, alertes 0 ; demandeur `a|b` → `a/b` |
| V8c | `-Reserver CHG` avec verrou `2` tenu par un tiers | 1 | 1, rien écrit | **PASS** : `NUMERO REFUSE …`, MD5 entier de la copie inchangé, dossiers inchangés |
| V8d | Codes 2 : fichier introuvable ; aucun type ; type inconnu ; `-Nombre 0` ; sans `-Lot` ; racine de verrou introuvable | 2 ×6 | 2, fichier inchangé | **PASS** (MD5 du fichier inchangé) |
| V8e | Fichier LF sans saut final ; CRLF sans saut final ; fichier vide | 0, 0, 2 | séparateur conservé ; vide = 2 avec verrou rendu | **PASS** : LF conservé (0 CR), CRLF conservé (0 LF seul), préfixes identiques ; fichier vide : code 2, `k-libre` posé |
| V8f | **Concurrence Numero** : 3 tours × 6 processus `-Reserver CHG` simultanés sur une copie | un 0 et cinq 1 par tour | pas de doublon, pas de corruption | **PASS** : CHG-328, 329, 330 (distincts, consécutifs) ; refusés = `NUMERO REFUSE : verrou occupe`, code 1 ; 3 lignes ajoutées = 3 gagnants ; préfixe identique ; 0 LF seul ; verrou final libre (l. 762-796) |
| V8g | Vrai `NUMEROS.md` | — | jamais écrit | **PASS** : MD5 `CD7800199276A0AB4F2019D4044816DF` au départ, après la copie, et à la fin des essais V8 / V7 (relevé de `d4`, l. 828) |
| V9a | `GitEtat.ps1 -Json` encadré par deux `git --no-optional-locks status --porcelain=v1 -z --untracked-files=all` (jeu, addon, modules) | 0 | une entrée par fichier, comptes égaux | **PASS** : jeu 102, addon 268, modules 0 ; ensembles (XY + chemin) identiques à `git status` ; champ `n` = longueur de `fichiers` ; code process = `code` du JSON ; synthèse `GIT OK jeu=ue5.8@7bceea6 102 fichiers ; addon=ue5.8@22dd7c3 268 fichiers ; modules=main@c8661cd 0 fichiers ; alertes_fins=0` (l. 5318-5325) |
| V9b | `GitEtat.ps1` (texte) encadré de même | 0 | une ligne par fichier | **PASS** : lignes par dépôt 102 / 268 / 0 = `git status` ; 3 en-têtes `== <depot> <branche>@<head> <n> fichiers` ; date d'écriture des index jeu et modules inchangée (l. 5701-5709) |
| V9c | `-Chemin Docs/Migration/etat/REPO/NUMEROS.md -Tous` | 0 | `i/crlf w/crlf`, CR arbre = CR HEAD | **PASS** : `.. = i/crlf w/crlf CR:45/45` ; comptes indépendants (ReadAllBytes / `git cat-file blob`) 45 / 45 ; `git ls-files --eol` : `i/crlf w/crlf`. Fichier propre (déjà committé) : l'écart de 3 CR noté par l'IMPL a disparu |
| V9d | `-Depot jeu -Chemin …/REPO/README.md -Tous` ; `-Chemin Tools/UeState.ps1 -Tous` | 0, 0 | statut `=`, CR égaux ; LF pur | **PASS** : README `CR:13/13` (indépendant 13 / 13) ; UeState `.M M i/lf w/lf CR:0/0` |
| V9e | Codes 2 : `-Tous` sans `-Chemin` ; `-Copie` inexistante ; `-Depot foo` ; copie sans nom 5.5 / 5.8 et sans `-Addon` ; `-Json -Tous` | 2 ×5 | 2 | **PASS** ; le JSON d'erreur est `{synthese, erreur, code:2}` |
| V10 | Dépôt jetable A (`git init`, `.gitattributes` `* -text`, `t.txt` LF committé puis passé en CRLF par `WriteAllBytes`) : `GitEtat.ps1 -Copie A -Addon A -ModulesGitDir A\.git -Depot jeu` | 1 | `ALERTE FINS`, code 1 | **PASS** : `GIT ALERTE jeu=main@… 1 fichiers ; alertes_fins=1` et `jeu .M M i/lf w/crlf CR:3/0 t.txt ALERTE FINS` ; propre avant : code 0 ; retour en LF : code 0 ; `-Json` : `alerte FINS`, `cr_arbre` 3, `cr_head` 0, `code` 1 (V10-0, 1, 1b, 1c) |
| V10b | Trois dépôts jetables (jeu `c`, addon, modules par `--git-dir` / `--work-tree`), 5 fichiers modifiés à alerte + 5 sans | 1 ; 0 sur dépôts propres ; 1 pour `-Depot modules` ; 0 pour `-Chemin crlf_ok.txt` | 5 alertes sur `lf.txt` (LF→CRLF), `crlf.txt` (CRLF→LF), `mix.txt` (LF→mixte), `a.txt` (addon), `m1.txt` (modules) ; aucune sur LF resté LF, CRLF resté CRLF, binaire, non suivi, nom avec espace | **PASS** (voir ci-dessous le seul `CHECK ECART` de la série v10b : attente fausse de l'essai) |
| V11 | Relecture en entier des 3 scripts (neufs, non suivis : pas de diff) ; recherche négative par Grep | — | aucune ligne hors périmètre, aucune commande git d'écriture, aucun `Remove-Item` | **PASS-STATIC** (§ 4) |
**Dernier écart de V10 (demande de l'orchestrateur)** : la série v10b se termine par `ECARTS D6 = 1`, `V10-3b alertes sur exactement lf.txt, crlf.txt, mix.txt, a.txt, m1.txt … trouves=crlf.txt,mix.txt,a.txt,m1.txt` (essais l. 6157). **Ce n'est pas un défaut de `GitEtat.ps1` : c'est une attente fausse de mon essai.** Preuve : la sortie de la même exécution (l. 6147) porte bien `jeu .M M i/lf w/crlf CR:3/0 lf.txt ALERTE FINS`, et la synthèse annonce `alertes_fins=5` avec 5 lignes `ALERTE FINS` (le `Check` précédent, l. 6156, est OK). Cause : mon test cherchait le motif `lf.txt` et exigeait **exactement une** ligne d'alerte ; or le motif est aussi contenu dans `crlf.txt` (2 lignes trouvées, `-eq 1` faux). La règle appliquée par le script est celle de `OUTC-SPEC.md` § 3.4 (CR de 0 à > 0, de > 0 à 0, ou mixte nouveau) : `lf.txt` passe de CR 0 à CR 3, donc alerte attendue, et c'est ce que le script rend. Les alertes réelles de la série : `lf.txt`, `crlf.txt` (`i/crlf w/lf CR:0/3`), `mix.txt` (`i/lf w/mixed CR:2/0`), `a.txt`, `m1.txt` ; aucune alerte sur `lf_ok.txt` (`i/lf w/lf CR:0/0`), `crlf_ok.txt` (`CR:3/2`), `sp ace.txt` (`CR:2/1`), `bin.dat` (`CR:bin/bin`), `new.txt` (`?? ?`). Je n'ai pas relancé la série (consigne de l'orchestrateur : aucun nouvel essai hors de ce tri, qui se fait par relecture de la sortie brute).
## 4. Diff lu en entier
Les trois fichiers sont neufs (`git status --short` : `?? Tools/GitEtat.ps1`, `?? Tools/Numero.ps1`, `?? Tools/Verrou.ps1`) : pas de diff, lecture intégrale au lieu du diff (`Verrou.ps1` l. 1-228, `Numero.ps1` l. 1-291, `GitEtat.ps1` l. 1-412).
- Recherche négative (Grep sur les 3 fichiers) de `Remove-Item`, `rm`, `del`, `Set-Content`, `Out-File`, `Rename-Item`, `Move-Item`, `Copy-Item` et des verbes git d'écriture (`add commit reset checkout restore push rm mv tag stash merge rebase cherry-pick revert apply clean gc fetch pull init config`) : **0 occurrence**. Témoin de la méthode (même glob, motif positif `cat-file|New-Item|WriteAllText|AppendAllText|FileMode]::Append`) : 11 occurrences, donc la recherche couvre bien les 3 fichiers.
- `GitEtat.ps1` : seules sous-commandes git lancées, lues dans le code : `branch --show-current`, `rev-parse --verify --quiet --short HEAD`, `status --porcelain=v1 -z --untracked-files=all`, `diff --name-status -z -M HEAD`, `ls-files -z`, `ls-files --eol -z`, `cat-file blob` (l. 202-268, 161) ; `--no-optional-locks` ; `GIT_DIR`, `GIT_WORK_TREE`, `GIT_INDEX_FILE` retirées de l'environnement (l. 98). Pour le dépôt Modules : toujours `--git-dir` + `--work-tree` (l. 366).
- `Numero.ps1` : une seule écriture de fichier, l'ajout d'octets par `FileStream` en `Append` (l. 251), suivie du contrôle du préfixe, de la longueur et de la fin (l. 255-263) ; le verrou est rendu dans `finally` (l. 273-276) ; aucune suppression.
- `Verrou.ps1` : écritures = `CreateDirectoryW`, `qui.txt` (`WriteAllText`, l. 167, 174) ; `New-Item` aux l. 165 et 206 uniquement sous `-TestCourse` ; aucun paramètre de forçage, aucune suppression, aucun renommage.
- Hors périmètre : aucune ligne hors périmètre trouvée dans les trois fichiers.
- Fins de ligne : voir V1 (LF pur ×3). Modification par script : non vérifiable (fichiers neufs, pas de diff).
## 5. Verdict
**T4b : PASS** (Verrou.ps1, Numero.ps1, GitEtat.ps1 ; V1, V7, V8, V9, V10 `PASS`, V11 `PASS-STATIC`), avec réserves listées en Constats. Codes 0, 1 et 2 prouvés pour chacun des trois scripts :
| Script | Code 0 | Code 1 | Code 2 |
|---|---|---|---|
| `Verrou.ps1` | V7a (Etat libre, Prendre, Rendre) | V7a (occupé, refus, déjà libre), V7d, vrai `-Etat` (occupé) | V7c ×5 |
| `Numero.ps1` | V8a, V8b, V8e | V8c, V8f | V8d ×6, fichier vide (V8e) |
| `GitEtat.ps1` | V9a, V9b, V9c, V10 propre | V10, V10b | V9e ×5 |
Le verdict global du lot est « le pire des deux » (`OUTC-VAL-A.md` est la VAL de l'autre moitié) : le verdict de T4b seul est PASS ; il ne préjuge pas de T4a. Le critère de la fiche § 8 (« essai réel V3 sur la copie 5.8 ») relève de T4a.
## 6. Points à confirmer par l'utilisateur
- [ ] Accepter l'écart E1 de T2 (`CreateDirectoryW` dans `Verrou.ps1`, ≈ 0,5 s de plus par appel) — la VAL confirme l'atomicité (13 / 13 tours à un seul gagnant) ; décision déjà prise par l'orchestrateur.
- [ ] Mettre à jour `sk-repo` § 2 et `lp-repo` § 7 (lot DOC) : `mkdir` de cmd est atomique, `New-Item` de PowerShell ne l'est pas (10 tours sur 60 à un seul succès en threads).
- [ ] Décider des écarts de forme de T3 (champ eol en deux jetons, `.` pour le blanc de XY, synthèse en tête, garde-fou 500, listes par virgule) et du statut du `-Rendre` sans `-Ticket` (E5).
- [ ] Prévoir, à la DOC, la réservation réelle (`Numero.ps1 -Reserver CHG` sans `-Fichier` ni `-Racine` écrit dans le vrai `NUMEROS.md` et prend le vrai `VERROU`) : non rejouée ici par interdit.
Tours : 57 / 55 (40 + 15 de prolongation) — compte propre, à confirmer par `python -I Tools/FicheStats.py --lot OUTC` ; budget dépassé de 2 tours (rédaction du livrable en deux Write)
## Constats
1. **Essais invalides conservés dans le fichier d'essais** (pas de suppression possible) : quatre lancements de mes pilotes ont échoué par des erreurs de mon script d'essai, pas des scripts validés, et sont signalés par une ligne `########## NOTE` : (a) premier `d1_v7` (collision de variables `$r` / `$R`, PowerShell est insensible à la casse), sans effet sur le projet ; (b) premier `d2_conc` (collision `$out` / `$Out`), base `v7c` ; (c) premier `d3_v8` : 8 `CHECK ECART` dus à mes attentes fausses (premier verrou k=2 et non 3, 7 lignes ajoutées et non 9), sorties de `Numero.ps1` correctes ; rejoué sur `v8b` ; (d) premier `d6_v10` : alias `GM` = `Get-Member` ; rejoué sur `v10b`, qui garde le seul écart traité en § 3. Le fichier compte donc 30 `CHECK ECART` au total (16 + 8 + 5 + 1) et aucun ne vient d'un script validé. Le contrôle « aucun dossier nouveau n'est de mes essais » de `d4` était vide (préfixe `=>` mal retiré) ; refait dans `d5` sur les `qui.txt` relus (l. 831-841).
2. **Vrai VERROU** : il a changé pendant la VAL (188 dossiers au départ, 195 ensuite, tenu par `STE-R7` puis `EVAL-R1`, gardien d'une autre session). Aucun de ces dossiers ne vient de moi ; j'ai fait seulement `-Etat` (4 appels, listes identiques avant / après chaque appel). Le critère d'arrêt « le vrai verrou change pendant l'essai » est donc noté, non déclenché par mes actes.
3. `-TestCourse` (crochet d'essai caché, E2) crée par `New-Item`, non atomique, et n'est utilisé que pour la simulation ; il ne sert pas en production mais reste appelable : à connaître, pas un défaut de V7.
4. Non rejoué par la VAL : Windows PowerShell 5.1 (les trois scripts sont ASCII / LF, l'IMPL en a joué 6 commandes) ; HEAD détaché, `index.lock`, rebase en cours, fichier de l'arbre illisible, suppression indexée `D.` et renommage `R` (cas cités par T3 § 4 et sa table F01 ; je n'ai pas utilisé `git rm` / `git mv`, même dans le scratchpad) ; droits d'écriture refusés ; appel réel `Numero.ps1 -Reserver` sur le vrai fichier (interdit). Le comptage de CR d'un fichier de plus de 8 000 octets a été vérifié sur `NUMEROS.md` (45 / 45) et `README.md` (13 / 13).
5. Mon écart de méthode : j'ai envoyé une commande Bash contenant `rm -f` (sur un fichier d'essais qui n'existait pas encore) ; le système de permissions l'a refusée, elle n'a pas été exécutée, aucune suppression n'a eu lieu.
6. Information V10 : sans `.gitattributes` `* -text`, un dépôt jetable (`a0`) montre le comportement de git avec `core.autocrlf` du poste (valeur relevée `false` en global / système ; voir le détail dans l'essai V10-2) ; l'attribut du projet (`.gitattributes` : `* -text`) est donc ce qui rend l'alerte `FINS` fiable, conformément à T3 § 5.3.
7. Observation V9 : l'index de l'addon (`D:\Game\LifePlay-Sandbox-5.8\.git\index`) n'existe pas comme fichier à ce chemin (relevé de date 0 avant et après) : l'addon est probablement un `.git` de type fichier (arbre de travail lié) ; sans effet sur `GitEtat.ps1`, qui répond correctement. Non élucidé.
8. Le HEAD du jeu a avancé pendant la VAL (`ae5d5e4` → `7bceea6`) : `NUMEROS.md` est passé de modifié (`CR:45/42`, IMPL T3) à propre (`45/45`). Ce n'est pas une divergence du script.
Fichiers écrits : `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\OUTC\OUTC-VAL-B.md`, `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\OUTC\OUTC-VAL-B_essais.txt` (ignoré par git), scratchpad `…\scratchpad\OUTC-T4b\`.
Fichiers à commiter (dépôt du jeu, branche `ue5.8`) : `A Docs/Migration/etat/OUTC/OUTC-VAL-B.md`. Aucun autre : aucun script modifié, aucune écriture git hors du scratchpad (`git init`, `add`, `commit` dans les dépôts jetables du scratchpad seulement).