import sys, pathlib, sqlite3, subprocess, hashlib, time, json, re
root=pathlib.Path(sys.argv[1]); scratch=pathlib.Path(sys.argv[2]); side=sys.argv[3]
records=[]; lines=[]
def emit(s):
 print(s,flush=True); lines.extend(s.splitlines()); records.append((time.monotonic(),list(lines)))
def digest(p):
 return hashlib.sha256(p.read_bytes()).hexdigest() if p.exists() else 'absent'
emit('REAL CLI CAPTURE | Linux | Node '+subprocess.check_output(['node','--version'],text=True).strip())
emit('Commit: '+subprocess.check_output(['git','rev-parse','HEAD'],cwd=root,text=True).strip())
emit('Synthetic data only; no server running; isolated destination; projects=5; threads=10')
for kind in ['pre-v2','schema-migrated']:
 source=scratch/(kind+'.sqlite'); dest=scratch/(side+'-'+kind)/'userdata'; dest.mkdir(parents=True)
 db=dest/'statev2.sqlite'; conn=sqlite3.connect(db)
 conn.execute('pragma journal_mode=wal'); conn.execute('create table evidence_marker(value text)'); conn.commit()
 conn.execute("insert into evidence_marker values ('existing destination with uncheckpointed WAL')"); conn.commit()
 wal=pathlib.Path(str(db)+'-wal'); before=(digest(db),digest(wal)); srcbefore=digest(source)
 src=sqlite3.connect('file:'+str(source)+'?mode=ro',uri=True)
 legacy=src.execute('select count(*) from projection_threads').fetchone()[0]
 v2=src.execute("select count(*) from sqlite_master where name='orchestration_v2_projection_threads'").fetchone()[0]; src.close()
 emit('\nSOURCE: '+kind+' | legacy threads='+str(legacy)+' | V2 table present='+str(bool(v2)))
 emit('$ node apps/server/scripts/migrate-dev-db.ts --source <synthetic-source> --base-dir <isolated-destination> --projects 5 --threads-per-project 10')
 p=subprocess.Popen(['node','apps/server/scripts/migrate-dev-db.ts','--source',str(source),'--base-dir',str(dest.parent),'--projects','5','--threads-per-project','10'],cwd=root,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True)
 for line in p.stdout:
  line=re.sub(r'\x1b\[[0-9;]*m','',line.rstrip()).replace(str(scratch),'<evidence>').replace(str(root),'<checkout>')
  line=re.sub(r'/home/[^\s:)]+','<runtime>',line)
  emit(line)
 code=p.wait(); after=(digest(db),digest(wal))
 emit('EXIT STATUS: '+str(code))
 emit('Destination database bytes unchanged: '+str(before[0]==after[0]))
 emit('Destination WAL bytes unchanged: '+str(before[1]==after[1]))
 emit('Source database bytes unchanged: '+str(srcbefore==digest(source)))
 if code==0:
  out=sqlite3.connect('file:'+str(db)+'?mode=ro',uri=True)
  emit('DESTINATION: legacy threads='+str(out.execute('select count(*) from projection_threads').fetchone()[0])+' | V2 threads='+str(out.execute('select count(*) from orchestration_v2_projection_threads').fetchone()[0])); out.close()
 conn.close()
(scratch/(side+'.txt')).write_text('\n'.join(lines)+'\n')
(scratch/(side+'-frames.json')).write_text(json.dumps(records))
