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>
18 KiB
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, journalCHG-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/**, etLPShowCoupleSubsystem.*(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
LPCoupleSimcô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 dansLifePlayEditorTools,BuildMod -Target sandboxnon 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
- VAL qui écrit la doc qu'elle valide : S2-T4b (« A-VAL puis prep DOC »), S6 (VAL a fait la mise à jour de
20/09puis l'a validée), S7-T4 (« VAL+DOC », coche elle-même21§ Acceptation). Pas d'erreur constatée, mais la séparation des rôles perd son intérêt. - 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. - 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.
- Purge destructive confiée à IMPL-L / M0 (S3-T3) : suppression de fichiers du jeu et modification du
.uproject, sans build dans la fiche. - 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 unuprojectqui contientPlugins/LPSandbox/, un submodule monté surPlugins/LPSandboxdu jeu aurait donnéPlugins/LPSandbox/Plugins/LPSandbox/(non scanné), et un submoduleExternal/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é
f09c42elocal et le pin pointait un commit absent du remote jusqu'à la fin de S7. Constat S8 :origin/main=dae6206(contientf09c42e), l'addon est à jour sur GitHub. Côté jeu, en revanche, aucun commit depuis le début du lot : le dernier commit touchantLifePlay.uprojectest antérieur (b11f7e8) ;21,etat/sandbox/**,Config/LPSandbox.inisont non suivis,LifePlay.uprojectet les deuxBuild.csmodifiés non commités. Le pin documenté n'est donc consommable par personne d'autre. - Identité git. Les deux premiers commits de l'addon (
4938abbS3-T1,d18243eS3-T2) portentLifePlay <lifeplay@localhost>: identité non configurée dans le nouveau dépôt. Les suivants portentedujiro5972 <edujiro5972@users.noreply.github.com>, alors que le dépôt jeu utilise336072401+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
21et 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-CARTjamais 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-RUNTIMEen S1,PASS-STATICen S5, réserveStreetMapen 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)
- 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-highpour 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 enFAIL-TRACE. - 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.emailidentique dans les deux dépôts). Prochaine action concrète : commiter côté jeuLifePlay.uproject,Config/LPSandbox.ini, lesBuild.cs,LPShowCoupleSubsystem.*,21,22etetat/sandbox/. - 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 de21avec un lot propriétaire, pour qu'aucun report ne reste orphelin (aujourd'hui :S1-CART, overrideWorldFile, Show en jeu, plancher, commandlets, Shipping compilé).