
    8j                    :   d Z ddlmZ ddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlZddlmZmZ ddlmZmZ ddlmZ ddlmZ  ee      j1                         j2                  d   Zed	z  Zd
ZdddZg dZg dZ G d de       Z! ed       G d d             Z" ed       G d d             Z# ed       G d d             Z$ ed       G d d             Z%d>dZ&d?dZ'd@dZ(dAdZ)dBd Z*dCd!Z+dDd"Z,dEd#Z-dFd$Z.dGd%Z/dHd&Z0	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dId'Z1dJd(Z2dKd)Z3	 	 dL	 	 	 	 	 	 	 	 	 	 	 dMd*Z4dNd+Z5dOd,Z6dPd-Z7dQd.Z8dRd/Z9dNd0Z:dNd1Z;dNd2Z<dNd3Z=dNd4Z>dSd5Z?dNd6Z@dTd7ZAdUd8ZBdNd9ZCdNd:ZDdVd;ZEdWdXd<ZFeGd=k(  r eH eF             y)Ya&  Prepare and optionally assist TradingView Pine updates.

This tool is intentionally human-in-the-loop. It validates local Pine source,
copies the exact script text for paste, records an update manifest, and can open
TradingView in a normal visible browser session when Playwright is installed.
    )annotationsN)asdict	dataclass)datetimetimezone)Path)Any   z.tradingview_e2ez"https://www.tradingview.com/chart/i    )widthheight)zCannot compilezCompilation errorzError atzMismatched inputzSyntax errorzUndeclared identifierz-Could not find function or function reference)zsign inzlog inzsign upzjoin for freec                      e Zd ZdZy)PineParseErrorz7Raised when a Pine script declaration cannot be parsed.N)__name__
__module____qualname____doc__     tools/tradingview_update.pyr   r   +   s    Ar   r   T)frozenc                  T    e Zd ZU ded<   ded<   ded<   ded<   ded<   ded	<   ded
<   y)PineScriptInfostrpathkindtitlez
int | Noneversionsha256int
line_count
char_countNr   r   r   __annotations__r   r   r   r   r   /   s&    
I
IJKOOr   r   c                  H    e Zd ZU ded<   ded<   ded<   ded<   ed
d       Zy	)CheckResult	list[str]commandr    
returncoder   stdoutstderrc                     | j                   dk(  S )Nr   )r)   )selfs    r   okzCheckResult.okA   s    !##r   N)returnbool)r   r   r   r$   propertyr.   r   r   r   r&   r&   :   s)    OKK$ $r   r&   c                  @    e Zd ZU ded<   ded<   ded<   ded<   ded	<   y
)PreparedUpdater   infolist[CheckResult]checksr   source_copymanifestr0   	clipboardNr#   r   r   r   r3   r3   F   s    
NOr   r3   c                  ,    e Zd ZU ded<   ded<   ded<   y)DoctorCheckr   namer0   r.   detailNr#   r   r   r   r;   r;   O   s    
IHKr   r;   c                    t        |       } 	 t        | j                         j                  t                    S # t
        $ r t        | j                               cY S w xY wN)r   r   resolverelative_toREPO
ValueErrorr   s    r   repo_relativerE   V   sL    :D#4<<>--d344 #4<<>""#s   +9 "AAc                &    | j                  d      S Nutf-8encoding)	read_textrD   s    r   rK   rK   ^   s    >>7>++r   c                R   t        j                  d| d|       }|sy |j                         dz
  }d}d}d}t        |t	        |             D ]Y  }| |   }|r|rd}n|dk(  rd}n|dk(  rd}|dk(  rd}'|d	k(  r|dz  }2|d
k(  s8|dz  }|dk(  sC| |j                         |dz    c S  y )Nz\bz\s*\(r
   r   F\T"())researchendrangelenstart)	source	call_namematchrV   depth	in_stringescapedidxchs	            r   _extract_callr_   b   s    III;e,f5EIIK!OEEIGUCK(C[ts!	9I3YQJE3YQJEzekkmS1W55# )$ r   c                    t        j                  d| t         j                        }|r|j                  d      S t        j                  d| t         j                        }|r|j                  d      S t	        d      )Nz\btitle\s*=\s*"([^"]+)"r
   z\(\s*"([^"]+)"z$Pine declaration has no string title)rQ   rR   DOTALLgroupr   )callnamed
positionals      r   _extract_titlerf      sa    II0$		BE{{1~,dBII>J""
?
@@r   c                   t        |       }t        |      }t        j                  d|t        j                        }|rt        |j                  d            nd }dD ]  }t        ||      }|st        |      } n t        d      t        t        |      |||t        j                  |j                  d            j                         t!        |j#                               t!        |            S )Nz^\s*//@version\s*=\s*(\d+)\s*$r
   )strategy	indicatorz@Expected a top-level strategy(...) or indicator(...) declarationrH   )r   r   r   r   r   r!   r"   )r   rK   rQ   rR   	MULTILINEr    rb   r_   rf   r   r   rE   hashlibr   encode	hexdigestrU   
