#!/usr/bin/env python3 """Generate a deterministic BUG-REPORT.html from data/reports/*.json. Every field is HTML-escaped; the page is self-contained (no external assets). Output is stable for a given set of reports — no wall-clock timestamps. """ import glob import html import json import os import sys ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) REPORTS_DIR = os.path.join(ROOT, "data", "reports") OUT_FILE = os.path.join(ROOT, "downloads", "bugs", "BUG-REPORT.html") MAX_REPORTS = 200 def esc(value): return html.escape("" if value is None else str(value), quote=True) def load_reports(): rows = [] for path in sorted(glob.glob(os.path.join(REPORTS_DIR, "RPT-*.json"))): try: with open(path, encoding="utf-8") as fh: rec = json.load(fh) if isinstance(rec, dict) and rec.get("id"): rows.append(rec) except (OSError, ValueError): continue rows.sort(key=lambda r: (str(r.get("created_at", "")), str(r.get("id", ""))), reverse=True) return rows[:MAX_REPORTS] def pretty(value, limit=6000): try: text = json.dumps(value, indent=2, ensure_ascii=False) except (TypeError, ValueError): text = str(value) if len(text) > limit: text = text[:limit] + "\n… (truncated)" return esc(text) def render(rows): total = len(rows) latest = esc(rows[0].get("created_at", "—")) if rows else "—" cards = [] for rec in rows: diag = rec.get("diagnostics") if isinstance(rec.get("diagnostics"), dict) else {} errors = diag.get("errors") if isinstance(diag.get("errors"), list) else [] cards.append( f"""

{esc(rec.get('title', '(untitled)'))}

{esc(rec.get('id', ''))}

{esc(rec.get('created_at', ''))} · version {esc(diag.get('version', 'unknown'))} · {len(errors)} error(s)

{f'

{esc(rec.get("body"))}

' if rec.get('body') else ''}
Diagnostics
{pretty(diag)}
""" ) if not cards: cards.append('

No reports yet. Run bug <title> in newOS4.

') return f""" newOS4 — Bug Reports

🐞 newOS4 Bug Reports

Generated from data/reports/*.json — no manual edits.

{total}reports
{esc(latest)}latest report
{chr(10).join(cards)}
""" def main(): rows = load_reports() page = render(rows) os.makedirs(os.path.dirname(OUT_FILE), exist_ok=True) with open(OUT_FILE, "w", encoding="utf-8") as fh: fh.write(page) os.chmod(OUT_FILE, 0o664) print(f"wrote {OUT_FILE} ({len(rows)} report(s), {len(page)} bytes)") return 0 if __name__ == "__main__": sys.exit(main())