LifePlay-Revival/Docs/Migration/etat/ST/STG/STG-B2q-VAL.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

21 KiB
Raw Blame History

Fiche STG-B2q-VAL — Niveau N1 — Modèle prévu (agent lp-validator) | utilisé claude-sonnet-5-5 — Agent lp-validator — Skills lp-validate, sk-protocol, sk-recount, debug-verification

STG-B2q-VAL : validation statique de B2q-a (bornes de rendu des Person) et du témoin T-cull (2026-10-14)

Méthode : VAL statique, sans UE ni compilation, aucune écriture hors de ce livrable. Copie D:\Game\LifePlay-master 5.8 (branche ue5.8, HEAD 0745917). Moteur lu : D:\Game\Launcher\Engine\UE_5.8. Les chemins moteur ci-dessous sont relatifs à Engine\Source\Runtime\.

Deux états validés : les sections 1 à 6 portent sur la première version (cpp C9D1AC98…, 1717 lignes) ; la section 4b contrôle le delta de la version corrigée par l'orchestrateur (cpp 7448C8FB…, 1724 lignes).

1. Fiches amont relues

Fiche Fichier Relue
STG-B2q-DIAG Docs\Migration\etat\ST\STG\STG-B2q-DIAG.md (137 lignes) en entier
STG-B2q-IMPL Docs\Migration\etat\ST\STG\STG-B2q-IMPL.md (88 lignes, version de la 1re VAL) en entier
Diff Docs\Migration\etat\ST\STG\STG-B2q.diff (167 lignes, version de la 1re VAL) en entier
Instantané D:\Game\LifePlay_Backup_5.5\STG-B2q\ (manifest.csv, 2 entrées) relu

Aucune autre IMPL dans le lot B2q (DIAG puis IMPL). L'IMPL § 2b et § 5 mis à jour par l'orchestrateur après la 1re VAL ne sont pas relus ici (le contrôle du delta porte sur le code, section 4b).

2. Points à confirmer des IMPL

# Point (IMPL § 4) Statut Motif
1 Bar et café : C2 autour des personnages assis, aucune disparition, lignes B2q-a / T-cull mesure, aucune alerte reporté (COMMUN-8) essai en jeu, hors VAL statique
2 Personnage couché : même contrôle reporté (COMMUN-8) idem
3 Coût : stat unit avant et après, ou lignes LPDebug hitch reporté (COMMUN-8) mesure en jeu
4 Alerte T-cull avec dans=1 : cause hors bornes reporté (COMMUN-8) dépend du journal de jeu

3. Critères rejoués (commande, sortie)

3.1 MD5 (point 1 de la fiche) : PASS

Commande : md5sum Source/LifePlay/LPDirectControlSubsystem.{cpp,h} et md5sum sur l'instantané.

c9d1ac98df479a4aac95e44213766f78 *Source/LifePlay/LPDirectControlSubsystem.cpp
5f3492917b8202b267d8879e4613966b *Source/LifePlay/LPDirectControlSubsystem.h
1a74d6b724bd63f04e04fda42682446d *D:/Game/LifePlay_Backup_5.5/STG-B2q/Source/LifePlay/LPDirectControlSubsystem.cpp
519e23dc9eb2809fa36c1bbf942a7667 *D:/Game/LifePlay_Backup_5.5/STG-B2q/Source/LifePlay/LPDirectControlSubsystem.h

Égal à IMPL § 5 (C9D1AC98… / 5F349291…) et § 1 (1A74D6B7… / 519E23DC…) à l'époque de la 1re VAL. manifest.csv : mêmes MD5, tailles 53814 / 3552. Tools\FileCheck.ps1 -Lot STG-B2q -OnlyChanged : fichiers=2 CRLF=2 alertes=0 introuvables=0, contenu modifie=2, code 0. Le cpp actuel a changé (section 4b).

3.2 Diff régénéré (point 2) : PASS, avec un écart de compte