splitlines)r   	pine_pathrW   version_matchr   r   rc   r   s           r   
parse_pinerq      s    T
Iy!FII?VM-:c-%%a()G)VT*"4(E	 * _``9%~~fmmG45??Av((*+v; r   c                    t        j                  | t        ddd      }t        | |j                  |j
                  |j                        S )NTF)cwdcapture_outputtextcheck)r(   r)   r*   r+   )
subprocessrunrB   r&   r)   r*   r+   )r(   results     r   run_commandrz      sH    ^^F $$}}}}	 r   c                   t        |       } t        t        j                  dt	        |       g      g}| j                         t        dz  j                         k(  r*|j                  t        t        j                  dg             |S )Nztools/check_pine_duplicates.pyz*strategies/strategy_activation_scores.pineztools/check_pine.py)r   rz   sys
executablerE   r@   rB   append)ro   r6   s     r   run_preflightr      sn    YIS^^%E}U^G_`aF t&RR[[]]k3>>3H"IJKMr   c                    t        j                  d      sy	 t        j                  dg| dd       y# t        j                  $ r Y yw xY w)NpbcopyFT)inputru   rv   )shutilwhichrw   rx   CalledProcessError)ru   s    r   copy_to_clipboardr      sI    <<!zDE  (( s   3 A	A	c                    t        j                  dd|j                        j                  d      xs d}| t	                d| dz  S )N[^A-Za-z0-9_.-]+_pine_script.json)rQ   subr   strip	timestamp)out_dirr4   
safe_titles      r   manifest_pathr      sC    +S$**=CCCHYMJ	}Aj\777r   c                 f    t        j                  t        j                        j	                  d      S )Nz%Y%m%dT%H%M%SZ)r   nowr   utcstrftimer   r   r   r   r      s!    <<%../?@@r   c                V    t        j                  dd|       j                  d      xs dS )Nr   r   capture)rQ   r   r   values    r   slugifyr      s&    66%sE288=JJr   c                @   | j                  dd       t        j                  t        j                        j                         t        |      t        |      t        |j                  dd|D cg c]B  }|j                  |j                  |j                  |j                  dd  |j                  dd  dD c}|||dd|j                   d|j                  d	d
dddgd}t!        | |      }	|	j#                  t%        j&                  |dd      dz   d       |	S c c}w )NTparentsexist_ok)	chart_urltarget_namehuman_review_requiredi`)r(   r)   r.   stdout_tailstderr_tail)copied_to_clipboardopened_default_browseropened_playwright_browserz5Open TradingView Pine Editor and select the existing z named .zkPaste the clipboard contents, save/update the script, and confirm TradingView shows no Pine compile errors.zUVisually inspect the chart/strategy tester for the expected script name and behavior.zpIf the script compiles, mark the relevant local sentinel, for example: python3 tools/check_pine.py --mark-valid.zXAttach screenshots or exported trades/CSV to future parity checks when behavior changes.)
created_atscriptr7   tradingviewlocal_checksactionsverification_steps   indent	sort_keys
rH   rI   )mkdirr   r   r   r   	isoformatr   rE   TRADINGVIEW_CHART_URLr   r(   r)   r.   r*   r+   r   r   
write_textjsondumps)
r   r4   r6   r9   browser_openedplaywright_openedr7   rv   payloadr   s
             r   write_manifestr      s*    MM$M.ll8<<0::<,$[1.::%)
  	
   !==#..hh$||EF3$||EF3  	
 $-&4):
 DDII;gVZV`V`Uccdeyc~f
1G@ $'DOODJJwqDADHSZO[K3	
s   /ADc                Z   	 ddl m} | dz  }|j                  dd        |       5 }|j                  j                  t        |      dt              }|j                  r|j                  d   n|j                         }|j                  |dd	
       t        d       | dz  }|j                  dd       |dt                dz  }|j                  t        |      d       t        dt        |              |j!                          d d d        y# t        $ r Y yw xY w# 1 sw Y   yxY w)Nr   sync_playwrightFplaywright-profileTr   headlessviewportdomcontentloaded`  
