LifePlay-Revival/Docs/Migration/22_Eval_Agents_Sandbox.md
edujiro5972 04b053554f Sandbox addon : brancher le jeu sur LifePlay-Sandbox (plugin LPSandbox).
Charge le plugin via AdditionalPluginDirectories, conserve ShowCouple et les commandlets anim côté jeu, et documente les lots S0–S8 (CHG-212 à CHG-220).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-06 21:10:53 +02:00

18 KiB
Raw Permalink Blame History

22. Évaluation du mode multi-agents + multi-modèles (migration sandbox → addon, S0–S8)

  • Date : 2026-10-06 | Fiche : S8-T1 | Rôle : A-DOC+Orch | Entrée journal : CHG-220
  • Modèle prévu : claude-opus-5-5-medium (M4) | Modèle utilisé : Claude Opus 5.5 (déclaré par l'environnement)
  • Sources : etat/sandbox/S0/ à S7/ (29 rapports *-CART, *-SPEC, *-IMPL*, *-INT*, *-VAL), 21_Sandbox_Addon.md, journal CHG-212 à CHG-219, état git des deux dépôts au 2026-10-06 21:00.
  • Validation de clôture : etat/sandbox/S8/S8-VAL.md (smoke Pair par le .bat, PASS).

Biais à garder en tête : ce bilan est écrit par le rôle orchestrateur, qui juge en partie sa propre organisation. Les faits (verdicts, horodatages, état git) sont vérifiables dans les fiches citées ; les appréciations (sur/sous-classement, coût) sont des jugements.


1. Résumé exécutif

Fait. Le code sandbox (Pair, Interaction, Mesure, ~7,5 k LOC) est sorti du module jeu vers le plugin LPSandbox du dépôt séparé LifePlay-Sandbox, chargé par le jeu via AdditionalPluginDirectories (clone sibling, pin manuel). La chaîne de mesure est un module à part (LPAnimMeasure), la géométrie du couple n'existe plus qu'en une copie (LPCoupleSim, −336 lignes dupliquées), le plugin ne connaît pas le jeu à la compilation (0 include / LIFEPLAY_API) et LPSandbox est exclu du Shipping. Huit validations PASS, aucune régression observée : la boîte du couple AgMakeout est identique au millième de cm entre S5, S7 et S8. Aucun retour arrière n'a été nécessaire. Le tout a été fait en une journée (S1 → S7 en ~3 h d'après les horodatages des fiches, 18:18 → 20:54).

Limites.

  • Rien n'est commité côté jeu : LifePlay.uproject, Config/LPSandbox.ini, 21, etat/sandbox/**, et LPShowCoupleSubsystem.* (non suivis). Un clone du jeu aujourd'hui ne monte pas l'addon ; le pin n'a de valeur que sur ce poste.
  • Show en jeu jamais exécuté : le partage LPCoupleSim côté jeu n'est prouvé que par compilation (PASS-STATIC, S5) ; l'alignement du plancher −90 / −88 n'est pas décidé.
  • Shipping non compilé (plan UBT seulement), commandlets anim (Catalog, Checks, Twist) toujours dans LifePlayEditorTools, BuildMod -Target sandbox non rejoué.
  • Le build du jeu dépend du clone sibling (LifePlay.Build.cs → LPAnimMeasure) malgré Optional: true.
  • Preuves par journal uniquement : aucun contrôle visuel, modes Interaction et Mesure non exercés après S2.

2. Lots S0–S8

« Rollback » = retour arrière exécuté. Tous les lots ont un retour arrière documenté dans le journal ; celui des lots S1, S2 et S5 côté jeu porte sur des fichiers non suivis par git, donc sans instantané : il est manuel et non testé.

