"""No desktop needed; rendering requires only optional Playwright + Chromium shell.""" import argparse import json import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parents[1])) from src.qa.headless import audit_pair, render_pair, write_review def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('source', type=Path); parser.add_argument('translated', type=Path) parser.add_argument('--manifest', type=Path); parser.add_argument('--structure', type=Path) parser.add_argument('--out', type=Path, default=Path('.work/headless-qa')) parser.add_argument('--render', action='store_true'); parser.add_argument('--chapter', action='append') parser.add_argument('--max-documents', type=int, default=4); parser.add_argument('--pages', type=int, default=2) args = parser.parse_args() if args.max_documents < 1 or args.pages < 1: parser.error('Sampling limits must be positive') args.out.mkdir(parents=True, exist_ok=True) if args.manifest and not args.structure: candidate = args.manifest.parent/'book_structure.json' if candidate.exists(): args.structure = candidate report, before, after = audit_pair(args.source, args.translated, args.manifest, args.structure) status = 1 if report['new_issues'] else 0 if args.render: try: report['render'] = render_pair(args.source, args.translated, before, after, args.out, args.chapter, args.max_documents, args.pages) report['render_status'] = 'evidence_generated' if any(not c['destination_reached'] or c.get('backlink_reached') is False for c in report['render']['note_clicks']): status = 1 except Exception as exc: report['render_status'] = 'failed' report['render_error'] = f'{type(exc).__name__}: {exc}' status = 2 (args.out/'report.json').write_text(json.dumps(report, ensure_ascii=False, indent=2)) write_review(args.out, report) print(f'New issues: {len(report["new_issues"])}; render: {report["render_status"]}; visual/semantic review: pending') return status if __name__ == '__main__': sys.exit(main())