#!/usr/bin/env python3 """Deterministic static-analysis regression for Phase 08-03: persistent side panel (R18). The extension JS can't run headless, so we assert the wiring CONTRACT by source inspection (mirroring the 06/07 plans). ASCII-only output. Proves: * content.js injects an idempotent left-docked iframe panel hosting popup/popup.html, with a collapse/dismiss toggle, handles TOGGLE_PANEL, and keeps EXTRACT_JD; it never disables page interaction globally. * manifest.json exposes the popup via web_accessible_resources, bumps the version to 1.5.0, and retains the content script + default_popup launcher. * popup.js keeps the background-owned run (ats_results + storage.onChanged + getCurrentUrlKey), adds launcher/embed awareness (TOGGLE_PANEL + window.top), and surfaces the 08-01 LaTeX compile-failure reason (pdf_error + compile_log). Exit code: 0 when every assertion passes, 1 otherwise. """ import json import os import sys REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) EXT = os.path.join(REPO_ROOT, "extension") CONTENT = os.path.join(EXT, "content.js") MANIFEST = os.path.join(EXT, "manifest.json") POPUP_JS = os.path.join(EXT, "popup", "popup.js") _failures = [] def _read(path): with open(path, encoding="utf-8") as fh: return fh.read() def check(condition, message): if condition: print(f" [PASS] {message}") else: print(f" [FAIL] {message}") _failures.append(message) def test_content_js(): print("[1] content.js injects a persistent left-docked iframe panel") js = _read(CONTENT) for token in ("injectSidePanel", "ats-side-panel-root", "chrome.runtime.getURL", "popup/popup.html", "TOGGLE_PANEL", "collapsed"): check(token in js, f"content.js references '{token}'") check("ats-side-panel-toggle" in js or "ats-side-panel-dismiss" in js, "collapse/dismiss toggle present") check("EXTRACT_JD" in js, "JD extraction listener preserved") # Crude guard against blocking the whole page. check("document.body.style.pointerEvents" not in js, "does NOT globally disable page pointer events") def test_manifest(): print("[2] manifest.json exposes popup + bumps version, keeps launcher") m = json.loads(_read(MANIFEST)) war = m.get("web_accessible_resources") check(bool(war), "web_accessible_resources present") res = (war[0].get("resources") if war else []) or [] check(any("popup/popup.html" in r for r in res), "popup/popup.html is web-accessible") # Panel landed in 1.5.0; accept any >= 1.5.0 so follow-up patch bumps # (1.5.1, 1.5.2, ...) don't break this check. _vt = tuple(int(x) for x in str(m.get("version", "0")).split(".")) check(_vt >= (1, 5, 0), f"version >= 1.5.0 (got {m.get('version')})") cs = m.get("content_scripts", []) check(any("content.js" in (c.get("js") or []) for c in cs) and any("" in (c.get("matches") or []) for c in cs), "content.js still registered on ") check(bool(m.get("action", {}).get("default_popup")), "default_popup retained (thin launcher)") def test_popup_js(): print("[3] popup.js keeps background-owned run + adds launcher/embed + pdf_error") js = _read(POPUP_JS) for token in ("ats_results", "chrome.storage.onChanged", "getCurrentUrlKey"): check(token in js, f"popup.js retains '{token}' (R15 run + live reflect)") check("TOGGLE_PANEL" in js and "window.top" in js, "popup.js has launcher/embed awareness (TOGGLE_PANEL + window.top)") check("pdf_error" in js and "compile_log" in js, "popup.js surfaces the 08-01 LaTeX compile-failure reason") def main(): print("=" * 68) print("Phase 08-03 verification: persistent left-docked side panel (R18)") print("=" * 68) test_content_js() test_manifest() test_popup_js() print("-" * 68) if _failures: print(f"FAIL - {len(_failures)} check(s) failed:") for f in _failures: print(f" - {f}") return 1 print("PASS - persistent side panel wiring verified (iframe panel + manifest " "+ background-owned run + pdf_error surfacing)") return 0 if __name__ == "__main__": sys.exit(main())