wait_untiltimeoutzITradingView is open. Press Enter here after you finish/save the update...screenshotstradingview_.pngr   	full_pagezScreenshot saved: )playwright.sync_apir   ImportErrorr   chromiumlaunch_persistent_contextr   DEFAULT_VIEWPORTpagesnew_pagegotor   r   
screenshotprintrE   close)	r   urlr   profile_dirpcontextpagescreenshot_dirscreenshot_paths	            r   open_playwright_browserr     s%   7 00KdT2		a**66% 7 

 $+==w}}Qg6F6F6H		#"4f	EYZ =0TD9(\)+d+KKS1TB"=#A"BCD 
 )  
 
 s   D C"D!	DD!D*c                   | dz  }|j                  dd       |t                dt        |j                         dz  }|j	                  |d       |dt        |j                         dz  }|j	                  |d       |S )	NrW   Tr   r   z.pinerH   rI   latest_)r   r   r   r   r   )r   r4   rW   
source_dirsource_pathlatest_paths         r   write_source_copyr   !  s    8#JTD1)+a

0C/DEJJK6G4)<(=UCCK6G4r   c           	     4   t        |       j                         st        | z  j                         n
t        |       }t	        |      }t        |      }t        |      }d}	|st        |      }	t        |||      }
t        ||||	|||
      }t        |||
||	      S )NF)r4   r6   r7   r8   r9   )r   is_absoluterB   r@   rq   r   rK   r   r   r   r3   )piner   no_clipboardr   r   ro   r4   r6   rW   r9   r7   r8   s               r   stage_updater   ,  s     04Dz/E/E/G%%'TRVZIi D9%Fy!FI%f-	#GT6:KgtVYPacnoH r   c                r   	 ddl m} t	        | j
                        }|dz  }|j                  dd       |dt                d	z  } |       5 }|j                  j                  d
      }|j                  t              }|j                  dd       |j                         }|j                  t        |      d       |j!                          d d d        dk(  |t#        |      d}	t        t%        j&                  |	dd             |	d   rdS dS # t        $ r t        d       Y yw xY w# 1 sw Y   _xY w)Nr   r   IPython Playwright is not installed. See docs/tradingview_e2e_workflow.md.r
   r   Tr   smoke_r   r   r   z^data:text/html,<title>tradingview-e2e-smoke</title><body><h1>TradingView E2E smoke</h1></body>r   )r   r   ztradingview-e2e-smoke)r.   r   r   r   r   r.   )r   r   r   r   resolve_out_dirr   r   r   r   launchr   r   r   r   r   r   r   rE   r   r   )
argsr   r   r   r   r   browserr   r   r   s
             r   playwright_smoker   G  s3   7
 dll+G},N5$	}D'AAO		a**##T#2)9:		:) 	 	

 

S1TB 
 ..#O4G
 
$**WQ$
781$1$7  YZ 
	s   D BD-D*)D*-D6c                >    | j                  t        |||             y )N)r<   r.   r=   )r~   r;   )r6   r<   r.   r=   s       r   add_doctor_checkr   h  s    
MM+4Bv>?r   c                    | D cg c]&  }|j                         s|j                         s%|( }}|sy t        |d       S c c}w )Nc                N    | j                         j                  | j                  fS r?   )statst_mtimer<   rD   s    r   <lambda>zlatest_file.<locals>.<lambda>p  s    499;+?+?*Kr   )key)existsis_filemax)pathsr   existings      r   latest_filer  l  s@    !&K$++-DLLNHKxKLL Ls   AAAc                H    t        t        | j                  |                  S r?   )r  listglob)rootpatterns     r   latest_globr	  s  s    tDIIg./00r   c                    | sy 	 t        j                  | j                  d            S # t         j                  $ r Y y w xY wrG   )r   loadsrK   JSONDecodeErrorrD   s    r   load_json_filer  w  s?    zz$..'.:;; s   $* A A c                   t        | j                        }t        |d      xs t        |d      }t        |d      }t        |d      }t        |dz  d      }t        |dz  d      }t        |d	z  d
      }t        |      }t        |      }	t        |      }
|
xs |	xs |}t	        |t
              r!t	        |j                  d      t
              r|n|}|j                         t        |      |rt        |      nd |rt        |      nd |rt        |      nd |rt        |      nd |rt        |      nd |rt        |      nd t	        |t
              r|j                  d      nd t	        |t
              r@t	        |j                  d      t
              r!|j                  di       j                  d      nd t	        |
t
              r|
j                  d      nd d}t        t        j                  |dd             |d   rdS dS )Nz*_MLPScores.jsonz*.jsonz*_capture.jsonz*_manual_update.jsonr   z*.png	page_textz*.txtrW   z*.piner   r.   r   verification)r.   r   latest_manifestlatest_capturelatest_manual_updatelatest_screenshotlatest_textlatest_sourcelatest_result_oklatest_script_titlemanual_update_verificationr   Tr   r   r
   )r   r   r	  r  
