
    *kiS                     `   d dl Z d dlZd dlZd dlZd dlmZ ej                  j                  d  e ee	      j                         j                  d                d dlmZmZmZmZmZmZmZmZmZmZmZmZmZ d dlmZ dededdfd	Zdefd
ZddZe dk(  r e jB                   e              yy)    N)Path   )PlannedToolCallSearchProductsArgs_derive_home_thread_state_extract_catalog_query _build_surface_direct_tool_calls_execute_tool_call$_home_requires_hard_direct_execution"_normalize_home_planned_tool_calls_normalize_sql_readonly_query_normalize_text_search_products_should_prefer_planner_for_home_timeclock_period_from_message)get_tenant_store	conditiondetailreturnc                     | st        |      y )N)AssertionError)r   r   s     7apps/backend-hub/scripts/check_assistant_regressions.py_assertr      s    V$$     c                  Z   t        j                  dd      j                         } | r| S t        t        j                  dd            }t	        j
                  |      5 }|j                  dd      j                         }d d d        t        d      t        |d         S # 1 sw Y   $xY w)	NASSISTANT_REGRESSION_TENANT_ID TENANCY_REGISTRY_DATABASEz/data/platform_registry.sqlite3z%SELECT id FROM tenants WHERE slug = ?)ritualzDTenant 'ritual' non trovato. Imposta ASSISTANT_REGRESSION_TENANT_ID.r   )
osgetenvstripr   sqlite3connectexecutefetchoneRuntimeErrorstr)
configuredregistry_path
connectionrows       r   _resolve_regression_tenant_idr-       s    ;R@FFHJ#>@abcM		' b:  !H+V__ab
{abbs1v;	b bs   !B!!B*c                    K   t               } | j                  t                     }|t        d      d}t	        |      }t        d|g i       }t        |xr |d   j                  dk(  d| d       t        t        ||g g |      d	       d
}t        t        |      dk(  d       d}t        t        |      dk(  d       t        d|g i       }t        |xr |d   j                  dk(  d       t        d|g i       }t        |xr |d   j                  dk(  d       t        dt        |d   j                  j                  d      xs d      j                         v xr; dt        |d   j                  j                  d      xs d      j                         vd|d   j                          t        dddd      g}	t        ||	      }
t        |
d   j                  j                  d      dk(  d       t!        d      }t        d|v d       t#        |t%        dd             }|j                  d!g       D cg c]   }t        |j                  d"      xs d      " }}t        |d#gk(  d$|        d%}t        d|g i       }t        |xr |d   j                  d&k(  d'|        |d   j                  }t        |j                  d(      d)k(  xr* |j                  d*      d+k(  xr |j                  d,      d-k(  d.|        t        |t        d/d-d+d0      g      }t        |xrX |d   j                  d&k(  xrD |d   j                  j                  d(      d)k(  xr! |d   j                  j                  d*      d+k(  d1|        t'        ||d   g 2       d {   }|j                  d3i       j                  d4g       }t        t)        |      d+k(  d5t)        |              d6}t        d|g d7d&d&d8      }t        |xr |d   j                  d&k(  xr |d   j                  j                  d      dk(  xrg |d   j                  j                  d(      d)k(  xrD |d   j                  j                  d*      d9k(  xr! |d   j                  j                  d,      d-k(  d:|        t        |t        d/d;d-d+d<      g      }t        |xr{ |d   j                  d&k(  xrg |d   j                  j                  d      dk(  xrD |d   j                  j                  d(      d)k(  xr! |d   j                  j                  d*      d9k(  d=|        d>}t        d|g i       }t        |xr{ |d   j                  d&k(  xrg |d   j                  j                  d      d?k(  xrD |d   j                  j                  d(      d)k(  xr! |d   j                  j                  d*      d+k(  d@|        t        |t        d/d?d-d+d<      g      }t        |xr{ |d   j                  d&k(  xrg |d   j                  j                  d      d?k(  xrD |d   j                  j                  d(      d)k(  xr! |d   j                  j                  d*      d+k(  dA|        dB}t        d|g i       }t        t+        |t	        |      |      dC       dD}t        d|g i       }t        |xr |d   j                  dEk(  dF       t        t        |t	        |      g g |       dG       dH}t        d|g i       } t        | xrt | d   j                  dEk(  xr` | d   j                  j                  dI      xr@ | d   j                  j                  dJ      xr  | d   j                  j                  d*      d udK|         t        |t        dEdLdMdNd dO      g      }!t        |!xr |!d   j                  dEk(  xr |!d   j                  j                  dP      dQk(  xr` |!d   j                  j                  dI      xr@ |!d   j                  j                  dJ      xr  |!d   j                  j                  d*      d udR|!        dSD ]^  }"t	        |"      }#t-        |"|#      \  }$}%}&}'t        t/        |%      xs t/        |&      xr t/        |'      xs |$dTk(  dU|" dV|$|%|&|'f        ` dW}(t        d|(g i       })t        |)xr |)d   j                  dEk(  dX       |)d   j                  }*t        |*j                  dP      dQk(  xr* |*j                  dI      dYk(  xr |*j                  dJ      dZk(  d[|*        t1        i ||dEd\d]d^d_d`daidbgdcg d      }+t        ddedf|dgdhdidgg|+      },t        |,xr |,d   j                  dEk(  dj|,        |,d   j                  }-t        |-j                  dk      |k(  dl       t        |-j                  dI      dYk(  xr |-j                  dJ      dZk(  dm|-        t        ddedfd
dgdhdndgdf|dgdhdidgdfdedgdhdodggdpdqdqd8      }.t        |.xr |.d   j                  dEk(  dr       t        |.d   j                  j                  dk      |k(  ds|.d   j                          t        ddtdf|(dgdhdudgdfdvdgdhdidggdE|(dwdxdy      }/t        |/xr |/d   j                  dzk(  d{|/        t        t        dtt	        dt      g g |/       d|       t1        dE|(d}dt|/g dcg d      }0t        |0j                  d~      dzk(  d|0        t        dddf|(dgdhdudgdfdtdgdhddgg|0      }1t        |1xr |1d   j                  dzk(  d|1        t        dddf|(dgdhdudgdfdtdgdhdidggdE|(dwd      }2t        |2xr |2d   j                  dzk(  d|2        t        dddf|dgdhdidgdfddgdhddggddqdqd8      }3t        t3        d |3D               d|3        t'        ||d   g 2       d {   }4|4j                  d3i       j                  dg       }5|5D 6cg c]1  }6t5        |6t6              st        |6j                  d      xs d      3 }7}6t        |7d#gk(  d|7        t'        ||d   g 2       d {   }8|8j                  d3i       j                  dg       }9|9D 6cg c]1  }6t5        |6t6              st        |6j                  d      xs d      3 }:}6t        |:d#gk(  d|:        t9        d       y c c}w 7 	7 c c}6w 7 c c}6w w)NzBSessione di servizio non disponibile per il tenant di regressione.z4Trovi rum Gosling nel catalogo dei nostri fornitori?homer   run_tenant_queryz7I cataloghi fornitori devono usare il query layer, non .)contextual_tool_callsdirect_tool_callsz4Le letture catalogo devono preferire il planner LLM.z*Trovi del gosling nei cataloghi fornitori?goslingz;La query catalogo non deve includere la preposizione 'nei'.z0Trovi Gosling nel catalogo di qualche fornitore?z[La query catalogo non deve diventare 'qualche' quando l'utente dice 'di qualche fornitore'.zJLa richiesta 'cataloghi fornitori' non deve finire nello storico acquisti.zbLa richiesta 'catalogo di qualche fornitore' deve interrogare i cataloghi, non rispondere a vuoto.sqlr   qualchez6La SQL cataloghi deve cercare Gosling, non 'qualche': search_productsrum
   )querylimit)tool	argumentsr:   zrum goslingz@Il normalizzatore deve reinserire il termine distintivo Gosling.zPSELECT * FROM supplier_catalog_items WHERE lower(product_name) LIKE '%gosling%';zlower(source_name)z9Le query supplier_catalog_items devono usare source_name.i  itemsproduct_namez
GOSLING 1Lz!Atteso solo GOSLING 1L, trovati: z!Mostrami il primo ordine del 2025get_purchase_batchesz9'Primo ordine' deve usare get_purchase_batches, trovati: 
sort_orderearliestr;   r   yeari  zF'Primo ordine del 2025' deve essere earliest/limit 1/year 2025, args: get_purchase_history)rC   r;   zIIl normalizzatore non deve trasformare 'primo ordine' in lista completa: )prior_tool_resultsresultbatcheszA'Primo ordine del 2025' deve restituire un solo ordine, trovati: z#Mostrami il secondo ordine del 2025
timbrature)purchase_querypurchase_view	last_tool   zZ'Secondo ordine del 2025' non deve ereditare query sporche e deve usare earliest/limit 2: secondo)r:   rC   r;   zRIl normalizzatore deve correggere 'secondo ordine' in secondo ordine cronologico: z+mostrami il primo ordine di laconi del 2025laconiz<'Primo ordine di laconi' deve mantenere il filtro prodotto: z-Il normalizzatore non deve perdere 'laconi': z<Crea una prenotazione per Mario domani alle 20 per 4 personez5Le scritture prenotazione devono restare hard-direct.zquanto ha lavorato Ale Cioeta?get_timeclock_summaryzALe domande sulle ore lavorate devono usare get_timeclock_summary.zALe domande semplici sui turni non devono passare dal planner SQL.z-quante ore hanno fatto i ragazzi questo mese?
start_dateend_datezS'quante ore ... ragazzi questo mese' deve essere una lettura Turni mensile valida: ragazzimonthz
2026-04-29)
query_textscopetarget_dater;   rU   allz^Il planner Turni con scope month/null limit deve essere normalizzato prima della validazione: )z,quante ore hanno fatto i ragazzi dopodomani?z4quante ore hanno fatto i ragazzi settimana prossima?z/quante ore hanno fatto i ragazzi mese prossimo?activez3Il riferimento temporale non e' stato risolto per 'z': z'quanto ha lavorato ale cioeta nel 2026?zILe domande dirette sui turni con anno devono usare get_timeclock_summary.z
2026-01-01z
2026-12-31zLLa domanda diretta sui turni nel 2026 non deve interrogare solo oggi, args: resolved_useruser_alez
Ale Cioetaalezale@example.test)user_idnameusernameemail)r<   rF   test)previous_statemessageexecuted_tool_callstool_resultsrouteconversationze in generale nel 2026?user)rolecontent	assistantzNon vedo timbrature per oggi.z<Il follow-up sui turni deve mantenere il contesto, trovati: rT   zGIl follow-up sul 2026 deve riusare la persona della domanda precedente.z;Il follow-up sul 2026 deve interrogare tutto l'anno, args: z(Ho trovato questi dati acquisti reali...z2Non riesco ancora a leggere questo dato operativo.zgosling neiget_purchase_overviewzLAnche un thread gia sporco deve recuperare l'ultima domanda reale sui turni.z3Il thread sporco deve recuperare Ale Cioeta, args: zabbiamo prenotazioni per oggi?z4Nel periodo richiesto Ale Cioeta ha lavorato 0h 01m.ze oggi?todayz
2026-04-26)rK   timeclock_query_texttimeclock_scopetimeclock_target_dateget_reservations_snapshotzLUn cambio contesto esplicito sulle prenotazioni non deve restare sui turni: zZLe letture semplici prenotazioni devono essere eseguite direttamente, non dal planner LLM.)rK   rm   rK   zCDopo una lettura prenotazioni lo stato non deve restare sui turni: z	e domani?z'Per oggi risultano alcune prenotazioni.z:Il follow-up dopo prenotazioni non deve tornare ai turni: )rK   rm   rn   zLAnche un thread gia sporco deve rispettare il cambio contesto prenotazioni: ze nel 2026?z#Quanta don julio ordinata nel 2025?z)Nel 2025 risulta ordinata una quantita...z	don julioc              3   :   K   | ]  }|j                   d k(    yw)rO   N)r<   ).0	tool_calls     r   	<genexpr>zmain.<locals>.<genexpr>  s     ii	"99is   zDUn follow-up acquisti non deve ereditare il vecchio contesto turni: rowsdisplay_namez]Il fallback diretto sui cataloghi deve trovare solo GOSLING 1L dal catalogo locale, trovati: zKLa frase 'catalogo di qualche fornitore' deve trovare GOSLING 1L, trovati: zassistant regressions: ok)r   build_service_sessionr-   r'   r   r	   r   r<   r   r   r(   r=   getlowerr   r   r   r   r   r
   lenr   r   boolr   any
isinstancedictprint);storesessioncatalog_messagenormalized_catalog_messagecatalog_direct_callsplural_supplier_catalog_messagesupplier_any_catalog_messageplural_supplier_catalog_callssupplier_any_catalog_callsplanned_searchnormalized_searchnormalized_sqlsearch_resultitemproduct_namesfirst_order_messagefirst_order_callsfirst_order_argsplanner_first_order_callsfirst_order_resultfirst_order_batchessecond_order_messagesecond_order_callsplanner_second_order_callsfirst_laconi_messagefirst_laconi_callsplanner_first_laconi_callsreservation_messagereservation_direct_callstimeclock_messagetimeclock_direct_callsteam_month_timeclock_messageteam_month_timeclock_callsplanner_team_month_callstemporal_messagenormalized_temporal_messagerU   rV   rP   rQ   timeclock_year_messagetimeclock_year_callstimeclock_year_argstimeclock_statetimeclock_followup_callstimeclock_followup_argsdirty_timeclock_followup_calls!reservation_after_timeclock_callsreservation_statereservation_followup_calls dirty_reservation_followup_callsnewer_purchase_followup_callsdirect_resultdirect_rowsr,   direct_namessupplier_any_resultsupplier_any_rowssupplier_any_namess;                                                              r   mainr   -   s    E))*G*IJG_``LO!0!A;FOUWY[\S!5a!8!=!=AS!S
ABVAWWXY '&"$2	
 	?	 'S#>?9LE $V ;<	Ie %EVMlnprt$u!%e*G*J*O*OSe*eT "B&Jfhjln!o"_'A!'D'I'IM_'_l S3A6@@DDUKQrRXXZZ 	cS!;A!>!H!H!L!LU!S!YWYZ``bb
@A[\]A^AhAh@ij &+<RWbdHefgN:?N[!&&**73}DJ
 3ZN  N24op$W.@}\`.abMEREVEVW^`bEcdTS.17R8dMdMl^+/PQ^P_-`a=8ATVXZ\]Q/277;QQ
CDUCVW )+55\*j8 	1  )Q.	1  (D0
PQaPbc	 !C	4XY@Z	[\! ! 	E%a(--1GG	E%a(2266|D
R	E &a(2266w?1D
STmSno  2';LQ;Odfgg,002>BB9bQ A%
KCPcLdKef A9
':P_uv	  	@q!&&*@@	@q!++//8B>	@ q!++//=K	@ q!++//8A=		@
 q!++//74?
dewdxy "D	4)]alm@n	op" " 	F&q)..2HH	F&q)3377@BF	F 'q)3377ES	F 'q)3377@AE
\]w\xy I9&BVXZ\^_ 	>q!&&*@@	>q!++//8HD	> q!++//=K	> q!++//8A=
FGYFZ[ "D	4(\`kl@m	no" " 	F&q)..2HH	F&q)3377@HL	F 'q)3377ES	F 'q)3377@AE
78R7ST Y?H[]_acd,/0$	

 	@ 9=fFWY[]_`\#9!#<#A#AE\#\K +-."$4
 	
 	L	 $S !A&Jfhjln!o" 	M&q)..2II	M&q)3377E	M 'q)3377
C	M 'q)3377@L
]^x]yz  B$,)2WUalpq	
    	K$Q',,0GG	K$Q'1155g>%G	K %Q'1155lC	K %Q'1155jA		K
 %Q'1155g>dJ
