SPB Git

spb/wp29_uqo

Public
5.7 KB · 88 lines python
1"""Authentic screenshot capture with a manifest (no synthetic imagery).2Modes: native_live (a real Terminal/Safari window via /usr/sbin/screencapture -l <windowid>), dashboard_live (Safari showing the3evidence viewer while runs execute), viewer_postrun (same viewer after runs), transcript_replay (not used unless labelled).4Each capture records tool+version, surface, UTC time, SHA-256, linked run/event ids, selection rule and caption."""5from __future__ import annotations6import hashlib, json, os, subprocess, datetime, re7from .contracts import utcnow89def _sha(p):10    return hashlib.sha256(open(p, "rb").read()).hexdigest()1112def window_id(app_name: str, title_substring: str = "") -> int | None:13    """Find a CGWindow id of a visible window of `app_name` (optionally with a title substring) via a tiny Swift-free route: osascript + python Quartz."""14    try:15        import Quartz  # type: ignore16        wins = Quartz.CGWindowListCopyWindowInfo(Quartz.kCGWindowListOptionOnScreenOnly | Quartz.kCGWindowListExcludeDesktopElements, Quartz.kCGNullWindowID)17        for w in wins:18            if w.get("kCGWindowOwnerName") == app_name and (title_substring in (w.get("kCGWindowName") or "")) and w.get("kCGWindowLayer", 0) == 0:19                return int(w["kCGWindowNumber"])20    except Exception:  # noqa: BLE00121        pass22    # fallback: osascript (System Events) cannot give CGWindow ids reliably; return None23    return None2425def capture_window(wid: int, out_path: str) -> bool:26    os.makedirs(os.path.dirname(out_path), exist_ok=True)27    r = subprocess.run(["/usr/sbin/screencapture", "-x", "-o", "-l", str(wid), out_path], capture_output=True)28    return r.returncode == 0 and os.path.exists(out_path) and os.path.getsize(out_path) > 02930def capture_screen(out_path: str) -> bool:31    os.makedirs(os.path.dirname(out_path), exist_ok=True)32    r = subprocess.run(["/usr/sbin/screencapture", "-x", out_path], capture_output=True)33    return r.returncode == 0 and os.path.exists(out_path)3435def tool_version() -> str:36    try:37        v = subprocess.run(["sw_vers", "-productVersion"], capture_output=True, text=True).stdout.strip()38        return f"/usr/sbin/screencapture (macOS {v})"39    except Exception:  # noqa: BLE00140        return "/usr/sbin/screencapture"4142def record(store, screenshot_id, path, mode, surface, run_id=None, task_id=None, treatment=None, phase=None, event_id=None, selection_rule="", caption="", claim_ids="", redaction="none"):43    rec = {"screenshot_id": screenshot_id, "run_id": run_id, "task_id": task_id, "treatment": treatment, "phase": phase, "event_id": event_id,44           "capture_timestamp_utc": utcnow(), "capture_mode": mode, "capture_tool": tool_version(), "source_surface": surface,45           "original_path": path, "original_sha256": _sha(path), "redacted_public_path": None, "redacted_sha256": None,46           "redaction_description": redaction, "selection_rule": selection_rule, "caption": caption, "claim_ids": claim_ids}47    store.add_screenshot(rec)48    return rec4950def publish(store, screenshot_id, public_path, crop=None, description="copied without modification"):51    """Create the public copy (optionally cropped with sips) and record its hash."""52    row = store.query("SELECT original_path FROM screenshots WHERE screenshot_id=?", (screenshot_id,))[0]53    os.makedirs(os.path.dirname(public_path), exist_ok=True)54    if crop:55        x, y, w, h = crop56        subprocess.run(["sips", "-c", str(h), str(w), "--cropOffset", str(y), str(x), row["original_path"], "--out", public_path], capture_output=True, check=True)57    else:58        subprocess.run(["cp", row["original_path"], public_path], check=True)59    with store.tx() as c:60        c.execute("UPDATE screenshots SET redacted_public_path=?, redacted_sha256=?, redaction_description=? WHERE screenshot_id=?", (public_path, _sha(public_path), description, screenshot_id))61    return public_path6263def window_bounds(wid: int):64    import Quartz  # type: ignore65    for w in Quartz.CGWindowListCopyWindowInfo(Quartz.kCGWindowListOptionAll, Quartz.kCGNullWindowID):66        if int(w["kCGWindowNumber"]) == wid:67            b = w["kCGWindowBounds"]; return int(b["X"]), int(b["Y"]), int(b["Width"]), int(b["Height"])68    return None6970def capture_region(bounds, out_path: str) -> bool:71    """Composited screen capture of a rectangle (used for Safari, whose web content is not captured by -l window capture)."""72    x, y, w, h = bounds; os.makedirs(os.path.dirname(out_path), exist_ok=True)73    r = subprocess.run(["/usr/sbin/screencapture", "-x", "-R", f"{x},{y},{w},{h}", out_path], capture_output=True)74    return r.returncode == 0 and os.path.exists(out_path) and os.path.getsize(out_path) > 07576def capture_safari_dashboard(store, screenshot_id, url, out_path, mode, **meta) -> dict | None:77    """Open/reload the URL in the front Safari window in the current Space, bring it to front, capture the composited region."""78    import time79    subprocess.run(["osascript", "-e", 'tell application "Safari" to activate', "-e", f'tell application "Safari" to set URL of front document to "{url}"'], capture_output=True)80    time.sleep(4)81    import Quartz  # type: ignore82    wins = Quartz.CGWindowListCopyWindowInfo(Quartz.kCGWindowListOptionOnScreenOnly | Quartz.kCGWindowListExcludeDesktopElements, Quartz.kCGNullWindowID)83    c = [w for w in wins if w.get("kCGWindowOwnerName") == "Safari" and w.get("kCGWindowLayer", 0) == 0 and w.get("kCGWindowName")]84    if not c: return None85    b = c[0]["kCGWindowBounds"]; bounds = (int(b["X"]), int(b["Y"]), int(b["Width"]), int(b["Height"]))86    if not capture_region(bounds, out_path): return None87    return record(store, screenshot_id, out_path, mode, f"Safari window '{c[0].get('kCGWindowName')}' → {url} (composited region capture of the evidence viewer over runs/state.sqlite)", **meta)88
Files · 55b92f9bcc679fb8bcbc12d51e0b6519e7f8b07d
Menu

Theme