From b18e66c28df7253730abf7a366fb8492a6453cab Mon Sep 17 00:00:00 2001 From: th Date: Sun, 7 Jun 2026 13:24:34 +0200 Subject: [PATCH] Add export environment plan --- .../Screenshot from 2026-06-07 10-34-26.png | Bin 0 -> 41890 bytes dev_docs/09_export-environment-copy-plan.md | 293 ++++++++++++++++++ package.json | 2 +- src/version.ts | 2 +- 4 files changed, 295 insertions(+), 2 deletions(-) create mode 100644 animatr_reference/Screenshot from 2026-06-07 10-34-26.png create mode 100644 dev_docs/09_export-environment-copy-plan.md diff --git a/animatr_reference/Screenshot from 2026-06-07 10-34-26.png b/animatr_reference/Screenshot from 2026-06-07 10-34-26.png new file mode 100644 index 0000000000000000000000000000000000000000..d6b169b16a2745ada8325647113ae690810fe9b3 GIT binary patch literal 41890 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

mWP7{0G&78hGEc}9+Ry1k!2i~$de8fDgkWf_F< zTz5}PYiHKG9?j*D1@p_{R!D(fH^^vBqF_;0E?Li(S6AHw`X2k5l#Ow4iQL?y#`RazxDoMNlwXu)nq>3AcZ zxAEpFq(^P{OOkym1k$Z(-kghvU)W3kWZ+%$F|kdx^Bb$97sljbA^e~o>{?AOwu}4a z6@;Zo{Vu)`KtZ~eM@ zII)<0y|8dVepiP94#_TDu^&Q0n32zoiSH;RHjjp!tBc6-c8;8hyZ@v=*yx|MQ2YB< z6`LBqZa?Z;t6o~I4jkx9Zr`?-bLO$xcuRw8VB<>^6J5Z>9BVrHU{`Ttq`{Pb98c+B z>k=4n+$dF~Z22;w!_FM7WsHi*#gdNP5=5)&;dl_luvq&Bb+_}q=c6MQr0{|e4S^R1 ziBGOhwIjPcN`8K&i4x2A{!d3hiSO%yIt>ZEM{dF}cUO`FXp41CN>R~bZyAR;@Su%4 z)5wUV*?CRL8q~wFu`mb085WpMh!&C=_xx0@)%Go&DT3xj86Jf=_BA-Fn2Z#pdgQ*c zdLB(GKm#FC$gkGcvZ(&v3jNJz&p9|o$1p0am-y|d?08%BK69jHuQAviSO7ew1nTa+ zl{^rtN20$=5esQmGBSj)l4h7cl-^C3z51eduX|0juNyVa3C1wrdPTQaFK2ZV{Wy?YRU9??7-Rq`J5`I|FAeL&eHo z!oa`)!k5E9-Yy3R@pz_oaD|&rd|oq8M-L`DJ45O0=+I}GX$x%u(6TtsAm)oma^wr< zmO9O!Ds&(cN*segQ%>7e`#c4*ATG6zjv?D{Z*M%lo*#Yl;o*#Q-g32a**-xhT#MUIiZb>zhTJe-3>_pnl_o|?M+dX6idubN}5wx zcpt%~MR(bJlpO!);@P>t)aQFEjB;|$C@A%yV*nNqRs0j5>>lge@INk_e|V^X;R1-v+1WYp;S1nT;rOw;wN+uig{eNZBoi}T zFSNL_Gc!Az_UK{=hg?`%LSmyMqTl2C9i>A3)&v1wb~d&w#hv3APGK@(LVSEUsQR^P z=P2QPkBJ!tcpWEWK0dOG9-+MNi%sFm%E);0j_UWQsQ&2-lFk4iBHq5G0}IeYjOLM% zPlSa0ixCf6mclhnOaP5NY$mB`*JcWOv%9IGB+}->7R9Y4_$!=I3l2&CetyK<8IGHe z8aqv3K4DIaWoqo}%TMHg$$d0GQO1lg==VIz(31fv`g?{_6>f3y5Ao52c9&_vxKN z;ul&kSwf=j+U}77nXt4$a#mKyZx@yEk+C>Y!6tz+6-F(=mqtdnqBv3Yu;fqadPWpmn}@b&f0%DSDWV63T`fg{MC zYyR33a{q*rrSlX9Mn({b(fc+AD(MBjPB#tjeY`%(&3>w0p@U?9( zM)j!(Xu?Ylv|--(!@$JJiH+AJP^ImjI$P`E4F--CfW0N#Z6Iq$S|UY~DzvfjwSbob z40zxnk&Y7p-8gtvv$GCAeBeXAetYGwda84$!!}U$aEHBM%`AP$EK8TZNJ*UA`A2>B zrAIc2;6c>2YuAWhSf)XW9W3=qR~j0B8;^5Z*^!K&XF=x8<%;q**gC_+SZQHqp3SiV ztpYOpL&#belg;?<3(|2ty)cMF`dv*#f8TcV_P2Ev4RNlucN$U0@Pmdr zB`@Se;2uUrbpSaDXfZ*F?y!x4#vS_MR16Qp8ygGDesv^hdAT|8EwEXN`Pu{_t%?0h za0rx>l`SqT{M`6>`Pp*--wch6V8I1h3y1liR6jp&92^{w*dx#rFyE~n4|W7aMd7pH zsL04xZKlqCY8KWj?%gFRj$zmMBr&ff9#_UNva%+{&NJ9=eiaJLfD_u&d%{*$K-~~> zSSyT2;^16;5S1{nV$grN&Vu!VxK=orEHoTKL(@^k5y(`w!^Xx&!0^>8V#Pw(+2)Ih zz|U6-{I2gtS6*HYE)p`~$nbD!?uqhpr6*6cGH!{fejOVl9?B2L+iL7$o1!Kg)}?_vF+vFnGNN4mT-T*+HIx{TrwVH8nNDz`}C%5&TMH z?3qPcN=nPHNg(lHF{^Jw+nac~P6S-X;{{=tAM*e!l$<hXj7o?v4)7(Q4+|w+8FL zu)xUZdc5miSJ%uQus&G@i5M=mAF&{CJS;3ph6;Y4roe;Cb;{z&cQR5I>m?vlceX7( zJn$gi30|lSfpYWd8OXd(iYR-N)C;?=pdUUX7_pM2Ayy#!OtFL;4+RCq?c&!{(eJ}U za#J;KW^m;KiYFl^1~TQ)R;8!+7{4@rZ=dV!4TFvF%1f$HwHo3~$(B*$q2)mhfD$ds z;54uzoi2m@cdDu`#=zJZ((=A1BxpdDgi94L%kQWMAb>^kMwJzXqSdi+@!L0VC_QRR z9a+l@zC*+#YcE9e!O?7)_clM=p52`57c3zfPJ5K+=O5t8Cb0L29q{|C7PBi3;%qbw zj2D)F@eIQsB*Z$E%@aNG_eHP$)!yiGxn{uytNr(NM`N12#s*M4u^#(Xv$2zHNj8k+ zV@9#<|1e5>ED(Rbs&`N5f|n8o!wkKz0Vk!o5V3g44PB3ghifq@mX~vR@~23)IG*U< z4gDM;#>OfN8L8KU^%x31{s+C3{oynl+8`W1{0EKnf22Kn3^?R6W!Lc5AT;%o7fKsk zBfdSLXaeVNtWs%A(9k zQTf>^TJ)mV|9?_XLXCgX=RSHFKj}M4ZL-k{^#_o_Cq^E1$s3OKr{3jXd_CN6oh8{4 z71dZ3^Z6N>aNArqa8dGM-UI}sEWdWGeB+B-NZqGJmr4jHinnhyr0}V+g-}{Y&k8o(=P!FVh4QZ36Uk5m~RvjSOmT zvn`Xtf+zwpl#kE|qB=DSUUYLl-o5(E`gA+E74Fu^SiAcu(Ms8gbWFP1yRYaQD`&-{ z>gd(07uUEGRt)RCM#;%0jBC&g4zg9s5~EmQdIXFH{9MJJ8XB3{_e`ZPa@1=aH~&-< zFrTK0SJ=8>6A{7mm6HyUl*gF7r!V`*{wMlr*akd_`2{y@6ZGDa8%d>aZs{)GyzaUY z-l!=a!{IPhjRFoaxQ|y8b)}^8N)856dBD3>WWQDS`E!!Q@2klD`}ZriMeqm5>O61p zoNj_^6b=titD>*(e6qF)lHZp`c;q2R^_WwzP|?>+#70Eu7`z~R^vkU|fL`70tTQ@# zq6>p8ti7;_^50aCbb3~1<_nu;1rrnh6v+h1`*?Uw4Jzqb_ZcF@+%6O`Fp|K~{Mz#o z8ynE^`n4Y=>E!7j&%{SXIlXD=E6|hRu{Q^bgCV_eX>~N@UCQBe&WeZ##ev~l^s2{I zX=%UewPvDU)J7&XHwmiOxZ3=SjzaVe47yrdeSOP&`uZjs=e9S)7gts;8u3UYh?a@1^W2DfH~A|uHntI}@BSw2U(7{0UD@ay7&(MtEFuI_%a zs1&@V{{H?z79sDa>)xxY#~mMEXJ&qfjXm4a(q40FX+Od+{`s>24-fNvN5tI10zl6& zt}D>Y!wz=!s;+`Ucu8>^^g6)qcOBWNDrx-f!UCs@wzkPCr(8+O)8)(y0Am1yK3y%K zhfNwHRyZwYu7!%wVxd(ZYB~uBz`+mnL(2ot1_xPXo~TmNy7vuQ^=DRV2+UFP<<(*wnV61^U0Lw*5WniA@ z!ZI`4*BCOo=)TOGc&CC<@Hrk{Nu29g`+Eiu^MiF~EM@jW)qH)518+B<;Lro7Ko|A( zYt`?q+9jrqs5iP((Seu`37I|Gam!MzSYOGtt2$n$!dU1|;0_hxHXLaA{8@`yt`cm) zRR;ZDV0qCv+Lq7AAnuIg#Y6z>`!hek4Mj8AYG)F-Uy3vv^Ha!|s$Fh0YHmfc8bQTK zU7Z{R30I#VN5P8@XcRC)i2J|zAn>v8?+s5uV(DoGMWS3LhylUm=~bL?^;fBd*6b{H zno3p>K<8n0U(KJ9rLS-9$0Q}~6q}5*n>y!0UM=gM>v$bVXL&hdEY`+!pta*c#P{#g z3gHyEUmic{E*Le26wlLB6;;(7AD?uf{XTtC9vTwp?4*7E@Hc!uPeDaZjl&^-9W$A)HhKgZR{Q z42(>bb{jm%kK|ID`tidk9*rKPSL&Q#jbzo4bn8Tok^Zc&eq^FU^61)lelWp4BYj#;#_g6=@B0@up zs?J*6PPN2k21p`n^w4bHktAyYa=6boO=Nm+o+1S>T2bK_&+TC=P~@+RBeACt-wp_r zK-|B7Z)VR=n^J~GD4BDIg4g6BXJ(m7J4)Gd?`kIHQR%K^m+v0Bm@RX(xapO`_y%4kg_Rd42)v=<5Fm()-^84w} zg5E^>`T3;{gNbEe^I)tf_YRR^|ENwvFWN`&&RYqS8^JhSbo__itjWvUjDWT687F4} zXy-e^EkILx&&M8Cs(U`AKN&C)@WoNQjaHE&g>z+S=*O+uDki2r0R$BA9Xlcl9?`8kj;pyD7|7Ste*+JfCqIu(hPttFA)E^`SHgjh`5%a( z>JJ}!r+h_{>iZ+O90&vT@Ug8F$qa$VwSWaH+j`=>Rv*n^DaqP+jvyGXO!TX>Qs#t7 zBL;TGO;c*yT|q(UNpW?p27Z82~O6 zLrS-Qh3%S;Z+Tzw&-8Skb{8&3NHgfuXpdBOh)GXN1J&)}ciJd$zNZHl7ViFfd2x1v z$-*jJF(P%#qt-AkAYEb(8bxThoezJhcfWzmavsR`0SXVaFO2wptVTlw1O#7R`Fmrm zy`#L3NXp1S*zkQS)UeP{dnXBaI*9ws%*RVLhr(6{oXcOoKJvU3$g3dffiqx~O}yxF z;{fbZaE7K=;~Ksci+n2YhI@kE)%6Ng-w?!fm0D3SGBOe)!NK=Z#G_#IeiZa(eL}dS z<;@e}{Q5K&JU$S`oNhUpfF*`$+ZhPBeNGq~cwv`5-rGQ4LQ?eJ%J7)_W{$+Qgz5)b z`ssMq;pV_F97qddphvQ3D8;@!K=r>D+vIeiTZ zLJe%@)^)i!E4idXLHz*&iLD3@7!ZI;p(6y(2zsMBxqLJifyMR@+oBMPCoH+?qi9IH zBxPbE9q?;C8PQQuRW>V}11lg+0!M2QnB_Bp`>%9l%{Q6jv@@M5vr^9V%&i_1ta>DD zd9p82@ww)UAY_xnddQdgv$B!}Mk+atle97QPZ;!~Cqy9S00D4i!SkCRp?rdK+*eHn z;t0v^eQ8Y8>l@pt2_2SJ4=SYirqyAmoR?HzJD194Bo{wK_URuM=5gnps#E}|X}Fxv z&d+#V52tTVz!g+DJ-kbMq_sni;&0#Jy6mA+QE*qFT zKK6nrhnVLUEEE*-*>e5*g{jZWm9i(R&y1)un};*NZS%XlL_|cS`gD6IQ$ES{bPKXO zN&xj3tvINlBTVQgIBfjHQ?F~axchNAG|g9JEGm2d#F_nJBdTzQeje5ML&e>DB5Ktxl#W+vM}NKAqE1Q0R5OdS+P35Bv-FMIJ~S9j8G& zPmiHmH@lT}cJpeuezmAkl|Zq}jl! zBGt4sW&p-&A+YCPY))kr#g&)*{LbEcG11X+rjI!ypIbn^;=FCcJI2N;^J=(a%woig7Q&ba~G@ z+Sc02RYqR;`!eCe>-GC&aqHc7`+|NyQ=7P92ue@5>0g}r0}|ML9fN|lex{{;b%d}Y zk+~Eobb%L2lq`^B{GEyli>@Chq*SoMLCcwkm-!vEp%CENVS_b65ts^SAZchApPUS_ z=elflFkn$q7y+2pDRM7zc6Jti%=zK$!#Fb&4aUps6M8@5`8+nJYQmzT>NWF*a#X{D zwqSq-o(C#L;J0L-R0s>UG#j84iV$<1X|T|5#F7EFrau&HZk zxO6qcd()qKGF24?Y{GNHZy`{dQ189;-zb_ND*+eSL1YH+-@imHFqBn*0!ravTwD(f zl5@q!K^-vg9j3kEYQ5mKtifPJcxDigFpysd@~HB16>$#J%!Gv4F?kx?(Xp}P#*>aX^>x7m=OV0C?w)9Ee#Ief@Kb9v%luBWpl{HK&~0Q zM7p|NbIY_!_t6n+4uOJF%Dsq}R3?3cgQ)Hx+mdqo4*j}U+-u*%c&E#NkAd+def6ls z_3>IL&=8>QP0MlB)?j=CR&Gz50g_6%r-2*+O0iAk3gl{d0zRL`X<}<@2te+Y>P2-U zqZJqqmW-+W_dl7{g1A#s>oUs7$n?8(L{7C@%Yrhn-8bCfa=PlCni@7w@cP^F@$t&A zmRvSE%4cgEqE6j{`ueF9Hes^hV!OX^lLO-khga};kdW{KND&+yjNw5lyocQ_Zxz?m zZ6>IyYGS;~$`P|ZJw2*%3v&5DyIqh+0L~{i$6b8G2``ZeLQ>K%0E;-k_I$r6Iqrj9 zbzyfObuSSN7H2(`N@rn7Sl9Sc`&mm^;DX`fi><2ih>1BH%ygscHq&5iX>QK_@(yIH z3Fi+D4X_#fm43=lyQlU~r;`q3f^N}Nf;`0HIR_FC;S7*<*jbgM`UL`k7dZiT7aPkH)(**3&eg18?VYWyrf%Q< z(?nx_U}_1>j32=jVECX?_$OB@U0`zmx_u2XH-}BnCJZayaTn# zOqPw+0~7=bl3K7tvp=L@*z62oITk~?R&-1Zc)Yk-tQBqcl8%oZ-A!qcsei-+Vv;?p z_1O=fQzZHO;3#{#ZP>=^n574qr5oTAuZ!I9eEezcOed8rC z!w!Iwft$Mu(wCre3kVz-YJ6XfVbVZlR1C9TwE_)bA8+4$PL1UP#umCqz#Q+kXUKv; z?GKI8eW)=sn+k|yrw8}EctM2IMlKaH6}%dm|Y26}Gfvz=U{vrv?OI>`5gR z7k_`7nwrA1*cH0*6_`?3zF)t3c-0*y7(gZnfUeTf0R(hBbv7}PA2Le7<^#(C%u56A z62s*VhG^W%E`_J3%--$Y2VOeuaw;{%%CfSfnL_`IiwTPjq=MK>adM+I$4Cb6`n-Yy zXqQ282RXs{{&@QOX|rHj$zH|WLT~&3;%FN6nCixf&^a2j#jZo!}Yn zKDb&IU+7P9t}k7Uk~rAx#M_F8;Wg7SG9aR3VY765!BP?ccv%484=mI}1(P(uzjFs( z&Cq7;d}|wre>^06`&OURUv+5bM~KPgUY7P9Pcnxq0!INpWOvu@C}_P7!{res{J%PD z{=>DxA>M3QlyR0g58v#PZ-E@7OAF9{@HR=rhnrz_U54%2w7}B7b*l@3K^N_e7DA;2 zlUlVqmF86M2)#+Z_c5Lk-};}vz}P2fA8X^WVMYiooEjU9!~qx3V*~Ai7c{sJ;!Fa- zdGkXKTCgI3ubCdApeH2@DY7nRhG(ybDntrq8}QUEtkot|Zss8UJ0P zD8G9xrhSk?SUOpn`hMHwO|ToQLAVrL+_+z8Lq*P;B5|OeW;t^ZfKutq!72h$ezdCl z1BPHjl+F~UEAi0dwu`(h2E1&eusy#du&}|HNG8mtET37~Z{4ApH)xn2mUQ{r1}TXH z9h6-MbPivS#bu+oqlZ$qDeu2(G8)Q*p8i`4@P9L7{cm*C0N$H>3qKDyDqHBwDRLLR zdH`hj_Rrg$d1>OIci5)`zUcp?>YDsl%2cW(c+a98D;)QzuUuh2cfNC=}g&y#%8}$O^54C3JG7S|K(+i6NE60kXBu$QL&W$z6YuhxB*Ku z)E@kbeo?@>6h5;-0!-1J+x9S;RP7CMBuLtWH}tlzIB~Bo%MSveXsT=_D0rrM{FTbJJVgRNgFryo@t!z$zZVyXhH$g8cp7-{y5og`r z8y-i!3Mf!=irqu}#S75%z~m1FPbd4i%F4=^L>!CoqJ_2Vb!?s-&IS%;D?^bwMBF&; zuP%Ws9h?ps=}$#*PmYfvtM&mQVPs?^r0$SDp20`NqMrlso{WKk0h^6{4wx8^sS&YQ zuBD>kbKxXDt)#TV!f(y9CclpvW8VIM{WW9q(jJ5~rposS%Yz?%27&|SS6^~2c;i-v zlcpSvtj0ND!Q0&0f=Et?wtea9x(=QSxm;K7Cr{4)wxR*#4ZH<7U@Q(?=ieI}6XHL2 zg4qGiG||yn;o5V>YM3jA62Stv=X7P5wKP%oGY%JtHHFE5o^7UOCWRg^GCcOR1;; zkeHk=9sdlXBy4P0Q{NK75CUcJ=jR0v9}0pa*B717*w|WF_%2MK>EIPzPftIXnK4D& z)6+-2?kJ~;^J@T@r6ksY16r*NNpd4vdipQ^{vbUvak@KT7|KuDY<+rlX{qDCyn8k^ z=UIw;Qc{-{fZ56xwY57H`f`^z@5V%#(`?h7hh6GCE6~RT@uVr1d4ha=3FIq92I3%+ zFV|^5$&~YaN-;H>uLCX!k>s}8S{_D52gtkf^6~=X4FQgg!(hfw`s$JMNhf7cXymH+ z*xHe3>Fc8*Ao7P?XmB}5_0Pk>ddgv84Q}m?3|S3!(+Q}!FoE_98=E>%HKAPUuE6`z z6kwA&)6vys@E}x4oa4m{Vh(HVwK1D1=K`m-vEkKKL6Ea`MzNDqOx?VBliQMP#-ClS zeLbOK?bDHnK0E}lAa*q?$s|8k7Bd7=#-^;ji>w!Vm_5i zs=+glfs9n0WI~8)dV2b0r{3QgCPD-ZSg#YCD2n?NpuCw0-|y_ChSPCZPgIl|+P3Ma zgal)!%J*X6ixMpJVt%){yN|*(1LPSrF5Upr1Pj%71yfu4geAI+P62br_#>KDbHaN#nru@Ui1U?2dYnws%$pB^z+*qP;~rvskI z>b+xsWuiB!`L$py3A3*A`16DH-&?&x%Fv9#Ws@-l7HAevNZ3*)GgQc%k%idG1fTWO zN0Jx4JCj>eEq>j;{G=$0?`hBWA3j_KJO9kg%#}Y7Yz)Hd)>@Am{lVVh;e(wWB6ic& zSnjDS2tXf6zsqsh^}4dyr&Lb%hB;YTF9YgrbAZ&XzoY~pvv_0pI`eT(+#)7R9o zkdX@S6apP)U>_RmwUBXjt^J7lB|Td{x9Rj`3i4BSY^+CMupNjO2O#&?FC^pR|3Dor z8sC%)&F~O%fb;=Kn2T|Y2@0B=4nQQ8l(-DPG4n+ev$my|mTvlB8mJWN6YybyjA!uM z&rxG)>J^V0ZXhzc;tv1sF@`h;y!$K?nW*9#e0-DB^(Sj3;3=XVP%hIMsZ$Y(#U zjcLZ(rY1HDijeLSpiqIOMfaR&Yg2kenWPlYBL>-Qdxn6qB>VV0lT}k!KWHY=YxX1H z1^zZVx}!LCXd3hCo-((1bGOdE^Z_Q}LoU!m(U4B3q-gh%Z5$q6Teh*bCL4?dBjesM zcFl!r^;$Kcc1LqzD4?x36oCqls;ZdzwJb%ThWqV zY5dsOT2?zX*M`Q%&=I)FqnUKJBbXQ9f+hrZ+Qb7Mr=~_+UG286siR}FF?ps~@DXoJe*WSWru*}q z_=IcpB-?2hL_}S?B5$i9Smh=n`aNslzMx=isvrZUVNvAUjX!2cNGnuuMl&_qtttdU z2#6%eN(#@gL;%3rn)L=+lg0k$T#`_z$*un&452q0qv8E2!P-b3F$f@~%bb9(i?jyb zGXR8HB~$0|<>ewP@^DCpfbh$OuBm$8bq)8@cR$mgExsj2bE-oq`1P4$sDM~dm3 zO|jGK*K>JV&5*nn9T_PSI#J{12Bj2l-v$7)C&9%L+KBub7`TQ&h6tqTvMPJl9mBbL zu3f!%Y-M|nnp&Q&1UdpOEg_UsV$2lk2B8?Z4}zEmi+g^#ml(V&4GR;pwG9C0FEw=> zlTJPmK}wOf2k#^TGaa&XbJf+=;UYXAl$VFjuYbZd)4IptEGknVBQ(;`@QOS{YVKbw z)^-E-4TK{mLB`Nc3=ldQiJp2b{^1He-4uz~RjZTz>|)^z<^e1rWy`XxtSs%mAL$U$ z4SX{xsVLZ-0awF7_%Qn?w?Ks+1Epb?zCX8s`_E|lNRdQD(>LRyA~z5}-fQ4e09 zXuuW%^z#zOPhj%u>r4Cy=U$y%iEq))W>TbPMU#{K%BkB?3Spo=ueiXPVipger089fDF>~`+cwIk<=($-~Pwx z!{aEE4S+osj!k2Gd;iEtS`;lfmbDo0u_<`ok_ZdiF)=wjZUG`sIEbuB55eZ#EY|I$APO}FF z3dhE3RxRg5cK^0c${a*@mmEVZB19#;A%nEW7*=XZ+BH%{TU(n(y_)6e9N&pOoS`9C z6dl2)c+0@dEGq24pxN-*%gd1p?_!pOI&EDRU}ja--w>UJygxm(faO)HqPd}gP5}$( z2NZ-P&HzT1l^N(kmvA}x4B^&K=W+l%yAZrdoaBX?<_0OJswLawX3aYJL$t~~N=3^> zeSN{jF;n|s>@rYdV=tkk>8LTEo&eo8R73O9(V0Rv+P7AvEBXiv($exqRLoBqcCs$XNeVlBS-x67+` z)>LYk@Ies;&h8xnfdYylXvuT&@o7CdATd^kIPvQ766}pBiKF!jZle7FyS3wa=wzrl zcl_wMGBa}uYo1#5L-9^dXd#80DGrQx&9m^X0w%7btqo(2uu){KUYyJ0dp@+Z-jWA% zuBR62nwov^O2ZPSR%VGK>m8}chxJK?4iAm0*yO~I3iFO?q3c=A`N!zh$};-lNS!j|H--_7AmnF%}*vJO^}rhBp2U?aMNxGLK8Ilqq8*woy`5W(9yjx zNlf4WIypPI1Q*o@cpm5Vv^XEG{|k4Z5+L zO}A5DvUYe%FjS~O??8a;7sn4IIFk`tl+iQG12ML>=6x3_FC|(TJO>@cBxyw72I%jEtyzp z8MO^pSk%R{^zkkCzxX>}%uXj_uG?6bO5|Mo^M|3Yxw*Ts(F8yoI8c96B~I0!1+xC34d2BcDAsf#Jo$NusOOq4MFCI5TcHS95^+AWK(O zMWw2e+}`o+&w>Ig3ybU=R~Cou0eANZ7$65%i3!VLSzQCJ2tMQG1rT89Z!S7MEVC+{ z*y!knX>%~7gE$4UE`T3_Gsem^fu|Q8&X-2bytI=F{f|q!XMkS8GRDd(982}mM2U9> zps+iHEQ=fG+7)Qe9=#_IYtPOZQq!A#np)O%3y*GlJMwEx%wWvleiE>wF-7<(ac*vC zGTr5)0h<_w>q}Ih;y5iptT0*Z((&c^85b#iP9~o zE*6=)Rj~gD&KL*;3#`Hn428q-&!E}_+B;tH@$vk+D6!j+5?6I1{^dqNVa9*e2kY9^ zxu+6S+gOsf&^}796iA(fE2MD>(Y zgB$f46(8A^duU(XgUJ5!b)Du_Ei^?VR6NqZZ?h1nXGI`s09-gz1$t8ei#BQs3k#?B zFPWFAKu8x@GJbs!faV0tvWeL(YnybINS>fKg<8#=V1d!hi+?0U7gk|5eBBkp*4iNLZ_rV`uCJUnu^0+9mDnC9l2u8xk^ zshVM$M?pELtE?f{($%(WL+e>Ia_O#f|N4&*(rXP-Ki;Nv5W z>J)rId{6kZv;zYrWm;}-ZrM>@X5zO{ld$$M&X|DS-d=Ur^n>%c*7osl;oIKHUq@`fb4C@(`n>v{ZoxgA{FXS$c0b4OF=nTg5$+>Ay{lOiTzKI9b00 zMy%FjL%qz>!Lsjffhfo{<>WBFG%l~LU2%s~pvmZV@f$Kj$^kWj5Y4e4L{5hyIxE0_2DQ}@Eb zeumla@@JuKzF$P2KMZJ|Ept5^4hqt6Z09}S3dyZGH!B&3oR#VNIN}%EHr9o83r9yF zON3p9&|eE&y6If@e_PnC7j*JUAmt%ab+VxC6 zWJzjKmXEJ@b=BC&h#3JhnMD~eJt?T))oQrw_i}@bdNs%NKvpft#B5I$W1UvqSWl@e-0WzXsd{WVaSPOB|@+7f(t$ ztH-=ZuXNS}pD&fHiAf2#eY#`0xtW=G63J0b)+L+`)7d(C27TUJ2e ztjXU2`5F;n!hlaj74W;X*EioCw7rnA{<`r1j)znNn&lQ`IF$=r%`N>uXAqh!t28WuW0~a;5GF2!9 zcPVEN`TA~v1B01KE^+2<@ZXA!^_<)qHV%%qiN@K4zuTX|H)m@H#>@7(j0_Ho^@)hY zL`@bQaDzdVUv^GTM_U`l&6_%JBkXQx(eNSX);;a zsLwK4X2nTLDn%7a%zga3%u4S^pOBFU7jbTh{O=xf|50V%#Jc)9R@SiUi*ruj#J+y! z#jYQzde0wr!Sinpyl`KCMmK4@(6#34t0kX16dJk~Ut<0I;lTzb2s2S$Iy=|(d<{sX zoZqp!qFnMFDluZ7O94Ug6$+{BCQ+}}{`vDK{oNo(jBRIR(Qb8B6}OL1U~sK`)*HFZ z3cQ$Cm&pedVePVt4wVH3Pgq&+{Eh&eP5QTDX(oM$0u3LtW**mbMb%`<2Fm-4*0gFf zH)z!+H9aM9O_=?AraGO9>1Y3+#;!ab%C!x@91ab~I+n5)jj1Ecv1LiglBLL!3fT&w zB-xj-bP&eKWQ!&<_LAtJA;vZ#TVk?AIB{g@*cwY&zq|9Df4={|`ORPNJHO|BX6Ct{ z=U%S+x=xg3WE9l}MRGx)L9hi*o@m%7mgX!ODcLD!EqH2-M{aFct++1ALOOl`uhD6zF*MzPeX#7RN zN%FGIYRNsW*wYlHH`*ewC9W`g_ec%3%h_l{%L6@Q@GLOX(t%Eg_v@4auc7i@HUw0c zhJrLOn2bCu$^1*u6p&bCcCjOYbyu+5r^}TP=fJ?hIe#IMTREg^X0XGOsf3VF;ZO?M z@H_BP2J=RGb>icspf?OHYieo-GQ!aSdN^Zblqcj{`N771OGWGP=*#rEH5q+`caX&iVIqZORLC(O$Z(5BgBWlCPHBqSN(1 zeex^cFAnky$FSG~5^B(#EQo;k$-A!nmD@5oJv=CZKK=7g7H^DH6_%Q%6Nw`Oh1pBr zHFNLXp->`^4Q}yD!X|0a z+SX=%?i^IzDnGpb`1wMr@#{Vm`%xL;uAg!rOjfPp$0gUSX_qG#Vl$@(q_&I4o(;VZ zPh~0&JWcG?z}Y4*o{{T1ecAs@Cdco8%(gVDQgKi4Z^z@+aSD5CIX%LtyWQ>&K0vOw zrg$jj#>cELR|p#mVM{HsQfr&3)bYfwo`}^GX@(P%zXB}t(W8>`MpNQ7Ticf#`YGih zmN+p3xh^KnT3N|=Y5RNStVisjA~M-G`Y|6H#kSPU^d&n-lE?|QpOMmlxYk2?`9c`R zUqEEPx%Lok2uBu9qX@g#?y@$omXKfqds-eAMe^SA@0?L*2CJ*@&eL>AsV|7qlA}pI z?m0b0kQ*9r81tbckU1+ovhV9%-JF$|(k)o#CyBu-m9I?O{jTRJ4+Ral6 z(UIKL{F7mikoVdkc@p8Ng_B}+gK&cN z%dIGiyq$D1@$fX6Ik~y_rt+bYs#@fQ3)`2mNg0Q4I=tAKc*im3yz7wUA(L*J-ucsP ztBeWp_U#o0gMplKLdUmH<$IeH6coH2dh_jDuz>*^VqEwKS(+c=WMf@@8yvc6x->KS z`gO2xMOOP1%c&bTo;j9pjFKHs3P?%uA^?Or8OaoAKMus@uBiYw-PzeKeacHR2NWwD zA!jiUY>smA@)lndV`-XNk$Zki9Jnl})pKBkyu3UXX<6B8?Svp~qF>#ZhEG+Xe^qAY(rR6jMNVJe^^Nn0m%DqM z4}fPN03YJ*)o|mylSrc!amGNCJa}E*pSC0df~fP8tz2$yz;rtPt%kq4*Y(A$8KFOm z#vbL?)$*>oKT|QKK!m~K476Z?Rkd6Av(QYWz-oUy9VB#0jw{#;19mw4YaO7oIy(c& zjWxL3T=QZ<(oCqLR-c6aF~AmFb9Yx%TEgwD+gm_mwV&T_S}b<{0uiel-WiH1XN`>u zPF_c!f9;wu5lJkJIQ*BJye-ymoe?c`J-Nk4l5*?$@NT){^-r$h;q@SoSW{zw$LFeCDRoENINW;{pkBNJlQLFHE!PftLfxhejIcdyQ3jGJ&f5hPqfN zt=0fG)rtz=T*2gO@1ee-n5W>zs1hi-)g#StVPFtA$avc25r|IuJdA$6tE-|?M<&0S zd!%vVDU}K?*lJVsh8zYDneHD-#1d-c03zie$y@{yD-HMW^HskZU79q3YL#W*An?3v zit{9Yem=V3<6T!9;N1bdVTXzLy@%#!A2hG8+e0w{NW(l9Cq_;e&ACv*?z^g#T} zj=Tp3-moKyUY?#%dF?*(WpTG%%m)r-pKSom0^`&)2w2m+VBZqQ1q2kD7hlC^i;Ag~ z*aVrHQJw0)UA3|zT7^Kf@ZfcEre?bPx-G_DU0J!ot!osV;jZab+zAa$&6T$RCKQGp zz}v^iPm2W2nH{|o^|+llpuoz`Hd{Vk{mQ#5g9@2<{?8#epvAp8d>`QNWem>KawSA^&!s*!ru)q$H@+(I2YFWsci`eu9I8PUTq+-56=z&DmT< z$L+ow>W%Xa_1JRhz8?1jdQwhe4YyGwbk3&z%_0{>X>9_=%IlTLKXbE)|8l<(yggml znLBChaWqe$4N^p-EOH(H5ai5Y@Ttwq&tluWjipIIHpfay= z(<`E)x|HKwE}d$c7Nsl6OV@v%9^Ts8h5ONe2Pm|Q^LWtXx-X7#!6)UuCNc?5B@3fn zuo6hxL8Ue%|1>A3i7UC!TDP~)9kTTG^;I%#o-Lu&)~4>i`fYbh3aWu12KM68$Kl{B z`EyBl{MUUm-Mtg?sm4(D8z>FX)6=_r89)Xu)g#ZZlvdl7br+n=Md(-R0)Yc<-d_tD zZgdLS3Y1HXYgYREmldtdDc}SEU>T4`Q*@eS&NKub7w6~i($*TWJh~{CyKPdoScE;Q zs=E6Ai5GP=;@fhrmiDN%HRC+~VEm6!k0IyLKzM6GdYaLZaU`8XEn64;)>D;m7~^A` zo`N8(-%SkkY%qXt1R|{LJe@_wDGiI9tRJ zzB0v9G<9_F4F)MKvJaKx5b^*IYgC77f|dAA+#UGYEYU*3!jfp&kw&L|h-}Ah81np9 zf00EL#D#CWMqj&E0=+YCt86CdwjLWd{c(O_##Ns98Gi+V$}LDI)fbP&669BMs%Hf; z9e8CnBUZ|UuQ_$g@?*#QwEb5sJ8~@E7g$75AnpmWsB|^-v+7TL_3Bp(?Ni)z+)~D- ztzh?<&P5%&C1-j`LXjG*5t zg{5?slNUYOL|KuX9tFjT{o>;If1UtfmFnt~nQ3XPQ3GBiMbCepfWcsliSD=i)uF6eUx-kdM|LrO>VKd?O+9V#~FNGKnS1`4Mm*iOu4Rr&5TowDE_Xj_WLid{PtMg4o z?J66~pHx%i{`3o3WuH(2Q}mcx>DDCi#M2iy`dXO;37)NRZJ4i1FPCF14DtU=|6hCm b_gn8uS+B-Okth^h1YRbF<_6DCJIDM7YV*Nj literal 0 HcmV?d00001 diff --git a/dev_docs/09_export-environment-copy-plan.md b/dev_docs/09_export-environment-copy-plan.md new file mode 100644 index 0000000..c18c789 --- /dev/null +++ b/dev_docs/09_export-environment-copy-plan.md @@ -0,0 +1,293 @@ +# Export Environment Copy Plan + +Date: 2026-06-07 + +## Goal + +Make the export dialog copy describe what actually happens in each runtime: + +- **Browser/PWA:** MP4 uses the render server; WebM records through browser + `MediaRecorder`. +- **Electron desktop:** MP4 uses the desktop render bridge and bundled ffmpeg; + WebM still records through the Chromium `MediaRecorder` runtime inside + Electron. + +The current labels are accurate for the browser build, but misleading inside +Electron: + +- `SERVER - FRAME-ACCURATE` on MP4, even when Electron is rendering locally. +- `BROWSER - REALTIME` on WebM, even when the app is running as Electron. + +## Current Code + +Primary files: + +- `src/components/ExportDialog.vue` +- `src/i18n/messages.ts` +- `src/lib/desktopRenderExport.ts` +- `src/types/desktop.d.ts` + +Runtime detection already exists as an exported helper in +`desktopRenderExport.ts`: + +```ts +export function hasDesktopRender(): boolean { + return !!window.ruwioDesktop?.renderMp4 +} +``` + +This is the right signal for MP4 copy because `ExportDialog.vue` routes MP4 +through `renderMp4OnDesktop()` when `hasDesktopRender()` returns true, otherwise +it calls `downloadFromServer()`. The MP4 copy should reuse this exact function +rather than reimplementing the predicate, so the text can never drift from the +route (see Implementation Plan step 1). + +`window.ruwioDesktop` is injected by the Electron preload before any app module +loads and never changes during a session, so a runtime check is stable at +module-init time — no reactivity is required to read it correctly. + +## Proposed Copy Matrix + +### MP4 + +Browser/PWA: + +- Badge: `Server · Frame-by-frame` +- Description: `H.264 export via render server` +- Progress: `Rendering MP4 with render server...` + +Electron: + +- Badge: `Desktop · Frame-by-frame` +- Description: `H.264 export via bundled ffmpeg` +- Progress: `Rendering MP4 in desktop app...` + +Rationale: both MP4 paths render deterministic frames through `server/render.html`. +The key difference is where rendering happens: HTTP render server vs Electron +desktop worker plus ffmpeg. + +Avoid `Frame-accurate` in the short badge. It sounds like a stronger quality +claim than the dialog needs, and it obscures the real user-facing distinction: +server vs desktop. The help text can explain frame-by-frame rendering if needed. + +Badge style: store badges in title case with a `·` middot separator, matching +the existing sibling badges (`gifBadge: 'Browser · Frame-by-frame'`, +`apngBadge: 'Browser · Lossless'`). The `.badge` CSS already applies +`text-transform: uppercase`, so do **not** write the strings in all-caps or +switch to a `-` hyphen separator — that would render MP4/WebM inconsistently +next to GIF/APNG in the same column. + +### WebM + +Browser/PWA: + +- Badge: `Browser · Realtime` +- Description: `Recorded in real time with MediaRecorder` +- Progress: `Rendering WebM in browser realtime...` + +Electron: + +- Badge: `Chromium · Realtime` +- Description: `Recorded in real time by Electron's Chromium runtime` +- Progress: `Rendering WebM in Chromium realtime...` + +Rationale: the implementation does not become a desktop ffmpeg pipeline in +Electron. It still uses `MediaRecorder` from the renderer process. Calling that +`browser` in the desktop app is imprecise, but `Chromium` is technically true +and short enough for the badge. + +## Implementation Plan + +1. Add environment booleans in `ExportDialog.vue`. + + ```ts + import { hasDesktopRender } from '@/lib/desktopRenderExport' + + const isDesktop = computed(() => !!window.ruwioDesktop) + const hasDesktopMp4 = computed(() => hasDesktopRender()) + ``` + + Use `hasDesktopMp4` for MP4 text. It wraps `hasDesktopRender()` — the *same* + function the MP4 route already calls in `exportMp4Server()` — so the copy + decision and the actual route share one predicate and can never diverge. Do + not reimplement `!!window.ruwioDesktop?.renderMp4` inline. + + Use `isDesktop` for WebM text because WebM is still available through renderer + Chromium even if MP4 desktop rendering is unavailable; there is no existing + helper for that distinction, so a local boolean is fine. + +2. Rename `exportMp4Server()` to `exportMp4()`. + + The current name is now misleading because the function already branches: + + - Desktop: `renderMp4OnDesktop(scene, ...)` + - Browser/server: `downloadFromServer(scene, ...)` + +3. Replace static MP4 bindings. + + Current: + + ```vue + {{ t('export.mp4Badge') }} + {{ t('export.mp4Desc') }} + ``` + + Proposed: + + ```vue + {{ t(hasDesktopMp4 ? 'export.mp4DesktopBadge' : 'export.mp4ServerBadge') }} + {{ t(hasDesktopMp4 ? 'export.mp4DesktopDesc' : 'export.mp4ServerDesc') }} + ``` + +4. Replace static WebM bindings. + + Current: + + ```vue + {{ t('export.webmBadge') }} + {{ videoSupported ? t('export.webmDesc') : t('export.webmNotSupported') }} + ``` + + Proposed: + + ```vue + {{ t(isDesktop ? 'export.webmDesktopBadge' : 'export.webmBrowserBadge') }} + {{ + videoSupported + ? t(isDesktop ? 'export.webmDesktopDesc' : 'export.webmBrowserDesc') + : t('export.webmNotSupported') + }} + ``` + +5. Split progress labels. + + MP4 currently uses: + + ```ts + label: t('export.labelMp4') + ``` + + Proposed: + + ```ts + label: t(hasDesktopMp4.value ? 'export.labelMp4Desktop' : 'export.labelMp4Server') + ``` + + WebM currently uses: + + ```ts + label: t('export.labelWebm') + ``` + + Proposed: + + ```ts + label: t(isDesktop.value ? 'export.labelWebmDesktop' : 'export.labelWebmBrowser') + ``` + +6. Update `src/i18n/messages.ts` in both locales. + + English keys to add: + + ```ts + mp4ServerBadge: 'Server · Frame-by-frame', + mp4ServerDesc: 'H.264 export via render server', + mp4DesktopBadge: 'Desktop · Frame-by-frame', + mp4DesktopDesc: 'H.264 export via bundled ffmpeg', + webmBrowserBadge: 'Browser · Realtime', + webmBrowserDesc: 'Recorded in real time with MediaRecorder', + webmDesktopBadge: 'Chromium · Realtime', + webmDesktopDesc: "Recorded in real time by Electron's Chromium runtime", + labelMp4Server: 'Rendering MP4 with render server...', + labelMp4Desktop: 'Rendering MP4 in desktop app...', + labelWebmBrowser: 'Rendering WebM in browser realtime...', + labelWebmDesktop: 'Rendering WebM in Chromium realtime...', + ``` + + Badges stay title case with a `·` separator; the `.badge` CSS uppercases + them at render time (see the MP4 copy-matrix note above). German keys should + mirror the meaning rather than preserve the old wording. + +7. Fix the export-button help string `exportHelp` in `messages.ts`. + + This is separate from the help dialog and is easy to miss. Both locales + currently hardcode the misleading claim: + + - `messages.ts:43` (en): "...MP4 needs the render server; WebM records in + real time in the browser." + - `messages.ts:1153` (de): "...MP4 braucht den Render-Server. WebM wird + direkt im Browser in Echtzeit aufgenommen." + + Add runtime-branched variants (e.g. `exportHelpServer` / `exportHelpDesktop`) + and select with the same `isDesktop` signal wherever `t('...exportHelp')` is + consumed. This is exactly the "globally visible text saying MP4 always needs + the render server" that must not be left in place. + +8. Update help-dialog format text in `messages.ts`, and branch it now. + + The strings live at `help.content.export.formats.mp4` / `.webm` + (`messages.ts:1081/1083` en, `:1923/1925` de) and `exportHelp` (handled in + step 7). Browser help should describe: + + - MP4 as render-server frame-by-frame export. + - WebM as browser `MediaRecorder` realtime recording. + + Electron help should describe: + + - MP4 as bundled-ffmpeg desktop frame-by-frame export. + - WebM as Chromium `MediaRecorder` realtime recording. + + Wiring the branch is cheaper than the old draft assumed. `HelpDialog.vue` + defines `CHAPTERS: Chapter[]` as a module-level `const` with static + `bodyKey` strings, but `window.ruwioDesktop` is set at preload before that + module loads and never changes, so a plain ternary on the `bodyKey` resolves + correctly at module-init time without making `CHAPTERS` reactive: + + ```ts + { bodyKey: window.ruwioDesktop?.renderMp4 + ? 'help.content.export.formats.mp4Desktop' + : 'help.content.export.formats.mp4' }, + { bodyKey: window.ruwioDesktop + ? 'help.content.export.formats.webmDesktop' + : 'help.content.export.formats.webm' }, + ``` + + Add the `*Desktop` keys in both locales and wire the branch in the same + change. Do not defer this and leave the help dialog asserting MP4 always + needs the render server. + +## Verification + +Browser/Vite: + +- Open the export dialog. +- MP4 badge renders `SERVER · FRAME-BY-FRAME` (stored title case, uppercased by CSS). +- MP4 description mentions the render server. +- WebM badge renders `BROWSER · REALTIME`. +- WebM description mentions `MediaRecorder`. +- Export-button help (`exportHelp`) and help dialog describe MP4 as a + render-server export. + +Electron: + +- Open the export dialog. +- MP4 badge renders `DESKTOP · FRAME-BY-FRAME`. +- MP4 description mentions bundled ffmpeg. +- WebM badge renders `CHROMIUM · REALTIME`. +- WebM description mentions Electron Chromium. +- Export-button help (`exportHelp`) and help dialog describe MP4 as a + bundled-ffmpeg desktop export, not the render server. + +Build checks: + +```bash +npm run build +npm run desktop:dir +``` + +Optional automated coverage: + +- Add a small in-app devtools test that stubs/removes `window.ruwioDesktop` and + verifies the selected i18n keys or rendered badge text. `src/devtools/headless.ts` + already reads `!!window.ruwioDesktop` (line 19) and is the natural home for it. +- Add an Electron harness assertion that export dialog MP4 copy is desktop copy. diff --git a/package.json b/package.json index 3f29cfa..f1d4de8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ruwio", "private": true, - "version": "1.3.1", + "version": "1.3.2", "type": "module", "main": "dist-electron/main.cjs", "scripts": { diff --git a/src/version.ts b/src/version.ts index 8113aad..4754c66 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1,2 +1,2 @@ -export const APP_VERSION = '1.3.1' +export const APP_VERSION = '1.3.2' export const APP_NAME = 'RUWIO'