import json, pathlib, re, shutil, zipfile, datetime, os
root=pathlib.Path(__file__).parent
final=pathlib.Path((root/'final-run-private.txt').read_text())
public=root/'public';public.mkdir(exist_ok=True)
logs=public/'redacted-runtime-logs';logs.mkdir(exist_ok=True)
fixture_providers={'auditplain','audit/slash','audit/hub','audit','lateplain','late/hub','late'}
fixture_slugs={'default','bare-slug','/leading','trailing/','auditplain/haiku-fixture','audit/slash/haiku-fixture','audit/hub/family/model','lateplain/haiku-fixture','late/hub/haiku-fixture'}
secrets=[]
local_config=json.load(open('/home/user/.pi/agent/models.json'))
for v in local_config['providers'].values():
 for k in ['apiKey','baseUrl']:
  if v.get(k):secrets.append(v[k])
for file in [*root.glob('token-*-private.txt'),*final.glob('token-*-private.txt')]:
 secrets.extend(x.strip() for x in file.read_text().splitlines() if x.strip())
for key,value in os.environ.items():
 if re.search(r'(API_KEY|AUTH_TOKEN|ACCESS_TOKEN|AUTHORIZATION|SECRET|PASSWORD)$',key) and len(value)>6:secrets.append(value)
def redact_text(s):
 s=s.replace('<token>','<token>')
 for secret in sorted(set(secrets),key=len,reverse=True):s=s.replace(secret,'<token>' if not secret.startswith('http') else '<url>')
 s=re.sub(r'https?://[^\s<>"\x27`\\]+','<url>',s)
 s=re.sub(r'(?i)(Bearer\s+)[A-Za-z0-9._~+/-]+',r'\1<token>',s)
 s=re.sub(r'(?i)\b(gpt-[a-z0-9_.-]+|claude-[a-z0-9_.-]+|grok-[a-z0-9_.-]+)\b','<redacted-runtime-model>',s)
 return s
def redact(x):
 if isinstance(x,dict):
  if 'instanceId' in x and 'driver' in x and not str(x['instanceId']).startswith('evidence-'):
   return {'redacted':'unrelated configured provider and runtime model metadata'}
  if 'slug' in x and 'name' in x and x['slug'] not in fixture_slugs:
   return {'redacted':'unrelated runtime model metadata'}
  if 'provider' in x and 'id' in x and ('api' in x or 'contextWindow' in x) and x['provider'] not in fixture_providers:
   return {'provider':'<redacted-provider>','id':'<redacted-runtime-model>','redacted':'unrelated Pi inventory entry'}
  return {k:redact(v) for k,v in x.items()}
 if isinstance(x,list):return [redact(v) for v in x]
 return redact_text(x) if isinstance(x,str) else x
def copy_redacted(src,dest):
 dest.parent.mkdir(parents=True,exist_ok=True)
 if src.suffix=='.json':dest.write_text(json.dumps(redact(json.loads(src.read_text())),indent=2)+'\n')
 elif src.suffix=='.jsonl' or src.name.startswith('driver-'):
  out=[]
  for line in src.read_text().splitlines():
   try:out.append(json.dumps(redact(json.loads(line))))
   except json.JSONDecodeError:out.append(redact_text(line))
  dest.write_text('\n'.join(out)+'\n')
 else:dest.write_text(redact_text(src.read_text()))
runs={}
for side in ['before','after']:
 for scenario in ['base','collision','late','fault','malformed']:
  source=final/f'driver-{side}-{scenario}.log'
  records=[json.loads(x) for x in source.read_text().splitlines()]
  run=pathlib.Path(next(x['data']['run'] for x in records if x['event']=='finished'))
  runs[(side,scenario)]={'dir':run,'records':records}
  copy_redacted(source,logs/side/scenario/'driver.jsonl')
  for file in [*run.glob('pi-*.jsonl'),*run.glob('F*.json'),run/'pi-agent/models.json',run/'pi-agent/settings.json']:
   copy_redacted(file,logs/side/scenario/file.name)
for side in ['before','after']:copy_redacted(final/f'dev-{side}-private.log',logs/f'dev-{side}.redacted.log')
copy_redacted(final/'supervisor.jsonl',logs/'supervisor.jsonl')
copy_redacted(root/'alias-private.log',logs/'alias-proxy.redacted.log')
copy_redacted(root/'install-before-private.log',logs/'install-before.redacted.log')
(logs/'README.md').write_text('Final, fresh-database runtime captures only. Original logs remain private. Redactions replace URLs, credentials, unrelated configured provider snapshots, and unrelated runtime model metadata. Pi fixture models and synthetic identifiers are preserved. No live T3 database was read or copied. The alias proxy log includes exploratory fixture calls as well as the final run; timestamps distinguish them.\n')
for name in ['driver.mjs','pi-interposer.mjs','fixtures.ts','alias-proxy.mjs','run-matrix.mjs','package-evidence.py','build-report.py']:
 # These sources contain runtime credential readers, but no credential values.
 (public/name).write_text((root/name).read_text().replace('<token>','<token>'))
archive=public/'redacted-runtime-logs.zip'
with zipfile.ZipFile(archive,'w',zipfile.ZIP_DEFLATED) as z:
 for f in logs.rglob('*'):
  if f.is_file():z.write(f,f.relative_to(public))
print('Packaged',len(list(logs.rglob('*'))),'paths;',archive.stat().st_size,'archive bytes')
print('Sensitive-value scan:')
bad=[]
for file in public.rglob('*'):
 if not file.is_file() or file.suffix=='.zip':continue
 text=file.read_text()
 for secret in secrets:
  if len(secret)>6 and secret in text:bad.append((str(file),'<matched private value>'))
 if re.search(r'(?i)\bgpt-[\w.-]+|\bclaude-[\w.-]+|\bgrok-[\w.-]+',text):bad.append((str(file),'<runtime model pattern>'))
 if re.search(r'https?://(?!127\.0\.0\.1|localhost|git\.cafe/|github\.com/|gh-file-drop-api-prod-mi5fy3sowv63ufte\.pinglabs\.workers\.dev/)[^\s<>"\x27`]+',text):bad.append((str(file),'<unexpected external URL>'))
print(json.dumps(bad));assert not bad
(root/'selected-runs-private.json').write_text(json.dumps({f'{side}:{scenario}':str(v['dir']) for (side,scenario),v in runs.items()},indent=2))