isinstancedictgetr   rE   r   r   r   )r   r   r8   r   manual_updater   ru   rW   manifest_payloadcapture_payloadmanual_payloadlatest_payloadtitle_sourcer   s                 r   statusr#    s   dll+G7$67Y;wPX;YH'#34G)?@MW}4g>Jw,g6D8+X6F%h/$W-O#M2N#JJ:JN>4(Z8J8J88TVZ-[ " 
 nn )6>=2D4;-0@Mm <SW:D]:6$.2}T*28v.d8B>SW8XN..t4^b ,-*\=M=Mh=WY]2^ Xr*..w7LVWegkLln&8&8&HrvG" 
$**WQ$
781$1$r   c                   g }t        | j                        j                         st        | j                  z  nt        | j                        }t	        |dt        j                         t        t                     t	        |dt        dz  j                         d       t	        |ddt        dz  j                  d      v d       	 t        |      }t	        |d	d
|j                   d|j                         |j                         rQt        |      }|D cg c]  }|j                  r| }}t	        |d| |sdndj                  d |D                     nt	        |dddt        |              	 t         j"                  j%                  d      }t	        |dd
|       	 ddlm}	 t	        |dd
d       t/        | j0                        }
d }d }d }|	rI| j2                  s| j4                  r0|
dz  }|
dz  }|j7                  d
d
       |j7                  d
d
       	  |	       5 }| j2                  r|dt9                dz  }|j:                  j=                  d
      }|j?                  t@              }|jC                  d       |j                         }|jE                  t        |      d
        |jG                          t	        |d!|d"k(  t        |             | j4                  r,t9               }|d#| dz  }|d#| d$z  }|j:                  j=                  d
      }|j?                  t@              }|jC                  tH        d%| jJ                  &       | jL                  r|jO                  | jL                         |jQ                  d'      jS                  d()      }|jE                  t        |      d
        |jG                          |jU                  |d       d*|v xr
 d+|v xs d,|v }t	        |d-|t        |       dt        |              d d d        tW        d/ |D              |rtY        |      nd |D cg c]  }tY        |       c}|rt        |      nd |rt        |      nd |rt        |      nd d0}t[        t]        j^                  |d1d
