#!/usr/bin/env python3
"""Real installer evidence. Requires genuine v0.1.8 release files and built npm launchers.
Usage: python prove.py WORKTREE BUILT_PACKAGE RELEASE_FILES OUTPUT_PARENT SIDE
Build each package with: vp exec node scripts/build-npm-launcher.ts --version 0.1.8 --output-dir OUTPUT
Download SHA256SUMS and t3-0.1.8-linux-x64.tar.gz from the official v0.1.8 release.
Only the hard-coded shell latest-release URL is redirected by a curl shim; all HTTP is real.
No installer logic, sleeps, archive contents, checksums, or executable is replaced.
"""
import os, sys, subprocess, time, json, threading, http.server, pathlib, pty, select, fcntl, termios, struct, hashlib
worktree, package, releases, parent, side = map(pathlib.Path, sys.argv[1:])
side = str(side)
out = parent / (side + '-' + time.strftime('%Y%m%dT%H%M%S'))
out.mkdir(parents=True)
start = time.monotonic()
cast = open(out / (side+'.cast'), 'w')
cast.write(json.dumps({'version':2,'width':120,'height':42,'timestamp':int(time.time()),'env':{'TERM':'xterm-256color'},'title':side+' - real CLI installer HTTP 504 evidence'})+'\n')
transcript = open(out/(side+'.txt'),'w')
lock = threading.Lock()
replacements = [(os.path.expanduser('~'), '<user-home>'), (str(out), '<run>'), (str(worktree), '<checkout>'), (str(package), '<npm-package>')]
def emit(s):
    for a,b in sorted(replacements,key=lambda x:len(x[0]),reverse=True): s=s.replace(a,b)
    with lock:
        cast.write(json.dumps([round(time.monotonic()-start,3),'o',s])+'\n'); cast.flush()
        transcript.write(s); transcript.flush()
        sys.stdout.write(s); sys.stdout.flush()
archive='t3-0.1.8-linux-x64.tar.gz'
expected=[l.split()[0] for l in (releases/'SHA256SUMS').read_text().splitlines() if l.endswith(' '+archive)][0]
assert hashlib.sha256((releases/archive).read_bytes()).hexdigest()==expected
state={}
class Mirror(http.server.BaseHTTPRequestHandler):
    def log_message(self,*a): pass
    def do_GET(self):
        key='release' if self.path=='/latest' else ('checksum' if self.path.endswith('/SHA256SUMS') else 'archive')
        state['counts'][key]=state['counts'].get(key,0)+1
        n=state['counts'][key]
        bad=key==state['target'] and n<=state['failures']
        emit(f'\r\n[release mirror] {key} request {n} -> HTTP {504 if bad else 200}\r\n')
        data=b'Gateway Timeout\n' if bad else (b'{"tag_name":"v0.1.8"}' if key=='release' else None)
        self.send_response(504 if bad else 200)
        file=None
        if data is None:
            file=open(releases/('SHA256SUMS' if key=='checksum' else archive),'rb')
            size=os.fstat(file.fileno()).st_size
        else: size=len(data)
        self.send_header('Content-Length', str(size)); self.end_headers()
        try:
            if file:
                while chunk:=file.read(1024*1024): self.wfile.write(chunk)
            else: self.wfile.write(data)
        except (BrokenPipeError,ConnectionResetError): pass
        finally:
            if file: file.close()
server=http.server.ThreadingHTTPServer(('127.0.0.1',0),Mirror)
threading.Thread(target=server.serve_forever,daemon=True).start()
url=f'http://127.0.0.1:{server.server_port}'
shim=out/'transport'; shim.mkdir()
realcurl=subprocess.check_output(['which','curl'],text=True).strip()
(shim/'curl').write_text('#!/usr/bin/env python3\nimport os,sys\na=[os.environ["EVIDENCE_MIRROR"]+"/latest" if x=="https://github.com/pingdotgg/t3code/releases/latest" else x for x in sys.argv[1:]]\nos.execv('+repr(realcurl)+',['+repr(realcurl)+']+a)\n')
(shim/'curl').chmod(0o755)
sha=subprocess.check_output(['git','-C',str(worktree),'rev-parse','HEAD'],text=True).strip()
results=[]
cases=[('shell',k,n,False) for n in (1,4) for k in ('release','checksum','archive')]+[('shell','archive',n,True) for n in (1,4)]+[('npm',k,n,False) for n in (1,4) for k in ('checksum','archive')]
try:
    for index,(kind,target,failures,interactive) in enumerate(cases,1):
        state.update(target=target,failures=failures,counts={})
        run=out/f'case-{index}'; run.mkdir()
        env=os.environ.copy()
        env.update(T3CODE_HOME=str(run/'home'),T3CODE_INSTALL_BIN_DIR=str(run/'bin'),TMPDIR=str(run),T3CODE_RELEASE_BASE_URL=url,EVIDENCE_MIRROR=url,PATH=str(shim)+':'+env['PATH'],TERM='xterm' if interactive else 'dumb',NO_COLOR='1',SHELL='/bin/sh',T3CODE_DEV_SEED='0')
        cmd=['sh','scripts/install.sh'] if kind=='shell' else ['node',str(package/'bin/t3.mjs'),'--version']
        title=f'{kind} | {target} | {failures} HTTP 504 response(s) | '+('TTY progress' if interactive else 'TERM=dumb')
        emit('\x1b[2J\x1b[H'+f'{side.upper()} - commit {sha[:12]}\r\nLinux x64 / glibc / Node 26.12.1 / 120x42 dark terminal\r\nFresh isolated runtime; genuine v0.1.8 archive; no database or credentials\r\nCase {index}/{len(cases)}: {title}\r\nCommand: '+('sh scripts/install.sh' if kind=='shell' else 'node <built-package>/bin/t3.mjs --version')+'\r\n'+'-'*100+'\r\n')
        master,slave=pty.openpty()
        fcntl.ioctl(slave,termios.TIOCSWINSZ,struct.pack('HHHH',42,120,0,0))
        proc=subprocess.Popen(cmd,cwd=worktree,env=env,stdin=subprocess.DEVNULL,stdout=slave,stderr=slave)
        os.close(slave)
        while True:
            ready,_,_=select.select([master],[],[],0.1)
            if ready:
                try: b=os.read(master,65536)
                except OSError: break
                if not b: break
                emit(b.decode('utf8','replace'))
            elif proc.poll() is not None: break
        os.close(master); code=proc.wait()
        complete=(run/'home/runtime/versions/0.1.8/.install-complete').exists()
        item=dict(case=index,kind=kind,target=target,failures=failures,interactive=interactive,exit=code,complete=complete,requests=dict(state['counts']))
        results.append(item)
        emit(f'\r\nRESULT: exit={code}; complete runtime={complete}; requests={state["counts"]}\r\n')
        if kind=='shell' and complete:
            check=subprocess.run([str(run/'bin/t3'),'--version'],env=env,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True)
            emit('Installed command: t3 --version\r\n'+check.stdout.replace('\n','\r\n')+f'exit={check.returncode}\r\n')
        time.sleep(1.5)
    emit('\r\nAll 12 real-command scenarios finished.\r\n')
    time.sleep(2)
finally:
    server.shutdown();server.server_close();cast.close();transcript.close()
(out/'results.json').write_text(json.dumps(dict(side=side,sha=sha,archiveSha256=expected,results=results),indent=2))
print('\nEvidence directory:',out)