Commande : diff -u <instantané> <actuel> pour chaque fichier, comparé à STG-B2q.diff (lignes d'en-tête et CR ôtés) : aucune différence (sortie vide). diff normal : cpp 0 retirée / 123 ajoutées ; h 0 retirée / 5 ajoutées. Recompte du fichier .diff (grep -c '^+' hors +++) : 128.

  • Écart E1 : IMPL § 2 annonce « 127 lignes ajoutées » ; recompté 128 (123 + 5). Sans conséquence sur le code ; chiffre de l'IMPL à corriger.
  • Rien d'autre que l'IMPL § 2 : hunks cpp = include Camera/PlayerCameraManager.h, appel FitPersonBounds(DeltaTime) dans Tick, corps de la fonction ; hunks h = déclaration + 3 membres. Aucun ajout non annoncé.
  • git diff --stat HEAD donne 635/24 lignes sur ces deux fichiers : ce sont les lots antérieurs (M1e, C6-b, C7-a, etc.) non encore commités ; le delta B2q est celui de l'instantané.

3.3 Fins de ligne, ASCII, en-tête (point 6) : PASS

Commande : script python -I (comptage d'octets) sur les fichiers.

Source/LifePlay/LPDirectControlSubsystem.cpp CRLF 1717 LFseul 0 CRseul 0 nonascii bytes 6 BOM False
Source/LifePlay/LPDirectControlSubsystem.h   CRLF 101  LFseul 0 CRseul 0 nonascii bytes 0 BOM False
Docs/Migration/etat/ST/STG/STG-B2q-IMPL.md   CRLF 0   LFseul 88 CRseul 0 nonascii bytes 182 BOM False
D:/Game/LifePlay_Backup_5.5/STG-B2q/.../LPDirectControlSubsystem.cpp CRLF 1594 LFseul 0 nonascii bytes 6
  • cpp : CRLF pur (1594 + 123 = 1717, donc les 123 lignes ajoutées sont en CRLF), aucun LF isolé. h : CRLF pur.
  • Non-ASCII du cpp : 6 octets avant (instantané) et 6 après, aux lignes 455 (« %s ») et 514 (accent), préexistantes ; 0 ajouté. Les 123 + 5 lignes ajoutées sont ASCII.
  • IMPL : LF pur, en-tête complet (« Fiche … — Niveau N3 — Modèle prévu … | utilisé … — Agent … — Skills … »), aucun C:\Users (Grep, 0 résultat).

3.4 Gardes de Big Boss, par lecture de FitPersonBounds (point 3) : PASS-STATIC

Source : Source/LifePlay/LPDirectControlSubsystem.cpp l. 1065-1185 (version de la 1re VAL ; le diff les range en l. 23-142).

Garde Lecture Verdict
Boucle unique toutes les 0,5 s BoundsDelay += DeltaTime; if (BoundsDelay < ScanInterval) return; puis remise à 0 ; une seule boucle TActorIterator<ACharacter> (+ un nettoyage de MeasuredSeats, borné par le nombre de personnes mesurées). Appel unique dans Tick (l. 875) PASS
Person visibles seulement continue si pas de maillage, Person->IsHidden(), !Body->IsVisible(), GetNumBones()==0, ou classe ne commençant pas par Person_C (même filtre que LPDebugSubsystem.cpp l. 198 et 367, LPOutdoorRoomSubsystem.cpp l. 343) PASS
S borné à [1 ; 4] FMath::Clamp(static_cast<float>(Needed), 1.f, MaxScale) avec MaxScale = 4.f ; Needed part de 1.0 et ne fait que croître PASS
Hystérésis 10 % if (FMath::Abs(Scale - Current) > ScaleChange * Current), ScaleChange = 0.1f, relatif à l'échelle courante PASS
Journal B2q-a une UE_LOG dans le seul bloc « changement de plus de 10 % » PASS
Journal T-cull mesure une UE_LOG par nouveau meuble : MeasuredSeats.FindRef(Person).Get() != Seat puis Add ; entrée retirée quand OccupyingFnt est vide PASS
Alerte T-cull ≤ 1/s CullAlertDelay décrémenté à chaque tick, condition CullAlertDelay <= 0.f, remis à AlertInterval = 1.f à l'émission ; un seul délai global PASS
Collisions et tracés voir ci-dessous PASS

Collisions et tracés (lu dans le moteur 5.8) :

  • UPrimitiveComponent::SetBoundsScale (Engine\Private\Components\PrimitiveComponent.cpp l. 2538-2543) : BoundsScale = Nouveau; UpdateBounds(); MarkRenderTransformDirty(); Rien d'autre.
  • USkinnedMeshComponent::InvalidateCachedBounds (SkinnedMeshComponent.cpp l. 3313-3339) : met à faux bCachedLocalBoundsUpToDate / bCachedWorldSpaceBoundsUpToDate sur le composant, ses suiveurs de pose et ses enfants skinnés. État de cache de bornes seulement.
  • CalcMeshBound (SkinnedMeshComponent.cpp l. 2300-2301) : BoxExtent *= BoundsScale et SphereRadius *= BoundsScale, centre inchangé.
  • bEnableLineCheckWithBounds (SkeletalMeshComponent.h l. 904) et LineCheckBoundsScale (l. 468) : absents du diff et de tout Source/ (Grep, 0 résultat). SkeletalMeshComponent.cpp ne les initialise qu'au constructeur (l. 450).
  • La seule lecture de Bounds ailleurs dans Source/LifePlay qui sert à une décision (LPDirectControlSubsystem.cpp l. 1352, GetClosestPointTo) porte sur des UStaticMeshComponent de meubles, pas sur le corps d'une Person.
  • Le diff ne touche ni capsule, ni profil de collision, ni asset physique.

3.5 Logique du facteur (point 4) : PASS-STATIC, avec réserves

Formule de la 1re version (l. 1125-1135) : Extent = Bounds.BoxExtent / Current (demi-étendue à l'échelle 1), Half = max(Extent[axe], 10), Needed = max(1, max sur les axes de (|Bassin - Origin| + Half) / Half).

  • Stabilité : établi par lecture. Bounds.Origin ne dépend pas de BoundsScale (seul BoxExtent est multiplié, CalcMeshBound l. 2300) ; Extent divisé par Current redonne la valeur à l'échelle 1 ; Needed est donc le même avant et après application, et au scan suivant |Scale - Current| = 0 : pas d'oscillation entre deux valeurs. Le cache de bornes est invalidé avant SetBoundsScale, indispensable car USkeletalMeshComponent::CalcBounds (SkeletalMeshComponent.cpp l. 3424-3445) réutilise sinon les bornes en cache, qui portent l'ancienne échelle.
  • Division par zéro impossible : Current >= KINDA_SMALL_NUMBER (1e-4f, UnrealMathUtility.h l. 131) et Half >= MinExtent = 10.0.
  • Cas debout (réserve R1, traitée en 4b) : la formule de la 1re version donne Needed = 1 + |écart| / Half par axe, donc S > 1 dès que le bassin n'est pas exactement au centre (S = 1,1 à 1,3 estimé). IMPL § 2 disait S = 1 : inexact à la lettre.
  • Variation avec l'orientation (R2) : les bornes du moteur sont une AABB monde ; une rotation en lacet change Extent et Offset, donc Needed. Une personne qui tourne peut faire changer S de plus de 10 % et produire une ligne par balayage (0,5 s). Borné, mais bruyant.
  • Échelle déjà > 1 venant d'ailleurs (R3) : Current est lue et divisée, donc le calcul reste juste, mais S est ensuite imposé (borné à [1 ; 4]) : une valeur externe de 3 sur le corps serait ramenée à S si S diffère de plus de 10 %, et un Blueprint qui remet 3 provoquerait un va-et-vient. Le DIAG § 2.2 estime la valeur du gabarit à 1 (non vérifié par MCP). Les SetBoundsScale(3.0) de Person::NewProxy portent sur les vêtements en bUseAttachParentBound, dont les bornes viennent du parent (SceneComponent.cpp l. 1696-1699) : sans conflit.
  • Enfants bUseAttachParentBound : Body->GetChildrenComponents(true, Children) (tous descendants) ; pour chaque UPrimitiveComponent avec le drapeau : UpdateBounds() puis MarkRenderTransformDirty(). Le corps est mis à jour avant les enfants. Correct.

3.6 Compilabilité par lecture des en-têtes UE 5.8 (point 5) : PASS-STATIC (non compilé)

Symbole Lu Accès / signature
UPrimitiveComponent::BoundsScale PrimitiveComponent.h l. 970 float, après public: (l. 961) : OK
SetBoundsScale(float) l. 1558 public (ENGINE_API)
WasRecentlyRendered(float) const l. 999 public
bUseAttachParentBound SceneComponent.h l. 236 uint8 : 1, après public: (l. 223) : OK
Bounds SceneComponent.h l. 129 FBoxSphereBounds, public (l. 127)
GetBox(), Origin, BoxExtent Math\BoxSphereBounds.h l. 226 (GetBox() const) membres publics
FBox::IsInside(const TVector<T>&) const Math\Box.h l. 494 OK avec FVector
FVector::GetAbs, operator[](int32) Math\Vector.h l. 457 et 465 T operator[](int32) const : OK en double
GetChildrenComponents(bool, TArray<USceneComponent*>&) const SceneComponent.h l. 725 public
UpdateBounds() SceneComponent.h l. 1130 (virtuel) public
MarkRenderTransformDirty() ActorComponent.h l. 1134 public (zone public: l. 889-1420)
InvalidateCachedBounds() SkinnedMeshComponent.h l. 1846 public (public: l. 1838)
GetPhysicsAsset() const SkinnedMeshComponent.cpp l. 2210 public
GetNumBones, GetBoneIndex, GetBoneName, GetBoneLocation SkinnedMeshComponent.h l. 1144, 1156, 1165, 2014 GetBoneLocation(FName, Space = WorldSpace) const
ProjectWorldLocationToScreen(FVector, FVector2D&, bool=false) const PlayerController.h l. 742 const : OK via const APlayerController*
GetViewportSize(int32&, int32&) const PlayerController.h l. 1191 const : OK
PlayerCameraManager->GetCameraLocation() const PlayerCameraManager.h l. 705 ; PlayerController.h l. 287 include Camera/PlayerCameraManager.h ajouté (l. 19)
TMap::FindRef(KeyInitType), Add(...), Remove(KeyInitType), CreateIterator, RemoveCurrent Containers\Map.h.inl l. 661, 323-326, 409, 979, 943/965 conformes ; précédent : TMap<TWeakObjectPtr<AActor>, ...> dans LPOutdoorRoomSubsystem.h l. 78 et Seen.Add(Person, ...) dans LPOutdoorRoomSubsystem.cpp l. 361
TActorIterator, FObjectPropertyBase, CastField EngineUtils.h inclus (l. 30) ; motif OccupyingFnt déjà compilé aux l. 526, 570-571, 972-973 OK
KINDA_SMALL_NUMBER UnrealMathUtility.h l. 67 et 131 (1.e-4f) float ; dépréciation désactivée par défaut ; déjà utilisé dans LPOutdoorRoomSubsystem.cpp

Conversions float / double (C4244) : Current, Scale, CullAlertDelay sont des float ; FMath::Max(float, float), FMath::Clamp(float, 1.f, 4.f) : types identiques. Extent[Axis], MinExtent, Needed : double. Needed ramené en float par static_cast explicite. Bounds.BoxExtent / Current : FVector / float accepté. Aucun C4244 attendu (estimé : seul le build COMMUN-8 le prouvera). Ambiguïté possible de surcharge sur MeasuredSeats.Add(Person, Seat) : même appel que le précédent Seen.Add(Person, ...) ; estimé sans risque.

Collisions de noms (unity) : membres BoundsDelay, CullAlertDelay, MeasuredSeats, FitPersonBounds : 24 occurrences dans 2 fichiers, aucun ailleurs dans Source/. Les constantes locales n'ont pas d'homonyme de portée fichier ni de macro dans Source/. Aucune variable locale ne masque un membre de la classe.

4. Diff lu en entier

  • Fichiers : 2 (LPDirectControlSubsystem.cpp, LPDirectControlSubsystem.h), 3 hunks cpp + 2 hunks h.
  • Lignes (1re version) : 128 ajoutées (123 + 5), 0 retirée. IMPL annonce 127 (écart E1).
  • Aucun fichier hors IMPL § 2 modifié par ce lot (instantané limité à ces deux fichiers). git status --short Source/ montre d'autres fichiers modifiés ou non suivis (LPDebugSubsystem.*, LPOutdoorRoomSubsystem.*, LifePlay.cpp, LPBonusRewardSubsystem.*, LPCameraModeSubsystem.*, LPSaveRelaunch.*) : autres lots, hors périmètre.

4b. Contrôle du delta (7448C8FB)

Demandé par l'orchestrateur après la 1re VAL : l'orchestrateur a corrigé E2 (S > 1 debout) et le transitoire d'apparition. Verdict de cette section : PASS-STATIC.

  1. MD5 (md5sum) : cpp 7448c8fb1091bd2a994cca4aa7f8b7a6, h 5f3492917b8202b267d8879e4613966b (inchangé). FileCheck.ps1 -Lot STG-B2q -OnlyChanged : même MD5, alertes=0. Établi.
  2. Contenu du delta (version corrigée contre l'instantané) : git diff --no-index --numstat = 130 0 ; 1re version = 123 + 0 ; delta = +7 lignes, 0 retirée. git diff --no-index -U0 : 3 hunks (-18,0 +19, -873,0 +875, -1062,0 +1065,128 : 121 + 7). Les lignes portant les termes du delta sont exactement :
    • l. 1068, phrase du commentaire d'en-tête : « … borne a [1, 4], au-dela d'un ecart tolere de 0,3 demi-etendue (debout : S = 1) ; applique seulement … » (ligne modifiée, même nombre de lignes) ;
    • l. 1078-1079 : commentaire et constexpr double Tolerance = 0.3; (+2) ;
    • l. 1130-1134 : if (Extent.GetMax() < 1.0) { // commentaire ; continue; } (+5) ;
    • l. 1140 : Needed = FMath::Max(Needed, (FMath::Max(0.0, Offset[Axis] - Tolerance * Half) + Half) / Half); (ligne modifiée). Total : 2 + 5 = 7 lignes ajoutées + 2 lignes modifiées, cohérent avec 130 − 123 = 7. Le fichier STG-B2q.diff actuel est identique au diff régénéré du cpp et du h (diff des deux flux, sortie vide). Limite : la version C9D1AC98… n'existe plus sur disque ; mon essai de la reconstituer en retirant ces lignes du fichier actuel (sed + md5sum) a donné 09493e3a… et non C9D1AC98… (reconstitution des deux lignes modifiées non fidèle à l'octet près, non élucidée). L'absence d'autre changement repose donc sur le compte (130 = 123 + 7, aucune ligne retirée) et sur la lecture des l. 1065-1145 contre le diff que j'ai lu en entier lors de la 1re VAL, pas sur une comparaison d'octets. Estimé fort, non prouvé à l'octet.
  3. Stabilité et types :
    • Needed = max(1, max sur les axes de (max(0, Offset − 0,3·Half) + Half) / Half) : toujours fonction de Extent (échelle 1) et de Offset, donc indépendante de BoundsScale courante ; au scan suivant Scale == Current : pas d'oscillation (raisonnement de 3.5 conservé). Établi par lecture.
    • Si tous les écarts sont ≤ 0,3 Half, le terme max(0, …) vaut 0 et chaque rapport vaut exactement 1 : S = 1. Établi. Marge de couverture : le bassin est couvert si S·Half ≥ écart ; la formule donne S·Half = écart + 0,7·Half, donc la marge autour du bassin passe de 1,0 à 0,7 demi-étendue (réduite, bassin toujours dans les bornes tant que S < 4). Risque faible, à lire dans COMMUN-8.
    • Types : FVector::GetMax() const renvoie T (Vector.h l. 516, TVector<double>) ; Extent.GetMax() < 1.0 double contre double ; FMath::Max(0.0, Offset[Axis] - Tolerance * Half) : 0.0, Offset[Axis] (double), Tolerance et Half (double) : FMath::Max<double> sans conversion ; résultat additionné à Half et divisé : double. Aucun C4244 attendu (estimé, non compilé).
    • Saut Extent.GetMax() < 1.0 : continue placé après le calcul de Pelvis et Current, avant le calcul de S, de la mesure T-cull et de l'alerte : une personne aux bornes encore nulles est ignorée entièrement pour ce balayage (0,5 s), y compris pour la mesure de meuble (refaite au balayage suivant, MeasuredSeats non mis à jour). Sans effet gênant. Toute personne dont l'étendue réelle serait inférieure à 1 cm serait ignorée en permanence : non réaliste pour un corps humain.
  4. Fins de ligne et ASCII : FileCheck : cpp CRLF 1724, LF 0, CR 0, pas de BOM ; h CRLF 101. Soit 1724 CR pour 1724 LF (1717 + 7). Grep [^\x00-\x7F] sur le cpp : 2 lignes seulement, l. 455 et 514, les mêmes qu'avant ; 0 non-ASCII ajouté (le « é » du commentaire a bien disparu).

Résultat : E2 est corrigé dans le code (le terme de tolérance rend S = 1 debout, sous la réserve de 0,3 demi-étendue mesurée sur les vraies bornes en COMMUN-8) ; le transitoire d'apparition est écarté par le saut. R1 est donc levé à la lecture ; R2 (rotation) et R3 (échelle externe) restent. E1 et E3 (documentation de l'IMPL) restent à la charge de l'orchestrateur ; l'IMPL § 2b / § 5 n'a pas été relu ici.

5. Verdict

PASS-STATIC pour la 1re version (7 constats ci-dessous) et PASS-STATIC pour le delta 7448C8FB… (section 4b), avec la limite d'octets nommée en 4b. Les MD5 concordent, le diff régénéré est identique au .diff, les quatre gardes de Big Boss sont tenues à la lecture, aucun effet sur collisions ni tracés, l'API relue en UE 5.8 est présente avec l'accès attendu. Non compilé, non exécuté.

Écarts :

  1. E1 : IMPL § 2 annonce 127 lignes ajoutées ; recompté 128 (1re version), 135 (130 + 5 du .h) pour la version corrigée.
  2. E2 : IMPL § 2 « debout S = 1 et rien ne change » inexact à la lettre dans la 1re version ; corrigé dans le code (4b).
  3. E3 (forme) : l'IMPL n'a pas la section « Écarts à la SPEC » du gabarit IMPL (gabarits.md : § 2), et sa liste « Fichiers à commiter » n'indique pas A / M / D. Les sections sont dans un autre ordre (instantané en premier).

Risques à surveiller en COMMUN-8 :

  • Coût de rendu et ombres : jusqu'à 4 fois plus grandes, les bornes des personnes assises ou couchées les font traiter plus souvent (rendu hors champ, passe d'ombre, requêtes d'occlusion) ; l'avertissement de PrimitiveComponent.h l. 966 le dit (« reduce performance and shadow quality »). Le streaming de textures utilise aussi le rayon des bornes (SkinnedMeshComponent.cpp l. 2200-2207) : des mips plus élevés possibles pour ces corps. Coût d'écriture borné : un balayage de tous les ACharacter par 0,5 s.
  • Personnes en scène de sexe : le bassin y est loin de la racine, donc S montera vers 4 pour les deux corps ; aucun conflit de code trouvé, mais l'essai doit couvrir au moins une scène.
  • Bassin loin pour une autre raison (animation de danse, ragdoll, téléportation, os 0 mal choisi sur un squelette sans hip ni pelvis) : S est quand même relevé jusqu'à 4. Au-delà de 3 demi-étendues d'écart, le plafond ne couvre plus le corps (alerte T-cull attendue avec dans=0).
  • Bruit de l'alerte T-cull : le filtre « non caché » n'écarte pas une personne légitimement occultée derrière un mur (bassin dans le viewport à moins de 15 m, WasRecentlyRendered faux). La limite d'1 ligne par seconde est tenue, mais le journal peut en contenir une par seconde dans ce cas.
  • Échelle externe sur le corps (R3 de 3.5) : va-et-vient possible si un Blueprint impose sa propre valeur.
  • Rotation (R2) : une personne qui tourne peut produire une ligne B2q-a par balayage.
  • Non établi : les dimensions réelles des bornes des assets bridget_gp et michael (non lues), donc la valeur réelle de la tolérance de 0,3 ; l'effet réel sur les disparitions (essai en jeu).

6. Points à confirmer par l'utilisateur

  • COMMUN-8 : bar, café fnt_new048 et lit sans disparition, lignes B2q-a / T-cull mesure présentes (IMPL § 4 points 1 et 2).
  • COMMUN-8 : coût (stat unit ou LPDebug hitch) (IMPL § 4 point 3).
  • COMMUN-8 : relever les lignes B2q-a des personnes debout : attendu aucune ligne (S = 1 sous la tolérance de 0,3) ; s'il y en a, la tolérance est trop basse.
  • Corriger dans l'IMPL le chiffre de lignes ajoutées (E1) et la forme (E3) : décision de l'orchestrateur ; non fait ici.
  • Fiche à part si une alerte T-cull apparaît avec dans=1 (IMPL § 4 point 4).

Fichiers à commiter : Docs/Migration/etat/ST/STG/STG-B2q-VAL.md (A). Aucun autre fichier écrit.

Tours : 24 / 30