import os, sys, pathlib, subprocess, time, json, hashlib, datetime
side, checkout = sys.argv[1:]
root = pathlib.Path(__file__).parent
run = root / (side + '-' + datetime.datetime.now().strftime('%Y%m%d-%H%M%S'))
run.mkdir()
home = run / 'state'
logs = home / 'userdata/logs'
logs.mkdir(parents=True)
sha = subprocess.check_output(['git','rev-parse','HEAD'],cwd=checkout,text=True).strip()
fixtures = {'server-child.log':['1','3','10','011','11.0','11e0','0xb','+11','notes','11','50'], 'renderer-history.ndjson':['1','2','03','3.0','3e0','0x3','+3','notes','3','50']}
for name,suffixes in fixtures.items():
 for suffix in suffixes: (logs / (name+'.'+suffix)).write_text('Synthetic saved copy: '+suffix+'\n')
def report(stage):
 lines = ['DESKTOP LOG PRUNING - '+side.upper(), 'Commit: '+sha[:10], 'Linux / Electron / isolated synthetic state', '', stage, 'Backend limit: 10     Renderer-history limit: 2', '']
 for name,suffixes in fixtures.items():
  lines += [name]
  for suffix in suffixes:
   present=(logs/(name+'.'+suffix)).exists()
   lines += ['  '+('.'+suffix).ljust(10)+('PRESENT' if present else 'DELETED')]
  lines += ['']
 text='\n'.join(lines)
 (run / (stage.lower().replace(' ','-')+'.txt')).write_text(text+'\n')
 return text
seed=report('Before app launch')
viewer=subprocess.Popen(['xmessage','-geometry','620x1010+0+0','-fn','fixed','-title','Filesystem observation','-buttons','','-file',str(run/'before-app-launch.txt')])
env=os.environ.copy()
env.update(T3CODE_HOME=str(home), T3CODE_DEV_SEED='0', T3CODE_DISABLE_AUTO_UPDATE='true', T3CODE_PORT='15871', XDG_CONFIG_HOME=str(run/'config'), XDG_DATA_HOME=str(run/'data'))
env.pop('ELECTRON_RUN_AS_NODE',None)
video=subprocess.Popen(['ffmpeg','-y','-loglevel','error','-f','x11grab','-video_size','1920x1080','-framerate','8','-i',os.environ['DISPLAY'],'-c:v','libx264','-preset','ultrafast','-pix_fmt','yuv420p',str(run/'startup.mp4')],stderr=open(run/'ffmpeg.log','w'))
app=None
try:
 time.sleep(2)
 binary=str(pathlib.Path(checkout)/'apps/desktop/node_modules/electron/dist/electron')
 app=subprocess.Popen([binary,'--no-sandbox','--disable-gpu',str(pathlib.Path(checkout)/'apps/desktop/dist-electron/boot.cjs')],cwd=checkout,env=env,stdout=open(run/'electron-private.log','w'),stderr=subprocess.STDOUT)
 time.sleep(20)
 subprocess.run(['wmctrl','-r','T3 Code','-e','0,640,0,1260,1040'])
 viewer.terminate(); viewer.wait()
 observation=report('After app startup')
 viewer=subprocess.Popen(['xmessage','-geometry','620x1010+0+0','-fn','fixed','-title','Filesystem observation','-buttons','','-file',str(run/'after-app-startup.txt')])
 time.sleep(3)
 # The filesystem report is static; capture it twice to verify stability.
 for index in (1,2):
  subprocess.run(['import','-window','root',str(run/f'desktop-{index}.png')],check=True)
  time.sleep(.5)
 subprocess.run(['import','-window','Filesystem observation',str(run/'files.png')],check=True)
 print(observation,flush=True)
 print('RUN_DIRECTORY='+str(run),flush=True)
finally:
 video.send_signal(2); video.wait()
 viewer.terminate(); viewer.wait()
 if app and app.poll() is None:
  app.terminate()
  try: app.wait(timeout=15)
  except subprocess.TimeoutExpired: app.kill(); app.wait()
