| """Faithful design preview: renders the REAL style.css + render.py output across all |
| UI states into a single static HTML file, so design iteration can be screenshot-verified |
| without launching Gradio or a GPU. Dev tool only β not part of the shipped app. |
| |
| Usage: python scripts/design_preview.py -> writes design_preview_live.html |
| """ |
| from __future__ import annotations |
|
|
| import json |
| import sys |
| from pathlib import Path |
|
|
| ROOT = Path(__file__).resolve().parent.parent |
| sys.path.insert(0, str(ROOT)) |
|
|
| import render |
| from schema import HandoffOutput |
|
|
| CSS = (ROOT / "style.css").read_text(encoding="utf-8") |
| CACHE = ROOT / "data" / "example_cache" |
|
|
|
|
| def load(name: str) -> HandoffOutput: |
| return HandoffOutput.model_validate(json.loads((CACHE / f"{name}.json").read_text(encoding="utf-8"))) |
|
|
|
|
| def sec(label: str) -> str: |
| return f'<div class="preview-sec">{label}</div>' |
|
|
|
|
| def build() -> str: |
| ahmed = load("ahmed") |
| arabic = load("arabic") |
| root_canal = load("root_canal") |
|
|
| |
| flagged = next((c for c in (root_canal, ahmed, arabic) if c.red_flags), root_canal) |
|
|
| blocks: list[str] = [ |
| render.header_html(), |
| render.footer_html(), |
| sec("Step rail"), |
| render.rail_html(), |
| sec("Agent dashboard β initial (Ready)"), |
| render.initial_agent_dashboard_html(), |
| sec("Agent dashboard β live auditable run"), |
| render.render_agent_dashboard( |
| "Cached", "Complete", f"{len(flagged.red_flags)} flags found", "Passed", |
| route_note="Cached case Β· model drafted narrative Β· sentinel ran between turns", |
| ), |
| sec("Safety panel β clear"), |
| render.initial_safety_html(), |
| sec("Safety panel β fired (rule-based)"), |
| render.render_safety_html(flagged), |
| sec("Handoff card β empty / ghost state"), |
| render.placeholder_handoff_html(), |
| sec("Handoff card β loading skeleton"), |
| render.skeleton_handoff_html(), |
| sec("Handoff card β English (Ahmed, model-authored narrative)"), |
| render.render_handoff_html(ahmed, "English", model_authored=True), |
| sec("Handoff card β Bilingual (English + Arabic)"), |
| render.render_handoff_html(arabic, "Bilingual"), |
| ] |
|
|
| |
| interrupt_case = next((c for c in (root_canal, ahmed, arabic) if render.is_hard_interrupt(c)), None) |
| if interrupt_case is not None: |
| blocks += [sec("Hard interrupt card"), render._interrupt_card(interrupt_case, "Bilingual")] |
|
|
| fonts = ( |
| '<link rel="preconnect" href="https://fonts.googleapis.com">' |
| '<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>' |
| '<link href="https://fonts.googleapis.com/css2?' |
| "family=Inter:wght@400;500;600;700&family=Inter+Tight:wght@500;600;700&" |
| "family=IBM+Plex+Mono:wght@400;500;600&family=IBM+Plex+Sans+Arabic:wght@400;500;600&" |
| 'display=swap" rel="stylesheet">' |
| ) |
| shell = ( |
| "body{max-width:1180px;margin:0 auto;padding:28px 20px;background:#F5F4F0;}" |
| ".preview-sec{margin:34px 0 12px;font-family:'IBM Plex Mono',monospace;font-size:11px;" |
| "letter-spacing:.14em;text-transform:uppercase;color:#8C887E;border-top:1px solid #E2DFD6;padding-top:14px;}" |
| ) |
| return ( |
| f"<!doctype html><html lang='en'><head><meta charset='utf-8'>{fonts}" |
| f"<style>{CSS}</style><style>{shell}</style></head><body>" |
| f"{''.join(blocks)}</body></html>" |
| ) |
|
|
|
|
| if __name__ == "__main__": |
| out = ROOT / "design_preview_live.html" |
| out.write_text(build(), encoding="utf-8") |
| print(f"wrote {out}") |
|
|