Add a comprehensive Puppeteer UI suite for the egress-policy feature: `tests/ui_tests/test_egress_policy_ui.js` (CI-safe, 32 assertions) covers every UX touchpoint — Privacy & Egress panel rendering, all four scopes painting their expected border/text colors (amber/teal/indigo palette verified via computed-style reads, not just DOM state), the STRICT-on-meta-picker guard reverting to "Both" with an explanatory hint, per-research overrides round-tripping through the settings DB, scope cue propagating to /history, /metrics and /chat via base.html's `body[data-scope]`, settings dashboard listing the policy keys, and the require-local toggles persisting across reloads. A second file, `tests/ui_tests/NO_CI_test_egress_policy_live_research.js`, drives end-to-end research runs against a real Ollama + SearXNG instance (defaults to a lab box; overridable via env) and verifies the run-start PEP at `research_routes.py:248` — STRICT+searxng succeeds, STRICT+auto returns 400 with the meta-picker incoherence message, PUBLIC_ONLY refuses a SearXNG whose instance URL resolves to a private IP (`scope_mismatch_public_only`), PRIVATE_ONLY accepts the same SearXNG (URL classifier overrides the static `is_public=True`), and a cloud LLM under `require_local_endpoint=true` is accepted at the precheck but reaches `failed` status as the strategy's `get_llm()` hits the PEP. Both files gate screenshots behind `!process.env.CI` matching the `tests/ui_tests/test_settings_page.js:57` convention; the live test's `NO_CI_` filename prefix means the runner skips it in CI (where the lab endpoints are unreachable). Screenshots land in `tests/ui_tests/screenshots/egress-policy{,-live}/` (already gitignored).
