ADR-0045 — Mirror est un onglet du Builder, pas un mode de la scene
L'ADR 0044 a fait de Mirror un sixieme WorkspaceMode (?mode=mirror), une cinquieme etape du stepper, avec sa propre ligne d'en-tete de 56 px, sa bande d'onglets Source / Resultat et sa colonne d'options a droite. Il…
Statut
Accepté · 2026-09-26
Remplace : ADR-0044 (partiellement : la ligne « sixieme mode de la scene » et l'alternative « un panneau dans le Builder » ecartee)
Piliers : ai-platform, design-system
Contexte
L'ADR 0044 a fait de Mirror un sixieme WorkspaceMode (?mode=mirror),
une cinquieme etape du stepper, avec sa propre ligne d'en-tete de 56 px,
sa bande d'onglets Source / Resultat et sa colonne d'options a droite. Il
ecartait « un panneau dans le Builder » pour deux raisons : le Builder
est du code vendore // @ts-nocheck epingle par des tests, et ses cadres
rendent des documents de theme, pas une page tierce opaque.
Le jour meme, la decision s'est inversee, et la raison est dans le produit : la section que Mirror construit s'installe dans un theme, et c'est le Builder qui montre ce theme. Deux etapes voisines du stepper pour une seule tache (trouver une section, puis la travailler) faisaient deux portes pour une piece. Il a demande en meme temps de nettoyer le chrome du Builder (« un bordel ») : son en-tete de 56 px repetait « Builder » sous le stepper qui le disait deja.
Les deux objections de 0044 tiennent toujours, mais elles visaient une IMPLEMENTATION (loger Mirror dans le code vendore, ou rendre la page tierce dans un cadre Onlook), pas un EMPLACEMENT.
Décision
Mirror est un onglet du panneau lateral du Builder et une porte de sa barre d'outils flottante (« Importer une section »). La section compilee s'installe dans le theme que le Builder edite, puis s'ouvre dans l'onglet Sections et sur le canevas.
Ce qui rend les deux objections de 0044 caduques :
- Le chrome n'est plus vendore. La barre d'outils, le panneau et
Mirror vivent dans
src/features/ai/onlook/chrome/, en TypeScript strict, lintes et traduits. Le seul fichier vendore touche estMain, qui lit le moteur MobX et le passe au chrome sous la forme d'un objetBuilderControls. - La page tierce n'entre jamais dans un cadre Onlook. Quand l'onglet
Mirror est ouvert, la region du stage montre
MirrorStage: le meme cadresandbox="allow-scripts"(jamaisallow-same-origin) servi par la meme route sous la meme CSP d'en-tete, et l'apercu compile dans un cadresandbox="". Le canevas Onlook reste monte dessous, cache etinert.
La cible d'installation n'est plus un choix parmi les brouillons : c'est
le theme que builder-library resout (pickBuilderTheme, la meme regle
que builder-frame), renvoye au client avec son nom et son role. Un
theme live n'est pas propose par le panneau et reste refuse en 409 par
decideThemeWrite sur la route : la regle 5 de 0044 ne bouge pas.
Tout le reste de 0044 (isolation par l'en-tete, lecture sous garde,
protocole par identite, rien du tiers ne sort, plan payant) est inchange,
et le moteur (src/features/ai/mirror/**) comme les deux routes n'ont
pas bouge.
Alternatives écartées
| Option | Pourquoi non |
|---|---|
Garder ?mode=mirror et ajouter un lien vers le Builder | Deux etapes pour une tache ; la section installee restait invisible tant qu'on ne changeait pas de mode, et le choix du theme cible pouvait differer du theme affiche par le Builder. |
| Rendre la page tierce dans un cadre Onlook | Les cadres Onlook chargent le script de preload d'Onlook et rendent nos documents ; y mettre du balisage tiers annulerait l'isolation par origine opaque de 0044. |
Ecrire le panneau Mirror dans upstream/ | Code @ts-nocheck, hors lint, catalogue anglais d'Onlook : exactement l'objection de 0044. |
| Garder le selecteur de brouillons dans l'onglet | Le theme choisi pouvait ne pas etre celui du Builder : la section « installee » n'apparaissait pas dans la Bibliotheque qu'on regardait. |
Conséquences
?mode=mirrorn'est plus un mode.parseWorkspaceModele lit commebuilder, et le Builder ouvre alors son onglet Mirror (builderToolFromModeParam). Aucune redirection : zero utilisateur.- Le chat n'a plus de cadrage
mirrorpropre : le fragmentbuilderdehandler-prompt-fragments.tsdecrit l'editeur ET son onglet Mirror. Le signal « Mirror est ouvert » n'atteint donc pas le prompt ; s'il manque, c'est un champ a ajouter au contexte, pas un mode a recreer. - Le Builder installe ce qu'il edite : si la boutique n'a qu'un theme live, le Builder l'affiche, et Mirror dit qu'il faut d'abord une copie.
- Signal pour revisiter : un marchand qui veut installer une section Mirror dans un autre theme que celui du Builder. La reponse serait que le Builder suive le theme choisi dans la Preview (backlog), pas un second selecteur.
Comment c'est appliqué
src/test/mirror-is-a-builder-tab.test.ts (pas de mode, pas d'etape,
l'onglet et la porte existent, les deux sandbox, la cible d'installation
et la regle de choix partagee), src/test/preview-toolbar-modes.test.ts
(pas d'en-tete, une barre flottante sur patterns/workbench-toolbar),
src/features/ai/onlook/builder-library.test.ts (pickBuilderTheme,
libraryTheme). La carte du chrome : docs/audits/2026-09-26-builder-chrome.md.