Lot Tenu Coupé / reporté Rollback Verdict VAL
S0 .gitignore /Debug/, 3 bats suivis, inventaire gelé — aucun PASS (S0-VAL)
S1 Config/LPSandbox.ini (19 clés, 6 sections), FLPSandboxConfig, 0 littéral oublié compilation et runtime (DLL plus ancienne que les sources) ; test d'override WorldFile laissé « manuel », jamais fait aucun PASS statique (S1-VAL, runtime BLOCKED)
S2 module LPAnimMeasure (8 fichiers, 6 exports), graphe acyclique, runtime Mesure (269 lignes LogLPAnimMeasure) commandlets non relancés (repris en S6 pour LPAnimEval seul) ; mise à jour de S1-CART demandée, jamais faite aucun PASS (S2-VAL)
S3 dépôt addon, transfert, purge du jeu, AdditionalPluginDirectories, pin, build 91/91 submodule abandonné ; addon mince avec réserve (plugin StreetMap absent, 2 458 erreurs BP sans effet) partiel : la junction Plugins\LPSandbox créée en S3-T3 a été retirée en S3-T4 PASS avec réserve (S3-VAL)
S4 LPPairSandbox.cpp 4 274 → 7 unités (max 837 LOC), GameMode Interaction legacy retiré (~543 LOC) commandlet LPPairCollisionTest cité dans l'objet du lot : non traité ; mode Interaction non exercé aucun PASS (S4-VAL)
S5 LPCoupleSim partagé (3 niveaux d'API), 0 erreur / 0 avertissement, parité de la boîte Show en jeu, décision du plancher, tests unitaires du niveau pur, mise sous git de LPShowCoupleSubsystem aucun PASS runtime Pair / PASS-STATIC Show (S5-VAL)
S6 doc 20 / 09 alignées, LPAnimEval court (code 0, 1,3 s) bat Mesure non rejoué (renvoi à S2-VAL) aucun PASS (S6-VAL)
S7 contrat d'isolation (0 écart), TargetConfigurationDenyList: Shipping, Optional compilation Shipping ; déplacement des commandlets ; push (fait après coup, constaté en S8) aucun PASS (S7-VAL)
S8 ce bilan ; smoke Pair par le .bat réel, parité de la boîte BuildMod -Target, bout en bout Show aucun PASS (S8-VAL)

3. Qualité des consignes et des handoffs

Ce qui a marché.

  • Chaque VAL cite ses références, le pin, le journal copié et une section « Limites » ; les verdicts nuancés (PASS statique, PASS-STATIC, BLOCKED-RUNTIME, « avec réserve ») ont empêché de sur-vendre un lot.
  • L'enchaînement CART → IMPL-H a payé : S3-T2, S4-T2 et S5-T2 ont compilé du premier coup, sans include à corriger (hors un défaut IWYU révélé par l'unity en S2).
  • Les écarts à la fiche sont déclarés au lieu d'être cachés : S4-T2 (7 unités au lieu de 5, justifié par la taille), S5-T2 (5 écarts de comportement listés exhaustivement), S7-T2 (options rejetées avec motif).

Ambiguïtés de consigne observées.

Où Ambiguïté Effet
S1-T2 / S1-T4 IMPL-L sans consigne de compiler, VAL sans droit de compiler personne n'a compilé S1 ; le runtime n'a été prouvé qu'indirectement par S2
S3-T3 / S3-T4 plan « submodule en T4 » alors que la structure de l'addon (plugin imbriqué) le rendait impossible junction temporaire créée puis retirée, décision d'architecture prise en INT
S3-T1, S7-T2 « push non autorisé » sans dire qui pousse ni quand pin pointant un commit local entre S7-T2 et la fin de S7
S4 objet du lot dans 21 (commandlet LPPairCollisionTest) ≠ fiches exécutées item tombé sans trace de décision
S7 / S8 libellés de 21 (S7 « commandlets », S8 « épuration, BuildMod -Target ») ≠ fiches reçues S7-VAL doit signaler un « ancien libellé non traité » ; S8 ici = bilan, pas épuration
21 § Lots ligne S1 toujours « placeholder ci-dessus » doc de référence partiellement périmée

