import pathlib,os,signal,subprocess,re,time
R=pathlib.Path('/tmp/lead-33036-r2/evidence-capture-2/20261110-gap')
roots=[int((R/(s+'-launch.pid')).read_text()) for s in ['before','after']]
parents={}
for p in pathlib.Path('/proc').iterdir():
 if not p.name.isdigit():continue
 try:
  stat=(p/'stat').read_text();ppid=int(stat[stat.rfind(')')+2:].split()[1]);parents.setdefault(ppid,[]).append(int(p.name))
 except (OSError,ValueError):pass
owned=[]
def walk(pid):
 owned.append(pid)
 for child in parents.get(pid,[]):walk(child)
for root in roots:walk(root)
ports=['7856','8524','15896','16564']
check=lambda:subprocess.run(['ss','-H','-ltnp','( '+' or '.join('sport = :'+p for p in ports)+' )'],capture_output=True,text=True,check=True).stdout
for line in check().splitlines():
 for val in re.findall(r'pid=(\d+)',line):
  pid=int(val);cwd=pathlib.Path(f'/proc/{pid}/cwd').resolve()
  assert str(cwd) in ['/home/user/wt/pr-33036','/home/user/wt/pr-33036/apps/web','/home/user/wt/pr-33036/apps/server','/home/user/wt/pr-33036-before','/home/user/wt/pr-33036-before/apps/web','/home/user/wt/pr-33036-before/apps/server'],(pid,cwd)
  if pid not in owned:walk(pid)
for pid in owned:
 try:os.kill(pid,signal.SIGTERM)
 except ProcessLookupError:pass
for n in range(50):
 if not check():break
 time.sleep(.1)
assert not check(),'Owned ports still listening'
(R/'cleanup-report.txt').write_text('Stopped both tracked dev-server launch processes and their descendants; confirmed owners of all four captured ports belonged to the two checkouts. All four ports are closed.\n')
print('Stopped tracked servers and descendants; all four ports closed.')