2             |d   rdS d3S # t        $ r$}d }t	        |d	dt        |             Y d }~d }~ww xY wc c}w # t         j"                  j&                  $ r t	        |ddd       Y mw xY w# t,        $ r$}t	        |ddt        |             d }	Y d }~d }~ww xY w# 1 sw Y   /xY w# t        $ r"}t	        |d.dt        |             Y d }~Xd }~ww xY wc c}w )4Nrepozrequirements-e2ezrequirements-e2e.txtzgitignore-artifactsz.tradingview_e2e/z
.gitignorerH   rI   z
pine-parseT Fzpine-preflightr.   z; c              3  p   K   | ].  }d j                  |j                         d|j                    0 yw)r&   -> N)joinr(   r)   .0rv   s     r   	<genexpr>zdoctor.<locals>.<genexpr>  s4     -untej%--1H0IeN^N^M_.`nts   46zmissing 
playwrightzplaywright-pythonznot installedr   r   zplaywright-importr   r  r   doctor_browser_r   r   r   z6data:text/html,<title>doctor</title><h1>doctor ok</h1>r   zbrowser-launchdoctordoctor_tradingview_.txtr   r   body  r   
Indicators	WatchlistPine Editorztradingview-renderzbrowser-runtimec              3  4   K   | ]  }|j                     y wr?   r.   r*  s     r   r,  zdoctor.<locals>.<genexpr>  s     /u%((s   )r.   r   r6   browser_screenshottradingview_screenshottradingview_textr   r   r
   )0r   r   r   rB   r   r   r   rK   rq   r   r   	Exceptionr   r.   r)  rE   	importlibmetadatar   PackageNotFoundErrorr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   
timeout_mswait_mswait_for_timeoutlocator
inner_textr   allr   r   r   r   )r   r6   ro   r4   exc	preflightrv   failedr   r   r   r:  r;  r<  r   text_dirr   r   r   r   stampru   renderedr   s                           r   r/  r/    s)    "F(,TYY(C(C(Etyy 4PTPYPY?IVVT[[]CI>V/$9O2O1W1W1Y[qrV24GDS_L_KjKjt{KjK|4|  R  S@)$t		{!DJJ>5RS
 !),	%.?YEehh%Y?JDDII-unt-u$u		
 	!15H]S\E]D^:_`N$$,,\:!4dGDB7
 	!4dDAdll+G!DLLD,<,< =0[(TD9td3!	I "a<<)7OIK=X\:])]&jj///>G"++5E+FDIIVW JJLEOO-?)@DOQMMO$V-=u?PR_`rRst##%KE-;@STYSZZ^>_-_*'/4Gwd2S'S$jj///>G"++5E+FDII3@R\`\k\kIl||--dll;<</::4:HDOO-C)DPTOUMMO$//w/G+t3f9L9eP]aePeH$, ()?@AMRbDcCde	3 #F /// $t$.45fU6%=f5CUm,>?[_Ka-0F"Ggk?OM*:;UYG 
$**WQ$
781$1$g  @uc#h??@ @ 22 N!4e_MN
  !4eSXF  #">  	IV%6s3xHH	I 6s   2R+ S)S4-S  "T U %G0UU  U=+	S4SS +TT	T?T::T?UU 	U:U55U:c                J   	 ddl m} t	        | j
                        }|dz  }|dz  }|dz  }|j                  dd	       |j                  dd	       t        | j                  xs | j                        }t               }|| d
| dz  }|| d
| dz  }	|| d
| dz  }
 |       5 }|j                  j                  t        |      | j                   t              }|j                   r|j                   d   n|j#                         }|j%                  | j                  | j&                  | j(                         | j*                  r|j-                  | j*                         |j/                         }| j0                  r!|j3                  d      j5                  d      nd}|j7                  t        |      d       |j9                          d d d        | j0                  r|	j;                  d       d| j                  t=        |      | j0                  rt=        |	      nd | j                  d}|
j;                  t?        j@                  |dd      dz   d       t        t?        j@                  |dd             y# t        $ r t        d       Y yw xY w# 1 sw Y   xY w)Nr   r   r   r
   r   r   r  Tr   r   r   r1  z_capture.jsonr   r   r2  r3  r4   r   rH   rI   )r.   r   r   r   ru   headedr   r   r   )!r   r   r   r   r   r   r   r   labelr   r   r   r   r   rO  r   r   r   r   r   rA  rB  rC  r   	save_textrD  rE  r   r   r   rE   r   r   )r   r   r   r   r   rJ  rP  rK  r   	text_pathmetadata_pathr   r   r   r   visible_textr   s                    r   capture_urlrU    sW   7
 dll+G00K},N$H5NN4$N/DJJ*$((+EKE$%%'==OeWAeWD11Iq}==M		a**66_% 7 

 $+==w}}Qg6F6F6H		$((t	P<<!!$,,/

HLt||F+66t6D\^S1TB 
 ~~\G< xx#O4,0NNi(++G TZZTJTQ\cd	$**WQ$
78[  YZ" 
	s   I? 'D&J?JJJ"c                   	 ddl m} t	        | j
                        }|dz  }|dz  }|dz  }|j                  dd	       |j                  dd	       t               }|d
| dz  }|d
| dz  }|d
| dz  }	 |       5 }
|
j                  j                  t        |      | j                   t              }|j                  r|j                  d   n|j                         }|j                  | j                   | j"                  | j$                         | j&                  rt)        d       | j*                  r|j-                  | j*                         |j/                         }|j1                  d      j3                  d      }|j5                  t        |      d       |j7                          d d d        |j9                  d       |j;                         }t<        D cg c]	  }||v s| }}dD cg c]	  }||v s| }}d| j                   t?        |      t?        |      t?        |      tA        |      ||tA        |      xr | d
}|	j9                  tC        jD                  |dd      dz   d       t        tC        jD                  |dd             y# t        $ r t        d       Y yw xY w# 1 sw Y   
xY wc c}w c c}w )Nr   r   r   r
   r   r   r  Tr   profile_status_r   r1  r   r   r   z`Use the visible browser to sign in or inspect TradingView, then press Enter to capture status...r2  r3  r4  r   rH   rI   )r5  r7  SavePublish)