Reprises. S1 runtime → couvert par S2 ; commandlets S2 → LPAnimEval en S6 (les autres jamais) ; junction S3-T3 → retirée S3-T4 ; bat équivalent S7 → bat réel S8 ; push S7 → fait (constaté S8). Orphelins (demandés, jamais repris) : mise à jour S1-CART, test d'override WorldFile, Show en jeu, commit côté jeu.

Forme. Les fiches S3-INT et S7 sont écrites sans accents et sans en-tête « Modèle », les autres avec : le gabarit de fiche n'était pas imposé.


4. Adéquation modèle ↔ complexité

Paliers d'après les fiches : M0 = composer-2.5-fast, M2 = claude-sonnet-5-5-high, M3 = claude-opus-5-thinking-high, M4 = claude-opus-5-5-medium ; gemini-3.8-flash-high n'a pas de palier noté (M1 supposé). « Réel » = champ « Modèle utilisé » de la fiche ; sinon « non tracé dans VAL », et l'évaluation porte sur le prévu. 12 fiches sur 28 tracent le modèle réel (11 sur 27 avant S8).

Fiche Rôle Modèle prévu Réel Résultat Classement
S0-T1 CART gemini-3.8-flash-high idem inventaire exact adéquat
S0-T2 IMPL (.gitignore) non tracé non tracé dans VAL 1 ligne, PASS —
S0-T3 VAL composer-2.5-fast (M0) idem PASS, preuve check-ignore adéquat
S1-T1 ARCH (SPEC) non tracé non tracé dans VAL contrat solide, réutilisé jusqu'en S7 —
S1-T2 IMPL-L non tracé non tracé dans VAL correct mais non compilé — (défaut de consigne, pas de modèle)
S1-T3 CART (audit grep) gemini-3.8-flash-high idem 0 oubli, confirmé par VAL adéquat
S1-T4 VAL sonnet (M2) idem bon diagnostic (DLL > sources) mais checklist statique légèrement sur-classé (M0 a fait des VAL plus lourdes en S4/S6)
S2-T1 CART sonnet (M2) non tracé dans VAL cartographie fiable adéquat
S2-T2 IMPL-H opus thinking (M3) non tracé dans VAL compilé, 1 fix IWYU sur-classé (déplacement + exports, M2 suffisait)
S2-T4 VAL sonnet (M2) idem PASS runtime Mesure adéquat
S3-T1 INT (scaffold) sonnet (M2) non tracé dans VAL scaffold correct, push gelé adéquat
S3-T2 IMPL-H opus thinking (M3) non tracé dans VAL transfert inter-dépôts compilé du premier coup adéquat
S3-T3 IMPL-L (purge jeu) composer (M0) composer (champ unique) purge correcte, sans build, junction contraire à la décision finale sous-classé (opération destructive inter-dépôts)
S3-T4 INT non tracé non tracé dans VAL abandon du submodule, build 91/91, premier push —
S3-T5 VAL sonnet (M2) idem deux runtimes, cause StreetMap identifiée adéquat
S4-T1 CART non tracé non tracé dans VAL découpage exploitable —
S4-T2 IMPL-H opus thinking (M3) non tracé dans VAL 4 274 LOC découpés, 0 erreur adéquat (risque élevé, aucune régression)
S4-T3 IMPL (retrait GM) non tracé non tracé dans VAL suppression propre —
S4-T4a VAL composer (M0) idem build + runtime, PASS adéquat
S5-T1 CART sonnet (M2) non tracé dans VAL 28 Ko d'écarts précis, base de S5-T2 adéquat
S5-T2 IMPL-H opus thinking (M3) idem refonte de comportement, 0 avertissement, écarts listés adéquat
S5-T3 VAL sonnet (M2) idem parité argumentée, PASS-STATIC honnête adéquat
S6-T1..T3 VAL (+DOC) composer (M0) idem PASS, commandlet court adéquat
S7-T1 ARCH (SPEC) non tracé non tracé dans VAL checklist C1–C5 réutilisable —
S7-T2 IMPL-L non tracé non tracé dans VAL uplugin / uproject corrects —
S7-T3 CART non tracé non tracé dans VAL 0 écart —
S7-T4 VAL+DOC non tracé non tracé dans VAL PASS, limites claires —
S8-T1/T2 DOC+Orch, VAL opus 5.5 medium (M4) Claude Opus 5.5 (effort non vérifiable) ce document, smoke PASS adéquat pour la synthèse ; M0 suffirait pour le smoke seul

