a3N8Mj#uHd(e7k47S3CEJWfv1FfL_zJf@9(8|Y)0
zDvs=BwFxGaumjtB=VWc}^_plhx}v`m{|o=o_Y)!Goc|8WlJJmeRA*Yfl^vsudR^Ds
z4U6@_x6&Rm90lQ?L+ct_5Hp6hIaM2Da~gke4#!)Py8V++2F
z&s-thP%J9(yV`=M{Thx3q7l$LT!zjWoJ8c6&Zcj^kRMmjI-%h{#hO)%9qP+fCD-u-
z^&+l5FkjJfnHBZn?-XlPaE3|7`fqpJ_n%)YI~4ag@qeb!#1Y}gnxYyW!RFu?&g<4AE!zCy<>)aj(K>$60BVraQf-6a8I
zSjI^qn)XDPpO`ZpOt1@Ck?x8h2UAxOqAqsO{L+G97(?!LNc}R=V6Ghg6Hm
zdC3}hM+79BKC^pn2p`Mf;Ji?7>Yz9}(7l*qw+A`9?8@!={1Jx4D!XnF5g~*;6jLL9
zaEa9UYQ=nnc^s{!DWSvfR)!}h>s074!!fAVOl+y<|NTn@S>H8}J>5^q9$29ZuEYQ>
z7w`<^Qwpr9LvuXn%jK?^>Xye3-wn0%#k)w!5lq35;l5qo-Q7WAR?5OAa-o)8Z_97_
z|0ZO{`H_7)=uYtArW+bfL`f1~I*CfM9T;`U3YqIEV7S56h1IQ=nUbyB;~H~Tdv@-wB#2zd~;-HYl6&@WC2zKQ4FGQ
z*g_c3><)%fKW)fTbb_xWQQ=?38yjGC*9)KoI~qq^)Ou{|qEJ6*IK;9H{b>7+%I?lQ
zdhyY|-Y182)b?C_X@sH5|5J5nF9Ypat%fdN^L39`5W&vg=vU~F8e)t`^Z_hGpK}6^
z3U%bb_C-?8TLx|_h`yT6HD=|Wj{#XttHd*LN5PI3QJYkCnepd8Pm`y2hD)~TxPqzd
zlb@@5U8|(2`UNdarD!EGmC84ZThJ{sH?Z#EUTtZtevuMoYSbrwnMz+CV5HKG3InGR
z)K$=eTrWlZY326?!7&gk(L00$dPwPI-5@vNz-2>rd={W(qK67V5(ro-^u0rGac4B_
zxP3ALaHrgKy)Rs-yzY*BigTZo000uAMo+uH8x#`gpE0NfkrXm(5tP>wbx`4x9zU1}
zE*duAhiqMwxi8%X?qzIE`co)Wsy0u4IEf8|0>UJ|#M`UTQ=ug@8#;04%eU38!^^uPSpGnz<>>)La&Cb;$n?<3|f+)mY#cWJXCA*ehgCPf*yq7fGd9mWq
zsEG@KrlUrIR;z4nhmRDKf$Aml17ubz1*+#qA;XsA(ZC^W0R^5*>FR8)AIpfIx9FL7
z3bD6>y$G9ZkEILTIvFh%j$I6Kh;7@3Nuzj~87$JByZzls
zy5b_-nm!aNZUGTUj?!>0P?hGXUNA;sEpd2kENQ9S@jSvm?SR$j9C*N8GAZR_;c6I}
zR7Z8?eD-o3{YAL;hikdfiTb&vJ+4U4!k~IH(K_2vMeQA}P0M$*SX%lT7$?b(5c&j?
znel{k+a<(uxezNGkYs^L62!&yn%bK;1&;o?A6Au*tY~ec8B$^f+z1zsm`)xCy(g)@
zP|9vkd_{@!p7B231+Z^s&Pgng%
zIK;=*w<1-V&tD7<~>Dkmc6;GjLv
z@;1m2my@GKv3U!tS^h~>M9T7OI>}EAk)z>#3}WL}v8dKrVBL$Iu?9p|OiE%TVOL+3
zX^!;mj{hLzA2LUoBj+7JwK8kD^BtB3mrT){QK;~QY>;uzls#N45Co~W)9?-Fmp9^(Jc9TG=zqJ7_GylcZ_(sCL*sY(gvn0L`)_+YAY?IJvw<~l?m|W5A9Ia-Yd1o(Ux~d9>Q+9@fSk!a=c&I@REQX@V
zB{4)}q#oiA@fOL6k>|i7iGP%Mk-covdNp^IFo~5`nz8QXJK9TRUToT_p4CbFX&hrB
zP>Nr@^tfBTN!QvOg>vS`lAM0R(gLXc5aU!?DhBmPq7W}loZf4pEuka6CyLd7ZML#m
z)%McyDkafZkp
zB04?K{DmNS;M00*R3>)&O`36|?&e(MU;|@&M*R3mJVBh4{Jf=f((jca4*ow4*}rtK
zTm{5YPU?relPP4CMvbNNbuS8oO?)whG$oNzf+sPv_f0s{6T*M-Ue(h@v{qw|pC~Y2
zKfGD{)RZHh7Z^81BY_!G%>SW(zHG};kP)^k_i7;4C_9rLbwQTX{8sn)JQ!i){^GYp
z1bvvjQB~{%ra6lrU|`J`&q&F_2_~+DZiHi^NSGAwvp@4n$eQiVIp5sgx@l^w<0ne>
zDz(hXO%1SAat~mM9~GXzUoyY?h)TH%A*fR!_%ZtH%dFJEFSvqkTyc!?Y6LDcSYNWK
zmOp8hGceMQIdb2)>LmC}*?a6#__kO`D21A(ER8w6y9ak77^Kb~#HV%a8)oyM8q_4#
zMdu5-M4E9jr0xNLV6d}t41ep|1uhyqUog<0tAOud86qCYpjRf~m7~iR#!O9kC?7U?
zcmM%`^&CDQzYqvRj%IqgbuVX#!g3PO5En6nB}X=7`C(oFgcBAIf3hutRjWKrl0ovi
z9hJ5|Oh}nq&Gd8z(@x)$d}$kvL+D%UM=$lekv9FkWrhTcTt7y0TE90IBYPkeeMaWu!?Ow4q-varWOL
zD;E+{a_i)LOBw_o>!kPqJooYo$){dlcvN_#BRCf!D}
zMc$4Ih3mId4<}g&_;H(}&{?@gj_(GR1%3*Qz%oDl_VR@#uzQ&;vp&bF;s6G`138=~
zFc&d$=b%mL2$;V4of*}ElA28GCSSN0HzUmIeD5CubT7$3n1&MWL#{d^`lHdC0P
z@td}hdp87571dDzO!+Vqr8n;FhRvvr3qkCLo-)BseXH~k8%kc){>NnN{>p<;+B}Qe
z%#Cn|7GeeE89`*AtAW&+`S1HY3@Gs*<2UDxgVx28L9JhI$7%_2T)(%3tGVQRg!!fX
z(PwD)&Y02SA28jq$B5ylM4}17EL9mJ~mOzbYZ||TFA^dPr;Xw%Da-C$+
zk`F0tqP=WFkAA}m+ll$>X><}Lj*&oD#PuF*Kw_L^Kmw_6rI~9X**joH5&m~Nm>s&^
zj&K73X3C`8;&EgbU%ou1oNSi2(l
z1rZ57`oM$EP*sM%$1+W$HwLa@uc~Fxgq?>Wx)^yVL~kBrC~gWXpW<{G4G(mYP$H0j
zxMr08k2_))W>k*I#SC}c5)7slh3-Ofp-^O(X_Yoy@p_O3$8~OE$C5s>h&G7?EKk=a6_QUxb|do4}`
zy@eJ4gAAA>qtp@(hbxpEtjt8I*A^W#2D*xUyL#&tuCf#QaVUEnnkB_v-(J|S>b~uf
zeg<56Gbn7Y9D-QMng)6UpZimgptm4bG_>4kIe&k~Zph~dLCDpb@HbwT_X0m%8vW#r
z;$n5I%_=n>E3{L{5(0^ej6^}U?{p$~1)1y*TiSG@FW}kb3vt9qFQ;KVI!8L4V|QuM
z1m}Rk5vYGx%1@O1nDc_4M(b^OgZ5`R-L!3_ncw%yxuSbDqm9b7;yO
z8>hM-6>;eB#bUp=!(i=U!4I)F<>i)R7?0hS>u4Eb<6c)3z_@iGJkeL=RIN2nTvZ`5
z+5p*Id;t%g;J)eDG&~9ZC_;oboAK
zQ!97Qw3Pa`1cft7peQoK6)=(LxG>PVHnk{DyFE^F$%OL4MzlssrqD)TY%CJP}^*p1<+?{8M
zv#B#8X8ZTu7pfCmVu9oc8zB#Gd7pd3=NB$
ziufmhq61YRk}~v9bYS0J>*;&}U_~jp_E3K2(RHW=bic=jl06{Q(|L2ePWTKq9JmU!
zsxB`URD4zm@D8pc)UZX;+%|SNT+h$5ntVgMjPH%2VhSmVPH+YDbh{5m!tlyzyWZE@
z_vNB1S&ok7(RIB$jpfjwZV#v7*Eki}J_L-n0=nFt?bck=
zIaCLgaKR(T%K_B;Bw(okl-*aS+Jms`oH*G@W&P`*7{cCC@4$T(42|FHCdigXTbc7Z
zI%=pPwZBU#d`w%Ow1?qYy10yQb-*?nlgL$p_-wRq5|&)IKP6gYUI{`Q+Y#vO{v>?9
zG&tuHhBoCk5?rfYM*Ol~L<(pQaFT~VT{TfJGmDt1z*BkqFm94#<2h&1={&;I#9I;i
zW}LRul+4ZH)ZB0`0W0)W@#V&2Zxv$R(yx(`Ij1b&Ty>vw2un1vtQgT}CJ>jR@z6ae
zz#{)~F)m^bDWCYm^)7YMN3xK`+Y*&DNk_j6$!Rd)QMU7kJ+)vvQs$FG-YQ$ykk
z!4>&!Nx5%v!S9(O^F<7IHw?sD1S-HpK4l-j?VI^3;B2(JAbr{1u@iY-&Gm;US4=;^
z^(%Y~vnT2bS?y5Q$DDe
zOyQ#jl*x68Mw-YOlHIk4XZ5h|3U4tvq++SmlIMeGxk(BXGka9tcNI5m`yHahLY;0<
zYkaVMD>_Ac`}8?OwGF;BFuYbLoyTm-O>6QXNiqS)hEMK^WayWLVO_?-F1!u6a`Y
za$ELWC0z#^VsVFGJ(~iDoj&X-BH)55dS31cBE0zv&?GPT%VAB&T;K}WN!)owP|x+0
zE3xHxwWzw^7FXNiAue`t1xJFD`_?njsE0uYDSe{!+nwUpr@1i$OVmxPR}7y^Y9x}uhg%(c
zwpo?@bj$*=gO)VCtJygMFvQGb!0{Boky+{$0u0U(n;%AR?L~r31)Cgp&mA{}pl?ID
zm$ti>!88Z&11N@??3O#RpKJ^KwYkr>Cxp8V{_KodXjqjeA()D4RI)Mz${Q)|7~@cjW^Dq4Q6IHh6^v@sDr!
z97Tl6z`^B)Dqnv_n2ca0u=J4G?9{g|r2TtTh#KqfL@5V*XYqB&2j3MmX4S;V7z~?Y
zh>(=6ReJ%dsHKoRqMyq!K4HTvcA^Op)tacuXH
zT$?xHC4}`*^g6VFJPkbGqFuYs1&gps8e}Z(=Q>%8{YF${lCY3kpjY-G05G3G`zYwB
z^6)=a>O~g-W`2&~q-b(!+()bh*OdCB$s{N3iI^9rI7^dM_@}1UpKm_1;`npzb|I+D
zdET-yU+|v2@C}a(oowZ1hH$mK@4x@%Su`yLy}+Fe=zJnz(~s1Gw&Y9A
z>kOf!WQypkL~po>RZALKh)cXcP_m#NPL#IJKc4?%!lZM1wBt)yWEVO=HGKFb@!YhS$3oK-_b)#PSGje*+Pe&oN~G}Zqx84y
z?A)Q{d&O1hrDtIqtIzmD6Bk6MDX35Qk5SFXu#V?!Yg-HZmmD4*X?&`SdaaqX%~0Cjm)@mrzJ*=
zvnQ`(^i3m}lZt=DykcD`rwK)dbHkVd8*LnjAph`sr;>zH26PsAR9S@R&BbtfNc6Dz
zfwGB=PfPCn90i6Ndmy%*I&}!2^vRm?qgPFYd%r~gD4o`Z1azIIC$y3@#=($zj(
z_WQGkxnanR<7n$&XS<(MqlK)}VOO+9=v~Tuq-~C+1DyJz8Z)Jf69eG{A-pQY!qF=!
zcvx=(8e)ElUup;i1x(~jBunU_PsEN@^zU|?XvDx|H>qKw`9FIC8%6N;Qb8XUfyoq&
zB0IL%#;<7Oq6@2)rQLt2Gz2I3Tw7-9_Jx$GF@2ZFdbahom|QMai|aUX?O|Z-!}q%w
zj7Grzx_Npwnk#~_w6G<#%3Z;@)*fuUD5L9nWASs2MljCMIS#(rr2f)l*iROqXZYEx
zBR1f~Y|q^-YlY$uc%Eni1!@gsuMV3N-d;4$Bwb!EGHCzMxngKD
zfmi=AjI*A|Y-rr#fl7&q@Z75@sLlKO#k2KCW!tXmw3%tlbX+W(ThWB!*M133dK!t0nEmLPq@E9z3`{1q$+AeBJNZ@B~^e
zh*QslsDasKT(Sk|_v$sn``4l+De6q_Uza2+uIj^8AK9Qx^;M!F#l0~K@#_46|aO>{Du!yg7b
zl+{bbnZ>jAHH-0dKBbe|%)p~$qgPp$%R6?UaArBv3}<~GleUTTEIj6~d&1?E6}_k+
zp9-vBJG1bnwH_2(J#BPS9{F>}2VlC$iQ3jZi5Xd*P(+-e*P2zQzblyCLnisKPFF=<
z9D4c8e-6esor(@oy3r(nrH;*HLzgh_R|hvr*BaqjJmWs_uPt8?dzKyu3jv_HZ`H*b|cXt
z8B>Z1AO+RyiJjaiFS&lX6?*uO>XyQ2ESro6M`~pY{YJVIf3t$xP#8u!l$FG-
zWOp--@?*qvh)-%`&TCed{X$M1&r%NtL?+S`PR~VJ8`qPwk(Q%(HXr0_T(s&YQTgv*
zzH&4yzI@0BkZ_v==e176=5b*_STCfwm@YDw_{F7>ByjR2m^#CG-W01%KCX7%CC4O(
z2E7e6ZUegub4Cu1x8q)MG{?MLa**Md6jd}kF4s?ONf0K6WhR8>1c@;3y28g2G^~4ig9@7v^;M!H8At6WQLIYH5y1Qvg
za-s?9R+|jA<0QnSGYbD$k_?5>k@V^tWGy;2STy({9U|kO`M|K@I=PZtQP^$NuKOu{
zb6W>@J7lcSpW_XE5W-ff4uQBRohT|196>mW2|_8{vYHV<|FDm`tJ!w4{?hv_AGP`J
zF9aRP+YqqKPyZZ1HEXIkV(LJ+(<{({tps-q{8D^f{9H(heL>ws709kdKdne~DDTWz
zgO(n2hXbwBs-}*1*U|+k=pMXs@LPj!m)8mH3$5A-9+kK9fQeLwwZlTRrjuxR*dcrk
zoB-wZQ!Z0J0Q2iZ{HW#i52A<1G8>%j4f7^i%fDSG)D3#VcoIoflqnK1|M>~yLhPU8
zY6$Q%@*e>3ZjM~f#Fo7K%IV}m`bE7c^BcS4$QI_8=Rn~bzxgY!MfpWcugh=Lt8%IY
zYi##gbXS7o1A(x2pUd%>g4kQS9)8OS#3L3(@FmN-p^fDd$98;nm4Xr7}MB@icR9-yX{(UWl=!>Wh3}C0VCWU?z%qUdc*%zrvcjx8gz1H+Sc)7NUh}
zC(J|^$;O!5ctwVolfBjB$ehWfOivdfOL%`i+kRZ$=eTQl{9Qcc#QqxaD=)HMHQZp4
z<%{qlW5FN0@DVqV6&iGd@O8Z!b`hSgbYGVtFHQ4)oBR|du%3*`y8Cr+gGftFa7fOH
znv-l()LNzOCF?4kTRQIVz?lk73h)RgI!<`^K(Xpd~k=UZ;KaiRVijl#%z
z7Ju8Z>cenMBcdYKNXQF3x(HfxNO>wLQ5razdL*)_36UN9t73s<54p8vncW_TZU6f$H0dxHk}FMV!ZaP$IU*BwG<^&P
z^&@2%l1$;~eli%c*p={)=XRM*SXMggv*PTmkadF<~JI{`ZJ0eud~l>pu33
zaGAY4D?hn55b7+r*sQj-Y``{OQkolJFPwT7ljIIZ%%VB)=CJO1HwFecPZL5}CYb7c
zrqo_*HS!Z@`GYc_R0dA>OrItNV4Fn1-hDlf{%NJ7CF#5
z<)#!ssYR~lxZ}<}#ebfptg7q9icm)+2mh;N`*H$ppPi^ZrSc4{$&>%LbpriWhxpo0
zp`kE~pP0*apHanC!A_^y3k9DO!`yR$pX|02uyPA%9ySd#hWH|z_auWoq3Q7JOZT_}
zz=WLH+$DZ2v%nDjlxcN5c~OqRpM&=5oKreyN8T+g6$fm0YGs;Q2KiW^2fO*wNk~qT
zUOG`#FIH}z?qY;XVK-DjCLeswD6Sf7b+H(Ab`o1U%r1{A)AjxSIZ-n&s1-v-5uyD+
zz!SKZ?RRv&8gs)pT{cq8Svs=y)#X>sxU<9V$Ta?@e`f4`ql1WCsX_i_?_$X|IhRi0
zQ;Gawanb*g
zAAZJi&y&i>-9ykM5TC^o-al#8Lq$DcjYR)wK~C+N#w_C2$TwtmIPkUW%YSpe(t~GE
zY~-+)*i_!I-o?cUPY{OsaG6mSSx=i@H;yZ!(!M)b_XgmmJGSf1oTLr;>Q3=(0y5Fm
zk%XMfM1%rtYa6ffr{?B?1^Objs2+Lg$(PBV>VwY^MxnrmCzq8Y{p?&!
zDK8E^c-F3(UsLX!xwO0g^rAGoO5*HuG*MRSwRJKIoxU{_Re(Mxtb6l|>sDTp{jF+T
zm_+gSbLwofoiDzVbN*BjS2oocrXl!+d-q8AV@?a=M&ftWbJ^8o-AK(+k;
zA{X_^lIYv1p+CWykVpeDk)EVj3kH)yE&ilZ+5fCpXD
z{G!=!6{(sr(H}!%u5woX{un;Ix;7#kG$ITXF6!%V
zM2&6&|He|Ri@$c*u*0N_Pqh_VVAENmYM%hX;gP9PT{&;e#06w8jD+?N9o656*FX+e
zWU5TiOE5QEnXvx``f6yt5`l<~xdj^;>&X%)Ftl+tYxA?TAqi6-vt9*+h8tJ@V`4MX
zk+%1!uk^v-n-?E51-2_}i
z{@q2?GJXpNF(G7x@Id7~1HoEaYR_P=tq6#D32}$zovwg;D7BoR$Uv5#@2M=RhZx8G
zqbmEcthL>aX|ljbY~DAh{m9F_l+O^NwDM&@PP4N?IGszVr$Z0ZO4viol=zL#zK0TK
z&AnZk3E+udL}|BLUD_x|{|g+vZn%pL>Y8ko7}84L@cA>>mu%zi4OFkiNNbqJgL_%;
ziR3}-`UIzxJ|I@}<2F0N?Yj|1Q-6hE49^6?-aDoPRcMT-C2X}(IO9CwJ
z?hu^d?!gIedpSAZy;Wb;{WbrlW@@H;x}SNwO>@375f@|J8QPER?ioA1@#Cm|J8?COu$lSv_2Fs(?F1TB1!8^xuXFWX+HW54~CG
z%&O~p>SoBJ2-XmLeb0VE52pecX
z$ZDf4n5@T6@8iOl<7V`-?$75Q-$fepW%VPh_jDf{JT|oca)=K~UBxz>
zCQDE9c!D_Hh)*hZjyMsE$a^9>vN+Lan|4Qe?R>MWEPKA&0YtnHZWkY7HgATSa-&QJVcm<_Dxj}TJ
zvQZsW4sPv}taTTAvv5x(AW6V
zFT@)+`9a>xwp2iNpzGySD|aeCo=jWd7dI7GwN<(h5V1*oP~SXP2f|MCJkOAzc$mhI
zN%XlojXr{P*ZP&SI9|=^Z}au$HD`Gq;K3H)4v*4QLIFU@UuYM3T12lkMtm@;Co>DO
za>~GG8uzacBP%;GF4}?gBUSidN&0YX-HN2&q4`9^4i_+;
zEr%br$2(_2OfqEl3Kd%Qt5pdk$9B-wsQodizM!2S!OEqQau_yKofAtY(TLT+J#ICZ
zSynKaiK!hw+1vnZcncR=La??nZ1e?xjZ>04-!CQ~=;y-0OMe&fn`ilbs6{v3z{x$z
zip8G(z_IZ{(aFQW{ksv=2H
zyz5a-TDAV#x+pK7Eyq4dv(`gvpzZsDJlwE{i<;n^(dI#+9?$0{5sZN~mNmjl8zYB}
z$6ahi>p2hVMHJc@+II{zRzQ$B
z-=>CVz+9sV?=9`;v5Ld@zXL0|8YXAb}*9IWQ;EbC8CYtKd4{@;0
z7!)g>^{2H~PmCGV3BD;O@j&?Bd;t)5$=XpL_U`!(=5$nn73IPy1vMFG*WXrVQb^4)
z0Mga{y9dMlpp8BcBjZ-jhA?IMM=zc=nYiuRvWt(u+aW%u`^VlUtmjZ#O6aqn{ZKQ)
zk7LGe$nuUdgP?U$Mu$b%zC+Xc?5gh`HEOAbfi#y@ABM?0lKH^>;2`(@udD}ccvNZY
z3|A6GQ>9Py4IeN0H@Dg;1?FU%*UrSD5McNHofWzDcRo$c}_9e0I)2AJGW1)9`PX3J?I
zO!3g3L&&*Kurs{0VWDb9LLG$cso>1=Pd)T
zyYcs3em)QTt@7vWcTTTqK%S~;%(XZHSF=({be}5o-b%g#SK;XdL_E~wkg!51)zzg$C5Y}*+FKDfooTW>)$Qr{+vnB-{KQ2XmrNC$G4ualvbDgydg3}?yr1#1V)8db0l;h0u9ktO{V$$5
zH9U*m!77$xq37;Wa
zvt|Eu2DO5xO`pT<@{-9jex1QUHinIUH`y?d*P`s;AZY~aj5ZNg5c`~IJ&M6-3hT*#
z@L4ql1zkGO>0|N6?sS$XwcX`e{Wz^Mww&kx`N5GTyEJOs2n$3gUoQ
zh=6L0%!Fw|q>CPw}IYA`c}-a-`bgH>2OdJ$g`1Lbr~NOD)HS$>6Byp0-tVR^#l6
zD18jAYeh-KK=ZB;81d@syw^&i&}h4i@)8=F4)w69GKXP_nl+DDUw2Hacl|4YJ#(9Q
zXTA?2V+}t^hx<-~``ez1Kld|XwP`5H*5>jaN05JcW~pXUMzbqc4iq4&y{suJp`5|2
zwB_I;QVPP+gMe@OR7RdE-SlyD^nmntv$rcH58f(S8O$~~gV2g6(}UVUKA%%XMzTRs
zC9B2RFP;|*r?<^%&O!#4@A;jW{)GEvtwi?!iA1SN|HKcPenCIXN=qvvVcnH4-d?Yp
zJMGFRlmzNVQd6i`_H~dO{o}jflU{Gt3pnHUzlr_dI0aStWUqFFNC`zg#By8gnSH(y
zoFVy0NZcUjXDTGBsl7Dq{F?isuB__OM|%v3Y`8im4lktcec*alEA~)}hgt<~fEEu?k|nM$vzw%%BbP(i@Hs7AhEq9o4{|$^Rl{}&
zYS@2WV4H4Ghvj(7>}skfIrrs9z~Flc!2~b=v4b0G>$CH%4Pn+8`XWmp3Qo$E__ReK
z7p=;l=%}$WWy7eW3d~O@Ykw=b#Jz6C^{JQU?40hdoR=1^W-t0_2}e*?8sxTYcxHsE
znyCHTw3V>ji?qfQzDd%}RspC;qB
zq&TKND7AucN8Q8d*V{1zbxLdoJ`5@~GF3~9Kq9#bBA@xF=;M=P;tk2XKl76glw;d}
z#$K9T`y}O8c*NMY5S|`R^R9FhrRny0ffu1KICJ=aD4Z2aruXc>_X~XW_f!oQ%AA3{
zDV}IR3o_d-&q(E|&|WfcO`CTzTP_+-|0>R1!bYJyz9B?~VPLuG*jiTKS(vai?11mp
z?N*jy-cvUW92Bs+!kH(I$KmXm7kVgb4Ckf-pd|7^yW(R?{Y=kl{nEobBoS#*MXbn-
zHx!7uEQ{II$9g>+;7aQVQzZ;)n|IzTgvLO)su~^~$TIu^m?a`SNM%4SNo|X7F_It8
zmuwle7uVP6TEmd?5Sg3Div&m1W=3yIn_bytCs=t}k?sP8J6ObeCbSyLq`7o(i2DbM
z-W+Kve?#VM7YfvO>O`m*guR1d7m2`qR{KCW6D1v$H|4x@DZ=8YR%K*TPA%{h(UORR
zU<|{gH9J=`9INc{EpaIOnghGFUpA5ZU6YDt+>qO}Q^Q#2Mv3QVS#zL(1xf!yxTA83?CZqW@kNB
zr|6b$q1IElcuXnor!wC@Cx>N}CLIpxPNWr$F6yIef25zlAN8Y?7AX@G?+WUn8bgTz
zU%DEF1BXde53P!Zx4N<(F_>JaqX==~M*$C)8t(ALGP~E;Cp(Bk#Dgo<(+6(qkwjNX
zF{`6Jz)H*4t@|hZVc^b4}ML3`O1$KIws%
zlRIf7xp&?c@GDle{SB$kP`MJ_$c%JIK>2bgZWsv<6~juvhfhHi5q3WW>u9>j@Xnhz
zH&{%Qy9n2{mu1GYr`OK&S#fp>d8MC@0GKeMG4{kZA2$A3Bc|2s8r@*BdH*GIqzt4R
ztlk>wE1DiHVF-^)72{KydZJast>zr0g~G}TE_G6P@Mx?rQZ!q8>tD1TA>$KLuwj$@
zNW5s(j~WUq8ig_7VR85kLaPgpI;7zz+HPg!=Z>BoLkAjCu(+{urm-0>LlZf~mX?Uxu
z>SS0cG2B?fVE@0?S5*2NSz8;Q?j&)3zSG+aMgo
zKQhaYHr5VV$mf%7%^q~Hh^==NO=K!RRlir^j%82WbdtV+G>p<}EtSs!o3No!OK2dBqmfc;lP%+X
zC+6@6-x>V!ypXc-1EdfQ&uYa6lv)=h_MI+?md0#orQN-gTFC0&Ri!2l4fUlp<{=G7
z6`{~KlGpdJ5*%LdMm{Mcpc$C7-wnyl74QIwZ0oxN4C3_3U;a9Ln5>R7!um
zsVj*0Q66F4ZD-jT8Ovcr&(MT773F>Z!tLkv_*JRJuF2S}{J?z$Q<(#wgCve
z_5Ir655`h@QC%$cUFC!Lf{|j&c!Z3Eve4tiDGVcovr|*oo+}DG1DoR;zlfEWFZu}*8$-SeNP!cC*?K#Y
zLF**`>($q30CA`H=_ijQFEFu360}7OiY`S+fdPnZeL`Mn!*Urwbc^tJoB&~jjR%ce
zPzDY5NrHUiof#~`C2yW@0FypTg|rVr%yN?)EF(~?#|p!{R2D0Pgao2Y?Hpe?Kdnn=
z6yMe4@ndxT*AI7&)j+(LM%!1(GH7>ucgkGCB$15N$^_5rTiT{{SLORv7_A75LP3G=E%ssPwT+J%
zNwoK|mIu0@+yTX#N=6GgSL6FrICv)(f3Rkjq${@2M=wysE`p`-Ixaz5S_x9QOGUhM
z-t%E@KA$`3tB8(_)z7Xc#EhTF>V8j#@
zdR?}8`VsgeQUdCCe|d`cU8KI008}2w_+-P_G1=G>kJvcP-FcZSH7|-ySj%kYkHpV`p+yThzPVcGKPK{ss0gPMF
z_lEew!R`#o<>@8d++p3b1au)0yR!MLB|a#epxKGA{UwV9pE)5xl9p8XUMf45lDPaB
zxfxb%2zJpISV3UHEvgL_QWa+#oAghl%^zhXg#i}j;R1?=?zAP%j<1yoNI?VRE4d7{
zvv!Y8R}8mQs&Cx-QogqOSZB$5Z}Qb+BmGd^Rw1P18;mqk92)>Ww&(d3m=Bvu_rGWh
zttbc?MzxXT39$19Q_^WDd>D^v)o*b_gR`WMuP@RnMfo~7Q>x0BZk($y>@@nBDEg7F
zOgm?mAETE2sXK=Ur!7eHDcY2#xSABss>T|MR7M8AEc`JgsK`KGQ$iQ|Of;xF_}ps;
zX%pdAI)tzaG4{#bB%BM-_kZwvD8vuz(|6WKJG>}7dwxeVSbil_Yu)p$;6gX9`KsIH
zT-UHgn%KGME27KD^kLdC8tZ$q>bxa`y^L{T&Z;gSeTQ75dW~SZdj@YkPEv7)06$YK
z08j*f;$eS?*#a$}cs&2E38zyY*mr0{#DWpvw}gGaCl8;>MGmq_izT*30fOtMQ7J+Tsc6MhGtE%9XgRT&yuV`C&33-&9D)0+n@G4@
z5L98#)Ue*)CA#%UyM!u??0U~N9S7ylSVTr`VxIiu?-zNBw?@g4$!Zg%vzRtybok7D
zt9O`U)P5VlOPlRQS_9UZ#q1?ko*7sni7vzxtiw$vB&gNy~y_Zd!PhAF~1czTiRPl7iI{;+}y
zTB`_?x(if?>o&?YKGY7q^392&H8R}#eY32P8Bx9RJzX79Fh0CD2yQ4=SyukziyL4t
zr(Nz~>D$|_Nf#Zd*4{h^NICGnOBt4{)RYkrn}sKX6n_8feeFC%i|A=vW@n+YGin(^
z6E`sP`{u*-cwYR(+)Ff#r`YC~VEpaClx|+_jh=914#xoW#iPq8WSCB#--hEYI%qcB
z?ke_U#8;l9hz9VMh=Pp-nWo77tii$)T5kpQ_Gk0jn!k#k;E1TkhvP*!{J_cjk=c2M
zCu9IxkWQ=Y6;6H&Y4
zdrk<>J2K&%0J14-VJHgml+)N29J=qbYv#fbi^h^>m%9_t*&Y)D?Gq>Oa2fP!V{{0m
zkCpIxOBdR%nL>>w>abt@_=(vMHFMRq6Dm+Xq3v_$THF)JnX<>q)!5%kCMUDN4&FPd@4ler(fJ?HzSdyn8
zyUKE;eV7A&?Hv?uL7Lq&|H3O4hpu~+W%(&wZF(rgg?Bh}mWtyl&h2O-AomK-{h-D2Q3p*3LBu{04JQZwOf~5mS{ZH@tpzTSg31
z-88#6ZPg~X-crqJD%r86B;1=7uO2;Q-PJx@7cDqhom)VamP
zjO5UqqV(zr6mRNO!@f(|2hR+zCJeba+U?{WFa0EHUk$EBWuMkKK&NO2p^su5@g79<2ip7#NDB+`-Wsad}2C$9gL&^J6bpxySeT4Q-}1;DHYkAc`a08Z43+nwg$>;Ojhb>so3d;k6X>3;WLz8P+&O~zW>
zgyf5{t8q`1JG_w40=3~0P>H8>P=MCxiED-glTh@hsimfdu_lW?);#GHA8`~}{=3cU
z$?rJL%UY4cJM4fiv4nRu@?4N`kCm#ZnA^_Adt3g9XPLg3TG#t0_f&EL=u5_dM~m6j
zCuh#E@B4NjH;Tf-&$8qde|2oY#-u3jrcLdk?r-(O
zJ@X--LD*>XJG`AU=6-1tlR>9k;m_1vj-)lD-`zym4G|~YNz=6HR*FZZ?kgVy&zR%&
z;Cj@0n_MtHppm_O)Am(%tF&M~^A1Xy@A_y1Vcs$Q>QoPX+v0c95`9`!LF$NC-eWM>
zA{3E^h#u30SCYv@Fcv4LN65vNoFF~(RkgKc7gK=BT0Alfb@s{kk46?=W~V}mV~XU|{IR&KFmIzl`wxkRbs8y~d1tKXfVt2Cd-FZiS
zY=kwWtHw6b`Y^Dhw<72=c+lDK@M(s0oirM$DVLlEnj4TvW-mBI^|rP72&}=Jvt*tL
z4z-49!zdE8yGMK}6vz=ls
zwJ%HgKq#MK{@Uh=zYqUU1&uK1Ca1Wy0@PP(YRS}3D}k0pqpLvmhcXAltg2F*{hh1`
zR!2zCU!{xKbx!&k4M3zMDkzg~g(>}6TQ)>7=FEhGK$h%xOYr%2R|6_z!W;g{a$
zux)p~{(iSqrcVHDgy8=0z^_eNyBPrXOamG}%XRaj1F6S5xWgdee#brAU&9p2d!7Cc
zoSyS9?EFs!7mDEsSo4$3<&Taj!lNgf#s+E714$PQK7WXVmV6^)zKD(szj)Vk0C>+!
zbrud^)Z&t@D;Iz^rX6`nk?N0C3fFTZ94?-2mKJH+1mE!$?Q%@(4-Z)P-4)^TJ;iqn
zQ_$s(w8aXb_jtys73#5yC2TxeY^Gri}fIz0aIYKZ7uDO6Zcac&Y$!pqX_U`CMZB!om(FA4NjHDyHG
z%rXm1-^A*YYxM^Jcqm`z)q=@h`+H=sV8l~NzSQ5by?mcQZQLv<^zH@5FzD&iXr|>D
zt-ABvw?VH30>`~lIj&Yuw|$BzkgU5GMSqc!`32DhPTF#7vJQjiz5(*l-}6%J`X8u_
B(xCtV
literal 0
HcmV?d00001
diff --git a/repository-review-decision-provenance-guard/reports/manifest.json b/repository-review-decision-provenance-guard/reports/manifest.json
new file mode 100644
index 00000000..cbd0114d
--- /dev/null
+++ b/repository-review-decision-provenance-guard/reports/manifest.json
@@ -0,0 +1,14 @@
+{
+ "generatedAt": "2026-06-01T10:39:58.097Z",
+ "module": "repository-review-decision-provenance-guard",
+ "cleanStatus": "READY",
+ "riskyStatus": "HOLD",
+ "riskyFindings": 9,
+ "artifacts": [
+ "clean-audit.json",
+ "risky-audit.json",
+ "risky-review.md",
+ "summary.svg",
+ "demo.mp4"
+ ]
+}
diff --git a/repository-review-decision-provenance-guard/reports/risky-audit.json b/repository-review-decision-provenance-guard/reports/risky-audit.json
new file mode 100644
index 00000000..5dc21af5
--- /dev/null
+++ b/repository-review-decision-provenance-guard/reports/risky-audit.json
@@ -0,0 +1,282 @@
+{
+ "generatedAt": "2026-06-01T10:39:58.091Z",
+ "status": "HOLD",
+ "summary": "Hold release/export: 7 critical or high decision-provenance blocker(s) need remediation before reviewer decisions are durable and public-safe.",
+ "findingCounts": {
+ "critical": 1,
+ "high": 6,
+ "warning": 2
+ },
+ "findings": [
+ {
+ "code": "PRIVATE_REVIEW_NOTE_EXPORTED",
+ "severity": "critical",
+ "message": "T-private-note contains a private reviewer note without export redaction.",
+ "evidence": "Repository exports must not leak private reviewer notes, blind-review details, or hidden institutional comments.",
+ "path": "mergeRequests[0].reviewThreads[0].redactedForExport",
+ "remediation": "Redact private notes and preserve only a public-safe reason code in the exported decision record.",
+ "owner": "scientific editor",
+ "mergeRequestId": "MR-317",
+ "threadId": "T-private-note"
+ },
+ {
+ "code": "RESOLUTION_RATIONALE_TOO_THIN",
+ "severity": "high",
+ "message": "T-notebook-role has no durable resolution rationale.",
+ "evidence": "A resolved scientific review thread needs enough rationale for future auditors and citation readers.",
+ "path": "mergeRequests[0].reviewThreads[2].resolutionRationale",
+ "remediation": "Record the accepted change, scientific reasoning, or deferral basis in the resolution rationale.",
+ "owner": "reviewer",
+ "mergeRequestId": null,
+ "threadId": null
+ },
+ {
+ "code": "RESOLVED_DECISION_NOT_EXPORTED",
+ "severity": "high",
+ "message": "T-metadata-missing-export is resolved but not marked for export.",
+ "evidence": "Resolved scientific review decisions should be carried into release/export evidence instead of disappearing after merge.",
+ "path": "mergeRequests[0].reviewThreads[3].exported",
+ "remediation": "Set exported=true and include the record in the reviewDecisionPacket manifest entry.",
+ "owner": "release engineer",
+ "mergeRequestId": "MR-317",
+ "threadId": "T-metadata-missing-export"
+ },
+ {
+ "code": "REVIEW_DECISION_PACKET_NOT_LINKED",
+ "severity": "high",
+ "message": "The export manifest does not link the review-decision provenance packet.",
+ "evidence": "Resolved scientific review decisions must be carried with the release/export evidence.",
+ "path": "releaseCandidate.exportManifest.reviewDecisionPacket",
+ "remediation": "Add a reviewDecisionPacket entry with packet hash, record count, and covered components.",
+ "owner": "release engineer",
+ "mergeRequestId": null,
+ "threadId": null
+ },
+ {
+ "code": "REVIEWER_ROLE_NOT_ELIGIBLE_FOR_COMPONENT",
+ "severity": "high",
+ "message": "T-notebook-role uses reviewer role viewer for notebook.",
+ "evidence": "Allowed reviewer roles for notebook: reproducibility-reviewer, methods-reviewer.",
+ "path": "mergeRequests[0].reviewThreads[2].reviewerRole",
+ "remediation": "Add an eligible reviewer decision or document an escalation override in the decision record.",
+ "owner": "scientific editor",
+ "mergeRequestId": "MR-317",
+ "threadId": "T-notebook-role"
+ },
+ {
+ "code": "THREAD_ANCHOR_INCOMPLETE",
+ "severity": "high",
+ "message": "T-notebook-role is missing file path or commit anchoring.",
+ "evidence": "Decision records cannot prove which repository content was reviewed without path and commit anchors.",
+ "path": "mergeRequests[0].reviewThreads[2].anchor",
+ "remediation": "Attach anchor.path and anchor.commit for the reviewed file or notebook output.",
+ "owner": "repository maintainer",
+ "mergeRequestId": "MR-317",
+ "threadId": "T-notebook-role"
+ },
+ {
+ "code": "THREAD_NOT_RESOLVED_FOR_EXPORT",
+ "severity": "high",
+ "message": "T-code-open is not resolved but is present in the release decision packet.",
+ "evidence": "This guard archives resolved decision provenance; open discussions should be routed back to merge review.",
+ "path": "mergeRequests[0].reviewThreads[1].status",
+ "remediation": "Resolve the discussion with a rationale or remove it from the release decision packet until review is complete.",
+ "owner": "scientific editor",
+ "mergeRequestId": "MR-317",
+ "threadId": "T-code-open"
+ },
+ {
+ "code": "DECISION_EVIDENCE_REFS_MISSING",
+ "severity": "warning",
+ "message": "T-code-open has no linked evidence references.",
+ "evidence": "Decision records should link tests, rendered outputs, reviewer screenshots, or manifest entries.",
+ "path": "mergeRequests[0].reviewThreads[1].evidenceRefs",
+ "remediation": "Attach evidenceRefs for tests, outputs, exported artifacts, or reviewer attachments.",
+ "owner": "reviewer",
+ "mergeRequestId": "MR-317",
+ "threadId": "T-code-open"
+ },
+ {
+ "code": "DECISION_EVIDENCE_REFS_MISSING",
+ "severity": "warning",
+ "message": "T-notebook-role has no linked evidence references.",
+ "evidence": "Decision records should link tests, rendered outputs, reviewer screenshots, or manifest entries.",
+ "path": "mergeRequests[0].reviewThreads[2].evidenceRefs",
+ "remediation": "Attach evidenceRefs for tests, outputs, exported artifacts, or reviewer attachments.",
+ "owner": "reviewer",
+ "mergeRequestId": "MR-317",
+ "threadId": "T-notebook-role"
+ }
+ ],
+ "coverage": {
+ "requiredComponents": [
+ "manuscript",
+ "data",
+ "code",
+ "notebook",
+ "metadata"
+ ],
+ "coveredComponents": [
+ "notebook"
+ ],
+ "missingComponents": [
+ "manuscript",
+ "data",
+ "code",
+ "metadata"
+ ],
+ "exportedRecordCount": 2
+ },
+ "decisionRecords": [
+ {
+ "id": "T-private-note",
+ "mergeRequestId": "MR-317",
+ "component": "data",
+ "category": "review-decision",
+ "decision": "deferred",
+ "reviewerRole": "data-steward",
+ "reviewerId": "reviewer-z",
+ "anchorPath": "data/patient-observations.csv",
+ "anchorCommit": "feedbee",
+ "resolutionRationale": "Data row issue discussed in private.",
+ "exportState": "included",
+ "redactionState": "leaking",
+ "evidenceRefs": [
+ "reviews/private-note.md"
+ ]
+ },
+ {
+ "id": "T-code-open",
+ "mergeRequestId": "MR-317",
+ "component": "code",
+ "category": "review-decision",
+ "decision": "unspecified",
+ "reviewerRole": "maintainer",
+ "reviewerId": "reviewer-c",
+ "anchorPath": "code/analysis.py",
+ "anchorCommit": "feedbee",
+ "resolutionRationale": "",
+ "exportState": "missing",
+ "redactionState": "public-safe",
+ "evidenceRefs": []
+ },
+ {
+ "id": "T-notebook-role",
+ "mergeRequestId": "MR-317",
+ "component": "notebook",
+ "category": "review-decision",
+ "decision": "accepted",
+ "reviewerRole": "viewer",
+ "reviewerId": "reviewer-q",
+ "anchorPath": "notebooks/replay.ipynb",
+ "anchorCommit": null,
+ "resolutionRationale": "Looks fine",
+ "exportState": "included",
+ "redactionState": "public-safe",
+ "evidenceRefs": []
+ },
+ {
+ "id": "T-metadata-missing-export",
+ "mergeRequestId": "MR-317",
+ "component": "metadata",
+ "category": "review-decision",
+ "decision": "changed",
+ "reviewerRole": "metadata-curator",
+ "reviewerId": "reviewer-d",
+ "anchorPath": "metadata.json",
+ "anchorCommit": "feedbee",
+ "resolutionRationale": "Added related identifiers for the cited dataset version.",
+ "exportState": "missing",
+ "redactionState": "public-safe",
+ "evidenceRefs": [
+ "metadata.json"
+ ]
+ }
+ ],
+ "releaseReadiness": {
+ "decision": "hold",
+ "releaseCandidate": "v2.2-public-export",
+ "blockerCodes": [
+ "PRIVATE_REVIEW_NOTE_EXPORTED",
+ "RESOLUTION_RATIONALE_TOO_THIN",
+ "RESOLVED_DECISION_NOT_EXPORTED",
+ "REVIEW_DECISION_PACKET_NOT_LINKED",
+ "REVIEWER_ROLE_NOT_ELIGIBLE_FOR_COMPONENT",
+ "THREAD_ANCHOR_INCOMPLETE",
+ "THREAD_NOT_RESOLVED_FOR_EXPORT"
+ ],
+ "exportedDecisionRecords": 2,
+ "privateLeakRecords": [
+ "T-private-note"
+ ]
+ },
+ "manifestPatch": {
+ "reviewDecisionPacket": {
+ "packetId": "packet-risky-review-decisions",
+ "packetHash": "aceced7e057804cb8815b37798951f94595973bc5a5af72ac5aedf10b70afcb5",
+ "releaseTag": "v2.2-public-export",
+ "decisionRecordCount": 1,
+ "coveredComponents": [
+ "notebook"
+ ],
+ "findingCount": 9
+ }
+ },
+ "remediationActions": [
+ {
+ "code": "PRIVATE_REVIEW_NOTE_EXPORTED",
+ "owner": "scientific editor",
+ "action": "Redact private notes and preserve only a public-safe reason code in the exported decision record.",
+ "path": "mergeRequests[0].reviewThreads[0].redactedForExport"
+ },
+ {
+ "code": "RESOLUTION_RATIONALE_TOO_THIN",
+ "owner": "reviewer",
+ "action": "Record the accepted change, scientific reasoning, or deferral basis in the resolution rationale.",
+ "path": "mergeRequests[0].reviewThreads[2].resolutionRationale"
+ },
+ {
+ "code": "RESOLVED_DECISION_NOT_EXPORTED",
+ "owner": "release engineer",
+ "action": "Set exported=true and include the record in the reviewDecisionPacket manifest entry.",
+ "path": "mergeRequests[0].reviewThreads[3].exported"
+ },
+ {
+ "code": "REVIEW_DECISION_PACKET_NOT_LINKED",
+ "owner": "release engineer",
+ "action": "Add a reviewDecisionPacket entry with packet hash, record count, and covered components.",
+ "path": "releaseCandidate.exportManifest.reviewDecisionPacket"
+ },
+ {
+ "code": "REVIEWER_ROLE_NOT_ELIGIBLE_FOR_COMPONENT",
+ "owner": "scientific editor",
+ "action": "Add an eligible reviewer decision or document an escalation override in the decision record.",
+ "path": "mergeRequests[0].reviewThreads[2].reviewerRole"
+ },
+ {
+ "code": "THREAD_ANCHOR_INCOMPLETE",
+ "owner": "repository maintainer",
+ "action": "Attach anchor.path and anchor.commit for the reviewed file or notebook output.",
+ "path": "mergeRequests[0].reviewThreads[2].anchor"
+ },
+ {
+ "code": "THREAD_NOT_RESOLVED_FOR_EXPORT",
+ "owner": "scientific editor",
+ "action": "Resolve the discussion with a rationale or remove it from the release decision packet until review is complete.",
+ "path": "mergeRequests[0].reviewThreads[1].status"
+ },
+ {
+ "code": "DECISION_EVIDENCE_REFS_MISSING",
+ "owner": "reviewer",
+ "action": "Attach evidenceRefs for tests, outputs, exported artifacts, or reviewer attachments.",
+ "path": "mergeRequests[0].reviewThreads[1].evidenceRefs"
+ },
+ {
+ "code": "DECISION_EVIDENCE_REFS_MISSING",
+ "owner": "reviewer",
+ "action": "Attach evidenceRefs for tests, outputs, exported artifacts, or reviewer attachments.",
+ "path": "mergeRequests[0].reviewThreads[2].evidenceRefs"
+ }
+ ],
+ "fingerprint": "ecea7282a32c0a38"
+}
diff --git a/repository-review-decision-provenance-guard/reports/risky-review.md b/repository-review-decision-provenance-guard/reports/risky-review.md
new file mode 100644
index 00000000..98cd0a4e
--- /dev/null
+++ b/repository-review-decision-provenance-guard/reports/risky-review.md
@@ -0,0 +1,78 @@
+# Repository Review-Decision Provenance Guard
+
+Packet: packet-risky-review-decisions
+Release candidate: v2.2-public-export
+Status: HOLD
+Fingerprint: ecea7282a32c0a38
+
+## Summary
+
+Hold release/export: 7 critical or high decision-provenance blocker(s) need remediation before reviewer decisions are durable and public-safe.
+
+## Coverage
+
+- Components requiring decision evidence: manuscript, data, code, notebook, metadata
+- Covered components: notebook
+- Missing components: manuscript, data, code, metadata
+
+## Decision Records
+
+- T-private-note: data deferred by data-steward
+ - Anchor: data/patient-observations.csv @ feedbee
+ - Export state: included
+- T-code-open: code unspecified by maintainer
+ - Anchor: code/analysis.py @ feedbee
+ - Export state: missing
+- T-notebook-role: notebook accepted by viewer
+ - Anchor: notebooks/replay.ipynb @ null
+ - Export state: included
+- T-metadata-missing-export: metadata changed by metadata-curator
+ - Anchor: metadata.json @ feedbee
+ - Export state: missing
+
+## Findings
+
+- CRITICAL PRIVATE_REVIEW_NOTE_EXPORTED: T-private-note contains a private reviewer note without export redaction.
+ - Evidence: Repository exports must not leak private reviewer notes, blind-review details, or hidden institutional comments.
+ - Remediation: Redact private notes and preserve only a public-safe reason code in the exported decision record.
+- HIGH RESOLUTION_RATIONALE_TOO_THIN: T-notebook-role has no durable resolution rationale.
+ - Evidence: A resolved scientific review thread needs enough rationale for future auditors and citation readers.
+ - Remediation: Record the accepted change, scientific reasoning, or deferral basis in the resolution rationale.
+- HIGH RESOLVED_DECISION_NOT_EXPORTED: T-metadata-missing-export is resolved but not marked for export.
+ - Evidence: Resolved scientific review decisions should be carried into release/export evidence instead of disappearing after merge.
+ - Remediation: Set exported=true and include the record in the reviewDecisionPacket manifest entry.
+- HIGH REVIEW_DECISION_PACKET_NOT_LINKED: The export manifest does not link the review-decision provenance packet.
+ - Evidence: Resolved scientific review decisions must be carried with the release/export evidence.
+ - Remediation: Add a reviewDecisionPacket entry with packet hash, record count, and covered components.
+- HIGH REVIEWER_ROLE_NOT_ELIGIBLE_FOR_COMPONENT: T-notebook-role uses reviewer role viewer for notebook.
+ - Evidence: Allowed reviewer roles for notebook: reproducibility-reviewer, methods-reviewer.
+ - Remediation: Add an eligible reviewer decision or document an escalation override in the decision record.
+- HIGH THREAD_ANCHOR_INCOMPLETE: T-notebook-role is missing file path or commit anchoring.
+ - Evidence: Decision records cannot prove which repository content was reviewed without path and commit anchors.
+ - Remediation: Attach anchor.path and anchor.commit for the reviewed file or notebook output.
+- HIGH THREAD_NOT_RESOLVED_FOR_EXPORT: T-code-open is not resolved but is present in the release decision packet.
+ - Evidence: This guard archives resolved decision provenance; open discussions should be routed back to merge review.
+ - Remediation: Resolve the discussion with a rationale or remove it from the release decision packet until review is complete.
+- WARNING DECISION_EVIDENCE_REFS_MISSING: T-code-open has no linked evidence references.
+ - Evidence: Decision records should link tests, rendered outputs, reviewer screenshots, or manifest entries.
+ - Remediation: Attach evidenceRefs for tests, outputs, exported artifacts, or reviewer attachments.
+- WARNING DECISION_EVIDENCE_REFS_MISSING: T-notebook-role has no linked evidence references.
+ - Evidence: Decision records should link tests, rendered outputs, reviewer screenshots, or manifest entries.
+ - Remediation: Attach evidenceRefs for tests, outputs, exported artifacts, or reviewer attachments.
+
+## Manifest Patch
+
+```json
+{
+ "reviewDecisionPacket": {
+ "packetId": "packet-risky-review-decisions",
+ "packetHash": "aceced7e057804cb8815b37798951f94595973bc5a5af72ac5aedf10b70afcb5",
+ "releaseTag": "v2.2-public-export",
+ "decisionRecordCount": 1,
+ "coveredComponents": [
+ "notebook"
+ ],
+ "findingCount": 9
+ }
+}
+```
diff --git a/repository-review-decision-provenance-guard/reports/summary.svg b/repository-review-decision-provenance-guard/reports/summary.svg
new file mode 100644
index 00000000..e57bd671
--- /dev/null
+++ b/repository-review-decision-provenance-guard/reports/summary.svg
@@ -0,0 +1,13 @@
+
\ No newline at end of file
diff --git a/repository-review-decision-provenance-guard/sample-data.js b/repository-review-decision-provenance-guard/sample-data.js
new file mode 100644
index 00000000..a3803f74
--- /dev/null
+++ b/repository-review-decision-provenance-guard/sample-data.js
@@ -0,0 +1,174 @@
+"use strict";
+
+const cleanPacket = {
+ id: "packet-clean-review-decisions",
+ repositoryComponents: [
+ { type: "manuscript", path: "manuscript/main.md" },
+ { type: "data", path: "data/observations.csv" },
+ { type: "code", path: "code/analysis.py" },
+ { type: "notebook", path: "notebooks/replay.ipynb" },
+ { type: "metadata", path: "metadata.json" }
+ ],
+ releaseCandidate: {
+ tag: "v2.1-review-ready",
+ exportManifest: {
+ doi: "10.5555/scibase.review.clean",
+ bundleHash: "sha256:1b2c3d4e5f6a7b8c",
+ reviewDecisionPacket: {
+ packetHash: "sha256:pending",
+ recordCount: 5
+ }
+ }
+ },
+ mergeRequests: [
+ {
+ id: "MR-242",
+ title: "Revise field protocol and reproduce notebook outputs",
+ changedComponents: ["manuscript", "data", "code", "notebook", "metadata"],
+ reviewThreads: [
+ {
+ id: "T-manuscript-claims",
+ component: "manuscript",
+ status: "resolved",
+ decision: "accepted",
+ reviewerRole: "scientific-editor",
+ reviewerId: "reviewer-a",
+ anchor: { path: "manuscript/main.md", line: 118, commit: "0e5fbb1" },
+ resolutionRationale: "The discussion now records the revised claim language and the corresponding figure reference.",
+ exported: true,
+ evidenceRefs: ["reports/rendered-manuscript-v2.pdf", "reviews/thread-T-manuscript-claims.md"]
+ },
+ {
+ id: "T-data-units",
+ component: "data",
+ status: "resolved",
+ decision: "changed",
+ reviewerRole: "data-steward",
+ reviewerId: "reviewer-b",
+ anchor: { path: "data/observations.csv", line: 1, commit: "0e5fbb1" },
+ resolutionRationale: "The dataset header now states SI units and links to the source instrument calibration sheet.",
+ exported: true,
+ evidenceRefs: ["data/README.md", "reports/data-dictionary.json"]
+ },
+ {
+ id: "T-code-seed",
+ component: "code",
+ status: "resolved",
+ decision: "changed",
+ reviewerRole: "reproducibility-reviewer",
+ reviewerId: "reviewer-c",
+ anchor: { path: "code/analysis.py", line: 42, commit: "0e5fbb1" },
+ resolutionRationale: "The analysis entry point now sets a deterministic seed and exports run metadata.",
+ exported: true,
+ evidenceRefs: ["reports/replay-log.json"]
+ },
+ {
+ id: "T-notebook-output",
+ component: "notebook",
+ status: "resolved",
+ decision: "accepted",
+ reviewerRole: "reproducibility-reviewer",
+ reviewerId: "reviewer-c",
+ anchor: { path: "notebooks/replay.ipynb", line: 12, commit: "0e5fbb1" },
+ resolutionRationale: "Notebook output hashes match the exported result bundle after the data-unit correction.",
+ exported: true,
+ evidenceRefs: ["reports/notebook-output-hashes.json"]
+ },
+ {
+ id: "T-metadata-doi",
+ component: "metadata",
+ status: "resolved",
+ decision: "accepted",
+ reviewerRole: "metadata-curator",
+ reviewerId: "reviewer-d",
+ anchor: { path: "metadata.json", line: 1, commit: "0e5fbb1" },
+ resolutionRationale: "DataCite creator, funder, and relatedIdentifier entries now match the release manifest.",
+ exported: true,
+ evidenceRefs: ["metadata.json", "reports/datacite-preview.json"]
+ }
+ ]
+ }
+ ]
+};
+
+const riskyPacket = {
+ id: "packet-risky-review-decisions",
+ repositoryComponents: [
+ { type: "manuscript", path: "manuscript/main.md" },
+ { type: "data", path: "data/patient-observations.csv" },
+ { type: "code", path: "code/analysis.py" },
+ { type: "notebook", path: "notebooks/replay.ipynb" },
+ { type: "metadata", path: "metadata.json" }
+ ],
+ releaseCandidate: {
+ tag: "v2.2-public-export",
+ exportManifest: {
+ doi: "10.5555/scibase.review.risky",
+ bundleHash: "sha256:risky"
+ }
+ },
+ mergeRequests: [
+ {
+ id: "MR-317",
+ title: "Prepare public export after restricted data review",
+ changedComponents: ["manuscript", "data", "code", "notebook", "metadata"],
+ reviewThreads: [
+ {
+ id: "T-private-note",
+ component: "data",
+ status: "resolved",
+ decision: "deferred",
+ reviewerRole: "data-steward",
+ reviewerId: "reviewer-z",
+ anchor: { path: "data/patient-observations.csv", line: 24, commit: "feedbee" },
+ resolutionRationale: "Data row issue discussed in private.",
+ containsPrivateNote: true,
+ redactedForExport: false,
+ exported: true,
+ evidenceRefs: ["reviews/private-note.md"]
+ },
+ {
+ id: "T-code-open",
+ component: "code",
+ status: "open",
+ decision: "unspecified",
+ reviewerRole: "maintainer",
+ reviewerId: "reviewer-c",
+ anchor: { path: "code/analysis.py", line: 88, commit: "feedbee" },
+ resolutionRationale: "",
+ exported: false,
+ evidenceRefs: []
+ },
+ {
+ id: "T-notebook-role",
+ component: "notebook",
+ status: "resolved",
+ decision: "accepted",
+ reviewerRole: "viewer",
+ reviewerId: "reviewer-q",
+ anchor: { path: "notebooks/replay.ipynb", line: 9 },
+ resolutionRationale: "Looks fine",
+ exported: true,
+ evidenceRefs: []
+ },
+ {
+ id: "T-metadata-missing-export",
+ component: "metadata",
+ status: "resolved",
+ decision: "changed",
+ reviewerRole: "metadata-curator",
+ reviewerId: "reviewer-d",
+ anchor: { path: "metadata.json", line: 1, commit: "feedbee" },
+ resolutionRationale: "Added related identifiers for the cited dataset version.",
+ exported: false,
+ evidenceRefs: ["metadata.json"]
+ }
+ ]
+ }
+ ]
+};
+
+module.exports = {
+ cleanPacket,
+ riskyPacket
+};
diff --git a/repository-review-decision-provenance-guard/test.js b/repository-review-decision-provenance-guard/test.js
new file mode 100644
index 00000000..d5ca7e02
--- /dev/null
+++ b/repository-review-decision-provenance-guard/test.js
@@ -0,0 +1,36 @@
+"use strict";
+
+const assert = require("node:assert/strict");
+const {
+ evaluateReviewDecisionProvenance,
+ renderMarkdownReport,
+ renderSvgSummary
+} = require("./index");
+const { cleanPacket, riskyPacket } = require("./sample-data");
+
+const clean = evaluateReviewDecisionProvenance(cleanPacket, { now: "2026-06-01T10:35:00.000Z" });
+assert.equal(clean.status, "READY");
+assert.equal(clean.findings.length, 0);
+assert.equal(clean.decisionRecords.length, 5);
+assert.deepEqual(clean.coverage.missingComponents, []);
+assert.equal(clean.manifestPatch.reviewDecisionPacket.decisionRecordCount, 5);
+
+const risky = evaluateReviewDecisionProvenance(riskyPacket, { now: "2026-06-01T10:35:00.000Z" });
+assert.equal(risky.status, "HOLD");
+assert.ok(risky.findings.some((finding) => finding.code === "PRIVATE_REVIEW_NOTE_EXPORTED"));
+assert.ok(risky.findings.some((finding) => finding.code === "THREAD_NOT_RESOLVED_FOR_EXPORT"));
+assert.ok(risky.findings.some((finding) => finding.code === "REVIEW_DECISION_PACKET_NOT_LINKED"));
+assert.ok(risky.findings.some((finding) => finding.code === "REVIEWER_ROLE_NOT_ELIGIBLE_FOR_COMPONENT"));
+assert.ok(risky.releaseReadiness.privateLeakRecords.includes("T-private-note"));
+
+const markdown = renderMarkdownReport(risky, riskyPacket);
+assert.match(markdown, /Repository Review-Decision Provenance Guard/);
+assert.match(markdown, /PRIVATE_REVIEW_NOTE_EXPORTED/);
+
+const svg = renderSvgSummary(risky);
+assert.match(svg, /