## Implementation Plan: DeepSearch Playwright Async Context Manager Race Fix ### Changes Required **File:** `devplacepy/services/jobs/deepsearch/crawl.py` 1. **Add import** for `asyncio` at module top (if not already present). 2. **Add module-level lock** immediately after imports: ```python _pw_lock = asyncio.Lock() ``` 3. **Guard the Playwright call** inside `fetch_page()` (around line 240). Replace the bare invocation with an `async with` block that acquires the lock: ```python if len(text) < MIN_PAGE_CHARS: async with _pw_lock: r_title, r_text, r_status, r_links = await _render_with_playwright(url) ``` No other files require modification. The change is minimal (adds 2 lines of new code, modifies 1 line) and serializes only the Playwright context manager entry, preserving HTTPX concurrency. ### Verification Commands The project’s test and lint commands must be run inside a **Python virtual environment** to avoid the PEP 668 system-package restriction. If a virtual environment does not exist, create and activate one first: ```bash python3 -m venv .venv && source .venv/bin/activate pip install --upgrade pip ``` Then execute: ```bash pip install -e '.[dev]' -q && make test-unit ``` And: ```bash pip install -q ruff && ruff check . ``` ### Definition of Done - [ ] The code change (lock addition + guarded call) is applied to `crawl.py`. - [ ] `ruff check .` exits with code 0 (no lint errors). - [ ] `make test-unit` exits with code 0 (all unit tests pass). - [ ] No existing functionality is broken – the same tests that passed before still pass. - [ ] (Optional) A manual test confirms that two concurrent `fetch_page` calls both needing Playwright no longer produce the `__aexit__` error.