{"record":{"id":"0c8c038d3341a56e","repo":"calesthio/OpenMontage","slug":"stage-drawer-did-not-open","errorCode":null,"errorMessage":"stage drawer did not open","messagePattern":"stage drawer did not open","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"scripts/backlot_visual_eval.py","lineNumber":180,"sourceCode":"        report.append(result)\n    return report\n\n\ndef run_interactions(capture_dir: Path) -> dict[str, Any]:\n    \"\"\"Run browser interaction smoke through Python Playwright.\"\"\"\n    from playwright.sync_api import sync_playwright\n\n    screenshot = capture_dir / \"interaction-smoke.png\"\n    with sync_playwright() as pw:\n        browser = pw.chromium.launch(headless=True)\n        page = browser.new_page(viewport={\"width\": 1560, \"height\": 1000})\n        page.goto(f\"http://127.0.0.1:{PORT}/p/the-last-lighthouse?static=1\")\n        page.wait_for_selector(\".stage\")\n        page.locator(\".stage\").first.click()\n        page.wait_for_selector(\".drawer\")\n        drawer_text = page.locator(\".drawer\").inner_text()\n        if \"research\" not in drawer_text:\n            raise RuntimeError(\"stage drawer did not open\")\n        page.locator(\".script-card\").first.click()\n        page.wait_for_selector(\".modal-bg.open\")\n        page.keyboard.press(\"Escape\")\n        page.wait_for_function(\"() => !document.querySelector('.modal-bg')?.classList.contains('open')\")\n        if page.locator(\".takes\").count() < 1:\n            raise RuntimeError(\"takes drawer not present on staged takes scene\")\n        replay_button = page.locator(\".rp-btn\", has_text=\"REPLAY RUN\")\n        if replay_button.count():\n            replay_button.first.click()\n            page.wait_for_selector('input[type=\"range\"]')\n            page.locator('input[type=\"range\"]').fill(\"500\")\n        page.screenshot(path=str(screenshot), full_page=True)\n        browser.close()\n    return {\"status\": \"passed\", \"screenshot\": str(capture_dir / \"interaction-smoke.png\")}\n\n\ndef main(argv: list[str] | None = None) -> int:\n    parser = argparse.ArgumentParser(description=__doc__)","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/calesthio/OpenMontage/blob/95e1c3d0ab93482159818560f6a8c8e866b9139f/scripts/backlot_visual_eval.py#L162-L198","documentation":"Raised by scripts/backlot_visual_eval.py's interaction smoke when clicking the first .stage element opens a .drawer but its rendered text does not contain the word 'research'. The check verifies the stage drawer actually populated with stage content (the expected first stage being research-related), not merely that a drawer element appeared — so this fires when the drawer opens empty, shows an error/loading state, or displays the wrong stage's data.","triggerScenarios":"Running the interaction smoke against the Backlot static page (?static=1) when stage data fails to load, the drawer component renders before data arrives, a refactor renamed stage content so 'research' no longer appears, or the clicked .stage resolves to a different stage than expected.","commonSituations":"Frontend refactor changing stage labels or drawer content structure; fixture data for 'the-last-lighthouse' missing or renamed; race where the smoke asserts text before async content renders.","solutions":["Open http://127.0.0.1:{PORT}/p/the-last-lighthouse?static=1 manually, click a stage, and inspect what the drawer actually shows.","If content is correct but the wording changed, update the expected substring in scripts/backlot_visual_eval.py.","If the drawer is empty/loading, fix the underlying data load or add a wait for the content to populate before asserting."],"exampleFix":"# before\nif \"research\" not in drawer_text:\n    raise RuntimeError(\"stage drawer did not open\")\n\n# after (match current content + wait for population)\npage.wait_for_function(\"() => document.querySelector('.drawer')?.innerText.trim().length > 0\")\nif \"research\" not in page.locator(\".drawer\").inner_text().lower():\n    raise RuntimeError(\"stage drawer did not open\")","handlingStrategy":"validation","validationCode":"drawer_text = page.locator(\".drawer\").inner_text()\nexpected_stage = \"research\"\nif expected_stage not in drawer_text.lower():\n    # drawer opened but content missing/wrong — dump actual text for diagnosis\n    raise AssertionError(f\"drawer content unexpected: {drawer_text[:200]!r}\")","typeGuard":null,"tryCatchPattern":"try:\n    run_interaction_smoke()\nexcept RuntimeError as e:\n    if \"stage drawer did not open\" in str(e):\n        # inspect capture_dir/interaction-smoke.png (if reached) or run manually to see actual drawer state\n        log.error(\"Drawer content check failed — open the page manually and inspect .drawer text\")\n    raise","preventionTips":["Keep smoke assertions tied to stable content anchors, and update them in the same PR that changes UI copy.","Wait for drawer text to be non-empty before substring assertions.","On failure, reproduce manually in a headed browser before changing the check."],"tags":["ui","playwright","smoke-test","frontend"],"backgroundTag":null,"analyzedSha":"95e1c3d0ab93482159818560f6a8c8e866b9139f","analyzedAt":"2026-08-15T06:31:20.014Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}