h  jB  iC  	D 


 '66F&G#3QRbd  4A0{J[$z"2"EtH~[%S[J[ABRASSVX]_jlv  yA  XB  WC  D	


 G;FDZ\^`bcX!5a!8!=!=AX!XS /q1;;(E1 	@##L1\A	@##J/<?
VWjVkl	 0!2 0##- ,$)!3	&

 %O(  @!(9: -LM	
 	   `%=a%@%E%EI`%`
FG_F`a 7q9CC##L15FFQ ##L1\A 	D#''
3|C
EF]E^_
 &F!(TU -WX(9: -LM(AB -ab	
 );Raxy&" &l+I!+L+Q+QUl+lV &q)3377EIZZ
=>\]^>_>i>i=jk )I((>? -cd	2 -LM		
 1$:&%1		
)%  )v.OPQ.R.W.W[v.v
VWxVyz +,<="$?
 	
 	e	 20$:
 1=
 k*.II
MN_M`a "B(>? -cd(HI -VW		
 	
" "h'A!'D'I'IMh'h
DE_D`a (H(>? -cd(HI -LM		
 1$:&	
($ (t-Ma-P-U-UYt-t
VWwVxy %E(9: -LM(MN -XY		
 '9P_vw
%! iKhiii
NOlNmn
 -W6STU6VkmnnM##Hb155fbAKBMg3Q[\_aeQfC/526gLg&
ghtguv !37<VWX<Ynp qq+//"=AA&"MHYs]ghkmq]r#cggn5;<ss|n,
UVhUij
 

%&c
 e6 hN	 og
 rssn   H8t>:%t'D<t>t,a?t>t/*t>t2 t2<)t>%t7&*t>t9& t9't>/t>2t>9t>__main__)r   N)"asyncior    r#   syspathlibr   pathinsertr(   __file__resolveparents*app.services.operational_assistant_servicer   r   r   r   r	   r
   r   r   r   r   r   r   r   app.services.tenant_storer   r{   r   r-   r   __name__run r   r   <module>r      s     	  
  3tH~--/77:; <    7%t %S %T %

s 
P'f zGKK r   