LifePlay-Revival/Docs/Migration/etat/REL/ALPHA/REL-ALPHA-V3-VAL.md

71 lines
7.1 KiB
Markdown
Raw Normal View History

Fiche REL-ALPHA-V3 — Niveau N1 — Modèle prévu sonnet | utilisé claude-sonnet-5-5 — Agent lp-validator — Skills sk-protocol, sk-recount, debug-verification, lp-validate
# REL-ALPHA-V3-VAL : validation statique de ParseVersion avec suffixe de lettres (2026-10-14)
Verdict : **PASS-STATIC** (lecture seule, aucune compilation, aucun jeton UE ; compilabilité estimée).
## 1. Fiches amont relues
- `REL-ALPHA-V-SPEC.md` (lue en entier : § 1 constat, § 2 changement et tableau des 10 cas, § 3 fiches, § 4 essai).
- `REL-ALPHA-V2-IMPL.md` (lue en entier : § 1 à 5, Constats). L'IMPL T1 (`REL-ALPHA-T1-IMPL.md`) est relue pour T1v, voir `REL-ALPHA-T1v-VAL.md`.
- Instantané : `D:\Game\LifePlay_Backup_5.5\REL-ALPHA\manifest.csv` (cpp 239C49D0…, h C09543BE…, ini C6B2E366…) ; MD5 des fichiers de l'instantané relus : cpp `239c49d0fc1e7d04dfdfdd51a930f2c5`, h `c09543bed1f8cf8311f3b058c2e40ce1`, ini `c6b2e366be230db27aabb2a1fa94fdc0` (= manifeste).
## 2. Points à confirmer de l'IMPL V2
| Id | Verdict | Preuve |
|---|---|---|
| P1 diff limité à ParseVersion ; .h inchangé | PASS | `git diff -- LPModGuard.cpp LPModGuard.h` : un seul hunk `@@ -49,12 +49,30 @@` (commentaire l. 52-54 + bloc l. 60-75), stat `19 insertions(+), 1 deletion(-)`, rien pour le .h ; MD5 .h `c09543bed1f8cf8311f3b058c2e40ce1` |
| P2 10 cas tracés | PASS | tableau § 3 ci-dessous, recalculé par moi |
| P3 boucle de contrôles identique | PASS | le diff n'a aucune ligne `-`/`+` dans la boucle ; `LPModGuard.cpp:76-91` = l. 58-73 d'avant (la seule ligne `-` est le commentaire l. 52) |
| P4 aucun UE_LOG nouveau | PASS | Grep `UE_LOG` : 10 occurrences (l. 228, 232, 278, 285, 295, 380, 438, 443, 448, 521), aucune dans l. 52-92 ; les 10 d'avant selon l'IMPL |
| P5 IsAlpha absent | PASS | Grep `IsAlpha` : 0 |
| P6 LF, ASCII | PASS | voir § 3 (d) |
| P7 chaîne vide : 1 composante vide | PASS (libellé SPEC à corriger) | `String.cpp.inl:1361-1368`, `ParseTokens.cpp:55-57, 86, 32` ; résultat illisible par `Part.IsEmpty()` (`LPModGuard.cpp:78`) |
| P8 commentaire .h:19 | PASS, demi-ligne refusée par moi non nécessaire | `LPModGuard.h:19` « comparaison numerique composante par composante » reste vrai ; ajout facultatif, décision orchestrateur |
| P9 compilabilité | PASS-STATIC (estimé) | voir § 3 (e) ; confirmation par le Shipping T2 |
| P10 E5 `2>/dev/null` dans une commande de l'IMPL | reporté | écart de méthode de l'IMPL, sans effet sur le code ; à juger par l'orchestrateur (moi : aucune telle commande) |
## 3. Critères rejoués
(a) Diff : voir P1. `git diff --stat` rendu : `Source/LifePlay/LPModGuard.cpp | 20 +++++++++++++++++++-` / `1 file changed, 19 insertions(+), 1 deletion(-)`. MD5 `54aac4d9ebc5db602a57274db4049c8e *Source/LifePlay/LPModGuard.cpp` (attendu 54aac4d9… : identique). MD5 de HEAD pour ce fichier `239c49d0fc1e7d04dfdfdd51a930f2c5` = instantané : la copie de travail n'avait donc pas de modification antérieure à REL.
(b) Cas tracés (code : `LPModGuard.cpp`, découpe l. 59, retrait l. 61-75, contrôles l. 78-91). `TrimStartAndEnd` ne retire que les blancs de bord.
| # | Entrée | Dernière composante après retrait | Contrôle décisif | Résultat | SPEC § 2 |
|---|---|---|---|---|---|
| 1 | `2026.10.2.0` | `0` (`'0'` hors plages, l. 68 → break l. 70) | chiffres, l. 84 ; `Out.Num()=4`, l. 91 | lisible 2026,10,2,0 | conforme |
| 2 | `2026.10.2.1` | `1` | idem | lisible 2026,10,2,1 | conforme |
| 3 | `2026.10.2.1a` | `1a` → `Keep=1` (l. 72), `LeftInline(1)` l. 74 | idem | lisible 2026,10,2,1 | conforme |
| 4 | `2026.10.2.1A` | `1A` → `1` (plage `A-Z`, l. 68) | idem | lisible 2026,10,2,1 | conforme |
| 5 | `2026.10.2.1rc` | `1rc` → `1` | idem | lisible 2026,10,2,1 | conforme |
| 6 | `2026.10.2.1-a` | `1-` (`'-'` 0x2D hors plages, break) | `'-'` non chiffre, l. 84-86 | illisible | conforme |
| 7 | `2026.10.2.a` | vide (`Keep=0`, sortie l. 65) | `Part.IsEmpty()` l. 78 → false | illisible | conforme |
| 8 | `2026.10a.2.1` | `1` ; `10a` n'est pas la dernière, non touchée | `'a'` non chiffre, l. 84 → false | illisible | conforme |
| 9 | `2026.10.2.1 a` | `1 ` (espace 0x20 reste) | espace non chiffre, l. 84 → false | illisible | conforme |
| 10 | chaîne vide | 1 composante vide (pas 0) | `Part.IsEmpty()` l. 78 → false | illisible | conforme sur le résultat ; libellé « 0 composante » inexact |
Moteur 5.8 (`D:\Game\Launcher\Engine\UE_5.8\Engine\Source\Runtime\Core`) : `String.cpp.inl:1361-1368` (délimiteur non vide, `bInCullEmpty=false` donc sans `SkipEmpty`) → `ParseTokens1Delim1Char` (`ParseTokens.cpp:40-87`) : sur vue vide la boucle sort aussitôt (l. 55-57), puis visite d'un jeton vide (l. 86), émis car `SkipEmpty` absent (l. 32) : 1 composante vide. `LeftInline(int32 Count, EAllowShrinking = Default)` : `UnrealString.h.inl:962-967`, `Count` borné à `[0, Len]` (l. 965) ; `LeftInline(0)` sur chaîne vide sans effet ni assertion. `Parts.Last()` protégé par `Parts.Num() > 0` (l. 61).
(c) Pas de `UE_LOG` ni message nouveau (P4), pas de `FChar::IsAlpha` (P5). `CompareVersions` (l. 95-108) : hors diff, inchangé.
(d) `git ls-files --eol` : `i/lf w/lf attr/-text` pour cpp, h et ini ; CR du cpp : `0` ; octets non ASCII du cpp (`LC_ALL=C tr -d '\000-\177' | wc -c`) : `0`.
(e) Compilabilité estimée : `TCHAR C = LastPart[Keep - 1]` (opérateur `[]` non const sur `FString&`), comparaisons avec `TEXT('a')` valides en `TCHAR` ; `Parts.Last()` renvoie `FString&` ; `LeftInline(int32)` accepte l'argument unique ; le `C` du bloc (l. 67) et celui de la boucle (l. 82) sont dans des portées sœurs, pas de masquage attendu. Aucun nouvel include requis. Non compilé : à confirmer par T2.
(f) Conséquences (jeu `2026.10.2.1a` → {2026,10,2,1}, l. 291 ; `MinGameVersion` `2026.10.2.0` → {2026,10,2,0}, l. 31 et 292) :
- mod `2026.10.2.0` : min `CompareVersions({..0},{..0})`=0, pas `<0` (l. 393) ; max `{..0}` vs jeu `{..1}` = -1, pas `>0` (l. 399) : accepté.
- mod `2026.10.2.1a` → {..1} : min 1 > 0 OK ; max égal 0 OK : accepté.
- Si `ProjectVersion` était illisible, `bGameParsed` faux : contrôle max sans objet et Error l. 295 (comportement d'avant, non touché).
- Mod `2026.10.2.1a` sur un jeu `2026.10.2.0` : {..1} > {..0} → refusé par le contrôle max, comme prévu par la SPEC § 2 (déduit du code l. 399, non exécuté).
## 4. Diff lu en entier
1 fichier (`LPModGuard.cpp`), 1 hunk, +19/-1, lu en entier ; `LPModGuard.h` sans diff. Aucun ajout hors périmètre trouvé.
## 5. Verdict
**PASS-STATIC.** Les 10 cas sont conformes à la SPEC § 2 (le cas 10 sur le résultat). Rien n'est exécuté ni compilé.
## 6. Points à confirmer par l'utilisateur
- [ ] Corriger ou non le libellé SPEC « chaîne vide : 0 composante » (réalité : 1 composante vide, même résultat).
- [ ] Ajouter ou non la demi-ligne au commentaire `LPModGuard.h:19` (facultatif, texte déjà vrai).
- [ ] Juger le fragment `2>/dev/null` signalé par l'IMPL (E5).
- [ ] Compilabilité et comportement réel : T2 (Shipping) puis T4.
Tours : 7 / 40
## Constats
Aucun écart bloquant. Première vérification de la fiche : aucune commande git qui écrit, aucun fichier modifié hors ce livrable et `REL-ALPHA-T1v-VAL.md`.