r.   r   r   r   r   ru   login_prompt_detectedlogin_promptscontrols_seenprofile_ready_hintr   r   r   )#r   r   r   r   r   r   r   r   r   r   r   rO  r   r   r   r   r   r   rA  wait_for_userr   rB  rC  r   rD  rE  r   r   r   lowerLOGIN_PROMPT_PATTERNSrE   r0   r   r   )r   r   r   r   r   rJ  rK  r   rR  rS  r   r   r   r   rT  
lower_textr  r[  itemr\  r   s                        r   profile_statusrc  :  s   7
 dll+G00K},N$H5NN4$N/KE$t'DDO_UG488Iwe<<M		a**66_% 7 

 $+==w}}Qg6F6F6H		$((t	Ptu<<!!$,,/

||F+66t6DS1TB 
" 8##%J,A[,AWPZEZW,AM[&Vo&VdZ^bnZnT&VMoxx$[1#O4i(!%m!4&&"=1G-6GG TZZTJTQ\cd	$**WQ$
78g  YZ  
	& \os6   J >D/J5 	K*K4	K>KJ21J25J?c                R   	 ddl m} t	        | j
                        }t        | j                  || j                        }t        |j                  |j                  |j                  |j                         t        dt        |j                                t!        d |j                  D              ry|dz  }|dz  }|d	z  }|j#                  d
d
       |j#                  d
d
       t%        | j&                  xs d|j                  j(                         }t+               }|| d| dz  }	|| d| dz  }
|| d| dz  }| j,                  xs |j                  j(                  g}| j.                  xs t0        }t                t        d       t        d|j                  j2                   d|j                  j(                          t        dt        |j                                t        d       t        d        |       5 }|j4                  j7                  t9        |      dt:              }|j<                  r|j<                  d   n|j?                         }|jA                  | jB                  | jD                  | jF                         tI        d       | jJ                  r|jM                  | jJ                         |j)                         }|jO                  d      jQ                  d      }|jS                  t9        |	      d
       |jU                          d d d        |
jW                  d        tY        |||      }|d!   | jB                  t[        |j                        t        |j                        t        |j                        t        |	      t        |
      |||d"}|jW                  t]        j^                  |d#d
$      d%z   d        t        t]        j^                  |d#d
$             |d!   rdS dS # t        $ r t        d       Y yw xY w# 1 sw Y   xY w)&Nr   r   r   r
     Source copy: c              3  6   K   | ]  }|j                      y wr?   r9  r*  s     r   r,  z guided_update.<locals>.<genexpr>       
5_Euxx<_   r   r   r  Tr   zmanual-update-r   r   r1  z_manual_update.jsonz,A visible browser will open. In TradingView:z.  1. Open Pine Editor and select the existing z: z*  2. Paste from clipboard, or paste from: zM  3. Save/update the script and confirm the editor reports no compile errors.zDReturn here and press Enter after the save/compile step is complete.Fr   r   z/Press Enter to capture verification evidence...r2  r3  r4  r   rH   rI   r.   )r.   r   
page_titler   r8   r7   r   ru   r  expectedrejectedr   r   r   )0r   r   r   r   r   r   r   r   r   print_summaryr4   r6   r8   r9   rE   r7   anyr   r   rP  r   r   expectrejectDEFAULT_REJECT_PATTERNSr   r   r   r   r   r   r   r   r   r   rA  r   rB  rC  rD  rE  r   r   r   verify_text_contentr   r   r   )r   r   r   preparedr   r   rJ  rP  rK  r   rR  rS  rj  rk  r   r   r   r   rT  r  r   s                        r   guided_updaters  s  s   7
 dll+GDIIw0A0ABH(--(2C2CXEWEWX	OM(*>*>?@
AB

5X__
5500K},N$H5NN4$N/DJJHN8==3F3F2G"HIEKE$%%'==OeWAeWD11Iq/BCCM{{3x}}223H{{55H	G	
89	:8==;M;M:NbQYQ^Q^QdQdPe
fg	6}XEYEY7Z6[
\]	
YZ	
PQ		a**66% 7 

 $+==w}}Qg6F6F6H		$((t	P?@<<!!$,,/

||F+66t6DS1TB 
  8&|XxHL4 xx'!("3"34$X%9%9:#O4i($G TZZTJTQ\cd	$**WQ$
78T"1))E  YZB 
	s   P DPPPP&c                    |D cg c]  }|s|| vs| }}|D cg c]  }|s|| v s| }}| xr | ||dS c c}w c c}w )N)r.   missing_expectedfound_rejectedr   )ru   rj  rk  rb  ru  rv  s         r   rq  rq    sc    )1OTd$>NO'/Ixt4DDLdxNI""9>'9,(  PIs   ;;;A A A c                f   t        | j                        }|j                         s	t        |z  }|j	                  d      }| j
                  xs t        }t        || j                  |      }i |t        |      | j                  |d}t        t        j                  |dd             |d   rdS d	S )
NrH   rI   )ru   rj  rk  r   Tr   r.   r   r
   )r   ru   r   rB   rK   ro  rp  rq  rn  rE   r   r   r   )r   rR  ru   rk  ry   r   s         r   verify_textrx    s    TYYI  "9$	0D{{55H t{{H=F