Lecture. Aucun échec imputable au modèle. Les deux défauts notables viennent de la consigne (S1 sans build) et d'un palier trop bas pour une opération destructive (S3-T3). Le sur-classement (S2-T2, S1-T4) n'a rien cassé, il coûte seulement. M0 s'est montré suffisant pour toutes les VAL à checklist + smoke.


5. Erreurs d'affectation de rôle

  1. VAL qui écrit la doc qu'elle valide : S2-T4b (« A-VAL puis prep DOC »), S6 (VAL a fait la mise à jour de 20 / 09 puis l'a validée), S7-T4 (« VAL+DOC », coche elle-même 21 § Acceptation). Pas d'erreur constatée, mais la séparation des rôles perd son intérêt.
  2. Décision d'architecture prise par INT : l'abandon du submodule (S3-T4) relevait d'A-ARCH ; il a été pris en intégration, sans SPEC préalable, et documenté a posteriori dans 21.
  3. Compilation sans propriétaire en S1 : ni IMPL-L ni VAL n'avaient le droit de compiler ; le trou a été comblé par chance au lot suivant.
  4. Purge destructive confiée à IMPL-L / M0 (S3-T3) : suppression de fichiers du jeu et modification du .uproject, sans build dans la fiche.
  5. Orchestrateur évaluateur (S8-T1) : le rôle qui a découpé les lots en fait le bilan ; voir le biais signalé en tête.

