ADRADR-0045 · Mirror est un onglet du Builder, pas un mode de la scene

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 :

  1. 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 est Main, qui lit le moteur MobX et le passe au chrome sous la forme d'un objet BuilderControls.
  2. La page tierce n'entre jamais dans un cadre Onlook. Quand l'onglet Mirror est ouvert, la region du stage montre MirrorStage : le meme cadre sandbox="allow-scripts" (jamais allow-same-origin) servi par la meme route sous la meme CSP d'en-tete, et l'apercu compile dans un cadre sandbox="". Le canevas Onlook reste monte dessous, cache et inert.

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

OptionPourquoi non
Garder ?mode=mirror et ajouter un lien vers le BuilderDeux 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 OnlookLes 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'ongletLe theme choisi pouvait ne pas etre celui du Builder : la section « installee » n'apparaissait pas dans la Bibliotheque qu'on regardait.

Conséquences

  • ?mode=mirror n'est plus un mode. parseWorkspaceMode le lit comme builder, et le Builder ouvre alors son onglet Mirror (builderToolFromModeParam). Aucune redirection : zero utilisateur.
  • Le chat n'a plus de cadrage mirror propre : le fragment builder de handler-prompt-fragments.ts decrit 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.