i(KK	G 
$**WQ$
78t1#!#r   c                x    t        |       j                         st        | z  j                         S t        |       S r?   )r   r   rB   r@   r   s    r   r   r     s-    +/;+B+B+DD5L!!#U$u+Ur   c                   |D cg c]  }|j                   r| }}t        d| j                   d| j                         t        d| j                          t        d| j
                          t        dt        |              t        d|rdnd        t                |rRt        d	       |D ]6  }t        d
dj                  |j                         d|j                          8 t        d       y t        d       t        d
| j                          t                t        d       t        t        j                  dd             y c c}w )Nz Prepared TradingView update for r&  z  Source:   z  SHA-256:  z  Manifest: z  Clipboard: updatedznot availablezPreflight failed:z  r(  z*Fix these before pasting into TradingView.z=Preflight passed. Use the exact same TradingView script name:zNext human-in-the-loop step:zOpen TradingView, select the existing script with that name in Pine Editor, paste from the clipboard, save it, and visually confirm there are no compile errors.X   )r   )r.   r   r   r   r   r   rE   r)  r(   r)   textwrapfill)r4   r6   r8   r9   rv   rI  s         r   rl  rl    s"   !'8uxxeF8	,TYYKq
GH	L
$%	L
&'	Lx01
23	My)oF
GH	G!"EBsxx./tE4D4D3EFG :;MN4::, ,-hmmc
 	# 9s
   EEc                d   t        | j                        }t        | j                  || j                  | j
                  | j                        }t        |j                  |j                  |j                  |j                         t        dt        |j                                t        d |j                  D              ryd}| j
                  rt!        j
                  t"              }d}| j                  rt%        |t"              }|st        d       | j
                  r|sy| j                  r|syy)Nre  c              3  6   K   | ]  }|j                      y wr?   r9  r*  s     r   r,  zprepare.<locals>.<genexpr>  rg  rh  r
   Fr   r   )r   r   r   r   r   openplaywright_openrl  r4   r6   r8   r9   r   rE   r7   rm  
webbrowserr   r   )r   r   rr  r   r   s        r   preparer    s    dll+GDIIw0A0A499dNbNbcH(--(2C2CXEWEWX	OM(*>*>?@
AB

5X__
55Nyy#)>?3G=RS ]^yy$5r   c                    t        | j                        }t        t        j                  t        |      dd             y)Nr   Tr   r   )rq   r   r   r   r   r   )r   r4   s     r   inspectr    s,    dii D	$**VD\!t
<=r   c                    t        j                  t              } | j                  dd      }|j	                  dd      }|j                  dd	       |j                  t        
       |j	                  dd      }|j                  dd       |j                  dt        t        j                  t                           |j                  ddd       |j                  ddd       |j                  ddd       |j                  t        
       |j	                  dd      }|j                  dd       |j                  dt               |j                  dd       |j                  dt        t        j                  t                           |j                  ddd       |j                  dt        dd        |j                  d!t        d"#       |j                  d$g d%d&'       |j                  d(d)g d*+       |j                  d,d)g d-+       |j                  t        
       |j	                  d.d/      }|j                  dt        t        j                  t                           |j                  t         
       |j	                  d0d1      }|j                  d2d3       |j                  dt        t        j                  t                           |j                  d4dd5       |j                  d6dd7       |j                  dt        d8#       |j                  d!t        d"#       |j                  t"        
       |j	                  d9d:      }|j                  dt        t        j                  t                           |j                  t$        
       |j	                  d;d<      }|j                  dt               |j                  dd       |j                  dt        t        j                  t                           |j                  d=dd>       |j                  d?dd@       |j                  dt        dAd        |j                  d!t        d"#       |j                  d$g d%d&'       |j                  t&        
       |j	                  dBdC      }	|	j                  dt               |	j                  dt        t        j                  t                           |	j                  d=ddD       |	j                  dEddF       |	j                  dt        d8#       |	j                  d!t        d"#       |	j                  d$g d%d&'       |	j                  t(        
       |j	                  dGdH      }
|
j                  dIddJK       |
j                  d(d)g dL+       |
j                  d,d)g d-+       |
j                  t*        
       | S )MN)descriptionr(   T)destrequiredr  z"Print parsed Pine metadata as JSON)helpr   zPath to a .pine script)funcr  z(Preflight and stage a TradingView updatez%Path to a .pine strategy or indicatorz	--out-dir)defaultz--no-clipboard