6. Friction git

  • Submodule abandonné → AdditionalPluginDirectories. Le plan initial (S3-T3 : « jonctions temporaires, avant submodule T4 ») supposait un submodule. L'addon étant un uproject qui contient Plugins/LPSandbox/, un submodule monté sur Plugins/LPSandbox du jeu aurait donné Plugins/LPSandbox/Plugins/LPSandbox/ (non scanné), et un submodule External/ aurait doublé le clone sibling. S3-T4 a retiré la junction et retenu deux clones voisins + AdditionalPluginDirectories + pin consigné à la main (S3-INT.md, README). Coût : une junction créée puis défaite, et un pin que rien n'automatise (4 bumps à la main : 4de1f0b, f810264, c1fdd29, f09c42e).
  • Push. S3-T1 a créé le remote sans pousser (consigne) ; premier push en S3-T4. S7-T2 a laissé f09c42e local et le pin pointait un commit absent du remote jusqu'à la fin de S7. Constat S8 : origin/main = dae6206 (contient f09c42e), l'addon est à jour sur GitHub. Côté jeu, en revanche, aucun commit depuis le début du lot : le dernier commit touchant LifePlay.uproject est antérieur (b11f7e8) ; 21, etat/sandbox/**, Config/LPSandbox.ini sont non suivis, LifePlay.uproject et les deux Build.cs modifiés non commités. Le pin documenté n'est donc consommable par personne d'autre.
  • Identité git. Les deux premiers commits de l'addon (4938abb S3-T1, d18243e S3-T2) portent LifePlay <lifeplay@localhost> : identité non configurée dans le nouveau dépôt. Les suivants portent edujiro5972 <edujiro5972@users.noreply.github.com>, alors que le dépôt jeu utilise 336072401+edujiro5972@users.noreply.github.com. Trois identités pour un seul auteur ; l'historique publié n'a pas été réécrit (il faudrait un push forcé).

7. Coût / bénéfice vs mono-agent mono-modèle

Coût mesurable.

  • 27 fiches (S0–S7) et 29 rapports, ~200 Ko de Markdown sous etat/sandbox/ (S5 seul : 52 Ko) pour un changement net de quelques milliers de lignes déplacées et −336 lignes dupliquées.
  • Chaque agent relit 21 et les fiches amont : le contexte est rechargé ~28 fois.
  • Trous de transmission que la continuité d'un seul agent aurait évités : S1 non compilé, junction S3 défaite, S1-CART jamais mis à jour, commit jeu jamais fait.
  • Traçabilité incomplète : 11 fiches sur 27 (S0–S7) indiquent le modèle réel.

Bénéfice mesurable.

  • 0 build cassé à l'étape IMPL-H, 0 retour arrière, 0 régression (parité de la boîte S5 = S7 = S8).
  • Des VAL indépendantes qui ont refusé de sur-vendre : BLOCKED-RUNTIME en S1, PASS-STATIC en S5, réserve StreetMap en S3. Un agent unique valide plus volontiers son propre travail.
  • Les paliers bas (M0, flash) ont porté 5 fiches de VAL / CART sans défaut (S0-T1, S0-T3, S1-T3, S4-T4a, S6) ; un mono-modèle haut de gamme aurait payé ces fiches au prix fort.

Verdict. Pour une migration à risque (déplacement inter-dépôts, refonte de géométrie partagée), le surcoût documentaire est justifié par l'absence de régression et la qualité des preuves. Pour des lots simples (S0, S6, S7-T2) le découpage en 3–4 rôles est du surcoût pur : un seul agent M0/M2 avec une VAL séparée suffisait.


8. Décision

GO conditionnel pour réutiliser le mode multi-agents + multi-modèles sur les prochaines migrations de même nature (extraction de code, refonte partagée jeu ↔ addon). Les trois conditions sont les recommandations ci-dessous ; sans elles, les mêmes trous (build sans propriétaire, git non clos, traçabilité partielle) se reproduiront. NO-GO pour les lots simples (≤ 1 fichier de config / doc, pas de C++) : un agent unique + une VAL M0.


9. Recommandations (3)

  1. Politique modèles, tracée et vérifiée. M0 (composer-2.5-fast) par défaut pour les VAL à checklist + smoke et les IMPL-L mécaniques non destructives ; gemini-3.8-flash-high pour les CART de type grep ; M2 (claude-sonnet-5-5-high) pour les CART analytiques, les VAL qui doivent juger une parité ou un PASS-STATIC, et toute opération destructive ou inter-dépôts (suppression de sources, .uproject) ; M3 (claude-opus-5-thinking-high) réservé aux IMPL-H qui changent un comportement (type S5-T2), pas aux déplacements (type S2-T2 → M2) ; M4 pour la synthèse transverse. Chaque fiche porte « Modèle prévu | utilisé » ; une VAL sans ce champ dans les fiches amont est en FAIL-TRACE.
  2. Clôture git par lot, avec un propriétaire. Toute fiche IMPL finit par un build vert (la compilation appartient à IMPL, pas à VAL). Le lot ne passe au suivant qu'après un « gate » A-INT : commit + push de l'addon, bump du pin, commit du jeu (fichiers non suivis inclus), identité git vérifiée (git config user.email identique dans les deux dépôts). Prochaine action concrète : commiter côté jeu LifePlay.uproject, Config/LPSandbox.ini, les Build.cs, LPShowCoupleSubsystem.*, 21, 22 et etat/sandbox/.
  3. Séparer VAL et DOC, et tenir un registre des reports. La VAL est en lecture seule sur les docs d'acceptation ; un rôle DOC distinct coche 21. Les décisions d'architecture passent par une SPEC avant l'INT. Chaque « reste à faire » d'une fiche entre dans une liste unique de 21 avec un lot propriétaire, pour qu'aucun report ne reste orphelin (aujourd'hui : S1-CART, override WorldFile, Show en jeu, plancher, commandlets, Shipping compilé).