our_knp/mnist-artifact/prepare.py

63 lines
3.1 KiB
Python

#!/usr/bin/env python3
"""Extract the saved inner artifact, preserving its UI and inference code."""
from pathlib import Path
import concurrent.futures
import hashlib
import json
import re
import urllib.request
import zipfile
ROOT = Path(__file__).resolve().parent
ARCHIVE = ROOT.parent / 'reports/2026-10-21/artifact/chrome-export.zip'
OUT = ROOT / 'site'
OUT.mkdir(exist_ok=True)
with zipfile.ZipFile(ARCHIVE) as z:
names = z.namelist()
inner = next(n for n in names if n.endswith('/saved_resource.html'))
original = z.read(inner).decode('utf-8')
css = z.read(next(n for n in names if n.endswith('/css2'))).decode('utf-8')
scripts = re.findall(r'<script\b[^>]*>(.*?)</script>', original, re.S)
assert len(scripts) == 3 and scripts[2].lstrip().startswith('const D = ')
app = scripts[2]
# Chrome saves the already populated DOM. The original code appends these controls.
reset = '// Remove Chrome-saved controls before the original application recreates them.\n' \
'document.getElementById("switch").replaceChildren();\n' \
'document.getElementById("gal").replaceChildren();\n'
(OUT / 'app.js').write_text(reset + app)
html = re.sub(r'<script\b[^>]*>.*?</script>', '', original, flags=re.S)
html = re.sub(r'<!-- saved from url=.*?-->', '', html)
html = html.replace('<html>', '<html lang="ru">', 1)
html = html.replace('<head>', '<head><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">', 1)
html = html.replace('href="./css2"', 'href="./fonts.css"')
html = re.sub(r'<link rel="preconnect"[^>]*>', '', html)
html = html.replace('</body>', '<script src="./app.js"></script>\n</body>')
(OUT / 'index.html').write_text(html)
fonts = OUT / 'fonts'
fonts.mkdir(exist_ok=True)
urls = sorted(set(re.findall(r'url\((https://[^)]+)\)', css)))
def fetch(url):
name = hashlib.sha256(url.encode()).hexdigest()[:20] + '.woff2'
target = fonts / name
if not target.exists():
with urllib.request.urlopen(url, timeout=30) as r:
target.write_bytes(r.read())
return url, './fonts/' + name
with concurrent.futures.ThreadPoolExecutor(max_workers=6) as pool:
for url, local in pool.map(fetch, urls):
css = css.replace(url, local)
(OUT / 'fonts.css').write_text(css)
manifest = {
'source': 'https://claude.ai/artifact/Vc1q1WCZuPY2QAHBSGtrKF',
'export_url': 'http://drop.t.snw.su/mearl',
'archive_sha256': hashlib.sha256(ARCHIVE.read_bytes()).hexdigest(),
'inner_html_sha256': hashlib.sha256(original.encode()).hexdigest(),
'original_app_sha256': hashlib.sha256(app.encode()).hexdigest(),
'changes': ['remove Claude iframe runtime', 'clear saved controls before original startup',
'local font files', 'viewport and Russian document language'],
'inference_code_and_weights': 'preserved verbatim after the control-reset prelude',
'files': {str(p.relative_to(OUT)): hashlib.sha256(p.read_bytes()).hexdigest()
for p in sorted(OUT.rglob('*')) if p.is_file()},
}
(ROOT / 'SOURCE.json').write_text(json.dumps(manifest, ensure_ascii=False, indent=2) + '\n')
print(json.dumps({'fonts': len(urls), 'files': len(manifest['files']), 'archive_sha256': manifest['archive_sha256']}))