from __future__ import annotations import argparse import hashlib import json import re from pathlib import Path REPOSITORY_ROOT = Path(__file__).resolve().parents[2] ORIGINAL_STATIC = REPOSITORY_ROOT / "static" FRONTEND_ROOT = REPOSITORY_ROOT / "app" / "frontend" EVIDENCE_PATH = ( REPOSITORY_ROOT / "docs" / "migration" / "evidence" / "slice-10" / "frontend-source-map.json" ) EXPECTED_SOURCE_SHA256 = "c020d0bc68f8a96b352a0ffa62c913a0ea3f5ca0afc41f70969f833e447166a6" RUNTIME_RANGES: dict[str, list[tuple[int, int]]] = { "pages/sentiment/page.js": [(1207, 1516)], "pages/pools/page.js": [(1517, 1915)], "pages/market/runtime.js": [(1916, 1957), (6893, 7719), (7969, 8426)], "pages/rotation/page.js": [(1958, 2124)], "pages/ladder/page.js": [(2125, 2216)], "pages/auction/page.js": [(2217, 2481)], "pages/themes/page.js": [(2482, 2583)], "pages/popularity/page.js": [(2584, 2659)], "pages/dragon-tiger/page.js": [(2660, 3028)], "pages/review/page.js": [(3029, 3470), (7720, 7968)], "pages/screener/page.js": [(3490, 4336), (6668, 6892)], "pages/mentor/page.js": [(4337, 4827)], "pages/heaven/page.js": [(4828, 6667)], "shared/export.js": [(8905, 9051)], } def digest(content: str) -> str: return hashlib.sha256(content.encode("utf-8")).hexdigest() def marker(start: int, end: int, kind: str) -> str: return f"/* PRESERVATION-SOURCE-{kind} app.js:{start}-{end} */" def wrapped_chunk(lines: list[str], start: int, end: int) -> str: content = "".join(lines[start - 1 : end]) return f"{marker(start, end, 'BEGIN')}\n{content}{marker(start, end, 'END')}\n" def complement_ranges(total: int, moved: set[int]) -> list[tuple[int, int]]: ranges: list[tuple[int, int]] = [] start = 0 for number in range(1, total + 1): if number in moved: if start: ranges.append((start, number - 1)) start = 0 elif not start: start = number if start: ranges.append((start, total)) return ranges def original_prefix(relative: str) -> str: source = ORIGINAL_STATIC / relative if not source.is_file(): return "" return source.read_text(encoding="utf-8").rstrip("\n") + "\n\n" def extract_written_chunks(paths: list[Path]) -> dict[tuple[int, int], str]: pattern = re.compile( r"/\* PRESERVATION-SOURCE-BEGIN app\.js:(\d+)-(\d+) \*/\n" r"(.*?)" r"/\* PRESERVATION-SOURCE-END app\.js:\1-\2 \*/\n?", re.DOTALL, ) chunks: dict[tuple[int, int], str] = {} for path in paths: content = path.read_text(encoding="utf-8") for match in pattern.finditer(content): key = (int(match.group(1)), int(match.group(2))) if key in chunks: raise RuntimeError(f"Duplicate preserved range {key}") chunks[key] = match.group(3) return chunks def main() -> None: parser = argparse.ArgumentParser( description="Reproduce the one-time Slice 10 frontend source split" ) parser.add_argument( "--apply", action="store_true", help="perform the historical split; this rewrites frontend runtime files", ) args = parser.parse_args() if not args.apply: parser.error( "this migration-only tool rewrites files; pass --apply only when " "reproducing Slice 10 from its documented pre-split checkpoint" ) source_path = ORIGINAL_STATIC / "app.js" target_path = FRONTEND_ROOT / "app.js" source_bytes = source_path.read_bytes() source_sha256 = hashlib.sha256(source_bytes).hexdigest() if source_sha256 != EXPECTED_SOURCE_SHA256: raise RuntimeError( f"Original app.js changed: expected {EXPECTED_SOURCE_SHA256}, got {source_sha256}" ) if not target_path.is_file(): raise RuntimeError(f"Missing target runtime: {target_path}") if hashlib.sha256(target_path.read_bytes()).hexdigest() != EXPECTED_SOURCE_SHA256: raise RuntimeError("Target app.js is not the exact pre-split original") source = source_bytes.decode("utf-8") lines = source.splitlines(keepends=True) moved_lines: set[int] = set() for ranges in RUNTIME_RANGES.values(): for start, end in ranges: overlap = moved_lines.intersection(range(start, end + 1)) if overlap: raise RuntimeError(f"Overlapping source ranges at line {min(overlap)}") moved_lines.update(range(start, end + 1)) core_ranges = complement_ranges(len(lines), moved_lines) target_path.write_text( "\n".join(wrapped_chunk(lines, start, end).rstrip("\n") for start, end in core_ranges) + "\n", encoding="utf-8", ) written_paths = [target_path] for relative, ranges in RUNTIME_RANGES.items(): path = FRONTEND_ROOT / relative path.parent.mkdir(parents=True, exist_ok=True) chunks = "\n".join( wrapped_chunk(lines, start, end).rstrip("\n") for start, end in ranges ) path.write_text(original_prefix(relative) + chunks + "\n", encoding="utf-8") written_paths.append(path) extracted = extract_written_chunks(written_paths) expected_ranges = { source_range for ranges in RUNTIME_RANGES.values() for source_range in ranges } | set(core_ranges) if set(extracted) != expected_ranges: raise RuntimeError("Written source ranges do not cover the original runtime exactly") reassembled = [""] * len(lines) for (start, end), content in extracted.items(): chunk_lines = content.splitlines(keepends=True) if len(chunk_lines) != end - start + 1: raise RuntimeError(f"Line count changed in preserved range {start}-{end}") reassembled[start - 1 : end] = chunk_lines reassembled_source = "".join(reassembled) if reassembled_source != source: raise RuntimeError("Split runtime cannot be reassembled byte-for-byte") manifest = { "source": "static/app.js", "source_sha256": source_sha256, "source_line_count": len(lines), "reassembled_sha256": digest(reassembled_source), "all_source_lines_preserved": True, "core": { "target": "app/frontend/app.js", "ranges": [{"start": start, "end": end} for start, end in core_ranges], }, "modules": [ { "target": f"app/frontend/{relative}", "ranges": [ { "start": start, "end": end, "sha256": digest("".join(lines[start - 1 : end])), } for start, end in ranges ], } for relative, ranges in RUNTIME_RANGES.items() ], } EVIDENCE_PATH.parent.mkdir(parents=True, exist_ok=True) EVIDENCE_PATH.write_text( json.dumps(manifest, ensure_ascii=False, indent=2) + "\n", encoding="utf-8" ) print(json.dumps(manifest, ensure_ascii=False, indent=2)) if __name__ == "__main__": main()