store_truez!Do not copy Pine source to pbcopy)actionr  z--openz-Open TradingView chart in the default browserz--playwright-openzVOpen a visible persistent Playwright browser and save a screenshot after manual reviewzmanual-updatezTStage Pine, open TradingView, wait for manual save, then capture and verify evidencez--urlz--labelrN  z	--wait-msr   zExtra wait before capture)typer  r  z--timeout-msr   )r  r  z--wait-until)commitr   loadnetworkidler   )choicesr  z--expectr~   zHString expected in the captured text. Defaults to the Pine script title.)r  r  r  z--rejectzKString that must not appear. Defaults to common Pine compile-error phrases.smokez2Verify Playwright can launch and save a screenshotr/  zCheck TradingView E2E readinessz--pinez#strategies/strategy_mlp_scores.pinez	--browserz*Launch a local headless browser smoke testz--tradingviewz)Capture TradingView chart render evidencei  r#  z*Summarize latest TradingView E2E artifactsr   z3Navigate to a URL and save screenshot/text metadataz--headedz,Show the browser instead of headless capturez--save-textz-Save visible body text next to the screenshotr   zprofile-statusz9Capture persistent TradingView profile readiness evidencez#Show the persistent browser profilez--wait-for-userz&Wait for Enter before capturing statuszverify-textz5Check captured text for expected and rejected stringsz--textz&Path to captured visible-text artifact)r  r  zHString that must appear in the captured text; repeat for multiple checks)argparseArgumentParserr   add_subparsers
add_parseradd_argumentset_defaultsr  r   DEFAULT_OUT_DIRrA   rB   r  r   r    rs  r   r/  r#  rU  rc  rx  )parser
subparsersinspect_parserprepare_parserguided_parsersmoke_parserdoctor_parserstatus_parsercapture_parserprofile_parserverify_parsers              r   build_parserr    s   $$9F&&I&EJ**9;_*`N-EFW-**9;e*fN-TUS9T9TUY9Z5[\ 0LopDste   
 W-))c * M v,STw0EFy"5{C8S8STX8Y4Z[/Kno{dIde~CHE"  
 W	   Z	   M2((7k(lLk37R7RSW7X3YZ#34))(9Z)[Mx1VW{C8S8STX8Y4Z[{<Frs|Juv{dC~CHF+))(9e)fM{C8S8STX8Y4Z[F+**9;p*qN1FG	26S9T9TUY9Z5[\
<FtulIxy#qGbcS&IE"   
 [1**+;B}*~N1FGS9T9TUY9Z5[\
<Fkl 1,Muv#tDS&IE"   
 ^4))->u)vMx$=efW	   Z	   K0Mr   c                Z    t               }|j                  |       }|j                  |      S r?   )r  
parse_argsr  )argvr  r   s      r   mainr    s'    ^FT"D99T?r   __main__)r   
str | Pathr/   r   )r   r   r/   r   )rW   r   rX   r   r/   z
str | None)rc   r   r/   r   )r   r  r/   r   )r(   r'   r/   r&   )ro   r  r/   r5   )ru   r   r/   r0   )r   r   r4   r   r/   r   )r/   r   )r   r   r/   r   )r   r   r4   r   r6   r5   r9   r0   r   r0   r   r0   r7   r   r/   r   )r   r   r   r   r/   r0   )r   r   r4   r   rW   r   r/   r   )FF)r   r   r   r   r   r0   r   r0   r   r0   r/   r3   )r   zargparse.Namespacer/   r    )
r6   zlist[DoctorCheck]r<   r   r.   r0   r=   r   r/   None)r  z
list[Path]r/   Path | None)r  r   r  r   r/   r  )r   r  r/   zdict[str, Any] | None)ru   r   rj  r'   rk  r'   r/   zdict[str, Any])r   r   r/   r   )
r4   r   r6   r5   r8   r   r9   r0   r/   r  )r/   zargparse.ArgumentParserr?   )r  zlist[str] | Noner/   r    )Ir   
__future__r   r  rk   importlib.metadatar>  r   rQ   r   rw   r|   r}  r  dataclassesr   r   r   r   pathlibr   typingr	   __file__r@   r   rB   r  r   r   rp  r`  rC   r   r   r&   r3   r;   rE   rK   r_   rf   rq   rz   r   r   r   r   r   r   r   r   r   r   r   r  r	  r  r#  r/  rU  rc  rs  rq  rx  r   rl  r  r  r  r  r   
SystemExitr   r   r   <module>r     si   #     	   
   ) '   H~''*++< !T2   J BZ B $   $$ $ $ $   $  #,<	A2 	8
AK,,
, , 	,
 , , , 
,^4 !#
  	
  6%B@M1#%L^%B0f6rE*P$"V24pf z
TV
 r   