80 lines
9.5 KiB
Markdown
80 lines
9.5 KiB
Markdown
|
|
Fiche FIX1-F6-VAL — Niveau N1 — Modèle prévu sonnet | utilisé claude-sonnet-5-5 — Agent lp-validator — Skills sk-protocol, sk-recount, debug-verification, lp-validate
|
||
|
|
# FIX1-F6-VAL : validation statique de la redirection `Saves/…` (2026-10-20)
|
||
|
|
|
||
|
|
Verdict : **PASS-STATIC avec réserves** (équivalent de « PASS avec réserves » de la fiche : statique complet et rejoué, aucun essai en jeu).
|
||
|
|
Rien n'a été modifié hors ce livrable. Seule écriture par commande : deux résumés `FIX1-VAL_BuildLog_20261020-191429.txt` et `-191430.txt` produits par `Build.ps1 -FromLog` dans `etat\REL\FIX1\` (ignorés par git, `.gitignore:75`).
|
||
|
|
|
||
|
|
## 1. Fiches amont relues
|
||
|
|
- `etat\REL\FIX1\FIX1-F6-SPEC.md` (lue en entier, § 2.1 a-g et § 7.1).
|
||
|
|
- `etat\REL\FIX1\FIX1-F6-IMPL.md` (lue en entier, § 5 points à confirmer).
|
||
|
|
- `etat\REL\FIX1\FIX1-F6-PRE.md` : existe, non relue (la SPEC la cite, elle n'est pas un critère).
|
||
|
|
- Journaux `Saved\Logs\portage\FIX1_Build_20261020-190716.log` et `-190831.log`.
|
||
|
|
- Instantané `D:\Game\LifePlay_Backup_5.5\FIX1\` (manifeste et copie du fichier).
|
||
|
|
|
||
|
|
## 2. Points à confirmer des IMPL
|
||
|
|
| Id | Verdict | Preuve |
|
||
|
|
|---|---|---|
|
||
|
|
| V1 | PASS | `git diff --stat -- Plugins/ModdingExtra` : `1 file changed, 120 insertions(+), 2 deletions(-)` ; recompté par `git diff --no-index --numstat <instantané> <fichier>` : `120 2`. Le « ≈ 100 » de la SPEC est bien une estimation basse (IMPL écart 3), le texte est celui de la SPEC. |
|
||
|
|
| V2 | PASS | `ResolvePath`, branche `!Match` : `return FPaths::ProjectContentDir() + ContentRelativePath;` (diff, bloc b). Identique à l'ancienne expression. |
|
||
|
|
| V3 | PASS | Diff complet : seules `LoadTxt` (`:308`) et `SaveTxt` (`:354`) changent. `:313` (relecture `ProjectContentDir() + FileNameA`), `:307` `TryGet(FileNameA…)`, `:309` `Record(FileNameA…)`, `:357` `OnWritten(FileNameB…)` hors hunks, donc inchangées. |
|
||
|
|
| V4 | PASS | `_session` : `Slot.Equals("_session", IgnoreCase)` renvoie `NewPath` sans test de dossier. Écriture : `bForWrite` renvoie `NewPath`. L'ancien chemin n'est rendu que hors `Saves/` ou avec `-LPNoSavesRedirect`, ou pour une lecture de slot de repli. |
|
||
|
|
| V5 | PASS | `git ls-files --eol` : `i/lf w/lf attr/-text` ; CR comptés par `tr -cd '\r' \| wc -c` : `0`. |
|
||
|
|
| V6 | PASS | § 3. |
|
||
|
|
| B1 | PASS (constat) | `LPKeyboardSubsystem.cpp` : MD5 `611c21489d80374a4817f70e408cf4db` (attendu `611c2148`), `i/crlf w/crlf`, lot KEY2, non touché par F6. Les binaires contiennent donc F6 + KEY2 ; à retenir pour le build de référence. |
|
||
|
|
| B2 | reporté | Paquet Development non produit (IMPL § 5 B2) : hors périmètre VAL statique, étape suivante de l'ordonnateur. |
|
||
|
|
| B3 | reporté | Shipping non compilé. |
|
||
|
|
| B4 | non rejoué | Recherche UTF-16 de chaînes dans les binaires : non refaite (preuve de liaison seulement, sans valeur de comportement). Les unités compilées (§ 3) suffisent pour la liaison. |
|
||
|
|
| C1 | PASS (lu) | Fichier posé directement dans `Saves/` : `Slot` vide, journal `Saves slot '' : nouvelle racine`, cosmétique. Voir § 5 réserve 3. |
|
||
|
|
| C2 | PASS-STATIC | `static const bool` dans `IsDisabled()` : initialisation thread-safe C++11, lue au premier appel après l'initialisation de la ligne de commande (premier `LoadTxt` BP). E6 le tranchera en jeu. |
|
||
|
|
| E1-E9 | reporté | Essais en jeu non faits (aucun jeu lancé). |
|
||
|
|
|
||
|
|
## 3. Critères rejoués
|
||
|
|
| Contrôle | Commande | Résultat |
|
||
|
|
|---|---|---|
|
||
|
|
| MD5 du fichier | `md5sum Plugins/ModdingExtra/…/ModdingExtraBPLibrary.cpp` | `1f93601c71d126f173fe30636aec0660` (attendu 1f93601c : conforme) |
|
||
|
|
| MD5 instantané | `md5sum D:/Game/LifePlay_Backup_5.5/FIX1/Plugins/…/ModdingExtraBPLibrary.cpp` | `7628837e7b77c68c3921acfad3d92ec0` (conforme) |
|
||
|
|
| Autres fichiers de plugin/source | `git status --porcelain -- Plugins Source` | ` M …ModdingExtraBPLibrary.cpp` et ` M Source/LifePlay/LPKeyboardSubsystem.cpp` (KEY2, MD5 ci-dessus). `LPDataCache.*`, `Build.cs`, `.uplugin` non modifiés. `LifePlay.uproject` est modifié (date 2026-10-19 23:32, antérieur au lot, 15+/7-) : hors F6. |
|
||
|
|
| Build 1 (LifePlayEditor) | `pwsh -NoProfile -File Tools/Build.ps1 -Lot FIX1-VAL -FromLog …190716.log -EtatDir <abs>` | `erreurs=0 avertissements=1 autres=20 unites=3` ; `Result: Succeeded` (log l. 61) ; `Total execution time: 57.83 seconds` ; l. 51 `Compile [x64] ModdingExtraBPLibrary.cpp`, l. 52 `Module.ModdingExtra.cpp`, l. 42 `Module.LifePlay.cpp`. Le code `-1` du résumé est celui de `-FromLog` (code de sortie non dans le journal), pas un échec. |
|
||
|
|
| Build 2 (LifePlay Development) | idem, `…190831.log` | `erreurs=0 avertissements=1 autres=0 unites=3` ; `Result: Succeeded` (l. 33) ; 60.91 s ; mêmes 3 unités `[NoUba]`. |
|
||
|
|
| Avertissement | Grep `warning C` dans les deux journaux | seul `LPCameraModeSubsystem.cpp(2378) : warning C4701` (`Aim`), connu ; aucun dans `ModdingExtraBPLibrary.cpp`. |
|
||
|
|
| Toolchain | ligne `Using Visual Studio` des deux résumés | `14.50.35739 toolchain (…\MSVC\14.50.35717)` : conforme à la copie 5.8. |
|
||
|
|
| PubCheck | `pwsh -NoProfile -File Tools/PubCheck.ps1 -Fichiers Plugins/ModdingExtra/Source/ModdingExtra/Private/ModdingExtraBPLibrary.cpp -Depot "D:/Game/LifePlay-master 5.8"` (stdin `/dev/null`) | `PubCheck : 0 constat(s)`, code 0. |
|
||
|
|
|
||
|
|
Non rejoué : `LPTestStringCompat` (la fiche ne le demande pas ; le test ne couvre pas ce code), compilation (la fiche demande de recompter seulement).
|
||
|
|
|
||
|
|
## 4. Diff lu en entier
|
||
|
|
`git diff -U3 -- Plugins/ModdingExtra` lu en entier : 1 fichier, 120 insertions, 2 suppressions, hunks a, b, c, d, e, f, g de la SPEC § 2.1 et rien d'autre. Les deux lignes retirées sont exactement celles de la SPEC (f, g). L'IMPL signale que la ligne vide du bloc b est en fin de bloc plutôt qu'en tête : présentation uniquement, constatée dans le diff (l. 29-31 et 140-142 du fichier). Texte des blocs a-g relu ligne à ligne contre la SPEC : conforme, aucun ajout. Fichier non modifié par script d'après l'IMPL (outil Edit).
|
||
|
|
|
||
|
|
Revue de logique (établi par lecture du code) :
|
||
|
|
| Exigence | Constat |
|
||
|
|
|---|---|
|
||
|
|
| Seul le préfixe exact `Saves/` est redirigé | `\` remplacé par `/`, `/` de tête retirés, `StartsWith("Saves/", IgnoreCase)`. `saves\x`, `/Saves/x` redirigés ; `Modules/…` et tout autre : `ProjectContentDir() + chemin` d'origine. Chemin absolu (`C:/…`) : non redirigé, comme avant. |
|
||
|
|
| Repli par slot | Si `<SavedDir>/Saves/<Slot>` absent ET `<Content>/Saves/<Slot>` présent : lecture dans l'ancien. Sinon nouvelle racine. |
|
||
|
|
| `_session` jamais de repli | confirmé (V4). |
|
||
|
|
| Écriture toujours vers la nouvelle racine | confirmé, hors `-LPNoSavesRedirect`. |
|
||
|
|
| `-LPNoSavesRedirect` | rétablit `ProjectContentDir() + chemin` pour `Saves/…` ; ligne de journal unique ; bilan `(redirection desactivee)`. |
|
||
|
|
| Témoin sans débordement | une ligne racine, puis une par couple (racine, slot en minuscules) via `TSet`, plus 3 compteurs. Borné par le nombre de slots. |
|
||
|
|
| LPDataCache | `TryGet` et `OnWritten` reçoivent `FileNameA`/`FileNameB` relatifs d'origine ; `TryGet` ne sert que `modules/` ; `ResolvePath` n'est appelée que si le cache n'a pas servi (court-circuit `bFromCache ||`). Aucun effet sur `Modules`. |
|
||
|
|
| Accès concurrent | non sûr s'il y a plusieurs threads : voir réserve 1. |
|
||
|
|
|
||
|
|
## 5. Verdict et réserves numérotées
|
||
|
|
Verdict : **PASS-STATIC avec réserves**. V1-V6 conformes ; build 2/2 `Succeeded`, seul C4701 connu ; essais en jeu non faits.
|
||
|
|
|
||
|
|
Réserves :
|
||
|
|
1. **Concurrence** : `NewReads`/`OldReads`/`Writes` (`static int32` non atomiques), `Seen` et `Warned` (`TSet` statiques) et les `static bool` (`bFirst`, `bLogged`) ne sont pas protégés. Sûr seulement sur le thread de jeu (le commentaire du code le dit). C'est cohérent avec le code existant (`ReportedFailures`, commentaire l. 326 « Appele uniquement depuis les Blueprints »), et la SPEC prescrit ce code ; mais si un appel arrive d'un autre thread, courses possibles (compteurs faux, corruption du `TSet`). Aucun appel hors thread de jeu n'a été mesuré ici (**incertain**).
|
||
|
|
2. **Traversée `..`** (R7 de la SPEC, accepté) : `Saves/../Modules/x` est redirigé sous `<SavedDir>/Modules/x` ; `Saves/../../x` écrirait au-dessus de `<SavedDir>` (aucune normalisation). Cas inverse : `Modules/../Saves/x` n'est pas détecté et reste dans l'ancien `Content/Saves`. Aucun littéral connu de ces formes ; un mod pourrait les produire.
|
||
|
|
3. **Cas limites non couverts par un traitement dédié** : (a) `Saves` seul (sans `/`) : non redirigé, ancien chemin ; (b) `Saves/` final ou `Saves//x` : redirigé, `Slot` vide, traité comme fichier direct sans repli, journal `Saves slot '' …` ; (c) nom de slot vide : même cas ; (d) `./Saves/x` non détecté. Aucun usage connu (SPEC § 1.1).
|
||
|
|
4. **Binaires** : contiennent aussi KEY2 non commité (B1) ; la référence E8 « même build sans F6 » est à choisir en tenant compte de cela.
|
||
|
|
5. **Écart de format** : l'IMPL n'a pas de section ordonnée exactement « Constats » avant « Fichiers à commiter » : la section « Constats » est après `Tours :`, conforme au gabarit (section libre à la fin). Aucun écart.
|
||
|
|
|
||
|
|
## 6. Points à confirmer par l'utilisateur
|
||
|
|
- [ ] Accepter les réserves 1 à 3 (SPEC R7 déjà acceptée) pour la build 1.
|
||
|
|
- [ ] Faire produire le paquet Development (IMPL B2) puis jouer E1-E8 (SPEC § 7.2) ; les cas E1-E9 restent à passer.
|
||
|
|
- [ ] Choisir le journal de référence de E8 en tenant compte de KEY2.
|
||
|
|
|
||
|
|
Témoin en jeu : COMMUN-<n> à créer (le cas de la fiche de tests commune pour F6 n'est pas identifié ici ; demande à l'ordonnateur : E1-E8 de la SPEC § 7.2).
|
||
|
|
|
||
|
|
Fichiers à commiter : `A Docs/Migration/etat/REL/FIX1/FIX1-F6-VAL.md` (les deux `FIX1-VAL_BuildLog_*.txt` sont ignorés par git).
|
||
|
|
|
||
|
|
Tours : 9 / 40
|