From d0e9cc76f2eb114ed63d398ee0a0185d64bff852 Mon Sep 17 00:00:00 2001 From: Dotta <34892728+cryppadotta@users.noreply.github.com> Date: Wed, 6 May 2026 09:00:54 -0500 Subject: [PATCH] Show workspace changes and stale notices in issue threads (#5356) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - The issue thread is the operator's durable audit trail for what changed and why > - Workspace changes and stale disposition notices need to be visible in that same timeline without noisy or misleading rendering > - The local branch already contained backend activity details, timeline conversion, and UI rendering work for those events > - This pull request isolates the issue-thread activity work into a standalone branch against `origin/master` > - The benefit is a focused audit-trail PR that can merge independently of the sidebar/operator UI polish branch ## What Changed - Adds readable workspace-change activity details to issue update activity events. - Surfaces workspace-change events in issue chat/timeline rendering. - Makes the existing issue comment migration idempotent. - Folds and renders stale disposition notices inline so they match activity-log styling and spacing. - Adds focused route, timeline, and issue-thread system notice coverage. ## Verification - `pnpm install --frozen-lockfile` - `pnpm exec vitest run server/src/__tests__/issue-activity-events-routes.test.ts ui/src/lib/issue-timeline-events.test.ts ui/src/components/IssueChatThreadSystemNotice.test.tsx` — 3 files passed, 22 tests passed. - Confirmed the PR changes 9 files and does not include `pnpm-lock.yaml` or `.github/workflows/*`. - `pnpm exec vitest run server/src/__tests__/issue-closed-workspace-routes.test.ts` — 1 file passed, 4 tests passed. - `pnpm exec vitest run server/src/__tests__/issue-activity-events-routes.test.ts ui/src/lib/issue-timeline-events.test.ts ui/src/components/IssueChatThreadSystemNotice.test.tsx server/src/services/recovery/successful-run-handoff.test.ts packages/shared/src/validators/issue.test.ts` — 5 files passed, 54 tests passed. - `pnpm --filter @paperclipai/shared typecheck && pnpm --filter @paperclipai/server typecheck && pnpm --filter @paperclipai/ui typecheck`. - `pnpm --filter @paperclipai/ui typecheck` after adding the Storybook screenshot fixture. - Captured Storybook screenshots for the new UI rendering paths: - Collapsed stale notice + workspace-change row: `docs/pr-screenshots/pr-5356/issue-thread-notices-collapsed.png` - Expanded stale notice details: `docs/pr-screenshots/pr-5356/issue-thread-notices-expanded.png` ### Screenshots Collapsed stale notice with workspace-change row: ![Collapsed stale notice with workspace-change row](docs/pr-screenshots/pr-5356/issue-thread-notices-collapsed.png) Expanded stale notice details: ![Expanded stale notice details](docs/pr-screenshots/pr-5356/issue-thread-notices-expanded.png) ## Risks - Moderate risk: this touches issue activity serialization and issue-thread rendering, both of which are central operator surfaces. - Migration risk is low: the only migration change makes an existing migration idempotent. - No new migrations are introduced, so there is no cross-PR migration ordering requirement. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex, GPT-5 coding agent, shell/tool-use enabled, used to split the existing branch, verify the isolated PR branch, and create this PR. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip --- .../issue-thread-notices-collapsed.png | Bin 0 -> 43721 bytes .../pr-5356/issue-thread-notices-expanded.png | Bin 0 -> 62949 bytes .../db/src/migrations/0078_white_darwin.sql | 6 +- packages/shared/src/types/issue.ts | 1 + packages/shared/src/validators/issue.test.ts | 2 + packages/shared/src/validators/issue.ts | 1 + .../issue-activity-events-routes.test.ts | 71 +++++ server/src/routes/issues.ts | 176 +++++++++-- .../recovery/successful-run-handoff.test.ts | 2 + .../recovery/successful-run-handoff.ts | 2 + ui/src/components/CommentThread.tsx | 17 +- ui/src/components/IssueChatThread.tsx | 284 +++++++++++++++++- .../IssueChatThreadSystemNotice.test.tsx | 93 +++++- ui/src/lib/issue-chat-messages.ts | 6 + ui/src/lib/issue-timeline-events.test.ts | 63 +++- ui/src/lib/issue-timeline-events.ts | 55 +++- .../stories/chat-comments.stories.tsx | 109 +++++++ 17 files changed, 852 insertions(+), 36 deletions(-) create mode 100644 docs/pr-screenshots/pr-5356/issue-thread-notices-collapsed.png create mode 100644 docs/pr-screenshots/pr-5356/issue-thread-notices-expanded.png diff --git a/docs/pr-screenshots/pr-5356/issue-thread-notices-collapsed.png b/docs/pr-screenshots/pr-5356/issue-thread-notices-collapsed.png new file mode 100644 index 0000000000000000000000000000000000000000..0dcefcc32a36280c27f9211a559d0b7a7fa95b36 GIT binary patch literal 43721 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%0D-K5j8J*!PENx_0`-n8dvA7seiGk zam4}7YPDso4|c!bH#>>DG<=$Wzj}%Fr6|*#`2of}dtWu2W62j@{{Mc(W8NTkU$5z{ z;#E&3y1ytlVs4z){=#7CTDiXxLf#w)a>Nz0u7-v$o$Y5o>GIp+v!>!-6UFA$DE>11 zm|l0H#n4G7`{+8MOZorAl=trW`|b8g)z2kvFQS9h7ykCspQ*$j>u^fYXL+)e-ZAcb zKAo$IXB^3nep+_bVUwm)QAbd|@cTNC{SvlSCD(S_7UxDy__`sH-J5^{?q+n2A^gP`ryrd_8Bj0uL zBin;Ny>y(G)}m)LpQmK&&Ce@0EWLW%>}HB^)srJ9e(YxBz8P9^+Tzb+v*(9j?frhw z`<}VrQm)_7l-d8?;acR2R<#~Q&Pu(G;|8r3ZH`kwSuPowK&DBr+SXr=5DehnW|KIUNv97MHv4&p4 zYm95{gXqKvf_s4)w zy2|>kX$y6>eLiP>dHb{2pov>8 z{dARd?mA!YO>$vNq`VGp5vnbZQ;jq{SEXRUzg+0XfeNo5albV3nV;R%Wfsc6cG&EC zR!Z(qjdrcwVsGY${5-+`=GYqJ)f02r<(>-M$lw1rV`;&)H4|c6D=*#at~lRw^=+8S z)n~>w*MHC3V{cz~*>S-l5y}6aAI7NIn?eTo&LNadG6}pol>X&U!3)|!e`Z|#YX?{O;yW&ENiQ_!Tz~MtXmQACmuX?Mby}~S++eh7dc4xQBAd)G z#{Kbg>TM>4T>mlM!S~HM>-Rm&Kh$g3J)A50f9?O-hbq5=<{-SJ(&H>W+Ly#sJZzmF zQ*<(K_uFIkfu{s*r0fm%Z8Qs+`D6OAMTbQGeSGq(Kdw1mLscQLq1U|Y|5=@ur}>-D zntgG4^!{mA^`$wQ>U>B4GJ8$=@|(MEYe$}>zPoqO)t>8?H7QTC?wz;$-Lpz6weiOv z^U`e>_I3x&ubA08^XIO@(-)4W%&Yi&cyH**y7V`%*YDqFl{!7PY~kYKw_C42%lf8K z$|#X7`v0WGUhP|2Ua3*P3g+b5KkhMJbmi;w>@^$NO5Yb~hfA$85s6wkb>sXC?upNw z`7EEz&fk})7`V#cCvalx=Dd&G7wu+FeNvI!Z~e~V)#Q-=@*9clTK1JuJ!(p&$HP-M zo3}+zsobr<|4$JYci=0#+dq~WiTO=!sI~s%d2-?@9_uV#zR5PXMNgIJ*vwH)^!L!d z9GX2p{qDAVRoPkM4_jZTZDMx6c}w^8vZqlx?&f!s{CGe3xvuxr|uf3wv_-g~{{>E!uNS6%1N-rg+AZLLzeBxPa$CCT5n zd(H1v+)SMg8uof~ul0?VOyr)IAKywR@=m^b+UkCnNo#$Z_$CvxnTu!p@`Y=v?`PA0 z?P|-KC;s%{@}P5;&*vPMudli6YtCDmW|#h`@(0JG;{L-~cXkw3+PQJv+_Hu}_M!aR zolpL+IJ3X}>Qo!{w2%+`XGg57UvK(jg3qb@+9&>WXgpEq3cCKP_)!ihE}AED)y#<4 z{Qq>XKWOBIb;q>RYp#K2?-o`4v3+Fo*wgpl&(|kSBhpk>t_$4p;K_@P$K^odDxWXb zAL3NM@bJXvzp9{99C*#|Tv!>b-ghc)Z&l&0DVJCLX;x4EuzyeHHKpw zwtii{=RlHYSZ3^bv)o%evQ}R%IP)((c=&1Dp2EsY`BQ#nJp%1V_;GPvto1L( zFE?JawQ(PPdF|4+FfBM11xToRK z<~m!?l+P4>5T&;{>hVswwH-w%AFJlg%Xx82KR#&gISu$bx*ZxeO3rV&w(+k3WUv!sWsx9wTqtjcc zByh2N^B&O1*^K$Yd;a7vwmVj~(d&R=1cqwSS`GL<0tebOxa!e(&Tc< zoT7dI|NV~S^(#HT-Sk=385>>a|7}MvH73_tO)nAob~}In79Rhr6YnY3o;}#ietG_a z%M<>zu3D3!dPp(-4ya}K%V*Eyhp$5yg(SA{312=ue~a5Xy8ZqQ;z8(lZ<_^F3>UCc~2=diUmYY{k+wV`_x z`!Q4Yu!aL?PI5ek<9vFcx9(9^QOBg=LlyLj-N+v}s>=ewKUdLAjY+IRh| zvU}C<_eMrNvp*X%d)nz68|{tQ@PaBE(H|@wq?G(w70t4@59RqS^}}W+ce(poFc1HmGbt8 zf&Kr6;@FyKjwsMR$Fpz#Jk5&p%l}+-^3UX$khJ7wp4pPG&gWE02sFaR0;2wHTXb;w zG8fjznyvM@KDh;9cE!uJVxqd&Za!!ArR{M3|4;9gi_Mi=HpfQ3?@9H&A#5bQKdRlc zC^K@q_IWOmedj+rZv1pg`|@P&-6pEsS%(Vu+P*%Oa(By`8xc{ac8(L|+dnUxo#$1n zV^@FVC+n|?CtD`3W?X$o_p{8lodtC*k5`*jhv=MdkI-v)$8|F{ma!)+5Ln6#6;?)aYxXw9fV+A-uRQo)RC;mA z&V9j~cl_`VJndpu^W%fsJ?1&tHks4DGk9M;_&lwa?ZFRsHLi)PSI>I0^2k4*le=X8 z9S@mVw>YXs(Dj<0>yMAK4?SN$ZH=zL)4Y2&ds||g=hP&DxDFsbBm33zz@6gyPdBlfzIV%o-DM|If%{kH`52FFg5LeKgDL$ zExz(_&%0f(gQ6COxjBP|zV(WBJhPbw3c2H-WVY>`5b;XO{Mk=|(@Q7Bwu-IZ^f(R{ zVn6Il53-62G~BQI{nk}1vc-0S?1EE&f=`rv^f$Qv>q%tYx}#w`Gb{aS!@e(@k+l*L zM8$u1uR#>1itK@Ura$(_#9p;p9&kQu=KD$4<=j<^`3r*2sjFUJ6Y<#7=V5*Ej{|FO z8fDk?xo34)*v2=%ub(9HLBHAP`U1!1MQ*(cA73o)KWF>>PVKKR3%`B+^?LpMx?e9# zgLbcI3}9QLa$|G)d4K!AU(OhxKU3wrNow-N#qPyZ1Z$^9=UF!00hPsnLYM5iy3||z z+v*?b^FtK)&m=tzd6r{a9h9s%@v6oBkME}j3;BAzmwWJkKZ})?s^YBk#^-HXL#m5D z3S~^4`t9xQ?U|R=K$E1-&W1bh=`CC}E${BGt40%B-{05U`nvdk`OTEc^>yEiZ2ixN z%zo;fx-_ah(`%B-$`X;+NplWeRl9$+e%+d)bN^W%L`vRY96JB9@zu1SL6M--;=F&p z1D)=Z>RK^#ZF%|i&Rb7*|2jW4^xV(u?-|5vXM}9`o-AeC_x#eHQqU=Kl~+FfK9IKk zmineYUvDhp`Tx=SfUAt!)wh?H6b1ZPKh0thHO?S2`@Y zZ_WwW~_`|y4CU>$MA6sf~wu{L!jn3X5^w2`@SfA|eRiUfDy}fOo zd&>kAF&hP|)cxlC`2Bvr`3tEy-lF(xZ`b~hkvtzM>6umXW5L5eN~I6B<=)ipW9zv zUfw>-Wyz$#nKt}^T#qNcx^ra;Xzj(S_@ig1&g>7H_AFlvw0?4u)UHR*PMvYz9K-o? zy(DO%@T9c%U+1Tu)Qo(`sQ35%2Jrb$rY>LSYflc=nv}UiWaq6?h_aG-x z&C>OHC--1Nvv;}%$cQW%FWvlqp^SQS7lM|NtSr>nx+fE|klQ3Wf^i#o^_6GpL9Pvu z<=$G{VGWR#?Lmk&u4bfM0Hj1ROtF+k*;~>mzPyQR^w-G)9_k1=P7hWcU9Pwn43#JR5x_n zfet@X@$7Y4`Sfhpq$uh2O(3r?aa(-lQ(9`soBX|-AkOX$4J=AsXQ{m?>HoWl5cg-T z>6)Znd^R%jOVxU)$ds-b+MCZs2BM4n?5}R{PJtYxX(6HtI*v>JJHzx7NZ$GSB3|^t zBq=Y@GJdJ{NvCFm4lB%p1*}$n+DZoX^%L|?K@RGA9Pnk&%%^e>o)}cNmIN+?#A*AY z=f04o#VS`pCWwB_QeC}%sR3jQh0H5^@3h)2M)Rhu**EPF)aDicb!L9O_~t&7tVlL^ z@z2V_75`&qrk{KBoq_%6EV$0_XER}|tv65q&Jb=0mGOEZ_h3nk>5U{`$O3V`uk*Dp zFAG^_i*_bx>a8hnzB8ytg4TFUQn~7OF?+w`x9SGyn)*pui(hQLzrYCOca@bqIM>pz zSaJTo^17Sv#UcJ(^eFA*8F%f;_jzNp9)t8QXD%yF*@VJbqs3<5UF5y`^!F+PC7RXek(uAnx zuH9m>yGj%}w&vg8mwI}dZ?J^o2ZM?2GZwNLRxF(wCS{g$qg}r42WVTjlu5?IRT6VTuW6C(t;O#B_x4u1Z;cS~PghK=xtThB>D^0dFD@@Xf5}^4 zHgsuJ_N3=ejdXWBXj(q6>Q!9z+tOz<)7Ndi76o=yy;kdw$|28o5MHHP>T|CMC&70fX z^Fz38Z21mE+J3zfeBSnZjLGloD%0ovPC+9(Af$ygzZCWrOav8;_>P z*Zq98dVR$&&?u-8Xsg?Ki^n~gmzQnS{eHjReq-g66B9uP5e^`YdB1OEufJ#kIw?tS_nS-W5q2{NWJyXDyrB+qv6QPqE9_95A{bTONDpEod2J zaryn)a=EC&qoOy@#Ml2djq|%T>%*eV)l$!HR=?j1+RDD_*B)7&nbQ}u?)&kGd(~fN zcD^U7YJPKOT+2IiK*;Xb3*}=s8COWO|J;5vZT9zj)%~5;?{*|F_nTX>SaP{x=G7;D zhpN5m;?n1qX8b>I|KG+(#vp-V?Uq-oR$o#8Eg|<$RC;eJ44TI`n`W7L095D9I{RYT zHKU2GdL=7WeYFq#cUUzud)>}ep;uDV<^?4rfR^NYxPvD8{{4Qx|HYzip{s3tvZqRn ze<-Xp&Yu9jbOJ*qM3bBWlYoec)5H&dsp{twR1y}d1WN8GMZuPIik4x44l z?-cUed|B*STX%1IX?)q83HTmZgcD=G=+2Rv2MMYBg76=3^4w*P}vf!K( z34Zsk6?hvcKTIlpWS%ZyAt`8I{_p2=_2kcTpw76-InX`>7bUC6@0(8R?f!Nv`}gGb$d&-efPs?VhOG=S;Dart^5OT#@Zt_jn8b|_5~RydiNl6LCQ$pz7>X6;)aZ8>Xx zzvi%zlTl37%cb%)9~{*-fwo46-AK7)y57U)_pjIM)qQ4M*qR;gHTQ|FlF~tauhi?y z=hw}W`nn=;@rt5$>GI8bTF25peaX~JF3jMSpOOOkF!9Xh;zTg6WjW$b(t__VlE$zMO^+{MN2@?|#? z-Q_A%_SgOOvwErWYITcD()sN5dqIbBOx~^WcjE3DpFbStxBq^p*x4>cB}PH^^`)iU zTQBT>w@W)F>cYC%-33o`r>rtI=9#E(BegDWMcCm%uwEG{lZ$6>qm*PxE-z^C^k5`pri6Xc6^vCyQLsbqmx&^fw$} zvaSAB^ZV`g$>$&KVPh>gSN@@7Q~3%5W1(3ZzkbW|X!|^FDGck``u567;oSi$;1ew` z`OKQSG~oSN8U0hYC;t&zZ24?P^CE3gn;`aw(a@q!a~?v96TprWh8 z$ENnu63?I4=O0qw-U%weJ%g5{o?_;=armV8!RF70!+Vq}XTOp^*x9ZjvVPB}Q{6h7 zP6)co6dso?|4{U>^^o_3?vAa|IU89w>aJqVTJq5DgNEqi$VP*69MK}5jMqAvEiO29 zCMDc$QOFeD;-JfQ|NnkpzmN6MNg3E!z^^Ph+n-M+8^<>(y#gIbkvH9UU*5Atmqd0L zUwAWRhv!kyHl{{)xr#R%kE^XW_dB&~RsOOGU7+I=&p8S#ocW`U>*2RQpU)rB zE4=SSjstDSzrIqS>W@@Dzs2k(^Z{N2aBFA3KSL#b{ z2OVaRzyI&IRjb!2-QV}&5H~X$PlA$Zgp${a&`F}5hM-#c&r+BF^;Qqxf0@Cpn#3g9 zI4#5X)$PP~*%RIi@3_A$Tsk%ER{s9KP6yN+1v|~}mIS9IuvSdHV6@n+S4mX3rK128 z)QasgPFAXW1h<10h_3k6u|vo5PTQ_OpH8c1KX|=vcit4P*gZ)*I;JZ|%P!rwv}cQC z+TwXXPwVe*dEeJnZ#VsD*}FTICYr8+Mu{0Rev&Qm5~p^p*dn_4pQLEQ=dX*&sLSay;ZvXZrS1l?|&*a$IdUEt9g6Vq&@CCS24XHc5D; z6KK`DiPY4rtc$h3zo|Z1&iYAAH|m4N%jvoCSu2+w+VwFnZ_7ouIr0mCfKJ|Sx71YD z-~DEjBD3+|<@4*fT5CbOmXC-UhCi#^vgu0J{-dW3geXt07qYYi9bo3ip~&aDvb!t3 z=A&y@%N6PHh(y+`LYpZyVN>thoelnWr}+G7{r!J_Jnm2T22G9LEx&JTV^a3!#=&Ox z@2{`x$NWE&E!Y4Gy3=~Qd%k$5sogUC`|I_3`*%AY=k5IpI)Jt6!GXr@cgt?4&#!gc zw&(x9-0}-!g~Z{R|ah=m{k9R?d9%wyR!fP{SGQHX3ngU zkm{ZEa^3ECr>5lZ`>FPCpN5k@Z|S|t=b-g_S9a|#e_!`(X8NadLJtppk4lXV5fYBn zVVv5O`|s=WZD-~jNoacN%x^35>iNbevr^W*Ix$f>^WNrjR^7d+zs{Q9pHuU$_WNCT z+sdn<;l2A+t&d4^-D6@ZuDNcQ8Yk6NayD9WUC=V7GpClkRSDF39klY@-QDJf7W-^x zgzkFSCf%`HWKLyllBIB_-nE}6l>1Zi6Q3uxf!Y9B99=WCKihhJ@R+?`q)p`7quUDE z4L`gb*GKs;^q8^ce$Zry6!)Gsyj49?{Az5T0Y}` z&U5$7$t#?rtp9vCJXsjLlI{I3mM80en3q0GuX?^a8> zO3HhQ(kok5H&vdl@OrlN(8;en*Ta{K8W@XDP3Qbs_^t6k#{CSsnT0_EWCl8 zTX%~9>%#(N^Q}*hibeNKmi@T+NpALj&`C_@cXySpPE}ewEx5@Obd>W-4bcZ`|M%Se za@PF*l4;(Sd1p(n356kK=ezL>Vb zU$>P-*@~x6?pkFWwCLB=Z^u6V+yq*gz5Cs+hul{uy)^&zTl*}ierj7}GI^QkgZ*c0 zzu$?hPiPZ*nzefEwe9)$z4iB+_%;82yZ!#+e!E#eg<8WKKwB)9rJtV{U-vUrmwRVv zMxW)gj{Qp`zpDKaxURqdj}WL0arAP8_5snQGfywBnyyp2iSM+|W*?2`LAo^$Tg4+( znG&~(1?f&!_y6}|ale=P-$P%bMfNWNjr#;KgU-8N#BzP5r(qqZrlehD`_pOBd99*h z9QB~Hetb?=X%^oSl>#Qozyn5YTzP1FkE3))z=yKoLVUdwPA2joe zZ3+v$cM-gk`RM|a$!V#X&pxfVw={OIP1&0p(s?@;mcG8WG#Y#Xh%PGR+J+1K?fmqx{J@bNQ)Y~=n@&T63*wC>E;4A+n) z_tnnX%ZVOd;yF3%Pqc;2MCeBU{gcx}mVi&xe(}C5JB@eSj?3LjpO@Ei*DrbsItIbB zOVlX?kayj&$4*k%Qvsi&Ne?k zCoVE_CuooCiwlaY%2%)7_e-f;N9Zh@bpD>gyYB*Bb5uPig_O9SpE@&m54*)($POCI z>oLU_^H&!=dwF^J&3s{@1LJ%6^{Y!Wn3=rugouR_vhK{d^zJZpNdo0qVr|Nth27H z0Cm5nhR1bYFPmF>?Pk$wT~N^pTAexX#;VZOpmn4LH`YWNhrN8*E-z=4;&H2sbZhXJ*_a^Dh zr)4W1G=eJN8TPMB{_T0Y?RHpPW$L+t!a4H_4so8G{@}x%^!c?nb|34N7C)P&QW^IC z)#~+p_fH<5W%K*Z=IL=&nIYHL?frHOv>!BY+APm?xwYFSsd#E>LJnT<@%r?8<>Ez2 zvTpryzSn0m<;=VJ;`}eAHAuYyE!Dmp3bqm%Y7Z+IN#%XTyOTQ#7X9T#wG* z3p&p2ald`qJlXO)6Xl+WhQ|md6;C-e?aRNHk)Z7h%;MP&j0`CxqV=0 z#)r@6?d?~oNlg}JH03y;(&%A&^rduL{+^F+Q;R2cTNFB9NlAb9_wT#i??LS(jZ&tj z@;$}R&&lZ9|NRm?V`hoh2kS>2$`-Dr2N>B4UM=yTZ#Q%Q#j^*i5A&MKl-)?2!w{7= zGc~T_VJm1vFpEZ5+?Tz%#WyMZiq6u@RD+}-Y z`|UQr-H(JnS~5DI6Fx)qEw~+A_CM~kHrhXBAB*bsZFbS1_U@FR(=!r(fQI$5B4SK< z@5UR+?KNk*Ctv@^P`Op`Uy2gHp>yeGtGkZ#Jg)Tyh2OYzU7amh_u=_@w$;au9xJ^b z`@K_rUd8{v-!+Q^A1_VVeL|_bC7tyMgP3a;D?RM~x5opDChUcnHXPn(s z?SoC0P527hqHjFe^?1L$zvGN62eWmz-AGEbvi(>2Y-YQPLtTfy(%XA`e+zl*IQsTD zIDMVH<-q0@vB$j^7ase!c0#;sn)ZrKZQYijGqZWkZae_>Nq#(NKFk#$XY+o~XAiYC zo>R0qg**-kzf63;{eImO)kSrG?%v&7^;Jpgqlj0;LNVWsbKUtZp9uJAsKifyzHY-I zt|@mo|A*{6>~e1+s1m=-D;{5CSYLE0@!!wq{KlZ8s@3P$e2Pq;d(?+L#jU5YIj@+;Nom;}C{O9BmspTcV zD!(vEE?n*Yz3*S)i8)`GoVQO^aZdaF=kxi;%P07~Yzk&S9V6A)K4<2hZ4(}BdDNwS ziBs)$n`X(={r~?}@A`2>(MWpd+zk^;?{=hr+`Qu5ro1C*O?p4oeN+TDZh3gP{kZ?a z{@-6N`ya2L6ea#6`r2(Z~x8$<#8%~vIsV849`!E0QGehx} z%gPF|rQarlPLSVa(l2!Da0-cP!cf45Ct+)3}kkhkA z-THF#oH};B+x2>d?WDO*=MDyW>w*rl-!X~5Y}JJ1o4gfa7H1DSov7Ht(>Q0dXkvE- z`{8Yq7u>iJpu@|pc&cbqgODnBdMKy#lK8M0uWSuivoO}5Mi8UJ5J0jJyEYLA9^QX7t2BAeMP3cvL98a$4t^PWSp1VnQx)uG+~$I z%UfHuEgQd_u;@&h8XC4R%GHE-^Tn_)lR#tI8dEpDXcF%Ce0k-U-QO?4YC#QLTQ3x> zdUW3Y|CvA2jD!TYy0~>jWUt>_79quG^g49+m+O{=4kGG`JW?hdtU-F*+x?4+8ZV{J z=nZ>XdRX-Fnm;Q77caW9_Lhm1f1U>`}{*c+?yDpxw7?p-?9WQYlgGlI{d*F4{rLaExRz!#BR6ajg$$$ zEZ7}qUyiXc-y_@1&cDnwBfX42OnHy~9=(k%O6gOWbtU~mkKAxwdAQy5WS8WP^b@gf zcD?D{voP@0p;EI6QZM=K|2U*Q-s5m1*)!PY$e%aNDJt8VYTLH>eB$v|w*S1w!0#|< zmy^!V7mNG(&bl5Bic*=k(Qe9)_j|v`dEI{_9l89nLf|8hl$L}!+1e+zvm7e8S~BBM zXY(@6?@L`)R?PqD;#YRz(2+fw!OK3xY@4oGBeEnnaED>zc8fP#DqbvXw@^OJ@mtZG zL-?ky=fc2OA>PlDEFX*2_sYDjd9kqFZDnxUoJ^~?TP`oUa_)?u+&^1^?8ni+9>=zB z))JXeITduA$}Q{5no{y57aSkv{RbTm%Wqyb>B+5Q=93CqK1Cj{1mo`5aum@Phk3CCBZ~n6#=u9Pb|Ir_Doe!`1742(kJgd;j;Ss zhLgo?n?_A|F zUCk-iEF}+CAD`!@{NY>c_J$j7=bqFqJi5t`f49JD!F?%x6Jyj%9KfTbmb-4wlvET5 z%I8l_REw+s`xVq6xTfBg-Q3PAE$095ZsPniyIeg#@|}5gR9*H_#hlWObB-k)PbhzC z;=AI0+sneKvz>L`+p#d2r0^!z6#V%9vrb=3n7E$%sDE|Q}3_tLqC z!F}6*Pjr_{TvGr4-^|x1Id#re8Zxgxw3Auu)k)d7Nh+oasxwUf{}Ov4Bx4r#MfT-} zON*B-aqCE$BPFX1N5edgs#Hs&M3VYmriHjZ?Bm#u=G?7FH|s@9(>K-!{kUENGSSRq0oj zYnWqmt5$q;y)vc0V!zYMZBe}iM@7S*{JfgFD)(fOWCG~oqgJt~ji6^qxz|2hEmBux@H*+|4a*-7nk$1j=2*Yoa(Ux%xzjFu zuL}57z2;_gzmMtgzTkLEoR?*e-owxz99-LT3e=P;H!0`lR(7;*c=+%(%{w@IaQ6R(>i@h=Dysp$)w17{k%1jleBjKU2C@A(#I*|@-p8Q z)`4wGJSy6|Y`nTS%5PsvRgV_>kl_$!oszK4_TM^%p!jR|O=FACnsQpssZDrR@V)fx z1wIptm7SqcSu2-rdUx1G^ImJO*{v6Qzu!AuGsP4%zvkSckhIY*F`Xk?L`YM(ldG^) zuhYDBvto|Zk2s}!n$wQWJ8+qE%SYMe4=Z)nYtgU>#Vt0hiPyS#Rh~^;U-9_H{Len1Q;%a(uO+cY1v3wTcRgDasGdhKTFcA$;CVN;o3fo}bisy*D_ z`~CIx^#`I~Z`PZZto5fTddGU}Ge1ESz;-#Zza4f6>?(L;0~!QLY?nP&czoZ%=Vul; zHW#hcU45kF+}Vx7M$a!SbdH?A=Jm;4pf;~ftNl&&^vmnlcu!hV6>tZ%isMUlgLnEK zLFJhjcJ?zH)L;7S&6cog>l5Bn?q8;!v~gJ+oxj)g^`d!IuU7v3et*Avzud!1PbE4# z^nUB@epB>r=krOWFMT&@SiRWuaZ2!``B7)PjQqa8yW7d~QKT!pWpx0*iqM;Vzu#S% z@bXsB$%Q9m{=W;H^6S~XAKKlY{_qt{eX(rwq&4>IPj?4>Q5HNJ&v#_8`TZK>=p$AE zZppGUoD{p4IL6P>Y`Iq<{c^!(0i!dZgL`T?wQf(b?OY$SIa}aTlFobs=Q1VJr<|AO zxZFsaoqI_4RAz-(pza%nJ=fnzFFfEE2RdS+-{zCYJ=3fW=64F5r$|57^vDC9%h0)~ z{{O!vF@0*&jvcCee4{%<_|%mxiuqnQzDN96xBH#cJ`vrRoxYbIgwF7=TPS%rTx?_Z z#gd1|S4a949Y4{0N&lsKlaPOi~PQ?y;OX0Il4EsKv()PTo)2L+d z+5X3a=Ib%VXAd+oFTP^#-R^QW+JVXDK?5`BYOH|IPd+R;sK5WuC(tFMp`gRDHpOL} zwG{bQIq%#<&%iCK*iP(=5IfY#aIIx>Sijw`43Ar&Q?`C;&iVb|ans+0QS%Sih~izFR+lc!lqJ)mu~Dx4PNDjo0;fM3vEP1Z-CX0}x%6!g=<=b?iK~h@+5^`f zoj&FHrh8SdFD8AzSDhbH`{d87bt=6Fs%4eL9$(^xv zYw^n~D}(2G-+9f;*t6H;X8akc+sj4U$(4Y|JX+?-EGqK@0(6v z-1G4Cy2%>c#W~AjIp?TdPfwGZ*$uh|ZvDJ%GT(Za`Od!fBP{w`{kKJ1rk>xrZAz8FpUqqO3d_v=~L*;3b4 zdF&5-)po|fY5m^|&iu7+w_cyrpLRAm()wd$`Krj3`W=0*oc@)#oUPgS^I7+Pon5=K zHcX0?R($*IvBp)VNM^Td%f;u_Exz*hNFZm&ei5xqC$EQ>x$Sw3`8S@)_nkj&($AQ# zMS-DNA8yXrd1KA;1BYC11^TAm{a?H`_nOGQw6wG|=3c!z{ouCT+tVz<^S_G~{p%5!YWnR8|EcWOC!iBgHCIgLD%e<* zIuEoWG3Rag(zIu1W|sa4)|e^2;9Quiy=?NYsVbg9f3@fSkvJa-Spyit#sgZ^IBChI zfWWN%bx%SsfX32sU&x%{Iz=&@bsOwTN$;0WPCc2T^PS=Ossm!sEzUt&=X8i#YC5e{f3<0=E)no@@if2J?0oI z(?rlrMUZny*4FzvpxQ71?An5qknpXCS8it>P9zhzkS2Jl{PS6kA1FA-l<%PUqpy>#q7dUq8r9Pu?)_x;1U@h4*HcLRRNBYUQmvW18-&d8K+Y^cwGg zqi3h?eD>$K?SZAna-a~IB(>(zvr{qs{~pUdxFm^el>7fx4AURLf+^wBpVdq;P0k=a zL5D+|JdM3sE#Ai6NrJBB3s9Y;z4<=#9GPWzyQ9~tt~g}|Not7ylP_Z_Pb@Eg$zrIpPvI=a8mR6toYfq zlj5_I`z&u9$h*6%wVh*{&6Rz%zgKKAo$_^xif54E#n?L)k9(uHb`>~%YDIGEYnfUb`O z%?I!Q^T|8pmei>#(DLOD&;^6{>;K#8<%OOW^49tI@why{tksvh<@euST^&AS$CF9k zb^m@oFIfWG3R#hKILKzC>FK2q_2b9eXm z?f2_`gAPSxi+W@t`gm%1+|Pdde>>jodj05S?Cvs9Ev2{j%cbx4>*rVUSv+8Pw(!TF zd)4n_3y+EltNX>2-z^25cDnhz9mtSp2G0Wafc6m!c(|5;=KTu}vRbND-UYP`eAG4a zHl0*k^YeOq{n?_3)jwJ-vP(}Wwi}#Z*eNgvou;pzy$Oak)1#Ju>$mWZv&jr}aMzJl+Dnoq4P3^SR}5ezqT8G%zx+SdqW+sMyXp?Va;L+t9ev8|TdV z{c81kxrzsk<@YMp*PJxFopacechwzGpY8f(d|o#tsa9)l%*^+44}>Jm!a$n{tX{8ij+j+^&hqDE z*}0EXZf(hAF+QXod?F-&&qp@p<@2hvI48G!d$G7*X#0tZ%x$4Z zQ}gNM996H`&kr#3tAtNp0h+L@{eE}4RL%^)C+{vUcHiODtor@+_5Rig?<~CfEgp4f zluEK0%hdn*=n@~6a8xwh=INB+6QwpsesrqOv&g$+A@udkOyiR?L3^JrM{?-9=cTN@ zu^lud{j5L!MZ0`mg6xc5=eZpc`&}w_gAQP1`VgJJxAb=I_KjCTN95iX-8PY5@RG$@ zCmnUO&lyF`KWkpz+?>8cZH{H6f~TFA>i^KNNYy1T*62!x^_ciw{`-CZ|FfT?PJVrI zMDFEY(4mg^s`Vdlan6{`Ykp_KWDd~kP1*802c69BmR$bfmG3!8#k8tqGiZL~$kInb zzczl6o9V&W`HA!Av^&yjlbBWrsb1E1>z9*tdr{vem-G7C+T}hoh18Xeis!xOPcrj5 za^=`0;h&pdls*>nne~sapmz6*Mco=UauW_s{P5@V`N?dSA$I?MB%gaNaDHC(JIjA5 zep)M%kM$^~8~IJOkTLdb(F?lcsXo^wb<)!_=J#u&^LDD9?o3x;$=mbsSV+eDozJBH zsbt=-c-%X4^^w;?%AiZzj)8iyPtL9bg_g%!nRfL#1x$|LC;QvoEW4e%|Hq?lu6|lkzUYxw+?Dh8|9u*(w%;vVoFXMu*K>2l zqkHxL|E7feOJPegDExI&ef|^wSC?{>O>cwt@8>FBYnzO|N>$ut046TRGZ9It* zOZk2TTsU`s(i&aS$3M>hSugsbvGn6nabu@Ds;~4n9ubnS{UVr}V)nDg_*}xT%l`If z+f=s4PEzsgy}jr2x!a z3^XPSoezu3RDJXgw3`le$$a~gDYMMfRfDtEp0PYGQ@m#9vsodXm(w0-D6Qd>u`u{I z*;(6?dEyKSvG~Q_MW?HjUoUWM_INy{*z?4ZghRQ11XOPtI5o~v+#1GY@HDI_dB!GQjaWniqn!>Y96zY5M%rmUGLEqS_ak}7x7qyMK_$0x zMc)`Ki3!qpF4(cpUB33q)9LYkU#Dv7q+eMP_%nLaSx-IP|JkfA?+k>bx+)_$W*1zK zEpL6P^S_zj?#1ox`JiPGMhGTduU#%#-In{Ex4R{rKAiyZ>e0u^!2fU!GL-FzmTocKc)HL7^K0OqKKPYB>(P z-}gH&B-DGE>ldwfZA;raJ>^XCrAOw6f!YOMp3SR%_waB#zqFaoAJ3OdgO~dSFY{Sg z@4=Y%=f}sE=w01AcTEp`wcPpTzMz_}-S@xTj$~p@tlIGTjPd#W{eQ!rW(kz9WNx3W zB&k{TtG8>e>SnuH|GKSrW^Fh+>)we1wP#x{`|bYyZg)G6q|ma0IRXun4R!up5`P+_ zHLYE?EMiAqBUAD%)4zdQ1x1ryZo8ew?dyKY`!}bm*FK)=udhVAR?Aex?kYLCN1#dF zXrk%ESc^|5l+Ev!Twc9?pOwv#LWy+;IllAPe7{@1M@;p?QL$*9x?hXB^`!P)?hap` zRTa!-_+v(L-^0kvnKq}s1*hGw`OGWNu4BAL{kZ*YSH6C(!<#i02H)Zpx0zhcd0@|% zt=HqC6TGj7=(fZi+u=T|4K+jeGV`iGE z+A=)%S_lfD9%=KwEuIp)-|c#Bp|Y#|{l546e)q{*e|x=te_xQLfmiLsPnZ4eW%DB5 z-rsM}IO*@a%N{e+YuR|EwpF2-S@9m48oB*Ae(0ShWyNv#>%YN3Ni@rsA zPfi9^yO-JdWKPUqKBtIF+UWhB&!5)F*Zo+SdwbhQ?u{vYN55W=ufMV)@ZqzThR*f- zerc^f?%gA2TXj9Q{Ao$}t=dDCAGD?%1nt8Ioi^=t*XhizKnFhddPUvH>Me??pFv9y z=5Q}?vNLyeay>F7<*`3elRlnJI{9e&% z-8F1CzrNXgzE6JF&u6nM^;)x+#aBFRmD%W1^Je35tFkv12?rW%zu%dxQGGQuyfuI0 zVlm&=nKvy?c+S>oUon&Cz?|bsTAR0}&nY}sb~|_awt1jq@h`f|-`$kz&2=5L%;(nM zGd}}=$L8<-ddT#=%Y~Phm-kB;D!Ig8+jDB#8e6|anSuk1pv0Z)x)`)x7j&D&5+m`V z{CV2*xdR_HZabJ6G|OE3+lz~f%~Gu%-8^sqUuLSothrK}lKGF0bY}9mCj7asdu!@c zmP1rhSusePLF!)7tbhWykGzS?@9IfGN7IdZ@~7v zyIC_&Oq$+0olpC~QO9#U-_NFbU3R{cGzzO9u{ennYcQ@?JNQX4y|?B5sZ z)S9m$MZa=Rtzg}j(!22)Gdtgt8pfUFFPBcAm)vIw8l3?(?t(NkXZ`GTS=#Vt!q270 zTNgig87^@3QjesuMgVAiz|+rH?`$=!`SBqmsTyxZoqvt6Jr>Po9wCYeH+-wYV8&-n=|$b;stHp-YWA^QwN46j-o zD1Kb0i}{>6+-l4ae((ZlTw>)ERpahN3w!1QKR56SI$m!N!($I(cn(BL)PlDBnZ|&5 z{}aA|771RlkZ3jzb@7_{b^D9=vPTy>xAVzbfi66BZs(IeXwbvq8?`k{bm}}g+p0g` zZs!O3mcF_1@%j9Ey_&jm4v_u5(ObO^LRN78{&-w|@ug(e9e2*NSwhVK8Mfgf|77K- zYu0EV$gF0lKc?;~qu*W_eW37r&2icC^W}FyjMM2h(=1gdi#|A(7Pjq+_3QV=Dt*%r z@6dg)qk7-tzTMBQ-+>sZM)RgvF0C=iy|yMYr0Us>4}wp*oiL+ahs4m zEqkp(;z`w(4|9b4`~PX$gtVP9WJs^wym_AfN#h=_8`-OO`yd68tkoRZ$i)XDuDqBU z%W&?i+4Z9MoICCdkPY-sjCiaPw6@?%hv_+nm}c`$2lnd5)g{|5l7WS@tW`5 zd0MPm7TIeeJw2S&;{5K2_TSTx&5^x!e!~Qp%PQZ)N9@Hk-RQ9I(F>ZN z*iG4K|8)NGk8Kut+!pWVz2EWp-OoPjck|v?ESBv5H?7paqv*u1fZN-0|BAh6)4j)B zxvSn?Caw=+Pm4wqnYp?0GS1p`ufygtZU+oN{%Y0%(Ev##8efjpes8 z-Ps^2l=`?>0B=NN=C)nW{Z^Iwxq`-ivKG`8dCi={psoB@x9;@i zd%q+9|1n#m1>Uf_a$Sgdf6K=o(HE3dB^oZPmQReS_L*88bZha|*uKlJ)2m*tUwC=0 zo%OQm|D>$$zTBLQB4B&|i`vfa?W}s~*X;LS^_cjb;rc=*`x0R*s3)AB@4i5_xS~%M*H!3jjpaIBrOWG2S^++10pG)zmnQK@3Yt5=U7K@cp z#^wQWOn>?J+@G^r;jiCJqtsVdR=zR6RtnB?A}Uf@6;r-|E>2!F)26a$2@CUwc#d6f zR7HMS#vA3`u_#^-YN@idD;V3he(~NlGr7<5!~v0SN=v64J+C0zWUQ(iwMF5t-yDmJ zU%;8%QTa+shVz-uFXqf2{wHr=v0_ES`4#`yp94GaW=n(fnao>TR=Vz6Fp>Siq5IFm z)<*fxwYqxO3AEvPvEu>7XIpY^Zu;^Qi4f-uB|)Y>(_B! zi|051-PWzLQgEhWa@+p5QlEVe#E1S<^PN@kcQeSvZlF<5MTXhsN|2GaB}R!v7Pnbv z{``AB16I;XB{F>b(gunL&0yD%dp@T@9y#T*^^yPLGhV%x4AOa^a9kNBRo(*|1dN0g z*G@a{Gsh@Ri!Hl(Zmu)2j6S;YoNv2WVpC6#ph#T4EW*8(o zh15#t?RW@UAenY%2H5K+)e;TaPd^@)umAOOx#Z01cRRP=Na9xd7@0m-6jabn^6H=N zaJ~29Vt4z`XN>ReF3-Qe&$fPB-rcI_bIa|X&nfP+d^Q7gBJ!Eb8a@fp(0GOjXr5Gm-;YP8*JCd4sVp`sNPTMG^}+t% zkH?=*>&qXD-kP=b&8E|JACHPp1cm3yYdi>HUepL0$pS5R3`yG) zzCKPl7_^1oGiYrkf5BRveLo)AR(;91w1ji%-Q#lAZ&og!m!uS|ac@%lVViE9O&r0G zme>4zIz90TXeYm6(vdx%&&^)*5wx^;vbuj<$wgPt=)%6*-;>(G7t;jA8ZcZx)vdoz zVjs)v4~O~HncF)-cl-Ugoxi`;zMWV4+qLNYqy953i_>iEYJYv%;=N#Th~SJ#Mk{A< zeE@C20LRsbP$k^y|w@YI-g>aitEKm-g=R1auK%LV z=QE%yrQKEgr!EPSUFimKgNW|lFPBt{?&sI7c~W#*SA3=09(Hhhc9CA}E*D;x&iLiA zryxqNObA-axZ@avBeFH)qEeQ^tu2|tFr$`ix-eru%WB6vhrq`XEL~i9e1)4t!|JbX zl9NE?@l?*ulkA&8k>z>SxcJ$bjmgLTW|?TNvIb4;-_GA}Tl(sX$L8Me;C6M;!n89p z3@bi708Lr``ttJ6&3(1MORvY4H?oR#WaXZjVF;R?Kg6wnr(s{;>Vt+*P50{m*S^{^ zJAdELn$Ks=b8nd(0_E~8-|tm#&%Uk~bkZ2Au8m*b?`rwNRw$Jg6l%1MKq&cU_yPSI(>T6>?&ySu(7b?dsVd3#|YGe4-;4k}DQI~*;(-g~`n z_q)~W_bs|7z4V=ooIwJE=wr|(j9J<1e*SvB-n#tVpO44o&(AW=UcGi3*Uz69-Q`pN zd2F5xscX4H0|Pf+bdv^EDlJ#@_x*gf_xruyZ#JJVyOGFl^r7GW-wB@ccE59G6#x42 zamGbxR%QoA{^ymNY_#2U+ zl%%=;xP1MbO>a+Wub25Zr~F>!;*ezy*Vo0ae7A1bt5pvdt_)rtq<3z!#tpU>a%ux)SE*Hc?pxQfSq+57!o^{12Snri)WwxD6xUX$67f@);| zXh+bOmzTjOEyveRwU6GOXPa=K;X|?e-scxe`CnqK*?wN3U_RREimd|CZ%W^>ZX{C;A z{hyDm=WUXY@i2LJi|J}`q}y3leo83{`}cbOfOG6|{OoOOAbZ;0&IfT<>* zSU}?rDxN{`wiLYU%e7Z`_rp&~<)BI{be2tJ(G`a?%R+VAUtIYCDV9SsudE0RWWLxC zw)G06M}3kZ2HIm5;gvSaIo2Z?c=Gq>^Y)QfJxqhd7;oGL7yM7Z-_GB^_t&e{fhVh< zP7RN^x?f9l`dJ?Ix4E#2^tcb0&UiQ-T7doADJ%(b|DWTvzJfs6AcWIGI< z&QGhVvY5)eWlQSz_n&=ScrP4y_2BOPTiMJE41Yd-dwaX{y`EhBz2D#8vtJA4OmI$M zV0hrSK7PNPafR7zUSZ>XOUmEh>($S{(d4IB$!Ea8a3Eh?Ts;5Yo}WKHK3*NZ{$Kgi zFJDS3Y@R=V{(t|chlkt!=iBkx_-Hg7Uo9oPX96<=gU{LJ+Rn~d+t+X!FfcH1u65pU zhm(haVMBoTlEZTtxMLX@8n()21wEB(Uee3Rz|fW=BRZdXO(P>i!;UmDQRa#Z2N)O} zBFsAGF!3@lI5?Fs+59Oy`}otROA!(b3>F5-&w4g){-W<3YTnSkI{we2^8cTopI`2O z_AnzuL$guZISK2}{p-a8f~^{!Khu8j=#dixGXn#A+L<|qWo+zl6-3=D6YH&)D# zv$VC9z5M<5_Wb7E_3H%>oIa-d>GARY$&)7+9<{0blro2tpMinl_k&NLK0P{heSN%m zyZ!7}x*QMgAG;P?W3#Sb`a5TYIRnFiD}Syxe6MV`)20`vThK2t%VqIGw-EmKAJ6axl^0{>m* z>?|Mj&P?CL!^XhyPo=ipjp6;dOPj78W?;Cmq(Z)%q0XdAf`LIvMrbJ zWJuVbaaU9Lz~r*uv)$#G84kSjyz^JJ;rk48IR=IUe>q7DL885gKYku?25x3x;9~Q1 zaSXu`S5&fTD3~rIFDna53~LLAk+0)`2OSn zzd)JmMz;6F*8)1Agg=e>MqCC11H-qwz0z}h!TDl`Wy9GO$I39)!y5^tXl89;f@dw1H%E6yY*Ss-&rbp^|=@r7_2u0 ztym{;pqY)0fg!;t%=gOF`OG=iCJYP={n>k8zB$EM^LO@1kRfF+6{RO%=Xvn@egqpc z1H*<~{{8CZTdNzke^Fv!V0a)V&3T^Pw?Vw83FNFc-g7bL!l2A+P&k|Cf$MZ>R%Ql< z4+6J$+$_@;PEZB8Luy;qi7RE>9kde}7#QAdnSFTbU1m_WKGer_Lj#n{Rjun*y<4Y# zz)OOGK_Tz>-Q5Y?Aa`;0iyiPjny~Y##WW&I~z~JfX=d#Wzp$P!({vdMz literal 0 HcmV?d00001 diff --git a/docs/pr-screenshots/pr-5356/issue-thread-notices-expanded.png b/docs/pr-screenshots/pr-5356/issue-thread-notices-expanded.png new file mode 100644 index 0000000000000000000000000000000000000000..9213270e72d215113d6656938e3ac7d4ec276fc2 GIT binary patch literal 62949 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 statement-breakpoint -ALTER TABLE "issue_comments" ADD COLUMN "presentation" jsonb;--> statement-breakpoint -ALTER TABLE "issue_comments" ADD COLUMN "metadata" jsonb; \ No newline at end of file +ALTER TABLE "issue_comments" ADD COLUMN IF NOT EXISTS "author_type" text;--> statement-breakpoint +ALTER TABLE "issue_comments" ADD COLUMN IF NOT EXISTS "presentation" jsonb;--> statement-breakpoint +ALTER TABLE "issue_comments" ADD COLUMN IF NOT EXISTS "metadata" jsonb; diff --git a/packages/shared/src/types/issue.ts b/packages/shared/src/types/issue.ts index 59d9f169..2f09515a 100644 --- a/packages/shared/src/types/issue.ts +++ b/packages/shared/src/types/issue.ts @@ -434,6 +434,7 @@ export interface IssueCommentMetadataSection { export interface IssueCommentMetadata { version: 1; + sourceRunId?: string | null; sections: IssueCommentMetadataSection[]; } diff --git a/packages/shared/src/validators/issue.test.ts b/packages/shared/src/validators/issue.test.ts index ad5fbc53..a8d26845 100644 --- a/packages/shared/src/validators/issue.test.ts +++ b/packages/shared/src/validators/issue.test.ts @@ -65,6 +65,7 @@ describe("issue validators", () => { }, metadata: { version: 1, + sourceRunId: "11111111-1111-4111-8111-111111111111", sections: [ { title: "Evidence", @@ -79,6 +80,7 @@ describe("issue validators", () => { }); expect(parsed.presentation?.detailsDefaultOpen).toBe(false); + expect(parsed.metadata?.sourceRunId).toBe("11111111-1111-4111-8111-111111111111"); expect(parsed.metadata?.sections[0]?.rows).toHaveLength(3); }); diff --git a/packages/shared/src/validators/issue.ts b/packages/shared/src/validators/issue.ts index d1f9af21..d7e26e76 100644 --- a/packages/shared/src/validators/issue.ts +++ b/packages/shared/src/validators/issue.ts @@ -318,6 +318,7 @@ export const issueCommentMetadataSectionSchema = z.object({ export const issueCommentMetadataSchema = z.object({ version: z.literal(1), + sourceRunId: z.string().uuid().nullable().optional(), sections: z.array(issueCommentMetadataSectionSchema).min(1).max(20), }).strict(); diff --git a/server/src/__tests__/issue-activity-events-routes.test.ts b/server/src/__tests__/issue-activity-events-routes.test.ts index dbd15303..14349614 100644 --- a/server/src/__tests__/issue-activity-events-routes.test.ts +++ b/server/src/__tests__/issue-activity-events-routes.test.ts @@ -1,5 +1,6 @@ import express from "express"; import request from "supertest"; +import { getTableName } from "drizzle-orm"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { normalizeIssueExecutionPolicy } from "../services/issue-execution-policy.ts"; @@ -266,6 +267,76 @@ describe("issue activity event routes", () => { }); }, 15_000); + it("logs readable workspace change activity details for issue updates", async () => { + const previousProjectWorkspaceId = "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa"; + const nextExecutionWorkspaceId = "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb"; + const issue = { + ...makeIssue(), + projectId: "cccccccc-cccc-4ccc-8ccc-cccccccccccc", + projectWorkspaceId: previousProjectWorkspaceId, + executionWorkspaceId: null, + executionWorkspacePreference: "shared_workspace", + executionWorkspaceSettings: { mode: "shared_workspace" }, + }; + mockIssueService.getById.mockResolvedValue(issue); + mockIssueService.update.mockImplementation(async (_id: string, patch: Record) => ({ + ...issue, + ...patch, + updatedAt: new Date(), + })); + + const dbMock = { + select: vi.fn(() => ({ + from: (table: unknown) => ({ + where: async () => { + const tableName = getTableName(table as Parameters[0]); + if (tableName === "project_workspaces") { + return [{ id: previousProjectWorkspaceId, name: "Main workspace" }]; + } + if (tableName === "execution_workspaces") { + return [{ id: nextExecutionWorkspaceId, name: "Feature workspace" }]; + } + return []; + }, + }), + })), + }; + + const res = await request(await createApp(dbMock)) + .patch(`/api/issues/${issue.id}`) + .send({ executionWorkspaceId: nextExecutionWorkspaceId }); + + expect(res.status).toBe(200); + await vi.waitFor(() => { + expect(mockLogActivity).toHaveBeenCalledWith( + expect.anything(), + expect.objectContaining({ + action: "issue.updated", + details: expect.objectContaining({ + executionWorkspaceId: nextExecutionWorkspaceId, + workspaceChange: { + from: { + label: "Main workspace", + projectWorkspaceId: previousProjectWorkspaceId, + executionWorkspaceId: null, + mode: "shared_workspace", + }, + to: { + label: "Feature workspace", + projectWorkspaceId: previousProjectWorkspaceId, + executionWorkspaceId: nextExecutionWorkspaceId, + mode: "shared_workspace", + }, + }, + _previous: expect.objectContaining({ + executionWorkspaceId: null, + }), + }), + }), + ); + }); + }); + it("logs successful_run_handoff_resolved when an in_progress issue transitions to done with a pending required handoff", async () => { const issue = { ...makeIssue(), status: "in_progress" }; mockIssueService.getById.mockResolvedValue(issue); diff --git a/server/src/routes/issues.ts b/server/src/routes/issues.ts index 69d206d9..4e568c15 100644 --- a/server/src/routes/issues.ts +++ b/server/src/routes/issues.ts @@ -4,7 +4,7 @@ import multer from "multer"; import { z } from "zod"; import { and, desc, eq, inArray } from "drizzle-orm"; import type { Db } from "@paperclipai/db"; -import { activityLog, issueExecutionDecisions } from "@paperclipai/db"; +import { activityLog, executionWorkspaces, issueExecutionDecisions, projectWorkspaces } from "@paperclipai/db"; import { addIssueCommentSchema, acceptIssueThreadInteractionSchema, @@ -96,6 +96,7 @@ import { redactIssueMonitorExternalRef, setIssueExecutionPolicyMonitorScheduledBy, } from "../services/issue-execution-policy.js"; +import { parseIssueExecutionWorkspaceSettings } from "../services/execution-workspace-policy.js"; import type { PluginWorkerManager } from "../services/plugin-worker-manager.js"; const MAX_ISSUE_COMMENT_LIMIT = 500; @@ -142,10 +143,148 @@ const SUCCESSFUL_RUN_HANDOFF_ACTIONS = [ "issue.successful_run_handoff_escalated", ] as const; +const ISSUE_WORKSPACE_AUDIT_FIELDS = new Set([ + "projectWorkspaceId", + "executionWorkspaceId", + "executionWorkspacePreference", + "executionWorkspaceSettings", +]); + function readNonEmptyString(value: unknown): string | null { return typeof value === "string" && value.trim().length > 0 ? value.trim() : null; } +function hasIssueWorkspaceAuditChange(previous: Record) { + return Object.keys(previous).some((key) => ISSUE_WORKSPACE_AUDIT_FIELDS.has(key)); +} + +function labelIssueWorkspaceMode(mode: string | null) { + switch (mode) { + case "shared_workspace": + return "Project default"; + case "isolated_workspace": + return "New isolated workspace"; + case "operator_branch": + return "Operator branch"; + case "reuse_existing": + return "Reuse existing workspace"; + case "agent_default": + return "Agent default"; + case "inherit": + return "Inherited workspace"; + default: + return "No workspace"; + } +} + +type IssueWorkspaceAuditInput = { + projectWorkspaceId?: string | null; + executionWorkspaceId?: string | null; + executionWorkspacePreference?: string | null; + executionWorkspaceSettings?: unknown; +}; + +type WorkspaceNameMaps = { + projectWorkspaceNames: Map; + executionWorkspaceNames: Map; +}; + +function emptyWorkspaceNameMaps(): WorkspaceNameMaps { + return { + projectWorkspaceNames: new Map(), + executionWorkspaceNames: new Map(), + }; +} + +function summarizeIssueWorkspaceForActivity( + issue: IssueWorkspaceAuditInput, + names: WorkspaceNameMaps, +) { + const settings = parseIssueExecutionWorkspaceSettings(issue.executionWorkspaceSettings); + const mode = settings?.mode ?? issue.executionWorkspacePreference ?? null; + const executionWorkspaceId = issue.executionWorkspaceId ?? null; + const projectWorkspaceId = issue.projectWorkspaceId ?? null; + + const label = (() => { + if (executionWorkspaceId) { + return names.executionWorkspaceNames.get(executionWorkspaceId) ?? `Workspace ${executionWorkspaceId.slice(0, 8)}`; + } + if (projectWorkspaceId) { + return names.projectWorkspaceNames.get(projectWorkspaceId) ?? `Workspace ${projectWorkspaceId.slice(0, 8)}`; + } + return labelIssueWorkspaceMode(mode); + })(); + + return { + label, + projectWorkspaceId, + executionWorkspaceId, + mode, + }; +} + +async function buildIssueWorkspaceChangeActivityDetails( + db: Db, + companyId: string, + previousIssue: IssueWorkspaceAuditInput, + nextIssue: IssueWorkspaceAuditInput, +) { + const projectWorkspaceIds = [ + previousIssue.projectWorkspaceId, + nextIssue.projectWorkspaceId, + ].filter((value): value is string => typeof value === "string" && value.length > 0); + const executionWorkspaceIds = [ + previousIssue.executionWorkspaceId, + nextIssue.executionWorkspaceId, + ].filter((value): value is string => typeof value === "string" && value.length > 0); + + const [projectRows, executionRows] = await Promise.all([ + projectWorkspaceIds.length > 0 + ? db + .select({ id: projectWorkspaces.id, name: projectWorkspaces.name }) + .from(projectWorkspaces) + .where(and(eq(projectWorkspaces.companyId, companyId), inArray(projectWorkspaces.id, projectWorkspaceIds))) + : Promise.resolve([]), + executionWorkspaceIds.length > 0 + ? db + .select({ id: executionWorkspaces.id, name: executionWorkspaces.name }) + .from(executionWorkspaces) + .where(and(eq(executionWorkspaces.companyId, companyId), inArray(executionWorkspaces.id, executionWorkspaceIds))) + : Promise.resolve([]), + ]); + + const names: WorkspaceNameMaps = { + projectWorkspaceNames: new Map(projectRows.map((row) => [row.id, row.name])), + executionWorkspaceNames: new Map(executionRows.map((row) => [row.id, row.name])), + }; + + return { + from: summarizeIssueWorkspaceForActivity(previousIssue, names), + to: summarizeIssueWorkspaceForActivity(nextIssue, names), + }; +} + +function hasExecutionParticipant(value: unknown) { + const state = parseIssueExecutionState(value); + if (!state || state.status !== "pending") return false; + const participant = state.currentParticipant; + if (!participant) return false; + if (participant.type === "agent") return Boolean(participant.agentId); + if (participant.type === "user") return Boolean(participant.userId); + return false; +} + +function hasScheduledMonitor(input: { + existingMonitorNextCheckAt?: Date | null; + patchMonitorNextCheckAt?: unknown; + executionPolicy?: unknown; +}) { + if (input.patchMonitorNextCheckAt instanceof Date && !Number.isNaN(input.patchMonitorNextCheckAt.getTime())) return true; + if (input.patchMonitorNextCheckAt === undefined && input.existingMonitorNextCheckAt) return true; + const policy = normalizeIssueExecutionPolicy(input.executionPolicy ?? null); + return Boolean(policy?.monitor?.nextCheckAt); +} + function successfulRunHandoffStateFromActivity(row: { action: string; agentId: string | null; @@ -236,27 +375,6 @@ const INVALID_AGENT_IN_REVIEW_DISPOSITION_MESSAGE = "link or request a pending approval, assign a human reviewer with assigneeUserId, set a typed executionState.currentParticipant through an execution policy, " + "or schedule an issue monitor for an external review/check. After creating one of those review paths, retry the status update."; -function hasExecutionParticipant(value: unknown) { - const state = parseIssueExecutionState(value); - if (!state || state.status !== "pending") return false; - const participant = state.currentParticipant; - if (!participant) return false; - if (participant.type === "agent") return Boolean(participant.agentId); - if (participant.type === "user") return Boolean(participant.userId); - return false; -} - -function hasScheduledMonitor(input: { - existingMonitorNextCheckAt?: Date | null; - patchMonitorNextCheckAt?: unknown; - executionPolicy?: unknown; -}) { - if (input.patchMonitorNextCheckAt instanceof Date && !Number.isNaN(input.patchMonitorNextCheckAt.getTime())) return true; - if (input.patchMonitorNextCheckAt === undefined && input.existingMonitorNextCheckAt) return true; - const policy = normalizeIssueExecutionPolicy(input.executionPolicy ?? null); - return Boolean(policy?.monitor?.nextCheckAt); -} - function executionPrincipalsEqual( left: ParsedExecutionState["currentParticipant"] | null, right: ParsedExecutionState["currentParticipant"] | null, @@ -2673,6 +2791,19 @@ export function issueRoutes( } const hasFieldChanges = Object.keys(previous).length > 0; + let workspaceChange = null; + if (hasIssueWorkspaceAuditChange(previous)) { + try { + workspaceChange = await buildIssueWorkspaceChangeActivityDetails(db, issue.companyId, existing, issue); + } catch (err) { + logger.warn({ err, issueId: issue.id }, "failed to enrich issue workspace change activity details"); + const fallbackNames = emptyWorkspaceNameMaps(); + workspaceChange = { + from: summarizeIssueWorkspaceForActivity(existing, fallbackNames), + to: summarizeIssueWorkspaceForActivity(issue, fallbackNames), + }; + } + } const reopened = commentBody && effectiveMoveToTodoRequested && @@ -2697,6 +2828,7 @@ export function issueRoutes( ...(reopened ? { reopened: true, reopenedFrom: reopenFromStatus } : {}), ...(interruptedRunId ? { interruptedRunId } : {}), ...(cancelledStatusRunId ? { cancelledStatusRunId } : {}), + ...(workspaceChange ? { workspaceChange } : {}), _previous: hasFieldChanges ? previous : undefined, ...summarizeIssueReferenceActivityDetails( updateReferenceDiff diff --git a/server/src/services/recovery/successful-run-handoff.test.ts b/server/src/services/recovery/successful-run-handoff.test.ts index b5e25b74..727512f4 100644 --- a/server/src/services/recovery/successful-run-handoff.test.ts +++ b/server/src/services/recovery/successful-run-handoff.test.ts @@ -218,6 +218,7 @@ describe("successful run handoff decision", () => { title: "Missing issue disposition", detailsDefaultOpen: false, }); + expect(notice.metadata.sourceRunId).toBe("22222222-2222-4222-8222-222222222222"); expect(notice.metadata.sections).toEqual(expect.arrayContaining([ expect.objectContaining({ title: "Required action", @@ -267,6 +268,7 @@ describe("successful run handoff decision", () => { tone: "danger", detailsDefaultOpen: false, }); + expect(notice.metadata.sourceRunId).toBe("22222222-2222-4222-8222-222222222222"); expect(notice.metadata.sections).toEqual(expect.arrayContaining([ expect.objectContaining({ title: "Recovery owner", diff --git a/server/src/services/recovery/successful-run-handoff.ts b/server/src/services/recovery/successful-run-handoff.ts index 2d5b79ff..1b9bbe18 100644 --- a/server/src/services/recovery/successful-run-handoff.ts +++ b/server/src/services/recovery/successful-run-handoff.ts @@ -146,6 +146,7 @@ export function buildSuccessfulRunHandoffRequiredNotice(input: { }), metadata: { version: 1, + sourceRunId: input.run.id, sections: [ { title: "Required action", @@ -193,6 +194,7 @@ export function buildSuccessfulRunHandoffExhaustedNotice(input: { }), metadata: { version: 1, + sourceRunId: input.sourceRun?.id ?? null, sections: [ { title: "Recovery owner", diff --git a/ui/src/components/CommentThread.tsx b/ui/src/components/CommentThread.tsx index 080b3e97..e80abea7 100644 --- a/ui/src/components/CommentThread.tsx +++ b/ui/src/components/CommentThread.tsx @@ -20,7 +20,7 @@ import { OutputFeedbackButtons } from "./OutputFeedbackButtons"; import { ApprovalCard } from "./ApprovalCard"; import { AgentIcon } from "./AgentIconPicker"; import { formatAssigneeUserLabel } from "../lib/assignees"; -import type { IssueTimelineAssignee, IssueTimelineEvent } from "../lib/issue-timeline-events"; +import { formatTimelineWorkspaceLabel, type IssueTimelineAssignee, type IssueTimelineEvent } from "../lib/issue-timeline-events"; import { timeAgo } from "../lib/timeAgo"; import { cn, formatDateTime } from "../lib/utils"; import { restoreSubmittedCommentDraft } from "../lib/comment-submit-draft"; @@ -535,6 +535,21 @@ function TimelineEventCard({ ) : null} + + {event.workspaceChange ? ( +
+ + Workspace + + + {formatTimelineWorkspaceLabel(event.workspaceChange.from)} + + + + {formatTimelineWorkspaceLabel(event.workspaceChange.to)} + +
+ ) : null} ); diff --git a/ui/src/components/IssueChatThread.tsx b/ui/src/components/IssueChatThread.tsx index 792b129f..9ac472f5 100644 --- a/ui/src/components/IssueChatThread.tsx +++ b/ui/src/components/IssueChatThread.tsx @@ -16,6 +16,7 @@ import { useCallback, useContext, useEffect, + useId, useImperativeHandle, useLayoutEffect, useMemo, @@ -61,7 +62,12 @@ import type { } from "../lib/issue-thread-interactions"; import { buildIssueThreadInteractionSummary, isIssueThreadInteraction } from "../lib/issue-thread-interactions"; import { resolveIssueChatTranscriptRuns } from "../lib/issueChatTranscriptRuns"; -import type { IssueTimelineAssignee, IssueTimelineEvent } from "../lib/issue-timeline-events"; +import { + formatTimelineWorkspaceLabel, + type IssueTimelineAssignee, + type IssueTimelineEvent, + type IssueTimelineWorkspace, +} from "../lib/issue-timeline-events"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; @@ -99,8 +105,15 @@ import { isSuccessfulRunHandoffComment, isSuccessfulRunHandoffEscalationComment, } from "../lib/successful-run-handoff"; -import { SystemNotice } from "./SystemNotice"; -import { buildSystemNoticeProps } from "../lib/system-notice-comment"; +import { + SystemNotice, + type SystemNoticeMetadataRow, + type SystemNoticeMetadataSection, +} from "./SystemNotice"; +import { + buildSystemNoticeProps, + mapCommentMetadataToSystemNoticeSections, +} from "../lib/system-notice-comment"; import type { IssueCommentMetadata, IssueCommentPresentation, @@ -155,11 +168,15 @@ interface IssueChatMessageContext { onCancelInteraction?: ( interaction: AskUserQuestionsInteraction, ) => Promise | void; + issueStatus?: string; + successfulRunHandoff?: SuccessfulRunHandoffState | null; } const IssueChatCtx = createContext({ feedbackDataSharingPreference: "prompt", feedbackTermsUrl: null, + issueStatus: undefined, + successfulRunHandoff: null, }); export function resolveAssistantMessageFoldedState(args: { @@ -1968,6 +1985,227 @@ function isIssueCommentMetadata(value: unknown): value is IssueCommentMetadata { return v.version === 1 && Array.isArray(v.sections); } +function issueStatusIsTerminalDisposition(issueStatus: string | undefined) { + return issueStatus === "done" || issueStatus === "cancelled"; +} + +function sourceRunIdFromSuccessfulRunHandoffMetadata(metadata: IssueCommentMetadata | null) { + if (metadata?.sourceRunId) return metadata.sourceRunId; + const runLinks = []; + for (const section of metadata?.sections ?? []) { + for (const row of section.rows) { + if (row.type === "run_link") runLinks.push(row.runId); + } + } + return runLinks.length === 1 ? runLinks[0] : null; +} + +function isStaleSuccessfulRunHandoffNotice(input: { + bodyText: string; + issueStatus?: string; + successfulRunHandoff?: SuccessfulRunHandoffState | null; + runId?: string | null; + metadata: IssueCommentMetadata | null; +}) { + if (!isSuccessfulRunHandoffComment(input.bodyText)) return false; + + const currentHandoff = input.successfulRunHandoff ?? null; + if (currentHandoff?.state === "resolved") return true; + if (issueStatusIsTerminalDisposition(input.issueStatus)) return true; + + const noticeSourceRunId = sourceRunIdFromSuccessfulRunHandoffMetadata(input.metadata) ?? input.runId ?? null; + if ( + noticeSourceRunId + && currentHandoff?.sourceRunId + && noticeSourceRunId !== currentHandoff.sourceRunId + ) { + return true; + } + + return false; +} + +function StaleDispositionWarningMetadataRow({ row }: { row: SystemNoticeMetadataRow }) { + const label = ( + + {row.label} + + ); + const value = (() => { + switch (row.kind) { + case "text": + return {row.value}; + case "code": + return ( + + {row.value} + + ); + case "issue": { + const content = ( + <> + {row.identifier} + {row.title ? - {row.title} : null} + + ); + return row.href ? ( + + {content} + + ) : ( + {content} + ); + } + case "agent": + return row.href ? ( + + {row.name} + + ) : ( + {row.name} + ); + case "run": { + const runShort = row.runId.length > 12 ? `${row.runId.slice(0, 8)}...` : row.runId; + const content = ( + <> + + {runShort} + + {row.status ? {row.status} : null} + + ); + return row.href ? ( + + {content} + + ) : ( + {content} + ); + } + } + })(); + + return ( +
+ {label} +
{value}
+
+ ); +} + +function metadataRowKey(row: SystemNoticeMetadataRow) { + switch (row.kind) { + case "issue": + return `issue:${row.label}:${row.identifier}:${row.href ?? ""}:${row.title ?? ""}`; + case "agent": + return `agent:${row.label}:${row.name}:${row.href ?? ""}`; + case "run": + return `run:${row.label}:${row.runId}:${row.href ?? ""}:${row.status ?? ""}`; + default: + return `${row.kind}:${row.label}:${row.value}`; + } +} + +function metadataSectionKey(section: SystemNoticeMetadataSection) { + return `${section.title ?? "details"}:${section.rows.map(metadataRowKey).join("|")}`; +} + +function isNullableString(value: unknown): value is string | null { + return value === null || typeof value === "string"; +} + +function isTimelineWorkspace(value: unknown): value is IssueTimelineWorkspace { + if (!value || typeof value !== "object" || Array.isArray(value)) return false; + const workspace = value as Record; + return isNullableString(workspace.label) + && isNullableString(workspace.projectWorkspaceId) + && isNullableString(workspace.executionWorkspaceId) + && isNullableString(workspace.mode); +} + +function isTimelineWorkspaceChange(value: unknown): value is NonNullable { + if (!value || typeof value !== "object" || Array.isArray(value)) return false; + const change = value as Record; + return isTimelineWorkspace(change.from) && isTimelineWorkspace(change.to); +} + +function StaleDispositionWarningDetails({ + sections, +}: { + sections: SystemNoticeMetadataSection[]; +}) { + if (sections.length === 0) { + return
No additional details.
; + } + + return ( +
+ {sections.map((section) => ( +
+ {section.title ? ( +
+ {section.title} +
+ ) : null} +
+ {section.rows.map((row) => ( + + ))} +
+
+ ))} +
+ ); +} + +function StaleDispositionWarningRow({ + anchorId, + message, + metadata, + runAgentId, +}: { + anchorId?: string; + message: ThreadMessage; + metadata: IssueCommentMetadata | null; + runAgentId?: string | null; +}) { + const [open, setOpen] = useState(false); + const detailsId = useId(); + const sections = mapCommentMetadataToSystemNoticeSections(metadata, { runAgentId }); + + return ( +
+
+ +
+ + +
+
+
+ ); +} + function SystemNoticeCommentRow({ message, anchorId, @@ -1975,7 +2213,7 @@ function SystemNoticeCommentRow({ message: ThreadMessage; anchorId?: string; }) { - const { onImageClick, agentMap } = useContext(IssueChatCtx); + const { onImageClick, agentMap, issueStatus, successfulRunHandoff } = useContext(IssueChatCtx); const custom = message.metadata.custom as Record; const presentation = isIssueCommentPresentation(custom.presentation) ? custom.presentation : null; const commentMetadata = isIssueCommentMetadata(custom.commentMetadata) ? custom.commentMetadata : null; @@ -1987,6 +2225,13 @@ function SystemNoticeCommentRow({ .filter((p): p is { type: "text"; text: string } => p.type === "text") .map((p) => p.text) .join("\n\n"); + const staleSuccessfulRunHandoffNotice = isStaleSuccessfulRunHandoffNotice({ + bodyText, + issueStatus, + successfulRunHandoff, + runId, + metadata: commentMetadata, + }); const [copied, setCopied] = useState(false); const [copiedLink, setCopiedLink] = useState(false); @@ -2033,6 +2278,17 @@ function SystemNoticeCommentRow({ }); }; + if (staleSuccessfulRunHandoffNotice) { + return ( + + ); + } + return (
@@ -2105,6 +2361,7 @@ function IssueChatSystemMessage({ message }: { message: ThreadMessage }) { to: IssueTimelineAssignee; } : null; + const workspaceChange = isTimelineWorkspaceChange(custom.workspaceChange) ? custom.workspaceChange : null; const interaction = isIssueThreadInteraction(custom.interaction) ? custom.interaction : null; @@ -2192,6 +2449,21 @@ function IssueChatSystemMessage({ message }: { message: ThreadMessage }) {
) : null} + + {workspaceChange ? ( +
+ + Workspace + + + {formatTimelineWorkspaceLabel(workspaceChange.from)} + + + + {formatTimelineWorkspaceLabel(workspaceChange.to)} + +
+ ) : null}
); @@ -3855,6 +4127,8 @@ export function IssueChatThread({ onRejectInteraction: stableOnRejectInteraction, onSubmitInteractionAnswers: stableOnSubmitInteractionAnswers, onCancelInteraction: stableOnCancelInteraction, + issueStatus, + successfulRunHandoff, }), [ feedbackDataSharingPreference, @@ -3875,6 +4149,8 @@ export function IssueChatThread({ stableOnRejectInteraction, stableOnSubmitInteractionAnswers, stableOnCancelInteraction, + issueStatus, + successfulRunHandoff, ], ); diff --git a/ui/src/components/IssueChatThreadSystemNotice.test.tsx b/ui/src/components/IssueChatThreadSystemNotice.test.tsx index 01453d38..a1173df4 100644 --- a/ui/src/components/IssueChatThreadSystemNotice.test.tsx +++ b/ui/src/components/IssueChatThreadSystemNotice.test.tsx @@ -7,7 +7,7 @@ import { MemoryRouter } from "react-router-dom"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { IssueChatThread } from "./IssueChatThread"; import type { IssueChatComment } from "../lib/issue-chat-messages"; -import type { Agent } from "@paperclipai/shared"; +import type { Agent, SuccessfulRunHandoffState } from "@paperclipai/shared"; vi.mock("@assistant-ui/react", () => ({ AssistantRuntimeProvider: ({ children }: { children: ReactNode }) =>
{children}
, @@ -70,7 +70,14 @@ afterEach(() => { container.remove(); }); -function renderThread(comments: IssueChatComment[], agentMap?: Map) { +function renderThread( + comments: IssueChatComment[], + options: { + agentMap?: Map; + issueStatus?: string; + successfulRunHandoff?: SuccessfulRunHandoffState | null; + } = {}, +) { act(() => { root.render( @@ -82,7 +89,9 @@ function renderThread(comments: IssueChatComment[], agentMap?: Map {}} showComposer={false} enableLiveTranscriptPolling={false} - agentMap={agentMap} + agentMap={options.agentMap} + issueStatus={options.issueStatus} + successfulRunHandoff={options.successfulRunHandoff} /> , ); @@ -265,7 +274,7 @@ describe("IssueChatThread system notice routing", () => { ...baseTimestamps, }; - renderThread([comment], agentMap); + renderThread([comment], { agentMap }); const status = container.querySelector('[role="status"]'); expect(status).not.toBeNull(); @@ -395,4 +404,80 @@ describe("IssueChatThread system notice routing", () => { expect(container.querySelector('[role="status"]')).toBeNull(); expect(container.querySelector('[data-message-role="assistant"]')).not.toBeNull(); }); + + it("folds stale successful-run disposition warnings into the activity log disclosure style", () => { + const comment: IssueChatComment = { + id: "comment-stale-disposition-warning", + companyId: "company-1", + issueId: "issue-1", + authorType: "system", + authorAgentId: null, + authorUserId: null, + runId: "run-stale", + runAgentId: "agent-codex", + body: "Paperclip needs a disposition before this issue can continue.", + presentation: { + kind: "system_notice", + tone: "warning", + title: "Missing issue disposition", + detailsDefaultOpen: false, + }, + metadata: { + version: 1, + sourceRunId: "run-stale", + sections: [ + { + title: "Run evidence", + rows: [ + { type: "run_link", label: "Completed run", runId: "run-stale", title: "succeeded" }, + { type: "key_value", label: "Normalized cause", value: "successful_run_missing_state" }, + ], + }, + ], + }, + ...baseTimestamps, + }; + + renderThread([comment], { + issueStatus: "done", + successfulRunHandoff: { + state: "resolved", + required: false, + sourceRunId: "run-stale", + correctiveRunId: "run-corrective", + assigneeAgentId: "agent-codex", + detectedProgressSummary: null, + createdAt: new Date("2026-05-04T17:00:00.000Z"), + }, + }); + + const row = container.querySelector('[data-testid="stale-disposition-warning"]'); + expect(row).not.toBeNull(); + expect(row?.querySelector('span[aria-hidden="true"]')?.className).toContain("size-6"); + const toggle = row?.querySelector("button[aria-expanded]") as HTMLButtonElement; + expect(toggle.className).toContain("w-full"); + expect(toggle.className).toContain("py-0.5"); + expect(row?.querySelector('[role="status"]')).toBeNull(); + expect(row?.querySelector(".lucide-triangle-alert")).toBeNull(); + expect(row?.querySelector(".lucide-chevron-down")).not.toBeNull(); + expect(row?.querySelector('[data-testid="stale-disposition-warning-time"]')?.parentElement?.className).toContain("ml-auto"); + expect(row?.textContent).toContain("Stale disposition warning"); + expect(row?.textContent).not.toContain("This disposition warning is stale because the issue now has a newer disposition."); + expect(row?.textContent).not.toContain("Paperclip needs a disposition before this issue can continue."); + + expect(toggle.getAttribute("aria-expanded")).toBe("false"); + const detailsId = toggle.getAttribute("aria-controls"); + expect(detailsId).toBeTruthy(); + const details = detailsId ? container.ownerDocument.getElementById(detailsId) : null; + expect(details).not.toBeNull(); + expect(details?.textContent).toContain("run-stale"); + expect(details).toHaveProperty("hidden", true); + act(() => { + toggle.click(); + }); + + expect(toggle.getAttribute("aria-expanded")).toBe("true"); + expect(details).toHaveProperty("hidden", false); + expect(container.textContent).toContain("run-stale"); + }); }); diff --git a/ui/src/lib/issue-chat-messages.ts b/ui/src/lib/issue-chat-messages.ts index ef50a4e6..59d0ac90 100644 --- a/ui/src/lib/issue-chat-messages.ts +++ b/ui/src/lib/issue-chat-messages.ts @@ -455,6 +455,11 @@ function createTimelineEventMessage(args: { : (formatAssigneeUserLabel(event.assigneeChange.to.userId, currentUserId, userLabelMap) ?? "Unassigned"); lines.push(`Assignee: ${from} -> ${to}`); } + if (event.workspaceChange) { + lines.push( + `Workspace: ${event.workspaceChange.from.label ?? "none"} -> ${event.workspaceChange.to.label ?? "none"}`, + ); + } const message: ThreadSystemMessage = { id: `activity:${event.id}`, @@ -471,6 +476,7 @@ function createTimelineEventMessage(args: { actorId: event.actorId, statusChange: event.statusChange ?? null, assigneeChange: event.assigneeChange ?? null, + workspaceChange: event.workspaceChange ?? null, followUpRequested: event.followUpRequested === true, }, }, diff --git a/ui/src/lib/issue-timeline-events.test.ts b/ui/src/lib/issue-timeline-events.test.ts index 3b073954..4458be79 100644 --- a/ui/src/lib/issue-timeline-events.test.ts +++ b/ui/src/lib/issue-timeline-events.test.ts @@ -171,6 +171,67 @@ describe("extractIssueTimelineEvents", () => { ]); }); + it("extracts workspace changes from issue update activity", () => { + const events = extractIssueTimelineEvents([ + { + id: "evt-workspace", + companyId: "company-1", + actorType: "user", + actorId: "local-board", + action: "issue.updated", + entityType: "issue", + entityId: "issue-1", + agentId: null, + runId: null, + createdAt: new Date("2026-03-31T12:01:00.000Z"), + details: { + projectWorkspaceId: "workspace-2", + workspaceChange: { + from: { + label: "Main workspace", + projectWorkspaceId: "workspace-1", + executionWorkspaceId: null, + mode: "shared_workspace", + }, + to: { + label: "Feature branch", + projectWorkspaceId: "workspace-2", + executionWorkspaceId: null, + mode: "shared_workspace", + }, + }, + _previous: { + projectWorkspaceId: "workspace-1", + }, + }, + }, + ] satisfies ActivityEvent[]); + + expect(events).toEqual([ + { + id: "evt-workspace", + createdAt: new Date("2026-03-31T12:01:00.000Z"), + actorType: "user", + actorId: "local-board", + runId: null, + workspaceChange: { + from: { + label: "Main workspace", + projectWorkspaceId: "workspace-1", + executionWorkspaceId: null, + mode: "shared_workspace", + }, + to: { + label: "Feature branch", + projectWorkspaceId: "workspace-2", + executionWorkspaceId: null, + mode: "shared_workspace", + }, + }, + }, + ]); + }); + it("synthesizes non-status follow-up rows from comment activity", () => { const events = extractIssueTimelineEvents([ { @@ -205,7 +266,7 @@ describe("extractIssueTimelineEvents", () => { ]); }); - it("ignores issue updates without visible status or assignee transitions", () => { + it("ignores issue updates without visible status, assignee, or workspace transitions", () => { const events = extractIssueTimelineEvents([ { id: "evt-title", diff --git a/ui/src/lib/issue-timeline-events.ts b/ui/src/lib/issue-timeline-events.ts index d1d12b11..4ade3db4 100644 --- a/ui/src/lib/issue-timeline-events.ts +++ b/ui/src/lib/issue-timeline-events.ts @@ -19,10 +19,26 @@ export interface IssueTimelineEvent { from: IssueTimelineAssignee; to: IssueTimelineAssignee; }; + workspaceChange?: { + from: IssueTimelineWorkspace; + to: IssueTimelineWorkspace; + }; commentId?: string | null; followUpRequested?: boolean; } +export interface IssueTimelineWorkspace { + label: string | null; + projectWorkspaceId: string | null; + executionWorkspaceId: string | null; + mode: string | null; +} + +export function formatTimelineWorkspaceLabel(workspace: IssueTimelineWorkspace) { + const fallbackId = workspace.executionWorkspaceId ?? workspace.projectWorkspaceId; + return workspace.label ?? (fallbackId ? fallbackId.slice(0, 8) : "None"); +} + function asRecord(value: unknown): Record | null { if (typeof value !== "object" || value === null || Array.isArray(value)) return null; return value as Record; @@ -44,6 +60,33 @@ function sameAssignee(left: IssueTimelineAssignee, right: IssueTimelineAssignee) return left.agentId === right.agentId && left.userId === right.userId; } +function sameWorkspace(left: IssueTimelineWorkspace, right: IssueTimelineWorkspace) { + return left.projectWorkspaceId === right.projectWorkspaceId + && left.executionWorkspaceId === right.executionWorkspaceId + && left.mode === right.mode + && left.label === right.label; +} + +function workspaceFromRecord(value: unknown): IssueTimelineWorkspace | null { + const record = asRecord(value); + if (!record) return null; + return { + label: nullableString(record.label), + projectWorkspaceId: nullableString(record.projectWorkspaceId), + executionWorkspaceId: nullableString(record.executionWorkspaceId), + mode: nullableString(record.mode), + }; +} + +function workspaceChangeFromDetails(details: Record) { + const change = asRecord(details.workspaceChange); + if (!change) return null; + const from = workspaceFromRecord(change.from); + const to = workspaceFromRecord(change.to); + if (!from || !to || sameWorkspace(from, to)) return null; + return { from, to }; +} + function sortTimelineEvents(events: T[]) { return [...events].sort((a, b) => { const createdAtDiff = toTimestamp(a.createdAt) - toTimestamp(b.createdAt); @@ -120,7 +163,17 @@ export function extractIssueTimelineEvents(activity: ActivityEvent[] | null | un } } - if (timelineEvent.statusChange || timelineEvent.assigneeChange || timelineEvent.followUpRequested) { + const workspaceChange = workspaceChangeFromDetails(details); + if (workspaceChange) { + timelineEvent.workspaceChange = workspaceChange; + } + + if ( + timelineEvent.statusChange + || timelineEvent.assigneeChange + || timelineEvent.workspaceChange + || timelineEvent.followUpRequested + ) { events.push(timelineEvent); } } diff --git a/ui/storybook/stories/chat-comments.stories.tsx b/ui/storybook/stories/chat-comments.stories.tsx index cb5431da..041293f9 100644 --- a/ui/storybook/stories/chat-comments.stories.tsx +++ b/ui/storybook/stories/chat-comments.stories.tsx @@ -404,6 +404,7 @@ const issueChatComments: IssueChatComment[] = [ }, metadata: { version: 1, + sourceRunId: "run-issue-chat-01", sections: [ { title: "Required action", @@ -459,6 +460,73 @@ const issueTimelineEvents: IssueTimelineEvent[] = [ }), ]; +const issueThreadNoticeReviewComments: IssueChatComment[] = [ + createComment({ + id: "comment-notice-board", + body: "The issue thread needs to show workspace routing changes and make old missing-disposition warnings feel resolved.", + createdAt: new Date("2026-04-20T13:44:00.000Z"), + }), + createComment({ + id: "comment-notice-system-warning", + authorType: "system", + authorAgentId: null, + authorUserId: null, + runId: "run-notice-source", + runAgentId: codexAgent.id, + body: "Paperclip needs a disposition before this issue can continue.", + presentation: { + kind: "system_notice", + tone: "warning", + title: "Missing issue disposition", + detailsDefaultOpen: false, + }, + metadata: { + version: 1, + sourceRunId: "run-notice-source", + sections: [ + { + title: "Required action", + rows: [ + { type: "issue_link", label: "Source issue", issueId, identifier: "PAP-3660", title: "Show issue-thread notices" }, + { type: "agent_link", label: "Assignee", agentId: codexAgent.id, name: codexAgent.name }, + { type: "key_value", label: "Missing disposition", value: "clear_next_step" }, + ], + }, + { + title: "Run evidence", + rows: [ + { type: "run_link", label: "Completed run", runId: "run-notice-source", title: "succeeded" }, + { type: "key_value", label: "Normalized cause", value: "successful_run_missing_state" }, + ], + }, + ], + }, + createdAt: new Date("2026-04-20T13:48:00.000Z"), + }), +]; + +const issueThreadNoticeReviewTimelineEvents: IssueTimelineEvent[] = [ + createSystemEvent({ + id: "event-notice-workspace-change", + createdAt: new Date("2026-04-20T13:46:00.000Z"), + statusChange: undefined, + workspaceChange: { + from: { + label: "Project primary workspace", + projectWorkspaceId: "workspace-primary", + executionWorkspaceId: null, + mode: "shared_workspace", + }, + to: { + label: "PAP-3660 issue-thread-notices", + projectWorkspaceId: null, + executionWorkspaceId: "execution-workspace-notices", + mode: "isolated_workspace", + }, + }, + }), +]; + const issueLinkedRuns: IssueChatLinkedRun[] = [ { runId: "run-issue-chat-01", @@ -701,6 +769,43 @@ function IssueChatMatrix() { ); } +function IssueThreadNoticeReview() { + return ( +
+
+
+
+ {}} + enableLiveTranscriptPolling={false} + showJumpToLatest={false} + /> +
+
+
+
+ ); +} + function ChatCommentsStories() { return (
@@ -771,3 +876,7 @@ export const IssueChatWithTimeline: Story = {
), }; + +export const IssueThreadNotices: Story = { + render: () => , +};