From fe379212232b9649cdf96cafa226e6fa54626851 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Fri, 5 Jun 2026 07:15:45 -0700 Subject: [PATCH 01/12] Studio: fix load_freeze audio-type tests for #6000's Gemma 4 `<|audio|>` probe (#6018) * Studio: fix load_freeze audio-type tests for #6000 Gemma 4 <|audio|> probe #6000 extended LlamaCppBackend._detect_audio_type_strict audio_vlm arm to also probe Gemma 4 `<|audio|>` (alongside Gemma 3n ``), but did not update the load_freeze simulation suite (last touched by #5922). Its "no-match" and "bicodec" fixtures only defeat ``; the unmapped `<|audio|>` probe falls through to FakeLlamaServer 1-token default, so detect_audio_type now returns audio_vlm where these tests expect None / bicodec: - test_functional_equivalence_no_match - test_functional_equivalence_bicodec_match - test_response_shape_matches_pre_fix_for_no_match main push-CI does not run "Repo tests (CPU)" (pull_request-only), so this surfaces in every open PR merge-ref (e.g. #5940, which is unrelated to audio). Fix: map `<|audio|>` to a 2-token response in the three fixtures that intend a non-audio_vlm result (restoring their original semantics), and add a positive test_functional_equivalence_audio_vlm_match locking in #6000 new `<|audio|>` detection. Co-Authored-By: Claude Opus 4.8 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Claude Opus 4.8 Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .../load_freeze/test_load_orchestrator.py | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/tests/studio/load_freeze/test_load_orchestrator.py b/tests/studio/load_freeze/test_load_orchestrator.py index 8d32932d13..91b70f0b03 100644 --- a/tests/studio/load_freeze/test_load_orchestrator.py +++ b/tests/studio/load_freeze/test_load_orchestrator.py @@ -3,7 +3,7 @@ Covers: 1. Behavioural canary (the bug class) — 2 tests 2. Behavioural fix-validation — 1 test - 3. Functional equivalence (sync == to_thread) — 5 tests, one per codec branch + 3. Functional equivalence (sync == to_thread) — 6 tests, one per codec branch 4. Failure modes (HTTP 500, malformed JSON, connection reset, unreachable, not-loaded) — 5 tests 5. Stress (50 concurrent probes / 100 healths) — 2 tests @@ -254,6 +254,7 @@ def shim_no_match(): "<|audio_eos|>": [0, 1], "<|startoftranscript|>": [0, 1], "": [0, 1], + "<|audio|>": [0, 1], "<|bicodec_semantic_0|>": [0, 1], "<|bicodec_global_0|>": [0, 1], "<|c1_0|>": [0, 1], @@ -314,6 +315,28 @@ def test_functional_equivalence_whisper_match(): assert sync_result == threaded +def test_functional_equivalence_audio_vlm_match(): + # audio_vlm: snac/csm/whisper fail first, then the Gemma 4 <|audio|> + # probe tokenises to a single token. #6000 added this arm alongside + # Gemma 3n's ; keep at 2 tokens so + # it is specifically the new <|audio|> arm that triggers the match. + with FakeLlamaServer( + detok_map = {128258: "non-snac", 128259: "non-snac"}, + tok_response_map = { + "<|AUDIO|>": [0, 1], # csm fails (>1 token) + "<|audio_eos|>": [0, 1], + "<|startoftranscript|>": [0, 1], # whisper fails + "": [0, 1], # Gemma 3n arm fails ... + "<|audio|>": [0], # ... Gemma 4 arm matches (#6000) + }, + ) as srv: + backend = _make_backend(srv.port) + sync_result = backend.detect_audio_type() + threaded = asyncio.run(asyncio.to_thread(backend.detect_audio_type)) + assert sync_result == "audio_vlm" + assert sync_result == threaded + + def test_functional_equivalence_bicodec_match(): # bicodec: snac/csm/whisper/audio_vlm all fail first, then both # bicodec_semantic_0 and bicodec_global_0 are single tokens. @@ -324,6 +347,7 @@ def test_functional_equivalence_bicodec_match(): "<|audio_eos|>": [0, 1], "<|startoftranscript|>": [0, 1], "": [0, 1], + "<|audio|>": [0, 1], "<|bicodec_semantic_0|>": [0], "<|bicodec_global_0|>": [0], }, @@ -644,6 +668,7 @@ def test_response_shape_matches_pre_fix_for_no_match(): "<|audio_eos|>": [0, 1], "<|startoftranscript|>": [0, 1], "": [0, 1], + "<|audio|>": [0, 1], "<|bicodec_semantic_0|>": [0, 1], "<|bicodec_global_0|>": [0, 1], "<|c1_0|>": [0, 1], From 783c9d1e8379664cb8ed67e05f14a5f62f1dbe8e Mon Sep 17 00:00:00 2001 From: Lee Jackson <130007945+Imagineer99@users.noreply.github.com> Date: Fri, 5 Jun 2026 15:16:50 +0100 Subject: [PATCH 02/12] Studio: fix chat preset persistence with fast mode (#5870) * fix: persist chat presets with fast mode * Add schema drift guard test for chat inference settings (#5862) Asserts ChatInferenceSettings declares every InferenceParams field the frontend persists (all but checkpoint). With extra="forbid", a field present in the UI but missing here 400s PUT /api/chat/settings, which is exactly how fastMode regressed. Catches the next occurrence at CI time. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Daniel Han Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- studio/backend/routes/chat_history.py | 1 + .../backend/tests/test_chat_history_routes.py | 66 +++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/studio/backend/routes/chat_history.py b/studio/backend/routes/chat_history.py index 8e24096233..75b5be2e49 100644 --- a/studio/backend/routes/chat_history.py +++ b/studio/backend/routes/chat_history.py @@ -143,6 +143,7 @@ class ChatInferenceSettings(BaseModel): maxTokens: Optional[float] = None systemPrompt: Optional[str] = None trustRemoteCode: Optional[bool] = None + fastMode: Optional[bool] = None class ChatPreset(BaseModel): diff --git a/studio/backend/tests/test_chat_history_routes.py b/studio/backend/tests/test_chat_history_routes.py index 9337544638..62bcd05205 100644 --- a/studio/backend/tests/test_chat_history_routes.py +++ b/studio/backend/tests/test_chat_history_routes.py @@ -3,6 +3,7 @@ import asyncio import os +import re import sys import pytest @@ -56,6 +57,71 @@ def test_replace_thread_messages_rejects_body_thread_mismatch(monkeypatch): assert called is False +# --------------------------------------------------------------------------- +# /api/chat/settings +# --------------------------------------------------------------------------- + + +def test_chat_settings_payload_accepts_fast_mode_presets(): + payload = chat_history.ChatSettingsPayload.model_validate( + { + "inferenceParams": {"fastMode": False}, + "customPresets": [ + { + "name": "Fast Opus", + "params": { + "temperature": 0.6, + "topP": 0.95, + "topK": 20, + "minP": 0.01, + "repetitionPenalty": 1.0, + "presencePenalty": 0.0, + "maxTokens": 8192, + "systemPrompt": "", + "trustRemoteCode": False, + "fastMode": True, + }, + }, + ], + } + ) + + dumped = payload.model_dump(exclude_unset = True) + assert dumped["inferenceParams"]["fastMode"] is False + assert dumped["customPresets"][0]["params"]["fastMode"] is True + + +def test_chat_inference_settings_covers_frontend_persisted_fields(): + # Drift guard: every InferenceParams field the UI persists (all but + # checkpoint) must exist on ChatInferenceSettings, else extra="forbid" + # 400s PUT /api/chat/settings on the next added field (issue #5862). + runtime_ts = os.path.join( + _backend, + "..", + "frontend", + "src", + "features", + "chat", + "types", + "runtime.ts", + ) + if not os.path.exists(runtime_ts): + pytest.skip("frontend runtime.ts not present") + + with open(runtime_ts, encoding = "utf-8") as fh: + block = re.search( + r"interface InferenceParams \{(.*?)\n\}", fh.read(), re.DOTALL + ) + assert block, "InferenceParams interface not found in runtime.ts" + persisted = set(re.findall(r"^\s*(\w+)\??:", block.group(1), re.M)) - {"checkpoint"} + + backend = set(chat_history.ChatInferenceSettings.model_fields) + assert persisted == backend, ( + f"schema drift: frontend-only {persisted - backend}, " + f"backend-only {backend - persisted}" + ) + + # --------------------------------------------------------------------------- # /api/chat/import-ledger # --------------------------------------------------------------------------- From 0003f889e6b8dd0a8da21cb382f175dab17985ac Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Fri, 5 Jun 2026 07:52:26 -0700 Subject: [PATCH 03/12] Studio: stop ROCm worker test leaking a fake utils into sys.modules (#6027) test_direct_wheel_url_returns_none_without_cuda_major set sys.modules "utils"/"utils.hardware" (and structlog/loggers) to MagicMocks without cleanup. Once run.py started importing utils.cpu_threads (#5760), the leaked non-package utils made later tests in the same job fail with 'No module named utils.cpu_threads; utils is not a package', e.g. all of test_selection_logic.py's TestStudioLocalhostIpv6Warning. Use monkeypatch.setitem so the stubs are undone after the test. --- tests/studio/install/test_rocm_support.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/tests/studio/install/test_rocm_support.py b/tests/studio/install/test_rocm_support.py index 1d6e4f4c51..1c1a4df377 100644 --- a/tests/studio/install/test_rocm_support.py +++ b/tests/studio/install/test_rocm_support.py @@ -1123,7 +1123,7 @@ class TestWorkerRocmMambaSsm: source = _WHEEL_UTILS_PATH.read_text(encoding = "utf-8") assert "getattr(torch.version, 'hip', None)" in source - def test_direct_wheel_url_returns_none_without_cuda_major(self): + def test_direct_wheel_url_returns_none_without_cuda_major(self, monkeypatch): """_direct_wheel_url should return None when cuda_major is empty (ROCm).""" # Load module for function access _worker_spec = importlib.util.spec_from_file_location( @@ -1132,12 +1132,15 @@ class TestWorkerRocmMambaSsm: assert _worker_spec is not None and _worker_spec.loader is not None worker_mod = importlib.util.module_from_spec(_worker_spec) - # Mock all the imports worker.py needs - sys.modules["structlog"] = MagicMock() - sys.modules["loggers"] = MagicMock() - sys.modules["loggers"].get_logger = MagicMock(return_value = MagicMock()) - sys.modules["utils"] = MagicMock() - sys.modules["utils.hardware"] = MagicMock() + # Stub worker.py's imports via monkeypatch so the fakes (notably a + # non-package "utils") are undone and don't break later tests that + # import the real utils.* package. + loggers_mock = MagicMock() + loggers_mock.get_logger = MagicMock(return_value = MagicMock()) + monkeypatch.setitem(sys.modules, "structlog", MagicMock()) + monkeypatch.setitem(sys.modules, "loggers", loggers_mock) + monkeypatch.setitem(sys.modules, "utils", MagicMock()) + monkeypatch.setitem(sys.modules, "utils.hardware", MagicMock()) try: _worker_spec.loader.exec_module(worker_mod) From 686a30f95e4432522609dcdcb1bec71aea38e471 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Sat, 6 Jun 2026 21:19:21 -0700 Subject: [PATCH 04/12] Studio: stop ROCm amd-smi tests leaking a fake loggers into sys.modules (#6055) Follow-up to #6027. The four TestAmdGpuMonitoring tests also set sys.modules["loggers"] = MagicMock() without cleanup, leaking a mock loggers module into later tests. Switch them to monkeypatch.setitem so the stub is undone at teardown, matching the worker test fix in #6027. --- tests/studio/install/test_rocm_support.py | 26 +++++++++++++---------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/tests/studio/install/test_rocm_support.py b/tests/studio/install/test_rocm_support.py index 1c1a4df377..4aa7fb3a34 100644 --- a/tests/studio/install/test_rocm_support.py +++ b/tests/studio/install/test_rocm_support.py @@ -1206,15 +1206,16 @@ class TestAmdGpuMonitoring: assert "def get_primary_gpu_utilization" in source assert "def get_visible_gpu_utilization" in source - def test_amd_smi_json_parsing(self): + def test_amd_smi_json_parsing(self, monkeypatch): """Verify _extract_gpu_metrics parses amd-smi JSON correctly.""" amd_path = PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "amd.py" _amd_spec = importlib.util.spec_from_file_location("test_amd", amd_path) assert _amd_spec is not None and _amd_spec.loader is not None amd_mod = importlib.util.module_from_spec(_amd_spec) - sys.modules["loggers"] = MagicMock() - sys.modules["loggers"].get_logger = MagicMock(return_value = MagicMock()) + loggers_mock = MagicMock() + loggers_mock.get_logger = MagicMock(return_value = MagicMock()) + monkeypatch.setitem(sys.modules, "loggers", loggers_mock) try: _amd_spec.loader.exec_module(amd_mod) @@ -1251,8 +1252,9 @@ class TestAmdGpuMonitoring: assert _amd_spec is not None and _amd_spec.loader is not None amd_mod = importlib.util.module_from_spec(_amd_spec) - sys.modules["loggers"] = MagicMock() - sys.modules["loggers"].get_logger = MagicMock(return_value = MagicMock()) + loggers_mock = MagicMock() + loggers_mock.get_logger = MagicMock(return_value = MagicMock()) + monkeypatch.setitem(sys.modules, "loggers", loggers_mock) try: _amd_spec.loader.exec_module(amd_mod) @@ -1290,15 +1292,16 @@ class TestAmdGpuMonitoring: assert result["gpu_utilization_pct"] == 50.0 assert result["temperature_c"] == 65.0 - def test_amd_smi_not_found_returns_unavailable(self): + def test_amd_smi_not_found_returns_unavailable(self, monkeypatch): """get_primary_gpu_utilization returns available=False when amd-smi is missing.""" amd_path = PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "amd.py" _amd_spec = importlib.util.spec_from_file_location("test_amd3", amd_path) assert _amd_spec is not None and _amd_spec.loader is not None amd_mod = importlib.util.module_from_spec(_amd_spec) - sys.modules["loggers"] = MagicMock() - sys.modules["loggers"].get_logger = MagicMock(return_value = MagicMock()) + loggers_mock = MagicMock() + loggers_mock.get_logger = MagicMock(return_value = MagicMock()) + monkeypatch.setitem(sys.modules, "loggers", loggers_mock) try: _amd_spec.loader.exec_module(amd_mod) @@ -1309,15 +1312,16 @@ class TestAmdGpuMonitoring: result = amd_mod.get_primary_gpu_utilization() assert result["available"] is False - def test_amd_timeout_returns_unavailable(self): + def test_amd_timeout_returns_unavailable(self, monkeypatch): """get_primary_gpu_utilization handles timeout gracefully.""" amd_path = PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "amd.py" _amd_spec = importlib.util.spec_from_file_location("test_amd4", amd_path) assert _amd_spec is not None and _amd_spec.loader is not None amd_mod = importlib.util.module_from_spec(_amd_spec) - sys.modules["loggers"] = MagicMock() - sys.modules["loggers"].get_logger = MagicMock(return_value = MagicMock()) + loggers_mock = MagicMock() + loggers_mock.get_logger = MagicMock(return_value = MagicMock()) + monkeypatch.setitem(sys.modules, "loggers", loggers_mock) try: _amd_spec.loader.exec_module(amd_mod) From 1b588cd141daf20af272afeed0e014b808bbc071 Mon Sep 17 00:00:00 2001 From: Michael Han <107991372+shimmyshimmer@users.noreply.github.com> Date: Sun, 7 Jun 2026 01:57:52 -0700 Subject: [PATCH 05/12] Studio: emit usage and timings for MLX generation speed stats (#6068) * Studio: emit usage and timings for MLX generation speed stats * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Studio: make MLX generation stats request scoped --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .../backend/core/inference/mlx_inference.py | 85 ++++++++++++++++--- studio/backend/core/inference/orchestrator.py | 19 +++++ studio/backend/core/inference/worker.py | 2 + studio/backend/routes/inference.py | 51 ++++++++++- 4 files changed, 142 insertions(+), 15 deletions(-) diff --git a/studio/backend/core/inference/mlx_inference.py b/studio/backend/core/inference/mlx_inference.py index 716e4c27a2..b9adba13e6 100644 --- a/studio/backend/core/inference/mlx_inference.py +++ b/studio/backend/core/inference/mlx_inference.py @@ -12,6 +12,35 @@ from loggers import get_logger logger = get_logger(__name__) +def _build_generation_stats(prompt_n, prompt_tps, gen_n, gen_tps): + """Map mlx_lm / mlx_vlm stream stats onto the usage/timings shape + llama-server emits so the chat speed popover renders the same.""" + prompt_n = int(prompt_n or 0) + gen_n = int(gen_n or 0) + prompt_tps = float(prompt_tps or 0.0) + gen_tps = float(gen_tps or 0.0) + prompt_ms = (prompt_n / prompt_tps * 1000.0) if prompt_tps > 0 else 0.0 + predicted_ms = (gen_n / gen_tps * 1000.0) if gen_tps > 0 else 0.0 + return { + "usage": { + "prompt_tokens": prompt_n, + "completion_tokens": gen_n, + "total_tokens": prompt_n + gen_n, + }, + "timings": { + "prompt_n": prompt_n, + "prompt_ms": prompt_ms, + "prompt_per_token_ms": (prompt_ms / prompt_n) if prompt_n > 0 else 0.0, + "prompt_per_second": prompt_tps, + "predicted_n": gen_n, + "predicted_ms": predicted_ms, + "predicted_per_token_ms": (predicted_ms / gen_n) if gen_n > 0 else 0.0, + "predicted_per_second": gen_tps, + "cache_n": 0, + }, + } + + class MLXInferenceBackend: def __init__(self): self.models = {} @@ -20,6 +49,8 @@ class MLXInferenceBackend: self.loaded_local_models = [] self.device = "mlx" self._generation_lock = threading.Lock() + # usage/timings of the latest generation; shipped on gen_done. + self.last_generation_stats = None # MLX state self._model = None @@ -258,6 +289,9 @@ class MLXInferenceBackend: if self._model is None: raise RuntimeError("No model loaded") + # Reset so a failed run cannot surface stale stats. + self.last_generation_stats = None + # Build messages with system prompt full_messages = [] if system_prompt: @@ -380,6 +414,7 @@ class MLXInferenceBackend: type(self._tokenizer).__name__, ) with self._generation_lock: + final_response = None try: gen_kwargs = dict( prompt = prompt, @@ -393,6 +428,7 @@ class MLXInferenceBackend: self._tokenizer, **gen_kwargs, ): + final_response = response token_ids.append(response.token) # Decode full sequence with skip_special_tokens — same as GPU cumulative = self._tokenizer.decode( @@ -408,6 +444,15 @@ class MLXInferenceBackend: logger.error("stream_generate failed:\n%s", traceback.format_exc()) raise + finally: + # Latch final cumulative stats for the usage/timings chunk. + if final_response is not None: + self.last_generation_stats = _build_generation_stats( + getattr(final_response, "prompt_tokens", 0), + getattr(final_response, "prompt_tps", 0.0), + getattr(final_response, "generation_tokens", 0), + getattr(final_response, "generation_tps", 0.0), + ) def _generate_vlm( self, @@ -483,20 +528,32 @@ class MLXInferenceBackend: vlm_kwargs["repetition_penalty"] = float(repetition_penalty) with self._generation_lock: - for response in vlm_stream( - self._model, - self._processor, - prompt, - images, - **vlm_kwargs, - ): - token_text = ( - response.text if hasattr(response, "text") else str(response) - ) - cumulative += token_text - yield cumulative - if cancel_event and cancel_event.is_set(): - break + final_response = None + try: + for response in vlm_stream( + self._model, + self._processor, + prompt, + images, + **vlm_kwargs, + ): + final_response = response + token_text = ( + response.text if hasattr(response, "text") else str(response) + ) + cumulative += token_text + yield cumulative + if cancel_event and cancel_event.is_set(): + break + finally: + # mlx_vlm exposes the same stats fields as mlx_lm. + if final_response is not None: + self.last_generation_stats = _build_generation_stats( + getattr(final_response, "prompt_tokens", 0), + getattr(final_response, "prompt_tps", 0.0), + getattr(final_response, "generation_tokens", 0), + getattr(final_response, "generation_tps", 0.0), + ) def generate_with_adapter_control( self, use_adapter = None, cancel_event = None, **gen_kwargs diff --git a/studio/backend/core/inference/orchestrator.py b/studio/backend/core/inference/orchestrator.py index 7e7d7026f6..6321ca892d 100644 --- a/studio/backend/core/inference/orchestrator.py +++ b/studio/backend/core/inference/orchestrator.py @@ -453,6 +453,7 @@ class InferenceOrchestrator: enable_thinking: Optional[bool] = None, reasoning_effort: Optional[str] = None, preserve_thinking: Optional[bool] = None, + stats_holder: Optional[dict] = None, ) -> Generator[str, None, None]: """Dispatched generation — sends command without holding _gen_lock. @@ -544,6 +545,8 @@ class InferenceOrchestrator: yield resp.get("text", "") elif rtype == "gen_done": + if stats_holder is not None: + stats_holder["stats"] = resp.get("stats") return elif rtype == "gen_error": @@ -793,6 +796,7 @@ class InferenceOrchestrator: enable_thinking: Optional[bool] = None, reasoning_effort: Optional[str] = None, preserve_thinking: Optional[bool] = None, + stats_holder: Optional[dict] = None, ) -> Generator[str, None, None]: """Generate response, streaming tokens from subprocess. @@ -800,6 +804,10 @@ class InferenceOrchestrator: ``preserve_thinking`` kwargs are forwarded into the worker so ``tokenizer.apply_chat_template`` can render tool schemas and reasoning controls when the template understands them. + + ``stats_holder``: caller-owned dict; on gen_done its "stats" key + receives the worker's usage/timings. Request-scoped by design so + concurrent streams cannot read each other's stats. """ yield from self._generate_inner( messages = messages, @@ -817,6 +825,7 @@ class InferenceOrchestrator: enable_thinking = enable_thinking, reasoning_effort = reasoning_effort, preserve_thinking = preserve_thinking, + stats_holder = stats_holder, ) def generate_chat_completion_with_tools( @@ -839,6 +848,7 @@ class InferenceOrchestrator: tool_call_timeout: int = 300, session_id: Optional[str] = None, use_adapter: Optional[Union[bool, str]] = None, + stats_holder: Optional[dict] = None, **_unused, ): """Run the safetensors agentic tool loop in this (parent) @@ -872,6 +882,8 @@ class InferenceOrchestrator: enable_thinking = enable_thinking, reasoning_effort = reasoning_effort, preserve_thinking = preserve_thinking, + # last turn wins, same as the GGUF tool loop's metadata + stats_holder = stats_holder, ) if use_adapter is not None: yield from self.generate_with_adapter_control( @@ -901,6 +913,7 @@ class InferenceOrchestrator: self, use_adapter: Optional[Union[bool, str]] = None, cancel_event = None, + stats_holder: Optional[dict] = None, **gen_kwargs, ) -> Generator[str, None, None]: """Generate with adapter control, streaming tokens from subprocess. @@ -912,6 +925,7 @@ class InferenceOrchestrator: yield from self._generate_dispatched( use_adapter = use_adapter, cancel_event = cancel_event, + stats_holder = stats_holder, **gen_kwargs, ) @@ -932,6 +946,7 @@ class InferenceOrchestrator: enable_thinking: Optional[bool] = None, reasoning_effort: Optional[str] = None, preserve_thinking: Optional[bool] = None, + stats_holder: Optional[dict] = None, ) -> Generator[str, None, None]: """Inner generation logic — sends command to subprocess, yields tokens. @@ -972,6 +987,7 @@ class InferenceOrchestrator: enable_thinking = enable_thinking, reasoning_effort = reasoning_effort, preserve_thinking = preserve_thinking, + stats_holder = stats_holder, ) def _generate_locked( @@ -991,6 +1007,7 @@ class InferenceOrchestrator: enable_thinking: Optional[bool] = None, reasoning_effort: Optional[str] = None, preserve_thinking: Optional[bool] = None, + stats_holder: Optional[dict] = None, ) -> Generator[str, None, None]: """Actual generation logic — must be called under _gen_lock.""" request_id = str(uuid.uuid4()) @@ -1069,6 +1086,8 @@ class InferenceOrchestrator: yield resp.get("text", "") elif rtype == "gen_done": + if stats_holder is not None: + stats_holder["stats"] = resp.get("stats") return elif rtype == "gen_error": diff --git a/studio/backend/core/inference/worker.py b/studio/backend/core/inference/worker.py index 20a7d2d16c..d01cce4fc1 100644 --- a/studio/backend/core/inference/worker.py +++ b/studio/backend/core/inference/worker.py @@ -481,6 +481,8 @@ def _handle_generate( { "type": "gen_done", "request_id": request_id, + # usage/timings from the MLX backend (None elsewhere). + "stats": getattr(backend, "last_generation_stats", None), "ts": time.time(), }, ) diff --git a/studio/backend/routes/inference.py b/studio/backend/routes/inference.py index 1d505e31f6..d3a279319a 100644 --- a/studio/backend/routes/inference.py +++ b/studio/backend/routes/inference.py @@ -3426,6 +3426,9 @@ async def openai_chat_completions( else: _sf_chat_messages.append(_msg) + # Request-scoped usage/timings receptacle (filled at gen_done). + _sf_stats_holder: dict = {} + def sf_generate_with_tools(): return backend.generate_chat_completion_with_tools( messages = _sf_chat_messages, @@ -3450,6 +3453,7 @@ async def openai_chat_completions( else 300, session_id = payload.session_id, use_adapter = payload.use_adapter, + stats_holder = _sf_stats_holder, ) _sf_tool_sentinel = object() @@ -3537,6 +3541,25 @@ async def openai_chat_completions( ], ) yield f"data: {final_chunk.model_dump_json(exclude_none = True)}\n\n" + # Usage chunk from the last turn, same shape as the + # GGUF tool loop's metadata. Request-scoped holder, so + # concurrent streams cannot read each other's stats. + _stats = _sf_stats_holder.get("stats") + if _stats: + _stream_usage = _stats.get("usage") or {} + usage_chunk = ChatCompletionChunk( + id = completion_id, + created = created, + model = model_name, + choices = [], + usage = CompletionUsage( + prompt_tokens = _stream_usage.get("prompt_tokens", 0), + completion_tokens = _stream_usage.get("completion_tokens", 0), + total_tokens = _stream_usage.get("total_tokens", 0), + ), + timings = _stats.get("timings"), + ) + yield f"data: {usage_chunk.model_dump_json(exclude_none = True)}\n\n" yield "data: [DONE]\n\n" except asyncio.CancelledError: @@ -3627,19 +3650,25 @@ async def openai_chat_completions( if payload.preserve_thinking is not None: gen_kwargs["preserve_thinking"] = payload.preserve_thinking + # Request-scoped usage/timings receptacle (filled at gen_done). + stats_holder: dict = {} + if payload.use_adapter is not None: def generate(): return backend.generate_with_adapter_control( use_adapter = payload.use_adapter, cancel_event = cancel_event, + stats_holder = stats_holder, **gen_kwargs, ) else: def generate(): return backend.generate_chat_response( - cancel_event = cancel_event, **gen_kwargs + cancel_event = cancel_event, + stats_holder = stats_holder, + **gen_kwargs, ) # ── Streaming response ──────────────────────────────────────── @@ -3716,6 +3745,26 @@ async def openai_chat_completions( ], ) yield f"data: {final_chunk.model_dump_json(exclude_none = True)}\n\n" + # Usage chunk (choices=[], usage set), same shape as the + # GGUF path so the speed popover works for MLX too. + # Request-scoped holder, so concurrent streams cannot + # read each other's stats. + _stats = stats_holder.get("stats") + if _stats: + _stream_usage = _stats.get("usage") or {} + usage_chunk = ChatCompletionChunk( + id = completion_id, + created = created, + model = model_name, + choices = [], + usage = CompletionUsage( + prompt_tokens = _stream_usage.get("prompt_tokens", 0), + completion_tokens = _stream_usage.get("completion_tokens", 0), + total_tokens = _stream_usage.get("total_tokens", 0), + ), + timings = _stats.get("timings"), + ) + yield f"data: {usage_chunk.model_dump_json(exclude_none = True)}\n\n" yield "data: [DONE]\n\n" except asyncio.CancelledError: From 1e811acd622de45bfad5c42dfac34dcb6e82a165 Mon Sep 17 00:00:00 2001 From: Michael Han <107991372+shimmyshimmer@users.noreply.github.com> Date: Sun, 7 Jun 2026 01:57:55 -0700 Subject: [PATCH 06/12] Studio: tag MLX loaded models as MLX instead of Base in chat (#6067) * Studio: tag MLX loaded models as MLX instead of Base in chat * Studio: tag MLX named hub defaults via name heuristic --- studio/backend/core/inference/orchestrator.py | 1 + studio/backend/core/inference/worker.py | 2 ++ studio/backend/models/models.py | 3 +++ studio/backend/routes/models.py | 17 ++++++++++++++++- .../chat/hooks/use-chat-model-runtime.ts | 13 ++++++++++++- studio/frontend/src/features/chat/types/api.ts | 1 + .../frontend/src/features/chat/types/runtime.ts | 1 + 7 files changed, 36 insertions(+), 2 deletions(-) diff --git a/studio/backend/core/inference/orchestrator.py b/studio/backend/core/inference/orchestrator.py index 6321ca892d..9810f2b9da 100644 --- a/studio/backend/core/inference/orchestrator.py +++ b/studio/backend/core/inference/orchestrator.py @@ -705,6 +705,7 @@ class InferenceOrchestrator: self.models[self.active_model_name] = { "is_vision": model_info.get("is_vision", False), "is_lora": model_info.get("is_lora", False), + "is_mlx": model_info.get("is_mlx", False), "display_name": model_info.get("display_name", model_name), "is_audio": model_info.get("is_audio", False), "audio_type": model_info.get("audio_type"), diff --git a/studio/backend/core/inference/worker.py b/studio/backend/core/inference/worker.py index d01cce4fc1..31fd55a156 100644 --- a/studio/backend/core/inference/worker.py +++ b/studio/backend/core/inference/worker.py @@ -342,6 +342,8 @@ def _handle_load(backend, config: dict, resp_queue: Any) -> None: "is_vision": mc.is_vision, "is_lora": mc.is_lora, "is_gguf": False, + # MLX backend sets device="mlx"; lets the UI tag MLX models. + "is_mlx": getattr(backend, "device", None) == "mlx", "is_audio": getattr(mc, "is_audio", False), "audio_type": getattr(mc, "audio_type", None), "has_audio_input": getattr(mc, "has_audio_input", False), diff --git a/studio/backend/models/models.py b/studio/backend/models/models.py index 46ca4e3784..a53569aaa1 100644 --- a/studio/backend/models/models.py +++ b/studio/backend/models/models.py @@ -76,6 +76,9 @@ class ModelDetails(BaseModel): is_gguf: bool = Field( False, description = "Whether model is a GGUF model (llama.cpp format)" ) + is_mlx: bool = Field( + False, description = "Whether model is served via the MLX backend (Apple Silicon)" + ) is_audio: bool = Field(False, description = "Whether model is a TTS audio model") audio_type: Optional[str] = Field( None, description = "Audio codec type: snac, csm, bicodec, dac" diff --git a/studio/backend/routes/models.py b/studio/backend/routes/models.py index 9ea113e488..2b729eea9c 100644 --- a/studio/backend/routes/models.py +++ b/studio/backend/routes/models.py @@ -1446,6 +1446,15 @@ async def browse_folders( ) +def _looks_like_mlx_repo(model_id: str) -> bool: + """Name heuristic for unloaded models, mirrors the -GGUF suffix check. + Tokenized so MLX only matches as a whole name segment.""" + if model_id.lower().startswith("mlx-community/"): + return True + tail = model_id.split("/")[-1] + return "MLX" in _re.split(r"[-_.]", tail.upper()) + + @router.get("/list") async def list_models( current_subject: str = Depends(get_current_subject), @@ -1471,6 +1480,7 @@ async def list_models( name = model_name.split("/")[-1] if "/" in model_name else model_name, is_vision = _is_vision, is_lora = model_data.get("is_lora", False), + is_mlx = model_data.get("is_mlx", False), is_audio = model_data.get("is_audio", False), audio_type = _audio_type, has_audio_input = model_data.get("has_audio_input", False), @@ -1498,13 +1508,18 @@ async def list_models( all_models = [] seen_ids = set() + # Prefer loaded entries for duplicate ids so runtime flags + # (is_mlx, is_vision, is_audio, ...) are not lost. + loaded_by_id = {model_info.id: model_info for model_info in loaded_models} + # Add default models for model_id in default_models: if model_id not in seen_ids: - model_info = ModelDetails( + model_info = loaded_by_id.get(model_id) or ModelDetails( id = model_id, name = model_id.split("/")[-1] if "/" in model_id else model_id, is_gguf = model_id.upper().endswith("-GGUF"), + is_mlx = _looks_like_mlx_repo(model_id), ) all_models.append(model_info) seen_ids.add(model_id) diff --git a/studio/frontend/src/features/chat/hooks/use-chat-model-runtime.ts b/studio/frontend/src/features/chat/hooks/use-chat-model-runtime.ts index e6892b34fd..d1dab924cb 100644 --- a/studio/frontend/src/features/chat/hooks/use-chat-model-runtime.ts +++ b/studio/frontend/src/features/chat/hooks/use-chat-model-runtime.ts @@ -94,16 +94,25 @@ function describeModel(model: { is_lora?: boolean; is_vision?: boolean; is_gguf?: boolean; + is_mlx?: boolean; is_audio?: boolean; has_audio_input?: boolean; }): string | undefined { const tags: string[] = []; if (model.is_gguf) tags.push("GGUF"); + if (model.is_mlx) tags.push("MLX"); if (model.is_lora) tags.push("LoRA"); if (model.is_vision) tags.push("Vision"); if (model.is_audio) tags.push("Audio"); if (model.has_audio_input) tags.push("Audio Input"); - if (!model.is_lora && !model.is_vision && !model.is_gguf && !model.is_audio && !model.has_audio_input) + if ( + !model.is_lora && + !model.is_vision && + !model.is_gguf && + !model.is_mlx && + !model.is_audio && + !model.has_audio_input + ) tags.push("Base"); return tags.join(" · "); } @@ -114,6 +123,7 @@ function toChatModelSummary(model: { is_lora?: boolean; is_vision?: boolean; is_gguf?: boolean; + is_mlx?: boolean; is_audio?: boolean; audio_type?: string | null; has_audio_input?: boolean; @@ -125,6 +135,7 @@ function toChatModelSummary(model: { isLora: Boolean(model.is_lora), isVision: Boolean(model.is_vision), isGguf: Boolean(model.is_gguf), + isMlx: Boolean(model.is_mlx), isAudio: Boolean(model.is_audio), audioType: model.audio_type ?? null, hasAudioInput: Boolean(model.has_audio_input), diff --git a/studio/frontend/src/features/chat/types/api.ts b/studio/frontend/src/features/chat/types/api.ts index d313b43438..92ea1500bd 100644 --- a/studio/frontend/src/features/chat/types/api.ts +++ b/studio/frontend/src/features/chat/types/api.ts @@ -7,6 +7,7 @@ export interface BackendModelDetails { is_vision?: boolean; is_lora?: boolean; is_gguf?: boolean; + is_mlx?: boolean; is_audio?: boolean; audio_type?: string | null; has_audio_input?: boolean; diff --git a/studio/frontend/src/features/chat/types/runtime.ts b/studio/frontend/src/features/chat/types/runtime.ts index 4c44ee1e9c..24286c94fb 100644 --- a/studio/frontend/src/features/chat/types/runtime.ts +++ b/studio/frontend/src/features/chat/types/runtime.ts @@ -44,6 +44,7 @@ export interface ChatModelSummary { isVision: boolean; isLora: boolean; isGguf?: boolean; + isMlx?: boolean; isAudio?: boolean; audioType?: string | null; hasAudioInput?: boolean; From da1c5b4b94a5628dce40ce773ba881f1ef08a4dc Mon Sep 17 00:00:00 2001 From: Michael Han <107991372+shimmyshimmer@users.noreply.github.com> Date: Sun, 7 Jun 2026 01:57:58 -0700 Subject: [PATCH 07/12] Studio: remove red border on chat error messages (#6063) Co-authored-by: shimmyshimmer --- studio/frontend/src/components/assistant-ui/thread.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/studio/frontend/src/components/assistant-ui/thread.tsx b/studio/frontend/src/components/assistant-ui/thread.tsx index a55c89f634..27404c83eb 100644 --- a/studio/frontend/src/components/assistant-ui/thread.tsx +++ b/studio/frontend/src/components/assistant-ui/thread.tsx @@ -1894,7 +1894,7 @@ const ComposerRightControls: FC<{ const MessageError: FC = () => { return ( - + From cf97faed9ff73af5e46c18a21efdad24ded876dc Mon Sep 17 00:00:00 2001 From: Michael Han <107991372+shimmyshimmer@users.noreply.github.com> Date: Sun, 7 Jun 2026 01:58:01 -0700 Subject: [PATCH 08/12] Studio: keep chat in place when composer attachments resize it (#6070) * Studio: keep chat in place when composer attachments resize it Attaching or removing a file in the chat composer could yank the whole conversation to the bottom, and the grown composer covered the end of the chat with no way to scroll it back into view. Root cause: the Viewport composes refs with an identity that changes on re-render, so React re-runs our scroll ref on unrelated renders and the autoscroll hook treated every rebind as a fresh mount, pinning to the bottom. On top of that the viewport reserved a fixed 160px under the last message regardless of composer size. - Treat same-element ref rebinds as no-ops in the autoscroll hook; only a genuinely new viewport element pins and resets detach state - Size the bottom spacer from the measured composer height plus a 24px gap so the chat can always be scrolled above the composer - On composer growth, detach from the bottom instead of auto-scrolling; the user scrolls down to reveal the covered lines - On composer shrink, defer the spacer shrink until it cannot clamp scrollTop, then release it invisibly on scroll or on bottom-pinning moments (run start, thread switch, thread load) * Studio: release deferred composer spacer when a run owns the bottom Sending with attachments cleared the chips after thread.runStart had already fired, so the spacer shrink was deferred while the user sat pinned at the bottom, leaving a permanent extra gap above the composer. Apply shrinks immediately while a run is active or within 1s of run start; the run-start pin owns the bottom then, so the clamp is the intended glide. Caught by a cross-engine Playwright pass (Chromium, Firefox, WebKit) over the pre and post builds. * Studio: track the viewport element in state so listeners survive remounts The deferred-shrink scroll listener was attached once against a ref, but the keyed overlay provider remounts the viewport subtree on thread switches, leaving the listener bound to the unmounted element. Removing an attachment near the bottom in the new thread then left the oversized spacer stuck until a run started. Track the viewport element in state so the listener and the clamp math follow the new element. Reproduced and verified with a thread-switch scenario on Chromium, Firefox and WebKit; full matrix re-run green. * Studio: release deferred composer spacer shrink when at the bottom (#6070) --------- Co-authored-by: shimmyshimmer Co-authored-by: Daniel Han --- .../src/components/assistant-ui/thread.tsx | 226 +++++++++++++++++- .../use-intent-aware-autoscroll.tsx | 71 ++++-- 2 files changed, 270 insertions(+), 27 deletions(-) diff --git a/studio/frontend/src/components/assistant-ui/thread.tsx b/studio/frontend/src/components/assistant-ui/thread.tsx index 27404c83eb..6b94bfff6c 100644 --- a/studio/frontend/src/components/assistant-ui/thread.tsx +++ b/studio/frontend/src/components/assistant-ui/thread.tsx @@ -119,6 +119,7 @@ import { useCallback, useContext, useEffect, + useLayoutEffect, useRef, useState, } from "react"; @@ -127,6 +128,18 @@ import { // composer), so the composer can show its "Drop files here" affordance. const PageDragContext = createContext(false); +// Gap (px) between the last message and the floating composer. The bottom +// spacer tracks composer height plus this gap so the chat can always be +// scrolled fully above the composer. +const COMPOSER_SCROLL_GAP_PX = 24; +// The scroll-to-bottom footer sits 10px below the spacer top. +const FOOTER_GAP_BELOW_SPACER_PX = 10; +// Composer shrinks this soon after a run start (send clears the chips) +// apply immediately: the run-start pin owns the bottom, so the clamp is +// the intended glide. Covers instant responses where isRunning is +// already false by the time the dock resize is observed. +const RUN_SHRINK_WINDOW_MS = 1000; + export const Thread: FC<{ hideComposer?: boolean; hideWelcome?: boolean; @@ -144,12 +157,156 @@ export const Thread: FC<{ ); const activeThreadId = useChatRuntimeStore((s) => s.activeThreadId); const threadId = targetThreadId ?? activeThreadId ?? null; + const aui = useAui(); + + // Measured height of the floating composer dock (null until measured). + // Drives the bottom spacer and the scroll-to-bottom footer offset. + const [composerHeight, setComposerHeight] = useState(null); + const footerBottomPx = + composerHeight == null + ? null + : composerHeight + COMPOSER_SCROLL_GAP_PX - FOOTER_GAP_BELOW_SPACER_PX; + + // The viewport element is owned by the autoscroll hook; mirror it + // locally for the spacer clamp math below. State, not a ref: the keyed + // provider below remounts the viewport on thread switches, and the + // scroll listener effect must re-attach to the new element. + const [viewportEl, setViewportEl] = useState(null); + const composedViewportRef = useCallback( + (node: HTMLElement | null) => { + setViewportEl(node); + viewportRef(node); + }, + [viewportRef], + ); + + // Bottom spacer sizing. Invariant: the chat never moves on its own when + // the composer resizes. + // - Grow (attachment added, multiline input): grow the spacer at once. + // Growth below the scroll position is invisible and only adds room. + // - Shrink (attachment removed): shrinking scrollHeight near the bottom + // would clamp scrollTop and yank the chat down. Defer the shrink until + // it is invisible (user scrolled up) or a bottom-pinning moment. + // Applied imperatively so a remounted spacer can be sized from refs even + // when composerHeight did not change (e.g. thread switch). + const spacerElRef = useRef(null); + const desiredSpacerPxRef = useRef(null); + const appliedSpacerPxRef = useRef(null); + + const applySpacerPx = useCallback((px: number) => { + appliedSpacerPxRef.current = px; + const node = spacerElRef.current; + if (node) { + node.style.height = `${px}px`; + } + }, []); + + // Release any deferred shrink; used at moments that pin to the bottom + // anyway, where the clamp is the intended motion. + const releaseSpacerExcess = useCallback(() => { + const desired = desiredSpacerPxRef.current; + const applied = appliedSpacerPxRef.current; + if (desired != null && applied != null && applied > desired) { + applySpacerPx(desired); + } + }, [applySpacerPx]); + + const spacerRef = useCallback( + (node: HTMLDivElement | null) => { + spacerElRef.current = node; + // Fresh mounts (thread switch, first message) start at the desired + // size; deferral state from a previous mount is moot. + const desired = desiredSpacerPxRef.current; + if (node && desired != null) { + applySpacerPx(desired); + } + }, + [applySpacerPx], + ); + + const prevComposerHeightRef = useRef(null); + // Set on thread.runStart; see RUN_SHRINK_WINDOW_MS. + const runStartAtRef = useRef(0); + useLayoutEffect(() => { + const prev = prevComposerHeightRef.current; + prevComposerHeightRef.current = composerHeight; + if (composerHeight == null || hideComposer) { + desiredSpacerPxRef.current = null; + appliedSpacerPxRef.current = null; + spacerElRef.current?.style.removeProperty("height"); + return; + } + const desired = composerHeight + COMPOSER_SCROLL_GAP_PX; + desiredSpacerPxRef.current = desired; + const applied = appliedSpacerPxRef.current; + if (applied == null || desired >= applied) { + applySpacerPx(desired); + } else { + const distance = viewportEl + ? viewportEl.scrollHeight - viewportEl.scrollTop - viewportEl.clientHeight + : Number.POSITIVE_INFINITY; + const runOwnsBottom = + aui.thread().getState().isRunning || + performance.now() - runStartAtRef.current < RUN_SHRINK_WINDOW_MS; + // At the bottom the shrink only drops blank spacer, so apply it now + // instead of stranding dead space until the next pin. + if ( + runOwnsBottom || + distance >= applied - desired || + autoScrollContext.getIsAtBottom() + ) { + applySpacerPx(desired); + } + // else: deferred; released on scroll or a bottom-pinning event. + } + if (prev != null && composerHeight > prev) { + // The chat is now above the new bottom. Detach as if the user had + // scrolled up so no later signal re-pins and shoves the chat up. + // Scrolling back down re-attaches; explicit pins still work. + // Mid-run growth comes from tool-status rows, not the user, and + // detaching then would break streaming autoscroll, so skip it. + if (!aui.thread().getState().isRunning) { + autoScrollContext.detachFromBottom(); + } + } + }, [composerHeight, hideComposer, autoScrollContext, aui, applySpacerPx, viewportEl]); + + // Drop deferred spacer excess as soon as the user has scrolled far + // enough above the bottom that the shrink cannot clamp scrollTop. + // Keyed on viewportEl so the listener follows viewport remounts. + useEffect(() => { + const el = viewportEl; + if (!el) { + return; + } + const onScroll = () => { + const desired = desiredSpacerPxRef.current; + const applied = appliedSpacerPxRef.current; + if (desired == null || applied == null || applied <= desired) { + return; + } + const distance = el.scrollHeight - el.scrollTop - el.clientHeight; + if (distance >= applied - desired) { + applySpacerPx(desired); + } + }; + el.addEventListener("scroll", onScroll, { passive: true }); + return () => el.removeEventListener("scroll", onScroll); + }, [viewportEl, applySpacerPx]); + + // These pin to the bottom, so releasing the excess here is invisible. + // runStart also opens the shrink window for the send-clears-chips case. + useAuiEvent("thread.runStart", () => { + runStartAtRef.current = performance.now(); + releaseSpacerExcess(); + }); + useAuiEvent("thread.initialize", releaseSpacerExcess); + useAuiEvent("threadListItem.switchedTo", releaseSpacerExcess); // Page-wide drag-and-drop: dropping a file anywhere on the chat page (not // just on the composer) attaches it and shows the composer drop affordance. // The composer's own dropzone still handles drops on the box itself; its // handler calls preventDefault, so the page handler skips them (no double-add). - const aui = useAui(); const [pageDragging, setPageDragging] = useState(false); const dragDepth = useRef(0); const hasFiles = (e: ReactDragEvent) => @@ -208,7 +365,7 @@ export const Thread: FC<{ > hideWelcome || !thread.isEmpty}>
@@ -250,21 +415,34 @@ export const Thread: FC<{ className={cn( "aui-thread-viewport-footer pointer-events-none sticky z-20 flex w-full justify-center bg-transparent", // 150px (was 140px) to add a small gap above the composer - hideComposer ? "bottom-3" : "bottom-[150px]", + hideComposer + ? "bottom-3" + : footerBottomPx == null + ? "bottom-[150px]" + : undefined, )} + style={ + !hideComposer && footerBottomPx != null + ? { bottom: footerBottomPx } + : undefined + } > - + {!hideComposer && ( hideWelcome || !thread.isEmpty}> )} @@ -275,9 +453,10 @@ export const Thread: FC<{ ); }; -const GeneratedImageViewportOverlay: FC<{ hideComposer?: boolean }> = ({ - hideComposer, -}) => { +const GeneratedImageViewportOverlay: FC<{ + hideComposer?: boolean; + bottomOffsetPx?: number | null; +}> = ({ hideComposer, bottomOffsetPx }) => { const { overlay, closeOverlay } = useGeneratedImageOverlay(); useEffect(() => { @@ -302,8 +481,17 @@ const GeneratedImageViewportOverlay: FC<{ hideComposer?: boolean }> = ({
@@ -370,11 +558,29 @@ const GeneratedImageViewportOverlay: FC<{ hideComposer?: boolean }> = ({ const ThreadComposerDock: FC<{ disabled?: boolean; threadId?: string | null; -}> = ({ disabled, threadId }) => { + onHeightChange?: (height: number | null) => void; +}> = ({ disabled, threadId, onHeightChange }) => { const { overlay } = useGeneratedImageOverlay(); + // Report the dock's rendered height so the viewport can reserve matching + // scroll space when attachments or multiline input grow the composer. + const dockRef = useRef(null); + useEffect(() => { + const el = dockRef.current; + if (!el || !onHeightChange) return; + const measure = () => onHeightChange(el.offsetHeight); + measure(); + const resizeObserver = new ResizeObserver(measure); + resizeObserver.observe(el); + return () => { + resizeObserver.disconnect(); + onHeightChange(null); + }; + }, [onHeightChange]); + return (
boolean; subscribe: (listener: () => void) => () => void; + /** + * Mark the user as detached from the bottom, as if they had scrolled + * up. Called when the composer grows and the bottom spacer grows with + * it: the chat is then above the new bottom, and observer-driven pins + * must not shove it up. Scrolling back to the bottom re-attaches; + * explicit pins (run start, scroll-to-bottom button) still work. + */ + detachFromBottom: () => void; }; const noopContext: AutoScrollContextValue = { @@ -87,6 +95,9 @@ const noopContext: AutoScrollContextValue = { subscribe: () => () => { /* no-op */ }, + detachFromBottom: () => { + /* no viewport mounted */ + }, }; const AutoScrollContext = createContext(noopContext); @@ -129,6 +140,9 @@ export function useIntentAwareAutoScroll(): { const scrollImplRef = useRef(() => { /* no viewport mounted */ }); + const detachImplRef = useRef<() => void>(() => { + /* no viewport mounted */ + }); const getIsAtBottom = useCallback(() => isAtBottomRef.current, []); @@ -153,8 +167,12 @@ export function useIntentAwareAutoScroll(): { scrollImplRef.current(behavior); }, []); + const detachFromBottom = useCallback(() => { + detachImplRef.current(); + }, []); + const attach = useCallback( - (el: HTMLElement) => { + (el: HTMLElement, isRebind: boolean) => { let rafId: number | null = null; let lastScrollTop = el.scrollTop; let lastClientWidth = el.clientWidth; @@ -286,6 +304,13 @@ export function useIntentAwareAutoScroll(): { requestTick(); }; + // Programmatic detach (see detachFromBottom). Same effect as the + // user scrolling up; the tick refresh updates isAtBottom. + detachImplRef.current = () => { + detach(); + requestTick(); + }; + const onWheel = (e: WheelEvent) => { if ( e.deltaY < 0 && @@ -476,21 +501,24 @@ export function useIntentAwareAutoScroll(): { const mutationObserver = new MutationObserver(onLayoutChange); const onViewportResize = onLayoutChange; - // Fresh attach always starts pinned. `userDetachedRef` survives - // ref rebinds (it's hook-scoped), so if the viewport element is - // ever unmounted and remounted without an AUI lifecycle event - // (e.g. a parent layout refactor that remounts the viewport), - // a prior detach would silently disable auto-follow for the - // rest of the session. - userDetachedRef.current = false; + // Fresh attach (a new viewport element) always starts pinned. + // Rebinds to the SAME element must not pin or reset detach state: + // the Viewport composes refs with an identity that changes on + // re-render, so React re-runs the ref (null, then same element) + // on unrelated renders such as composer resizes. Pinning here + // would yank the chat to the bottom on every such render. The + // observers below are re-installed either way. + if (!isRebind) { + userDetachedRef.current = false; - // Pin to bottom when the ref first attaches. Covers the case - // where `thread.initialize` fires before the ref is bound. - extendFollow(); - if (el.scrollHeight > el.clientHeight) { - el.scrollTo({ top: el.scrollHeight, behavior: "instant" }); + // Pin to bottom when the ref first attaches. Covers the case + // where `thread.initialize` fires before the ref is bound. + extendFollow(); + if (el.scrollHeight > el.clientHeight) { + el.scrollTo({ top: el.scrollHeight, behavior: "instant" }); + } + setIsAtBottom(true); } - setIsAtBottom(true); requestTick(); // Observe the border box, not the content box. The stabilizer @@ -544,6 +572,9 @@ export function useIntentAwareAutoScroll(): { scrollImplRef.current = () => { /* no viewport mounted */ }; + detachImplRef.current = () => { + /* no viewport mounted */ + }; }; }, [setIsAtBottom], @@ -562,6 +593,7 @@ export function useIntentAwareAutoScroll(): { useAuiEvent("thread.initialize", () => pinToBottom("instant")); useAuiEvent("threadListItem.switchedTo", () => pinToBottom("instant")); + const lastElRef = useRef(null); const ref = useCallback>( (el) => { if (cleanupRef.current) { @@ -569,15 +601,20 @@ export function useIntentAwareAutoScroll(): { cleanupRef.current = null; } if (el) { - cleanupRef.current = attach(el); + // Same-element rebind vs a genuinely new element, see attach(). + const isRebind = lastElRef.current === el; + lastElRef.current = el; + cleanupRef.current = attach(el, isRebind); } + // On null, keep lastElRef so a rebind to the same element is + // recognized; a real remount binds a different element anyway. }, [attach], ); const context = useMemo( - () => ({ scrollToBottom, getIsAtBottom, subscribe }), - [scrollToBottom, getIsAtBottom, subscribe], + () => ({ scrollToBottom, getIsAtBottom, subscribe, detachFromBottom }), + [scrollToBottom, getIsAtBottom, subscribe, detachFromBottom], ); return { ref, context }; From b2b4e4c37655fa9a3ce19555c9868a1b7240b4dd Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Sun, 7 Jun 2026 21:43:09 -0700 Subject: [PATCH 09/12] CI: allowlist deepseek_ocr2 in the compiler full-model-sweep (#6085) transformers-latest ships a new deepseek_ocr2 model whose source-rewriter compile exceeds the 60s per-model budget on the CI runner, same as the existing beit/sam/sam_hq entries. Add it to KNOWN_BROKEN_COMPILE Category F so HF=latest Core stops failing on a new upstream model. The slow compile path itself remains a follow-up for unsloth_zoo. --- .github/workflows/consolidated-tests-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/consolidated-tests-ci.yml b/.github/workflows/consolidated-tests-ci.yml index f8eccc7d18..bf7e62e295 100644 --- a/.github/workflows/consolidated-tests-ci.yml +++ b/.github/workflows/consolidated-tests-ci.yml @@ -992,6 +992,7 @@ jobs: "beit": "TimeoutError: compile exceeds per-model budget", "sam": "TimeoutError: compile exceeds per-model budget", "sam_hq": "TimeoutError: compile exceeds per-model budget", + "deepseek_ocr2": "TimeoutError: compile exceeds per-model budget", } From e20a6c30206e213f5e18111460a20281ce89c33b Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Mon, 8 Jun 2026 03:40:47 -0700 Subject: [PATCH 10/12] Restore KTO logps truncation guard for TRL (re-apply dropped #5996) (#6086) * Restore KTO logps truncation guard for TRL (re-apply dropped #5996) #5996 ported the KTO truncation guard to TRL's _compute_logps refactor but was dropped from main in the 2026-06-05 history rewrite. Re-apply the unsloth/models/rl_replacements.py guard (kto_trainer_get_batch_logps + kto_trainer_align_completion_logps); its regexes still match TRL main's current compute_ref_log_probs / _compute_kl_logps shape (per_token_logps = selective_log_softmax(shift_logits, ...)), so the guard remains effective. Also extend the version_compat detection to recognize that current shape: TRL refactored KTO again (no get_batch_logps / _compute_logps), so the test was failing on TRL main even though the rewrite still applies. * KTO patcher: match single or double quotes in dict-key regexes Per review: _KTO_COMPLETION_RE / _KTO_KL_RE hardcoded double quotes for the TRL dict keys, so a formatter or TRL version using single quotes would make the patch silently skip. Accept both quote styles. Verified the regexes still match TRL main's current experimental/kto source. --- .../test_trl_grpo_pinned_symbols.py | 25 +++++--- unsloth/models/rl_replacements.py | 57 +++++++++++++++++++ 2 files changed, 74 insertions(+), 8 deletions(-) diff --git a/tests/version_compat/test_trl_grpo_pinned_symbols.py b/tests/version_compat/test_trl_grpo_pinned_symbols.py index 4c7dcc4234..815cb5f784 100644 --- a/tests/version_compat/test_trl_grpo_pinned_symbols.py +++ b/tests/version_compat/test_trl_grpo_pinned_symbols.py @@ -551,12 +551,12 @@ def test_trl_grpo_source_inference_mode_unwrap(tag: str): @pytest.mark.parametrize("tag", TRL_TAGS) def test_trl_kto_get_batch_logps_signature(tag: str): - """TRL 0.27+ moved KTOTrainer to trl.experimental.kto and the - canonical kto_trainer.py shrank to a thin re-export wrapper. The - real `get_batch_logps` lives at trl/experimental/kto/kto_trainer.py. - Unsloth's MRO walk in models/rl.py:592-708 already follows - trl.experimental.* parents, so either path is fine — we just - require the symbol to exist SOMEWHERE.""" + """KTO log-prob computation must stay patchable. Through TRL 1.x the + target was KTOTrainer.get_batch_logps; TRL 1.x dropped it and moved the + math into _compute_logps / compute_ref_log_probs calling + selective_log_softmax. unsloth/models/rl_replacements.py patches BOTH + shapes (kto_trainer_get_batch_logps + kto_trainer_align_completion_logps), + so we require EITHER form to exist wherever KTOTrainer lives.""" candidates = [ "trl/trainer/kto_trainer.py", "trl/experimental/kto/kto_trainer.py", @@ -566,11 +566,20 @@ def test_trl_kto_get_batch_logps_signature(tag: str): src = fetch_text("huggingface/trl", tag, path) if src is None: continue + # Legacy: explicit get_batch_logps method. if has_def(src, "get_batch_logps", "func"): return + # TRL 1.x: refactored into _compute_logps + selective_log_softmax. + if has_def(src, "_compute_logps", "func") and "selective_log_softmax" in src: + return + # TRL 1.x (current): compute_ref_log_probs / _compute_kl_logps build + # per_token_logps via selective_log_softmax(shift_logits, ...); this is + # the exact shape kto_trainer_align_completion_logps patches. + if "per_token_logps = selective_log_softmax(shift_logits" in src: + return pytest.fail( - f"{tag}: KTOTrainer.get_batch_logps not found in any of {candidates}; " - f"unsloth/models/rl_replacements.py:1675 rewrite silently skipped" + f"{tag}: KTO log-prob computation not found in any of {candidates}; " + f"unsloth/models/rl_replacements.py KTO rewrite silently skipped" ) diff --git a/unsloth/models/rl_replacements.py b/unsloth/models/rl_replacements.py index 31d54675c9..7bceebb252 100644 --- a/unsloth/models/rl_replacements.py +++ b/unsloth/models/rl_replacements.py @@ -1962,6 +1962,63 @@ def kto_trainer_get_batch_logps(function_name, function): RL_FUNCTIONS["kto_trainer"].append(kto_trainer_get_batch_logps) +# TRL 1.x dropped KTOTrainer.get_batch_logps and moved the log-prob math into +# _compute_logps / compute_ref_log_probs / _compute_kl_logps, which call +# selective_log_softmax on completion-only tokens. Same truncation hazard as +# above, so clamp logits/ids/mask to the shorter seq length (no-op when equal). +_KTO_COMPLETION_RE = re.compile( + r"(?P[ \t]*)shift_logits = completion_logits\[:, :-1, :\]\.contiguous\(\)\n" + r"(?P=ws)per_token_logps = selective_log_softmax\(\s*shift_logits,\s*" + r"(?P\w+)\[[\"']completion_input_ids[\"']\]\[:, 1:\]\.contiguous\(\)\s*\)\n" + r"(?P=ws)per_token_logps\[(?P=var)\[[\"']completion_mask[\"']\]\[:, 1:\] == 0\] = 0\.0" +) +_KTO_KL_RE = re.compile( + r"(?P[ \t]*)shift_KL_logits = KL_logits\[:, :-1, :\]\.contiguous\(\)\n" + r"(?P=ws)KL_per_token_logps = selective_log_softmax\(\s*shift_KL_logits,\s*" + r"(?P\w+)\[[\"']KL_completion_input_ids[\"']\]\[:, 1:\]\.contiguous\(\)\s*\)\n" + r"(?P=ws)KL_per_token_logps\[(?P=var)\[[\"']KL_completion_mask[\"']\]\[:, 1:\] == 0\] = 0\.0" +) + + +def _kto_completion_repl(m): + ws, var = m.group("ws"), m.group("var") + return ( + f"{ws}shift_logits = completion_logits[:, :-1, :].contiguous()\n" + f"{ws}# Unsloth: clamp logits/ids/mask to shorter seq len (model may truncate input_ids)\n" + f'{ws}_uns_ids = {var}["completion_input_ids"][:, 1:].contiguous()\n' + f"{ws}_uns_n = min(shift_logits.shape[1], _uns_ids.shape[1])\n" + f"{ws}per_token_logps = selective_log_softmax(shift_logits[:, :_uns_n], _uns_ids[:, :_uns_n])\n" + f'{ws}per_token_logps[{var}["completion_mask"][:, 1:][:, :_uns_n] == 0] = 0.0' + ) + + +def _kto_kl_repl(m): + ws, var = m.group("ws"), m.group("var") + return ( + f"{ws}shift_KL_logits = KL_logits[:, :-1, :].contiguous()\n" + f"{ws}# Unsloth: clamp logits/ids/mask to shorter seq len (model may truncate input_ids)\n" + f'{ws}_uns_kl_ids = {var}["KL_completion_input_ids"][:, 1:].contiguous()\n' + f"{ws}_uns_kl_n = min(shift_KL_logits.shape[1], _uns_kl_ids.shape[1])\n" + f"{ws}KL_per_token_logps = selective_log_softmax(shift_KL_logits[:, :_uns_kl_n], _uns_kl_ids[:, :_uns_kl_n])\n" + f'{ws}KL_per_token_logps[{var}["KL_completion_mask"][:, 1:][:, :_uns_kl_n] == 0] = 0.0' + ) + + +def kto_trainer_align_completion_logps(function_name, function): + if function_name not in ( + "_compute_logps", + "compute_ref_log_probs", + "_compute_kl_logps", + ): + return function + function = _KTO_COMPLETION_RE.sub(_kto_completion_repl, function) + function = _KTO_KL_RE.sub(_kto_kl_repl, function) + return function + + +RL_FUNCTIONS["kto_trainer"].append(kto_trainer_align_completion_logps) + + # https://github.com/huggingface/trl/blob/main/trl/trainer/grpo_trainer.py#L356 # TRL warns if batch size is not a multiple of num_generations -> fix this. def grpo_trainer_fix_batch_size(RLTrainer_source, RLConfig_source): From 8ccdf596aa8e69f9f949c07098cbced0c37ae111 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Mon, 8 Jun 2026 03:40:59 -0700 Subject: [PATCH 11/12] Studio: stop leaking internal exceptions to API clients; harden sandbox path (#6072) * Studio: stop leaking internal exceptions to API clients; harden sandbox path Security hardening for the FastAPI backend. Error exposure (CodeQL py/stack-trace-exposure): many route handlers returned raw caught-exception text to clients via HTTPException detail / response bodies, which can leak internal filesystem paths and stack detail. Add shared helpers in utils/utils.py (safe_error_detail, log_and_http_error) that log the full exception server-side and return a generic message, and sweep the route layer (inference, models, export, training, datasets, chat_history, providers, mcp_servers, settings, data_recipe/{jobs,seed,validate,mcp}) to use them. Intentionally user-facing validation messages, the existing _friendly_error SSE paths, and upstream-service body passthrough (llama-server / OpenAI) are kept; absolute server paths echoed in models.py browse/read errors are redacted. Path injection (CodeQL py/path-injection): serve_sandbox_file already does basename + realpath containment; add a strict filename allowlist (^[A-Za-z0-9._-]{1,255}$) before the path is built as defense-in-depth and to give the analyzer a clear sanitizer. No behavior change beyond error-message text; status codes preserved. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Address review: keep curated error messages, fix remaining load leak - inference.py /load non-native path: redact str(e) instead of leaking it (matched the native branch which already redacted). - llama_extra_args validation: return the curated, path-redacted message instead of the generic fallback so users see the offending flag. - sandbox file serving: allowlist now forbids only separators/control chars via fullmatch, so generated images like 'loss curve.png' render again while traversal is still blocked by basename + extension + realpath. - Add safe_curated_detail() for domain/validation exceptions whose message is intentionally user-facing; apply it to data_recipe job/validate, chat conflict, provider test, and MCP probe paths (these were collapsing to 'An internal error occurred', and 'connection' even mis-mapped to an upstream-service message). Generic Exception paths keep safe_error_detail. - log_and_http_error: tolerate stdlib loggers (no structlog kwargs). - delete_openai_container: log transport errors with exc_info like list/create. - Drop helper/HTTPException imports this change left unused. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * log_and_http_error: log original error traceback on stdlib-logger fallback * Tidy error-helper and sandbox comments for PR #6072 * Trim redundant comments in studio error-hardening routes for PR #6072 * Re-trigger CI now that unsloth-zoo #727 is merged (Core pulls zoo main) * Address PR #6072 review feedback - inference.py: keep the actionable NativePathLeaseError detail (path-redacted) instead of collapsing it to the generic message, matching the other curated validation paths in this file. - utils.py: log via a single formatted log.error(exc_info=error) call that works for structlog and stdlib loggers; drop the now-unneeded try/except helper. - models.py: use Path.name instead of os.path.basename(str(current)). --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- studio/backend/routes/chat_history.py | 28 ++++- studio/backend/routes/data_recipe/jobs.py | 51 ++++++-- studio/backend/routes/data_recipe/mcp.py | 17 ++- studio/backend/routes/data_recipe/seed.py | 50 ++++++-- studio/backend/routes/data_recipe/validate.py | 25 +++- studio/backend/routes/datasets.py | 6 +- studio/backend/routes/export.py | 18 +-- studio/backend/routes/inference.py | 83 +++++++++---- studio/backend/routes/mcp_servers.py | 25 +++- studio/backend/routes/models.py | 113 ++++++++++++------ studio/backend/routes/providers.py | 20 +++- studio/backend/routes/settings.py | 14 ++- studio/backend/routes/training.py | 57 ++++++--- studio/backend/utils/utils.py | 61 ++++++++++ 14 files changed, 436 insertions(+), 132 deletions(-) diff --git a/studio/backend/routes/chat_history.py b/studio/backend/routes/chat_history.py index 75b5be2e49..4da3c7d621 100644 --- a/studio/backend/routes/chat_history.py +++ b/studio/backend/routes/chat_history.py @@ -11,6 +11,8 @@ from fastapi import APIRouter, Depends, HTTPException, Query from pydantic import BaseModel, ConfigDict, Field, ValidationError from auth.authentication import get_current_subject +from loggers import get_logger +from utils.utils import safe_curated_detail, log_and_http_error from storage.studio_db import ( ChatMessageConflictError, CorruptSettingsError, @@ -40,6 +42,8 @@ from storage.studio_db import ( router = APIRouter() +logger = get_logger(__name__) + class ChatThread(BaseModel): id: str @@ -406,7 +410,13 @@ async def save_thread_message( try: return ChatMessage(**upsert_chat_message(payload.model_dump())) except ChatMessageConflictError as exc: - raise HTTPException(status_code = 409, detail = str(exc)) from exc + raise log_and_http_error( + exc, + 409, + safe_curated_detail(exc), + event = "chat_history.save_message_conflict", + log = logger, + ) from exc @router.put("/threads/{thread_id}/messages", response_model = ChatMessageListResponse) @@ -442,7 +452,13 @@ async def replace_thread_messages( ] ) except ChatMessageConflictError as exc: - raise HTTPException(status_code = 409, detail = str(exc)) from exc + raise log_and_http_error( + exc, + 409, + safe_curated_detail(exc), + event = "chat_history.replace_messages_conflict", + log = logger, + ) from exc @router.get("/count", response_model = ChatCountResponse) @@ -497,7 +513,13 @@ async def put_settings( settings = upsert_chat_settings_merge(parsed.model_dump(exclude_unset = True)) ) except CorruptSettingsError as exc: - raise HTTPException(status_code = 409, detail = str(exc)) from exc + raise log_and_http_error( + exc, + 409, + safe_curated_detail(exc), + event = "chat_history.put_settings_conflict", + log = logger, + ) from exc @router.get("/export", response_model = ChatExportResponse) diff --git a/studio/backend/routes/data_recipe/jobs.py b/studio/backend/routes/data_recipe/jobs.py index 107a1657f3..238ff08006 100644 --- a/studio/backend/routes/data_recipe/jobs.py +++ b/studio/backend/routes/data_recipe/jobs.py @@ -19,13 +19,16 @@ from core.data_recipe.huggingface import ( publish_recipe_dataset, ) from core.data_recipe.jobs import get_job_manager +from loggers import get_logger from models.data_recipe import ( JobCreateResponse, PublishDatasetRequest, PublishDatasetResponse, RecipePayload, ) +from utils.utils import safe_error_detail, safe_curated_detail, log_and_http_error +logger = get_logger(__name__) router = APIRouter() @@ -439,14 +442,24 @@ def create_job(payload: RecipePayload, request: Request): RunConfig.model_validate(run_config_raw) except (ImportError, ValidationError, TypeError, ValueError) as exc: - raise HTTPException( - status_code = 400, detail = f"invalid run_config: {exc}" + raise log_and_http_error( + exc, + 400, + "invalid run_config", + event = "data_recipe.jobs.run_config_invalid", + log = logger, ) from exc try: internal_api_key_id = _inject_local_providers(recipe, request) except ValueError as exc: - raise HTTPException(status_code = 400, detail = str(exc)) from exc + raise log_and_http_error( + exc, + 400, + safe_curated_detail(exc), + event = "data_recipe.jobs.inject_local_providers_failed", + log = logger, + ) from exc # Single try block covers get_job_manager() AND mgr.start() so a workflow # key minted above never outlives the request even when an unexpected @@ -463,11 +476,23 @@ def create_job(payload: RecipePayload, request: Request): except RuntimeError as exc: if internal_api_key_id is not None: _revoke_internal_api_key_safe(internal_api_key_id) - raise HTTPException(status_code = 409, detail = str(exc)) from exc + raise log_and_http_error( + exc, + 409, + safe_curated_detail(exc), + event = "data_recipe.jobs.start_conflict", + log = logger, + ) from exc except ValueError as exc: if internal_api_key_id is not None: _revoke_internal_api_key_safe(internal_api_key_id) - raise HTTPException(status_code = 400, detail = str(exc)) from exc + raise log_and_http_error( + exc, + 400, + safe_curated_detail(exc), + event = "data_recipe.jobs.start_failed", + log = logger, + ) from exc except Exception: if internal_api_key_id is not None: _revoke_internal_api_key_safe(internal_api_key_id) @@ -593,9 +618,21 @@ def publish_job_dataset(job_id: str, payload: PublishDatasetRequest): private = payload.private, ) except RecipeDatasetPublishError as exc: - raise HTTPException(status_code = 400, detail = str(exc)) from exc + raise log_and_http_error( + exc, + 400, + safe_curated_detail(exc), + event = "data_recipe.jobs.publish_failed", + log = logger, + ) from exc except Exception as exc: - raise HTTPException(status_code = 500, detail = str(exc)) from exc + raise log_and_http_error( + exc, + 500, + safe_error_detail(exc), + event = "data_recipe.jobs.publish_error", + log = logger, + ) from exc return { "success": True, diff --git a/studio/backend/routes/data_recipe/mcp.py b/studio/backend/routes/data_recipe/mcp.py index 7184934ce9..2c79d323f3 100644 --- a/studio/backend/routes/data_recipe/mcp.py +++ b/studio/backend/routes/data_recipe/mcp.py @@ -10,12 +10,15 @@ from collections import defaultdict from fastapi import APIRouter from core.data_recipe.service import build_mcp_providers +from loggers import get_logger from models.data_recipe import ( McpToolsListRequest, McpToolsListResponse, McpToolsProviderResult, ) +from utils.utils import safe_error_detail +logger = get_logger(__name__) router = APIRouter() @@ -24,11 +27,16 @@ def list_mcp_tools(payload: McpToolsListRequest) -> McpToolsListResponse: try: from data_designer.engine.mcp import io as mcp_io except ImportError as exc: + logger.error( + "data_recipe.mcp.dependencies_unavailable", + error = str(exc), + exc_info = True, + ) return McpToolsListResponse( providers = [ McpToolsProviderResult( name = "", - error = f"MCP dependencies unavailable: {exc}", + error = "MCP dependencies unavailable.", ) ] ) @@ -73,10 +81,15 @@ def list_mcp_tools(payload: McpToolsListRequest) -> McpToolsListResponse: ) ) except Exception as exc: + logger.error( + "data_recipe.mcp.list_tools_failed", + error = str(exc), + exc_info = True, + ) providers.append( McpToolsProviderResult( name = provider.name or provider_name, - error = str(exc).strip() or "Failed to load tools.", + error = safe_error_detail(exc, fallback = "Failed to load tools."), ) ) diff --git a/studio/backend/routes/data_recipe/seed.py b/studio/backend/routes/data_recipe/seed.py index a18f8f3e32..51ea37452e 100644 --- a/studio/backend/routes/data_recipe/seed.py +++ b/studio/backend/routes/data_recipe/seed.py @@ -30,7 +30,9 @@ except ImportError: normalize_unstructured_text = None resolve_chunking = None from core.data_recipe.jsonable import to_preview_jsonable +from loggers import get_logger from utils.paths import ensure_dir, seed_uploads_root, unstructured_uploads_root +from utils.utils import log_and_http_error from utils.upload_limits import ( LOCAL_SEED_UPLOAD_MAX_BYTES, LOCAL_SEED_UPLOAD_MAX_LABEL, @@ -47,6 +49,7 @@ from models.data_recipe import ( UnstructuredFileUploadResponse, ) +logger = get_logger(__name__) router = APIRouter() DATA_EXTS = (".parquet", ".jsonl", ".json", ".csv") @@ -201,8 +204,12 @@ def _read_preview_rows_from_local_file( try: import pandas as pd except ImportError as exc: - raise HTTPException( - status_code = 500, detail = f"seed inspect dependencies unavailable: {exc}" + raise log_and_http_error( + exc, + 500, + "seed inspect dependencies unavailable", + event = "data_recipe.seed.dependencies_unavailable", + log = logger, ) from exc ext = path.suffix.lower() @@ -231,8 +238,12 @@ def _read_preview_rows_from_local_file( except HTTPException: raise except (ValueError, OSError) as exc: - raise HTTPException( - status_code = 422, detail = f"seed inspect failed: {exc}" + raise log_and_http_error( + exc, + 422, + "seed inspect failed", + event = "data_recipe.seed.local_preview_failed", + log = logger, ) from exc rows = df.to_dict(orient = "records") @@ -260,8 +271,12 @@ def _read_preview_rows_from_unstructured_file( chunk_overlap = overlap, ) except (FileNotFoundError, RuntimeError, ValueError, OSError) as exc: - raise HTTPException( - status_code = 422, detail = f"seed inspect failed: {exc}" + raise log_and_http_error( + exc, + 422, + "seed inspect failed", + event = "data_recipe.seed.unstructured_preview_failed", + log = logger, ) from exc return _serialize_preview_rows(rows) @@ -312,8 +327,12 @@ def inspect_seed_dataset(payload: SeedInspectRequest) -> SeedInspectResponse: try: from datasets import load_dataset except ImportError as exc: - raise HTTPException( - status_code = 500, detail = f"seed inspect dependencies unavailable: {exc}" + raise log_and_http_error( + exc, + 500, + "seed inspect dependencies unavailable", + event = "data_recipe.seed.dependencies_unavailable", + log = logger, ) from exc split = _normalize_optional_text(payload.split) or DEFAULT_SPLIT @@ -356,8 +375,12 @@ def inspect_seed_dataset(payload: SeedInspectRequest) -> SeedInspectResponse: preview_size = preview_size, ) except (ValueError, OSError, RuntimeError) as exc: - raise HTTPException( - status_code = 422, detail = f"seed inspect failed: {exc}" + raise log_and_http_error( + exc, + 422, + "seed inspect failed", + event = "data_recipe.seed.hf_preview_failed", + log = logger, ) from exc if not preview_rows: @@ -480,12 +503,17 @@ async def upload_unstructured_file( except Exception as e: raw_path.unlink(missing_ok = True) extracted_path.unlink(missing_ok = True) + logger.error( + "data_recipe.seed.text_extraction_failed", + error = str(e), + exc_info = True, + ) return UnstructuredFileUploadResponse( file_id = file_id, filename = original_filename, size_bytes = size_bytes, status = "error", - error = f"Text extraction failed: {type(e).__name__}: {e}", + error = "Text extraction failed.", ) try: diff --git a/studio/backend/routes/data_recipe/validate.py b/studio/backend/routes/data_recipe/validate.py index e794d68e54..f6fd9e6046 100644 --- a/studio/backend/routes/data_recipe/validate.py +++ b/studio/backend/routes/data_recipe/validate.py @@ -7,7 +7,7 @@ from __future__ import annotations from typing import Any -from fastapi import APIRouter, HTTPException +from fastapi import APIRouter from core.data_recipe.service import ( build_config_builder, @@ -16,6 +16,7 @@ from core.data_recipe.service import ( ) from loggers import get_logger from models.data_recipe import RecipePayload, ValidateError, ValidateResponse +from utils.utils import safe_error_detail, safe_curated_detail, log_and_http_error logger = get_logger(__name__) router = APIRouter() @@ -170,7 +171,12 @@ def validate(payload: RecipePayload) -> ValidateResponse: missing_module = exc.name, ) except Exception as exc: - detail = str(exc).strip() or "Validation failed." + logger.error( + "data_recipe.validate.github_config_failed", + error = str(exc), + exc_info = True, + ) + detail = safe_error_detail(exc, fallback = "Validation failed.") return ValidateResponse( valid = False, errors = [ValidateError(message = detail)], @@ -181,9 +187,20 @@ def validate(payload: RecipePayload) -> ValidateResponse: try: validate_recipe(recipe) except RuntimeError as exc: - raise HTTPException(status_code = 503, detail = str(exc)) from exc + raise log_and_http_error( + exc, + 503, + safe_error_detail(exc), + event = "data_recipe.validate.service_unavailable", + log = logger, + ) from exc except Exception as exc: - detail = str(exc).strip() or "Validation failed." + logger.error( + "data_recipe.validate.recipe_failed", + error = str(exc), + exc_info = True, + ) + detail = safe_curated_detail(exc, fallback = "Validation failed.") parsed_errors = _collect_validation_errors(recipe) return ValidateResponse( valid = False, diff --git a/studio/backend/routes/datasets.py b/studio/backend/routes/datasets.py index c34d6d8732..1ea696705c 100644 --- a/studio/backend/routes/datasets.py +++ b/studio/backend/routes/datasets.py @@ -647,9 +647,7 @@ def check_format( raise except Exception as e: logger.error(f"Error checking dataset format: {e}", exc_info = True) - raise HTTPException( - status_code = 500, detail = f"Failed to check dataset format: {str(e)}" - ) + raise HTTPException(status_code = 500, detail = "Failed to check dataset format") @router.post("/ai-assist-mapping", response_model = AiAssistMappingResponse) @@ -705,4 +703,4 @@ def ai_assist_mapping( except Exception as e: logger.error(f"AI assist mapping failed: {e}", exc_info = True) - raise HTTPException(status_code = 500, detail = f"AI assist failed: {str(e)}") + raise HTTPException(status_code = 500, detail = "AI assist failed") diff --git a/studio/backend/routes/export.py b/studio/backend/routes/export.py index 7dbc52dbed..2bfca30cee 100644 --- a/studio/backend/routes/export.py +++ b/studio/backend/routes/export.py @@ -26,6 +26,8 @@ if str(backend_path) not in sys.path: # Auth from auth.authentication import get_current_subject +from utils.utils import safe_error_detail + # Import backend functions try: from core.export import get_export_backend @@ -125,7 +127,7 @@ async def load_checkpoint( logger.error(f"Error loading checkpoint: {e}", exc_info = True) raise HTTPException( status_code = 500, - detail = f"Failed to load checkpoint: {str(e)}", + detail = "Failed to load checkpoint", ) @@ -158,7 +160,7 @@ async def cleanup_export_memory( logger.error(f"Error during export memory cleanup: {e}", exc_info = True) raise HTTPException( status_code = 500, - detail = f"Failed to cleanup export memory: {str(e)}", + detail = "Failed to cleanup export memory", ) @@ -180,7 +182,7 @@ async def get_export_status( logger.error(f"Error getting export status: {e}", exc_info = True) raise HTTPException( status_code = 500, - detail = f"Failed to get export status: {str(e)}", + detail = "Failed to get export status", ) @@ -235,7 +237,7 @@ async def export_merged_model( logger.error(f"Error exporting merged model: {e}", exc_info = True) raise HTTPException( status_code = 500, - detail = f"Failed to export merged model: {str(e)}", + detail = "Failed to export merged model", ) @@ -275,7 +277,7 @@ async def export_base_model( logger.error(f"Error exporting base model: {e}", exc_info = True) raise HTTPException( status_code = 500, - detail = f"Failed to export base model: {str(e)}", + detail = "Failed to export base model", ) @@ -314,7 +316,7 @@ async def export_gguf( logger.error(f"Error exporting GGUF model: {e}", exc_info = True) raise HTTPException( status_code = 500, - detail = f"Failed to export GGUF model: {str(e)}", + detail = "Failed to export GGUF model", ) @@ -353,7 +355,7 @@ async def export_lora_adapter( logger.error(f"Error exporting LoRA adapter: {e}", exc_info = True) raise HTTPException( status_code = 500, - detail = f"Failed to export LoRA adapter: {str(e)}", + detail = "Failed to export LoRA adapter", ) @@ -492,7 +494,7 @@ async def stream_export_logs( logger.error("Export log stream failed: %s", exc, exc_info = True) try: yield _format_sse( - json.dumps({"error": str(exc)}), + json.dumps({"error": safe_error_detail(exc)}), event = "error", ) except Exception: diff --git a/studio/backend/routes/inference.py b/studio/backend/routes/inference.py index d3a279319a..5d22b3ff90 100644 --- a/studio/backend/routes/inference.py +++ b/studio/backend/routes/inference.py @@ -227,6 +227,7 @@ from core.inference.key_exchange import decrypt_api_key from core.inference.providers import get_provider_info, get_base_url from core.inference.external_provider import ExternalProviderClient from storage import providers_db +from utils.utils import safe_error_detail, log_and_http_error import io import wave @@ -697,7 +698,13 @@ def _resolve_model_identifier_for_request( allowed_suffixes = (".gguf",), ) except NativePathLeaseError as exc: - raise HTTPException(status_code = 400, detail = str(exc)) from exc + # Curated, client-correctable lease error (expired / wrong type / re-select); + # keep the actionable message, just redact paths. + logger.warning("inference.native_path_lease_failed: %s", exc) + raise HTTPException( + status_code = 400, + detail = redact_native_paths(str(exc)), + ) from exc display_label = ( grant.display_label or Path(request.model_path).name or "Native model" ) @@ -735,7 +742,12 @@ async def load_model( try: extra_llama_args = validate_extra_args(request.llama_extra_args) except ValueError as exc: - raise HTTPException(status_code = 400, detail = str(exc)) + # Keep the curated validation message (names the flag); just strip paths. + logger.warning("inference.validate_extra_args_failed: %s", exc) + raise HTTPException( + status_code = 400, + detail = redact_native_paths(str(exc)), + ) # Re-narrow []-from-None back to None so the inheritance path # below can tell "caller omitted" from "caller explicit []". extra_llama_args: Optional[list[str]] = ( @@ -1221,7 +1233,8 @@ async def load_model( ) raise HTTPException(status_code = 400, detail = redacted_msg) logger.warning("Rejected inference GPU selection: %s", e) - raise HTTPException(status_code = 400, detail = str(e)) + # User-facing validation (e.g. "Invalid gpu_ids [99]"): redact paths, keep detail. + raise HTTPException(status_code = 400, detail = redact_native_paths(str(e))) except Exception as e: # Surface a friendlier message for models that Unsloth cannot load not_supported_hints = [ @@ -1245,7 +1258,7 @@ async def load_model( detail = f"Failed to load native model {model_log_label}: {msg}", ) logger.error(f"Error loading model: {e}", exc_info = True) - msg = str(e) + msg = redact_native_paths(str(e)) if any(h.lower() in msg.lower() for h in not_supported_hints): msg = f"This model is not supported yet. Try a different model. (Original error: {msg})" raise HTTPException(status_code = 500, detail = f"Failed to load model: {msg}") @@ -1324,7 +1337,7 @@ async def validate_model( ) raise HTTPException( status_code = 400, - detail = f"Invalid model: {str(e)}", + detail = "Invalid model", ) @@ -1359,7 +1372,7 @@ async def unload_model( except Exception as e: logger.error(f"Error unloading model: {e}", exc_info = True) - raise HTTPException(status_code = 500, detail = f"Failed to unload model: {str(e)}") + raise HTTPException(status_code = 500, detail = "Failed to unload model") @studio_router.post("/cancel") @@ -1444,8 +1457,12 @@ async def generate_stream( except HTTPException: raise except Exception as e: - raise HTTPException( - status_code = 400, detail = f"Failed to decode image: {str(e)}" + raise log_and_http_error( + e, + 400, + "Failed to decode image", + event = "inference.decode_image_failed", + log = logger, ) async def stream(): @@ -1614,7 +1631,7 @@ async def get_status( except Exception as e: logger.error(f"Error getting status: {e}", exc_info = True) - raise HTTPException(status_code = 500, detail = f"Failed to get status: {str(e)}") + raise HTTPException(status_code = 500, detail = "Failed to get status") @router.get("/load-progress", response_model = LoadProgressResponse) @@ -1715,7 +1732,7 @@ async def generate_audio( ) except Exception as e: logger.error(f"Audio generation error: {e}", exc_info = True) - raise HTTPException(status_code = 500, detail = str(e)) + raise HTTPException(status_code = 500, detail = safe_error_detail(e)) audio_b64 = base64.b64encode(wav_bytes).decode("ascii") return JSONResponse( @@ -2402,9 +2419,12 @@ async def list_openai_containers( detail = f"OpenAI rejected /containers list: {detail}", ) except httpx.HTTPError as exc: - raise HTTPException( - status_code = 502, - detail = f"Failed to reach OpenAI: {exc}", + raise log_and_http_error( + exc, + 502, + "Could not reach OpenAI.", + event = "openai_container_list.transport_error", + log = logger, ) # OpenAI keeps expired containers in /v1/containers indefinitely # with status="expired" — they're effectively dead but still @@ -2443,9 +2463,12 @@ async def create_openai_container( detail = f"OpenAI rejected /containers create: {detail}", ) except httpx.HTTPError as exc: - raise HTTPException( - status_code = 502, - detail = f"Failed to reach OpenAI: {exc}", + raise log_and_http_error( + exc, + 502, + "Could not reach OpenAI.", + event = "openai_container_create.transport_error", + log = logger, ) if not isinstance(raw, dict): raise HTTPException( @@ -2490,14 +2513,12 @@ async def delete_openai_container( detail = f"OpenAI rejected /containers delete: {detail}", ) except httpx.HTTPError as exc: - logger.warning( - "openai_container_delete.transport_error container_id=%s error=%s", - body.container_id, + raise log_and_http_error( exc, - ) - raise HTTPException( - status_code = 502, - detail = f"Failed to reach OpenAI: {exc}", + 502, + "Could not reach OpenAI.", + event = "openai_container_delete.transport_error", + log = logger, ) finally: await client.close() @@ -3262,7 +3283,7 @@ async def openai_chat_completions( except Exception as e: logger.error(f"Error during GGUF completion: {e}", exc_info = True) - raise HTTPException(status_code = 500, detail = str(e)) + raise HTTPException(status_code = 500, detail = safe_error_detail(e)) # ── Standard Unsloth path ───────────────────────────────── @@ -3290,7 +3311,13 @@ async def openai_chat_completions( except HTTPException: raise except Exception as e: - raise HTTPException(status_code = 400, detail = f"Failed to decode image: {e}") + raise log_and_http_error( + e, + 400, + "Failed to decode image", + event = "inference.decode_image_failed", + log = logger, + ) # Classify capability flags from the loaded template. _sf_model_info = backend.models.get(backend.active_model_name, {}) @@ -3817,7 +3844,7 @@ async def openai_chat_completions( except Exception as e: backend.reset_generation_state() logger.error(f"Error during OpenAI completion: {e}", exc_info = True) - raise HTTPException(status_code = 500, detail = str(e)) + raise HTTPException(status_code = 500, detail = safe_error_detail(e)) # ===================================================================== @@ -3869,6 +3896,10 @@ async def serve_sandbox_file( safe_filename = os.path.basename(filename) if not safe_filename or safe_filename in (".", ".."): raise HTTPException(status_code = 404, detail = "Not found") + # Defense-in-depth allowlist (clears CodeQL py/path-injection), still allowing + # names like "loss curve.png"; basename + extension + realpath below are the guards. + if not _re.fullmatch(r"[^/\\\x00-\x1f]{1,255}", safe_filename): + raise HTTPException(status_code = 404, detail = "Not found") # ── Extension allowlist ───────────────────────────────────── ext = os.path.splitext(safe_filename)[1].lower() diff --git a/studio/backend/routes/mcp_servers.py b/studio/backend/routes/mcp_servers.py index 200c0ed452..87cdcf9402 100644 --- a/studio/backend/routes/mcp_servers.py +++ b/studio/backend/routes/mcp_servers.py @@ -26,6 +26,7 @@ from models.mcp_servers import ( McpServerUpdate, ) from storage import mcp_servers_db +from utils.utils import safe_curated_detail, log_and_http_error logger = structlog.get_logger(__name__) @@ -51,7 +52,13 @@ def _validate_url(url: str) -> str: try: parts = parse_stdio_command(trimmed) except ValueError as exc: - raise HTTPException(status_code = 400, detail = f"Invalid command: {exc}") + raise log_and_http_error( + exc, + 400, + "Invalid command. Check quoting and try again.", + event = "mcp_servers.invalid_command", + log = logger, + ) if not parts or not parts[0].strip(): raise HTTPException(status_code = 400, detail = "command must not be empty") if "://" in parts[0]: @@ -241,8 +248,13 @@ async def refresh_mcp_server_tools( use_oauth = use_oauth, ) except Exception as exc: # noqa: BLE001 — surface transport+timeout errors to UI - logger.warning("MCP refresh failed", server_id = server_id, error = str(exc)) - return McpServerProbeResult(ok = False, error = str(exc)) + logger.error( + "mcp_servers.refresh_failed", + server_id = server_id, + error = str(exc), + exc_info = True, + ) + return McpServerProbeResult(ok = False, error = safe_curated_detail(exc)) return McpServerProbeResult(ok = True, tool_count = len(tools)) @@ -265,6 +277,11 @@ async def test_mcp_server( use_oauth = payload.use_oauth, ) except Exception as exc: # noqa: BLE001 - return McpServerProbeResult(ok = False, error = str(exc)) + logger.error( + "mcp_servers.test_failed", + error = str(exc), + exc_info = True, + ) + return McpServerProbeResult(ok = False, error = safe_curated_detail(exc)) return McpServerProbeResult(ok = True, tool_count = len(tools)) diff --git a/studio/backend/routes/models.py b/studio/backend/routes/models.py index 2b729eea9c..0e1e491998 100644 --- a/studio/backend/routes/models.py +++ b/studio/backend/routes/models.py @@ -16,6 +16,7 @@ from fastapi import APIRouter, Body, Depends, HTTPException, Query from typing import List, Optional import structlog from loggers import get_logger +from utils.utils import log_and_http_error import re as _re @@ -825,10 +826,12 @@ async def list_local_models( models = models, ) except Exception as e: - logger.error(f"Error listing local models: {e}", exc_info = True) - raise HTTPException( - status_code = 500, - detail = f"Failed to list local models: {str(e)}", + raise log_and_http_error( + e, + 500, + "Failed to list local models", + event = "models.list_local_models_failed", + log = logger, ) @@ -854,7 +857,10 @@ async def add_scan_folder_endpoint( folder = add_scan_folder(body.path) except ValueError as e: logger.warning("Scan folder rejected: %s (path=%s)", e, body.path) - raise HTTPException(status_code = 400, detail = str(e)) + # Curated, path-free validation message (e.g. "Path does not exist"): + # forward the text, not the raw exception. + rejection_message = str(e) + raise HTTPException(status_code = 400, detail = rejection_message) logger.info("Scan folder added: %s", folder.get("path")) return folder @@ -1182,12 +1188,15 @@ def _match_browse_child(current: Path, name: str) -> Optional[Path]: except PermissionError: raise HTTPException( status_code = 403, - detail = f"Permission denied reading {current}", + detail = f"Permission denied reading {current.name}", ) from None except OSError as exc: + logger.warning( + "browse-folders: could not read %s: %s", current, exc, exc_info = True + ) raise HTTPException( status_code = 500, - detail = f"Could not read {current}: {exc}", + detail = f"Could not read {os.path.basename(str(current))}", ) from exc return None @@ -1219,14 +1228,21 @@ def _resolve_browse_target(path: Optional[str], allowed_roots: list[Path]) -> Pa if child is None: raise HTTPException( status_code = 404, - detail = f"Path does not exist: {requested_path}", + detail = f"Path does not exist: {os.path.basename(requested_path)}", ) try: resolved_child = child.resolve() except OSError as exc: + logger.warning( + "browse-folders: invalid path component %r under %s: %s", + part, + current, + exc, + exc_info = True, + ) raise HTTPException( status_code = 400, - detail = f"Invalid path: {exc}", + detail = "Invalid path", ) from exc if not _is_path_inside_allowlist(resolved_child, resolved_roots): raise HTTPException( @@ -1242,7 +1258,7 @@ def _resolve_browse_target(path: Optional[str], allowed_roots: list[Path]) -> Pa if not current.is_dir(): raise HTTPException( status_code = 400, - detail = f"Not a directory: {current}", + detail = f"Not a directory: {os.path.basename(str(current))}", ) return current @@ -1325,12 +1341,15 @@ async def browse_folders( except PermissionError: raise HTTPException( status_code = 403, - detail = f"Permission denied reading {target}", + detail = f"Permission denied reading {os.path.basename(str(target))}", ) except OSError as exc: + logger.warning( + "browse-folders: could not read %s: %s", target, exc, exc_info = True + ) raise HTTPException( status_code = 500, - detail = f"Could not read {target}: {exc}", + detail = f"Could not read {os.path.basename(str(target))}", ) try: @@ -1533,8 +1552,13 @@ async def list_models( return ModelListResponse(models = all_models, default_models = default_models) except Exception as e: - logger.error(f"Error listing models: {e}", exc_info = True) - raise HTTPException(status_code = 500, detail = f"Failed to list models: {str(e)}") + raise log_and_http_error( + e, + 500, + "Failed to list models", + event = "models.list_models_failed", + log = logger, + ) def _get_max_position_embeddings(config) -> Optional[int]: @@ -1653,9 +1677,12 @@ async def get_model_config( ) except Exception as e: - logger.error(f"Error getting model config: {e}", exc_info = True) - raise HTTPException( - status_code = 500, detail = f"Failed to get model config: {str(e)}" + raise log_and_http_error( + e, + 500, + "Failed to get model config", + event = "models.get_model_config_failed", + log = logger, ) @@ -1710,9 +1737,12 @@ async def scan_loras( return LoRAScanResponse(loras = lora_list, outputs_dir = resolved_outputs_dir) except Exception as e: - logger.error(f"Error scanning LoRAs: {e}", exc_info = True) - raise HTTPException( - status_code = 500, detail = f"Failed to scan LoRA adapters: {str(e)}" + raise log_and_http_error( + e, + 500, + "Failed to scan LoRA adapters", + event = "models.scan_loras_failed", + log = logger, ) @@ -2044,7 +2074,7 @@ async def delete_finetuned_model( ) raise HTTPException( status_code = 500, - detail = f"Failed to delete fine-tuned model: {str(e)}", + detail = "Failed to delete fine-tuned model", ) @@ -2075,9 +2105,12 @@ async def get_lora_base_model( except HTTPException: raise except Exception as e: - logger.error(f"Error getting LoRA base model: {e}", exc_info = True) - raise HTTPException( - status_code = 500, detail = f"Failed to get base model: {str(e)}" + raise log_and_http_error( + e, + 500, + "Failed to get base model", + event = "models.get_lora_base_model_failed", + log = logger, ) @@ -2102,9 +2135,12 @@ async def check_vision_model( ) except Exception as e: - logger.error(f"Error checking vision model: {e}", exc_info = True) - raise HTTPException( - status_code = 500, detail = f"Failed to check vision model: {str(e)}" + raise log_and_http_error( + e, + 500, + "Failed to check vision model", + event = "models.check_vision_model_failed", + log = logger, ) @@ -2132,9 +2168,12 @@ async def check_embedding_model( ) except Exception as e: - logger.error(f"Error checking embedding model: {e}", exc_info = True) - raise HTTPException( - status_code = 500, detail = f"Failed to check embedding model: {str(e)}" + raise log_and_http_error( + e, + 500, + "Failed to check embedding model", + event = "models.check_embedding_model_failed", + log = logger, ) @@ -2247,7 +2286,7 @@ async def get_gguf_variants( logger.error(f"Error listing GGUF variants for '{repo_id}': {e}", exc_info = True) raise HTTPException( status_code = 500, - detail = f"Failed to list GGUF variants: {str(e)}", + detail = "Failed to list GGUF variants", ) @@ -2722,7 +2761,7 @@ async def delete_cached_model( logger.error(f"Error deleting cached model {repo_id}: {e}", exc_info = True) raise HTTPException( status_code = 500, - detail = f"Failed to delete cached model: {str(e)}", + detail = "Failed to delete cached model", ) @@ -2763,8 +2802,10 @@ async def list_checkpoints( models = models, ) except Exception as e: - logger.error(f"Error listing checkpoints: {e}", exc_info = True) - raise HTTPException( - status_code = 500, - detail = f"Failed to list checkpoints: {str(e)}", + raise log_and_http_error( + e, + 500, + "Failed to list checkpoints", + event = "models.list_checkpoints_failed", + log = logger, ) diff --git a/studio/backend/routes/providers.py b/studio/backend/routes/providers.py index 5d4bd46e62..4eaa007750 100644 --- a/studio/backend/routes/providers.py +++ b/studio/backend/routes/providers.py @@ -40,6 +40,7 @@ from models.providers import ( ProviderUpdate, ) from storage import providers_db +from utils.utils import safe_curated_detail, log_and_http_error logger = structlog.get_logger(__name__) @@ -254,10 +255,15 @@ async def test_provider( models_count = len(models), ) except Exception as exc: - logger.warning("Provider test failed for %s: %s", payload.provider_type, exc) + logger.error( + "providers.test_failed", + provider_type = payload.provider_type, + error = str(exc), + exc_info = True, + ) return ProviderTestResult( success = False, - message = f"Connection failed: {exc}", + message = f"Connection failed: {safe_curated_detail(exc)}", models_count = None, ) finally: @@ -375,10 +381,12 @@ async def list_provider_models( for m in models ] except Exception as exc: - logger.error("Failed to list models from %s: %s", payload.provider_type, exc) - raise HTTPException( - status_code = 502, - detail = f"Failed to list models from {payload.provider_type}: {exc}", + raise log_and_http_error( + exc, + 502, + f"Failed to list models from {payload.provider_type}.", + event = "providers.list_models_failed", + log = logger, ) finally: await client.close() diff --git a/studio/backend/routes/settings.py b/studio/backend/routes/settings.py index 275fbb678b..b6fbeeee7a 100644 --- a/studio/backend/routes/settings.py +++ b/studio/backend/routes/settings.py @@ -1,10 +1,12 @@ # SPDX-License-Identifier: AGPL-3.0-only # Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0 -from fastapi import APIRouter, Depends, HTTPException +from fastapi import APIRouter, Depends from pydantic import BaseModel, Field from auth.authentication import get_current_subject +from loggers import get_logger +from utils.utils import safe_error_detail, log_and_http_error from utils.upload_limits import ( MAX_UPLOAD_LIMIT_MB, MIN_UPLOAD_LIMIT_MB, @@ -17,6 +19,8 @@ from utils.upload_limits import ( router = APIRouter() +logger = get_logger(__name__) + class UploadLimitPayload(BaseModel): max_upload_size_mb: int = Field(..., ge = MIN_UPLOAD_LIMIT_MB, le = MAX_UPLOAD_LIMIT_MB) @@ -55,5 +59,11 @@ def update_upload_limit( try: limit_mb = set_upload_limit_mb(payload.max_upload_size_mb) except ValueError as exc: - raise HTTPException(status_code = 400, detail = str(exc)) from exc + raise log_and_http_error( + exc, + 400, + safe_error_detail(exc, fallback = "Invalid upload limit."), + event = "settings.update_upload_limit_failed", + log = logger, + ) from exc return _upload_limit_response(limit_mb) diff --git a/studio/backend/routes/training.py b/studio/backend/routes/training.py index 41a9e15562..5b4267b2ef 100644 --- a/studio/backend/routes/training.py +++ b/studio/backend/routes/training.py @@ -51,6 +51,8 @@ except ImportError: # Auth from auth.authentication import get_current_subject +from utils.utils import log_and_http_error + from models import ( TrainingStartRequest, TrainingJobResponse, @@ -171,7 +173,9 @@ async def start_training( request.resume_from_checkpoint ) except ValueError as e: - raise HTTPException(status_code = 400, detail = str(e)) + # Deliberate user-facing validation message. + validation_message = str(e) + raise HTTPException(status_code = 400, detail = validation_message) resume_run = get_resumable_run_by_output_dir(resume_output_dir) if not resume_run or not can_resume_run(resume_run): @@ -319,12 +323,16 @@ async def start_training( except ValueError as e: logger.warning("Rejected training GPU selection: %s", e) - raise HTTPException(status_code = 400, detail = str(e)) + # Deliberate user-facing GPU-selection validation message. + validation_message = str(e) + raise HTTPException(status_code = 400, detail = validation_message) except Exception as e: - logger.error(f"Error starting training: {e}", exc_info = True) - raise HTTPException( - status_code = 500, - detail = f"Failed to start training: {str(e)}", + raise log_and_http_error( + e, + 500, + "Failed to start training", + event = "training.start_failed", + log = logger, ) @@ -358,9 +366,12 @@ async def stop_training( ) except Exception as e: - logger.error(f"Error stopping training: {e}", exc_info = True) - raise HTTPException( - status_code = 500, detail = f"Failed to stop training: {str(e)}" + raise log_and_http_error( + e, + 500, + "Failed to stop training", + event = "training.stop_failed", + log = logger, ) @@ -412,10 +423,12 @@ async def reset_training( except HTTPException: raise except Exception as e: - logger.error(f"Error resetting training: {e}", exc_info = True) - raise HTTPException( - status_code = 500, - detail = f"Failed to reset training: {str(e)}", + raise log_and_http_error( + e, + 500, + "Failed to reset training", + event = "training.reset_failed", + log = logger, ) @@ -505,9 +518,12 @@ async def get_training_status( ) except Exception as e: - logger.error(f"Error getting training status: {e}", exc_info = True) - raise HTTPException( - status_code = 500, detail = f"Failed to get training status: {str(e)}" + raise log_and_http_error( + e, + 500, + "Failed to get training status", + event = "training.status_failed", + log = logger, ) @@ -545,9 +561,12 @@ async def get_training_metrics( ) except Exception as e: - logger.error(f"Error getting training metrics: {e}", exc_info = True) - raise HTTPException( - status_code = 500, detail = f"Failed to get training metrics: {str(e)}" + raise log_and_http_error( + e, + 500, + "Failed to get training metrics", + event = "training.metrics_failed", + log = logger, ) diff --git a/studio/backend/utils/utils.py b/studio/backend/utils/utils.py index 4e61a5b969..e95ef08a7d 100644 --- a/studio/backend/utils/utils.py +++ b/studio/backend/utils/utils.py @@ -17,6 +17,67 @@ import tempfile logger = get_logger(__name__) +# ── Client-safe error helpers ─────────────────────────────────── +# Never return raw exception text to clients (it can leak paths/internals); +# log the full exception server-side and return a generic message. + + +def safe_error_detail( + error: Exception, fallback: str = "An internal error occurred" +) -> str: + """Map a caught exception to a generic, client-safe message. + + Never includes raw ``str(error)`` (which can leak internal paths or stack + detail); known transient conditions get a friendlier hint. Always log the + real exception server-side (e.g. via ``log_and_http_error``) for diagnosis. + """ + text = str(error).lower() + if ( + isinstance(error, (ConnectionError, TimeoutError)) + or "connection" in text + or "timed out" in text + or "timeout" in text + ): + return "Could not reach an upstream service. Please try again." + if "out of memory" in text or "cuda error" in text: + return "Ran out of memory. Try a smaller model or shorter input." + return fallback + + +def safe_curated_detail( + error: Exception, fallback: str = "An internal error occurred" +) -> str: + """Client-safe text for curated domain/validation exceptions meant for the user. + + Keeps the message (paths stripped) instead of a generic fallback; use for known + exception types, keep ``safe_error_detail`` for generic ``Exception``. + """ + from utils.native_path_leases import redact_native_paths + + msg = redact_native_paths(str(error)).strip() + return msg or fallback + + +def log_and_http_error( + error: Exception, + status_code: int, + public_message: str, + *, + event: str = "request_failed", + log = None, +): + """Log ``error`` in full server-side and return an ``HTTPException`` whose + ``detail`` is only ``public_message`` -- never the raw exception text. + + Usage: raise log_and_http_error(e, 500, "Failed to start training") + """ + from fastapi import HTTPException + + # Works for both structlog and stdlib loggers; exc_info=error logs its traceback. + (log or logger).error(f"{event}: {error}", exc_info = error) + return HTTPException(status_code = status_code, detail = public_message) + + @contextmanager def without_hf_auth(): """ From 3ce187da021b17ef8ca001f1abf20817f28f23e0 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Mon, 8 Jun 2026 04:24:13 -0700 Subject: [PATCH 12/12] Formatting: ruff line-length 100, kwarg-spacing passes, drop blank after short local imports (#6079) Raise ruff line-length to 100 and extend the local pre-commit format pipeline (def-signature magic-comma normalization, short multi-line assert collapse, kwarg '=' spacing, blank-line-after-short-import removal, adjacent string-literal / f-string+plain merge, redundant-pass pruning). Every transform re-checks the file AST and is dropped if it would differ; the whole-repo reformat is verified AST-identical per file and idempotent. --- .pre-commit-config.yaml | 3 + pyproject.toml | 1 + scripts/check_frontend_dep_removal.py | 64 +- scripts/check_new_install_scripts.py | 11 +- scripts/enforce_kwargs_spacing.py | 499 +++++++++++- scripts/lint_workflow_triggers.py | 8 +- scripts/lockfile_supply_chain_audit.py | 9 +- scripts/notebook_to_python.py | 20 +- scripts/notebook_validator.py | 61 +- scripts/run_ruff_format.py | 16 +- scripts/scan_npm_packages.py | 49 +- scripts/scan_packages.py | 64 +- scripts/stamp_studio_release.py | 10 +- scripts/verify_comment_only_diff.py | 9 +- scripts/verify_import_hoist.py | 76 +- studio/backend/auth/authentication.py | 12 +- studio/backend/auth/storage.py | 16 +- studio/backend/colab.py | 25 +- studio/backend/core/__init__.py | 1 - studio/backend/core/_torchao_stub.py | 14 +- .../backend/core/data_recipe/huggingface.py | 4 +- .../backend/core/data_recipe/jobs/manager.py | 47 +- studio/backend/core/data_recipe/jobs/parse.py | 38 +- .../backend/core/data_recipe/jobs/worker.py | 23 +- studio/backend/core/data_recipe/jsonable.py | 2 - .../data_recipe/local_callable_validators.py | 50 +- studio/backend/core/data_recipe/service.py | 39 +- studio/backend/core/export/export.py | 53 +- studio/backend/core/export/orchestrator.py | 23 +- studio/backend/core/export/worker.py | 20 +- .../core/inference/anthropic_compat.py | 7 +- studio/backend/core/inference/audio_codecs.py | 33 +- .../core/inference/chat_template_helpers.py | 4 +- .../core/inference/external_provider.py | 722 +++++------------- studio/backend/core/inference/inference.py | 218 ++---- studio/backend/core/inference/llama_cpp.py | 492 +++--------- .../core/inference/llama_server_args.py | 32 +- studio/backend/core/inference/mcp_client.py | 17 +- .../backend/core/inference/mlx_inference.py | 19 +- studio/backend/core/inference/orchestrator.py | 60 +- studio/backend/core/inference/pricing.py | 21 +- studio/backend/core/inference/providers.py | 3 +- .../core/inference/safetensors_agentic.py | 23 +- .../core/inference/tool_call_parser.py | 10 +- studio/backend/core/inference/tools.py | 144 +--- studio/backend/core/inference/worker.py | 54 +- studio/backend/core/tool_healing.py | 10 +- studio/backend/core/training/trainer.py | 530 +++++-------- studio/backend/core/training/training.py | 82 +- studio/backend/core/training/worker.py | 210 ++--- studio/backend/main.py | 69 +- studio/backend/models/auth.py | 12 +- studio/backend/models/data_recipe.py | 4 +- studio/backend/models/inference.py | 128 +--- studio/backend/models/models.py | 52 +- studio/backend/models/providers.py | 16 +- studio/backend/models/responses.py | 12 +- studio/backend/models/training.py | 95 +-- .../data_designer_github_repo_seed/scraper.py | 36 +- .../scraper_impl/gh_client.py | 35 +- .../scraper_impl/scraper.py | 87 +-- .../scraper_impl/state_store.py | 6 +- .../chunking.py | 47 +- studio/backend/routes/auth.py | 28 +- studio/backend/routes/chat_history.py | 52 +- studio/backend/routes/data_recipe/jobs.py | 37 +- studio/backend/routes/data_recipe/mcp.py | 4 +- studio/backend/routes/data_recipe/seed.py | 51 +- studio/backend/routes/data_recipe/validate.py | 19 +- studio/backend/routes/datasets.py | 47 +- studio/backend/routes/export.py | 36 +- studio/backend/routes/inference.py | 379 +++------ studio/backend/routes/mcp_servers.py | 37 +- studio/backend/routes/models.py | 141 +--- studio/backend/routes/providers.py | 41 +- studio/backend/routes/settings.py | 7 +- studio/backend/routes/training.py | 152 +--- studio/backend/routes/training_history.py | 19 +- studio/backend/run.py | 48 +- studio/backend/state/tool_policy.py | 4 +- studio/backend/storage/mcp_servers_db.py | 8 +- studio/backend/storage/providers_db.py | 11 +- studio/backend/storage/studio_db.py | 72 +- .../tests/test_amd_apu_unified_memory.py | 7 +- .../tests/test_anthropic_citations_edge.py | 8 +- .../tests/test_anthropic_code_execution.py | 18 +- .../tests/test_anthropic_compaction.py | 45 +- .../test_anthropic_fast_mode_and_refusal.py | 6 +- .../tests/test_anthropic_fast_mode_edge.py | 19 +- .../backend/tests/test_anthropic_messages.py | 61 +- .../tests/test_anthropic_tool_versions.py | 5 +- .../backend/tests/test_anthropic_web_fetch.py | 19 +- .../tests/test_audio_token_detection.py | 4 +- .../backend/tests/test_cached_gguf_routes.py | 31 +- .../backend/tests/test_chat_history_routes.py | 8 +- .../tests/test_chat_history_storage.py | 40 +- .../test_cleanup_cancelled_checkpoints.py | 1 - studio/backend/tests/test_cpu_threads.py | 4 +- .../tests/test_dataset_upload_limits.py | 8 +- studio/backend/tests/test_desktop_auth.py | 44 +- .../backend/tests/test_detect_mmproj_file.py | 9 +- .../backend/tests/test_export_log_cursor.py | 7 +- .../test_external_provider_usage_chunk.py | 14 +- .../backend/tests/test_frontend_resolution.py | 8 +- studio/backend/tests/test_gemini_provider.py | 349 +++------ .../tests/test_gguf_completion_usage.py | 8 +- studio/backend/tests/test_gguf_metadata.py | 20 +- studio/backend/tests/test_gpu_selection.py | 83 +- .../tests/test_gpu_selection_sandbox.py | 22 +- studio/backend/tests/test_host_defaults.py | 13 +- .../tests/test_index_bootstrap_origin.py | 24 +- .../test_index_bootstrap_origin_extra.py | 15 +- .../tests/test_inference_model_validation.py | 5 +- .../backend/tests/test_kv_cache_estimation.py | 121 +-- .../test_lemonade_llamacpp_rocm_bins_mock.py | 24 +- .../tests/test_llama_cpp_context_fit.py | 10 +- .../backend/tests/test_llama_cpp_freshness.py | 44 +- .../tests/test_llama_cpp_load_progress.py | 4 - .../test_llama_cpp_load_progress_live.py | 6 +- .../test_llama_cpp_max_context_threshold.py | 7 +- .../tests/test_llama_cpp_mtp_detection.py | 41 +- ..._llama_cpp_start_failure_classification.py | 7 +- .../test_llama_cpp_wait_for_vram_settle.py | 8 +- .../test_llama_cpp_windows_nvidia_path.py | 8 +- .../backend/tests/test_llama_server_args.py | 29 +- studio/backend/tests/test_login_rate_limit.py | 36 +- studio/backend/tests/test_mcp_servers.py | 39 +- .../tests/test_mcp_stdio_improvements.py | 26 +- studio/backend/tests/test_mcp_stdio_pr5863.py | 37 +- studio/backend/tests/test_middleware.py | 13 +- .../tests/test_mlx_inference_backend.py | 11 +- .../tests/test_mlx_training_worker_config.py | 8 +- ...models_get_model_config_case_resolution.py | 4 +- .../backend/tests/test_multimodal_document.py | 19 +- .../tests/test_native_context_length.py | 16 +- .../tests/test_offline_gguf_cache_fallback.py | 79 +- .../tests/test_offline_inference_parent.py | 21 +- .../test_openai_citation_markers_edge.py | 4 +- .../tests/test_openai_code_execution.py | 15 +- .../tests/test_openai_container_crud.py | 9 +- .../test_openai_responses_translation.py | 11 +- .../tests/test_openai_tool_passthrough.py | 68 +- studio/backend/tests/test_pricing.py | 22 +- studio/backend/tests/test_pricing_edge.py | 14 +- studio/backend/tests/test_providers_api.py | 52 +- studio/backend/tests/test_responses_api.py | 5 +- .../tests/test_responses_tool_passthrough.py | 16 +- studio/backend/tests/test_rocm_oom_guard.py | 4 +- .../test_safetensors_capability_advertise.py | 6 +- .../tests/test_safetensors_tool_loop.py | 155 ++-- studio/backend/tests/test_sandbox_tools.py | 12 +- studio/backend/tests/test_studio_api.py | 51 +- studio/backend/tests/test_tool_xml_strip.py | 4 +- .../backend/tests/test_trained_model_scan.py | 20 +- .../tests/test_training_raw_support.py | 5 +- .../tests/test_training_worker_flash_attn.py | 239 ++---- .../tests/test_transformers_version.py | 4 +- studio/backend/tests/test_utils.py | 15 +- studio/backend/tests/test_vision_cache.py | 4 +- studio/backend/tests/test_vram_estimation.py | 87 +-- .../tests/test_windows_gpu_detection_mock.py | 44 +- studio/backend/utils/cache_cleanup.py | 3 +- .../backend/utils/datasets/data_collators.py | 16 +- .../utils/datasets/dataset_none_detect.py | 83 +- .../backend/utils/datasets/dataset_utils.py | 68 +- .../utils/datasets/format_conversion.py | 71 +- .../utils/datasets/format_detection.py | 43 +- studio/backend/utils/datasets/llm_assist.py | 50 +- studio/backend/utils/datasets/raw_text.py | 8 +- .../backend/utils/datasets/vlm_processing.py | 5 +- studio/backend/utils/downsample.py | 4 +- studio/backend/utils/hardware/amd.py | 30 +- studio/backend/utils/hardware/hardware.py | 114 +-- studio/backend/utils/hardware/nvidia.py | 32 +- .../backend/utils/hardware/vram_estimation.py | 151 +--- .../utils/inference/inference_config.py | 5 +- studio/backend/utils/llama_cpp_freshness.py | 5 +- studio/backend/utils/models/checkpoints.py | 8 +- studio/backend/utils/models/gguf_metadata.py | 3 +- studio/backend/utils/models/model_config.py | 119 +-- studio/backend/utils/native_path_leases.py | 38 +- studio/backend/utils/paths/path_utils.py | 1 - studio/backend/utils/paths/storage_roots.py | 15 +- studio/backend/utils/studio_version.py | 4 +- studio/backend/utils/transformers_version.py | 27 +- studio/backend/utils/update_status.py | 25 +- studio/backend/utils/upload_limits.py | 1 - studio/backend/utils/utils.py | 8 +- studio/backend/utils/wheel_utils.py | 4 +- studio/install_llama_prebuilt.py | 633 ++++----------- studio/install_python_stack.py | 61 +- tests/_zoo_aggressive_cuda_spoof.py | 6 +- tests/conftest.py | 2 - tests/python/conftest.py | 8 +- tests/python/test_cross_platform_parity.py | 10 +- .../test_dpo_vision_processor_passthrough.py | 13 +- tests/python/test_e2e_no_torch_sandbox.py | 61 +- ...sentence_transformer_redirect_lifecycle.py | 18 +- .../test_flash_attn_install_python_stack.py | 108 ++- tests/python/test_gpu_init_ldconfig_guard.py | 4 +- tests/python/test_no_torch_filtering.py | 85 +-- .../test_orpo_processor_text_tokenizer.py | 13 +- tests/python/test_studio_import_no_torch.py | 35 +- .../test_tokenizers_and_torch_constraint.py | 40 +- .../test_unsloth_run_tool_policy_resolver.py | 8 +- tests/qlora/test_hf_qlora_train_and_merge.py | 4 +- .../saving/gpt-oss-merge/test_merged_model.py | 8 +- tests/saving/gpt-oss-merge/train_and_merge.py | 12 +- .../test_merge_4bit_validation.py | 8 +- .../test_merge_model_perplexity_llama-3.2.py | 26 +- .../test_merge_model_perplexity_mistral.py | 28 +- .../test_merge_model_perplexity_phi_4.py | 26 +- ...st_merged_model_perplexity_llama-3.1-8b.py | 26 +- .../test_merged_model_perplexity_qwen_2.5.py | 18 +- .../test_push_to_hub_merged.py | 8 +- ...t_push_to_hub_merged_sharded_index_file.py | 8 +- .../test_save_merged_grpo_model.py | 41 +- .../test_fix_sentencepiece_gguf_robustness.py | 9 +- .../test_preserve_tokenizer_eos_token.py | 7 +- tests/saving/test_save_shell_injection.py | 9 +- tests/saving/test_unsloth_save.py | 64 +- .../saving/text_to_speech_models/test_csm.py | 4 +- .../saving/text_to_speech_models/test_lasa.py | 4 +- .../text_to_speech_models/test_orpheus.py | 8 +- .../text_to_speech_models/test_whisper.py | 8 +- .../test_index_file_sharded_model.py | 4 +- .../vision_models/test_push_to_hub_merged.py | 4 +- ..._merge_qwen2.5vl32B_model_ocr_benchmark.py | 4 +- ...t_save_merge_vision_model_ocr_benchmark.py | 4 +- .../test_lockfile_supply_chain_audit.py | 5 +- tests/security/test_new_install_scripts.py | 20 +- tests/security/test_scan_npm_packages.py | 10 +- tests/security/test_scan_packages.py | 7 +- tests/studio/_playwright_robust.py | 8 +- .../install/smoke_test_llama_prebuilt.py | 12 +- .../smoke_test_parallel_studio_home.py | 41 +- .../test_install_llama_prebuilt_logic.py | 178 ++--- .../install/test_llama_pr_force_and_source.py | 40 +- .../install/test_macos_version_compat.py | 28 +- tests/studio/install/test_pr4562_bugfixes.py | 114 +-- tests/studio/install/test_rocm_support.py | 164 +--- tests/studio/install/test_selection_logic.py | 257 ++----- tests/studio/load_freeze/llama_server_shim.py | 14 +- .../load_freeze/test_load_orchestrator.py | 28 +- tests/studio/playwright_chat_ime_i18n.py | 18 +- tests/studio/playwright_chat_ui.py | 70 +- tests/studio/playwright_extra_ui.py | 36 +- tests/studio/run_real_mlx_smoke.py | 36 +- tests/studio/studio_api_smoke.py | 4 +- tests/studio/test_auth_form_input_count.py | 5 +- tests/studio/test_cancel_atomicity.py | 16 +- tests/studio/test_cancel_id_wiring.py | 19 +- .../test_chat_preset_builtin_invariants.py | 7 +- tests/studio/test_cli_repo_variant.py | 8 +- tests/studio/test_cli_run_alias.py | 8 +- tests/studio/test_cli_studio_defaults.py | 8 +- .../test_composer_rtl_bidi_attribute.py | 27 +- .../test_export_output_path_contract.py | 8 +- tests/studio/test_frontend_dep_removal.py | 63 +- tests/studio/test_hardware_dispatch_matrix.py | 29 +- tests/studio/test_is_mlx_dispatch_gate.py | 10 +- .../test_stream_cancel_registration_timing.py | 22 +- .../test_studio_gguf_export_script_pin.py | 28 +- .../test_studio_text_descender_clipping.py | 20 +- tests/test_callback_signature_drift.py | 6 +- tests/test_enforce_kwargs_spacing.py | 428 +++++++++++ tests/test_finetune_last_n_layers.py | 2 - tests/test_gemma4_chat_template.py | 4 +- tests/test_get_model_name.py | 8 +- tests/test_import_fixes_drift.py | 23 +- tests/test_loader_glob_skip.py | 16 +- tests/test_model_registry.py | 7 +- tests/test_multi_image_grpo_chunking.py | 16 +- tests/test_peft_weight_converter_compat.py | 26 +- tests/test_raw_text.py | 39 +- tests/test_resolve_model_class.py | 7 +- tests/test_studio_install_workspace_guard.py | 80 +- tests/test_studio_root_resilience.py | 20 +- tests/test_tool_mask_zoo_compat.py | 19 +- tests/utils/aime_eval.py | 36 +- tests/utils/cleanup_utils.py | 14 +- tests/utils/data_utils.py | 20 +- tests/utils/generate_dataset_with_none.py | 8 +- tests/utils/hf_utils.py | 30 +- tests/utils/ocr_eval.py | 45 +- tests/utils/os_utils.py | 18 +- tests/utils/perplexity_eval.py | 12 +- tests/utils/run_none_detect_tests.py | 54 +- tests/utils/test_attention_masks.py | 41 +- tests/utils/test_packing.py | 45 +- tests/utils/test_q_galore.py | 24 +- tests/utils/test_qat.py | 5 +- tests/utils/test_trunc_normal_patch.py | 4 +- tests/version_compat/_fetch.py | 6 +- .../test_bitsandbytes_pinned_symbols.py | 45 +- .../test_peft_pinned_symbols.py | 16 +- ...st_sentence_transformers_pinned_symbols.py | 16 +- .../test_transformers_pinned_symbols.py | 32 +- .../test_trl_grpo_pinned_symbols.py | 20 +- ..._unsloth_zoo_save_merged_pinned_symbols.py | 12 +- .../test_extended_module_imports.py | 18 +- tests/vllm_compat/test_vllm_pinned_symbols.py | 33 +- unsloth-cli.py | 22 +- unsloth/__init__.py | 6 +- unsloth/_gpu_init.py | 8 +- unsloth/dataprep/raw_text.py | 94 ++- unsloth/dataprep/synthetic.py | 17 +- unsloth/device_type.py | 14 +- unsloth/import_fixes.py | 170 ++--- unsloth/kernels/__init__.py | 4 +- unsloth/kernels/cross_entropy_loss.py | 15 +- unsloth/kernels/fast_lora.py | 31 +- unsloth/kernels/flex_attention.py | 9 +- unsloth/kernels/fp8.py | 77 +- unsloth/kernels/geglu.py | 48 +- unsloth/kernels/layernorm.py | 12 +- unsloth/kernels/moe/autotune_cache.py | 16 +- .../moe/benchmark/benchmark_fused_moe.py | 42 +- unsloth/kernels/moe/benchmark/utils.py | 31 +- unsloth/kernels/moe/grouped_gemm/interface.py | 85 +-- .../moe/grouped_gemm/kernels/autotuning.py | 14 +- .../moe/grouped_gemm/kernels/backward.py | 32 +- .../moe/grouped_gemm/kernels/forward.py | 21 +- .../moe/grouped_gemm/kernels/tuning.py | 18 +- .../reference/layers/llama4_moe.py | 46 +- .../reference/layers/qwen3_moe.py | 33 +- .../moe/grouped_gemm/reference/moe_block.py | 15 +- .../moe/grouped_gemm/reference/moe_ops.py | 23 +- unsloth/kernels/moe/tests/common.py | 78 +- unsloth/kernels/moe/tests/moe_utils.py | 92 +-- .../kernels/moe/tests/test_grouped_gemm.py | 117 +-- unsloth/kernels/moe/tests/test_llama4_moe.py | 47 +- unsloth/kernels/moe/tests/test_qwen3_moe.py | 55 +- unsloth/kernels/rms_layernorm.py | 25 +- unsloth/kernels/rope_embedding.py | 44 +- unsloth/kernels/swiglu.py | 26 +- unsloth/kernels/utils.py | 94 ++- unsloth/models/_utils.py | 326 +++----- unsloth/models/cohere.py | 74 +- unsloth/models/falcon_h1.py | 77 +- unsloth/models/gemma.py | 73 +- unsloth/models/gemma2.py | 76 +- unsloth/models/glm4_moe.py | 30 +- unsloth/models/granite.py | 83 +- unsloth/models/llama.py | 407 ++++------ unsloth/models/loader.py | 100 +-- unsloth/models/loader_utils.py | 33 +- unsloth/models/mistral.py | 50 +- unsloth/models/qwen2.py | 8 +- unsloth/models/qwen3.py | 48 +- unsloth/models/qwen3_moe.py | 35 +- unsloth/models/rl.py | 180 ++--- unsloth/models/rl_replacements.py | 259 +++---- unsloth/models/sentence_transformer.py | 272 ++----- unsloth/models/vision.py | 130 +--- unsloth/optimizers/q_galore_adamw.py | 16 +- unsloth/optimizers/q_galore_projector.py | 17 +- unsloth/registry/__init__.py | 20 +- unsloth/registry/_deepseek.py | 28 +- unsloth/registry/_gemma.py | 4 +- unsloth/registry/_llama.py | 16 +- unsloth/registry/_mistral.py | 16 +- unsloth/registry/_phi.py | 4 +- unsloth/registry/_qwen.py | 16 +- unsloth/registry/registry.py | 24 +- unsloth/save.py | 285 ++----- unsloth/tokenizer_utils.py | 129 +--- unsloth/trainer.py | 55 +- unsloth/utils/attention_dispatch.py | 55 +- unsloth/utils/packing.py | 40 +- unsloth_cli/commands/export.py | 4 +- unsloth_cli/commands/studio.py | 76 +- unsloth_cli/commands/train.py | 12 +- unsloth_cli/config.py | 5 +- unsloth_cli/options.py | 4 +- .../tests/test_studio_run_parallel_flag.py | 40 +- .../test_studio_run_short_alias_clashes.py | 46 +- 377 files changed, 5945 insertions(+), 11859 deletions(-) create mode 100644 tests/test_enforce_kwargs_spacing.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8cfa7f998b..e018803a5f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,5 +14,8 @@ repos: entry: scripts/run_ruff_format.py language: python types: [python] + # Mirror ruff's [tool.ruff] extend-exclude so this hook does not + # half-process files ruff itself skips (which produced churn). + exclude: '(chat_templates|ollama_template_mappers|_auto_install|mapper)\.py$' additional_dependencies: - ruff==0.6.9 diff --git a/pyproject.toml b/pyproject.toml index 24fd66dbbb..713146ff32 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1308,6 +1308,7 @@ repository = "https://github.com/unslothai/unsloth" [tool.ruff] target-version = "py311" +line-length = 100 force-exclude = true extend-exclude = [ "*chat_templates.py", diff --git a/scripts/check_frontend_dep_removal.py b/scripts/check_frontend_dep_removal.py index 260ad5215a..3ec4e9037f 100644 --- a/scripts/check_frontend_dep_removal.py +++ b/scripts/check_frontend_dep_removal.py @@ -52,9 +52,7 @@ EXPECTED_NOISE_FILES = { } # Only quoted-string occurrences in these file types can be module specifiers. -JS_LIKE_EXT = re.compile( - r"\.(ts|tsx|js|jsx|mjs|cjs|html|htm|css|scss|sass|json|jsonc)$" -) +JS_LIKE_EXT = re.compile(r"\.(ts|tsx|js|jsx|mjs|cjs|html|htm|css|scss|sass|json|jsonc)$") # Files where JS-syntactic import patterns (static/dynamic/require/re-export) # could be a real module reference. Markdown gets a separate gate (.mdx is # real ESM; .md code fences are not). @@ -273,9 +271,7 @@ def classify(pkg: str, file: str, content: str) -> str | None: if is_script and re.search(rf"\bimport\(\s*['\"]{esc}{sub}['\"]\s*\)", content): return "dynamic_import" # require / require.resolve - if is_script and re.search( - rf"\brequire(?:\.resolve)?\(\s*['\"]{esc}{sub}['\"]\s*\)", content - ): + if is_script and re.search(rf"\brequire(?:\.resolve)?\(\s*['\"]{esc}{sub}['\"]\s*\)", content): return "require" # Re-exports: `export * from "pkg"`, `export { x } from "pkg"`, # `export type { Foo } from "pkg"`. Multi-line supported. @@ -289,16 +285,12 @@ def classify(pkg: str, file: str, content: str) -> str | None: # segment bounded by a quote / `#` / `?` or a subpath `/`, so # `/node_modules/foo-extra/...` is NOT treated as usage of `foo`. html_pkg = rf"{esc}(?:/[^'\"#?]*)?(?=['\"#?])" - if is_html and re.search( - rf"]*src\s*=\s*['\"][^'\"]*/{html_pkg}", content - ): + if is_html and re.search(rf"]*src\s*=\s*['\"][^'\"]*/{html_pkg}", content): return "html_script" if is_html and re.search(rf"]*href\s*=\s*['\"][^'\"]*/{html_pkg}", content): return "html_link" # TypeScript triple-slash - if is_ts and re.search( - rf"///\s* str | None: if first in {"npx", "pnpx", "bunx"} and idx + 1 < len(words): idx += 1 continue - if ( - first in {"pnpm", "yarn"} - and idx + 2 < len(words) - and words[idx + 1] in {"exec", "dlx"} - ): + if first in {"pnpm", "yarn"} and idx + 2 < len(words) and words[idx + 1] in {"exec", "dlx"}: idx += 2 continue # 3. Wrapper bin (cross-env, dotenv, etc.). Skip the wrapper's # own flags and any subsequent env-prefix tokens, then re-loop. - bin_token = first.removeprefix("./node_modules/.bin/").removeprefix( - "node_modules/.bin/" - ) + bin_token = first.removeprefix("./node_modules/.bin/").removeprefix("node_modules/.bin/") if bin_token in _SCRIPT_WRAPPERS and bin_token not in seen_wrappers: seen_wrappers.add(bin_token) idx += 1 @@ -585,9 +571,7 @@ def _next_real_bin(words: list[str], idx: int) -> str | None: return None -def scripts_bin_refs( - head_pkg: dict, bin_to_pkg: dict[str, str] -) -> dict[str, list[str]]: +def scripts_bin_refs(head_pkg: dict, bin_to_pkg: dict[str, str]) -> dict[str, list[str]]: """Return `{package_name: ['scripts.X: cmd', ...]}` listing every package referenced via its bin name in package.json scripts. @@ -652,11 +636,7 @@ def tsconfig_compiler_types_refs() -> set[str]: if not isinstance(t, str): continue # `vite/client` resolves to `vite` package. - pkg = ( - t.split("/", 1)[0] - if not t.startswith("@") - else "/".join(t.split("/", 2)[:2]) - ) + pkg = t.split("/", 1)[0] if not t.startswith("@") else "/".join(t.split("/", 2)[:2]) out.add(pkg) return out @@ -820,9 +800,7 @@ _file_lines_cache: dict[str, list[str]] = {} def _read_file(path: str) -> list[str]: if path not in _file_lines_cache: try: - _file_lines_cache[path] = ( - Path(path).read_text(errors = "replace").splitlines() - ) + _file_lines_cache[path] = Path(path).read_text(errors = "replace").splitlines() except (OSError, UnicodeDecodeError): _file_lines_cache[path] = [] return _file_lines_cache[path] @@ -952,18 +930,14 @@ def find_types_runtime_usage(pkg: str, tsc_types: set[str]) -> list[Hit]: def main() -> int: - p = argparse.ArgumentParser( - description = __doc__, formatter_class = argparse.RawTextHelpFormatter - ) + p = argparse.ArgumentParser(description = __doc__, formatter_class = argparse.RawTextHelpFormatter) p.add_argument( "--base", default = "origin/main", help = "git ref to diff against (default: origin/main). " "Examples: HEAD~1, main, a-tag, a-sha.", ) - p.add_argument( - "--base-pkg", help = "optional override: read base package.json from this path" - ) + p.add_argument("--base-pkg", help = "optional override: read base package.json from this path") p.add_argument( "--base-lock", help = "optional override: read base package-lock.json from this path. " @@ -1057,9 +1031,7 @@ def main() -> int: print(f" - {w}") print() if missing_imports: - print( - f"Imports without a matching package.json dep ({len(missing_imports)}):" - ) + print(f"Imports without a matching package.json dep ({len(missing_imports)}):") for file, ln, spec in missing_imports[:20]: print(f" - {file}:{ln} imports '{spec}'") print() @@ -1097,9 +1069,7 @@ def main() -> int: return 1 return 0 - print( - f"Checking {len(removed)} removed package(s) from studio/frontend/package.json" - ) + print(f"Checking {len(removed)} removed package(s) from studio/frontend/package.json") print(f"Base: {args.base} Head: working tree") print() @@ -1127,9 +1097,7 @@ def main() -> int: top = f"node_modules/{name}" top_path = top if top in reachable_paths else None nested = sorted( - p - for p in reachable_paths - if p != top and p.endswith(f"/node_modules/{name}") + p for p in reachable_paths if p != top and p.endswith(f"/node_modules/{name}") ) return top_path, nested @@ -1177,9 +1145,7 @@ def main() -> int: _print_hygiene() if failures: - print( - f"FAIL: {len(failures)} removed package(s) still referenced and not resolvable" - ) + print(f"FAIL: {len(failures)} removed package(s) still referenced and not resolvable") for name, _ in failures: print(f" - {name}") return 1 diff --git a/scripts/check_new_install_scripts.py b/scripts/check_new_install_scripts.py index af3c84f96d..2beaada0bf 100644 --- a/scripts/check_new_install_scripts.py +++ b/scripts/check_new_install_scripts.py @@ -53,9 +53,7 @@ HIGH = "HIGH" class Finding: __slots__ = ("severity", "name", "version", "kind", "detail") - def __init__( - self, severity: str, name: str, version: str, kind: str, detail: str - ) -> None: + def __init__(self, severity: str, name: str, version: str, kind: str, detail: str) -> None: self.severity = severity self.name = name self.version = version @@ -206,9 +204,7 @@ def diff_new_install_scripts(base_lock: dict, head_lock: dict) -> list[Finding]: continue # pre-existing install-script dep; not in scope name = head[key] # key is "name@version"; rsplit("@", 1) handles scoped names. - version = ( - key[len(name) + 1 :] if key.startswith(name + "@") else "" - ) + version = key[len(name) + 1 :] if key.startswith(name + "@") else "" scripts = _fetch_registry_scripts(name, version) if scripts: detail = "; ".join(f"{h}={cmd!r}" for h, cmd in scripts.items()) @@ -238,8 +234,7 @@ def diff_new_install_scripts(base_lock: dict, head_lock: dict) -> list[Finding]: def main(argv: list[str] | None = None) -> int: parser = argparse.ArgumentParser( description = ( - "Diff two package-lock.json files and refuse any newly-" - "added install-script dep." + "Diff two package-lock.json files and refuse any newly-added install-script dep." ), ) parser.add_argument( diff --git a/scripts/enforce_kwargs_spacing.py b/scripts/enforce_kwargs_spacing.py index 6b36231610..fdef950d7f 100755 --- a/scripts/enforce_kwargs_spacing.py +++ b/scripts/enforce_kwargs_spacing.py @@ -1,5 +1,10 @@ #!/usr/bin/env python3 -"""Ensure keyword arguments use spaces around '=', prune redundant pass statements.""" +"""Ensure keyword arguments use spaces around '=', prune redundant pass statements, +drop the blank line after a short indented import block, merge adjacent same-line +string literals, normalize def-signature magic commas (pre-ruff) so a def with +>= 3 params and a default goes one-per-line while everything else stays +collapsible, and collapse a short multi-line assert onto one line (pre-ruff) by +stripping the magic trailing comma that holds it open.""" from __future__ import annotations @@ -123,9 +128,7 @@ def remove_redundant_passes(text: str) -> tuple[str, bool]: lines = text.splitlines(keepends=True) changed = False - for node in sorted( - redundant, key=lambda item: (item.lineno, item.col_offset), reverse=True - ): + for node in sorted(redundant, key=lambda item: (item.lineno, item.col_offset), reverse=True): start = node.lineno - 1 end = (node.end_lineno or node.lineno) - 1 if start >= len(lines): @@ -160,7 +163,470 @@ def remove_redundant_passes(text: str) -> tuple[str, bool]: return "".join(result_lines), changed -def process_file(path: Path) -> bool: +def remove_blank_after_short_import(text: str) -> tuple[str, bool]: + """Drop blank line(s) after an import block in a *small* nested suite. + + Inside an indented suite of <= 3 statements (function/try/if/with/etc., never + module level), when a run of consecutive ``import`` / ``from ... import`` + statements is directly followed -- across one or more blank lines and nothing + else -- by another statement in the same suite, remove those blank lines so + the import sits next to the code that uses it. A comment in the gap blocks the + rule. Removing blank lines never changes the AST, so this is always + semantics-preserving. + """ + try: + tree = ast.parse(text) + except SyntaxError: + return text, False + + lines = text.splitlines(keepends=True) + import_types = (ast.Import, ast.ImportFrom) + drop: set[int] = set() # 1-based physical line numbers to delete + + def suites_of(node: ast.AST) -> list[list[ast.stmt]]: + if isinstance(node, ast.Module): + return [] # module-level import spacing is left alone + out: list[list[ast.stmt]] = [] + for attr in ("body", "orelse", "finalbody"): + val = getattr(node, attr, None) + if isinstance(val, list) and val and all(isinstance(s, ast.stmt) for s in val): + out.append(val) + return out + + for node in ast.walk(tree): + for suite in suites_of(node): + if len(suite) > 3: # only small blocks + continue + i = 0 + while i < len(suite): + if not isinstance(suite[i], import_types): + i += 1 + continue + j = i + while j + 1 < len(suite) and isinstance(suite[j + 1], import_types): + j += 1 + if j + 1 < len(suite): # an import block followed by another statement + last_imp, nxt = suite[j], suite[j + 1] + gap = range((last_imp.end_lineno or last_imp.lineno) + 1, nxt.lineno) + nums = [n for n in gap if 1 <= n <= len(lines)] + if nums and all(lines[n - 1].strip() == "" for n in nums): + drop.update(nums) + i = j + 1 + + if not drop: + return text, False + kept = [ln for idx, ln in enumerate(lines, start=1) if idx not in drop] + return "".join(kept), True + + +_STRING_TRIVIA = (tokenize.NL, tokenize.NEWLINE, tokenize.COMMENT, tokenize.INDENT, tokenize.DEDENT) + + +_DEF_MIN_PARAMS_FOR_MULTILINE = 3 # signatures with < this many params stay one line + + +def _def_specs_by_line(tree: ast.AST) -> dict[int, tuple[int, bool]]: + """Map the line of each def keyword to (param count, has-any-default). + + One def per line, so the line is a stable key. ``*`` / ``/`` markers are not + parameters and are not counted. A default exists if any positional default + is present or any keyword-only default is not ``None`` (a ``None`` entry in + ``kw_defaults`` means a required keyword-only arg). + """ + out: dict[int, tuple[int, bool]] = {} + for node in ast.walk(tree): + if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): + a = node.args + count = ( + len(a.posonlyargs) + + len(a.args) + + len(a.kwonlyargs) + + (1 if a.vararg else 0) + + (1 if a.kwarg else 0) + ) + has_default = bool(a.defaults) or any(d is not None for d in a.kw_defaults) + out[node.lineno] = (count, has_default) + return out + + +def normalize_def_trailing_comma(text: str) -> tuple[str, bool]: + """Force a def / async-def signature one-per-line iff it has >= 3 parameters + AND at least one default value; otherwise keep it collapsible. + + Rationale: signatures with defaults read better one parameter per line, but + only once they are non-trivial (< 3 params always stay on one line). A + signature with >= 3 params and a default gets a magic trailing comma added + (ruff then wraps it one-per-line regardless of length); every other + signature has its trailing comma stripped so ruff collapses it onto one line + when it fits (and wraps a genuinely long one by length alone). + + Function-definition parameter lists only, never call sites or collection + literals. Parameter counts and defaults come from the AST. Run BEFORE ruff + format. Adding or removing a def trailing comma never changes the AST, which + is re-checked before returning. + """ + try: + tree = ast.parse(text) + toks = list(tokenize.generate_tokens(io.StringIO(text).readline)) + except (tokenize.TokenError, IndentationError, SyntaxError): + return text, False + + specs = _def_specs_by_line(tree) + n = len(toks) + edits: list[tuple[int, int, str]] = [] # (row, col, "del" | "ins") + i = 0 + while i < n: + t = toks[i] + if t.type == tokenize.NAME and t.string == "def" and t.start[0] in specs: + cnt, has_default = specs[t.start[0]] + force_multiline = cnt >= _DEF_MIN_PARAMS_FOR_MULTILINE and has_default + j = i + 1 + while j < n and not (toks[j].type == tokenize.OP and toks[j].string == "("): + if toks[j].type == tokenize.NEWLINE: + break + j += 1 + if j < n and toks[j].type == tokenize.OP and toks[j].string == "(": + depth = 0 + k = j + while k < n: + tk = toks[k] + if tk.type == tokenize.OP and tk.string == "(": + depth += 1 + elif tk.type == tokenize.OP and tk.string == ")": + depth -= 1 + if depth == 0: + m = k - 1 + while m > j and toks[m].type in _STRING_TRIVIA: + m -= 1 + last = toks[m] + has_comma = last.type == tokenize.OP and last.string == "," + empty = m == j # nothing between ( and ) + if force_multiline and not has_comma and not empty: + edits.append((last.end[0], last.end[1], "ins")) + elif not force_multiline and has_comma: + edits.append((last.start[0], last.start[1], "del")) + break + k += 1 + i = k + 1 + continue + i += 1 + + if not edits: + return text, False + + lines = text.splitlines(keepends=True) + for row, col, kind in sorted(edits, reverse=True): + ln = lines[row - 1] + if kind == "del": + if col < len(ln) and ln[col] == ",": + lines[row - 1] = ln[:col] + ln[col + 1 :] + else: # ins + lines[row - 1] = ln[:col] + "," + ln[col:] + out = "".join(lines) + try: + if ast.dump(ast.parse(out)) != ast.dump(ast.parse(text)): + return text, False + except SyntaxError: + return text, False + return out, True + + +def _split_string_token(s: str) -> tuple[str, str, str] | None: + """Split a string literal's source into (prefix, quote, body). + + ``prefix`` is the letters before the opening quote (``r``/``f``/``b``/``u`` + in any case/order), ``quote`` is the opening delimiter (``'``, ``"``, + ``'''`` or ``\"\"\"``) and ``body`` is everything between the delimiters. + Returns ``None`` if ``s`` is not a recognizable string literal. + """ + i = 0 + while i < len(s) and s[i] not in ("'", '"'): + i += 1 + if i >= len(s): + return None + prefix, rest = s[:i], s[i:] + for q in ('"""', "'''", '"', "'"): + if rest.startswith(q) and rest.endswith(q) and len(rest) >= 2 * len(q): + return prefix, q, rest[len(q) : len(rest) - len(q)] + return None + + +# A "piece" is one string literal in source: a plain STRING token, or a whole +# f-string spanning FSTRING_START..FSTRING_END. (kind, (row, col0), (row, col1), raw) +def _string_pieces( + toks: list[tokenize.TokenInfo], lines: list[str] +) -> list[tuple[str, tuple[int, int], tuple[int, int], str | None]]: + pieces: list[tuple[str, tuple[int, int], tuple[int, int], str | None]] = [] + n = len(toks) + + def raw_of(start: tuple[int, int], end: tuple[int, int]) -> str | None: + if start[0] != end[0]: # only single-physical-line pieces are mergeable + return None + return lines[start[0] - 1][start[1] : end[1]] + + i = 0 + while i < n: + t = toks[i] + if t.type == tokenize.STRING: + pieces.append(("str", t.start, t.end, raw_of(t.start, t.end))) + i += 1 + elif t.type == tokenize.FSTRING_START: + depth = 0 + j = i + while j < n: # walk to the matching FSTRING_END (f-strings can nest) + if toks[j].type == tokenize.FSTRING_START: + depth += 1 + elif toks[j].type == tokenize.FSTRING_END: + depth -= 1 + if depth == 0: + break + j += 1 + end = toks[j].end + pieces.append(("f", t.start, end, raw_of(t.start, end))) + i = j + 1 + else: + pieces.append(("other", t.start, t.end, None)) + i += 1 + return pieces + + +def _merge_string_run(pieces: list[tuple[str, str]]) -> str | None: + """Merge a run of adjacent string pieces into one literal's source text. + + ``pieces`` is a list of ``(kind, raw_source)`` where kind is ``"str"`` or + ``"f"``. Rules: bytes are left side-by-side (return ``None``); a run with no + f-string merges plain/raw/unicode pieces sharing one prefix+quote by simple + body concatenation; a run mixing an f-string with at least one plain string + (and no bytes, no raw) folds into a single f-string -- f pieces keep their + bodies verbatim and plain pieces have their braces escaped (``{`` -> ``{{``). + Runs of only f-strings are left side-by-side. The caller re-checks the file + AST and drops the change if it differs, so any subtle case (e.g. ``\\N{...}``) + that this would mis-handle is caught and skipped. + """ + parsed = [] + for kind, raw in pieces: + pqb = _split_string_token(raw) + if pqb is None: + return None + prefix, quote, body = pqb + if "b" in prefix.lower(): + return None # bytes: leave side-by-side + parsed.append((kind, prefix, quote, body)) + if len({p[2] for p in parsed}) != 1: + return None # mixed quote style: not a safe textual merge + quote = parsed[0][2] + if not any(p[0] == "f" for p in parsed): + # No f-string: merge plain/raw/unicode sharing one prefix by concatenation. + if len({p[1].lower() for p in parsed}) != 1: + return None + return f"{parsed[0][1]}{quote}{''.join(p[3] for p in parsed)}{quote}" + # f-string fold only when a plain string is glued onto an f-string; a run of + # only f-strings is left side-by-side (folding long ones would force ruff to + # re-wrap the surrounding statement). + if all(p[0] == "f" for p in parsed): + return None + # raw mixed with f is too subtle (backslash + brace escaping) -> skip. + if any("r" in p[1].lower() for p in parsed): + return None + body = "".join( + b if kind == "f" else b.replace("{", "{{").replace("}", "}}") + for kind, _pfx, _q, b in parsed + ) + return f"f{quote}{body}{quote}" + + +_LINE_LENGTH = 100 # ruff line-length; an f-fold must not push a statement past it + + +def _enclosing_stmt(tree: ast.AST, row: int) -> ast.stmt | None: + """The innermost statement whose physical-line span contains ``row``.""" + best: tuple[ast.stmt, int] | None = None + for node in ast.walk(tree): + if isinstance(node, ast.stmt): + lo = node.lineno + hi = node.end_lineno or lo + if lo <= row <= hi and (best is None or hi - lo < best[1]): + best = (node, hi - lo) + return best[0] if best else None + + +def _fold_collapses( + tree: ast.AST, lines: list[str], row: int, c0: int, c1: int, merged: str +) -> bool: + """Whether an f-string fold at ``row[c0:c1]`` -> ``merged`` is safe to apply. + + Only ``assert`` statements wrap awkwardly when a message is folded: ruff + parenthesizes the *condition* once ``assert cond, msg`` no longer fits on one + line. For every other construct (call argument, ``raise``, assignment, ...) a + folded long message wraps acceptably, so the fold is always allowed. For an + ``assert`` the fold is allowed only when the statement is already one physical + line, or its estimated one-line length after folding fits the line length; + otherwise the message is left side-by-side. + """ + stmt = _enclosing_stmt(tree, row) + if not isinstance(stmt, ast.Assert): + return True + lo, hi = stmt.lineno, stmt.end_lineno or stmt.lineno + if lo == hi: + return True + seg = [] + for k in range(lo, hi + 1): + ln = lines[k - 1].rstrip("\n") + if k == row: + ln = ln[:c0] + merged + ln[c1:] + seg.append(ln) + indent = len(seg[0]) - len(seg[0].lstrip()) + # Conservative over-estimate: join continuation lines with a single space + # (ruff joins bracketed wraps with none), so borderline cases skip the fold. + joined = " ".join(s.strip() for s in seg) + return indent + len(joined) <= _LINE_LENGTH + + +def merge_adjacent_string_literals(text: str) -> tuple[str, bool]: + """Merge a run of adjacent string literals on ONE physical line into a single + literal (the ``"a" "b"`` form ruff emits when it collapses an implicit + concatenation). Plain/raw/unicode runs merge by concatenation; a run mixing + an f-string with a plain string folds into one f-string (plain parts' braces + escaped) -- but only when the statement still fits on one line, so a long + message is left side-by-side rather than forcing the statement to re-wrap. + Runs of only f-strings, and bytes, are left side-by-side. The whole file's AST + is re-checked and the change is dropped if it would differ, so the transform + can never change meaning. + """ + try: + toks = list(tokenize.generate_tokens(io.StringIO(text).readline)) + tree = ast.parse(text) + except (tokenize.TokenError, IndentationError, SyntaxError): + return text, False + + lines = text.splitlines(keepends=True) + pieces = _string_pieces(toks, lines) + + # Group consecutive mergeable pieces (str/f, single line, same physical line). + runs: list[list[tuple[str, tuple[int, int], tuple[int, int], str]]] = [] + cur: list[tuple[str, tuple[int, int], tuple[int, int], str]] = [] + for kind, start, end, raw in pieces: + if kind in ("str", "f") and raw is not None: + if cur and cur[-1][2][0] != start[0]: + if len(cur) >= 2: + runs.append(cur) + cur = [] + cur.append((kind, start, end, raw)) + else: + if len(cur) >= 2: + runs.append(cur) + cur = [] + if len(cur) >= 2: + runs.append(cur) + if not runs: + return text, False + + edits = [] + for run in runs: + merged = _merge_string_run([(kind, raw) for kind, _s, _e, raw in run]) + if merged is None: + continue + row, c0, c1 = run[0][1][0], run[0][1][1], run[-1][2][1] + # An f-string fold must not push its statement onto extra lines; a plain + # concatenation always collapses cleanly so it skips this check. + if any(kind == "f" for kind, _s, _e, _r in run) and not _fold_collapses( + tree, lines, row, c0, c1, merged + ): + continue + edits.append((row, c0, c1, merged)) + if not edits: + return text, False + + for row, c0, c1, repl in sorted(edits, key=lambda e: (e[0], e[1]), reverse=True): + ln = lines[row - 1] + lines[row - 1] = ln[:c0] + repl + ln[c1:] + out = "".join(lines) + try: + if ast.dump(ast.parse(text)) != ast.dump(ast.parse(out)): + return text, False + except SyntaxError: + return text, False + return out, True + + +def collapse_short_asserts(text: str) -> tuple[str, bool]: + """Collapse a multi-line ``assert`` onto one line when it would fit. + + An ``assert`` is often kept multi-line only by a magic trailing comma inside + a collection / call / tuple-message (``assert x == {\"a\": 1,}`` written + across lines). When the whole statement's estimated one-line length fits the + line length, strip those trailing commas (the comma before a ``)`` / ``]`` / + ``}``) so ruff joins it back onto one line on the following format pass. + + Run BEFORE ruff format. Skips any assert that contains a comment (a comment + forces ruff to keep it multi-line, which would oscillate). Stripping a + trailing comma is non-semantic except for a one-element tuple ``(x,)``; the + file AST is re-checked and any assert whose strip would change it is left + alone. + """ + try: + tree = ast.parse(text) + toks = list(tokenize.generate_tokens(io.StringIO(text).readline)) + except (tokenize.TokenError, IndentationError, SyntaxError): + return text, False + + lines = text.splitlines(keepends=True) + multiline = [ + (n.lineno, n.end_lineno) + for n in ast.walk(tree) + if isinstance(n, ast.Assert) and (n.end_lineno or n.lineno) > n.lineno + ] + if not multiline: + return text, False + + comment_rows = {t.start[0] for t in toks if t.type == tokenize.COMMENT} + + targets = [] # (lo, hi) spans whose one-line form fits and have no comment + for lo, hi in multiline: + if any(lo <= r <= hi for r in comment_rows): + continue # a comment would keep ruff multi-line -> never collapses + seg = [lines[k].rstrip("\n") for k in range(lo - 1, hi)] + indent = len(seg[0]) - len(seg[0].lstrip()) + # Over-estimate (join with a space; keep the comma) so a "fits" verdict + # is always at least as long as ruff's real one-line output -> no fight. + if indent + len(" ".join(s.strip() for s in seg)) <= _LINE_LENGTH: + targets.append((lo, hi)) + if not targets: + return text, False + + # Trailing commas (a ',' whose next significant token is a closer), grouped + # by the target assert they belong to. + sig = [t for t in toks if t.type not in _STRING_TRIVIA] + by_target: dict[tuple[int, int], list[tuple[int, int]]] = defaultdict(list) + for i, t in enumerate(sig): + if t.type == tokenize.OP and t.string == ",": + nxt = sig[i + 1] if i + 1 < len(sig) else None + if nxt and nxt.type == tokenize.OP and nxt.string in (")", "]", "}"): + for lo, hi in targets: + if lo <= t.start[0] <= hi: + by_target[(lo, hi)].append(t.start) + break + if not by_target: + return text, False + + base_dump = ast.dump(tree) + working = lines[:] + changed = False + for positions in by_target.values(): # apply per assert; skip any that break AST + trial = working[:] + for row, col in sorted(positions, reverse=True): + ln = trial[row - 1] + if col < len(ln) and ln[col] == ",": + trial[row - 1] = ln[:col] + ln[col + 1 :] + try: + if ast.dump(ast.parse("".join(trial))) == base_dump: + working, changed = trial, True + except SyntaxError: + pass + return ("".join(working), True) if changed else (text, False) + + +def process_file(path: Path, pre: bool = False) -> bool: try: with tokenize.open(path) as handle: original = handle.read() @@ -169,9 +635,23 @@ def process_file(path: Path) -> bool: print(f"Failed to read {path}: {exc}", file=sys.stderr) return False + if pre: + # Pre-ruff: normalize def-signature magic commas (>=3 params + a default + # add so ruff forces one-per-line; everything else strips so ruff + # collapses), and strip the magic trailing comma from a short multi-line + # assert so ruff joins it onto one line. Everything else runs post-ruff. + updated, normalized = normalize_def_trailing_comma(original) + updated, collapsed = collapse_short_asserts(updated) + if normalized or collapsed: + _atomic_write_text(path, updated, encoding) + return True + return False + updated, changed = enforce_spacing(original) + updated, blanked = remove_blank_after_short_import(updated) + updated, merged = merge_adjacent_string_literals(updated) updated, removed = remove_redundant_passes(updated) - if changed or removed: + if changed or blanked or merged or removed: _atomic_write_text(path, updated, encoding) return True return False @@ -180,6 +660,11 @@ def process_file(path: Path) -> bool: def main(argv: list[str]) -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("files", nargs="+", help="Python files to fix") + parser.add_argument( + "--pre", + action="store_true", + help="pre-ruff pass: normalize def-signature commas + collapse short multi-line asserts", + ) args = parser.parse_args(argv) touched: list[Path] = [] @@ -192,7 +677,7 @@ def main(argv: list[str]) -> int: continue if not path.exists() or path.is_dir(): continue - if process_file(path): + if process_file(path, pre=args.pre): touched.append(path) if touched: diff --git a/scripts/lint_workflow_triggers.py b/scripts/lint_workflow_triggers.py index d8e7356fd1..34868b7d68 100644 --- a/scripts/lint_workflow_triggers.py +++ b/scripts/lint_workflow_triggers.py @@ -47,9 +47,7 @@ from pathlib import Path try: import yaml except ImportError: - print( - "ERROR: PyYAML is required. Install with 'pip install pyyaml'", file = sys.stderr - ) + print("ERROR: PyYAML is required. Install with 'pip install pyyaml'", file = sys.stderr) sys.exit(2) REPO_ROOT = Path(__file__).resolve().parents[1] @@ -153,9 +151,7 @@ def main() -> int: ) if findings: - print( - "Workflow trigger lint failed with the following issues:", file = sys.stderr - ) + print("Workflow trigger lint failed with the following issues:", file = sys.stderr) for f in findings: print(f" - {f}", file = sys.stderr) return 1 diff --git a/scripts/lockfile_supply_chain_audit.py b/scripts/lockfile_supply_chain_audit.py index ffeea51c23..5b503dcffe 100644 --- a/scripts/lockfile_supply_chain_audit.py +++ b/scripts/lockfile_supply_chain_audit.py @@ -541,9 +541,7 @@ def audit_npm_lockfile(path: Path) -> list[Finding]: path = str(path), package = key, kind = "blocked-known-malicious", - detail = ( - f"{pkg_name}@{version} is on the " "BLOCKED_NPM_VERSIONS list" - ), + detail = (f"{pkg_name}@{version} is on the BLOCKED_NPM_VERSIONS list"), ) ) @@ -765,10 +763,7 @@ def main(argv: list[str] | None = None) -> int: "--cargo-lockfile", action = "append", default = None, - help = ( - "Path to a Cargo.lock (repeatable). " - "Default: studio/src-tauri/Cargo.lock." - ), + help = ("Path to a Cargo.lock (repeatable). Default: studio/src-tauri/Cargo.lock."), ) parser.add_argument( "--strict", diff --git a/scripts/notebook_to_python.py b/scripts/notebook_to_python.py index 4e3046103e..cc9dc0acda 100644 --- a/scripts/notebook_to_python.py +++ b/scripts/notebook_to_python.py @@ -186,9 +186,7 @@ def convert_cell_to_python(source: str, *, allow_shell: bool = True) -> str: cmd_lines.append(lines[i].strip()) full_cmd = "\n".join(cmd_lines) - result.extend( - _emit_shell_command(indent, full_cmd, allow_shell = allow_shell) - ) + result.extend(_emit_shell_command(indent, full_cmd, allow_shell = allow_shell)) # %cd path -> os.chdir(path) elif stripped.startswith("%cd "): @@ -313,9 +311,7 @@ def convert_notebook_to_script( # Generate output filename output_filename = filename.replace(".ipynb", ".py") # Clean up filename - output_filename = ( - output_filename.replace("(", "").replace(")", "").replace("-", "_") - ) + output_filename = output_filename.replace("(", "").replace(")", "").replace("-", "_") # Add output directory if specified if output_dir: @@ -337,9 +333,7 @@ def convert_notebook_to_script( def main(): import argparse - class Formatter( - argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter - ): + class Formatter(argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter): pass parser = argparse.ArgumentParser( @@ -353,12 +347,8 @@ Examples: python notebook_to_python.py https://github.com/unslothai/notebooks/blob/main/nb/Oute_TTS_(1B).ipynb """, ) - parser.add_argument( - "notebooks", nargs = "+", help = "Notebook files or URLs to convert." - ) - parser.add_argument( - "-o", "--output", dest = "output_dir", default = ".", help = "Output directory." - ) + parser.add_argument("notebooks", nargs = "+", help = "Notebook files or URLs to convert.") + parser.add_argument("-o", "--output", dest = "output_dir", default = ".", help = "Output directory.") # Default True for backwards compatibility: existing Colab notebooks # routinely use pipes / redirection / interpolation in `!cmd` lines # and the converted script needs to keep working. Operators who diff --git a/scripts/notebook_validator.py b/scripts/notebook_validator.py index 55a9203e0b..74bfaa8d41 100644 --- a/scripts/notebook_validator.py +++ b/scripts/notebook_validator.py @@ -92,9 +92,7 @@ COLAB_ORACLE_FILES: dict[str, str] = { "apt-list-gpu.txt": "colab_apt_list.gpu.txt", "os-info-gpu.txt": "colab_os_info.gpu.txt", } -COLAB_ORACLE_BASE_URL = ( - "https://raw.githubusercontent.com/googlecolab/backend-info/main/" -) +COLAB_ORACLE_BASE_URL = "https://raw.githubusercontent.com/googlecolab/backend-info/main/" # ----- Compat tables. PRs add rows as new releases land. ----- # @@ -195,9 +193,7 @@ def install_cells(nb: dict[str, Any]) -> list[tuple[int, str]]: if first and first[0].strip().startswith("%%capture"): out.append((i, src)) continue - if re.search( - r"^[ \t]*!\s*(uv\s+)?pip\s+(install|uninstall)\b", src, re.MULTILINE - ): + if re.search(r"^[ \t]*!\s*(uv\s+)?pip\s+(install|uninstall)\b", src, re.MULTILINE): out.append((i, src)) return out @@ -331,9 +327,7 @@ def parse_pip_line(line: str, line_no: int = 0) -> PipInvocation | None: if t in ("install", "uninstall"): continue packages.append(t) - return PipInvocation( - tool = tool, flags = flags, packages = packages, raw = line, line_no = line_no - ) + return PipInvocation(tool = tool, flags = flags, packages = packages, raw = line, line_no = line_no) def _glue_line_continuations(text: str) -> list[tuple[int, str]]: @@ -418,9 +412,7 @@ def pypi_metadata(name: str, version: str) -> dict[str, Any] | None: return data -def transitive_constraint( - name: str, version: str, target: str -) -> tuple[str | None, list[str]]: +def transitive_constraint(name: str, version: str, target: str) -> tuple[str | None, list[str]]: """Return (raw_specifier_string_or_None, list_of_(op,version) tuples) for the constraint that `name==version` places on `target`. """ @@ -501,10 +493,7 @@ def resolved_set(install_cell: str, colab: dict[str, str]) -> dict[str, str]: out[sp.name] = ver pinned.add(sp.name) elif op == "<=" and sp.name not in pinned: - if ( - sp.name not in upper_bounds - or cmp_versions(ver, upper_bounds[sp.name]) < 0 - ): + if sp.name not in upper_bounds or cmp_versions(ver, upper_bounds[sp.name]) < 0: upper_bounds[sp.name] = ver # Apply upper bounds where Colab's preinstall violates them. for name, ub in upper_bounds.items(): @@ -519,9 +508,7 @@ def resolved_set(install_cell: str, colab: dict[str, str]) -> dict[str, str]: # ----- Rules ----- # -def rule_inst_001_git_plus( - install_cell: str, file: str, cell_idx: int -) -> list[Finding]: +def rule_inst_001_git_plus(install_cell: str, file: str, cell_idx: int) -> list[Finding]: findings: list[Finding] = [] for inv in iter_pip_invocations(install_cell): if any("git+" in p for p in inv.packages) or "git+" in inv.raw: @@ -714,9 +701,7 @@ def rule_inst_005_transformers_tokenizers( _RE_DOUBLE_BANG = re.compile(r"^[ \t]*!{2,}\s*pip\b", re.MULTILINE) -def rule_inst_006_double_bang( - install_cell: str, file: str, cell_idx: int -) -> list[Finding]: +def rule_inst_006_double_bang(install_cell: str, file: str, cell_idx: int) -> list[Finding]: findings: list[Finding] = [] for m in _RE_DOUBLE_BANG.finditer(install_cell): line_no = install_cell.count("\n", 0, m.start()) + 1 @@ -813,9 +798,7 @@ POLICY_CLAUSES_DEFAULT = [ ] -def extract_policy_clauses( - update_script: pathlib.Path, -) -> list[tuple[str, re.Pattern[str], Any]]: +def extract_policy_clauses(update_script: pathlib.Path) -> list[tuple[str, re.Pattern[str], Any]]: """Best-effort: scan update_all_notebooks.py for canonical phrases used by multiple templates. Falls back to POLICY_CLAUSES_DEFAULT. @@ -879,11 +862,7 @@ def cmd_drift(args: argparse.Namespace) -> int: print(f"FAIL: {update_script} not found", file = sys.stderr) return 2 # Stash any pre-existing dirty state, run the updater, diff, restore. - head = ( - subprocess.check_output(["git", "rev-parse", "HEAD"], cwd = nbdir) - .decode() - .strip() - ) + head = subprocess.check_output(["git", "rev-parse", "HEAD"], cwd = nbdir).decode().strip() subprocess.run( ["git", "-C", str(nbdir), "stash", "--include-untracked"], check = False, @@ -990,9 +969,7 @@ def cmd_convert(args: argparse.Namespace) -> int: hint = proc.stderr[-200:].strip(), ) ) - print( - f"converted {len(notebooks) - len(failed)}/{len(notebooks)} notebooks to {out}" - ) + print(f"converted {len(notebooks) - len(failed)}/{len(notebooks)} notebooks to {out}") _emit(failed) return 0 if not failed else 1 @@ -1002,11 +979,7 @@ def cmd_convert(args: argparse.Namespace) -> int: def cmd_lint(args: argparse.Namespace) -> int: nbdir = pathlib.Path(args.notebooks_dir).resolve() - colab_path = ( - pathlib.Path(args.colab_pin).resolve() - if args.colab_pin - else COLAB_FALLBACK_FILE - ) + colab_path = pathlib.Path(args.colab_pin).resolve() if args.colab_pin else COLAB_FALLBACK_FILE colab = parse_pip_freeze(colab_path) if not colab: print( @@ -1049,13 +1022,9 @@ def cmd_lint(args: argparse.Namespace) -> int: first_cell = cells[0][0] if cells else None findings += rule_inst_003_peft_torchao(merged, oracle, rel, first_cell) findings += rule_inst_004_torchcodec_torch(merged, oracle, rel, first_cell) - findings += rule_inst_005_transformers_tokenizers( - merged, oracle, rel, first_cell - ) + findings += rule_inst_005_transformers_tokenizers(merged, oracle, rel, first_cell) if not args.no_pypi: - findings += rule_inst_002_no_deps_transitive( - merged, oracle, rel, first_cell - ) + findings += rule_inst_002_no_deps_transitive(merged, oracle, rel, first_cell) findings += scan_user_cells(nb, rel) _emit(findings) return 0 if not any(f.severity == "error" for f in findings) else 1 @@ -1232,9 +1201,7 @@ def cmd_colab_diff(args: argparse.Namespace) -> int: print(f"::warning::colab-diff: could not fetch {url}: {e}") continue if not snap_path.exists(): - print( - f"::warning::colab-diff: no committed snapshot at {snap_path}; skipping" - ) + print(f"::warning::colab-diff: no committed snapshot at {snap_path}; skipping") continue snapshot_text = snap_path.read_text(encoding = "utf-8", errors = "replace") parser = _COLAB_ORACLE_PARSERS[upstream_name] diff --git a/scripts/run_ruff_format.py b/scripts/run_ruff_format.py index 5ec16cd9f5..2f0a6c6bba 100755 --- a/scripts/run_ruff_format.py +++ b/scripts/run_ruff_format.py @@ -1,5 +1,7 @@ #!/usr/bin/env python3 -"""Run `ruff format` followed by kwarg spacing enforcement.""" +"""Run a pre-pass (normalize def-signature magic commas + collapse short +multi-line asserts), then `ruff format`, then the kwarg-spacing / import / +string-merge post-pass.""" from __future__ import annotations @@ -15,12 +17,22 @@ def main(argv: list[str]) -> int: if not files: return 0 + spacing_script = HERE / "enforce_kwargs_spacing.py" + + # Pre-ruff: normalize def-signature trailing commas (>=3 params with a + # default -> one-per-line; everything else collapsible) and strip the magic + # comma from a short multi-line assert, so ruff wraps signatures accordingly + # and joins the assert back onto one line. + pre_cmd = [sys.executable, str(spacing_script), "--pre", *files] + pre_proc = subprocess.run(pre_cmd) + if pre_proc.returncode != 0: + return pre_proc.returncode + ruff_cmd = [sys.executable, "-m", "ruff", "format", *files] ruff_proc = subprocess.run(ruff_cmd) if ruff_proc.returncode != 0: return ruff_proc.returncode - spacing_script = HERE / "enforce_kwargs_spacing.py" spacing_cmd = [sys.executable, str(spacing_script), *files] spacing_proc = subprocess.run(spacing_cmd) return spacing_proc.returncode diff --git a/scripts/scan_npm_packages.py b/scripts/scan_npm_packages.py index 07eccdd716..14a3cd6560 100644 --- a/scripts/scan_npm_packages.py +++ b/scripts/scan_npm_packages.py @@ -823,8 +823,7 @@ def download_tarball( written += len(chunk) if written > max_bytes: return dest, ( - f"download exceeded cap {max_bytes} bytes " - f"after {written} bytes" + f"download exceeded cap {max_bytes} bytes " f"after {written} bytes" ) h.update(chunk) out.write(chunk) @@ -926,11 +925,7 @@ def safe_extract( # get the generous binary cap. We bound BOTH cases. header = src.read(16) is_binary = _looks_binary(name, header) - file_cap = ( - HARD_MAX_BINARY_FILE_BYTES - if is_binary - else HARD_MAX_TEXT_FILE_BYTES - ) + file_cap = HARD_MAX_BINARY_FILE_BYTES if is_binary else HARD_MAX_TEXT_FILE_BYTES if declared > file_cap: return ( f"member {name!r} declared size {declared} > " @@ -963,7 +958,11 @@ def safe_extract( # ───────────────────────────────────────────────────────────────────── -def _evidence(text: str, pat: re.Pattern, max_chars: int = 200) -> str: +def _evidence( + text: str, + pat: re.Pattern, + max_chars: int = 200, +) -> str: m = pat.search(text) if not m: return "" @@ -978,11 +977,7 @@ def _evidence(text: str, pat: re.Pattern, max_chars: int = 200) -> str: LIFECYCLE_HOOKS = ("preinstall", "install", "postinstall", "prepare") -def scan_package_json( - pkg: PackageEntry, - rel: str, - text: str, -) -> list[Finding]: +def scan_package_json(pkg: PackageEntry, rel: str, text: str) -> list[Finding]: findings: list[Finding] = [] try: meta = json.loads(text) @@ -1056,9 +1051,7 @@ def scan_package_json( if isinstance(opt, dict): for k, v in opt.items(): if isinstance(v, str) and ( - v.startswith("github:") - or v.startswith("git+") - or v.startswith("git://") + v.startswith("github:") or v.startswith("git+") or v.startswith("git://") ): findings.append( Finding( @@ -1117,11 +1110,7 @@ def _host_in_outbound_context(text: str, host: str) -> bool: return False -def scan_text_blob( - pkg: PackageEntry, - rel: str, - text: str, -) -> list[Finding]: +def scan_text_blob(pkg: PackageEntry, rel: str, text: str) -> list[Finding]: findings: list[Finding] = [] # IOC substrings (literal, case-sensitive). @@ -1190,10 +1179,7 @@ def scan_text_blob( filename = rel, pattern = "js-fetch-eval", evidence = _evidence(text, _JS_FETCH_EVAL), - detail = ( - "Function/eval against base64-decoded payload " - "(obfuscated dropper shape)" - ), + detail = ("Function/eval against base64-decoded payload (obfuscated dropper shape)"), ) ) if _JS_ENV_TOKEN.search(text): @@ -1247,10 +1233,7 @@ _TEXT_SUFFIXES = ( ) -def scan_extracted_tree( - pkg: PackageEntry, - root: Path, -) -> list[Finding]: +def scan_extracted_tree(pkg: PackageEntry, root: Path) -> list[Finding]: findings: list[Finding] = [] for path in sorted(root.rglob("*")): if not path.is_file(): @@ -1304,10 +1287,7 @@ def scan_extracted_tree( # ───────────────────────────────────────────────────────────────────── -def scan_one( - pkg: PackageEntry, - workspace: Path, -) -> tuple[list[Finding], str | None]: +def scan_one(pkg: PackageEntry, workspace: Path) -> tuple[list[Finding], str | None]: """Download + extract + scan a single package. Cleans up its dir. Returns (findings, error). `error` is non-None only on hard @@ -1444,8 +1424,7 @@ def main(argv: list[str] | None = None) -> int: if hard_errors or blocking: if blocking: print( - f"\n[scan-npm] FAIL: {len(blocking)} finding(s) " - f"at or above {threshold}", + f"\n[scan-npm] FAIL: {len(blocking)} finding(s) " f"at or above {threshold}", file = sys.stderr, ) return 1 diff --git a/scripts/scan_packages.py b/scripts/scan_packages.py index 6779b634f7..d753a17e49 100644 --- a/scripts/scan_packages.py +++ b/scripts/scan_packages.py @@ -86,8 +86,7 @@ RE_SUBPROCESS = re.compile( # Encoding / obfuscation RE_BASE64 = re.compile( - r"\bbase64\s*\.\s*(b64decode|decodebytes|b32decode|b16decode)\b" - r"|\bcodecs\s*\.\s*decode\b", + r"\bbase64\s*\.\s*(b64decode|decodebytes|b32decode|b16decode)\b|\bcodecs\s*\.\s*decode\b", ) # exec / eval @@ -299,9 +298,7 @@ RE_CRYPTO_THEFT = re.compile( RE_PTH_IMPORT = re.compile(r"^\s*import\s+", re.MULTILINE) # openssl CLI invocations via subprocess (encrypted exfiltration) -RE_OPENSSL_CLI = re.compile( - r"\bopenssl\s+(enc|rand|rsautl|pkeyutl|genrsa|dgst|s_client)\b" -) +RE_OPENSSL_CLI = re.compile(r"\bopenssl\s+(enc|rand|rsautl|pkeyutl|genrsa|dgst|s_client)\b") # Write to /tmp then execute (staged dropper) RE_TEMP_EXEC = re.compile( @@ -962,7 +959,11 @@ def check_py_file(content: str, filename: str, package: str) -> list[Finding]: return findings -def _extract_evidence(content: str, pattern: re.Pattern, max_matches: int = 3) -> str: +def _extract_evidence( + content: str, + pattern: re.Pattern, + max_matches: int = 3, +) -> str: """Pull matching lines as evidence snippets.""" lines = content.splitlines() matches = [] @@ -1266,15 +1267,13 @@ def iter_archive_files(archive_path: str): # have historically dereferenced them on extract. if member.issym() or member.islnk(): print( - f" [WARN] {path.name}: refused link member " - f"{member.name!r}", + f" [WARN] {path.name}: refused link member " f"{member.name!r}", file = sys.stderr, ) continue if member.isdev() or member.isfifo(): print( - f" [WARN] {path.name}: refused special member " - f"{member.name!r}", + f" [WARN] {path.name}: refused special member " f"{member.name!r}", file = sys.stderr, ) continue @@ -1379,9 +1378,7 @@ def scan_archive(archive_path: str, package: str) -> list[Finding]: _RE_PYPI_SPEC_VERSION = re.compile(r"==\s*([A-Za-z0-9_.\-+!]+)") -def _check_blocked_pypi_versions( - specs: list[str], -) -> tuple[list[str], list[Finding]]: +def _check_blocked_pypi_versions(specs: list[str]) -> tuple[list[str], list[Finding]]: """Filter ``specs`` against ``BLOCKED_PYPI_VERSIONS``. Returns ``(safe_specs, findings)``. Each blocked spec emits a CRITICAL @@ -1502,9 +1499,7 @@ def download_packages( env = env, ) if proc.returncode != 0: - msg = ( - f"pip download (with deps) failed: " f"{proc.stderr.strip()[:500]}" - ) + msg = f"pip download (with deps) failed: " f"{proc.stderr.strip()[:500]}" print(f" [ERROR] {msg}", file = sys.stderr) download_errors.append(msg) except subprocess.TimeoutExpired: @@ -1547,10 +1542,7 @@ def download_packages( env = env, ) if proc.returncode != 0: - msg = ( - f"pip download failed for {spec}: " - f"{proc.stderr.strip()[:500]}" - ) + msg = f"pip download failed for {spec}: " f"{proc.stderr.strip()[:500]}" print(f" [ERROR] {msg}", file = sys.stderr) download_errors.append(msg) continue @@ -1579,9 +1571,7 @@ def _extract_pkg_name(spec: str) -> str: """Extract the package name from a pip spec string.""" m = _RE_NAME.match(spec) return ( - m.group(1) - if m - else spec.split("==")[0].split(">=")[0].split("<=")[0].split("[")[0].strip() + m.group(1) if m else spec.split("==")[0].split(">=")[0].split("<=")[0].split("[")[0].strip() ) @@ -1917,11 +1907,7 @@ def update_req_file(filepath: str, updates: dict[int, str]) -> None: raise -def _run_fix( - critical_pkgs: set[str], - entries: list[dict], - max_search: int, -) -> None: +def _run_fix(critical_pkgs: set[str], entries: list[dict], max_search: int) -> None: """Run the --fix flow: find safe versions, update requirements files.""" # Map package names to their entries for source tracking pkg_entries: dict[str, list[dict]] = {} @@ -1941,9 +1927,7 @@ def _run_fix( if git_entries: for e in git_entries: src = e["source_file"] or "CLI" - print( - f" [SKIP] {pkg_name} is a git URL dep in {src}, cannot auto-update" - ) + print(f" [SKIP] {pkg_name} is a git URL dep in {src}, cannot auto-update") changes_summary.append(f" SKIP {pkg_name} (git URL)") continue @@ -1967,9 +1951,7 @@ def _run_fix( shutil.rmtree(dl_dir, ignore_errors = True) if not current_ver: - print( - f" [WARN] Cannot determine current version of {pkg_name}, skipping fix" - ) + print(f" [WARN] Cannot determine current version of {pkg_name}, skipping fix") changes_summary.append(f" SKIP {pkg_name} (version unknown)") continue @@ -1986,9 +1968,7 @@ def _run_fix( continue print(f" [OK] {pkg_name}: {current_ver} -> {safe_ver}") - changes_summary.append( - f" FIX {pkg_name}=={current_ver} -> {pkg_name}=={safe_ver}" - ) + changes_summary.append(f" FIX {pkg_name}=={current_ver} -> {pkg_name}=={safe_ver}") # Update all occurrences in requirements files file_updates: dict[str, dict[int, str]] = {} @@ -2038,9 +2018,7 @@ def _find_requirements_files(root: str) -> list[str]: dirnames[:] = [ d for d in dirnames - if not d.startswith(".") - and d not in skip_dirs - and not d.endswith(".egg-info") + if not d.startswith(".") and d not in skip_dirs and not d.endswith(".egg-info") ] dirname = os.path.basename(dirpath) for fname in sorted(filenames): @@ -2115,9 +2093,7 @@ def main() -> int: print(f" {f}") req_files.extend(found) else: - print( - f" [WARN] No requirements files found in {scan_dir}/", file = sys.stderr - ) + print(f" [WARN] No requirements files found in {scan_dir}/", file = sys.stderr) # Build unified entry list: list of dicts with source tracking entries: list[dict] = [] @@ -2211,7 +2187,7 @@ def main() -> int: for err in download_errors: print(f" [ERROR] {err}", file = sys.stderr) print( - " Refusing to report 'all clean' on a partial scan; " "exiting 2.", + " Refusing to report 'all clean' on a partial scan; exiting 2.", file = sys.stderr, ) return 2 diff --git a/scripts/stamp_studio_release.py b/scripts/stamp_studio_release.py index ac538e9937..a3c8712a6e 100644 --- a/scripts/stamp_studio_release.py +++ b/scripts/stamp_studio_release.py @@ -17,7 +17,11 @@ import zipfile from pathlib import Path -def _atomic_write_text(path: Path, data: str, encoding: str = "utf-8") -> None: +def _atomic_write_text( + path: Path, + data: str, + encoding: str = "utf-8", +) -> None: """Atomic version of ``Path.write_text``. A crash or signal mid-write leaves the prior file intact; the @@ -41,9 +45,7 @@ def _atomic_write_text(path: Path, data: str, encoding: str = "utf-8") -> None: REPO_ROOT = Path(__file__).resolve().parents[1] -BUILD_INFO_PATH = ( - REPO_ROOT / "studio" / "backend" / "utils" / "_studio_release_build.py" -) +BUILD_INFO_PATH = REPO_ROOT / "studio" / "backend" / "utils" / "_studio_release_build.py" BUILD_INFO_SUFFIX = "studio/backend/utils/_studio_release_build.py" VERSION_RE = re.compile(r"^v\d+\.\d+\.\d+(?:-[0-9A-Za-z.][0-9A-Za-z.-]*)?$") GIT_DESCRIBE_SUFFIX_RE = re.compile(r"-\d+-g[0-9A-Fa-f]+(?:-dirty)?$") diff --git a/scripts/verify_comment_only_diff.py b/scripts/verify_comment_only_diff.py index 90eafb7f8f..b661f76859 100644 --- a/scripts/verify_comment_only_diff.py +++ b/scripts/verify_comment_only_diff.py @@ -128,12 +128,15 @@ def _normalize_yaml_run_strings(obj: Any) -> Any: return obj -def _walk_yaml_diff(b: Any, a: Any, prefix: str = "") -> None: +def _walk_yaml_diff( + b: Any, + a: Any, + prefix: str = "", +) -> None: """Print a path-keyed summary of the first structural / scalar diff.""" if type(b) is not type(a): print( - f" type-diff at {prefix or '/'}: " - f"{type(b).__name__} -> {type(a).__name__}", + f" type-diff at {prefix or '/'}: " f"{type(b).__name__} -> {type(a).__name__}", ) return if isinstance(b, dict): diff --git a/scripts/verify_import_hoist.py b/scripts/verify_import_hoist.py index 606488cc7f..6f5b452f3c 100644 --- a/scripts/verify_import_hoist.py +++ b/scripts/verify_import_hoist.py @@ -123,9 +123,7 @@ class _Builder(ast.NodeVisitor): def __init__(self): self.module = Scope("module", "", None) self.uses: list[tuple[Scope, str, int]] = [] # (scope, name, lineno) hard loads - self.soft_uses: list[ - tuple[Scope, str, int] - ] = [] # annotations: count as "used" + self.soft_uses: list[tuple[Scope, str, int]] = [] # annotations: count as "used" # but never as "unresolved" # (forward refs / string annos) @@ -166,9 +164,7 @@ class _Builder(ast.NodeVisitor): def _visit_stmt(self, node: ast.AST, scope: Scope) -> None: if isinstance(node, (ast.Import, ast.ImportFrom)): - star = isinstance(node, ast.ImportFrom) and any( - a.name == "*" for a in node.names - ) + star = isinstance(node, ast.ImportFrom) and any(a.name == "*" for a in node.names) if star: scope.star_import = True for alias in node.names: @@ -356,9 +352,7 @@ class _Builder(ast.NodeVisitor): self._bind_args(node.args, child) self._visit_expr(node.body, child) return - if isinstance( - node, (ast.ListComp, ast.SetComp, ast.GeneratorExp, ast.DictComp) - ): + if isinstance(node, (ast.ListComp, ast.SetComp, ast.GeneratorExp, ast.DictComp)): child = Scope("comp", f"{scope.qualname}.", scope) for i, gen in enumerate(node.generators): # first iterable is evaluated in the enclosing scope @@ -447,9 +441,7 @@ def _legb_chain(scope: Scope) -> list[Scope]: chain = [scope] p = scope.parent while p is not None: - if ( - p.kind != "class" or p.parent is None - ): # module-level class never happens; keep module + if p.kind != "class" or p.parent is None: # module-level class never happens; keep module if p.kind != "class": chain.append(p) p = p.parent @@ -624,9 +616,7 @@ def compare(before_src: str, after_src: str, path: str) -> list[tuple[str, str]] for scope, names in b["ambiguous"].items(): new = names - a["ambiguous"].get(scope, set()) for n in sorted(new): - findings.append( - ("WARN", f"{path}: AMBIGUOUS-BIND '{n}' import+non-import in {scope}") - ) + findings.append(("WARN", f"{path}: AMBIGUOUS-BIND '{n}' import+non-import in {scope}")) # 6. TARGET-MISSING (informational): a scope stopped resolving to an import # target. Real bugs are already covered above; remaining cases are code @@ -639,9 +629,7 @@ def compare(before_src: str, after_src: str, path: str) -> list[tuple[str, str]] if t in added_module_targets else " [target not re-added here -> likely relocated/deleted]" ) - findings.append( - ("INFO", f"{path}: TARGET-MISSING {t} in scope {scope}{relocated}") - ) + findings.append(("INFO", f"{path}: TARGET-MISSING {t} in scope {scope}{relocated}")) return findings @@ -650,45 +638,38 @@ def compare(before_src: str, after_src: str, path: str) -> list[tuple[str, str]] _SELF_TESTS = { "dangling_alias": ( # before: inline aliased import, used as _b - "import os\n" - "def f():\n" - " import glob as _b\n" - " return _b.glob('*')\n", + "import os\ndef f():\n import glob as _b\n return _b.glob('*')\n", # after: hoisted to canonical, but reference NOT normalized -> _b dangles - "import os\n" "import glob\n" "def f():\n" " return _b.glob('*')\n", + "import os\nimport glob\ndef f():\n return _b.glob('*')\n", "BLOCKER", ), "rename_clash": ( # before: _b is a deliberate alias; `b` already means something else - "import re as _b\n" "b = 123\n" "def f():\n" " return _b.compile('x'), b\n", + "import re as _b\nb = 123\ndef f():\n return _b.compile('x'), b\n", # after: someone normalized _b -> b ; now f().b is the int, re is lost - "import re\n" "b = 123\n" "def f():\n" " return b.compile('x'), b\n", + "import re\nb = 123\ndef f():\n return b.compile('x'), b\n", "BLOCKER", # TARGET-MISSING from:.. or import:re in f ), "clean_rename": ( - "def f():\n" " import glob as _g\n" " return _g.glob('*')\n", - "import glob\n" "def f():\n" " return glob.glob('*')\n", + "def f():\n import glob as _g\n return _g.glob('*')\n", + "import glob\ndef f():\n return glob.glob('*')\n", None, # expect NO blocker ), "clean_dedup_redundant": ( - "import sys\n" "def f():\n" " import sys\n" " return sys.argv\n", - "import sys\n" "def f():\n" " return sys.argv\n", + "import sys\ndef f():\n import sys\n return sys.argv\n", + "import sys\ndef f():\n return sys.argv\n", None, ), "from_import_dangling": ( # from-import alias left un-normalized - "def f():\n" - " from importlib.metadata import version as _v\n" - " return _v('x')\n", - "from importlib.metadata import version\n" "def f():\n" " return _v('x')\n", + "def f():\n from importlib.metadata import version as _v\n return _v('x')\n", + "from importlib.metadata import version\ndef f():\n return _v('x')\n", "BLOCKER", ), "local_var_clash": ( # _b renamed to b, but b is a LOCAL variable in f -> import silently unused - "def f(b):\n" " import re as _b\n" " return _b.compile(b)\n", - "import re\n" - "def f(b):\n" - " return b.compile(b)\n", # 'b' is the param, not the module + "def f(b):\n import re as _b\n return _b.compile(b)\n", + "import re\ndef f(b):\n return b.compile(b)\n", # 'b' is the param, not the module "BLOCKER", ), "substring_safe": ( @@ -705,11 +686,8 @@ _SELF_TESTS = { ), "attr_access_not_a_use": ( # x._b is attribute access, not a use of name _b; removing import _b is fine - "import os\n" - "def f(x):\n" - " import sys as _b\n" - " return x._b + _b.argv[0]\n", - "import os\n" "import sys\n" "def f(x):\n" " return x._b + sys.argv[0]\n", + "import os\ndef f(x):\n import sys as _b\n return x._b + _b.argv[0]\n", + "import os\nimport sys\ndef f(x):\n return x._b + sys.argv[0]\n", None, ), } @@ -797,9 +775,7 @@ def audit_files(paths: list[str]) -> int: ok = n_err == 0 and n_fp == 0 print( "\nAUDIT:", - "ROBUST (no crashes, no false positives vs pyflakes)" - if ok - else "NEEDS WORK (see above)", + "ROBUST (no crashes, no false positives vs pyflakes)" if ok else "NEEDS WORK (see above)", ) return 0 if ok else 1 @@ -835,18 +811,12 @@ def main() -> int: blockers = [f for f in findings if f[0] == "BLOCKER"] warns = [f for f in findings if f[0] == "WARN"] infos = [f for f in findings if f[0] == "INFO"] - status = ( - "CLEAN" - if not blockers and not warns - else ("BLOCKERS" if blockers else "WARNINGS") - ) + status = "CLEAN" if not blockers and not warns else ("BLOCKERS" if blockers else "WARNINGS") print(f"\n=== {path}: {status} ===") for sev, m in blockers + warns + infos: print(f" [{sev}] {m}") any_blocker = any_blocker or bool(blockers) - print( - "\nOVERALL:", "FAIL (blockers found)" if any_blocker else "PASS (no blockers)" - ) + print("\nOVERALL:", "FAIL (blockers found)" if any_blocker else "PASS (no blockers)") return 1 if any_blocker else 0 diff --git a/studio/backend/auth/authentication.py b/studio/backend/auth/authentication.py index 6ddcbc8e0b..bb5b873e65 100644 --- a/studio/backend/auth/authentication.py +++ b/studio/backend/auth/authentication.py @@ -108,9 +108,7 @@ def create_refresh_token(subject: str, *, desktop: bool = False) -> str: return token -def refresh_access_token( - refresh_token: str, -) -> Tuple[Optional[str], Optional[str], bool]: +def refresh_access_token(refresh_token: str) -> Tuple[Optional[str], Optional[str], bool]: """ Validate a refresh token and issue a new access token. @@ -137,9 +135,7 @@ def reload_secret() -> None: load_jwt_secret() -async def get_current_subject( - credentials: HTTPAuthorizationCredentials = Depends(security), -) -> str: +async def get_current_subject(credentials: HTTPAuthorizationCredentials = Depends(security)) -> str: """Validate JWT and require the password-change flow to be completed.""" return await _get_current_subject( credentials, @@ -158,9 +154,7 @@ async def get_current_subject_allow_password_change( async def _get_current_subject( - credentials: HTTPAuthorizationCredentials, - *, - allow_password_change: bool, + credentials: HTTPAuthorizationCredentials, *, allow_password_change: bool ) -> str: """ FastAPI dependency to validate the JWT and return the subject. diff --git a/studio/backend/auth/storage.py b/studio/backend/auth/storage.py index 3233aa05ef..0e34a0cf28 100644 --- a/studio/backend/auth/storage.py +++ b/studio/backend/auth/storage.py @@ -151,13 +151,9 @@ def get_connection() -> sqlite3.Connection: ); """ ) - api_key_columns = { - row["name"] for row in conn.execute("PRAGMA table_info(api_keys)") - } + api_key_columns = {row["name"] for row in conn.execute("PRAGMA table_info(api_keys)")} if "is_internal" not in api_key_columns: - conn.execute( - "ALTER TABLE api_keys ADD COLUMN is_internal INTEGER NOT NULL DEFAULT 0" - ) + conn.execute("ALTER TABLE api_keys ADD COLUMN is_internal INTEGER NOT NULL DEFAULT 0") conn.execute( """ CREATE TABLE IF NOT EXISTS app_secrets ( @@ -171,13 +167,9 @@ def get_connection() -> sqlite3.Connection: conn.execute( "ALTER TABLE auth_user ADD COLUMN must_change_password INTEGER NOT NULL DEFAULT 0" ) - refresh_columns = { - row["name"] for row in conn.execute("PRAGMA table_info(refresh_tokens)") - } + refresh_columns = {row["name"] for row in conn.execute("PRAGMA table_info(refresh_tokens)")} if "is_desktop" not in refresh_columns: - conn.execute( - "ALTER TABLE refresh_tokens ADD COLUMN is_desktop INTEGER NOT NULL DEFAULT 0" - ) + conn.execute("ALTER TABLE refresh_tokens ADD COLUMN is_desktop INTEGER NOT NULL DEFAULT 0") conn.commit() return conn diff --git a/studio/backend/colab.py b/studio/backend/colab.py index 1bca16359b..c3a1e03fbe 100644 --- a/studio/backend/colab.py +++ b/studio/backend/colab.py @@ -44,12 +44,7 @@ def get_colab_url(port: int = 8888) -> str: try: url = eval_js(f"google.colab.kernel.proxyPort({port})", timeout_sec = 10) # A valid Colab proxy URL starts with https:// and embeds the port. - if ( - url - and isinstance(url, str) - and url.startswith("https://") - and str(port) in url - ): + if url and isinstance(url, str) and url.startswith("https://") and str(port) in url: return url.rstrip("/") except Exception as e: logger.info(f"Note: Could not get Colab URL (attempt {attempt + 1}/3: {e})") @@ -118,11 +113,8 @@ def show_link(port: int = 8888, *, _url: "str | None" = None): def _is_studio_healthy(port: int, timeout: float = 2.0) -> bool: """Return True if a Studio backend is already answering health checks on *port*.""" import urllib.request - try: - with urllib.request.urlopen( - f"http://localhost:{port}/api/health", timeout = timeout - ): + with urllib.request.urlopen(f"http://localhost:{port}/api/health", timeout = timeout): return True except Exception: return False @@ -178,7 +170,6 @@ def _show_and_embed(port: int): # Fallback: Colab's built-in helper (less control, but always works) try: from google.colab import output as colab_output - colab_output.serve_kernel_port_as_iframe(port, height = 900, width = "100%") except ImportError: pass @@ -200,9 +191,7 @@ def start(port: int = 8888): # Re-launching would either collide on the port or silently shift to a new # port and confuse the user. Just re-show the link and iframe instead. if _is_studio_healthy(port): - logger.info( - f" Studio is already running on port {port} — reusing existing server." - ) + logger.info(f" Studio is already running on port {port} — reusing existing server.") _show_and_embed(port) try: for _ in range(10000): @@ -225,9 +214,7 @@ def start(port: int = 8888): logger.info(" Starting server...") try: - app = run_server( - host = "0.0.0.0", port = port, frontend_path = frontend_path, silent = True - ) + app = run_server(host = "0.0.0.0", port = port, frontend_path = frontend_path, silent = True) except SystemExit as exc: logger.error(f"❌ Unsloth Studio failed to start: {exc}") return @@ -250,9 +237,7 @@ def start(port: int = 8888): server_ready = False for _ in range(40): try: - with urllib.request.urlopen( - f"http://localhost:{actual_port}/api/health", timeout = 1 - ): + with urllib.request.urlopen(f"http://localhost:{actual_port}/api/health", timeout = 1): server_ready = True break except Exception: diff --git a/studio/backend/core/__init__.py b/studio/backend/core/__init__.py index d39815c437..2ba9d5c65c 100644 --- a/studio/backend/core/__init__.py +++ b/studio/backend/core/__init__.py @@ -140,7 +140,6 @@ def __getattr__(name): # Datasets if name == "format_and_template_dataset": from utils.datasets import format_and_template_dataset - globals()["format_and_template_dataset"] = format_and_template_dataset return format_and_template_dataset diff --git a/studio/backend/core/_torchao_stub.py b/studio/backend/core/_torchao_stub.py index 5650a60ee2..217c25fda3 100644 --- a/studio/backend/core/_torchao_stub.py +++ b/studio/backend/core/_torchao_stub.py @@ -64,7 +64,11 @@ def _make_mod_stub(mod_name): m._unsloth_stub = _STUB_SENTINEL m.__spec__ = importlib.machinery.ModuleSpec(mod_name, loader = None, is_package = True) - def _ga(attr, _m = m, _n = mod_name): + def _ga( + attr, + _m = m, + _n = mod_name, + ): if attr.startswith("__"): raise AttributeError(attr) # Return a stub CLASS (not a module) so that isinstance(x, attr) @@ -89,7 +93,12 @@ class _StubSubpackageLoader(importlib.abc.Loader): class _StubSubpackageFinder(importlib.abc.MetaPathFinder): - def find_spec(self, fullname, path, target = None): + def find_spec( + self, + fullname, + path, + target = None, + ): if "." not in fullname: return None parent = sys.modules.get(fullname.rsplit(".", 1)[0]) @@ -118,7 +127,6 @@ def install_torchao_windows_rocm_stub() -> None: if sys.platform == "win32": try: import torch as _torch_probe - _is_win32_rocm = bool( getattr(getattr(_torch_probe, "version", None), "hip", None) or "rocm" in getattr(_torch_probe, "__version__", "").lower() diff --git a/studio/backend/core/data_recipe/huggingface.py b/studio/backend/core/data_recipe/huggingface.py index 16f6b15af5..d5a6db6baf 100644 --- a/studio/backend/core/data_recipe/huggingface.py +++ b/studio/backend/core/data_recipe/huggingface.py @@ -36,9 +36,7 @@ def _resolve_recipe_artifact_path(artifact_path: str) -> Path: if not resolved.exists(): raise RecipeDatasetPublishError("Execution artifacts are no longer available.") if not resolved.is_dir(): - raise RecipeDatasetPublishError( - "Execution artifact path is not a dataset folder." - ) + raise RecipeDatasetPublishError("Execution artifact path is not a dataset folder.") return resolved diff --git a/studio/backend/core/data_recipe/jobs/manager.py b/studio/backend/core/data_recipe/jobs/manager.py index cdc28d9560..75dc1efb9c 100644 --- a/studio/backend/core/data_recipe/jobs/manager.py +++ b/studio/backend/core/data_recipe/jobs/manager.py @@ -108,9 +108,7 @@ class Subscription: event_id = self._next_id body = json.dumps(event, separators = (",", ":"), ensure_ascii = False) event_type = event.get("type") or "message" - return ( - f"id: {event_id}\n" f"event: {event_type}\n" f"data: {body}\n\n" - ).encode("utf-8") + return (f"id: {event_id}\n" f"event: {event_type}\n" f"data: {body}\n\n").encode("utf-8") class JobManager: @@ -158,9 +156,7 @@ class JobManager: job_id = uuid.uuid4().hex self._job = Job(job_id = job_id, status = "pending", started_at = time.time()) self._job.progress_columns_total = llm_column_count - self._job.source_progress_estimated_total = _github_source_estimated_total( - recipe - ) + self._job.source_progress_estimated_total = _github_source_estimated_total(recipe) self._job.internal_api_key_id = internal_api_key_id self._events.clear() self._seq = 0 @@ -187,9 +183,7 @@ class JobManager: self._pump_thread = threading.Thread(target = self._pump_loop, daemon = True) self._pump_thread.start() - self._emit( - {"type": EVENT_JOB_ENQUEUED, "ts": time.time(), "job_id": job_id} - ) + self._emit({"type": EVENT_JOB_ENQUEUED, "ts": time.time(), "job_id": job_id}) return job_id def cancel(self, job_id: str) -> bool: @@ -200,9 +194,7 @@ class JobManager: if self._proc is None or not self._proc.is_alive(): return True self._job.status = "cancelling" - self._emit( - {"type": EVENT_JOB_CANCELLING, "ts": time.time(), "job_id": job_id} - ) + self._emit({"type": EVENT_JOB_CANCELLING, "ts": time.time(), "job_id": job_id}) try: self._proc.terminate() except (AttributeError, OSError): @@ -319,19 +311,12 @@ class JobManager: if not parquet_dir.exists(): return {"error": f"dataset path missing: {parquet_dir}"} - return self._load_dataset_page( - parquet_dir = parquet_dir, limit = limit, offset = offset - ) + return self._load_dataset_page(parquet_dir = parquet_dir, limit = limit, offset = offset) except Exception as exc: return {"error": f"dataset load failed: {exc}"} @staticmethod - def _load_dataset_page( - *, - parquet_dir: Path, - limit: int, - offset: int, - ) -> dict[str, Any]: + def _load_dataset_page(*, parquet_dir: Path, limit: int, offset: int) -> dict[str, Any]: dataset_page = JobManager._load_dataset_page_with_duckdb( parquet_dir = parquet_dir, limit = limit, @@ -347,10 +332,7 @@ class JobManager: @staticmethod def _load_dataset_page_with_duckdb( - *, - parquet_dir: Path, - limit: int, - offset: int, + *, parquet_dir: Path, limit: int, offset: int ) -> dict[str, Any] | None: parquet_glob = str((parquet_dir / "*.parquet").resolve()) try: @@ -389,10 +371,7 @@ class JobManager: @staticmethod def _load_dataset_page_with_data_designer( - *, - parquet_dir: Path, - limit: int, - offset: int, + *, parquet_dir: Path, limit: int, offset: int ) -> dict[str, Any]: from data_designer.config.utils.io_helpers import read_parquet_dataset @@ -402,7 +381,10 @@ class JobManager: return {"dataset": to_preview_jsonable(rows), "total": total} def subscribe( - self, job_id: str, *, after_seq: int | None = None + self, + job_id: str, + *, + after_seq: int | None = None, ) -> Subscription | None: """SSE subscribe: get replay buffer + live events stream.""" with self._lock: @@ -497,9 +479,7 @@ class JobManager: self._job.error = self._job.error or "process exited" self._job.finished_at = time.time() event_type = ( - EVENT_JOB_CANCELLED - if self._job.status == "cancelled" - else EVENT_JOB_ERROR + EVENT_JOB_CANCELLED if self._job.status == "cancelled" else EVENT_JOB_ERROR ) self._emit( { @@ -566,7 +546,6 @@ class JobManager: return try: from auth import storage # deferred: avoids circular import - storage.revoke_internal_api_key(int(key_id)) except Exception: pass diff --git a/studio/backend/core/data_recipe/jobs/parse.py b/studio/backend/core/data_recipe/jobs/parse.py index cea6d8ea64..8ca3702edd 100644 --- a/studio/backend/core/data_recipe/jobs/parse.py +++ b/studio/backend/core/data_recipe/jobs/parse.py @@ -119,8 +119,7 @@ def parse_log_message(msg: str) -> ParsedUpdate | None: page_items = page_items, rate_remaining = int(m.group("remaining")), message = ( - f"Scraping GitHub source: {repo} " - f"{resource} page {page} (+{page_items})" + f"Scraping GitHub source: {repo} " f"{resource} page {page} (+{page_items})" ), ), ) @@ -134,10 +133,7 @@ def parse_log_message(msg: str) -> ParsedUpdate | None: source = "github", status = "rate_limited", retry_after_sec = seconds, - message = ( - "Waiting for GitHub rate limit. " - "Studio will resume automatically." - ), + message = ("Waiting for GitHub rate limit. Studio will resume automatically."), ), ) @@ -151,8 +147,7 @@ def parse_log_message(msg: str) -> ParsedUpdate | None: status = "rate_limited", retry_after_sec = seconds, message = ( - "Waiting for GitHub secondary rate limit. " - "Studio will resume automatically." + "Waiting for GitHub secondary rate limit. Studio will resume automatically." ), ), ) @@ -166,10 +161,7 @@ def parse_log_message(msg: str) -> ParsedUpdate | None: source = "github", status = "rate_limited", retry_after_sec = seconds, - message = ( - "Waiting for GitHub rate limit. " - "Studio will resume automatically." - ), + message = ("Waiting for GitHub rate limit. Studio will resume automatically."), ), ) @@ -387,15 +379,13 @@ def _apply_source_progress(job: Job, progress: SourceProgress) -> None: count_key = f"{progress.repo}:{progress.resource}" if page_key not in job._source_seen_pages: job._source_seen_pages.add(page_key) - job._source_counts[count_key] = int( - job._source_counts.get(count_key, 0) - ) + int(page_items or 0) + job._source_counts[count_key] = int(job._source_counts.get(count_key, 0)) + int( + page_items or 0 + ) fetched_items = sum(job._source_counts.values()) if fetched_items <= 0: - fetched_items = progress.fetched_items or ( - previous.fetched_items if previous else None - ) + fetched_items = progress.fetched_items or (previous.fetched_items if previous else None) estimated_total = ( progress.estimated_total @@ -415,14 +405,10 @@ def _apply_source_progress(job: Job, progress: SourceProgress) -> None: repo = progress.repo or (previous.repo if previous else None), resource = progress.resource or (previous.resource if previous else None), page = ( - progress.page - if progress.page is not None - else (previous.page if previous else None) + progress.page if progress.page is not None else (previous.page if previous else None) ), page_items = ( - page_items - if page_items is not None - else (previous.page_items if previous else None) + page_items if page_items is not None else (previous.page_items if previous else None) ), fetched_items = fetched_items, estimated_total = estimated_total, @@ -453,9 +439,7 @@ def _compute_overall_progress(job: Job, column_progress: Progress) -> Progress: if len(job._column_done) == 0: done = current_done else: - sum_done = sum( - max(0, min(value, total_rows)) for value in job._column_done.values() - ) + sum_done = sum(max(0, min(value, total_rows)) for value in job._column_done.values()) done = int(sum_done / total_columns) prev_done = int(job.progress.done or 0) diff --git a/studio/backend/core/data_recipe/jobs/worker.py b/studio/backend/core/data_recipe/jobs/worker.py index 8c5c7fe657..f59538769e 100644 --- a/studio/backend/core/data_recipe/jobs/worker.py +++ b/studio/backend/core/data_recipe/jobs/worker.py @@ -60,9 +60,7 @@ def _slugify_run_name(value: str) -> str: return slug[:80].strip("-") -def _build_dataset_name( - *, run_name: str | None, job_id: str, artifact_root: Path -) -> str: +def _build_dataset_name(*, run_name: str | None, job_id: str, artifact_root: Path) -> str: fallback = f"recipe_{job_id}" slug = _slugify_run_name(run_name or "") base_name = f"recipe_{slug}" if slug else fallback @@ -74,21 +72,14 @@ def _build_dataset_name( return candidate -def run_job_process( - *, - event_queue, - recipe: dict[str, Any], - run: dict[str, Any], -) -> None: +def run_job_process(*, event_queue, recipe: dict[str, Any], run: dict[str, Any]) -> None: """ Subprocess entrypoint. Sends events to `event_queue`. """ import os - os.environ["PYTHONWARNINGS"] = ( - "ignore" # Suppress warnings at C-level before imports - ) + os.environ["PYTHONWARNINGS"] = "ignore" # Suppress warnings at C-level before imports import warnings from loggers.config import LogConfig @@ -172,14 +163,10 @@ def run_job_process( } ) else: - results = designer.create( - builder, num_records = rows, dataset_name = dataset_name - ) + results = designer.create(builder, num_records = rows, dataset_name = dataset_name) analysis = to_jsonable(results.load_analysis().model_dump(mode = "json")) if merge_batches: - _merge_batches_to_single_parquet( - results.artifact_storage.base_dataset_path - ) + _merge_batches_to_single_parquet(results.artifact_storage.base_dataset_path) artifact_path = str(results.artifact_storage.base_dataset_path) event_queue.put( { diff --git a/studio/backend/core/data_recipe/jsonable.py b/studio/backend/core/data_recipe/jsonable.py index 8bec60cf82..5a4fcd35c3 100644 --- a/studio/backend/core/data_recipe/jsonable.py +++ b/studio/backend/core/data_recipe/jsonable.py @@ -23,7 +23,6 @@ def _pil_to_preview_payload(image: Any) -> dict[str, Any]: def _open_pil_image_from_bytes(raw_bytes: bytes): from PIL import Image # type: ignore - with Image.open(io.BytesIO(raw_bytes)) as image: return image.copy() @@ -52,7 +51,6 @@ def _to_pil_from_hf_image_dict(value: Any) -> Any | None: if isinstance(path_value, str) and path_value.strip(): try: from PIL import Image # type: ignore - with Image.open(Path(path_value)) as image: return image.copy() except (OSError, ValueError, TypeError): diff --git a/studio/backend/core/data_recipe/local_callable_validators.py b/studio/backend/core/data_recipe/local_callable_validators.py index 44459e88c5..a40261fa92 100644 --- a/studio/backend/core/data_recipe/local_callable_validators.py +++ b/studio/backend/core/data_recipe/local_callable_validators.py @@ -81,9 +81,7 @@ def split_oxc_local_callable_validators( def register_oxc_local_callable_validators( - *, - builder, - specs: list[OxcLocalCallableValidatorSpec], + *, builder, specs: list[OxcLocalCallableValidatorSpec] ) -> None: if not specs: return @@ -114,10 +112,7 @@ def register_oxc_local_callable_validators( ) -def _parse_oxc_spec( - *, - column: dict[str, Any], -) -> OxcLocalCallableValidatorSpec | None: +def _parse_oxc_spec(*, column: dict[str, Any]) -> OxcLocalCallableValidatorSpec | None: if str(column.get("column_type") or "").strip() != "validation": return None if str(column.get("validator_type") or "").strip() != "local_callable": @@ -138,11 +133,7 @@ def _parse_oxc_spec( target_columns_raw = column.get("target_columns") target_columns = ( - [ - value.strip() - for value in target_columns_raw - if isinstance(value, str) and value.strip() - ] + [value.strip() for value in target_columns_raw if isinstance(value, str) and value.strip()] if isinstance(target_columns_raw, list) else [] ) @@ -182,9 +173,7 @@ def _parse_oxc_validation_marker(fn_name: str) -> tuple[str, str, str]: return "javascript", "syntax", "auto" code_lang = parts[0] if parts[0] in _OXC_LANG_TO_NODE_LANG else "javascript" mode = parts[1] if parts[1] in _OXC_VALIDATION_MODES else "syntax" - code_shape = ( - parts[2] if len(parts) >= 3 and parts[2] in _OXC_CODE_SHAPES else "auto" - ) + code_shape = parts[2] if len(parts) >= 3 and parts[2] in _OXC_CODE_SHAPES else "auto" return code_lang, mode, code_shape @@ -205,10 +194,7 @@ def _build_oxc_validation_function(lang: str, validation_mode: str, code_shape: code_values = ( ["" for _ in range(row_count)] if not code_column - else [ - "" if value is None else str(value) - for value in df[code_column].tolist() - ] + else ["" if value is None else str(value) for value in df[code_column].tolist()] ) results = _run_oxc_batch( @@ -224,16 +210,14 @@ def _build_oxc_validation_function(lang: str, validation_mode: str, code_shape: ) return pd.DataFrame(results) - _validator.__name__ = f"{OXC_VALIDATION_FN_MARKER}_{node_lang}_{mode.replace('+', '_')}_{normalized_code_shape}" + _validator.__name__ = ( + f"{OXC_VALIDATION_FN_MARKER}_{node_lang}_{mode.replace('+', '_')}_{normalized_code_shape}" + ) return _validator def _run_oxc_batch( - *, - node_lang: str, - validation_mode: str, - code_shape: str, - code_values: list[str], + *, node_lang: str, validation_mode: str, code_shape: str, code_values: list[str] ) -> list[dict[str, Any]]: if not _OXC_RUNNER_PATH.exists(): return _fallback_results( @@ -308,21 +292,13 @@ def _run_oxc_batch( warning_count_raw = item.get("warning_count") out.append( { - "is_valid": bool(is_valid_raw) - if isinstance(is_valid_raw, bool) - else False, - "error_count": int(error_count_raw) - if isinstance(error_count_raw, int) - else 0, + "is_valid": bool(is_valid_raw) if isinstance(is_valid_raw, bool) else False, + "error_count": int(error_count_raw) if isinstance(error_count_raw, int) else 0, "error_message": str(message_raw or ""), - "severity": str(severity_raw) - if isinstance(severity_raw, str) - else None, + "severity": str(severity_raw) if isinstance(severity_raw, str) else None, "code": str(code_raw) if isinstance(code_raw, str) else None, "labels": labels_raw if isinstance(labels_raw, list) else [], - "codeframe": str(codeframe_raw) - if isinstance(codeframe_raw, str) - else None, + "codeframe": str(codeframe_raw) if isinstance(codeframe_raw, str) else None, "warning_count": int(warning_count_raw) if isinstance(warning_count_raw, int) else 0, diff --git a/studio/backend/core/data_recipe/service.py b/studio/backend/core/data_recipe/service.py index 85b567885f..cb5901f04e 100644 --- a/studio/backend/core/data_recipe/service.py +++ b/studio/backend/core/data_recipe/service.py @@ -22,9 +22,7 @@ def _encode_bytes_to_base64(value: bytes | bytearray) -> str: return base64.b64encode(bytes(value)).decode("utf-8") -def _load_image_file_to_base64( - path_value: str, *, base_path: str | None = None -) -> str | None: +def _load_image_file_to_base64(path_value: str, *, base_path: str | None = None) -> str | None: try: path = Path(path_value) candidates: list[Path] = [] @@ -119,9 +117,7 @@ def _apply_data_designer_image_context_patch() -> None: original_auto_resolve = ImageContext._auto_resolve_context_value - def _patched_auto_resolve( - self: Any, context_value: Any, base_path: str | None - ) -> Any: + def _patched_auto_resolve(self: Any, context_value: Any, base_path: str | None) -> Any: normalized = _normalize_image_context_value(context_value, base_path = base_path) return original_auto_resolve(self, normalized, base_path) @@ -163,17 +159,12 @@ def _recipe_has_llm_columns(recipe: dict[str, Any]) -> bool: return False -def _validate_recipe_runtime_support( - recipe: dict[str, Any], - model_providers: list[Any], -) -> None: +def _validate_recipe_runtime_support(recipe: dict[str, Any], model_providers: list[Any]) -> None: if _recipe_has_llm_columns(recipe) and not model_providers: raise ValueError("Add a Provider connection block before running this recipe.") -def build_mcp_providers( - recipe: dict[str, Any], -) -> list: +def build_mcp_providers(recipe: dict[str, Any]) -> list: from data_designer.config.mcp import LocalStdioMCPProvider, MCPProvider # pyright: ignore[reportMissingImports] # Same gate as the chat MCP path: stdio providers spawn a local subprocess, @@ -259,9 +250,7 @@ def build_config_builder(recipe: dict[str, Any]): if key not in {"model_providers", "mcp_providers"} } recipe_core = _strip_frontend_model_config_metadata(recipe_core) - recipe_core, oxc_local_callable_specs = split_oxc_local_callable_validators( - recipe_core - ) + recipe_core, oxc_local_callable_specs = split_oxc_local_callable_validators(recipe_core) builder = DataDesignerConfigBuilder.from_config({"data_designer": recipe_core}) register_oxc_local_callable_validators( builder = builder, @@ -285,11 +274,7 @@ def build_config_builder(recipe: dict[str, Any]): return builder -def create_data_designer( - recipe: dict[str, Any], - *, - artifact_path: str | None = None, -): +def create_data_designer(recipe: dict[str, Any], *, artifact_path: str | None = None): _apply_data_designer_image_context_patch() from data_designer.interface.data_designer import DataDesigner # pyright: ignore[reportMissingImports] @@ -302,7 +287,6 @@ def create_data_designer( # so sampler/expression-only recipes can run without a real provider. if not model_providers: from data_designer.config.models import ModelProvider # pyright: ignore[reportMissingImports] - model_providers = [ ModelProvider( name = "_unused", @@ -326,8 +310,7 @@ def validate_recipe(recipe: dict[str, Any]) -> None: def preview_recipe( - recipe: dict[str, Any], - num_records: int, + recipe: dict[str, Any], num_records: int ) -> tuple[list[dict[str, Any]], dict[str, Any] | None, dict[str, Any] | None]: builder = build_config_builder(recipe) designer = create_data_designer(recipe) @@ -339,14 +322,10 @@ def preview_recipe( dataset = [to_jsonable(row) for row in raw_rows] artifacts = ( - None - if results.processor_artifacts is None - else to_jsonable(results.processor_artifacts) + None if results.processor_artifacts is None else to_jsonable(results.processor_artifacts) ) analysis = ( - None - if results.analysis is None - else to_jsonable(results.analysis.model_dump(mode = "json")) + None if results.analysis is None else to_jsonable(results.analysis.model_dump(mode = "json")) ) return dataset, artifacts, analysis diff --git a/studio/backend/core/export/export.py b/studio/backend/core/export/export.py index 7cabd382eb..e74dc13e8a 100644 --- a/studio/backend/core/export/export.py +++ b/studio/backend/core/export/export.py @@ -58,16 +58,11 @@ def _apply_wsl_sudo_patch(): import unsloth_zoo.llama_cpp as llama_cpp_module def _wsl_do_we_need_sudo(system_type = "debian"): - logger.info( - "WSL detected — skipping sudo check " - "(build deps pre-installed by setup.sh)" - ) + logger.info("WSL detected — skipping sudo check (build deps pre-installed by setup.sh)") return False llama_cpp_module.do_we_need_sudo = _wsl_do_we_need_sudo - logger.info( - "Applied WSL sudo patch to " "unsloth_zoo.llama_cpp.do_we_need_sudo" - ) + logger.info("Applied WSL sudo patch to unsloth_zoo.llama_cpp.do_we_need_sudo") except Exception as e: logger.warning(f"Could not apply WSL sudo patch: {e}") @@ -146,7 +141,6 @@ class ExportBackend: List of tuples: [(model_name, [(display_name, checkpoint_path), ...]), ...] """ from utils.models.checkpoints import scan_checkpoints - return scan_checkpoints(outputs_dir = outputs_dir) def load_checkpoint( @@ -224,7 +218,6 @@ class ExportBackend: elif self._audio_type == "bicodec": from unsloth import FastModel - logger.info("Loading as BiCodec (Spark-TTS) audio model...") model, tokenizer = FastModel.from_pretrained( model_name = checkpoint_path, @@ -236,7 +229,6 @@ class ExportBackend: elif self._audio_type == "dac": from unsloth import FastModel - logger.info("Loading as DAC (OuteTTS) audio model...") model, tokenizer = FastModel.from_pretrained( model_name = checkpoint_path, @@ -348,9 +340,7 @@ class ExportBackend: output_path: Optional[str] = None try: if _IS_MLX: - mlx_save_method = ( - "merged_4bit" if format_type == "4-bit (FP4)" else "merged_16bit" - ) + mlx_save_method = "merged_4bit" if format_type == "4-bit (FP4)" else "merged_16bit" else: if format_type == "4-bit (FP4)": save_method = "merged_4bit_forced" @@ -415,9 +405,7 @@ class ExportBackend: private = private, ) else: - hub_save_method = ( - save_method if save_method is not None else "merged_16bit" - ) + hub_save_method = save_method if save_method is not None else "merged_16bit" self.current_model.push_to_hub_merged( repo_id, self.current_tokenizer, @@ -523,9 +511,7 @@ class ExportBackend: else: # Get base model name from request or model config base_model = ( - base_model_id - or self.current_model.config._name_or_path - or "unknown" + base_model_id or self.current_model.config._name_or_path or "unknown" ) # Create repo @@ -547,9 +533,7 @@ class ExportBackend: extra = "unsloth", ) card = ModelCard(content) - card.push_to_hub( - repo_id, token = hf_token, commit_message = "Unsloth Model Card" - ) + card.push_to_hub(repo_id, token = hf_token, commit_message = "Unsloth Model Card") # Upload model files if save_directory: @@ -614,10 +598,7 @@ class ExportBackend: LLAMA_CPP_DEFAULT_DIR, _resolve_local_convert_script, # noqa: F401 ) - - os.environ.setdefault( - "UNSLOTH_LLAMA_CPP_SCRIPTS_DIR", LLAMA_CPP_DEFAULT_DIR - ) + os.environ.setdefault("UNSLOTH_LLAMA_CPP_SCRIPTS_DIR", LLAMA_CPP_DEFAULT_DIR) except ImportError: if not _LLAMA_CPP_SCRIPTS_WARNING_EMITTED: logger.warning( @@ -663,15 +644,11 @@ class ExportBackend: # Relocate GGUF artifacts into the export directory. # convert_to_gguf writes .gguf files to cwd (repo root) # because --outfile is a relative path like "model.Q4_K_M.gguf". - new_ggufs = ( - set(glob.glob(os.path.join(cwd, "*.gguf"))) - pre_existing_ggufs - ) + new_ggufs = set(glob.glob(os.path.join(cwd, "*.gguf"))) - pre_existing_ggufs for src in sorted(new_ggufs): dest = os.path.join(abs_save_dir, os.path.basename(src)) shutil.move(src, dest) - logger.info( - f"Relocated GGUF: {os.path.basename(src)} → {abs_save_dir}/" - ) + logger.info(f"Relocated GGUF: {os.path.basename(src)} → {abs_save_dir}/") # Flatten any .gguf files from subdirectories into abs_save_dir. # save_pretrained_gguf may create subdirs (e.g. model_gguf/) @@ -701,9 +678,7 @@ class ExportBackend: # Also relocate Ollama Modelfile if present modelfile = gguf_dir / "Modelfile" if modelfile.is_file(): - shutil.move( - str(modelfile), os.path.join(abs_save_dir, "Modelfile") - ) + shutil.move(str(modelfile), os.path.join(abs_save_dir, "Modelfile")) logger.info(f"Relocated Modelfile → {abs_save_dir}/") shutil.rmtree(str(gguf_dir), ignore_errors = True) logger.info(f"Cleaned up intermediate GGUF dir: {gguf_dir}") @@ -814,12 +789,8 @@ class ExportBackend: repo_type = "model", ) else: - self.current_model.push_to_hub( - repo_id, token = hf_token, private = private - ) - self.current_tokenizer.push_to_hub( - repo_id, token = hf_token, private = private - ) + self.current_model.push_to_hub(repo_id, token = hf_token, private = private) + self.current_tokenizer.push_to_hub(repo_id, token = hf_token, private = private) logger.info(f"Adapter pushed successfully to {repo_id}") return True, "LoRA adapter exported successfully", output_path diff --git a/studio/backend/core/export/orchestrator.py b/studio/backend/core/export/orchestrator.py index 82de925592..90a946163e 100644 --- a/studio/backend/core/export/orchestrator.py +++ b/studio/backend/core/export/orchestrator.py @@ -261,7 +261,11 @@ class ExportOrchestrator: except (EOFError, OSError, ValueError): return None - def _wait_response(self, expected_type: str, timeout: float = 3600.0) -> dict: + def _wait_response( + self, + expected_type: str, + timeout: float = 3600.0, + ) -> dict: """Block until a response of the expected type arrives. Export operations can take a very long time — GGUF conversion for @@ -318,9 +322,7 @@ class ExportOrchestrator: expected_type, ) - raise RuntimeError( - f"Timeout waiting for '{expected_type}' response after {timeout}s" - ) + raise RuntimeError(f"Timeout waiting for '{expected_type}' response after {timeout}s") def _drain_queue(self) -> list: """Drain all pending responses.""" @@ -371,9 +373,7 @@ class ExportOrchestrator: elif self._proc is not None: self._shutdown_subprocess(timeout = 2) - logger.info( - "Spawning fresh export subprocess for '%s'", checkpoint_path - ) + logger.info("Spawning fresh export subprocess for '%s'", checkpoint_path) self._spawn_subprocess(sub_config) try: @@ -485,9 +485,7 @@ class ExportOrchestrator: }, ) - def _run_export( - self, export_type: str, params: dict - ) -> Tuple[bool, str, Optional[str]]: + def _run_export(self, export_type: str, params: dict) -> Tuple[bool, str, Optional[str]]: """Send an export command to the subprocess and wait for result. Returns ``(success, message, output_path)``. ``output_path`` is the @@ -554,12 +552,9 @@ class ExportOrchestrator: finally: self._export_active = False - def scan_checkpoints( - self, outputs_dir: str = str(outputs_root()) - ) -> List[Tuple[str, list]]: + def scan_checkpoints(self, outputs_dir: str = str(outputs_root())) -> List[Tuple[str, list]]: """Scan for checkpoints — no ML imports needed, runs locally.""" from utils.models.checkpoints import scan_checkpoints - return scan_checkpoints(outputs_dir = outputs_dir) diff --git a/studio/backend/core/export/worker.py b/studio/backend/core/export/worker.py index defcff924b..405956ec9d 100644 --- a/studio/backend/core/export/worker.py +++ b/studio/backend/core/export/worker.py @@ -362,12 +362,7 @@ def _handle_cleanup(backend, resp_queue: Any) -> None: ) -def run_export_process( - *, - cmd_queue: Any, - resp_queue: Any, - config: dict, -) -> None: +def run_export_process(*, cmd_queue: Any, resp_queue: Any, config: dict) -> None: """Subprocess entrypoint. Persistent — runs command loop until shutdown. Args: @@ -383,9 +378,7 @@ def run_export_process( _setup_log_capture(resp_queue) os.environ["TOKENIZERS_PARALLELISM"] = "false" - os.environ["PYTHONWARNINGS"] = ( - "ignore" # Suppress warnings at C-level before imports - ) + os.environ["PYTHONWARNINGS"] = "ignore" # Suppress warnings at C-level before imports # Force unbuffered output from any child Python process (e.g. the # GGUF converter) so their prints surface in the log stream as they # happen rather than at the end. @@ -430,7 +423,6 @@ def run_export_process( if sys.platform == "win32": try: import triton # noqa: F401 - logger.info("Triton available — torch.compile enabled") except ImportError: os.environ["TORCHDYNAMO_DISABLE"] = "1" @@ -467,9 +459,7 @@ def run_export_process( import transformers - logger.info( - "Export subprocess loaded transformers %s", transformers.__version__ - ) + logger.info("Export subprocess loaded transformers %s", transformers.__version__) except Exception as exc: _send_response( @@ -570,9 +560,7 @@ def run_export_process( ) except Exception as exc: - logger.error( - "Error handling command '%s': %s", cmd_type, exc, exc_info = True - ) + logger.error("Error handling command '%s': %s", cmd_type, exc, exc_info = True) _send_response( resp_queue, { diff --git a/studio/backend/core/inference/anthropic_compat.py b/studio/backend/core/inference/anthropic_compat.py index cdb0fdebff..61dea5c010 100644 --- a/studio/backend/core/inference/anthropic_compat.py +++ b/studio/backend/core/inference/anthropic_compat.py @@ -42,8 +42,7 @@ def _anthropic_image_block_to_openai_part(block: dict) -> Optional[dict]: def anthropic_messages_to_openai( - messages: list[dict], - system: Optional[Union[str, list]] = None, + messages: list[dict], system: Optional[Union[str, list]] = None ) -> list[dict]: """Convert Anthropic messages + system to OpenAI-format message dicts. @@ -125,9 +124,7 @@ def anthropic_messages_to_openai( tc = b.get("content", "") if isinstance(tc, list): tc = " ".join( - p["text"] - for p in tc - if isinstance(p, dict) and p.get("type") == "text" + p["text"] for p in tc if isinstance(p, dict) and p.get("type") == "text" ) tool_results.append( { diff --git a/studio/backend/core/inference/audio_codecs.py b/studio/backend/core/inference/audio_codecs.py index df3bf27c16..e6b7f9c613 100644 --- a/studio/backend/core/inference/audio_codecs.py +++ b/studio/backend/core/inference/audio_codecs.py @@ -77,12 +77,14 @@ class AudioCodecManager: return from snac import SNAC - self._snac_model = ( - SNAC.from_pretrained("hubertsiuzdak/snac_24khz").to(device).eval() - ) + self._snac_model = SNAC.from_pretrained("hubertsiuzdak/snac_24khz").to(device).eval() logger.info("Loaded SNAC codec (24kHz)") - def _load_bicodec(self, device: str, model_repo_path: Optional[str] = None) -> None: + def _load_bicodec( + self, + device: str, + model_repo_path: Optional[str] = None, + ) -> None: if self._bicodec_tokenizer is not None: return import os @@ -90,9 +92,7 @@ class AudioCodecManager: # Clone SparkAudio/Spark-TTS GitHub repo for the sparktts Python package # (same approach as training — the HF model repos don't contain the package) - spark_code_dir = os.path.join( - os.path.dirname(model_repo_path or "."), "Spark-TTS" - ) + spark_code_dir = os.path.join(os.path.dirname(model_repo_path or "."), "Spark-TTS") sparktts_pkg = os.path.join(spark_code_dir, "sparktts") if not os.path.isdir(sparktts_pkg): logger.info(f"Cloning SparkAudio/Spark-TTS to {spark_code_dir}...") @@ -177,9 +177,7 @@ class AudioCodecManager: # ── Decoders ───────────────────────────────────────────────── - def decode_snac( - self, generated_ids: torch.Tensor, device: str - ) -> Tuple[bytes, int]: + def decode_snac(self, generated_ids: torch.Tensor, device: str) -> Tuple[bytes, int]: """ Decode SNAC tokens (Orpheus) into WAV bytes. @@ -195,9 +193,7 @@ class AudioCodecManager: cropped = generated_ids[:, token_indices[1][-1] + 1 :] else: # Gracefully fall back to using entire output if marker not found - logger.warning( - "No START_OF_SPEECH token (128257) found — using full generated output" - ) + logger.warning("No START_OF_SPEECH token (128257) found — using full generated output") cropped = generated_ids row = cropped[0] @@ -223,8 +219,7 @@ class AudioCodecManager: layer_3.append(codes[7 * i + 6] - 24576) snac_codes = [ - torch.tensor(layer).unsqueeze(0).to(device) - for layer in [layer_1, layer_2, layer_3] + torch.tensor(layer).unsqueeze(0).to(device) for layer in [layer_1, layer_2, layer_3] ] with torch.no_grad(): @@ -254,16 +249,12 @@ class AudioCodecManager: f"BiCodec decode: {len(global_matches)} global tokens, {len(semantic_matches)} semantic tokens" ) if len(global_matches) < 10: - logger.info( - f"BiCodec generated text (first 500 chars): {generated_text[:500]}" - ) + logger.info(f"BiCodec generated text (first 500 chars): {generated_text[:500]}") if not semantic_matches: raise ValueError("No bicodec_semantic tokens found in generated output") - semantic_ids = ( - torch.tensor([int(t) for t in semantic_matches]).long().unsqueeze(0) - ) + semantic_ids = torch.tensor([int(t) for t in semantic_matches]).long().unsqueeze(0) # Speaker encoder expects exactly 32 global tokens (token_num=32 in BiCodec config). # Pad with zeros or truncate to 32. diff --git a/studio/backend/core/inference/chat_template_helpers.py b/studio/backend/core/inference/chat_template_helpers.py index 833a714ee4..c70e9b3c53 100644 --- a/studio/backend/core/inference/chat_template_helpers.py +++ b/studio/backend/core/inference/chat_template_helpers.py @@ -55,6 +55,4 @@ def apply_chat_template_for_generation( break if last_exc is not None: raise last_exc - raise RuntimeError( - "apply_chat_template_for_generation: no attempt produced a result" - ) + raise RuntimeError("apply_chat_template_for_generation: no attempt produced a result") diff --git a/studio/backend/core/inference/external_provider.py b/studio/backend/core/inference/external_provider.py index 8a1edd608b..3142434d09 100644 --- a/studio/backend/core/inference/external_provider.py +++ b/studio/backend/core/inference/external_provider.py @@ -65,9 +65,7 @@ def _is_openai_family_cloud(base_url: Optional[str]) -> bool: return host == "api.openai.com" or host.endswith(".openai.azure.com") -_ANTHROPIC_4_7_SAMPLING_REMOVED = re.compile( - r"^claude-(?:opus|sonnet|haiku)-4-7(?:[-.]|$)" -) +_ANTHROPIC_4_7_SAMPLING_REMOVED = re.compile(r"^claude-(?:opus|sonnet|haiku)-4-7(?:[-.]|$)") _OPENAI_REASONING_SUMMARY_UNSUPPORTED = re.compile(r"^o3(?:[-.]|$)") _OPENAI_REASONING_STATUSES = {"in_progress", "completed", "incomplete"} @@ -77,9 +75,7 @@ def _openai_image_replay_requires_reasoning(model: str) -> bool: return normalized.startswith("gpt-5") or normalized.startswith("o") -def _sanitize_openai_reasoning_replay_item( - item: Any, -) -> Optional[dict[str, Any]]: +def _sanitize_openai_reasoning_replay_item(item: Any) -> Optional[dict[str, Any]]: """Return a Responses input-safe reasoning item, if ``item`` is one. OpenAI's image-generation docs allow follow-up edits by sending the @@ -128,9 +124,7 @@ _OPENAI_CITATION_MARKER = re.compile( ) -def _build_citation_lookup( - url_citations: list[dict[str, Any]], -) -> dict[str, tuple[int, str]]: +def _build_citation_lookup(url_citations: list[dict[str, Any]]) -> dict[str, tuple[int, str]]: """Map every known ``source_id`` alias to ``(citation_index, url)``. Accepts singular ``source_id`` and plural ``source_ids``. First-seen @@ -153,10 +147,7 @@ def _build_citation_lookup( return by_source -def _replace_openai_citation_markers( - text: str, - url_citations: list[dict[str, Any]], -) -> str: +def _replace_openai_citation_markers(text: str, url_citations: list[dict[str, Any]]) -> str: """Rewrite `\\ue200cite\\ue202SOURCE_ID[\\ue202LOCATOR]\\ue201` markers into `[[N]](URL)` per resolvable id. Multi-source markers expand to one link per id; unresolved tokens drop silently. Idempotent on text without @@ -185,8 +176,7 @@ def _replace_openai_citation_markers( def _rewrite_citation_markers_partial( - text: str, - url_citations: list[dict[str, Any]], + text: str, url_citations: list[dict[str, Any]] ) -> tuple[str, bool]: """Like ``_replace_openai_citation_markers`` but also reports whether any marker referenced a source_id not yet in ``url_citations``. @@ -366,9 +356,7 @@ def _anthropic_supports_compaction(model: str) -> bool: def _anthropic_supports_fast_mode(model: str) -> bool: # Require a family boundary ("" or "-") after the prefix so IDs like # "claude-opus-4-70" / "claude-opus-4-7b" do not match. - return any( - model == p or model.startswith(f"{p}-") for p in _ANTHROPIC_FAST_MODE_PREFIXES - ) + return any(model == p or model.startswith(f"{p}-") for p in _ANTHROPIC_FAST_MODE_PREFIXES) # Cap on ``cited_text`` forwarded in document_citations tool_events; @@ -632,9 +620,7 @@ def _safe_fetch_image_for_gemini_sync( if rp_info is None: return None _rp, current_host, current_port = rp_info - ok2, reason2, pinned_ip = _validate_and_resolve_host( - current_host, current_port - ) + ok2, reason2, pinned_ip = _validate_and_resolve_host(current_host, current_port) if not ok2: logger.warning( "Gemini image fetch: refusing redirect host=%s reason=%s", @@ -654,13 +640,9 @@ def _safe_fetch_image_for_gemini_sync( with resp: status = getattr(resp, "status", None) or resp.getcode() if status != 200: - logger.info( - "Gemini image fetch: status=%s host=%s", status, current_host - ) + logger.info("Gemini image fetch: status=%s host=%s", status, current_host) return None - _hdr_mime = ( - (resp.headers.get("content-type") or "").split(";")[0].strip().lower() - ) + _hdr_mime = (resp.headers.get("content-type") or "").split(";")[0].strip().lower() # Declared non-image MIME is a refusal; missing MIME falls back to caller's. if _hdr_mime and not _hdr_mime.startswith("image/"): logger.info( @@ -670,9 +652,7 @@ def _safe_fetch_image_for_gemini_sync( ) return None _final_mime_pre = _hdr_mime if _hdr_mime else fallback_mime - if not isinstance(_final_mime_pre, str) or not _final_mime_pre.startswith( - "image/" - ): + if not isinstance(_final_mime_pre, str) or not _final_mime_pre.startswith("image/"): logger.info( "Gemini image fetch: missing content-type and no image fallback host=%s", current_host, @@ -715,10 +695,7 @@ async def _safe_fetch_image_for_gemini( rejected up front. """ import asyncio - - return await asyncio.to_thread( - _safe_fetch_image_for_gemini_sync, url, fallback_mime, max_bytes - ) + return await asyncio.to_thread(_safe_fetch_image_for_gemini_sync, url, fallback_mime, max_bytes) # Synthetic-tool names stamped onto outbound _toolEvent.arguments so the @@ -753,9 +730,7 @@ def _stamp_server_tool_marker(payload: dict[str, Any]) -> None: def _build_kimi_tool_end( - synthetic_chunk_fn: Any, - tool_call_id: str, - citations: list[dict[str, str]], + synthetic_chunk_fn: Any, tool_call_id: str, citations: list[dict[str, str]] ) -> str: """Format Kimi web_search citations into the tool_end payload. @@ -798,10 +773,10 @@ class ExternalProviderClient: if self.provider_type == "gemini": _parsed_base = urlparse(self.base_url) if ( - (_parsed_base.hostname or "").lower() - == "generativelanguage.googleapis.com" - and _parsed_base.path.rstrip("/") == "/v1beta/openai" - ): + _parsed_base.hostname or "" + ).lower() == "generativelanguage.googleapis.com" and _parsed_base.path.rstrip( + "/" + ) == "/v1beta/openai": self.base_url = self.base_url[: -len("/openai")] self.api_key = api_key self._timeout = httpx.Timeout(timeout, connect = 10.0) @@ -1018,9 +993,7 @@ class ExternalProviderClient: else: body["thinking"] = {"type": "disabled"} elif self.provider_type == "mistral": - _apply_mistral_reasoning_controls( - body, model, enable_thinking, reasoning_effort - ) + _apply_mistral_reasoning_controls(body, model, enable_thinking, reasoning_effort) elif self.provider_type == "vllm" and enable_thinking is not None: # vLLM gates thinking via chat_template_kwargs.enable_thinking. tpl_kw = body.get("chat_template_kwargs") @@ -1061,9 +1034,7 @@ class ExternalProviderClient: and "web_search" in enabled_tools ): plugins = list(body.get("plugins") or []) - if not any( - isinstance(p, dict) and p.get("id") == "web" for p in plugins - ): + if not any(isinstance(p, dict) and p.get("id") == "web" for p in plugins): plugins.append({"id": "web"}) body["plugins"] = plugins logger.info( @@ -1110,9 +1081,7 @@ class ExternalProviderClient: response.status_code, error_text[:500], ) - yield _error_sse_line( - response.status_code, error_text, self.provider_type - ) + yield _error_sse_line(response.status_code, error_text, self.provider_type) return # Manual __anext__ (not `async for`) so we can close @@ -1193,11 +1162,7 @@ class ExternalProviderClient: { "type": "tool_end", "tool_call_id": web_search_tool_id, - "result": ( - "\n---\n".join(blocks) - if blocks - else "(search complete)" - ), + "result": ("\n---\n".join(blocks) if blocks else "(search complete)"), } ) @@ -1245,18 +1210,14 @@ class ExternalProviderClient: # in particular returns 200 then surfaces the # actual failure as an SSE error event. if "error" in parsed: - event_counts["error"] = ( - event_counts.get("error", 0) + 1 - ) + event_counts["error"] = event_counts.get("error", 0) + 1 logger.warning( "%s SSE error event: %s", self.provider_type, parsed.get("error"), ) else: - event_counts["delta"] = ( - event_counts.get("delta", 0) + 1 - ) + event_counts["delta"] = event_counts.get("delta", 0) + 1 # OpenRouter (and most OAI-compat providers) # report the underlying model that handled # the request in every chunk's `model` field. @@ -1284,20 +1245,13 @@ class ExternalProviderClient: ): if not isinstance(envelope, dict): continue - for ann in ( - envelope.get("annotations") - or [] - ): + for ann in envelope.get("annotations") or []: _record_or_url_citation(ann) yield line # Stream ended without [DONE] (some upstreams just close # the connection). Emit tool_end so the card doesn't # stay in "running" forever. - if ( - web_search_active - and web_search_tool_started - and not web_search_tool_ended - ): + if web_search_active and web_search_tool_started and not web_search_tool_ended: yield _build_web_search_tool_end() web_search_tool_ended = True except GeneratorExit: @@ -1341,10 +1295,7 @@ class ExternalProviderClient: ) async def _stream_kimi_web_search( - self, - messages: list[dict[str, Any]], - model: str, - max_tokens: Optional[int], + self, messages: list[dict[str, Any]], model: str, max_tokens: Optional[int] ) -> AsyncGenerator[str, None]: """ Kimi $web_search round-trip. @@ -1377,9 +1328,7 @@ class ExternalProviderClient: # $web_search forbids thinking; sending the toggle silently # would have the server reject the request with 400. "thinking": {"type": "disabled"}, - "tools": [ - {"type": "builtin_function", "function": {"name": "$web_search"}} - ], + "tools": [{"type": "builtin_function", "function": {"name": "$web_search"}}], } if max_tokens is not None: body["max_tokens"] = max_tokens @@ -1429,9 +1378,7 @@ class ExternalProviderClient: response.status_code, error_text[:500], ) - yield _error_sse_line( - response.status_code, error_text, self.provider_type - ) + yield _error_sse_line(response.status_code, error_text, self.provider_type) return lines_gen = response.aiter_lines().__aiter__() @@ -1496,14 +1443,11 @@ class ExternalProviderClient: # of every other provider when web_search is on but the model # didn't actually need it. search_calls = [ - tc - for tc in tool_calls_acc.values() - if tc["function"]["name"] == "$web_search" + tc for tc in tool_calls_acc.values() if tc["function"]["name"] == "$web_search" ] if not search_calls: logger.info( - "Kimi $web_search: model did not invoke search; " - "falling back to plain stream" + "Kimi $web_search: model did not invoke search; falling back to plain stream" ) fallback_body = dict(body) fallback_body.pop("tools", None) @@ -1523,9 +1467,7 @@ class ExternalProviderClient: response.status_code, error_text[:500], ) - yield _error_sse_line( - response.status_code, error_text, self.provider_type - ) + yield _error_sse_line(response.status_code, error_text, self.provider_type) return # Manual __anext__ loop instead of `async for` — see the # comment in stream_chat_completion for the Python 3.13 + @@ -1641,9 +1583,7 @@ class ExternalProviderClient: response.status_code, error_text[:500], ) - yield _error_sse_line( - response.status_code, error_text, self.provider_type - ) + yield _error_sse_line(response.status_code, error_text, self.provider_type) return lines_gen = response.aiter_lines().__aiter__() @@ -1686,9 +1626,7 @@ class ExternalProviderClient: ): if not isinstance(envelope, dict): continue - for ann in ( - envelope.get("annotations") or [] - ): + for ann in envelope.get("annotations") or []: if isinstance(ann, dict): annotation_shapes.add( str(ann.get("type") or "?") @@ -1758,9 +1696,7 @@ class ExternalProviderClient: system = ( content if isinstance(content, str) - else "\n".join( - p["text"] for p in content if p.get("type") == "text" - ) + else "\n".join(p["text"] for p in content if p.get("type") == "text") ) continue @@ -1823,18 +1759,13 @@ class ExternalProviderClient: # https://platform.claude.com/docs/en/build-with-claude/compaction summary = part.get("content") or "" if isinstance(summary, str) and summary: - anthropic_parts.append( - {"type": "compaction", "content": summary} - ) + anthropic_parts.append({"type": "compaction", "content": summary}) elif part.get("type") == "image_url": url = part.get("image_url", {}).get("url", "") if url.startswith("data:"): # data:image/png;base64, -> split header and data header, _, b64data = url.partition(",") - media_type = ( - header.split(";")[0].replace("data:", "") - or "image/jpeg" - ) + media_type = header.split(";")[0].replace("data:", "") or "image/jpeg" anthropic_parts.append( { "type": "image", @@ -1918,9 +1849,7 @@ class ExternalProviderClient: # Messages API does not accept OpenAI's top-level # `tool_calls` field; the call lives inside a content # block with `{type:"tool_use", id, name, input}`. - if msg.get("role") == "assistant" and isinstance( - msg.get("tool_calls"), list - ): + if msg.get("role") == "assistant" and isinstance(msg.get("tool_calls"), list): for _tc in msg["tool_calls"]: if not isinstance(_tc, dict): continue @@ -1929,9 +1858,7 @@ class ExternalProviderClient: continue _raw = _fn.get("arguments") or "{}" try: - _input = ( - _json.loads(_raw) if isinstance(_raw, str) else _raw - ) + _input = _json.loads(_raw) if isinstance(_raw, str) else _raw except Exception: _input = {"_raw": _raw} if not isinstance(_input, dict): @@ -1999,9 +1926,7 @@ class ExternalProviderClient: continue _raw = _fn.get("arguments") or "{}" try: - _input = ( - _json.loads(_raw) if isinstance(_raw, str) else _raw - ) + _input = _json.loads(_raw) if isinstance(_raw, str) else _raw except Exception: _input = {"_raw": _raw} if not isinstance(_input, dict): @@ -2097,18 +2022,14 @@ class ExternalProviderClient: last_msg["content"] = head thinking_spec = _anthropic_thinking_spec(model) allowed_efforts = ( - thinking_spec.efforts - if thinking_spec - else ("none", "low", "medium", "high") + thinking_spec.efforts if thinking_spec else ("none", "low", "medium", "high") ) effort = reasoning_effort if reasoning_effort in allowed_efforts else None # Claude 4.6 Opus/Sonnet accept top-tier adaptive effort as "max" only; # "xhigh" is rejected (supported on Claude 4.7). Map our shared "xhigh" # semantic to "max" for 4.6 outbound requests while still accepting # both in ``allowed_efforts`` for persisted / cross-provider UI state. - if effort == "xhigh" and model.startswith( - ("claude-opus-4-6", "claude-sonnet-4-6") - ): + if effort == "xhigh" and model.startswith(("claude-opus-4-6", "claude-sonnet-4-6")): effort = "max" if effort is None: if enable_thinking is False: @@ -2170,17 +2091,12 @@ class ExternalProviderClient: and bool(tool_choice["function"].get("name")) ) _anthropic_hosted_builtins_allowed = ( - not _anthropic_tool_choice_disabled - and not _anthropic_tool_choice_forced_function + not _anthropic_tool_choice_disabled and not _anthropic_tool_choice_forced_function ) # Anthropic web_search (date-pinned per model family). # https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool - if ( - _anthropic_hosted_builtins_allowed - and enabled_tools - and "web_search" in enabled_tools - ): + if _anthropic_hosted_builtins_allowed and enabled_tools and "web_search" in enabled_tools: anthropic_tools = list(body.get("tools") or []) anthropic_tools.append( { @@ -2194,9 +2110,7 @@ class ExternalProviderClient: # Anthropic web_fetch: only URLs already in conversation. Date-pinned. # https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-fetch-tool web_fetch_enabled = bool( - _anthropic_hosted_builtins_allowed - and enabled_tools - and "web_fetch" in enabled_tools + _anthropic_hosted_builtins_allowed and enabled_tools and "web_fetch" in enabled_tools ) if web_fetch_enabled: anthropic_tools = list(body.get("tools") or []) @@ -2302,9 +2216,7 @@ class ExternalProviderClient: # Merge new beta flags onto whatever the registry contributed. existing_beta = request_headers.get("anthropic-beta", "").strip() beta_parts = ( - [p.strip() for p in existing_beta.split(",") if p.strip()] - if existing_beta - else [] + [p.strip() for p in existing_beta.split(",") if p.strip()] if existing_beta else [] ) if code_execution_enabled and _ANTHROPIC_CODE_EXECUTION_BETA not in beta_parts: beta_parts.append(_ANTHROPIC_CODE_EXECUTION_BETA) @@ -2337,10 +2249,7 @@ class ExternalProviderClient: # expired / missing, emit container_invalidated so # the chat adapter clears the stored id and the # next turn falls back to auto-create. - if ( - anthropic_code_exec_container_id - and 400 <= response.status_code < 500 - ): + if anthropic_code_exec_container_id and 400 <= response.status_code < 500: lowered = error_text.lower() if "container" in lowered and ( "expired" in lowered @@ -2353,9 +2262,7 @@ class ExternalProviderClient: f"data: " f"{_json.dumps({'id': completion_id, 'object': 'chat.completion.chunk', 'choices': [{'index': 0, 'delta': {}, 'finish_reason': None}], '_toolEvent': {'type': 'container_invalidated'}})}" ) - yield _error_sse_line( - response.status_code, error_text, self.provider_type - ) + yield _error_sse_line(response.status_code, error_text, self.provider_type) return # NOTE: same manual __anext__ loop as stream_chat_completion — see comment there. @@ -2457,9 +2364,7 @@ class ExternalProviderClient: } return f"data: {_json.dumps(chunk)}" - def _format_web_search_results( - results: list[Any], - ) -> str: + def _format_web_search_results(results: list[Any]) -> str: blocks: list[str] = [] for r in results: if not isinstance(r, dict): @@ -2506,11 +2411,7 @@ class ExternalProviderClient: # Inline a short text preview so the source # pill carries usable context; skip for PDFs # since the body is base64-encoded. - if ( - media_type.startswith("text/") - and isinstance(data, str) - and data - ): + if media_type.startswith("text/") and isinstance(data, str) and data: snippet = data[:240].strip() # Frontend parseSourcesFromResult only emits a source # pill when both `Title:` and `URL:` are present, so @@ -2527,9 +2428,7 @@ class ExternalProviderClient: parts.append(f"Snippet: {snippet}") return "\n".join(parts) if parts else "(fetch complete)" - def _format_code_execution_result( - inner: dict[str, Any], - ) -> str: + def _format_code_execution_result(inner: dict[str, Any]) -> str: """Render an Anthropic code-execution result block as the preformatted text payload the frontend's CodeExecutionToolUI displays inside a
. Handles
@@ -2560,9 +2459,7 @@ class ExternalProviderClient:
                         if "lines" in inner and isinstance(inner.get("lines"), list):
                             return "\n".join(str(line) for line in inner["lines"])
                         if "is_file_update" in inner:
-                            return (
-                                "Updated" if inner.get("is_file_update") else "Created"
-                            )
+                            return "Updated" if inner.get("is_file_update") else "Created"
                         content_field = inner.get("content")
                         if isinstance(content_field, str):
                             return content_field
@@ -2611,10 +2508,7 @@ class ExternalProviderClient:
                             content_block = event.get("content_block") or {}
                             block_type = content_block.get("type")
                             block_name = content_block.get("name")
-                            if (
-                                block_type == "server_tool_use"
-                                and block_name == "web_search"
-                            ):
+                            if block_type == "server_tool_use" and block_name == "web_search":
                                 tool_use_id = content_block.get("id", "") or (
                                     f"ws_{len(web_search_calls)}"
                                 )
@@ -2635,14 +2529,9 @@ class ExternalProviderClient:
                                 content = content_block.get("content") or []
                                 current_result_block = {
                                     "tool_use_id": tool_use_id,
-                                    "results": list(content)
-                                    if isinstance(content, list)
-                                    else [],
+                                    "results": list(content) if isinstance(content, list) else [],
                                 }
-                            elif (
-                                block_type == "server_tool_use"
-                                and block_name == "web_fetch"
-                            ):
+                            elif block_type == "server_tool_use" and block_name == "web_fetch":
                                 tool_use_id = content_block.get("id", "") or (
                                     f"wf_{len(web_fetch_calls)}"
                                 )
@@ -2669,9 +2558,7 @@ class ExternalProviderClient:
                                     f"ce_{len(code_execution_calls)}"
                                 )
                                 kind = (
-                                    "bash"
-                                    if block_name == "bash_code_execution"
-                                    else "text_editor"
+                                    "bash" if block_name == "bash_code_execution" else "text_editor"
                                 )
                                 current_code_exec_use = {
                                     "id": tool_use_id,
@@ -2751,9 +2638,7 @@ class ExternalProviderClient:
                                 if isinstance(cit, dict):
                                     key = _anthropic_citation_key(cit)
                                     idx_for_marker: Optional[int] = None
-                                    for idx, existing in enumerate(
-                                        document_citations, start = 1
-                                    ):
+                                    for idx, existing in enumerate(document_citations, start = 1):
                                         if existing.get("_key") == key:
                                             idx_for_marker = idx
                                             break
@@ -2807,9 +2692,7 @@ class ExternalProviderClient:
                                         "type": "tool_start",
                                         "tool_name": "web_search",
                                         "tool_call_id": tool_use_id,
-                                        "arguments": (
-                                            {"query": query} if query else {}
-                                        ),
+                                        "arguments": ({"query": query} if query else {}),
                                     }
                                 )
                                 current_server_tool_use = None
@@ -2851,9 +2734,7 @@ class ExternalProviderClient:
                                 kind = current_code_exec_use["kind"]
                                 emit_args = {"kind": kind, **parsed_args}
                                 if tool_use_id in code_execution_calls:
-                                    code_execution_calls[tool_use_id]["arguments"] = (
-                                        emit_args
-                                    )
+                                    code_execution_calls[tool_use_id]["arguments"] = emit_args
                                 yield _emit_tool_event(
                                     {
                                         "type": "tool_start",
@@ -2892,17 +2773,13 @@ class ExternalProviderClient:
                                     file_blocks = inner.get("content")
                                     if isinstance(file_blocks, list):
                                         for entry in file_blocks:
-                                            if isinstance(entry, dict) and entry.get(
-                                                "file_id"
-                                            ):
+                                            if isinstance(entry, dict) and entry.get("file_id"):
                                                 code_execution_generated_files += 1
                                 result_text = _format_code_execution_result(
                                     inner if isinstance(inner, dict) else {}
                                 )
                                 if tool_use_id in code_execution_calls:
-                                    code_execution_calls[tool_use_id]["result"] = (
-                                        result_text
-                                    )
+                                    code_execution_calls[tool_use_id]["result"] = result_text
                                 yield _emit_tool_event(
                                     {
                                         "type": "tool_end",
@@ -2989,10 +2866,7 @@ class ExternalProviderClient:
                                     c_in = 0
                                     c_out = 0
                                     for it in iterations:
-                                        if (
-                                            isinstance(it, dict)
-                                            and it.get("type") == "compaction"
-                                        ):
+                                        if isinstance(it, dict) and it.get("type") == "compaction":
                                             c_in += int(it.get("input_tokens") or 0)
                                             c_out += int(it.get("output_tokens") or 0)
                                     if c_in or c_out:
@@ -3008,18 +2882,14 @@ class ExternalProviderClient:
                             # the same id to the thread record every turn.
                             delta_obj = event.get("delta") or {}
                             container_obj = delta_obj.get("container")
-                            if (
-                                isinstance(container_obj, dict)
-                                and latched_container_id is None
-                            ):
+                            if isinstance(container_obj, dict) and latched_container_id is None:
                                 probe = container_obj.get("id")
                                 if isinstance(probe, str) and probe:
                                     latched_container_id = probe
                             if (
                                 latched_container_id
                                 and not container_id_emitted
-                                and latched_container_id
-                                != anthropic_code_exec_container_id
+                                and latched_container_id != anthropic_code_exec_container_id
                             ):
                                 yield _emit_tool_event(
                                     {
@@ -3059,9 +2929,7 @@ class ExternalProviderClient:
                                         "or remove the previous turn and try "
                                         "again._"
                                     )
-                                    yield _emit_tool_event(
-                                        {"type": "anthropic_refusal"}
-                                    )
+                                    yield _emit_tool_event({"type": "anthropic_refusal"})
                                 if mapped is not None:
                                     chunk = {
                                         "id": completion_id,
@@ -3089,13 +2957,8 @@ class ExternalProviderClient:
                                 for c in document_citations:
                                     entry = {k: v for k, v in c.items() if k != "_key"}
                                     cited = entry.get("cited_text")
-                                    if (
-                                        isinstance(cited, str)
-                                        and len(cited) > _CITED_TEXT_MAX_LEN
-                                    ):
-                                        entry["cited_text"] = (
-                                            cited[:_CITED_TEXT_MAX_LEN] + "…"
-                                        )
+                                    if isinstance(cited, str) and len(cited) > _CITED_TEXT_MAX_LEN:
+                                        entry["cited_text"] = cited[:_CITED_TEXT_MAX_LEN] + "…"
                                     clean_cits.append(entry)
                                 yield _emit_tool_event(
                                     {
@@ -3114,9 +2977,7 @@ class ExternalProviderClient:
                             if usage_line:
                                 yield usage_line
                             yield "data: [DONE]"
-                            await (
-                                response.aclose()
-                            )  # set PoolByteStream._closed=True FIRST
+                            await response.aclose()  # set PoolByteStream._closed=True FIRST
                             break
                 except GeneratorExit:
                     await response.aclose()  # set PoolByteStream._closed=True FIRST
@@ -3126,18 +2987,12 @@ class ExternalProviderClient:
                     # Surface per-event-type counts + web_search summary so
                     # reports of "no reasoning panel content" / "Search
                     # didn't do anything" can be triaged at a glance.
-                    web_search_requested = bool(
-                        enabled_tools and "web_search" in enabled_tools
-                    )
+                    web_search_requested = bool(enabled_tools and "web_search" in enabled_tools)
                     web_search_invocations = len(web_search_calls)
                     total_results = sum(
                         len(sc.get("results") or []) for sc in web_search_calls.values()
                     )
-                    queries = [
-                        sc["query"]
-                        for sc in web_search_calls.values()
-                        if sc.get("query")
-                    ]
+                    queries = [sc["query"] for sc in web_search_calls.values() if sc.get("query")]
                     # cache_read_input_tokens > 0 on turn N proves the
                     # cache_control marker on the system block is doing
                     # its job — turn 1 will show cache_creation > 0
@@ -3146,15 +3001,11 @@ class ExternalProviderClient:
                     # discount.
                     code_execution_invocations = len(code_execution_calls)
                     code_execution_results = sum(
-                        1
-                        for c in code_execution_calls.values()
-                        if c.get("result") is not None
+                        1 for c in code_execution_calls.values() if c.get("result") is not None
                     )
                     web_fetch_requested = web_fetch_enabled
                     web_fetch_invocations = len(web_fetch_calls)
-                    web_fetch_urls = [
-                        wf["url"] for wf in web_fetch_calls.values() if wf.get("url")
-                    ]
+                    web_fetch_urls = [wf["url"] for wf in web_fetch_calls.values() if wf.get("url")]
                     logger.info(
                         "Anthropic stream complete (model=%s, "
                         "web_search_requested=%s, web_search_invocations=%s, "
@@ -3347,10 +3198,7 @@ class ExternalProviderClient:
                         if url.startswith("data:"):
                             header, _, b64data = url.partition(",")
                             media_type = (
-                                header.split(";")[0]
-                                .replace("data:", "")
-                                .strip()
-                                .lower()
+                                header.split(";")[0].replace("data:", "").strip().lower()
                                 or "image/jpeg"
                             )
                             # Symmetry with the fetched remote image
@@ -3368,10 +3216,7 @@ class ExternalProviderClient:
                                 # data: URLs share the same caps as fetched
                                 # URLs so inline payloads don't bypass them.
                                 _data_approx_bytes = (len(b64data) * 3) // 4
-                                if (
-                                    _remote_image_count
-                                    >= _GEMINI_REMOTE_IMAGE_MAX_COUNT
-                                ):
+                                if _remote_image_count >= _GEMINI_REMOTE_IMAGE_MAX_COUNT:
                                     logger.info(
                                         "Gemini inlineData: per-request count cap %d reached, dropping image",
                                         _GEMINI_REMOTE_IMAGE_MAX_COUNT,
@@ -3425,8 +3270,7 @@ class ExternalProviderClient:
                             _guessed, _ = mimetypes.guess_type(_img_path)
                             _media_type = (
                                 _guessed
-                                if isinstance(_guessed, str)
-                                and _guessed.startswith("image/")
+                                if isinstance(_guessed, str) and _guessed.startswith("image/")
                                 else "image/jpeg"
                             )
                             if _is_youtube:
@@ -3459,8 +3303,7 @@ class ExternalProviderClient:
                                 # byte budget is spent; pass the remainder
                                 # so over-budget URLs reject on Content-Length.
                                 _remaining_bytes = (
-                                    _GEMINI_REMOTE_IMAGE_MAX_TOTAL_BYTES
-                                    - _remote_image_total_bytes
+                                    _GEMINI_REMOTE_IMAGE_MAX_TOTAL_BYTES - _remote_image_total_bytes
                                 )
                                 if _remaining_bytes <= 0:
                                     logger.info(
@@ -3506,9 +3349,7 @@ class ExternalProviderClient:
                 if isinstance(_msg_extra, dict):
                     _msg_g = _msg_extra.get("google") or {}
                     if isinstance(_msg_g, dict):
-                        _msg_sig = _msg_g.get("thought_signature") or _msg_g.get(
-                            "thoughtSignature"
-                        )
+                        _msg_sig = _msg_g.get("thought_signature") or _msg_g.get("thoughtSignature")
                         if isinstance(_msg_sig, str) and _msg_sig:
                             for _idx in range(len(parts) - 1, -1, -1):
                                 if "text" in parts[_idx]:
@@ -3579,9 +3420,7 @@ class ExternalProviderClient:
                         and isinstance(args, dict)
                         and (
                             args.get("_server_tool") is True
-                            or isinstance(
-                                (args.get("google") or {}).get("native_part"), dict
-                            )
+                            or isinstance((args.get("google") or {}).get("native_part"), dict)
                         )
                     )
                     if _is_synthetic_server_builtin and not (
@@ -3624,9 +3463,9 @@ class ExternalProviderClient:
                         # thoughtSignature only when one subpart exists;
                         # for code+result, prefer executableCode and drop
                         # the signature elsewhere.
-                        _legacy_sig = _native_part.get(
-                            "thoughtSignature"
-                        ) or _native_part.get("thought_signature")
+                        _legacy_sig = _native_part.get("thoughtSignature") or _native_part.get(
+                            "thought_signature"
+                        )
                         _legacy_subparts = [
                             _k
                             for _k in (
@@ -3769,9 +3608,7 @@ class ExternalProviderClient:
 
         body: dict[str, Any] = {"contents": contents}
         if system_text_parts:
-            body["systemInstruction"] = {
-                "parts": [{"text": "\n\n".join(system_text_parts)}]
-            }
+            body["systemInstruction"] = {"parts": [{"text": "\n\n".join(system_text_parts)}]}
 
         # Generation config -- temperature / topP / topK / maxOutputTokens
         # map straight across. The frontend capability matrix restricts
@@ -3815,9 +3652,7 @@ class ExternalProviderClient:
             and isinstance(tool_choice.get("function"), dict)
             and bool(tool_choice["function"].get("name"))
         )
-        _hosted_builtins_allowed = (
-            not _tool_choice_disabled and not _tool_choice_forced_function
-        )
+        _hosted_builtins_allowed = not _tool_choice_disabled and not _tool_choice_forced_function
         # Image-tier model IDs reject text-only tools (code_execution,
         # user functions) and thinkingConfig regardless of whether the
         # Images pill is on -- those are model-level constraints
@@ -3828,9 +3663,7 @@ class ExternalProviderClient:
         # forwards `tools: [{codeExecution: {}}]` plus
         # `thinkingConfig` to an image model and 400s.
         image_tool_requested = bool(
-            _hosted_builtins_allowed
-            and enabled_tools
-            and "image_generation" in enabled_tools
+            _hosted_builtins_allowed and enabled_tools and "image_generation" in enabled_tools
         )
         # Strict tool / thinking strip uses the model-id check.
         is_image_model_strict = is_image_picker_model
@@ -3862,13 +3695,10 @@ class ExternalProviderClient:
             "gemini-pro-latest",
         )
         _PRO_THINKING_PREFIXES = ("gemini-2.5-pro",)
-        is_gemini3_thinking = any(
-            model_lc.startswith(p) for p in _GEMINI3_THINKING_PREFIXES
-        )
+        is_gemini3_thinking = any(model_lc.startswith(p) for p in _GEMINI3_THINKING_PREFIXES)
         is_gemini3_pro = any(model_lc.startswith(p) for p in _GEMINI3_PRO_PREFIXES)
         _is_pro_thinking_only = any(
-            model_lc == p or model_lc.startswith(p + "-")
-            for p in _PRO_THINKING_PREFIXES
+            model_lc == p or model_lc.startswith(p + "-") for p in _PRO_THINKING_PREFIXES
         )
         effort_lc = (reasoning_effort or "").strip().lower()
         if not is_image_model_strict and is_gemini3_thinking:
@@ -3945,8 +3775,7 @@ class ExternalProviderClient:
             )
 
         google_search_allowed = (
-            not is_image_model_strict
-            or _gemini_image_model_allows_google_search(model_lc)
+            not is_image_model_strict or _gemini_image_model_allows_google_search(model_lc)
         )
         code_execution_allowed = not is_image_model_strict
         text_tools_allowed = not is_image_model_strict
@@ -4001,9 +3830,7 @@ class ExternalProviderClient:
             }
         )
 
-        def _resolve_local_schema_ref(
-            root: Optional[dict[str, Any]], ref: str
-        ) -> Optional[Any]:
+        def _resolve_local_schema_ref(root: Optional[dict[str, Any]], ref: str) -> Optional[Any]:
             # Walk a `#/foo/bar` JSON pointer against the schema root.
             # Returns None if the pointer doesn't resolve to a dict, so
             # the caller can fall back to the unresolved node.
@@ -4058,9 +3885,7 @@ class ExternalProviderClient:
                             **_target,
                             **{k: v for k, v in node.items() if k != "$ref"},
                         }
-                        return _sanitize_gemini_schema(
-                            _merged, root, _seen_refs | {_ref}
-                        )
+                        return _sanitize_gemini_schema(_merged, root, _seen_refs | {_ref})
                 cleaned: dict[str, Any] = {}
                 _nullable_from_union = False
                 _flattened_type: Optional[str] = None
@@ -4076,9 +3901,7 @@ class ExternalProviderClient:
                         # Preserve multi-type unions as anyOf; flattening
                         # to the first non-null type silently drops the
                         # other branches and changes the tool contract.
-                        _union_any_of = [
-                            {"type": _t} for _t in _non_null if isinstance(_t, str)
-                        ]
+                        _union_any_of = [{"type": _t} for _t in _non_null if isinstance(_t, str)]
                 for _k, _v in node.items():
                     if _k == "type" and isinstance(_v, list):
                         # Handled below via _flattened_type.
@@ -4108,15 +3931,10 @@ class ExternalProviderClient:
                         _non_null_entries = [
                             _entry
                             for _entry in _v
-                            if not (
-                                isinstance(_entry, dict)
-                                and _entry.get("type") == "null"
-                            )
+                            if not (isinstance(_entry, dict) and _entry.get("type") == "null")
                         ]
                         if len(_non_null_entries) == 1 and _saw_null:
-                            _inner = _sanitize_gemini_schema(
-                                _non_null_entries[0], root, _seen_refs
-                            )
+                            _inner = _sanitize_gemini_schema(_non_null_entries[0], root, _seen_refs)
                             if isinstance(_inner, dict):
                                 for _ik, _iv in _inner.items():
                                     cleaned.setdefault(_ik, _iv)
@@ -4135,8 +3953,7 @@ class ExternalProviderClient:
                         cleaned[_k] = _v
                 if _union_any_of is not None and "anyOf" not in cleaned:
                     cleaned["anyOf"] = [
-                        _sanitize_gemini_schema(_s, root, _seen_refs)
-                        for _s in _union_any_of
+                        _sanitize_gemini_schema(_s, root, _seen_refs) for _s in _union_any_of
                     ]
                 elif _flattened_type is not None:
                     cleaned["type"] = _flattened_type
@@ -4178,9 +3995,7 @@ class ExternalProviderClient:
                     _mode = "NONE"
                 elif _tc_lc in ("required", "any"):
                     _mode = "ANY"
-            elif (
-                isinstance(tool_choice, dict) and tool_choice.get("type") == "function"
-            ):
+            elif isinstance(tool_choice, dict) and tool_choice.get("type") == "function":
                 _fn_pick = tool_choice.get("function") or {}
                 _name = _fn_pick.get("name") if isinstance(_fn_pick, dict) else None
                 if isinstance(_name, str) and _name:
@@ -4208,8 +4023,7 @@ class ExternalProviderClient:
         completion_id = f"chatcmpl-gemini-{model.replace('/', '-')}"
 
         logger.info(
-            "Proxying Gemini streamGenerateContent to %s (model=%s, "
-            "tools=%s, image=%s)",
+            "Proxying Gemini streamGenerateContent to %s (model=%s, tools=%s, image=%s)",
             url,
             model,
             [list(t.keys())[0] for t in tools_array] if tools_array else [],
@@ -4232,9 +4046,7 @@ class ExternalProviderClient:
             }
             return f"data: {_json.dumps(chunk)}"
 
-        def _text_chunk(
-            text: str, extra_content: Optional[dict[str, Any]] = None
-        ) -> str:
+        def _text_chunk(text: str, extra_content: Optional[dict[str, Any]] = None) -> str:
             delta: dict[str, Any] = {"content": text}
             if extra_content:
                 delta["extra_content"] = extra_content
@@ -4321,9 +4133,7 @@ class ExternalProviderClient:
                         response.status_code,
                         error_text[:500],
                     )
-                    yield _error_sse_line(
-                        response.status_code, error_text, self.provider_type
-                    )
+                    yield _error_sse_line(response.status_code, error_text, self.provider_type)
                     return
 
                 if web_search_active:
@@ -4379,9 +4189,7 @@ class ExternalProviderClient:
                         # response. Surface as a content_filter error
                         # event so the UI can render the block reason.
                         prompt_feedback = event.get("promptFeedback")
-                        if isinstance(prompt_feedback, dict) and prompt_feedback.get(
-                            "blockReason"
-                        ):
+                        if isinstance(prompt_feedback, dict) and prompt_feedback.get("blockReason"):
                             block_reason = str(prompt_feedback.get("blockReason"))
                             # Close out the synthetic web_search start so
                             # the UI does not show a spinner stuck on
@@ -4432,9 +4240,7 @@ class ExternalProviderClient:
                                         u = web.get("uri") or ""
                                         if not u or not isinstance(u, str):
                                             continue
-                                        if any(
-                                            c["url"] == u for c in web_search_citations
-                                        ):
+                                        if any(c["url"] == u for c in web_search_citations):
                                             continue
                                         web_search_citations.append(
                                             {
@@ -4446,9 +4252,7 @@ class ExternalProviderClient:
 
                             content_obj = cand.get("content") or {}
                             parts = (
-                                content_obj.get("parts")
-                                if isinstance(content_obj, dict)
-                                else None
+                                content_obj.get("parts") if isinstance(content_obj, dict) else None
                             )
                             if isinstance(parts, list):
                                 for part in parts:
@@ -4487,10 +4291,7 @@ class ExternalProviderClient:
                                     if isinstance(fc, dict):
                                         fc_name = fc.get("name") or ""
                                         fc_args = fc.get("args") or {}
-                                        fc_id = (
-                                            fc.get("id")
-                                            or f"call_{fc_name}_{time.time_ns()}"
-                                        )
+                                        fc_id = fc.get("id") or f"call_{fc_name}_{time.time_ns()}"
                                         if fc_id in emitted_function_call_ids:
                                             continue
                                         emitted_function_call_ids.add(fc_id)
@@ -4521,9 +4322,9 @@ class ExternalProviderClient:
                                         # so the frontend can persist it
                                         # and our outbound translator
                                         # (below) can replay it.
-                                        thought_sig = part.get(
-                                            "thoughtSignature"
-                                        ) or part.get("thought_signature")
+                                        thought_sig = part.get("thoughtSignature") or part.get(
+                                            "thought_signature"
+                                        )
                                         if isinstance(thought_sig, str) and thought_sig:
                                             tool_call_delta["extra_content"] = {
                                                 "google": {
@@ -4537,9 +4338,7 @@ class ExternalProviderClient:
                                             "choices": [
                                                 {
                                                     "index": 0,
-                                                    "delta": {
-                                                        "tool_calls": [tool_call_delta]
-                                                    },
+                                                    "delta": {"tool_calls": [tool_call_delta]},
                                                     "finish_reason": None,
                                                 }
                                             ],
@@ -4596,9 +4395,7 @@ class ExternalProviderClient:
                                                         "kind": "code_execution",
                                                         "language": (
                                                             (
-                                                                exec_code.get(
-                                                                    "language"
-                                                                )
+                                                                exec_code.get("language")
                                                                 or "PYTHON"
                                                             ).lower()
                                                         ),
@@ -4619,9 +4416,7 @@ class ExternalProviderClient:
                                         # non-OK outcomes as stderr so the
                                         # UI surfaces the error.
                                         if outcome and outcome != "OUTCOME_OK":
-                                            result_text = (
-                                                f"[{outcome}]\n{output}".rstrip()
-                                            )
+                                            result_text = f"[{outcome}]\n{output}".rstrip()
                                         else:
                                             result_text = output
                                         # Pair tool_end with the most recent
@@ -4687,8 +4482,7 @@ class ExternalProviderClient:
                                                 not is_image_model
                                                 and last_code_exec_tool_id is not None
                                                 and bool(enabled_tools)
-                                                and "code_execution"
-                                                in (enabled_tools or [])
+                                                and "code_execution" in (enabled_tools or [])
                                             )
                                             if attached_to_code_exec:
                                                 updated_result = (
@@ -4712,28 +4506,22 @@ class ExternalProviderClient:
                                                     isinstance(_plot_thought_sig, str)
                                                     and _plot_thought_sig
                                                 ):
-                                                    _plot_part_entry[
-                                                        "thoughtSignature"
-                                                    ] = _plot_thought_sig
+                                                    _plot_part_entry["thoughtSignature"] = (
+                                                        _plot_thought_sig
+                                                    )
                                                 yield _emit_tool_event(
                                                     {
                                                         "type": "tool_end",
-                                                        "tool_call_id": (
-                                                            last_code_exec_tool_id
-                                                        ),
+                                                        "tool_call_id": (last_code_exec_tool_id),
                                                         "result": updated_result,
                                                         "google": {
                                                             "native_part": {
-                                                                "parts": [
-                                                                    _plot_part_entry
-                                                                ],
+                                                                "parts": [_plot_part_entry],
                                                             },
                                                         },
                                                     }
                                                 )
-                                                last_code_exec_result_text = (
-                                                    updated_result
-                                                )
+                                                last_code_exec_result_text = updated_result
                                             else:
                                                 img_id = f"img_{time.time_ns()}"
                                                 yield _emit_tool_event(
@@ -4773,9 +4561,9 @@ class ExternalProviderClient:
                                                     isinstance(_img_thought_sig, str)
                                                     and _img_thought_sig
                                                 ):
-                                                    _img_part_entry[
-                                                        "thoughtSignature"
-                                                    ] = _img_thought_sig
+                                                    _img_part_entry["thoughtSignature"] = (
+                                                        _img_thought_sig
+                                                    )
                                                 _img_native: dict[str, Any] = {
                                                     "parts": [_img_part_entry],
                                                 }
@@ -4802,11 +4590,7 @@ class ExternalProviderClient:
                     # chunk -> [DONE]. Matches the Anthropic / OpenAI
                     # helpers' contract so the frontend handler does
                     # not need provider-specific ordering knowledge.
-                    if (
-                        web_search_active
-                        and web_search_tool_started
-                        and not web_search_tool_ended
-                    ):
+                    if web_search_active and web_search_tool_started and not web_search_tool_ended:
                         blocks: list[str] = []
                         for cit in web_search_citations:
                             line_out = f"Title: {cit['title']}\nURL: {cit['url']}"
@@ -4818,9 +4602,7 @@ class ExternalProviderClient:
                                 "type": "tool_end",
                                 "tool_call_id": web_search_tool_id,
                                 "result": (
-                                    "\n---\n".join(blocks)
-                                    if blocks
-                                    else "(search complete)"
+                                    "\n---\n".join(blocks) if blocks else "(search complete)"
                                 ),
                             }
                         )
@@ -4857,25 +4639,19 @@ class ExternalProviderClient:
                         # Gemini bills tool-call prompt slices separately
                         # via `toolUsePromptTokenCount`. Fold into input
                         # so total_tokens does not undercount tool turns.
-                        tool_use_prompt_tokens = (
-                            last_usage.get("toolUsePromptTokenCount") or 0
-                        )
+                        tool_use_prompt_tokens = last_usage.get("toolUsePromptTokenCount") or 0
                         translated_usage = {
                             "input_tokens": prompt_tokens + tool_use_prompt_tokens,
                             "output_tokens": candidate_tokens + thought_tokens,
                             "input_tokens_details": {
-                                "cached_tokens": (
-                                    last_usage.get("cachedContentTokenCount") or 0
-                                ),
+                                "cached_tokens": (last_usage.get("cachedContentTokenCount") or 0),
                                 "tool_use_prompt_tokens": tool_use_prompt_tokens,
                             },
                             "output_tokens_details": {
                                 "reasoning_tokens": thought_tokens,
                             },
                         }
-                        usage_line = _build_usage_chunk(
-                            completion_id, "openai", translated_usage
-                        )
+                        usage_line = _build_usage_chunk(completion_id, "openai", translated_usage)
                         if usage_line:
                             yield usage_line
 
@@ -5064,13 +4840,9 @@ class ExternalProviderClient:
                         elif _pt == "image_url":
                             _u = _part.get("image_url", {}).get("url", "")
                             if _u:
-                                _asst_parts.append(
-                                    {"type": "input_image", "image_url": _u}
-                                )
+                                _asst_parts.append({"type": "input_image", "image_url": _u})
                     if _asst_parts:
-                        input_items.append(
-                            {"role": "assistant", "content": _asst_parts}
-                        )
+                        input_items.append({"role": "assistant", "content": _asst_parts})
 
                 for _tc in _tool_calls:
                     if not isinstance(_tc, dict):
@@ -5096,9 +4868,7 @@ class ExternalProviderClient:
                                 _is_server_builtin = True
                             else:
                                 _g = _args_obj.get("google")
-                                if isinstance(_g, dict) and isinstance(
-                                    _g.get("native_part"), dict
-                                ):
+                                if isinstance(_g, dict) and isinstance(_g.get("native_part"), dict):
                                     _is_server_builtin = True
                     _call_id_out = _tc.get("id") or f"call_{time.time_ns()}"
                     if _is_server_builtin:
@@ -5134,9 +4904,7 @@ class ExternalProviderClient:
                         if url:
                             # Responses takes image_url as a flat string (both
                             # https:// URLs and data: URLs are accepted).
-                            translated_parts.append(
-                                {"type": "input_image", "image_url": url}
-                            )
+                            translated_parts.append({"type": "input_image", "image_url": url})
                     elif (
                         part_type == "reasoning"
                         and role == "assistant"
@@ -5314,11 +5082,7 @@ class ExternalProviderClient:
 
         # Server-side context compaction (OpenAI cloud only).
         # https://developers.openai.com/api/docs/guides/compaction
-        if (
-            is_openai_cloud
-            and compaction_threshold is not None
-            and compaction_threshold > 0
-        ):
+        if is_openai_cloud and compaction_threshold is not None and compaction_threshold > 0:
             body["context_management"] = [
                 {
                     "type": "compaction",
@@ -5394,13 +5158,10 @@ class ExternalProviderClient:
             and bool(tool_choice["function"].get("name"))
         )
         _responses_hosted_builtins_allowed = (
-            not _responses_tool_choice_none
-            and not _responses_tool_choice_forced_function
+            not _responses_tool_choice_none and not _responses_tool_choice_forced_function
         )
 
-        if (
-            enabled_tools or responses_user_function_tools
-        ) and not _responses_tool_choice_none:
+        if (enabled_tools or responses_user_function_tools) and not _responses_tool_choice_none:
             tools_array: list[dict[str, Any]] = list(responses_user_function_tools)
             if (
                 _responses_hosted_builtins_allowed
@@ -5440,12 +5201,8 @@ class ExternalProviderClient:
             first attempt.
             """
             attempt_body = dict(body)
-            if (
-                enabled_tools or responses_user_function_tools
-            ) and not _responses_tool_choice_none:
-                tools_array_attempt: list[dict[str, Any]] = list(
-                    responses_user_function_tools
-                )
+            if (enabled_tools or responses_user_function_tools) and not _responses_tool_choice_none:
+                tools_array_attempt: list[dict[str, Any]] = list(responses_user_function_tools)
                 if (
                     _responses_hosted_builtins_allowed
                     and enabled_tools
@@ -5460,13 +5217,8 @@ class ExternalProviderClient:
                         }
                     else:
                         env_attempt = {"type": "container_auto"}
-                    tools_array_attempt.append(
-                        {"type": "shell", "environment": env_attempt}
-                    )
-                if (
-                    _responses_hosted_builtins_allowed
-                    and image_generation_enabled_openai
-                ):
+                    tools_array_attempt.append({"type": "shell", "environment": env_attempt})
+                if _responses_hosted_builtins_allowed and image_generation_enabled_openai:
                     tools_array_attempt.append(_openai_image_generation_tool())
                 if tools_array_attempt:
                     attempt_body["tools"] = tools_array_attempt
@@ -5524,9 +5276,7 @@ class ExternalProviderClient:
                             retried = True
                             attempt_container_id = None
                             continue
-                        yield _error_sse_line(
-                            response.status_code, error_text, self.provider_type
-                        )
+                        yield _error_sse_line(response.status_code, error_text, self.provider_type)
                         return
 
                     # NOTE: same manual __anext__ loop as stream_chat_completion —
@@ -5622,9 +5372,7 @@ class ExternalProviderClient:
                             # Unterminated: drop the whole tail, otherwise the
                             # residual ``cite`` would leak as plain text.
                             return ""
-                        rendered = _replace_openai_citation_markers(
-                            tail, all_url_citations
-                        )
+                        rendered = _replace_openai_citation_markers(tail, all_url_citations)
                         # Scrub residual private-use bytes (e.g. a partial opener).
                         for ch in ("", "", ""):
                             rendered = rendered.replace(ch, "")
@@ -5682,11 +5430,7 @@ class ExternalProviderClient:
                                     chunk_parts.append("(timeout)")
                             if chunk_parts:
                                 parts.append("\n".join(chunk_parts))
-                        return (
-                            "\n--- next command ---\n".join(parts)
-                            if parts
-                            else "(no output)"
-                        )
+                        return "\n--- next command ---\n".join(parts) if parts else "(no output)"
 
                     def _record_url_citation(payload: dict[str, Any]) -> None:
                         """Append a url_citation onto the shared all_url_citations
@@ -5755,17 +5499,11 @@ class ExternalProviderClient:
                                 return existing
                         summary_text = ""
                         part = payload.get("part")
-                        if (
-                            isinstance(part, dict)
-                            and part.get("type") == "summary_text"
-                        ):
+                        if isinstance(part, dict) and part.get("type") == "summary_text":
                             text = part.get("text")
                             if isinstance(text, str):
                                 summary_text = text
-                        elif (
-                            payload.get("type")
-                            == "response.reasoning_summary_text.done"
-                        ):
+                        elif payload.get("type") == "response.reasoning_summary_text.done":
                             text = payload.get("text")
                             if isinstance(text, str):
                                 summary_text = text
@@ -5777,22 +5515,16 @@ class ExternalProviderClient:
                                     "type": "summary_text",
                                     "text": summary_text,
                                 }
-                                if (
-                                    isinstance(summary_index, int)
-                                    and summary_index >= 0
-                                ):
+                                if isinstance(summary_index, int) and summary_index >= 0:
                                     while len(summary) <= summary_index:
-                                        summary.append(
-                                            {"type": "summary_text", "text": ""}
-                                        )
+                                        summary.append({"type": "summary_text", "text": ""})
                                     summary[summary_index] = summary_part
                                 else:
                                     summary.append(summary_part)
                         return existing
 
                     def _image_generation_arguments(
-                        prompt: str,
-                        raw_item_id: Any,
+                        prompt: str, raw_item_id: Any
                     ) -> dict[str, Any]:
                         arguments: dict[str, Any] = {"kind": "image", "prompt": prompt}
                         if isinstance(raw_item_id, str) and raw_item_id:
@@ -5800,9 +5532,7 @@ class ExternalProviderClient:
                         if current_openai_response_id:
                             arguments["openai_response_id"] = current_openai_response_id
                         if last_openai_reasoning_replay_item:
-                            arguments["openai_reasoning_item"] = (
-                                last_openai_reasoning_replay_item
-                            )
+                            arguments["openai_reasoning_item"] = last_openai_reasoning_replay_item
                         return arguments
 
                     def _extract_reasoning_text(payload: Any) -> str:
@@ -5861,9 +5591,7 @@ class ExternalProviderClient:
                                 # Flush any held-over partial marker; strip
                                 # private-use bytes so garbled glyphs don't leak.
                                 if pending_marker_tail:
-                                    flushed = _flush_pending_marker_tail(
-                                        pending_marker_tail
-                                    )
+                                    flushed = _flush_pending_marker_tail(pending_marker_tail)
                                     pending_marker_tail = ""
                                     if flushed:
                                         if reasoning_open:
@@ -5906,8 +5634,8 @@ class ExternalProviderClient:
                                     # Prepend any held-over tail so a marker
                                     # straddling two SSE events resolves cleanly.
                                     combined = pending_marker_tail + delta_text
-                                    head, pending_marker_tail = (
-                                        _split_pending_citation_tail(combined)
+                                    head, pending_marker_tail = _split_pending_citation_tail(
+                                        combined
                                     )
                                     if head:
                                         if reasoning_open:
@@ -5928,9 +5656,7 @@ class ExternalProviderClient:
                                             )
                                         )
                                         if has_unresolved or pending_citation_segments:
-                                            pending_citation_segments.append(
-                                                head_rewritten
-                                            )
+                                            pending_citation_segments.append(head_rewritten)
                                         elif head_rewritten:
                                             yield _chunk_with_text(head_rewritten)
 
@@ -5949,24 +5675,14 @@ class ExternalProviderClient:
 
                             elif event_type == "response.output_item.added":
                                 item = event.get("item", {})
-                                if (
-                                    isinstance(item, dict)
-                                    and item.get("type") == "web_search_call"
-                                ):
-                                    item_id = item.get("id", "") or (
-                                        f"ws_{len(web_search_calls)}"
-                                    )
+                                if isinstance(item, dict) and item.get("type") == "web_search_call":
+                                    item_id = item.get("id", "") or (f"ws_{len(web_search_calls)}")
                                     web_search_calls.setdefault(item_id, {"query": ""})
                                 # Register shell_call eagerly so out-of-order
                                 # output links back. Probe env.container_id
                                 # to emit container_ready before response.completed.
-                                if (
-                                    isinstance(item, dict)
-                                    and item.get("type") == "shell_call"
-                                ):
-                                    item_id = item.get("id", "") or (
-                                        f"sc_{len(shell_calls)}"
-                                    )
+                                if isinstance(item, dict) and item.get("type") == "shell_call":
+                                    item_id = item.get("id", "") or (f"sc_{len(shell_calls)}")
                                     shell_calls.setdefault(
                                         item_id,
                                         {"commands": [], "output": None},
@@ -6008,9 +5724,7 @@ class ExternalProviderClient:
                                     last_openai_reasoning_replay_item = (
                                         _record_openai_reasoning_replay_item(item)
                                     )
-                                    summary_text = _extract_reasoning_text(
-                                        item.get("summary")
-                                    )
+                                    summary_text = _extract_reasoning_text(item.get("summary"))
                                     if summary_text and not reasoning_emitted:
                                         if not reasoning_open:
                                             summary_text = f"{summary_text}"
@@ -6027,14 +5741,10 @@ class ExternalProviderClient:
                                     # response.completed with the citation list
                                     # (so the source-pill extraction at message
                                     # tail surfaces them once).
-                                    item_id = item.get("id", "") or (
-                                        f"ws_{len(web_search_calls)}"
-                                    )
+                                    item_id = item.get("id", "") or (f"ws_{len(web_search_calls)}")
                                     action = item.get("action")
                                     query = (
-                                        action.get("query", "")
-                                        if isinstance(action, dict)
-                                        else ""
+                                        action.get("query", "") if isinstance(action, dict) else ""
                                     )
                                     web_search_calls[item_id] = {"query": query}
                                     yield _emit_tool_event(
@@ -6042,16 +5752,12 @@ class ExternalProviderClient:
                                             "type": "tool_start",
                                             "tool_name": "web_search",
                                             "tool_call_id": item_id,
-                                            "arguments": (
-                                                {"query": query} if query else {}
-                                            ),
+                                            "arguments": ({"query": query} if query else {}),
                                         }
                                     )
                                     # Per-card text; last call gets overwritten
                                     # with citations at response.completed.
-                                    per_call_result = (
-                                        f"Searching: {query}" if query else ""
-                                    )
+                                    per_call_result = f"Searching: {query}" if query else ""
                                     yield _emit_tool_event(
                                         {
                                             "type": "tool_end",
@@ -6068,14 +5774,10 @@ class ExternalProviderClient:
                                     # `command`. Multiple commands in one
                                     # shell_call get joined with newlines so
                                     # they still render as one card.
-                                    item_id = item.get("id", "") or (
-                                        f"sc_{len(shell_calls)}"
-                                    )
+                                    item_id = item.get("id", "") or (f"sc_{len(shell_calls)}")
                                     action = item.get("action") or {}
                                     commands = (
-                                        action.get("commands")
-                                        if isinstance(action, dict)
-                                        else None
+                                        action.get("commands") if isinstance(action, dict) else None
                                     ) or []
                                     joined_command = (
                                         "\n".join(str(c) for c in commands)
@@ -6091,9 +5793,7 @@ class ExternalProviderClient:
                                         },
                                     )
                                     shell_calls[item_id]["commands"] = (
-                                        list(commands)
-                                        if isinstance(commands, list)
-                                        else []
+                                        list(commands) if isinstance(commands, list) else []
                                     )
                                     yield _emit_tool_event(
                                         {
@@ -6109,19 +5809,14 @@ class ExternalProviderClient:
                                     # Fallback: output may be bundled on the
                                     # shell_call done event itself.
                                     embedded_output = item.get("output")
-                                    if (
-                                        isinstance(embedded_output, list)
-                                        and embedded_output
-                                    ):
+                                    if isinstance(embedded_output, list) and embedded_output:
                                         shell_calls[item_id]["output"] = embedded_output
                                         shell_calls[item_id]["tool_end_emitted"] = True
                                         yield _emit_tool_event(
                                             {
                                                 "type": "tool_end",
                                                 "tool_call_id": item_id,
-                                                "result": _format_shell_output(
-                                                    embedded_output
-                                                ),
+                                                "result": _format_shell_output(embedded_output),
                                             }
                                         )
                                 elif item.get("type") == "shell_call_output":
@@ -6130,15 +5825,11 @@ class ExternalProviderClient:
                                     # tool_call_id on tool_start. Match on
                                     # call_id when present so the matching
                                     # card transitions to complete.
-                                    call_id = (
-                                        item.get("call_id") or item.get("id") or ""
-                                    )
+                                    call_id = item.get("call_id") or item.get("id") or ""
                                     output = item.get("output") or []
                                     # Skip if bundled-output path already
                                     # finalised this card.
-                                    if shell_calls.get(call_id, {}).get(
-                                        "tool_end_emitted"
-                                    ):
+                                    if shell_calls.get(call_id, {}).get("tool_end_emitted"):
                                         continue
                                     if call_id in shell_calls:
                                         shell_calls[call_id]["output"] = output
@@ -6158,9 +5849,7 @@ class ExternalProviderClient:
                                     raw_item_id = item.get("id")
                                     item_id = raw_item_id or f"img_{time.time_ns()}"
                                     prompt_in = (
-                                        item.get("revised_prompt")
-                                        or item.get("prompt")
-                                        or ""
+                                        item.get("revised_prompt") or item.get("prompt") or ""
                                     )
                                     done_arguments = _image_generation_arguments(
                                         prompt_in,
@@ -6175,9 +5864,7 @@ class ExternalProviderClient:
                                                 "arguments": done_arguments,
                                             }
                                         )
-                                    b64 = (
-                                        item.get("result") or item.get("b64_json") or ""
-                                    )
+                                    b64 = item.get("result") or item.get("b64_json") or ""
                                     output_format = item.get("output_format") or "png"
                                     yield _emit_tool_event(
                                         {
@@ -6227,9 +5914,7 @@ class ExternalProviderClient:
                                                                     "type": "function",
                                                                     "function": {
                                                                         "name": fn_name,
-                                                                        "arguments": (
-                                                                            fn_args
-                                                                        ),
+                                                                        "arguments": (fn_args),
                                                                     },
                                                                 }
                                                             ],
@@ -6242,17 +5927,10 @@ class ExternalProviderClient:
                                     )
                                     saw_function_call = True
 
-                            elif (
-                                isinstance(event_type, str)
-                                and "reasoning" in event_type
-                            ):
-                                recorded_reasoning = (
-                                    _record_openai_reasoning_replay_item(event)
-                                )
+                            elif isinstance(event_type, str) and "reasoning" in event_type:
+                                recorded_reasoning = _record_openai_reasoning_replay_item(event)
                                 if recorded_reasoning:
-                                    last_openai_reasoning_replay_item = (
-                                        recorded_reasoning
-                                    )
+                                    last_openai_reasoning_replay_item = recorded_reasoning
                                 reasoning_delta = _extract_reasoning_text(event)
                                 if reasoning_delta:
                                     if not reasoning_open:
@@ -6262,9 +5940,7 @@ class ExternalProviderClient:
                                     reasoning_emitted = True
 
                             elif event_type == "response.completed":
-                                completed_usage = (event.get("response") or {}).get(
-                                    "usage"
-                                )
+                                completed_usage = (event.get("response") or {}).get("usage")
                                 if isinstance(completed_usage, dict):
                                     last_usage = completed_usage
                                 # Flush any unterminated citation tail
@@ -6276,9 +5952,7 @@ class ExternalProviderClient:
                                 # private-use bytes so no garbled
                                 # glyph reaches the user.
                                 if pending_marker_tail:
-                                    flushed = _flush_pending_marker_tail(
-                                        pending_marker_tail
-                                    )
+                                    flushed = _flush_pending_marker_tail(pending_marker_tail)
                                     pending_marker_tail = ""
                                     if flushed:
                                         if reasoning_open:
@@ -6321,8 +5995,7 @@ class ExternalProviderClient:
                                 if (
                                     latched_container_id
                                     and not container_id_emitted
-                                    and latched_container_id
-                                    != openai_code_exec_container_id
+                                    and latched_container_id != openai_code_exec_container_id
                                 ):
                                     yield _emit_tool_event(
                                         {
@@ -6339,9 +6012,7 @@ class ExternalProviderClient:
                                     last_id = list(web_search_calls.keys())[-1]
                                     blocks: list[str] = []
                                     for cit in all_url_citations:
-                                        line = (
-                                            f"Title: {cit['title']}\nURL: {cit['url']}"
-                                        )
+                                        line = f"Title: {cit['title']}\nURL: {cit['url']}"
                                         if cit.get("snippet"):
                                             line += f"\nSnippet: {cit['snippet']}"
                                         blocks.append(line)
@@ -6375,9 +6046,7 @@ class ExternalProviderClient:
                                             "index": 0,
                                             "delta": {},
                                             "finish_reason": (
-                                                "tool_calls"
-                                                if saw_function_call
-                                                else "stop"
+                                                "tool_calls" if saw_function_call else "stop"
                                             ),
                                         }
                                     ],
@@ -6395,18 +6064,14 @@ class ExternalProviderClient:
                                     yield usage_line
 
                             elif event_type == "response.incomplete":
-                                incomplete_usage = (event.get("response") or {}).get(
-                                    "usage"
-                                )
+                                incomplete_usage = (event.get("response") or {}).get("usage")
                                 if isinstance(incomplete_usage, dict):
                                     last_usage = incomplete_usage
                                 # Same flush as response.completed --
                                 # truncated streams can leave a half-
                                 # marker in the buffer.
                                 if pending_marker_tail:
-                                    flushed = _flush_pending_marker_tail(
-                                        pending_marker_tail
-                                    )
+                                    flushed = _flush_pending_marker_tail(pending_marker_tail)
                                     pending_marker_tail = ""
                                     if flushed:
                                         if reasoning_open:
@@ -6436,9 +6101,7 @@ class ExternalProviderClient:
                                     last_id = list(web_search_calls.keys())[-1]
                                     blocks = []
                                     for cit in all_url_citations:
-                                        line = (
-                                            f"Title: {cit['title']}\nURL: {cit['url']}"
-                                        )
+                                        line = f"Title: {cit['title']}\nURL: {cit['url']}"
                                         if cit.get("snippet"):
                                             line += f"\nSnippet: {cit['snippet']}"
                                         blocks.append(line)
@@ -6492,9 +6155,7 @@ class ExternalProviderClient:
                             elif event_type in ("response.failed", "error"):
                                 # Surface the failure to the client; let the
                                 # outer route emit [DONE] as part of its cleanup.
-                                error_payload = event.get("response", {}).get(
-                                    "error", {}
-                                ) or {
+                                error_payload = event.get("response", {}).get("error", {}) or {
                                     "message": event.get("message", "Unknown error"),
                                     "code": event.get("code"),
                                 }
@@ -6513,15 +6174,11 @@ class ExternalProviderClient:
                         # support reports of "I clicked Search and got nothing"
                         # can be triaged at a glance: was the tool requested,
                         # did OpenAI invoke it, and how many sources came back?
-                        web_search_requested = bool(
-                            enabled_tools and "web_search" in enabled_tools
-                        )
+                        web_search_requested = bool(enabled_tools and "web_search" in enabled_tools)
                         web_search_invocations = len(web_search_calls)
                         total_citations = len(all_url_citations)
                         queries = [
-                            sc["query"]
-                            for sc in web_search_calls.values()
-                            if sc.get("query")
+                            sc["query"] for sc in web_search_calls.values() if sc.get("query")
                         ]
                         # cached_input_tokens > 0 on turn N proves
                         # prompt_cache_retention="24h" is letting the previous
@@ -6538,9 +6195,7 @@ class ExternalProviderClient:
                         code_execution_requested = code_execution_enabled_openai
                         code_execution_invocations = len(shell_calls)
                         code_execution_results = sum(
-                            1
-                            for sc in shell_calls.values()
-                            if sc.get("output") is not None
+                            1 for sc in shell_calls.values() if sc.get("output") is not None
                         )
                         logger.info(
                             "OpenAI Responses stream complete (model=%s, "
@@ -6698,9 +6353,7 @@ class ExternalProviderClient:
             if (
                 isinstance(methods, list)
                 and methods
-                and not any(
-                    m in methods for m in ("generateContent", "streamGenerateContent")
-                )
+                and not any(m in methods for m in ("generateContent", "streamGenerateContent"))
             ):
                 continue
             base_id = entry.get("baseModelId")
@@ -6808,19 +6461,11 @@ class ExternalProviderClient:
         logger.info(
             "openai_container_list.response count=%s items=%s",
             len(result),
-            [
-                {"id": c.get("id"), "status": c.get("status")}
-                for c in result
-                if isinstance(c, dict)
-            ],
+            [{"id": c.get("id"), "status": c.get("status")} for c in result if isinstance(c, dict)],
         )
         return result
 
-    async def create_openai_container(
-        self,
-        name: str,
-        ttl_minutes: int,
-    ) -> dict[str, Any]:
+    async def create_openai_container(self, name: str, ttl_minutes: int) -> dict[str, Any]:
         """
         POST /v1/containers with ``expires_after.anchor="last_active_at"``.
         ``ttl_minutes`` is the idle timeout — every API call that
@@ -6894,7 +6539,6 @@ class ExternalProviderClient:
 
 def _provider_display_name(provider_type: str) -> str:
     from core.inference.providers import get_provider_info
-
     info = get_provider_info(provider_type) or {}
     return str(info.get("display_name") or provider_type)
 
@@ -6942,9 +6586,7 @@ def _error_sse_line(status_code: int, message: str, provider_type: str) -> str:
 
 
 def _build_usage_chunk(
-    completion_id: str,
-    provider: Literal["anthropic", "openai"],
-    last_usage: Optional[dict],
+    completion_id: str, provider: Literal["anthropic", "openai"], last_usage: Optional[dict]
 ) -> Optional[str]:
     """Build an OpenAI ``include_usage``-style SSE chunk that carries the
     upstream prompt-cache accounting back to the client.
diff --git a/studio/backend/core/inference/inference.py b/studio/backend/core/inference/inference.py
index e1620f5ca3..33647a6cd1 100644
--- a/studio/backend/core/inference/inference.py
+++ b/studio/backend/core/inference/inference.py
@@ -68,7 +68,13 @@ class HarmonyTextStreamer:
         _re.DOTALL,
     )
 
-    def __init__(self, tokenizer, *, skip_prompt: bool = True, timeout: float = 0.2):
+    def __init__(
+        self,
+        tokenizer,
+        *,
+        skip_prompt: bool = True,
+        timeout: float = 0.2,
+    ):
         import queue
 
         self.tokenizer = tokenizer
@@ -142,7 +148,6 @@ class HarmonyTextStreamer:
 
     def __next__(self):
         from queue import Empty
-
         while True:
             try:
                 val = self._queue.get(timeout = self.timeout)
@@ -293,9 +298,7 @@ class InferenceBackend:
             if config.is_audio:
                 audio_type = config.audio_type
                 adapter_info = " (LoRA adapter)" if config.is_lora else ""
-                logger.info(
-                    f"Loading audio ({audio_type}) model{adapter_info}: {model_name}"
-                )
+                logger.info(f"Loading audio ({audio_type}) model{adapter_info}: {model_name}")
                 log_gpu_memory(f"Before loading {model_name}")
 
                 if audio_type == "csm":
@@ -330,9 +333,7 @@ class InferenceBackend:
                             from huggingface_hub import snapshot_download
 
                             local_dir = base_path.split("/")[-1]
-                            repo_path = snapshot_download(
-                                base_path, local_dir = local_dir
-                            )
+                            repo_path = snapshot_download(base_path, local_dir = local_dir)
                             abs_repo_path = os.path.abspath(repo_path)
 
                         logger.info(
@@ -443,9 +444,7 @@ class InferenceBackend:
                     )
 
                 # Reject CPU/disk offload for audio models too
-                raise_if_offloaded(
-                    self.models[model_name]["model"], device_map, "Inference"
-                )
+                raise_if_offloaded(self.models[model_name]["model"], device_map, "Inference")
 
                 self.active_model_name = model_name
                 self.loading_models.discard(model_name)
@@ -454,9 +453,7 @@ class InferenceBackend:
                 return True
 
             model_type = "vision" if config.is_vision else "text"
-            adapter_info = (
-                " (LoRA adapter)" if self.models[model_name]["is_lora"] else ""
-            )
+            adapter_info = " (LoRA adapter)" if self.models[model_name]["is_lora"] else ""
             logger.info(f"Loading {model_type} model{adapter_info}: {model_name}")
             log_gpu_memory(f"Before loading {model_name}")
 
@@ -482,14 +479,11 @@ class InferenceBackend:
                 from transformers import ProcessorMixin
 
                 if not (
-                    isinstance(processor, ProcessorMixin)
-                    or hasattr(processor, "image_processor")
+                    isinstance(processor, ProcessorMixin) or hasattr(processor, "image_processor")
                 ):
                     # For LoRA adapters, use the base model. For local merged exports,
                     # read export_metadata.json to find the original base model.
-                    processor_source = (
-                        config.base_model if config.is_lora else config.identifier
-                    )
+                    processor_source = config.base_model if config.is_lora else config.identifier
                     if not config.is_lora and config.is_local:
                         _meta_path = Path(config.path) / "export_metadata.json"
                         try:
@@ -510,9 +504,7 @@ class InferenceBackend:
                         token = hf_token if hf_token and hf_token.strip() else None,
                         trust_remote_code = trust_remote_code,
                     )
-                    logger.info(
-                        f"Loaded {type(processor).__name__} from {processor_source}"
-                    )
+                    logger.info(f"Loaded {type(processor).__name__} from {processor_source}")
 
                 self.models[model_name]["model"] = model
                 self.models[model_name]["tokenizer"] = processor
@@ -536,9 +528,7 @@ class InferenceBackend:
                 self.models[model_name]["model"] = model
                 self.models[model_name]["tokenizer"] = tokenizer
 
-            raise_if_offloaded(
-                self.models[model_name]["model"], device_map, "Inference"
-            )
+            raise_if_offloaded(self.models[model_name]["model"], device_map, "Inference")
 
             # Load chat template info
             self._load_chat_template_info(model_name)
@@ -588,11 +578,7 @@ class InferenceBackend:
                 import sys as _sys
                 from utils.cache_cleanup import clear_unsloth_compiled_cache
 
-                _preserve = (
-                    ["Unsloth*Trainer.py"]
-                    if _sys.platform in ("win32", "darwin")
-                    else None
-                )
+                _preserve = ["Unsloth*Trainer.py"] if _sys.platform in ("win32", "darwin") else None
                 clear_unsloth_compiled_cache(preserve_patterns = _preserve)
 
                 logger.info(f"Model '{model_name}' successfully unloaded.")
@@ -665,13 +651,9 @@ class InferenceBackend:
             base_model_name = lora_config.base_model
 
             # 1. Load the base model if it's not already in memory
-            if base_model_name not in self.models or not self.models[
-                base_model_name
-            ].get("model"):
+            if base_model_name not in self.models or not self.models[base_model_name].get("model"):
                 logger.info(f"Base model '{base_model_name}' not loaded, loading now.")
-                base_config = ModelConfig.from_ui_selection(
-                    base_model_name, None, is_lora = False
-                )
+                base_config = ModelConfig.from_ui_selection(base_model_name, None, is_lora = False)
                 if not self.load_model(
                     base_config,
                     max_seq_length,
@@ -707,9 +689,7 @@ class InferenceBackend:
             logger.error(traceback.format_exc())
             return False, None, None
 
-    def load_adapter(
-        self, base_model_name: str, adapter_path: str, adapter_name: str
-    ) -> bool:
+    def load_adapter(self, base_model_name: str, adapter_path: str, adapter_name: str) -> bool:
         """
         Loads an adapter onto the model ONLY if it's not already attached.
         """
@@ -790,16 +770,12 @@ class InferenceBackend:
                 )
                 model.base_model.disable_adapter_layers()
             else:
-                logger.info(
-                    f"Compare mode: model '{base}' is not a PeftModel, already base"
-                )
+                logger.info(f"Compare mode: model '{base}' is not a PeftModel, already base")
 
         elif use_adapter is True:
             # Re-enable LoRA layers → adapter output
             if isinstance(model, (PeftModel, PeftModelForCausalLM)):
-                logger.info(
-                    f"Compare mode: enabling adapters on '{base}' for LoRA generation"
-                )
+                logger.info(f"Compare mode: enabling adapters on '{base}' for LoRA generation")
                 model.base_model.enable_adapter_layers()
             else:
                 logger.warning("use_adapter=true but model is not a PeftModel")
@@ -807,15 +783,11 @@ class InferenceBackend:
         elif isinstance(use_adapter, str):
             # Enable adapters and set the specific one active
             if isinstance(model, (PeftModel, PeftModelForCausalLM)):
-                logger.info(
-                    f"Compare mode: enabling adapter '{use_adapter}' on '{base}'"
-                )
+                logger.info(f"Compare mode: enabling adapter '{use_adapter}' on '{base}'")
                 model.base_model.enable_adapter_layers()
                 self.set_active_adapter(base, use_adapter)
             else:
-                logger.warning(
-                    f"use_adapter='{use_adapter}' but model is not a PeftModel"
-                )
+                logger.warning(f"use_adapter='{use_adapter}' but model is not a PeftModel")
 
     def generate_with_adapter_control(
         self,
@@ -996,8 +968,7 @@ class InferenceBackend:
 
             processor = model_info.get("processor")
             has_image_processing = processor is not None and (
-                isinstance(processor, ProcessorMixin)
-                or hasattr(processor, "image_processor")
+                isinstance(processor, ProcessorMixin) or hasattr(processor, "image_processor")
             )
             if has_image_processing:
                 yield from self._generate_vision_response(
@@ -1029,7 +1000,6 @@ class InferenceBackend:
                 MODEL_TO_TEMPLATE_MAPPER,
                 get_tokenizer_chat_template,
             )
-
             model_name_lower = self.active_model_name.lower()
 
             # Check if model has a registered template
@@ -1053,9 +1023,7 @@ class InferenceBackend:
 
         # Step 2: Format with tokenizer.apply_chat_template()
         if system_prompt:
-            template_messages = [
-                {"role": "system", "content": system_prompt}
-            ] + messages
+            template_messages = [{"role": "system", "content": system_prompt}] + messages
         else:
             template_messages = messages
         try:
@@ -1119,7 +1087,6 @@ class InferenceBackend:
         user_message = ""
         if messages and messages[-1]["role"] == "user":
             import re
-
             user_message = messages[-1]["content"]
             user_message = re.sub(r"]*>", "", user_message).strip()
 
@@ -1171,9 +1138,7 @@ class InferenceBackend:
         else:
             # Text-only for vision model
             formatted_prompt = self.format_chat_prompt(messages, system_prompt)
-            inputs = raw_tokenizer(formatted_prompt, return_tensors = "pt").to(
-                model.device
-            )
+            inputs = raw_tokenizer(formatted_prompt, return_tensors = "pt").to(model.device)
 
         # Stream with TextIteratorStreamer + background thread
         try:
@@ -1385,7 +1350,9 @@ class InferenceBackend:
             yield f"Error: {str(e)}"
 
     def generate_whisper_response(
-        self, audio_array, cancel_event = None
+        self,
+        audio_array,
+        cancel_event = None,
     ) -> Generator[str, None, None]:
         """Whisper ASR — takes audio numpy array, yields transcribed text.
 
@@ -1411,7 +1378,6 @@ class InferenceBackend:
     def _is_gpt_oss_model(self, model_name: str = None) -> bool:
         """Check if the given (or active) model uses the gpt-oss harmony protocol."""
         from utils.datasets import is_gpt_oss_model_name
-
         return is_gpt_oss_model_name(model_name or self.active_model_name or "")
 
     def generate_stream(
@@ -1459,9 +1425,7 @@ class InferenceBackend:
                         timeout = 0.2,
                     )
                 except Exception as e:
-                    logger.warning(
-                        f"HarmonyTextStreamer init failed, falling back: {e}"
-                    )
+                    logger.warning(f"HarmonyTextStreamer init failed, falling back: {e}")
                     streamer = TextIteratorStreamer(
                         tokenizer,
                         skip_prompt = True,
@@ -1496,7 +1460,6 @@ class InferenceBackend:
                     StoppingCriteria,
                     StoppingCriteriaList,
                 )
-
                 class _CancelCriteria(StoppingCriteria):
                     def __init__(self, ev):
                         self.ev = ev
@@ -1559,9 +1522,7 @@ class InferenceBackend:
                     cancel_event.set()
                 thread.join(timeout = 10)
                 if thread.is_alive():
-                    logger.warning(
-                        "Generation thread did not exit after cancel/join timeout"
-                    )
+                    logger.warning("Generation thread did not exit after cancel/join timeout")
 
             if err.get("msg"):
                 yield f"Error: {err['msg']}"
@@ -1638,21 +1599,12 @@ class InferenceBackend:
                 raise RuntimeError(f"Unknown audio_type: {audio_type}")
 
     def _generate_snac(
-        self,
-        model,
-        tokenizer,
-        text,
-        temperature,
-        top_p,
-        max_new_tokens,
-        repetition_penalty,
+        self, model, tokenizer, text, temperature, top_p, max_new_tokens, repetition_penalty
     ):
         """Generate audio using SNAC codec (Orpheus)."""
         device = model.device
         start_token = torch.tensor([[128259]], device = device)  # START_OF_HUMAN
-        end_tokens = torch.tensor(
-            [[128009, 128260]], device = device
-        )  # EOT, END_OF_HUMAN
+        end_tokens = torch.tensor([[128009, 128260]], device = device)  # EOT, END_OF_HUMAN
         text_ids = tokenizer(text, return_tensors = "pt").input_ids.to(device)
         input_ids = torch.cat([start_token, text_ids, end_tokens], dim = 1)
         attention_mask = torch.ones_like(input_ids)
@@ -1676,20 +1628,12 @@ class InferenceBackend:
         inputs = processor(
             f"[{speaker_id}]{text}", add_special_tokens = True, return_tensors = "pt"
         ).to(model.device)
-        audio_values = model.generate(
-            **inputs, max_new_tokens = max_new_tokens, output_audio = True
-        )
+        audio_values = model.generate(**inputs, max_new_tokens = max_new_tokens, output_audio = True)
         return self._audio_codec_manager.decode_csm(audio_values)
 
-    def _generate_bicodec(
-        self, model, tokenizer, text, temperature, top_k, max_new_tokens
-    ):
+    def _generate_bicodec(self, model, tokenizer, text, temperature, top_k, max_new_tokens):
         """Generate audio using BiCodec (Spark-TTS)."""
-        prompt = (
-            "<|task_tts|><|start_content|>"
-            + text
-            + "<|end_content|><|start_global_token|>"
-        )
+        prompt = "<|task_tts|><|start_content|>" + text + "<|end_content|><|start_global_token|>"
         inputs = tokenizer([prompt], return_tensors = "pt").to(model.device)
         generated = model.generate(
             **inputs,
@@ -1761,9 +1705,7 @@ class InferenceBackend:
             def __init__(self, penalty: float):
                 self.penalty_last_n = 64
                 if not isinstance(penalty, float) or penalty <= 0:
-                    raise ValueError(
-                        f"`penalty` has to be a positive float, but is {penalty}"
-                    )
+                    raise ValueError(f"`penalty` has to be a positive float, but is {penalty}")
                 self.penalty = penalty
 
             @torch.no_grad()
@@ -1788,12 +1730,8 @@ class InferenceBackend:
                         )
                 return scores
 
-        generation_utils.RepetitionPenaltyLogitsProcessor = (
-            RepetitionPenaltyLogitsProcessorPatch
-        )
-        logger.info(
-            "Patched RepetitionPenaltyLogitsProcessor with 64-token window for OuteTTS"
-        )
+        generation_utils.RepetitionPenaltyLogitsProcessor = RepetitionPenaltyLogitsProcessorPatch
+        logger.info("Patched RepetitionPenaltyLogitsProcessor with 64-token window for OuteTTS")
 
     def _apply_chat_template_for_generation(
         self,
@@ -1813,7 +1751,6 @@ class InferenceBackend:
         from core.inference.chat_template_helpers import (
             apply_chat_template_for_generation,
         )
-
         return apply_chat_template_for_generation(
             tokenizer,
             messages,
@@ -1823,7 +1760,11 @@ class InferenceBackend:
             preserve_thinking = preserve_thinking,
         )
 
-    def format_chat_prompt(self, messages: list, system_prompt: str = None) -> str:
+    def format_chat_prompt(
+        self,
+        messages: list,
+        system_prompt: str = None,
+    ) -> str:
         if not self.active_model_name or self.active_model_name not in self.models:
             logger.error("No active model available")
             return ""
@@ -1832,9 +1773,7 @@ class InferenceBackend:
             logger.error("Tokenizer not loaded for active model")
             return ""
 
-        chat_template_info = self.models[self.active_model_name].get(
-            "chat_template_info", {}
-        )
+        chat_template_info = self.models[self.active_model_name].get("chat_template_info", {})
         tokenizer = self.models[self.active_model_name]["tokenizer"]
         tokenizer = getattr(tokenizer, "tokenizer", tokenizer)
 
@@ -1851,14 +1790,11 @@ class InferenceBackend:
 
             if role in ["system", "user", "assistant"] and content.strip():
                 if role == last_role:
-                    logger.debug(
-                        f"Skipping consecutive {role} message to maintain alternation"
-                    )
+                    logger.debug(f"Skipping consecutive {role} message to maintain alternation")
                     continue
 
                 if role == "user":
                     import re
-
                     clean_content = re.sub(r"<[^>]+>", "", content).strip()
                     if clean_content:
                         chat_messages.append({"role": role, "content": clean_content})
@@ -1870,9 +1806,7 @@ class InferenceBackend:
                     continue
 
         if chat_messages and chat_messages[-1]["role"] == "assistant":
-            logger.debug(
-                "Removing final assistant message to ensure proper alternation"
-            )
+            logger.debug("Removing final assistant message to ensure proper alternation")
             chat_messages.pop()
 
         logger.info(f"Sending {len(chat_messages)} messages to tokenizer:")
@@ -1887,10 +1821,7 @@ class InferenceBackend:
             return formatted_prompt
         except Exception as e:
             error_msg = str(e).lower()
-            if (
-                "chat_template is not set" in error_msg
-                or "no template argument" in error_msg
-            ):
+            if "chat_template is not set" in error_msg or "no template argument" in error_msg:
                 logger.info(
                     f"Base model detected - no built-in chat template available, using fallback formatting"
                 )
@@ -1901,9 +1832,7 @@ class InferenceBackend:
             )
 
         if chat_template_info.get("has_template", False):
-            logger.info(
-                "Falling back to manual template formatting based on detected patterns"
-            )
+            logger.info("Falling back to manual template formatting based on detected patterns")
             template_type = chat_template_info.get("format_type", "generic")
             manual_prompt = self._format_chat_manual(
                 chat_messages,
@@ -1916,9 +1845,7 @@ class InferenceBackend:
             logger.info("Using generic chat formatting for base model")
             return self._format_generic_template(chat_messages, {})
 
-    def _format_chat_manual(
-        self, messages: list, template_type: str, special_tokens: dict
-    ) -> str:
+    def _format_chat_manual(self, messages: list, template_type: str, special_tokens: dict) -> str:
         """
         Manual chat formatting fallback for when tokenizer template fails
 
@@ -1949,9 +1876,7 @@ class InferenceBackend:
         for msg in messages:
             role = msg["role"]
             content = msg["content"]
-            formatted += (
-                f"<|start_header_id|>{role}<|end_header_id|>\n\n{content}<|eot_id|>"
-            )
+            formatted += f"<|start_header_id|>{role}<|end_header_id|>\n\n{content}<|eot_id|>"
 
         formatted += "<|start_header_id|>assistant<|end_header_id|>\n\n"
         return formatted
@@ -1980,10 +1905,7 @@ class InferenceBackend:
 
                 formatted += f"[INST] {user_content} [/INST]"
 
-                if (
-                    i + 1 < len(conversation)
-                    and conversation[i + 1]["role"] == "assistant"
-                ):
+                if i + 1 < len(conversation) and conversation[i + 1]["role"] == "assistant":
                     formatted += f" {conversation[i + 1]['content']}"
                     i += 2
                 else:
@@ -2088,7 +2010,11 @@ class InferenceBackend:
         except Exception as e:
             logger.warning(f"Could not fully reset generation state: {e}")
 
-    def resize_image(self, img, max_size: int = 800):
+    def resize_image(
+        self,
+        img,
+        max_size: int = 800,
+    ):
         """Resize image while maintaining aspect ratio if either dimension exceeds max_size"""
         if img is None:
             return None
@@ -2107,7 +2033,6 @@ class InferenceBackend:
             # Strip harmony protocol tokens and other gpt-oss added tokens
             # (e.g. <|return|>) that may leak past the streamer.
             import re
-
             text = re.sub(r"<\|[a-z_]+\|>", "", text)
             return text.strip()
 
@@ -2119,9 +2044,7 @@ class InferenceBackend:
         return text.strip()
 
     def _load_chat_template_info(self, model_name: str):
-        if model_name not in self.models or not self.models[model_name].get(
-            "tokenizer"
-        ):
+        if model_name not in self.models or not self.models[model_name].get("tokenizer"):
             return
 
         tokenizer = self.models[model_name]["tokenizer"]
@@ -2139,9 +2062,7 @@ class InferenceBackend:
             # Try exact match first
             model_name_lower = model_name.lower()
             if model_name_lower in MODEL_TO_TEMPLATE_MAPPER:
-                chat_template_info["template_name"] = MODEL_TO_TEMPLATE_MAPPER[
-                    model_name_lower
-                ]
+                chat_template_info["template_name"] = MODEL_TO_TEMPLATE_MAPPER[model_name_lower]
                 logger.info(
                     f"Detected template '{chat_template_info['template_name']}' for {model_name} from mapper"
                 )
@@ -2149,17 +2070,13 @@ class InferenceBackend:
                 # Try partial match (for variants like model_name-bnb-4bit)
                 for key in MODEL_TO_TEMPLATE_MAPPER:
                     if key in model_name_lower or model_name_lower in key:
-                        chat_template_info["template_name"] = MODEL_TO_TEMPLATE_MAPPER[
-                            key
-                        ]
+                        chat_template_info["template_name"] = MODEL_TO_TEMPLATE_MAPPER[key]
                         logger.info(
                             f"Detected template '{chat_template_info['template_name']}' for {model_name} (partial match)"
                         )
                         break
         except Exception as e:
-            logger.warning(
-                f"Could not detect template from mapper for {model_name}: {e}"
-            )
+            logger.warning(f"Could not detect template from mapper for {model_name}: {e}")
 
         try:
             if hasattr(tokenizer, "chat_template") and tokenizer.chat_template:
@@ -2168,10 +2085,7 @@ class InferenceBackend:
 
                 template_str = tokenizer.chat_template.lower()
 
-                if (
-                    "start_header_id" in template_str
-                    and "end_header_id" in template_str
-                ):
+                if "start_header_id" in template_str and "end_header_id" in template_str:
                     chat_template_info["format_type"] = "llama3"
                 elif "[inst]" in template_str and "[/inst]" in template_str:
                     chat_template_info["format_type"] = "mistral"
@@ -2198,9 +2112,7 @@ class InferenceBackend:
                 chat_template_info["special_tokens"] = special_tokens
 
             else:
-                logger.info(
-                    f"No chat template found for {model_name}, will use generic formatting"
-                )
+                logger.info(f"No chat template found for {model_name}, will use generic formatting")
 
         except Exception as e:
             logger.error(f"Error loading chat template info for {model_name}: {e}")
@@ -2212,9 +2124,7 @@ class InferenceBackend:
                 f"Chat template loaded for {model_name}: {chat_template_info['format_type']} format"
             )
         else:
-            logger.info(
-                f"No built-in chat template for {model_name}, will use generic formatting"
-            )
+            logger.info(f"No built-in chat template for {model_name}, will use generic formatting")
 
     def get_current_model(self) -> Optional[str]:
         """Get currently active model name"""
diff --git a/studio/backend/core/inference/llama_cpp.py b/studio/backend/core/inference/llama_cpp.py
index 0f23549138..72dcc11beb 100644
--- a/studio/backend/core/inference/llama_cpp.py
+++ b/studio/backend/core/inference/llama_cpp.py
@@ -220,7 +220,6 @@ def _period_from_layer_types(layer_types: list) -> Optional[int]:
 def _fetch_swa_entry_from_hf(repo_id: str) -> Optional[object]:
     try:
         from huggingface_hub import hf_hub_download
-
         cfg_path = hf_hub_download(repo_id, "config.json", repo_type = "model")
         with open(cfg_path) as f:
             cfg = json.load(f)
@@ -233,9 +232,7 @@ def _fetch_swa_entry_from_hf(repo_id: str) -> Optional[object]:
         return period
     lt = src.get("layer_types")
     if isinstance(lt, list) and lt:
-        return _period_from_layer_types(lt) or [
-            "full" not in str(t).lower() for t in lt
-        ]
+        return _period_from_layer_types(lt) or ["full" not in str(t).lower() for t in lt]
     return None
 
 
@@ -255,15 +252,11 @@ def _swa_entry_from_config_obj(cfg) -> Optional[object]:
         return period
     lt = getattr(src, "layer_types", None)
     if isinstance(lt, list) and lt:
-        return _period_from_layer_types(lt) or [
-            "full" not in str(t).lower() for t in lt
-        ]
+        return _period_from_layer_types(lt) or ["full" not in str(t).lower() for t in lt]
     return None
 
 
-_SWA_PATTERN_SOURCE_RE = re.compile(
-    r"sliding_window_pattern\s*(?::\s*[\w\[\], ]*)?\s*=\s*(\d+)"
-)
+_SWA_PATTERN_SOURCE_RE = re.compile(r"sliding_window_pattern\s*(?::\s*[\w\[\], ]*)?\s*=\s*(\d+)")
 
 
 def _resolve_swa_entry_from_transformers(arch: str) -> Optional[object]:
@@ -383,7 +376,6 @@ def _hf_repo_from_url(url: Optional[str]) -> Optional[str]:
 # at module level.  See PR description for the full explanation.
 def _extract_model_size_b(model_id: str):
     from utils.models import extract_model_size_b
-
     return extract_model_size_b(model_id)
 
 
@@ -465,10 +457,7 @@ def detect_reasoning_flags(
     return flags
 
 
-def _is_mtp_model_name(
-    model_identifier: Optional[str],
-    gguf_path: Optional[str] = None,
-) -> bool:
+def _is_mtp_model_name(model_identifier: Optional[str], gguf_path: Optional[str] = None) -> bool:
     """Name-based MTP detector. Fallback for the metadata signal."""
     for cand in (model_identifier, Path(gguf_path).name if gguf_path else None):
         if cand and "-mtp" in cand.lower():
@@ -1047,9 +1036,7 @@ class LlamaCppBackend:
         if build_path.is_file():
             return str(build_path)
         if sys.platform == "win32":
-            win_path = (
-                project_root / "llama.cpp" / "build" / "bin" / "Release" / binary_name
-            )
+            win_path = project_root / "llama.cpp" / "build" / "bin" / "Release" / binary_name
             if win_path.is_file():
                 return str(win_path)
 
@@ -1071,9 +1058,7 @@ class LlamaCppBackend:
     _capability_cache: dict[tuple[str, int], dict[str, object]] = {}
 
     @classmethod
-    def probe_server_capabilities(
-        cls, binary: Optional[str] = None
-    ) -> dict[str, object]:
+    def probe_server_capabilities(cls, binary: Optional[str] = None) -> dict[str, object]:
         """Parse `llama-server --help` for feature flags. Returns
         {found, mtp_token, supports_mtp, ngram_mod_flavor,
         supports_ngram_mod, spec_draft_n_max_flag}.
@@ -1142,9 +1127,7 @@ class LlamaCppBackend:
                     # first token that isn't itself a flag, so flag
                     # references inside descriptions are ignored.
                     for tok in re.split(r"[,\s]+", stripped):
-                        if tok.startswith("--") and re.match(
-                            r"--[A-Za-z][A-Za-z0-9_-]*$", tok
-                        ):
+                        if tok.startswith("--") and re.match(r"--[A-Za-z][A-Za-z0-9_-]*$", tok):
                             current_flags.append(tok)
                         elif tok.startswith("-") and len(tok) > 1:
                             # short alias like -fa; keep scanning aliases.
@@ -1228,11 +1211,7 @@ class LlamaCppBackend:
         if m:
             prefix, _, num_total = m.group(1), m.group(2), m.group(3)
             sibling_pat = re.compile(
-                r"^"
-                + re.escape(prefix)
-                + r"-\d{5}-of-"
-                + re.escape(num_total)
-                + r"\.gguf$"
+                r"^" + re.escape(prefix) + r"-\d{5}-of-" + re.escape(num_total) + r"\.gguf$"
             )
             for sibling in main.parent.iterdir():
                 if sibling != main and sibling_pat.match(sibling.name):
@@ -1255,10 +1234,7 @@ class LlamaCppBackend:
                 return False
             for _i in range(torch.cuda.device_count()):
                 try:
-                    _arch = (
-                        getattr(torch.cuda.get_device_properties(_i), "gcnArchName", "")
-                        or ""
-                    )
+                    _arch = getattr(torch.cuda.get_device_properties(_i), "gcnArchName", "") or ""
                 except Exception:
                     continue
                 if _arch.split(":")[0].strip().lower() in {"gfx1150", "gfx1151"}:
@@ -1308,9 +1284,7 @@ class LlamaCppBackend:
                         # an empty token. An explicitly empty mask (CVD="")
                         # yields an empty `allowed` set so all GPUs are
                         # filtered out, matching the codebase convention.
-                        allowed = set(
-                            int(x.strip()) for x in cvd.split(",") if x.strip()
-                        )
+                        allowed = set(int(x.strip()) for x in cvd.split(",") if x.strip())
                     except ValueError:
                         pass
                 gpus: list[tuple[int, int]] = []
@@ -1527,9 +1501,7 @@ class LlamaCppBackend:
         return out
 
     @staticmethod
-    def _build_windows_path_dirs(
-        binary_dir: str, prefix: str, cuda_path: str
-    ) -> list[str]:
+    def _build_windows_path_dirs(binary_dir: str, prefix: str, cuda_path: str) -> list[str]:
         """Ordered PATH entries the win32 branch of start_llama_server
         prepends so llama-server.exe resolves cudart / cublas DLLs:
         binary_dir, pip nvidia wheels, CUDA_PATH/bin, CUDA_PATH/bin/x64.
@@ -1548,8 +1520,7 @@ class LlamaCppBackend:
 
     @staticmethod
     def _select_gpus(
-        model_size_bytes: int,
-        gpus: list[tuple[int, int]],
+        model_size_bytes: int, gpus: list[tuple[int, int]]
     ) -> tuple[Optional[list[int]], bool]:
         """Pick GPU(s) for a model based on estimated VRAM and free memory.
 
@@ -1612,9 +1583,7 @@ class LlamaCppBackend:
         )
 
     def _kv_heads_for_layer(self, layer_idx: int, fallback: int) -> int:
-        if self._n_kv_heads_by_layer is not None and layer_idx < len(
-            self._n_kv_heads_by_layer
-        ):
+        if self._n_kv_heads_by_layer is not None and layer_idx < len(self._n_kv_heads_by_layer):
             return self._n_kv_heads_by_layer[layer_idx]
         return fallback
 
@@ -1699,10 +1668,7 @@ class LlamaCppBackend:
 
         # Path 2: Hybrid Mamba/Attention (Qwen3.5-27B, Qwen3.5-35B-A3B)
         # Only 1 in N layers is attention; the rest are Mamba (no KV cache).
-        if (
-            self._ssm_inner_size is not None
-            and self._full_attention_interval is not None
-        ):
+        if self._ssm_inner_size is not None and self._full_attention_interval is not None:
             fai = self._full_attention_interval
             n_attn = -(-n_layers // fai) if fai > 0 else n_layers  # ceiling division
             if key_len is not None and val_len is not None:
@@ -1736,9 +1702,7 @@ class LlamaCppBackend:
             # cells = per_slot_ctx and the slots*per-slot product collapses
             # back to the constant ``n_ctx`` total.  Otherwise SWA caches
             # 2*sliding_window per slot, clamped at the per-slot ctx.
-            swa_cells_per_slot = (
-                per_slot_ctx if swa_full else min(n_ctx, 2 * swa, per_slot_ctx)
-            )
+            swa_cells_per_slot = per_slot_ctx if swa_full else min(n_ctx, 2 * swa, per_slot_ctx)
             key_len_swa = self._kv_key_length_swa or key_len
             val_len_swa = self._kv_value_length_swa or val_len
             if self._sliding_window_pattern is not None:
@@ -1755,10 +1719,7 @@ class LlamaCppBackend:
                     )
                     if is_swa:
                         swa_bytes_per_slot += (
-                            swa_cells_per_slot
-                            * layer_n_kv
-                            * (key_len_swa + val_len_swa)
-                            * bpe
+                            swa_cells_per_slot * layer_n_kv * (key_len_swa + val_len_swa) * bpe
                         )
                         if ctx_checkpoints > 0 and not swa_full:
                             checkpoint_extra_per_slot += (
@@ -1770,10 +1731,7 @@ class LlamaCppBackend:
                             )
                     else:
                         global_bytes += n_ctx * layer_n_kv * (key_len + val_len) * bpe
-                return int(
-                    global_bytes
-                    + slots * (swa_bytes_per_slot + checkpoint_extra_per_slot)
-                )
+                return int(global_bytes + slots * (swa_bytes_per_slot + checkpoint_extra_per_slot))
             n_global = max(1, n_layers_kv // 4)
             n_swa = n_layers_kv - n_global
             kv_per_token = n_kv * (key_len + val_len) * bpe
@@ -1785,9 +1743,7 @@ class LlamaCppBackend:
                 if ctx_checkpoints > 0 and not swa_full
                 else 0.0
             )
-            return int(
-                global_bytes + slots * (swa_bytes_per_slot + checkpoint_extra_per_slot)
-            )
+            return int(global_bytes + slots * (swa_bytes_per_slot + checkpoint_extra_per_slot))
 
         # Path 4: Standard GQA with explicit key/value dimensions
         if key_len is not None and val_len is not None:
@@ -1910,9 +1866,7 @@ class LlamaCppBackend:
             from huggingface_hub import get_paths_info, list_repo_files
 
             files = list_repo_files(hf_repo, token = hf_token)
-            gguf_files = [
-                f for f in files if f.endswith(".gguf") and "mmproj" not in f.lower()
-            ]
+            gguf_files = [f for f in files if f.endswith(".gguf") and "mmproj" not in f.lower()]
             if not gguf_files:
                 return None
 
@@ -2128,10 +2082,7 @@ class LlamaCppBackend:
                             if vtype == 8:  # STRING
                                 slen = struct.unpack(" %s from local HF cache",
@@ -2525,7 +2450,6 @@ class LlamaCppBackend:
         target: Optional[str] = None
         try:
             from huggingface_hub import list_repo_files
-
             target = _pick_mmproj(list_repo_files(hf_repo, token = hf_token))
         except Exception as e:
             logger.debug(f"Could not list repo files for mmproj: {e}")
@@ -2535,11 +2459,8 @@ class LlamaCppBackend:
         if target is None:
             try:
                 from utils.models.model_config import _iter_hf_cache_snapshots
-
                 for snap in _iter_hf_cache_snapshots(hf_repo):
-                    rel_files = [
-                        p.relative_to(snap).as_posix() for p in snap.rglob("*.gguf")
-                    ]
+                    rel_files = [p.relative_to(snap).as_posix() for p in snap.rglob("*.gguf")]
                     target = _pick_mmproj(rel_files)
                     if target is not None:
                         logger.info("Resolved mmproj %s from local HF cache", target)
@@ -2565,10 +2486,7 @@ class LlamaCppBackend:
             return None
 
     def _resolve_launch_mmproj_path(
-        self,
-        *,
-        model_path: str,
-        mmproj_path: Optional[str],
+        self, *, model_path: str, mmproj_path: Optional[str]
     ) -> Optional[str]:
         """Return mmproj_path iff it exists on disk AND matches the model family.
 
@@ -2622,9 +2540,7 @@ class LlamaCppBackend:
 
     @staticmethod
     def _classify_llama_start_failure(
-        output: str,
-        gguf_path: Optional[str],
-        model_identifier: Optional[str],
+        output: str, gguf_path: Optional[str], model_identifier: Optional[str]
     ) -> str:
         """Explain *why* llama-server failed to start, from its output.
 
@@ -2788,9 +2704,9 @@ class LlamaCppBackend:
                     # Re-derive after a retried probe (_mmproj_has_audio persists).
                     from utils.models.model_config import is_audio_input_type
 
-                    self._has_audio_input = bool(
-                        is_audio_input_type(self._audio_type)
-                    ) or bool(self._mmproj_has_audio)
+                    self._has_audio_input = bool(is_audio_input_type(self._audio_type)) or bool(
+                        self._mmproj_has_audio
+                    )
                 if not self._healthy:
                     return False
                 return True
@@ -2867,18 +2783,10 @@ class LlamaCppBackend:
                 cache_override = parse_cache_override(extra_args)
                 cache_type_kv = resolve_cache_type_kv(extra_args, cache_type_kv)
                 if ctx_override is not None and ctx_override > 0:
-                    logger.info(
-                        f"User --ctx-size {ctx_override} honored; "
-                        "skipping auto-reduce"
-                    )
+                    logger.info(f"User --ctx-size {ctx_override} honored; skipping auto-reduce")
                 if cache_override is not None:
-                    logger.info(
-                        f"User --cache-type-k/-v {cache_override} "
-                        "honored for KV estimate"
-                    )
-                effective_ctx = (
-                    requested_ctx if requested_ctx > 0 else (self._context_length or 0)
-                )
+                    logger.info(f"User --cache-type-k/-v {cache_override} honored for KV estimate")
+                effective_ctx = requested_ctx if requested_ctx > 0 else (self._context_length or 0)
                 max_available_ctx = self._context_length or effective_ctx
                 gpus: list[tuple[int, int]] = []
                 try:
@@ -2910,9 +2818,7 @@ class LlamaCppBackend:
                     _mtp_canonical = _canonicalize_spec_mode(speculative_type)
                     _mtp_effective = _mtp_canonical or "auto"
                     _mtp_size_for_fit = _extract_model_size_b(model_identifier)
-                    _mtp_sub_3b_for_fit = (
-                        _mtp_size_for_fit is not None and _mtp_size_for_fit < 3.0
-                    )
+                    _mtp_sub_3b_for_fit = _mtp_size_for_fit is not None and _mtp_size_for_fit < 3.0
                     _mtp_will_engage = bool(
                         not _extra_args_set_spec_type(extra_args)
                         and (
@@ -2950,9 +2856,7 @@ class LlamaCppBackend:
                         # bounds), independent of the currently requested context.
                         native_ctx_for_cap = self._context_length or effective_ctx
                         if native_ctx_for_cap > 0:
-                            ranked_for_cap = sorted(
-                                gpus, key = lambda g: g[1], reverse = True
-                            )
+                            ranked_for_cap = sorted(gpus, key = lambda g: g[1], reverse = True)
                             best_cap = 0
                             for n_gpus in range(1, len(ranked_for_cap) + 1):
                                 subset = ranked_for_cap[:n_gpus]
@@ -2990,15 +2894,10 @@ class LlamaCppBackend:
                             # -ngl (CPU layer offload). The UI is expected to
                             # have surfaced the "might be slower" warning before
                             # the user submitted a ctx above the fit ceiling.
-                            requested_total = (
-                                model_size
-                                + self._estimate_kv_cache_bytes(
-                                    effective_ctx, cache_type_kv, n_parallel = n_parallel
-                                )
-                            )
-                            gpu_indices, use_fit = self._select_gpus(
-                                requested_total, gpus
+                            requested_total = model_size + self._estimate_kv_cache_bytes(
+                                effective_ctx, cache_type_kv, n_parallel = n_parallel
                             )
+                            gpu_indices, use_fit = self._select_gpus(requested_total, gpus)
                             # No silent shrink: effective_ctx stays == requested_ctx.
                         else:
                             # Auto context: prefer fewer GPUs, cap context
@@ -3043,9 +2942,7 @@ class LlamaCppBackend:
                                         )
                                         total_mib = (model_size + kv) / (1024 * 1024)
                                         if total_mib <= pool_mib * pin_fraction:
-                                            gpu_indices = sorted(
-                                                idx for idx, _ in subset
-                                            )
+                                            gpu_indices = sorted(idx for idx, _ in subset)
                                             use_fit = False
                                             break
 
@@ -3062,9 +2959,7 @@ class LlamaCppBackend:
                             # Weights don't fit on any subset. Default the UI to
                             # 4096 so the slider doesn't land on an unusable native
                             # context. --fit on will flex -ngl at runtime.
-                            effective_ctx = (
-                                min(4096, effective_ctx) if effective_ctx > 0 else 4096
-                            )
+                            effective_ctx = min(4096, effective_ctx) if effective_ctx > 0 else 4096
 
                     if effective_ctx < original_ctx:
                         kv_est = self._estimate_kv_cache_bytes(
@@ -3112,7 +3007,6 @@ class LlamaCppBackend:
                         from utils.models.gguf_metadata import (
                             read_mmproj_audio_capability,
                         )
-
                         self._mmproj_has_audio = bool(
                             read_mmproj_audio_capability(launch_mmproj_path)
                         )
@@ -3144,9 +3038,7 @@ class LlamaCppBackend:
                 # -1 = llama.cpp auto-detect (physical cores). Pass explicitly so we
                 # do not inherit llama-server's internal default, which has historically
                 # varied (hardware concurrency incl. hyperthreads on some builds).
-                cmd.extend(
-                    ["--threads", str(n_threads if n_threads is not None else -1)]
-                )
+                cmd.extend(["--threads", str(n_threads if n_threads is not None else -1)])
 
                 # Always enable Jinja chat template rendering for proper template support
                 cmd.extend(["--jinja"])
@@ -3224,9 +3116,7 @@ class LlamaCppBackend:
                     self._supports_reasoning = flags["supports_reasoning"]
                     self._reasoning_style = flags["reasoning_style"]
                     self._reasoning_always_on = flags["reasoning_always_on"]
-                    self._supports_preserve_thinking = flags[
-                        "supports_preserve_thinking"
-                    ]
+                    self._supports_preserve_thinking = flags["supports_preserve_thinking"]
                     self._supports_tools = flags["supports_tools"]
 
                     self._chat_template_file = tempfile.NamedTemporaryFile(
@@ -3238,9 +3128,7 @@ class LlamaCppBackend:
                     self._chat_template_file.write(chat_template_override)
                     self._chat_template_file.close()
                     cmd.extend(["--chat-template-file", self._chat_template_file.name])
-                    logger.info(
-                        f"Using custom chat template file: {self._chat_template_file.name}"
-                    )
+                    logger.info(f"Using custom chat template file: {self._chat_template_file.name}")
 
                 # For reasoning models, set default thinking mode.
                 # Qwen3.5/3.6 models below 9B (0.8B, 2B, 4B) disable thinking by default.
@@ -3274,9 +3162,7 @@ class LlamaCppBackend:
                 if _os.getenv("UNSLOTH_DIRECT_STREAM", "0") == "1":
                     self._api_key = _secrets.token_urlsafe(32)
                     cmd.extend(["--api-key", self._api_key])
-                    logger.info(
-                        "llama-server started with --api-key for direct streaming"
-                    )
+                    logger.info("llama-server started with --api-key for direct streaming")
                 else:
                     self._api_key = None
 
@@ -3287,9 +3173,7 @@ class LlamaCppBackend:
                 # the managed-flag denylist via validate_extra_args().
                 if extra_args:
                     cmd.extend(str(a) for a in extra_args)
-                    logger.info(
-                        f"Appending user extra args to llama-server: {list(extra_args)}"
-                    )
+                    logger.info(f"Appending user extra args to llama-server: {list(extra_args)}")
 
                 _log_cmd = list(cmd)
                 if "--api-key" in _log_cmd:
@@ -3309,9 +3193,7 @@ class LlamaCppBackend:
                 # shared system RAM. setdefault so a user value wins.
                 if self._amd_apu_wants_unified_memory():
                     env.setdefault("GGML_CUDA_ENABLE_UNIFIED_MEMORY", "1")
-                    logger.info(
-                        "AMD unified-memory APU: set GGML_CUDA_ENABLE_UNIFIED_MEMORY=1"
-                    )
+                    logger.info("AMD unified-memory APU: set GGML_CUDA_ENABLE_UNIFIED_MEMORY=1")
 
                 if sys.platform == "win32":
                     # See _build_windows_path_dirs for ordering. #5106.
@@ -3331,13 +3213,9 @@ class LlamaCppBackend:
                     # not exist, causing a silent crash on the first GEMM.
                     # ROCBLAS_TENSILE_LIBPATH overrides that search to point at
                     # the ROCm installation where the kernel files actually are.
-                    _hip_path = os.environ.get(
-                        "HIP_PATH", os.environ.get("ROCM_PATH", "")
-                    )
+                    _hip_path = os.environ.get("HIP_PATH", os.environ.get("ROCM_PATH", ""))
                     if _hip_path:
-                        _rocblas_lib = os.path.join(
-                            _hip_path, "bin", "rocblas", "library"
-                        )
+                        _rocblas_lib = os.path.join(_hip_path, "bin", "rocblas", "library")
                         if os.path.isdir(_rocblas_lib):
                             env.setdefault("ROCBLAS_TENSILE_LIBPATH", _rocblas_lib)
                 else:
@@ -3402,9 +3280,7 @@ class LlamaCppBackend:
                             lib_dirs.append(cuda_lib)
                     existing_ld = env.get("LD_LIBRARY_PATH", "")
                     new_ld = ":".join(lib_dirs)
-                    env["LD_LIBRARY_PATH"] = (
-                        f"{new_ld}:{existing_ld}" if existing_ld else new_ld
-                    )
+                    env["LD_LIBRARY_PATH"] = f"{new_ld}:{existing_ld}" if existing_ld else new_ld
 
                 # Pin to selected GPU(s). On ROCm, llama-server (and any torch
                 # in the subprocess) honors HIP_VISIBLE_DEVICES / ROCR_VISIBLE_DEVICES;
@@ -3415,14 +3291,11 @@ class LlamaCppBackend:
                     env["CUDA_VISIBLE_DEVICES"] = pinned
                     try:
                         import torch as _torch
-
                         if getattr(_torch.version, "hip", None) is not None:
                             env["HIP_VISIBLE_DEVICES"] = pinned
                             env["ROCR_VISIBLE_DEVICES"] = pinned
                     except Exception as e:
-                        logger.debug(
-                            "Failed to set ROCm visibility env vars for child: %s", e
-                        )
+                        logger.debug("Failed to set ROCm visibility env vars for child: %s", e)
 
                 # Defensive kill: if a concurrent load slipped past Phase 1
                 # (because its `self._process` was None at the time) and
@@ -3483,7 +3356,6 @@ class LlamaCppBackend:
                 elif gguf_path:
                     try:
                         from utils.models.model_config import _extract_quant_label
-
                         self._hf_variant = _extract_quant_label(gguf_path)
                     except Exception:
                         self._hf_variant = None
@@ -3499,9 +3371,7 @@ class LlamaCppBackend:
                     effective_ctx if effective_ctx > 0 else self._context_length
                 )
                 self._max_context_length = (
-                    max_available_ctx
-                    if max_available_ctx > 0
-                    else self._effective_context_length
+                    max_available_ctx if max_available_ctx > 0 else self._effective_context_length
                 )
 
                 # Wait for llama-server to become healthy
@@ -3543,8 +3413,7 @@ class LlamaCppBackend:
                     )
 
                 logger.info(
-                    f"llama-server ready on port {self._port} "
-                    f"for model '{model_identifier}'"
+                    f"llama-server ready on port {self._port} " f"for model '{model_identifier}'"
                 )
 
             # Probe outside _lock (interruptible by /unload); init inside.
@@ -3893,9 +3762,7 @@ class LlamaCppBackend:
         return True
 
     def _classify_gpu_offload(
-        self,
-        expected_gpu: bool,
-        detected_gpus: list[tuple[int, int]],
+        self, expected_gpu: bool, detected_gpus: list[tuple[int, int]]
     ) -> Optional[bool]:
         """True if a GPU model buffer was allocated, False if only CPU
         buffers landed despite GPU intent, None when there's no signal
@@ -3974,7 +3841,6 @@ class LlamaCppBackend:
             if hasattr(self, "_chat_template_file") and self._chat_template_file:
                 try:
                     import os
-
                     os.unlink(self._chat_template_file.name)
                 except Exception:
                     pass
@@ -4105,7 +3971,6 @@ class LlamaCppBackend:
             # Linux when psutil is not installed.
             try:
                 import psutil
-
                 has_psutil = True
             except ImportError:
                 has_psutil = False
@@ -4137,8 +4002,7 @@ class LlamaCppBackend:
 
                         proc.kill()
                         logger.info(
-                            f"Killed orphaned llama-server process "
-                            f"(pid={proc.info['pid']})"
+                            f"Killed orphaned llama-server process " f"(pid={proc.info['pid']})"
                         )
                     except (
                         psutil.NoSuchProcess,
@@ -4203,7 +4067,11 @@ class LlamaCppBackend:
         """atexit handler to ensure llama-server is terminated."""
         self._kill_process()
 
-    def _wait_for_health(self, timeout: float = 120.0, interval: float = 0.5) -> bool:
+    def _wait_for_health(
+        self,
+        timeout: float = 120.0,
+        interval: float = 0.5,
+    ) -> bool:
         """
         Poll llama-server's /health endpoint until it responds 200.
 
@@ -4256,10 +4124,7 @@ class LlamaCppBackend:
         return _shared_parse_tool_calls_from_text(content)
 
     @staticmethod
-    def _build_openai_messages(
-        messages: list[dict],
-        image_b64: Optional[str] = None,
-    ) -> list[dict]:
+    def _build_openai_messages(messages: list[dict], image_b64: Optional[str] = None) -> list[dict]:
         """
         Build OpenAI-format messages, optionally injecting an image_url
         content part into the last user message for vision models.
@@ -4294,8 +4159,7 @@ class LlamaCppBackend:
 
     @staticmethod
     def _iter_text_cancellable(
-        response: "httpx.Response",
-        cancel_event: Optional[threading.Event] = None,
+        response: "httpx.Response", cancel_event: Optional[threading.Event] = None
     ) -> Generator[str, None, None]:
         """Iterate over an httpx streaming response with cancel support.
 
@@ -4368,18 +4232,14 @@ class LlamaCppBackend:
                                 r.close()
                                 return
                             except Exception as e:
-                                logger.debug(
-                                    f"Error closing response in cancel watcher: {e}"
-                                )
+                                logger.debug(f"Error closing response in cancel watcher: {e}")
                         # Response not created yet -- wait briefly and retry
                         _cancel_closed.wait(timeout = 0.1)
                     return
 
         watcher = None
         if cancel_event is not None:
-            watcher = threading.Thread(
-                target = _cancel_watcher, daemon = True, name = "prefill-cancel"
-            )
+            watcher = threading.Thread(target = _cancel_watcher, daemon = True, name = "prefill-cancel")
             watcher.start()
 
         try:
@@ -4484,9 +4344,7 @@ class LlamaCppBackend:
             # can finish.  Cancel during streaming is handled by the
             # watcher thread (closes the response on cancel_event).
             stream_timeout = httpx.Timeout(connect = 10, read = 0.5, write = 10, pool = 10)
-            _auth_headers = (
-                {"Authorization": f"Bearer {self._api_key}"} if self._api_key else None
-            )
+            _auth_headers = {"Authorization": f"Bearer {self._api_key}"} if self._api_key else None
             with httpx.Client(
                 timeout = stream_timeout, limits = httpx.Limits(max_keepalive_connections = 0)
             ) as client:
@@ -4506,9 +4364,7 @@ class LlamaCppBackend:
                     buffer = ""
                     has_content_tokens = False
                     reasoning_text = ""
-                    for raw_chunk in self._iter_text_cancellable(
-                        response, cancel_event
-                    ):
+                    for raw_chunk in self._iter_text_cancellable(response, cancel_event):
                         buffer += raw_chunk
                         while "\n" in buffer:
                             line, buffer = buffer.split("\n", 1)
@@ -4568,9 +4424,7 @@ class LlamaCppBackend:
                                         cumulative += token
                                         yield cumulative
                             except json.JSONDecodeError:
-                                logger.debug(
-                                    f"Skipping malformed SSE line: {line[:100]}"
-                                )
+                                logger.debug(f"Skipping malformed SSE line: {line[:100]}")
                         if _stream_done:
                             break  # exit outer for
                     if _metadata_usage or _metadata_timings:
@@ -4640,9 +4494,7 @@ class LlamaCppBackend:
         # XML prefixes that signal a tool call in content.
         # Empty when auto_heal is disabled so the buffer never
         # speculatively holds content for XML detection.
-        _TOOL_XML_SIGNALS = (
-            ("", "", " 0:
@@ -5138,12 +4956,7 @@ class LlamaCppBackend:
                         tool_calls = [
                             tool_calls_acc[i]
                             for i in sorted(tool_calls_acc)
-                            if (
-                                tool_calls_acc[i]
-                                .get("function", {})
-                                .get("name", "")
-                                .strip()
-                            )
+                            if (tool_calls_acc[i].get("function", {}).get("name", "").strip())
                         ] or None
                     if (
                         not tool_calls
@@ -5170,32 +4983,20 @@ class LlamaCppBackend:
                         yield {"type": "status", "text": ""}
                         if content_accum:
                             # Strip leaked tool-call XML before yielding
-                            content_accum = _strip_tool_markup(
-                                content_accum, final = True
-                            )
+                            content_accum = _strip_tool_markup(content_accum, final = True)
                         if content_accum:
                             yield {"type": "content", "text": content_accum}
-                        _fu = (
-                            _backfill_usage_from_timings(_iter_usage, _iter_timings)
-                            or {}
-                        )
+                        _fu = _backfill_usage_from_timings(_iter_usage, _iter_timings) or {}
                         _fc = _fu.get("completion_tokens", 0)
                         _fp = _fu.get("prompt_tokens", 0)
                         _tc = _fc + _accumulated_completion_tokens
-                        if (
-                            _iter_usage
-                            or _iter_timings
-                            or _accumulated_completion_tokens
-                        ):
+                        if _iter_usage or _iter_timings or _accumulated_completion_tokens:
                             _mt = dict(_iter_timings) if _iter_timings else {}
                             if _accumulated_predicted_ms or _accumulated_predicted_n:
                                 _mt["predicted_ms"] = (
-                                    _mt.get("predicted_ms", 0)
-                                    + _accumulated_predicted_ms
-                                )
-                                _tn = (
-                                    _mt.get("predicted_n", 0) + _accumulated_predicted_n
+                                    _mt.get("predicted_ms", 0) + _accumulated_predicted_ms
                                 )
+                                _tn = _mt.get("predicted_n", 0) + _accumulated_predicted_n
                                 _mt["predicted_n"] = _tn
                                 _tms = _mt["predicted_ms"]
                                 if _tms > 0:
@@ -5259,26 +5060,18 @@ class LlamaCppBackend:
                         else:
                             status_text = f"Searching: {arguments.get('query', '')}"
                     elif tool_name == "python":
-                        preview = (
-                            (arguments.get("code") or "").strip().split("\n")[0][:60]
-                        )
+                        preview = (arguments.get("code") or "").strip().split("\n")[0][:60]
                         status_text = (
-                            f"Running Python: {preview}"
-                            if preview
-                            else "Running Python..."
+                            f"Running Python: {preview}" if preview else "Running Python..."
                         )
                     elif tool_name == "terminal":
                         cmd_preview = (arguments.get("command") or "")[:60]
                         status_text = (
-                            f"Running: {cmd_preview}"
-                            if cmd_preview
-                            else "Running command..."
+                            f"Running: {cmd_preview}" if cmd_preview else "Running command..."
                         )
                     else:
                         status_text = f"Calling: {tool_name}"
-                    _repeat_render_html = (
-                        tool_name == "render_html" and _render_html_succeeded
-                    )
+                    _repeat_render_html = tool_name == "render_html" and _render_html_succeeded
                     if not _repeat_render_html:
                         yield {"type": "status", "text": status_text}
 
@@ -5450,9 +5243,7 @@ class LlamaCppBackend:
 
         try:
             stream_timeout = httpx.Timeout(connect = 10, read = 0.5, write = 10, pool = 10)
-            _auth_headers = (
-                {"Authorization": f"Bearer {self._api_key}"} if self._api_key else None
-            )
+            _auth_headers = {"Authorization": f"Bearer {self._api_key}"} if self._api_key else None
             with httpx.Client(
                 timeout = stream_timeout, limits = httpx.Limits(max_keepalive_connections = 0)
             ) as client:
@@ -5470,9 +5261,7 @@ class LlamaCppBackend:
                         )
 
                     buffer = ""
-                    for raw_chunk in self._iter_text_cancellable(
-                        response, cancel_event
-                    ):
+                    for raw_chunk in self._iter_text_cancellable(response, cancel_event):
                         buffer += raw_chunk
                         while "\n" in buffer:
                             line, buffer = buffer.split("\n", 1)
@@ -5486,9 +5275,7 @@ class LlamaCppBackend:
                                         cumulative += ""
                                         yield {
                                             "type": "content",
-                                            "text": _strip_tool_markup(
-                                                cumulative, final = True
-                                            ),
+                                            "text": _strip_tool_markup(cumulative, final = True),
                                         }
                                     else:
                                         cumulative = reasoning_text
@@ -5533,35 +5320,27 @@ class LlamaCppBackend:
                                             _last_emitted = cleaned
                                             yield {"type": "content", "text": cleaned}
                             except json.JSONDecodeError:
-                                logger.debug(
-                                    f"Skipping malformed SSE line: {line[:100]}"
-                                )
+                                logger.debug(f"Skipping malformed SSE line: {line[:100]}")
                         if _stream_done:
                             break  # exit outer for
                     _final_usage = _metadata_usage or {}
                     _final_completion = _final_usage.get("completion_tokens", 0)
                     _final_prompt = _final_usage.get("prompt_tokens", 0)
-                    _total_completion = (
-                        _final_completion + _accumulated_completion_tokens
-                    )
+                    _total_completion = _final_completion + _accumulated_completion_tokens
                     if _metadata_usage or _metadata_timings:
-                        _merged_timings = (
-                            dict(_metadata_timings) if _metadata_timings else {}
-                        )
+                        _merged_timings = dict(_metadata_timings) if _metadata_timings else {}
                         if _accumulated_predicted_ms or _accumulated_predicted_n:
                             _merged_timings["predicted_ms"] = (
-                                _merged_timings.get("predicted_ms", 0)
-                                + _accumulated_predicted_ms
+                                _merged_timings.get("predicted_ms", 0) + _accumulated_predicted_ms
                             )
                             _total_predicted_n = (
-                                _merged_timings.get("predicted_n", 0)
-                                + _accumulated_predicted_n
+                                _merged_timings.get("predicted_n", 0) + _accumulated_predicted_n
                             )
                             _merged_timings["predicted_n"] = _total_predicted_n
                             _total_predicted_ms = _merged_timings["predicted_ms"]
                             if _total_predicted_ms > 0:
-                                _merged_timings["predicted_per_second"] = (
-                                    _total_predicted_n / (_total_predicted_ms / 1000.0)
+                                _merged_timings["predicted_per_second"] = _total_predicted_n / (
+                                    _total_predicted_ms / 1000.0
                                 )
                         yield {
                             "type": "metadata",
@@ -5594,9 +5373,7 @@ class LlamaCppBackend:
         """Codec name on match, None on definitive non-audio, raises on transport/JSON errors."""
         if not self.is_loaded:
             return None
-        _auth_headers = (
-            {"Authorization": f"Bearer {self._api_key}"} if self._api_key else None
-        )
+        _auth_headers = {"Authorization": f"Bearer {self._api_key}"} if self._api_key else None
         with httpx.Client(timeout = 10, headers = _auth_headers) as client:
 
             def _detok(tid: int) -> str:
@@ -5617,9 +5394,7 @@ class LlamaCppBackend:
                 return r.json().get("tokens", [])
 
             # Check codec-specific tokens (not generic ones that may exist in non-audio models)
-            if "")) == 1 and len(_tok("<|audio_eos|>")) == 1:
                 return "csm"
@@ -5628,10 +5403,7 @@ class LlamaCppBackend:
             # Gemma 3n: ; Gemma 4: <|audio|> (not csm's <|AUDIO|>).
             if len(_tok("")) == 1 or len(_tok("<|audio|>")) == 1:
                 return "audio_vlm"
-            if (
-                len(_tok("<|bicodec_semantic_0|>")) == 1
-                and len(_tok("<|bicodec_global_0|>")) == 1
-            ):
+            if len(_tok("<|bicodec_semantic_0|>")) == 1 and len(_tok("<|bicodec_global_0|>")) == 1:
                 return "bicodec"
             if len(_tok("<|c1_0|>")) == 1 and len(_tok("<|c2_0|>")) == 1:
                 return "dac"
@@ -5675,14 +5447,10 @@ class LlamaCppBackend:
             from huggingface_hub import snapshot_download
             import os
 
-            repo_path = snapshot_download(
-                "unsloth/Spark-TTS-0.5B", local_dir = "Spark-TTS-0.5B"
-            )
+            repo_path = snapshot_download("unsloth/Spark-TTS-0.5B", local_dir = "Spark-TTS-0.5B")
             model_repo_path = os.path.abspath(repo_path)
 
-        LlamaCppBackend._codec_mgr.load_codec(
-            audio_type, device, model_repo_path = model_repo_path
-        )
+        LlamaCppBackend._codec_mgr.load_codec(audio_type, device, model_repo_path = model_repo_path)
         logger.info(f"Loaded audio codec for GGUF TTS: {audio_type}")
 
     def generate_audio_response(
@@ -5720,17 +5488,11 @@ class LlamaCppBackend:
         if need_ids:
             payload["n_probs"] = 1
 
-        _auth_headers = (
-            {"Authorization": f"Bearer {self._api_key}"} if self._api_key else None
-        )
-        with httpx.Client(
-            timeout = httpx.Timeout(300, connect = 10), headers = _auth_headers
-        ) as client:
+        _auth_headers = {"Authorization": f"Bearer {self._api_key}"} if self._api_key else None
+        with httpx.Client(timeout = httpx.Timeout(300, connect = 10), headers = _auth_headers) as client:
             resp = client.post(f"{self.base_url}/completion", json = payload)
             if resp.status_code != 200:
-                raise RuntimeError(
-                    f"llama-server returned {resp.status_code}: {resp.text}"
-                )
+                raise RuntimeError(f"llama-server returned {resp.status_code}: {resp.text}")
 
         data = resp.json()
         token_ids = (
diff --git a/studio/backend/core/inference/llama_server_args.py b/studio/backend/core/inference/llama_server_args.py
index b299e1ee9e..66cd138d99 100644
--- a/studio/backend/core/inference/llama_server_args.py
+++ b/studio/backend/core/inference/llama_server_args.py
@@ -126,9 +126,7 @@ def is_managed_flag(flag: str) -> bool:
 # stripped from inherited extras so they can't last-wins-override an
 # Apply that re-sets the same field.
 _CONTEXT_FLAGS: frozenset[str] = frozenset({"-c", "--ctx-size"})
-_CACHE_FLAGS: frozenset[str] = frozenset(
-    {"-ctk", "--cache-type-k", "-ctv", "--cache-type-v"}
-)
+_CACHE_FLAGS: frozenset[str] = frozenset({"-ctk", "--cache-type-k", "-ctv", "--cache-type-v"})
 _SPEC_FLAGS: frozenset[str] = frozenset(
     {
         "--spec-default",
@@ -157,15 +155,11 @@ _TEMPLATE_FLAGS: frozenset[str] = frozenset(
     }
 )
 
-_SHADOWING_FLAGS: frozenset[str] = (
-    _CONTEXT_FLAGS | _CACHE_FLAGS | _SPEC_FLAGS | _TEMPLATE_FLAGS
-)
+_SHADOWING_FLAGS: frozenset[str] = _CONTEXT_FLAGS | _CACHE_FLAGS | _SPEC_FLAGS | _TEMPLATE_FLAGS
 
 # Shadowing flags that take no value -- strip the flag only, never the
 # following token.
-_BOOLEAN_SHADOWING_FLAGS: frozenset[str] = frozenset(
-    {"--spec-default", "--jinja", "--no-jinja"}
-)
+_BOOLEAN_SHADOWING_FLAGS: frozenset[str] = frozenset({"--spec-default", "--jinja", "--no-jinja"})
 
 
 def parse_ctx_override(args: Optional[Iterable[str]]) -> Optional[int]:
@@ -192,31 +186,22 @@ def parse_ctx_override(args: Optional[Iterable[str]]) -> Optional[int]:
             i += 1
         else:
             if i + 1 >= n or _flag_name(tokens[i + 1]) is not None:
-                raise ValueError(
-                    f"llama-server flag '{flag}' requires an integer value"
-                )
+                raise ValueError(f"llama-server flag '{flag}' requires an integer value")
             raw_value = tokens[i + 1]
             i += 2
 
         try:
             value = int(str(raw_value).strip())
         except ValueError as exc:
-            raise ValueError(
-                f"llama-server flag '{flag}' requires an integer value"
-            ) from exc
+            raise ValueError(f"llama-server flag '{flag}' requires an integer value") from exc
         if value < 0:
-            raise ValueError(
-                f"llama-server flag '{flag}' requires a non-negative integer value"
-            )
+            raise ValueError(f"llama-server flag '{flag}' requires a non-negative integer value")
         override = value
 
     return override
 
 
-def resolve_requested_ctx(
-    args: Optional[Iterable[str]],
-    fallback_n_ctx: int,
-) -> int:
+def resolve_requested_ctx(args: Optional[Iterable[str]], fallback_n_ctx: int) -> int:
     """Return the context size load_model should treat as requested.
 
     Single source of truth for the two-line ``ctx_override = parse_ctx_override(...);
@@ -267,8 +252,7 @@ def parse_cache_override(args: Optional[Iterable[str]]) -> Optional[str]:
 
 
 def resolve_cache_type_kv(
-    args: Optional[Iterable[str]],
-    fallback_cache_type_kv: Optional[str],
+    args: Optional[Iterable[str]], fallback_cache_type_kv: Optional[str]
 ) -> Optional[str]:
     """Return the cache type load_model should treat as requested.
 
diff --git a/studio/backend/core/inference/mcp_client.py b/studio/backend/core/inference/mcp_client.py
index 2ed1a630dc..ad5f67f325 100644
--- a/studio/backend/core/inference/mcp_client.py
+++ b/studio/backend/core/inference/mcp_client.py
@@ -34,10 +34,7 @@ def parse_stdio_command(address: str) -> list[str]:
         # posix=False keeps backslash paths intact but also keeps the surrounding
         # quotes on a token. Strip a matched pair so the argv reaches the
         # subprocess clean ('"C:\\Program Files\\node"' -> C:\\Program Files\\node).
-        parts = [
-            p[1:-1] if len(p) >= 2 and p[0] == p[-1] and p[0] in "\"'" else p
-            for p in parts
-        ]
+        parts = [p[1:-1] if len(p) >= 2 and p[0] == p[-1] and p[0] in "\"'" else p for p in parts]
     return parts
 
 
@@ -104,7 +101,6 @@ async def clear_oauth_tokens_async(url: str) -> None:
     failing must not make the delete / update route 500."""
     try:
         from fastmcp.client.auth import OAuth
-
         auth = OAuth(mcp_url = url, token_storage = _oauth_store())
         await auth.token_storage_adapter.clear()
     except Exception as exc:  # noqa: BLE001
@@ -112,7 +108,11 @@ async def clear_oauth_tokens_async(url: str) -> None:
         logger.warning("Failed to clear OAuth tokens for %s: %s", url, exc)
 
 
-def _client(url: str, headers: Optional[dict], use_oauth: bool = False):
+def _client(
+    url: str,
+    headers: Optional[dict],
+    use_oauth: bool = False,
+):
     from fastmcp import Client
 
     if is_stdio(url):
@@ -142,13 +142,10 @@ def _client(url: str, headers: Optional[dict], use_oauth: bool = False):
     auth = None
     if use_oauth:
         from fastmcp.client.auth import OAuth
-
         auth = OAuth(mcp_url = url, token_storage = _oauth_store())
 
     transport_cls = (
-        SSETransport
-        if infer_transport_type_from_url(url) == "sse"
-        else StreamableHttpTransport
+        SSETransport if infer_transport_type_from_url(url) == "sse" else StreamableHttpTransport
     )
     return Client(transport_cls(url = url, headers = headers or None, auth = auth))
 
diff --git a/studio/backend/core/inference/mlx_inference.py b/studio/backend/core/inference/mlx_inference.py
index b9adba13e6..5913c29282 100644
--- a/studio/backend/core/inference/mlx_inference.py
+++ b/studio/backend/core/inference/mlx_inference.py
@@ -133,7 +133,6 @@ class MLXInferenceBackend:
 
         if hf_token:
             import os
-
             os.environ["HF_TOKEN"] = hf_token
         self._configure_memory_limits()
 
@@ -311,9 +310,7 @@ class MLXInferenceBackend:
                     elif isinstance(content, list):
                         # Prepend image if not already there
                         has_image = any(
-                            p.get("type") == "image"
-                            for p in content
-                            if isinstance(p, dict)
+                            p.get("type") == "image" for p in content if isinstance(p, dict)
                         )
                         if not has_image:
                             content.insert(0, {"type": "image"})
@@ -383,9 +380,7 @@ class MLXInferenceBackend:
             preserve_thinking = preserve_thinking,
         )
         if prompt is None:
-            raise RuntimeError(
-                "apply_chat_template returned None — tokenizer may be incompatible"
-            )
+            raise RuntimeError("apply_chat_template returned None — tokenizer may be incompatible")
 
         sampler = make_sampler(
             temp = temperature,
@@ -441,7 +436,6 @@ class MLXInferenceBackend:
                         break
             except Exception as e:
                 import traceback
-
                 logger.error("stream_generate failed:\n%s", traceback.format_exc())
                 raise
             finally:
@@ -538,9 +532,7 @@ class MLXInferenceBackend:
                     **vlm_kwargs,
                 ):
                     final_response = response
-                    token_text = (
-                        response.text if hasattr(response, "text") else str(response)
-                    )
+                    token_text = response.text if hasattr(response, "text") else str(response)
                     cumulative += token_text
                     yield cumulative
                     if cancel_event and cancel_event.is_set():
@@ -556,7 +548,10 @@ class MLXInferenceBackend:
                     )
 
     def generate_with_adapter_control(
-        self, use_adapter = None, cancel_event = None, **gen_kwargs
+        self,
+        use_adapter = None,
+        cancel_event = None,
+        **gen_kwargs,
     ) -> Generator[str, None, None]:
         # MLX LoRA adapter toggling not yet supported — generate normally
         yield from self.generate_chat_response(cancel_event = cancel_event, **gen_kwargs)
diff --git a/studio/backend/core/inference/orchestrator.py b/studio/backend/core/inference/orchestrator.py
index 9810f2b9da..1c132c3f52 100644
--- a/studio/backend/core/inference/orchestrator.py
+++ b/studio/backend/core/inference/orchestrator.py
@@ -63,9 +63,7 @@ class InferenceOrchestrator:
         self._resp_queue: Any = None
         self._cancel_event: Any = None  # mp.Event — set to cancel generation instantly
         self._lock = threading.Lock()
-        self._gen_lock = (
-            threading.Lock()
-        )  # Serializes generation — one request at a time
+        self._gen_lock = threading.Lock()  # Serializes generation — one request at a time
 
         # Dispatcher state — for compare mode (adapter-controlled requests).
         # Instead of serializing via _gen_lock, adapter-controlled requests
@@ -95,9 +93,7 @@ class InferenceOrchestrator:
         logger.info("InferenceOrchestrator initialized (subprocess mode)")
 
         # Kick off background fetch of top models from HF
-        threading.Thread(
-            target = self._fetch_top_models, daemon = True, name = "top-models"
-        ).start()
+        threading.Thread(target = self._fetch_top_models, daemon = True, name = "top-models").start()
 
     # ------------------------------------------------------------------
     # Default models (top GGUFs fetched dynamically from HF)
@@ -125,7 +121,6 @@ class InferenceOrchestrator:
         """Fetch top GGUF and non-GGUF repos from unsloth by downloads."""
         try:
             import httpx
-
             resp = httpx.get(
                 "https://huggingface.co/api/models",
                 params = {
@@ -140,14 +135,12 @@ class InferenceOrchestrator:
                 models = resp.json()
                 # Top 40 GGUFs - frontend pages through them on-demand via
                 # infinite scroll, so we send a deep pool.
-                gguf_ids = [
-                    m["id"] for m in models if m.get("id", "").upper().endswith("-GGUF")
-                ][:40]
+                gguf_ids = [m["id"] for m in models if m.get("id", "").upper().endswith("-GGUF")][
+                    :40
+                ]
                 # Top 40 non-GGUF hub models
                 hub_ids = [
-                    m["id"]
-                    for m in models
-                    if not m.get("id", "").upper().endswith("-GGUF")
+                    m["id"] for m in models if not m.get("id", "").upper().endswith("-GGUF")
                 ][:40]
                 if gguf_ids:
                     self._top_gguf_cache = gguf_ids
@@ -277,7 +270,11 @@ class InferenceOrchestrator:
         except (EOFError, OSError, ValueError):
             return None
 
-    def _wait_response(self, expected_type: str, timeout: float = 300.0) -> dict:
+    def _wait_response(
+        self,
+        expected_type: str,
+        timeout: float = 300.0,
+    ) -> dict:
         """Block until a response of the expected type arrives.
 
         Also handles 'status' and 'error' events during the wait.
@@ -329,8 +326,7 @@ class InferenceOrchestrator:
             )
 
         raise RuntimeError(
-            f"Timeout waiting for '{expected_type}' response "
-            f"(no activity for {timeout}s)"
+            f"Timeout waiting for '{expected_type}' response " f"(no activity for {timeout}s)"
         )
 
     def _drain_queue(self) -> list:
@@ -556,7 +552,11 @@ class InferenceOrchestrator:
             with self._mailbox_lock:
                 self._mailboxes.pop(request_id, None)
 
-    def _drain_mailbox(self, mailbox: queue.Queue, timeout: float = 5.0) -> None:
+    def _drain_mailbox(
+        self,
+        mailbox: queue.Queue,
+        timeout: float = 5.0,
+    ) -> None:
         """Drain a mailbox until gen_done/gen_error, discarding tokens."""
         deadline = time.monotonic() + timeout
         while time.monotonic() < deadline:
@@ -683,8 +683,7 @@ class InferenceOrchestrator:
                     # First stall and Xet was enabled -> retry with Xet disabled
                     if attempt == 0 and not disable_xet:
                         logger.warning(
-                            "Download stalled for '%s' -- retrying with "
-                            "HF_HUB_DISABLE_XET=1",
+                            "Download stalled for '%s' -- retrying with HF_HUB_DISABLE_XET=1",
                             model_name,
                         )
                         self._shutdown_subprocess(timeout = 5)
@@ -715,13 +714,9 @@ class InferenceOrchestrator:
                     # capabilities without re-entering the subprocess.
                     _tpl_info = model_info.get("chat_template_info")
                     if isinstance(_tpl_info, dict):
-                        self.models[self.active_model_name]["chat_template_info"] = (
-                            _tpl_info
-                        )
+                        self.models[self.active_model_name]["chat_template_info"] = _tpl_info
                     self.loading_models.discard(model_name)
-                    logger.info(
-                        "Model '%s' loaded successfully in subprocess", model_name
-                    )
+                    logger.info("Model '%s' loaded successfully in subprocess", model_name)
                     return True
                 else:
                     error = resp.get("error", "Failed to load model")
@@ -1157,9 +1152,7 @@ class InferenceOrchestrator:
 
             if resp is None:
                 if not self._ensure_subprocess_alive():
-                    raise RuntimeError(
-                        "Inference subprocess crashed during audio generation"
-                    )
+                    raise RuntimeError("Inference subprocess crashed during audio generation")
                 continue
 
             rtype = resp.get("type", "")
@@ -1251,9 +1244,7 @@ class InferenceOrchestrator:
 
             # Convert numpy array to list for mp.Queue serialization
             audio_data = (
-                audio_array.tolist()
-                if hasattr(audio_array, "tolist")
-                else list(audio_array)
+                audio_array.tolist() if hasattr(audio_array, "tolist") else list(audio_array)
             )
 
             cmd = {
@@ -1314,7 +1305,11 @@ class InferenceOrchestrator:
     # Local helpers (no subprocess needed)
     # ------------------------------------------------------------------
 
-    def resize_image(self, img, max_size: int = 800):
+    def resize_image(
+        self,
+        img,
+        max_size: int = 800,
+    ):
         """Resize image while maintaining aspect ratio.
         No ML imports needed — runs locally in parent process.
         """
@@ -1357,7 +1352,6 @@ class InferenceOrchestrator:
         """Parent-side gpt-oss detection so the safetensors route can run
         the same guard without an IPC round-trip to the subprocess."""
         from utils.datasets import is_gpt_oss_model_name
-
         return is_gpt_oss_model_name(model_name or self.active_model_name or "")
 
 
diff --git a/studio/backend/core/inference/pricing.py b/studio/backend/core/inference/pricing.py
index 84eec17e84..a604749c9c 100644
--- a/studio/backend/core/inference/pricing.py
+++ b/studio/backend/core/inference/pricing.py
@@ -106,11 +106,7 @@ def _lookup(provider: str, model: str) -> Optional[dict[str, float]]:
     return None
 
 
-def calculate_cost(
-    provider: str,
-    model: str,
-    usage: dict[str, Any],
-) -> dict[str, float]:
+def calculate_cost(provider: str, model: str, usage: dict[str, Any]) -> dict[str, float]:
     """Return a per-turn USD cost breakdown with per-bucket + total
     fields so the frontend can render either a single number or a
     tooltip without re-doing the math. When the model isn't in the
@@ -141,8 +137,7 @@ def calculate_cost(
     # Clamp tokens >=0 so corrupted payloads can't produce a negative bill.
     cache_creation = max(0, int(usage.get("cache_creation_input_tokens") or 0))
     cache_read_native_present = (
-        "cache_read_input_tokens" in usage
-        and usage.get("cache_read_input_tokens") is not None
+        "cache_read_input_tokens" in usage and usage.get("cache_read_input_tokens") is not None
     )
     cache_read = max(0, int(usage.get("cache_read_input_tokens") or 0))
     # Fallback to mirrored prompt_tokens_details only when the native
@@ -226,14 +221,10 @@ def calculate_cost(
         if cc_5m + cc_1h == 0 and cache_creation > 0:
             # No breakdown -- assume default 5m pool.
             cc_5m = cache_creation
-        out["cache_write_usd"] = (
-            cc_5m / 1_000_000.0
-        ) * base * ANTHROPIC_CACHE_5M_WRITE_MULT + (
+        out["cache_write_usd"] = (cc_5m / 1_000_000.0) * base * ANTHROPIC_CACHE_5M_WRITE_MULT + (
             cc_1h / 1_000_000.0
         ) * base * ANTHROPIC_CACHE_1H_WRITE_MULT
-        out["cache_read_usd"] = (
-            (cache_read / 1_000_000.0) * base * ANTHROPIC_CACHE_READ_MULT
-        )
+        out["cache_read_usd"] = (cache_read / 1_000_000.0) * base * ANTHROPIC_CACHE_READ_MULT
         # Server-tool surcharges.
         srv = usage.get("server_tool_use") or {}
         if isinstance(srv, dict):
@@ -250,9 +241,7 @@ def calculate_cost(
         if cache_read > 0:
             non_cached_input = max(0, input_tokens - cache_read)
             out["input_usd"] = (non_cached_input / 1_000_000.0) * base
-            out["cache_read_usd"] = (
-                (cache_read / 1_000_000.0) * base * OPENAI_CACHE_READ_MULT
-            )
+            out["cache_read_usd"] = (cache_read / 1_000_000.0) * base * OPENAI_CACHE_READ_MULT
         # OpenAI server-tool surcharges arrive under `openai_tool_use`
         # (normalised by the SSE finaliser from output array items).
         srv = usage.get("openai_tool_use") or {}
diff --git a/studio/backend/core/inference/providers.py b/studio/backend/core/inference/providers.py
index 785f1dec3b..19b776a6d9 100644
--- a/studio/backend/core/inference/providers.py
+++ b/studio/backend/core/inference/providers.py
@@ -258,8 +258,7 @@ PROVIDER_REGISTRY: dict[str, dict[str, Any]] = {
         # sources. The HF /v1/models response is otherwise hundreds of
         # ids long (community fine-tunes, mirrors, fp8 variants, etc.).
         "model_id_allowlist": re.compile(
-            r"^(openai|deepseek-ai|google|meta-llama|Qwen|moonshotai|"
-            r"mistralai|zai-org)/"
+            r"^(openai|deepseek-ai|google|meta-llama|Qwen|moonshotai|mistralai|zai-org)/"
         ),
         # Cap the post-filter list. /v1/models has no server-side limit
         # or popularity sort, so this is just "first N matches" — pair it
diff --git a/studio/backend/core/inference/safetensors_agentic.py b/studio/backend/core/inference/safetensors_agentic.py
index 94e9e303ab..e4eb0cd100 100644
--- a/studio/backend/core/inference/safetensors_agentic.py
+++ b/studio/backend/core/inference/safetensors_agentic.py
@@ -86,9 +86,7 @@ def _detect_render_html_tool_start(content: str) -> bool:
     if not function_match and tool_call_index < 0:
         return False
 
-    if function_match and (
-        tool_call_index < 0 or function_match.start() < tool_call_index
-    ):
+    if function_match and (tool_call_index < 0 or function_match.start() < tool_call_index):
         return function_match.group(1) == "render_html"
 
     if tool_call_index >= 0:
@@ -98,7 +96,12 @@ def _detect_render_html_tool_start(content: str) -> bool:
     return False
 
 
-def _coerce_arguments(raw_args, *, heal: bool, tool_name: str = "") -> dict:
+def _coerce_arguments(
+    raw_args,
+    *,
+    heal: bool,
+    tool_name: str = "",
+) -> dict:
     """Normalise tool ``arguments`` to a dict.
 
     Some templates emit a JSON string, others a bare query string. With
@@ -403,15 +406,11 @@ def run_safetensors_tool_loop(
                     "final answer."
                 )
             else:
-                already_ran_ok = any(
-                    k == tc_key and not err for k, err in tool_call_history
-                )
+                already_ran_ok = any(k == tc_key and not err for k, err in tool_call_history)
                 if already_ran_ok:
                     result = DUPLICATE_CALL_NUDGE
                 else:
-                    eff_timeout = (
-                        None if tool_call_timeout >= 9999 else tool_call_timeout
-                    )
+                    eff_timeout = None if tool_call_timeout >= 9999 else tool_call_timeout
                     try:
                         result = execute_tool(
                             tool_name,
@@ -432,9 +431,7 @@ def run_safetensors_tool_loop(
                     "result": result,
                 }
 
-            is_error = isinstance(result, str) and result.lstrip().startswith(
-                TOOL_ERROR_PREFIXES
-            )
+            is_error = isinstance(result, str) and result.lstrip().startswith(TOOL_ERROR_PREFIXES)
             if tool_name == "render_html" and not is_error:
                 render_html_succeeded = True
             tool_call_history.append((tc_key, is_error))
diff --git a/studio/backend/core/inference/tool_call_parser.py b/studio/backend/core/inference/tool_call_parser.py
index dacbc19ac0..23b7d4c97a 100644
--- a/studio/backend/core/inference/tool_call_parser.py
+++ b/studio/backend/core/inference/tool_call_parser.py
@@ -160,9 +160,7 @@ def parse_tool_calls_from_text(content: str, *, id_offset: int = 0) -> list[dict
                     },
                 }
                 if isinstance(tc["function"]["arguments"], dict):
-                    tc["function"]["arguments"] = json.dumps(
-                        tc["function"]["arguments"]
-                    )
+                    tc["function"]["arguments"] = json.dumps(tc["function"]["arguments"])
                 tool_calls.append(tc)
             except (json.JSONDecodeError, ValueError):
                 pass
@@ -179,11 +177,7 @@ def parse_tool_calls_from_text(content: str, *, id_offset: int = 0) -> list[dict
         for idx, fm in enumerate(func_starts):
             func_name = fm.group(1)
             body_start = fm.end()
-            next_func = (
-                func_starts[idx + 1].start()
-                if idx + 1 < len(func_starts)
-                else len(content)
-            )
+            next_func = func_starts[idx + 1].start() if idx + 1 < len(func_starts) else len(content)
             end_tag = _TC_END_TAG_RE.search(content[body_start:])
             if end_tag:
                 body_end = body_start + end_tag.start()
diff --git a/studio/backend/core/inference/tools.py b/studio/backend/core/inference/tools.py
index 0f5dbfa237..9be2276d3d 100644
--- a/studio/backend/core/inference/tools.py
+++ b/studio/backend/core/inference/tools.py
@@ -121,9 +121,7 @@ _BLOCKED_COMMANDS = (
 )
 
 
-_SHELL_SEPARATORS = frozenset(
-    {";", "&&", "||", "|", "&", "\n", "(", ")", "`", "{", "}"}
-)
+_SHELL_SEPARATORS = frozenset({";", "&&", "||", "|", "&", "\n", "(", ")", "`", "{", "}"})
 # Bash keywords that introduce a new command position (then $cmd, do $cmd, etc.).
 _SHELL_KEYWORDS_AS_SEP = frozenset({"then", "do", "else", "elif"})
 # Wrappers whose next non-flag argument is itself the command Bash will exec.
@@ -256,9 +254,7 @@ def _find_blocked_commands(command: str) -> set[str]:
         tok_lower = token.lower()
         # Match -c exactly, or combined flags ending in c (e.g. -lc, -xc)
         is_unix_c = tok_lower == "-c" or (
-            tok_lower.startswith("-")
-            and tok_lower.endswith("c")
-            and not tok_lower.startswith("--")
+            tok_lower.startswith("-") and tok_lower.endswith("c") and not tok_lower.startswith("--")
         )
         is_win_c = tok_lower == "/c"
         if not (is_unix_c or is_win_c) or i < 1 or i + 1 >= len(tokens):
@@ -370,18 +366,11 @@ def _sandbox_preexec():
         except (ValueError, OSError, AttributeError):
             pass
         try:
-            _resource.setrlimit(
-                _resource.RLIMIT_FSIZE, (100 * 1024 * 1024, 100 * 1024 * 1024)
-            )
+            _resource.setrlimit(_resource.RLIMIT_FSIZE, (100 * 1024 * 1024, 100 * 1024 * 1024))
         except (ValueError, OSError):
             pass
         try:
-            as_bytes = (
-                int(os.environ.get("UNSLOTH_STUDIO_SANDBOX_AS_GB", "8"))
-                * 1024
-                * 1024
-                * 1024
-            )
+            as_bytes = int(os.environ.get("UNSLOTH_STUDIO_SANDBOX_AS_GB", "8")) * 1024 * 1024 * 1024
             _resource.setrlimit(_resource.RLIMIT_AS, (as_bytes, as_bytes))
         except (ValueError, OSError, AttributeError):
             pass
@@ -398,9 +387,7 @@ def _sandbox_preexec():
             # value (would otherwise leave NOFILE at the parent's default).
             nofile = int(os.environ.get("UNSLOTH_STUDIO_SANDBOX_NOFILE", "16384"))
             _soft_cur, hard_cur = _resource.getrlimit(_resource.RLIMIT_NOFILE)
-            target = (
-                nofile if hard_cur == _resource.RLIM_INFINITY else min(nofile, hard_cur)
-            )
+            target = nofile if hard_cur == _resource.RLIM_INFINITY else min(nofile, hard_cur)
             _resource.setrlimit(_resource.RLIMIT_NOFILE, (target, target))
         except (ValueError, OSError, AttributeError):
             pass
@@ -432,12 +419,9 @@ def _get_project_workdir(session_id: str) -> str | None:
         return None
     try:
         from storage.studio_db import ensure_chat_project_workspace
-
         project = ensure_chat_project_workspace(project_id)
     except Exception:
-        logger.warning(
-            "Failed to resolve project sandbox for %s", session_id, exc_info = True
-        )
+        logger.warning("Failed to resolve project sandbox for %s", session_id, exc_info = True)
         return None
     if not project:
         return None
@@ -468,9 +452,7 @@ def _get_workdir(session_id: str | None = None) -> str:
             workdir = project_workdir
         elif session_id and _SESSION_ID_RE.match(session_id):
             workdir = os.path.join(sandbox_root, session_id)
-            if not os.path.realpath(workdir).startswith(
-                os.path.realpath(sandbox_root) + os.sep
-            ):
+            if not os.path.realpath(workdir).startswith(os.path.realpath(sandbox_root) + os.sep):
                 workdir = os.path.join(sandbox_root, "_invalid")
         elif session_id:
             workdir = os.path.join(sandbox_root, "_invalid")
@@ -618,9 +600,7 @@ def _mcp_specs_for_server(server: dict, mcp_tools: list[dict]) -> list[dict]:
         # Same MCP server returning duplicate tool names would also 400
         # OpenAI ("tools[N].function.name duplicates ..."). Drop dupes.
         if name in seen_names:
-            logger.warning(
-                "Skipping duplicate MCP tool '%s' on '%s'.", raw_name, display
-            )
+            logger.warning("Skipping duplicate MCP tool '%s' on '%s'.", raw_name, display)
             continue
         seen_names.add(name)
         specs.append(
@@ -629,8 +609,7 @@ def _mcp_specs_for_server(server: dict, mcp_tools: list[dict]) -> list[dict]:
                 "function": {
                     "name": name,
                     "description": f"[{display}] {tool.get('description') or ''}".strip(),
-                    "parameters": tool.get("inputSchema")
-                    or {"type": "object", "properties": {}},
+                    "parameters": tool.get("inputSchema") or {"type": "object", "properties": {}},
                 },
             }
         )
@@ -708,9 +687,7 @@ def execute_tool(
     unset (default) uses ``_EXEC_TIMEOUT`` (300 s).
     ``session_id``: optional thread/session ID for per-conversation sandbox isolation.
     """
-    logger.info(
-        f"execute_tool: name={name}, session_id={session_id}, timeout={timeout}"
-    )
+    logger.info(f"execute_tool: name={name}, session_id={session_id}, timeout={timeout}")
     effective_timeout = _EXEC_TIMEOUT if timeout is _TIMEOUT_UNSET else timeout
     if name == "render_html":
         return _render_html_result(arguments)
@@ -742,13 +719,9 @@ def execute_tool(
             timeout = effective_timeout,
         )
     if name == "python":
-        return _python_exec(
-            arguments.get("code", ""), cancel_event, effective_timeout, session_id
-        )
+        return _python_exec(arguments.get("code", ""), cancel_event, effective_timeout, session_id)
     if name == "terminal":
-        return _bash_exec(
-            arguments.get("command", ""), cancel_event, effective_timeout, session_id
-        )
+        return _bash_exec(arguments.get("command", ""), cancel_event, effective_timeout, session_id)
     return f"Unknown tool: {name}"
 
 
@@ -867,7 +840,9 @@ def _validate_and_resolve_host(hostname: str, port: int) -> tuple[bool, str, str
 
 
 def _fetch_page_text(
-    url: str, max_chars: int = _MAX_PAGE_CHARS, timeout: int = 30
+    url: str,
+    max_chars: int = _MAX_PAGE_CHARS,
+    timeout: int = 30,
 ) -> str:
     """Fetch a URL and return plain text content (HTML tags stripped).
 
@@ -921,9 +896,7 @@ def _fetch_page_text(
                 resp = opener.open(req, timeout = timeout)
             except _HTTPError as e:
                 if e.code not in (301, 302, 303, 307, 308):
-                    return (
-                        f"Failed to fetch URL: HTTP {e.code} {getattr(e, 'reason', '')}"
-                    )
+                    return f"Failed to fetch URL: HTTP {e.code} {getattr(e, 'reason', '')}"
                 location = e.headers.get("Location")
                 if not location:
                     return "Failed to fetch URL: redirect missing Location header."
@@ -1188,9 +1161,7 @@ def _check_signal_escape_patterns(code: str):
             if func_name:
                 if func_name in ("signal.signal", "signal"):
                     if len(node.args) >= 1:
-                        if _ast_name_matches(
-                            node.args[0], ("SIGALRM", "signal.SIGALRM")
-                        ):
+                        if _ast_name_matches(node.args[0], ("SIGALRM", "signal.SIGALRM")):
                             signal_tampering.append(
                                 {
                                     "type": "signal_handler_override",
@@ -1200,9 +1171,7 @@ def _check_signal_escape_patterns(code: str):
                             )
                 elif func_name in ("signal.setitimer", "setitimer"):
                     if len(node.args) >= 1:
-                        if _ast_name_matches(
-                            node.args[0], ("ITIMER_REAL", "signal.ITIMER_REAL")
-                        ):
+                        if _ast_name_matches(node.args[0], ("ITIMER_REAL", "signal.ITIMER_REAL")):
                             signal_tampering.append(
                                 {
                                     "type": "timer_manipulation",
@@ -1255,9 +1224,7 @@ def _check_signal_escape_patterns(code: str):
                     else:
                         has_opaque_kwargs = True
 
-                cmd_kw_values = [
-                    v for k, v in expanded_kwargs.items() if k in _CMD_KWARGS
-                ]
+                cmd_kw_values = [v for k, v in expanded_kwargs.items() if k in _CMD_KWARGS]
                 all_call_args = list(node.args) + cmd_kw_values
                 blocked_in_args = _check_args_for_blocked(all_call_args)
 
@@ -1267,9 +1234,7 @@ def _check_signal_escape_patterns(code: str):
                         {
                             "type": "shell_escape_dynamic",
                             "line": node.lineno,
-                            "description": (
-                                f"{shell_func}() called with dynamic **kwargs"
-                            ),
+                            "description": (f"{shell_func}() called with dynamic **kwargs"),
                         }
                     )
                 elif blocked_in_args:
@@ -1301,8 +1266,7 @@ def _check_signal_escape_patterns(code: str):
                     )
                     shell_node = expanded_kwargs.get("shell")
                     shell_safe = shell_node is None or (
-                        isinstance(shell_node, ast.Constant)
-                        and shell_node.value is False
+                        isinstance(shell_node, ast.Constant) and shell_node.value is False
                     )
                     # Dynamic shell-exec args (chr/format/concat bypasses).
                     if (
@@ -1315,15 +1279,10 @@ def _check_signal_escape_patterns(code: str):
                             if _extract_string_from_node(n) is not None:
                                 return True
                             if isinstance(n, (ast.List, ast.Tuple)):
-                                return all(
-                                    _extract_string_from_node(e) is not None
-                                    for e in n.elts
-                                )
+                                return all(_extract_string_from_node(e) is not None for e in n.elts)
                             return False
 
-                        has_non_literal = any(
-                            not _is_safe_literal(a) for a in all_call_args
-                        )
+                        has_non_literal = any(not _is_safe_literal(a) for a in all_call_args)
                         if has_non_literal:
                             shell_escapes.append(
                                 {
@@ -1582,9 +1541,7 @@ def _check_signal_escape_patterns(code: str):
         "/etc/sudoers",
         "/etc/ssh/",
     )
-    _SENSITIVE_FILE_RE = re.compile(
-        r"^/proc/(?:self|\d+)/(?:environ|cmdline|task/\d+/environ)$"
-    )
+    _SENSITIVE_FILE_RE = re.compile(r"^/proc/(?:self|\d+)/(?:environ|cmdline|task/\d+/environ)$")
 
     def _normalize_host(host: str) -> str:
         if not host:
@@ -1627,15 +1584,9 @@ def _check_signal_escape_patterns(code: str):
                 return True
             if kw.arg == "data":
                 v = kw.value
-                if (
-                    isinstance(v, ast.Call)
-                    and isinstance(v.func, ast.Name)
-                    and v.func.id == "open"
-                ):
+                if isinstance(v, ast.Call) and isinstance(v.func, ast.Name) and v.func.id == "open":
                     return True
-                if isinstance(v, ast.Constant) and isinstance(
-                    v.value, (bytes, bytearray)
-                ):
+                if isinstance(v, ast.Constant) and isinstance(v.value, (bytes, bytearray)):
                     return True
         return False
 
@@ -1777,9 +1728,7 @@ def _check_signal_escape_patterns(code: str):
         """Whether the path argument resolves to a sandbox-local literal."""
         if node is None:
             return False
-        if isinstance(node, ast.Constant) and isinstance(
-            node.value, (bytes, bytearray)
-        ):
+        if isinstance(node, ast.Constant) and isinstance(node.value, (bytes, bytearray)):
             return True  # inline bytes, no file access
         if isinstance(node, ast.Constant) and isinstance(node.value, str):
             return _is_safe_relative_path(node.value)
@@ -1865,11 +1814,7 @@ def _check_signal_escape_patterns(code: str):
                     )
 
             # Direct sock.connect((host, port)) bypasses the FQ-prefix branch below.
-            if (
-                isinstance(node.func, ast.Attribute)
-                and node.func.attr == "connect"
-                and node.args
-            ):
+            if isinstance(node.func, ast.Attribute) and node.func.attr == "connect" and node.args:
                 a0 = node.args[0]
                 host_lit = None
                 if isinstance(a0, ast.Tuple) and a0.elts:
@@ -1906,9 +1851,7 @@ def _check_signal_escape_patterns(code: str):
                         {
                             "type": "upload_blocked",
                             "line": getattr(node, "lineno", -1),
-                            "description": (
-                                "Blocked: file upload disallowed in sandbox"
-                            ),
+                            "description": ("Blocked: file upload disallowed in sandbox"),
                         }
                     )
 
@@ -2010,28 +1953,18 @@ def _check_code_safety(code: str) -> str | None:
         if info.get("error"):
             return None
 
-        reasons = [
-            item.get("description", "") for item in info.get("signal_tampering", [])
-        ]
-        shell_reasons = [
-            item.get("description", "") for item in info.get("shell_escapes", [])
-        ]
+        reasons = [item.get("description", "") for item in info.get("signal_tampering", [])]
+        shell_reasons = [item.get("description", "") for item in info.get("shell_escapes", [])]
         exception_reasons = [
             item.get("description", "") for item in info.get("exception_catching", [])
         ]
-        network_reasons = [
-            item.get("description", "") for item in info.get("network_calls", [])
-        ]
+        network_reasons = [item.get("description", "") for item in info.get("network_calls", [])]
         file_reasons = [
             item.get("description", "") for item in info.get("sensitive_file_reads", [])
         ]
         all_reasons = [
             r
-            for r in reasons
-            + shell_reasons
-            + exception_reasons
-            + network_reasons
-            + file_reasons
+            for r in reasons + shell_reasons + exception_reasons + network_reasons + file_reasons
             if r
         ]
         if all_reasons:
@@ -2063,7 +1996,11 @@ def _kill_process_tree(proc) -> None:
         pass
 
 
-def _cancel_watcher(proc, cancel_event, poll_interval = 0.2):
+def _cancel_watcher(
+    proc,
+    cancel_event,
+    poll_interval = 0.2,
+):
     """Daemon thread that kills a process when cancel_event is set."""
     while proc.poll() is None:
         if cancel_event is not None and cancel_event.is_set():
@@ -2107,9 +2044,7 @@ def _python_exec(
                     except OSError:
                         pass
     try:
-        fd, tmp_path = tempfile.mkstemp(
-            suffix = ".py", prefix = "studio_exec_", dir = workdir
-        )
+        fd, tmp_path = tempfile.mkstemp(suffix = ".py", prefix = "studio_exec_", dir = workdir)
         with os.fdopen(fd, "w") as f:
             f.write(code)
 
@@ -2170,7 +2105,6 @@ def _python_exec(
                     new_images.append(_name)
             if new_images:
                 import json as _json
-
                 result += f"\n__IMAGES__:{_json.dumps(sorted(new_images))}"
 
         return result
diff --git a/studio/backend/core/inference/worker.py b/studio/backend/core/inference/worker.py
index 31fd55a156..525aa53a70 100644
--- a/studio/backend/core/inference/worker.py
+++ b/studio/backend/core/inference/worker.py
@@ -93,9 +93,7 @@ def _build_model_config(config: dict):
     return mc
 
 
-def _get_hf_download_state(
-    model_names: list[str] | None = None,
-) -> tuple[int, bool] | None:
+def _get_hf_download_state(model_names: list[str] | None = None) -> tuple[int, bool] | None:
     """Return (total_bytes, has_incomplete) for the HF Hub cache, or None on error.
 
     When *model_names* is provided, only those models' ``blobs/``
@@ -124,7 +122,6 @@ def _get_hf_download_state(
 
         if model_names:
             from utils.paths import resolve_cached_repo_id_case
-
             for name in model_names:
                 if not name:
                     continue
@@ -265,14 +262,10 @@ def _handle_load(backend, config: dict, resp_queue: Any) -> None:
                         adapter_cfg = json.load(f)
                     training_method = adapter_cfg.get("unsloth_training_method")
                     if training_method == "lora" and load_in_4bit:
-                        logger.info(
-                            "adapter_config.json says lora — setting load_in_4bit=False"
-                        )
+                        logger.info("adapter_config.json says lora — setting load_in_4bit=False")
                         load_in_4bit = False
                     elif training_method == "qlora" and not load_in_4bit:
-                        logger.info(
-                            "adapter_config.json says qlora — setting load_in_4bit=True"
-                        )
+                        logger.info("adapter_config.json says qlora — setting load_in_4bit=True")
                         load_in_4bit = True
                     elif not training_method:
                         if (
@@ -401,12 +394,7 @@ def _handle_load(backend, config: dict, resp_queue: Any) -> None:
         )
 
 
-def _handle_generate(
-    backend,
-    cmd: dict,
-    resp_queue: Any,
-    cancel_event,
-) -> None:
+def _handle_generate(backend, cmd: dict, resp_queue: Any, cancel_event) -> None:
     """Handle a generate command: stream tokens back via resp_queue.
 
     cancel_event is an mp.Event shared with the parent process.
@@ -504,11 +492,7 @@ def _handle_generate(
         )
 
 
-def _handle_generate_audio(
-    backend,
-    cmd: dict,
-    resp_queue: Any,
-) -> None:
+def _handle_generate_audio(backend, cmd: dict, resp_queue: Any) -> None:
     """Handle TTS audio generation — returns WAV bytes + sample_rate."""
     request_id = cmd.get("request_id", "")
     try:
@@ -551,12 +535,7 @@ def _handle_generate_audio(
         )
 
 
-def _handle_generate_audio_input(
-    backend,
-    cmd: dict,
-    resp_queue: Any,
-    cancel_event,
-) -> None:
+def _handle_generate_audio_input(backend, cmd: dict, resp_queue: Any, cancel_event) -> None:
     """Handle audio input generation (ASR/Whisper) — streams text tokens back."""
     request_id = cmd.get("request_id", "")
 
@@ -591,9 +570,7 @@ def _handle_generate_audio_input(
 
         for text_chunk in generator:
             if cancel_event.is_set():
-                logger.info(
-                    "Audio input generation cancelled for request %s", request_id
-                )
+                logger.info("Audio input generation cancelled for request %s", request_id)
                 break
 
             _send_response(
@@ -660,13 +637,7 @@ def _handle_unload(backend, cmd: dict, resp_queue: Any) -> None:
         )
 
 
-def run_inference_process(
-    *,
-    cmd_queue: Any,
-    resp_queue: Any,
-    cancel_event,
-    config: dict,
-) -> None:
+def run_inference_process(*, cmd_queue: Any, resp_queue: Any, cancel_event, config: dict) -> None:
     """Subprocess entrypoint. Persistent — runs command loop until shutdown.
 
     Args:
@@ -676,9 +647,7 @@ def run_inference_process(
         config: Initial configuration dict with model info.
     """
     os.environ["TOKENIZERS_PARALLELISM"] = "false"
-    os.environ["PYTHONWARNINGS"] = (
-        "ignore"  # Suppress warnings at C-level before imports
-    )
+    os.environ["PYTHONWARNINGS"] = "ignore"  # Suppress warnings at C-level before imports
 
     if config.get("disable_xet"):
         os.environ["HF_HUB_DISABLE_XET"] = "1"
@@ -810,7 +779,6 @@ def run_inference_process(
     if sys.platform == "win32":
         try:
             import triton  # noqa: F401
-
             logger.info("Triton available — torch.compile enabled")
         except ImportError:
             os.environ["TORCHDYNAMO_DISABLE"] = "1"
@@ -986,9 +954,7 @@ def run_inference_process(
                 )
 
         except Exception as exc:
-            logger.error(
-                "Error handling command '%s': %s", cmd_type, exc, exc_info = True
-            )
+            logger.error("Error handling command '%s': %s", cmd_type, exc, exc_info = True)
             _send_response(
                 resp_queue,
                 {
diff --git a/studio/backend/core/tool_healing.py b/studio/backend/core/tool_healing.py
index e8bd7d9ea4..77619bcdb3 100644
--- a/studio/backend/core/tool_healing.py
+++ b/studio/backend/core/tool_healing.py
@@ -87,9 +87,7 @@ def parse_tool_calls_from_text(content: str) -> list[dict]:
                     },
                 }
                 if isinstance(tc["function"]["arguments"], dict):
-                    tc["function"]["arguments"] = json.dumps(
-                        tc["function"]["arguments"]
-                    )
+                    tc["function"]["arguments"] = json.dumps(tc["function"]["arguments"])
                 tool_calls.append(tc)
             except (json.JSONDecodeError, ValueError):
                 pass
@@ -108,11 +106,7 @@ def parse_tool_calls_from_text(content: str) -> list[dict]:
             func_name = fm.group(1)
             body_start = fm.end()
             # Hard boundaries: next 
-            next_func = (
-                func_starts[idx + 1].start()
-                if idx + 1 < len(func_starts)
-                else len(content)
-            )
+            next_func = func_starts[idx + 1].start() if idx + 1 < len(func_starts) else len(content)
             end_tag = _TC_END_TAG_RE.search(content[body_start:])
             if end_tag:
                 body_end = body_start + end_tag.start()
diff --git a/studio/backend/core/training/trainer.py b/studio/backend/core/training/trainer.py
index 0365b3ffd8..781c18ff15 100644
--- a/studio/backend/core/training/trainer.py
+++ b/studio/backend/core/training/trainer.py
@@ -22,9 +22,7 @@ os.environ["TOKENIZERS_PARALLELISM"] = "false"
 # (not just Pool workers) can find compiled modules.
 # NOTE: Do NOT import unsloth_zoo.compiler here -- it triggers heavy torch/triton imports.
 if sys.platform in ("win32", "darwin"):
-    _compile_cache = os.environ.get(
-        "UNSLOTH_COMPILE_LOCATION", "unsloth_compiled_cache"
-    )
+    _compile_cache = os.environ.get("UNSLOTH_COMPILE_LOCATION", "unsloth_compiled_cache")
     if not os.path.isabs(_compile_cache):
         _compile_cache = os.path.abspath(_compile_cache)
         os.environ["UNSLOTH_COMPILE_LOCATION"] = _compile_cache
@@ -136,16 +134,10 @@ class UnslothTrainer:
         self.is_cpt = False  # Set to True for Continued Pretraining
         self.is_vlm = False
         self.is_audio = False
-        self.is_audio_vlm = (
-            False  # Multimodal model (e.g. Gemma 3N) trained on audio data
-        )
+        self.is_audio_vlm = False  # Multimodal model (e.g. Gemma 3N) trained on audio data
         self._audio_type = None  # 'csm', 'whisper', 'snac', 'bicodec', 'dac'
-        self._cuda_audio_used = (
-            False  # Set once after audio CUDA preprocessing; never cleared
-        )
-        self._spark_tts_repo_dir = (
-            None  # Path to downloaded Spark-TTS repo (for BiCodecTokenizer)
-        )
+        self._cuda_audio_used = False  # Set once after audio CUDA preprocessing; never cleared
+        self._spark_tts_repo_dir = None  # Path to downloaded Spark-TTS repo (for BiCodecTokenizer)
         self.model_name = None
 
         # Training metrics tracking
@@ -205,11 +197,7 @@ class UnslothTrainer:
             self._cuda_audio_used = False
 
         # --- Detect VLM ---
-        vision = (
-            is_vision_model(model_name, hf_token = hf_token)
-            if not self.is_audio
-            else False
-        )
+        vision = is_vision_model(model_name, hf_token = hf_token) if not self.is_audio else False
         self.is_vlm = not self.is_audio_vlm and vision and is_dataset_image
 
         logger.info(
@@ -225,7 +213,6 @@ class UnslothTrainer:
         # All others work with AutoTokenizer (CSM loads its own processor inline).
         if self._audio_type == "whisper":
             from transformers import AutoProcessor
-
             self.tokenizer = AutoProcessor.from_pretrained(
                 model_name,
                 trust_remote_code = trust_remote_code,
@@ -233,7 +220,6 @@ class UnslothTrainer:
             )
         else:
             from transformers import AutoTokenizer
-
             self.tokenizer = AutoTokenizer.from_pretrained(
                 model_name,
                 trust_remote_code = trust_remote_code,
@@ -267,7 +253,14 @@ class UnslothTrainer:
         trainer_ref = self
 
         class _ProgressCallback(TrainerCallback):
-            def on_log(self, args, state, control, logs = None, **kwargs):
+            def on_log(
+                self,
+                args,
+                state,
+                control,
+                logs = None,
+                **kwargs,
+            ):
                 if not logs:
                     return
                 loss_value = logs.get("loss", logs.get("train_loss", None))
@@ -284,9 +277,7 @@ class UnslothTrainer:
                     if total_steps > 0:
                         steps_remaining = total_steps - current_step
                         if steps_remaining > 0:
-                            eta_seconds = (
-                                elapsed_seconds / current_step
-                            ) * steps_remaining
+                            eta_seconds = (elapsed_seconds / current_step) * steps_remaining
 
                 num_tokens = getattr(state, "num_input_tokens_seen", None)
 
@@ -314,9 +305,7 @@ class UnslothTrainer:
 
         return _ProgressCallback()
 
-    def _calculate_total_steps(
-        self, num_samples, batch_size, grad_accum, num_epochs, max_steps
-    ):
+    def _calculate_total_steps(self, num_samples, batch_size, grad_accum, num_epochs, max_steps):
         """Calculate total training steps from dataset size and training params."""
         if max_steps and max_steps > 0:
             return max_steps
@@ -326,16 +315,20 @@ class UnslothTrainer:
         )
         return steps_per_epoch * num_epochs
 
-    def _build_audio_training_args(self, training_args, output_dir, *, extra_args = None):
+    def _build_audio_training_args(
+        self,
+        training_args,
+        output_dir,
+        *,
+        extra_args = None,
+    ):
         """Build training args dict for audio branches.
 
         Constructs the common config (batch size, lr, warmup, fp16/bf16, etc.)
         and applies per-branch overrides via extra_args.
         """
         batch_size = training_args.get("batch_size", 2)
-        gradient_accumulation_steps = training_args.get(
-            "gradient_accumulation_steps", 4
-        )
+        gradient_accumulation_steps = training_args.get("gradient_accumulation_steps", 4)
         warmup_steps_val = training_args.get("warmup_steps", 5)
         max_steps_val = training_args.get("max_steps", 0)
         learning_rate = training_args.get("learning_rate", 2e-4)
@@ -383,7 +376,11 @@ class UnslothTrainer:
 
         return config
 
-    def _finalize_training(self, output_dir, label = ""):
+    def _finalize_training(
+        self,
+        output_dir,
+        label = "",
+    ):
         """Save model after training and update progress. Used by all training branches."""
         if self.should_stop and self.save_on_stop:
             self.trainer._save_checkpoint(self.trainer.model, trial = None)
@@ -399,9 +396,7 @@ class UnslothTrainer:
         elif self.should_stop:
             msg = f"{label} training cancelled" if label else "Training cancelled"
             logger.info(f"\n{msg}.\n")
-            self._update_progress(
-                is_training = False, status_message = "Training cancelled."
-            )
+            self._update_progress(is_training = False, status_message = "Training cancelled.")
         else:
             self.trainer.save_model()
             self.tokenizer.save_pretrained(output_dir)
@@ -429,9 +424,7 @@ class UnslothTrainer:
         ]
         # Spark-TTS path is relative to the downloaded repo
         if self._spark_tts_repo_dir:
-            spark_code_dir = os.path.join(
-                os.path.dirname(self._spark_tts_repo_dir), "Spark-TTS"
-            )
+            spark_code_dir = os.path.join(os.path.dirname(self._spark_tts_repo_dir), "Spark-TTS")
             audio_paths.append(spark_code_dir)
 
         removed_paths = []
@@ -452,7 +445,11 @@ class UnslothTrainer:
                 f"{len(removed_modules)} modules\n"
             )
 
-    def _resolve_audio_columns(self, dataset, custom_format_mapping: dict = None):
+    def _resolve_audio_columns(
+        self,
+        dataset,
+        custom_format_mapping: dict = None,
+    ):
         """Resolve audio, text, and speaker columns from user mapping or hardcoded fallback.
 
         Returns:
@@ -482,11 +479,7 @@ class UnslothTrainer:
         # Hardcoded fallback (existing behavior)
         audio_col = next((c for c in cols if c.lower() in ("audio", "speech")), None)
         text_col = next(
-            (
-                c
-                for c in cols
-                if c.lower() in ("text", "sentence", "transcript", "transcription")
-            ),
+            (c for c in cols if c.lower() in ("text", "sentence", "transcript", "transcription")),
             None,
         )
 
@@ -516,9 +509,7 @@ class UnslothTrainer:
     ) -> bool:
         """Load model for training (supports both text and vision models)"""
         self.load_in_4bit = load_in_4bit  # Store for training_meta.json
-        self.trust_remote_code = (
-            trust_remote_code  # For AutoProcessor etc. used during training
-        )
+        self.trust_remote_code = trust_remote_code  # For AutoProcessor etc. used during training
         try:
             if self.model is not None:
                 del self.model
@@ -554,18 +545,14 @@ class UnslothTrainer:
             # Remove stale compiled cache so the new model gets a fresh one
             from utils.cache_cleanup import clear_unsloth_compiled_cache
 
-            _preserve = (
-                ["Unsloth*Trainer.py"] if sys.platform in ("win32", "darwin") else None
-            )
+            _preserve = ["Unsloth*Trainer.py"] if sys.platform in ("win32", "darwin") else None
             clear_unsloth_compiled_cache(preserve_patterns = _preserve)
             # Detect audio model type dynamically (config.json + tokenizer)
             self._audio_type = detect_audio_type(model_name, hf_token)
             # audio_vlm is detected as an audio_type now, handle it separately
             if self._audio_type == "audio_vlm":
                 self.is_audio = False
-                self.is_audio_vlm = (
-                    is_dataset_audio  # Only use audio VLM path if dataset has audio
-                )
+                self.is_audio_vlm = is_dataset_audio  # Only use audio VLM path if dataset has audio
                 self._audio_type = None
             else:
                 self.is_audio = self._audio_type is not None
@@ -575,11 +562,7 @@ class UnslothTrainer:
                 self._cuda_audio_used = False
 
             # VLM: vision model with image dataset (mutually exclusive with audio paths)
-            vision = (
-                is_vision_model(model_name, hf_token = hf_token)
-                if not self.is_audio
-                else False
-            )
+            vision = is_vision_model(model_name, hf_token = hf_token) if not self.is_audio else False
             self.is_vlm = not self.is_audio_vlm and vision and is_dataset_image
             self.model_name = model_name
             self.max_seq_length = max_seq_length
@@ -587,9 +570,7 @@ class UnslothTrainer:
             logger.info(
                 f"Audio type: {self._audio_type}, is_audio: {self.is_audio}, is_audio_vlm: {self.is_audio_vlm}"
             )
-            logger.info(
-                f"Dataset has images: {is_dataset_image}, audio: {is_dataset_audio}"
-            )
+            logger.info(f"Dataset has images: {is_dataset_image}, audio: {is_dataset_audio}")
             logger.info(f"Using VLM path: {self.is_vlm}")
 
             # Reset training state for new run
@@ -603,12 +584,8 @@ class UnslothTrainer:
             )
 
             # Update UI immediately with loading message
-            model_display = (
-                model_name.split("/")[-1] if "/" in model_name else model_name
-            )
-            model_type_label = (
-                "audio" if self.is_audio else ("vision" if self.is_vlm else "text")
-            )
+            model_display = model_name.split("/")[-1] if "/" in model_name else model_name
+            model_type_label = "audio" if self.is_audio else ("vision" if self.is_vlm else "text")
             self._update_progress(
                 status_message = f"Loading {model_type_label} model... {model_display}"
             )
@@ -625,7 +602,6 @@ class UnslothTrainer:
             if "/" in model_name and not _env_offline():
                 try:
                     from huggingface_hub import model_info as hf_model_info
-
                     info = hf_model_info(model_name, token = hf_token or None)
                     # model_info succeeds even for gated repos (metadata is public),
                     # but info.gated tells us if files require acceptance/token.
@@ -644,7 +620,6 @@ class UnslothTrainer:
                         GatedRepoError,
                         RepositoryNotFoundError,
                     )
-
                     if isinstance(gate_err, (GatedRepoError, RepositoryNotFoundError)):
                         friendly = (
                             f"Access denied for '{model_name}'. This model is gated or private. "
@@ -669,12 +644,9 @@ class UnslothTrainer:
             # Derive ROCm inline (not hardware.IS_ROCM) because that flag is unset
             # until detect_hardware() runs, which isn't guaranteed in this subprocess.
             _is_rocm = (
-                bool(getattr(torch.version, "hip", None))
-                or "rocm" in torch.__version__.lower()
-            )
-            _auto_dtype = (
-                torch.float16 if (_is_rocm and not is_bfloat16_supported()) else None
+                bool(getattr(torch.version, "hip", None)) or "rocm" in torch.__version__.lower()
             )
+            _auto_dtype = torch.float16 if (_is_rocm and not is_bfloat16_supported()) else None
 
             # Branch based on model type
             if self._audio_type == "csm":
@@ -731,9 +703,7 @@ class UnslothTrainer:
                     token = hf_token,
                     trust_remote_code = trust_remote_code,
                 )
-                logger.info(
-                    f"Loaded {self._audio_type} audio model (FastLanguageModel)"
-                )
+                logger.info(f"Loaded {self._audio_type} audio model (FastLanguageModel)")
 
             elif self._audio_type == "bicodec":
                 # Spark-TTS: download full repo (contains sparktts package + BiCodec weights),
@@ -756,9 +726,7 @@ class UnslothTrainer:
                     llm_path = f"{local_dir}/LLM"
 
                 repo_path = snapshot_download(hf_repo, local_dir = local_dir)
-                self._spark_tts_repo_dir = os.path.abspath(
-                    repo_path
-                )  # Absolute path for sys.path
+                self._spark_tts_repo_dir = os.path.abspath(repo_path)  # Absolute path for sys.path
                 llm_path = os.path.join(self._spark_tts_repo_dir, "LLM")
 
                 self.model, self.tokenizer = FastModel.from_pretrained(
@@ -776,7 +744,6 @@ class UnslothTrainer:
             elif self._audio_type == "dac":
                 # OuteTTS: uses FastModel (not FastLanguageModel) with load_in_4bit=False
                 from unsloth import FastModel
-
                 self.model, self.tokenizer = FastModel.from_pretrained(
                     model_name,
                     max_seq_length = max_seq_length,
@@ -792,7 +759,6 @@ class UnslothTrainer:
                 # Audio VLM: multimodal model trained on audio (e.g. Gemma 3N)
                 # Uses FastModel (general loader) — returns (model, processor)
                 from unsloth import FastModel
-
                 self.model, self.tokenizer = FastModel.from_pretrained(
                     model_name = model_name,
                     max_seq_length = max_seq_length,
@@ -823,21 +789,15 @@ class UnslothTrainer:
                 from transformers import ProcessorMixin
 
                 tok = self.tokenizer
-                has_image_proc = isinstance(tok, ProcessorMixin) or hasattr(
-                    tok, "image_processor"
-                )
-                logger.info(
-                    f"\n[VLM Diagnostic] FastVisionModel returned: {type(tok).__name__}"
-                )
+                has_image_proc = isinstance(tok, ProcessorMixin) or hasattr(tok, "image_processor")
+                logger.info(f"\n[VLM Diagnostic] FastVisionModel returned: {type(tok).__name__}")
                 logger.info(
                     f"[VLM Diagnostic] Is ProcessorMixin: {isinstance(tok, ProcessorMixin)}"
                 )
                 logger.info(
                     f"[VLM Diagnostic] Has image_processor: {hasattr(tok, 'image_processor')}"
                 )
-                logger.info(
-                    f"[VLM Diagnostic] Usable as vision processor: {has_image_proc}\n"
-                )
+                logger.info(f"[VLM Diagnostic] Usable as vision processor: {has_image_proc}\n")
             else:
                 # Load text model - returns (model, tokenizer)
                 self.model, self.tokenizer = FastLanguageModel.from_pretrained(
@@ -960,9 +920,7 @@ class UnslothTrainer:
 
             # Full finetuning mode - skip PEFT entirely
             if not use_lora:
-                self._update_progress(
-                    status_message = "Full finetuning mode - no LoRA adapters"
-                )
+                self._update_progress(status_message = "Full finetuning mode - no LoRA adapters")
                 logger.info("Full finetuning mode - training all parameters\n")
                 return True
 
@@ -990,10 +948,7 @@ class UnslothTrainer:
             # Must be one of: True, False, or "unsloth"
             if isinstance(use_gradient_checkpointing, str):
                 use_gradient_checkpointing = use_gradient_checkpointing.strip().lower()
-                if (
-                    use_gradient_checkpointing == ""
-                    or use_gradient_checkpointing == "unsloth"
-                ):
+                if use_gradient_checkpointing == "" or use_gradient_checkpointing == "unsloth":
                     use_gradient_checkpointing = "unsloth"
                 elif use_gradient_checkpointing in ("true", "1", "yes"):
                     use_gradient_checkpointing = True
@@ -1021,14 +976,14 @@ class UnslothTrainer:
 
             # Check if model has the expected attributes
             if not hasattr(self.model, "config"):
-                error_msg = "Model does not have config attribute - model may not be loaded correctly"
+                error_msg = (
+                    "Model does not have config attribute - model may not be loaded correctly"
+                )
                 logger.error(error_msg)
                 self._update_progress(error = error_msg)
                 return False
 
-            logger.info(
-                f"Configuring LoRA adapters (r={lora_r}, alpha={lora_alpha})...\n"
-            )
+            logger.info(f"Configuring LoRA adapters (r={lora_r}, alpha={lora_alpha})...\n")
             logger.info(
                 f"Gradient checkpointing: {use_gradient_checkpointing} (type: {type(use_gradient_checkpointing).__name__})\n"
             )
@@ -1043,12 +998,8 @@ class UnslothTrainer:
                 logger.info(f"  - Target modules: {target_modules}")
                 if self.is_audio_vlm:
                     logger.info(f"  - Finetune vision layers: {finetune_vision_layers}")
-                    logger.info(
-                        f"  - Finetune language layers: {finetune_language_layers}"
-                    )
-                    logger.info(
-                        f"  - Finetune attention modules: {finetune_attention_modules}"
-                    )
+                    logger.info(f"  - Finetune language layers: {finetune_language_layers}")
+                    logger.info(f"  - Finetune attention modules: {finetune_attention_modules}")
                     logger.info(f"  - Finetune MLP modules: {finetune_mlp_modules}")
                 logger.info()
 
@@ -1061,9 +1012,7 @@ class UnslothTrainer:
                     use_gradient_checkpointing = use_gradient_checkpointing,
                     random_state = 3407,
                     use_rslora = use_rslora,
-                    loftq_config = {"loftq_bits": 4, "loftq_iter": 1}
-                    if use_loftq
-                    else None,
+                    loftq_config = {"loftq_bits": 4, "loftq_iter": 1} if use_loftq else None,
                 )
                 # Audio VLM models support VLM-style layer selection
                 if self.is_audio_vlm:
@@ -1093,9 +1042,7 @@ class UnslothTrainer:
                     use_gradient_checkpointing = use_gradient_checkpointing,
                     random_state = 3407,
                     use_rslora = use_rslora,
-                    loftq_config = {"loftq_bits": 4, "loftq_iter": 1}
-                    if use_loftq
-                    else None,
+                    loftq_config = {"loftq_bits": 4, "loftq_iter": 1} if use_loftq else None,
                     task_type = None,
                 )
 
@@ -1114,9 +1061,7 @@ class UnslothTrainer:
                     use_gradient_checkpointing = use_gradient_checkpointing,
                     random_state = 3407,
                     use_rslora = use_rslora,
-                    loftq_config = {"loftq_bits": 4, "loftq_iter": 1}
-                    if use_loftq
-                    else None,
+                    loftq_config = {"loftq_bits": 4, "loftq_iter": 1} if use_loftq else None,
                 )
 
             elif self.is_vlm:
@@ -1124,9 +1069,7 @@ class UnslothTrainer:
                 logger.info(f"Vision model LoRA configuration:")
                 logger.info(f"  - Finetune vision layers: {finetune_vision_layers}")
                 logger.info(f"  - Finetune language layers: {finetune_language_layers}")
-                logger.info(
-                    f"  - Finetune attention modules: {finetune_attention_modules}"
-                )
+                logger.info(f"  - Finetune attention modules: {finetune_attention_modules}")
                 logger.info(f"  - Finetune MLP modules: {finetune_mlp_modules}\n")
 
                 self.model = FastVisionModel.get_peft_model(
@@ -1143,9 +1086,7 @@ class UnslothTrainer:
                     use_gradient_checkpointing = use_gradient_checkpointing,
                     random_state = 3407,
                     use_rslora = use_rslora,
-                    loftq_config = {"loftq_bits": 4, "loftq_iter": 1}
-                    if use_loftq
-                    else None,
+                    loftq_config = {"loftq_bits": 4, "loftq_iter": 1} if use_loftq else None,
                     modules_to_save = modules_to_save,
                 )
             else:
@@ -1165,9 +1106,7 @@ class UnslothTrainer:
                     use_gradient_checkpointing = use_gradient_checkpointing,
                     random_state = 3407,
                     use_rslora = use_rslora,
-                    loftq_config = {"loftq_bits": 4, "loftq_iter": 1}
-                    if use_loftq
-                    else None,
+                    loftq_config = {"loftq_bits": 4, "loftq_iter": 1} if use_loftq else None,
                     modules_to_save = modules_to_save,
                 )
 
@@ -1185,9 +1124,7 @@ class UnslothTrainer:
             import sys
 
             error_details = (
-                f"{type(e).__name__}: {str(e)}"
-                if str(e)
-                else f"{type(e).__name__} (no message)"
+                f"{type(e).__name__}: {str(e)}" if str(e) else f"{type(e).__name__} (no message)"
             )
             full_traceback = traceback.format_exc()
             logger.error(f"Error preparing model: {error_details}")
@@ -1256,9 +1193,7 @@ class UnslothTrainer:
             kwargs.pop("task_ids", None)
 
             # Only keep recognized TransformersKwargs
-            clean_kwargs = {
-                k: v for k, v in kwargs.items() if k in _TRANSFORMERS_KWARGS
-            }
+            clean_kwargs = {k: v for k, v in kwargs.items() if k in _TRANSFORMERS_KWARGS}
 
             if input_ids is not None and input_ids.ndim == 2:
                 merged = self._merge_input_ids_with_input_values(
@@ -1283,9 +1218,7 @@ class UnslothTrainer:
 
             backbone_hidden_states = backbone_outputs[0]
             slice_indices = (
-                slice(-logits_to_keep, None)
-                if isinstance(logits_to_keep, int)
-                else logits_to_keep
+                slice(-logits_to_keep, None) if isinstance(logits_to_keep, int) else logits_to_keep
             )
             backbone_logits = self.lm_head(backbone_hidden_states[:, slice_indices, :])
 
@@ -1303,9 +1236,7 @@ class UnslothTrainer:
                 )
 
                 train_mask = ~(labels[:, :, 1:] == -100).all(dim = -1)
-                depth_decoder_input_ids = labels[train_mask][
-                    ..., : self.config.num_codebooks - 1
-                ]
+                depth_decoder_input_ids = labels[train_mask][..., : self.config.num_codebooks - 1]
                 depth_decoder_input_ids = nn.functional.pad(
                     depth_decoder_input_ids, (1, 0), value = 0
                 )
@@ -1320,9 +1251,9 @@ class UnslothTrainer:
                 dd_kwargs = clean_kwargs.copy()
                 # Scale num_items_in_batch for depth decoder (31 codebooks)
                 if "num_items_in_batch" in dd_kwargs:
-                    dd_kwargs["num_items_in_batch"] = dd_kwargs[
-                        "num_items_in_batch"
-                    ] * (self.config.num_codebooks - 1)
+                    dd_kwargs["num_items_in_batch"] = dd_kwargs["num_items_in_batch"] * (
+                        self.config.num_codebooks - 1
+                    )
 
                 depth_decoder_outputs = self.depth_decoder(
                     input_ids = depth_decoder_input_ids,
@@ -1359,14 +1290,10 @@ class UnslothTrainer:
                     depth_decoder_outputs.logits if depth_decoder_outputs else None
                 ),
                 depth_decoder_past_key_values = (
-                    depth_decoder_outputs.past_key_values
-                    if depth_decoder_outputs
-                    else None
+                    depth_decoder_outputs.past_key_values if depth_decoder_outputs else None
                 ),
                 depth_decoder_hidden_states = (
-                    depth_decoder_outputs.hidden_states
-                    if depth_decoder_outputs
-                    else None
+                    depth_decoder_outputs.hidden_states if depth_decoder_outputs else None
                 ),
                 depth_decoder_attentions = (
                     depth_decoder_outputs.attentions if depth_decoder_outputs else None
@@ -1380,7 +1307,11 @@ class UnslothTrainer:
         CsmForConditionalGeneration.forward = _fixed_csm_forward
         logger.info("Applied CSM forward fix (class + instance level)\n")
 
-    def _preprocess_csm_dataset(self, dataset, custom_format_mapping = None):
+    def _preprocess_csm_dataset(
+        self,
+        dataset,
+        custom_format_mapping = None,
+    ):
         """Preprocess dataset for CSM TTS training (exact notebook copy)."""
         from transformers import AutoProcessor
         from datasets import Audio
@@ -1403,17 +1334,11 @@ class UnslothTrainer:
         speaker_key = resolved["speaker_col"]
 
         if audio_col is None:
-            raise ValueError(
-                f"No audio column found in dataset. Columns: {dataset.column_names}"
-            )
+            raise ValueError(f"No audio column found in dataset. Columns: {dataset.column_names}")
         if text_col is None:
-            raise ValueError(
-                f"No text column found in dataset. Columns: {dataset.column_names}"
-            )
+            raise ValueError(f"No text column found in dataset. Columns: {dataset.column_names}")
         if speaker_key is None:
-            logger.info(
-                "No speaker found, adding default 'source' of 0 for all examples\n"
-            )
+            logger.info("No speaker found, adding default 'source' of 0 for all examples\n")
             dataset = dataset.add_column("source", ["0"] * len(dataset))
             speaker_key = "source"
 
@@ -1493,18 +1418,19 @@ class UnslothTrainer:
                 )
 
         if not processed_examples:
-            raise ValueError(
-                f"No valid examples after CSM preprocessing (skipped {skipped})"
-            )
+            raise ValueError(f"No valid examples after CSM preprocessing (skipped {skipped})")
 
         result_dataset = Dataset.from_list(processed_examples)
         logger.info(
-            f"CSM preprocessing complete: {len(result_dataset)} examples "
-            f"({skipped} skipped)\n"
+            f"CSM preprocessing complete: {len(result_dataset)} examples " f"({skipped} skipped)\n"
         )
         return result_dataset
 
-    def _format_audio_vlm_dataset(self, dataset, custom_format_mapping = None):
+    def _format_audio_vlm_dataset(
+        self,
+        dataset,
+        custom_format_mapping = None,
+    ):
         """Format dataset as audio chat messages for multimodal models (e.g. Gemma 3N).
 
         Expects columns: audio (Audio), text (str).
@@ -1563,7 +1489,11 @@ class UnslothTrainer:
         logger.info(f"Audio VLM dataset formatted: {len(dataset)} examples\n")
         return dataset
 
-    def _preprocess_snac_dataset(self, dataset, custom_format_mapping = None):
+    def _preprocess_snac_dataset(
+        self,
+        dataset,
+        custom_format_mapping = None,
+    ):
         """Preprocess dataset for Orpheus TTS training with SNAC codec.
 
         Mirrors Orpheus_(3B)-TTS.ipynb: encode audio with SNAC (24kHz, 3 hierarchical
@@ -1654,9 +1584,7 @@ class UnslothTrainer:
 
                 # --- Encode audio with SNAC (notebook lines 122-142) ---
                 waveform = (
-                    torch.from_numpy(audio_data["array"])
-                    .unsqueeze(0)
-                    .to(dtype = torch.float32)
+                    torch.from_numpy(audio_data["array"]).unsqueeze(0).to(dtype = torch.float32)
                 )
                 if resample_transform is not None:
                     waveform = resample_transform(waveform)
@@ -1670,21 +1598,11 @@ class UnslothTrainer:
                 for i in range(codes[0].shape[1]):
                     all_codes.append(codes[0][0][i].item() + AUDIO_OFFSET)
                     all_codes.append(codes[1][0][2 * i].item() + AUDIO_OFFSET + 4096)
-                    all_codes.append(
-                        codes[2][0][4 * i].item() + AUDIO_OFFSET + (2 * 4096)
-                    )
-                    all_codes.append(
-                        codes[2][0][(4 * i) + 1].item() + AUDIO_OFFSET + (3 * 4096)
-                    )
-                    all_codes.append(
-                        codes[1][0][(2 * i) + 1].item() + AUDIO_OFFSET + (4 * 4096)
-                    )
-                    all_codes.append(
-                        codes[2][0][(4 * i) + 2].item() + AUDIO_OFFSET + (5 * 4096)
-                    )
-                    all_codes.append(
-                        codes[2][0][(4 * i) + 3].item() + AUDIO_OFFSET + (6 * 4096)
-                    )
+                    all_codes.append(codes[2][0][4 * i].item() + AUDIO_OFFSET + (2 * 4096))
+                    all_codes.append(codes[2][0][(4 * i) + 1].item() + AUDIO_OFFSET + (3 * 4096))
+                    all_codes.append(codes[1][0][(2 * i) + 1].item() + AUDIO_OFFSET + (4 * 4096))
+                    all_codes.append(codes[2][0][(4 * i) + 2].item() + AUDIO_OFFSET + (5 * 4096))
+                    all_codes.append(codes[2][0][(4 * i) + 3].item() + AUDIO_OFFSET + (6 * 4096))
 
                 if len(all_codes) == 0:
                     skipped += 1
@@ -1740,9 +1658,7 @@ class UnslothTrainer:
 
             # Progress update every 100 examples
             if (idx + 1) % 100 == 0:
-                self._update_progress(
-                    status_message = f"Encoding audio... {idx + 1}/{len(dataset)}"
-                )
+                self._update_progress(status_message = f"Encoding audio... {idx + 1}/{len(dataset)}")
 
         # Free SNAC model from GPU
         logger.info("Freeing SNAC codec model from GPU...\n")
@@ -1754,18 +1670,19 @@ class UnslothTrainer:
         self._cuda_audio_used = True
 
         if not processed_examples:
-            raise ValueError(
-                f"No valid examples after SNAC preprocessing (skipped {skipped})"
-            )
+            raise ValueError(f"No valid examples after SNAC preprocessing (skipped {skipped})")
 
         result_dataset = Dataset.from_list(processed_examples)
         logger.info(
-            f"SNAC preprocessing complete: {len(result_dataset)} examples "
-            f"({skipped} skipped)\n"
+            f"SNAC preprocessing complete: {len(result_dataset)} examples " f"({skipped} skipped)\n"
         )
         return result_dataset
 
-    def _preprocess_bicodec_dataset(self, dataset, custom_format_mapping = None):
+    def _preprocess_bicodec_dataset(
+        self,
+        dataset,
+        custom_format_mapping = None,
+    ):
         """Preprocess dataset for Spark-TTS training with BiCodec tokenizer.
 
         Mirrors Spark_TTS_(0_5B).ipynb: encode audio with BiCodec (semantic + global tokens),
@@ -1779,9 +1696,7 @@ class UnslothTrainer:
 
         # The sparktts Python package lives in the SparkAudio/Spark-TTS GitHub repo,
         # NOT in the unsloth/Spark-TTS-0.5B HF model repo. Clone it if needed.
-        spark_code_dir = os.path.join(
-            os.path.dirname(self._spark_tts_repo_dir), "Spark-TTS"
-        )
+        spark_code_dir = os.path.join(os.path.dirname(self._spark_tts_repo_dir), "Spark-TTS")
         sparktts_pkg = os.path.join(spark_code_dir, "sparktts")
         if not os.path.isdir(sparktts_pkg):
             self._update_progress(status_message = "Cloning Spark-TTS code repo...")
@@ -1848,9 +1763,7 @@ class UnslothTrainer:
                 return_tensors = "pt",
                 padding = True,
             )
-            input_values = processed.input_values.to(
-                audio_tokenizer.feature_extractor.device
-            )
+            input_values = processed.input_values.to(audio_tokenizer.feature_extractor.device)
             model_output = audio_tokenizer.feature_extractor(input_values)
 
             if model_output.hidden_states is None:
@@ -1899,12 +1812,8 @@ class UnslothTrainer:
                 ref_wav_np = audio_tokenizer.get_ref_clip(audio_array)
 
                 # Prepare tensors
-                audio_tensor = (
-                    torch.from_numpy(audio_array).unsqueeze(0).float().to(device)
-                )
-                ref_wav_tensor = (
-                    torch.from_numpy(ref_wav_np).unsqueeze(0).float().to(device)
-                )
+                audio_tensor = torch.from_numpy(audio_array).unsqueeze(0).float().to(device)
+                ref_wav_tensor = torch.from_numpy(ref_wav_np).unsqueeze(0).float().to(device)
 
                 # Extract wav2vec2 features
                 feat = extract_wav2vec2_features(audio_tensor)
@@ -1916,15 +1825,10 @@ class UnslothTrainer:
                 }
 
                 # BiCodec tokenize
-                semantic_token_ids, global_token_ids = audio_tokenizer.model.tokenize(
-                    batch
-                )
+                semantic_token_ids, global_token_ids = audio_tokenizer.model.tokenize(batch)
 
                 global_tokens = "".join(
-                    [
-                        f"<|bicodec_global_{i}|>"
-                        for i in global_token_ids.squeeze().cpu().numpy()
-                    ]
+                    [f"<|bicodec_global_{i}|>" for i in global_token_ids.squeeze().cpu().numpy()]
                 )
                 semantic_tokens = "".join(
                     [
@@ -1980,9 +1884,7 @@ class UnslothTrainer:
         self._cuda_audio_used = True
 
         if not processed_examples:
-            raise ValueError(
-                f"No valid examples after BiCodec preprocessing (skipped {skipped})"
-            )
+            raise ValueError(f"No valid examples after BiCodec preprocessing (skipped {skipped})")
 
         result_dataset = Dataset.from_list(processed_examples)
         logger.info(
@@ -1995,7 +1897,11 @@ class UnslothTrainer:
         logger.info(f"Sample text length: {len(sample)} chars\n")
         return result_dataset
 
-    def _preprocess_dac_dataset(self, dataset, custom_format_mapping = None):
+    def _preprocess_dac_dataset(
+        self,
+        dataset,
+        custom_format_mapping = None,
+    ):
         """Preprocess dataset for OuteTTS training with DAC codec.
 
         Mirrors Oute_TTS_(1B).ipynb DataCreationV3: uses Whisper for word timings,
@@ -2065,9 +1971,7 @@ class UnslothTrainer:
         logger.info("Cast audio column to 24kHz\n")
 
         # Load Whisper for word timings
-        self._update_progress(
-            status_message = "Loading Whisper model for word timings..."
-        )
+        self._update_progress(status_message = "Loading Whisper model for word timings...")
         logger.info("Loading Whisper model for word timings...\n")
         import whisper
 
@@ -2086,9 +1990,7 @@ class UnslothTrainer:
         prompt_processor = PromptProcessor(model_tokenizer_path)
 
         self._update_progress(status_message = "Preprocessing audio with OuteTTS...")
-        logger.info(
-            f"DAC preprocessing: audio_col='{audio_col}', text_col='{text_col}'\n"
-        )
+        logger.info(f"DAC preprocessing: audio_col='{audio_col}', text_col='{text_col}'\n")
 
         processed_examples = []
         skipped = 0
@@ -2128,9 +2030,7 @@ class UnslothTrainer:
                     tmp.flush()
                     tmp_path = tmp.name
                 try:
-                    whisper_result = whisper_model.transcribe(
-                        tmp_path, word_timestamps = True
-                    )
+                    whisper_result = whisper_model.transcribe(tmp_path, word_timestamps = True)
                 finally:
                     Path(tmp_path).unlink(missing_ok = True)
 
@@ -2191,21 +2091,21 @@ class UnslothTrainer:
         self._cuda_audio_used = True
 
         if not processed_examples:
-            raise ValueError(
-                f"No valid examples after DAC preprocessing (skipped {skipped})"
-            )
+            raise ValueError(f"No valid examples after DAC preprocessing (skipped {skipped})")
 
         result_dataset = HFDataset.from_list(processed_examples)
         logger.info(
-            f"DAC preprocessing complete: {len(result_dataset)} examples "
-            f"({skipped} skipped)\n"
+            f"DAC preprocessing complete: {len(result_dataset)} examples " f"({skipped} skipped)\n"
         )
         sample = result_dataset[0]["text"]
         logger.info(f"Sample text (first 200 chars): {sample[:200]}...\n")
         return result_dataset
 
     def _preprocess_whisper_dataset(
-        self, dataset, eval_split = None, custom_format_mapping = None
+        self,
+        dataset,
+        eval_split = None,
+        custom_format_mapping = None,
     ):
         """Preprocess dataset for Whisper speech-to-text training.
 
@@ -2226,9 +2126,7 @@ class UnslothTrainer:
             )
 
         # Cast audio to 16kHz (Whisper's expected sample rate)
-        dataset = dataset.cast_column(
-            audio_col, Audio(sampling_rate = WHISPER_SAMPLE_RATE)
-        )
+        dataset = dataset.cast_column(audio_col, Audio(sampling_rate = WHISPER_SAMPLE_RATE))
 
         # Train/eval split (notebook does dataset.train_test_split)
         eval_dataset_raw = None
@@ -2255,11 +2153,7 @@ class UnslothTrainer:
                 try:
                     audio_data = example.get(audio_col)
                     text = example.get(text_col)
-                    if (
-                        audio_data is None
-                        or audio_data.get("array") is None
-                        or not text
-                    ):
+                    if audio_data is None or audio_data.get("array") is None or not text:
                         skipped += 1
                         continue
 
@@ -2277,9 +2171,7 @@ class UnslothTrainer:
                         }
                     )
                 except Exception as e:
-                    logger.warning(
-                        f"Error processing Whisper {split_name} example {idx}: {e}"
-                    )
+                    logger.warning(f"Error processing Whisper {split_name} example {idx}: {e}")
                     skipped += 1
                     continue
 
@@ -2294,9 +2186,7 @@ class UnslothTrainer:
             return processed
 
         train_data = process_split(dataset, "train")
-        eval_data = (
-            process_split(eval_dataset_raw, "eval") if eval_dataset_raw else None
-        )
+        eval_data = process_split(eval_dataset_raw, "eval") if eval_dataset_raw else None
 
         if not train_data:
             raise ValueError("No valid examples after Whisper preprocessing")
@@ -2331,9 +2221,7 @@ class UnslothTrainer:
                 if candidates:
                     all_files.extend(str(c) for c in candidates)
                     continue
-                raise ValueError(
-                    f"No supported data files in directory: {file_path_obj}"
-                )
+                raise ValueError(f"No supported data files in directory: {file_path_obj}")
             else:
                 all_files.append(str(file_path_obj))
         return all_files
@@ -2378,9 +2266,7 @@ class UnslothTrainer:
         try:
             dataset = None
             eval_dataset = None
-            has_separate_eval_source = (
-                False  # True if eval comes from a separate HF split
-            )
+            has_separate_eval_source = False  # True if eval comes from a separate HF split
             eval_enabled = eval_steps is not None and eval_steps > 0
             raw_text_mode = is_cpt or format_type == "raw"
 
@@ -2524,9 +2410,7 @@ class UnslothTrainer:
                         if eval_dataset is not None:
                             has_separate_eval_source = True
                 else:
-                    logger.info(
-                        "Eval disabled (eval_steps <= 0), skipping eval split detection\n"
-                    )
+                    logger.info("Eval disabled (eval_steps <= 0), skipping eval split detection\n")
 
             if dataset is None:
                 raise ValueError("No dataset provided")
@@ -2535,11 +2419,7 @@ class UnslothTrainer:
             if dataset_slice_start is not None or dataset_slice_end is not None:
                 total_rows = len(dataset)
                 start = dataset_slice_start if dataset_slice_start is not None else 0
-                end = (
-                    dataset_slice_end
-                    if dataset_slice_end is not None
-                    else total_rows - 1
-                )
+                end = dataset_slice_end if dataset_slice_end is not None else total_rows - 1
                 # Clamp to valid range
                 start = max(0, min(start, total_rows - 1))
                 end = max(start, min(end, total_rows - 1))
@@ -2570,15 +2450,11 @@ class UnslothTrainer:
                 return (train_data, eval_data)
 
             elif self._audio_type == "snac":
-                processed = self._preprocess_snac_dataset(
-                    dataset, custom_format_mapping
-                )
+                processed = self._preprocess_snac_dataset(dataset, custom_format_mapping)
                 return (processed, None)
 
             elif self._audio_type == "bicodec":
-                processed = self._preprocess_bicodec_dataset(
-                    dataset, custom_format_mapping
-                )
+                processed = self._preprocess_bicodec_dataset(dataset, custom_format_mapping)
                 return ({"dataset": processed, "final_format": "audio_bicodec"}, None)
 
             elif self._audio_type == "dac":
@@ -2628,9 +2504,7 @@ class UnslothTrainer:
                 return (dataset_info, eval_dataset)
 
             elif self.is_audio_vlm:
-                formatted = self._format_audio_vlm_dataset(
-                    dataset, custom_format_mapping
-                )
+                formatted = self._format_audio_vlm_dataset(dataset, custom_format_mapping)
                 return (formatted, None)
 
             # ========== FORMAT FIRST ==========
@@ -2666,9 +2540,7 @@ class UnslothTrainer:
             self._update_progress(
                 status_message = f"Dataset ready ({final_n:,} samples, {detected} format)"
             )
-            logger.info(
-                f"Dataset formatted successfully ({final_n} samples, {detected})\n"
-            )
+            logger.info(f"Dataset formatted successfully ({final_n} samples, {detected})\n")
 
             # ========== THEN SPLIT ==========
             if has_separate_eval_source and eval_dataset is not None:
@@ -2863,15 +2735,12 @@ class UnslothTrainer:
             # compiled modules such as UnslothSFTTrainer.
             if sys.platform in ("win32", "darwin"):
                 from utils.cache_cleanup import register_compiled_cache_on_path
-
                 register_compiled_cache_on_path()
 
             # Store training parameters for metrics calculation
             self.batch_size = training_args.get("batch_size", 2)
             self.max_seq_length = training_args.get("max_seq_length", 2048)
-            self.gradient_accumulation_steps = training_args.get(
-                "gradient_accumulation_steps", 4
-            )
+            self.gradient_accumulation_steps = training_args.get("gradient_accumulation_steps", 4)
 
             # Set training start time
             self.training_start_time = time.time()
@@ -2879,15 +2748,10 @@ class UnslothTrainer:
             self._update_progress(is_training = True, error = None)
 
             # Setup logging
-            if training_args.get("enable_wandb", False) and training_args.get(
-                "wandb_token"
-            ):
+            if training_args.get("enable_wandb", False) and training_args.get("wandb_token"):
                 os.environ["WANDB_API_KEY"] = training_args["wandb_token"]
                 import wandb
-
-                wandb.init(
-                    project = training_args.get("wandb_project", "unsloth-training")
-                )
+                wandb.init(project = training_args.get("wandb_project", "unsloth-training"))
 
             # Create output directory
             output_dir = str(resolve_output_dir(training_args.get("output_dir")))
@@ -2923,9 +2787,7 @@ class UnslothTrainer:
                     training_args.get("num_epochs", 3),
                     training_args.get("max_steps", 0),
                 )
-                self._update_progress(
-                    total_steps = total, status_message = "Starting CSM training..."
-                )
+                self._update_progress(total_steps = total, status_message = "Starting CSM training...")
                 logger.info(f"CSM training config: {config}\n")
                 self.trainer.train(
                     resume_from_checkpoint = training_args.get("resume_from_checkpoint")
@@ -2964,9 +2826,7 @@ class UnslothTrainer:
                     training_args.get("num_epochs", 3),
                     training_args.get("max_steps", 0),
                 )
-                self._update_progress(
-                    total_steps = total, status_message = "Starting SNAC training..."
-                )
+                self._update_progress(total_steps = total, status_message = "Starting SNAC training...")
                 logger.info(f"SNAC training config: {config}\n")
                 self.trainer.train(
                     resume_from_checkpoint = training_args.get("resume_from_checkpoint")
@@ -2992,9 +2852,7 @@ class UnslothTrainer:
                 trainer_kwargs = {
                     "model": self.model,
                     "train_dataset": dataset,
-                    "data_collator": DataCollatorSpeechSeq2SeqWithPadding(
-                        processor = self.tokenizer
-                    ),
+                    "data_collator": DataCollatorSpeechSeq2SeqWithPadding(processor = self.tokenizer),
                     "processing_class": self.tokenizer.feature_extractor,
                     "args": Seq2SeqTrainingArguments(**config),
                 }
@@ -3034,16 +2892,12 @@ class UnslothTrainer:
             # ========== DATA COLLATOR SELECTION ==========
             # Detect special model types
             model_name_lower = self.model_name.lower()
-            is_deepseek_ocr = (
-                "deepseek" in model_name_lower and "ocr" in model_name_lower
-            )
+            is_deepseek_ocr = "deepseek" in model_name_lower and "ocr" in model_name_lower
 
             logger.info("Configuring data collator...\n")
 
             dataset_final_format = (
-                str(dataset.get("final_format", "")).lower()
-                if isinstance(dataset, dict)
-                else ""
+                str(dataset.get("final_format", "")).lower() if isinstance(dataset, dict) else ""
             )
             raw_text_mode = dataset_final_format == "raw_text"
 
@@ -3082,9 +2936,7 @@ class UnslothTrainer:
                         image_size = 640,
                         base_size = 1024,
                         crop_mode = True,
-                        train_on_responses_only = training_args.get(
-                            "train_on_completions", False
-                        ),
+                        train_on_responses_only = training_args.get("train_on_completions", False),
                     )
                     logger.info("DeepSeek OCR data collator configured successfully\n")
 
@@ -3114,9 +2966,7 @@ class UnslothTrainer:
                         texts.append(text)
                         audios.append(example[audio_col_name]["array"])
 
-                    batch = processor(
-                        text = texts, audio = audios, return_tensors = "pt", padding = True
-                    )
+                    batch = processor(text = texts, audio = audios, return_tensors = "pt", padding = True)
 
                     # Labels = input_ids with special tokens masked
                     labels = batch["input_ids"].clone()
@@ -3144,13 +2994,9 @@ class UnslothTrainer:
                 FastVisionModel.for_training(self.model)
                 vision_image_size = training_args.get("vision_image_size")
                 if vision_image_size is None:
-                    data_collator = UnslothVisionDataCollator(
-                        self.model, self.tokenizer
-                    )
+                    data_collator = UnslothVisionDataCollator(self.model, self.tokenizer)
                 else:
-                    logger.info(
-                        f"Vision image resize: {vision_image_size} (max dimension)\n"
-                    )
+                    logger.info(f"Vision image resize: {vision_image_size} (max dimension)\n")
                     data_collator = UnslothVisionDataCollator(
                         self.model,
                         self.tokenizer,
@@ -3171,12 +3017,8 @@ class UnslothTrainer:
 
             config_args = {
                 "per_device_train_batch_size": training_args.get("batch_size", 2),
-                "gradient_accumulation_steps": training_args.get(
-                    "gradient_accumulation_steps", 4
-                ),
-                "num_train_epochs": training_args.get(
-                    "num_epochs", 3
-                ),  # Default to epochs
+                "gradient_accumulation_steps": training_args.get("gradient_accumulation_steps", 4),
+                "num_train_epochs": training_args.get("num_epochs", 3),  # Default to epochs
                 "learning_rate": lr_value,
                 "fp16": not is_bfloat16_supported(),
                 "bf16": is_bfloat16_supported(),
@@ -3206,7 +3048,6 @@ class UnslothTrainer:
             # sys.path (.venv_t5) in spawned workers.
             if sys.platform in ("win32", "darwin"):
                 import transformers as _tf
-
                 if _tf.__version__.startswith("5."):
                     config_args["dataloader_num_workers"] = 0
 
@@ -3271,9 +3112,7 @@ class UnslothTrainer:
                 logger.info(f"Configuring {label} model training parameters\n")
                 # Use provided values or defaults for vision models
                 optim_value = training_args.get("optim", "adamw_torch_fused")
-                lr_scheduler_type_value = training_args.get(
-                    "lr_scheduler_type", "cosine"
-                )
+                lr_scheduler_type_value = training_args.get("lr_scheduler_type", "cosine")
                 config_args.update(
                     {
                         "optim": optim_value,
@@ -3328,9 +3167,7 @@ class UnslothTrainer:
                 # Audio VLM (e.g. Gemma 3N + audio): raw Dataset from _format_audio_vlm_dataset
                 # Notebook uses processing_class=processor.tokenizer (text tokenizer only)
                 # Raw-text runs are routed to the text path below.
-                train_dataset = (
-                    dataset if isinstance(dataset, Dataset) else dataset["dataset"]
-                )
+                train_dataset = dataset if isinstance(dataset, Dataset) else dataset["dataset"]
                 processing_class = (
                     self.tokenizer.tokenizer
                     if hasattr(self.tokenizer, "tokenizer")
@@ -3349,9 +3186,7 @@ class UnslothTrainer:
             elif self.is_vlm and not raw_text_mode:
                 # Image VLM: dataset is dict wrapper from format_and_template_dataset
                 # Raw-text runs are routed to the text path below.
-                train_dataset = (
-                    dataset["dataset"] if isinstance(dataset, dict) else dataset
-                )
+                train_dataset = dataset["dataset"] if isinstance(dataset, dict) else dataset
                 trainer_kwargs = {
                     "model": self.model,
                     "train_dataset": train_dataset,
@@ -3440,9 +3275,7 @@ class UnslothTrainer:
             )
 
             if is_cpt:
-                logger.info(
-                    "CPT mode: skipping train_on_responses_only — training on all tokens\n"
-                )
+                logger.info("CPT mode: skipping train_on_responses_only — training on all tokens\n")
             elif raw_text_mode:
                 logger.info(
                     "Raw-text mode: skipping train_on_responses_only — training on all tokens\n"
@@ -3467,16 +3300,12 @@ class UnslothTrainer:
                         logger.info(f"Detected template: {template_name}\n")
 
                         if template_name in TEMPLATE_TO_RESPONSES_MAPPER:
-                            instruction_part = TEMPLATE_TO_RESPONSES_MAPPER[
-                                template_name
-                            ]["instruction"]
-                            response_part = TEMPLATE_TO_RESPONSES_MAPPER[template_name][
-                                "response"
+                            instruction_part = TEMPLATE_TO_RESPONSES_MAPPER[template_name][
+                                "instruction"
                             ]
+                            response_part = TEMPLATE_TO_RESPONSES_MAPPER[template_name]["response"]
 
-                            logger.info(
-                                f"Instruction marker: {instruction_part[:50]}...\n"
-                            )
+                            logger.info(f"Instruction marker: {instruction_part[:50]}...\n")
                             logger.info(f"Response marker: {response_part[:50]}...\n")
                         else:
                             logger.info(
@@ -3484,9 +3313,7 @@ class UnslothTrainer:
                             )
                             train_on_responses_enabled = False
                     else:
-                        logger.info(
-                            f"No template mapping found for model: {self.model_name}\n"
-                        )
+                        logger.info(f"No template mapping found for model: {self.model_name}\n")
                         train_on_responses_enabled = False
 
                 except Exception as e:
@@ -3522,11 +3349,7 @@ class UnslothTrainer:
                     filtered_len = len(self.trainer.train_dataset)
                     original_len = len(dataset["dataset"])
                     dropped = original_len - filtered_len
-                    drop_pct = (
-                        round(100 * dropped / original_len, 1)
-                        if original_len > 0
-                        else 0
-                    )
+                    drop_pct = round(100 * dropped / original_len, 1) if original_len > 0 else 0
 
                     if filtered_len == 0 or drop_pct > 30:
                         max_seq = training_args.get("max_seq_length", 2048)
@@ -3584,9 +3407,7 @@ class UnslothTrainer:
             # ========== PROGRESS TRACKING ==========
             self.trainer.add_callback(self._create_progress_callback())
 
-            num_samples = len(
-                dataset["dataset"] if isinstance(dataset, dict) else dataset
-            )
+            num_samples = len(dataset["dataset"] if isinstance(dataset, dict) else dataset)
             batch_size = training_args.get("batch_size", 2)
             total_steps = self._calculate_total_steps(
                 num_samples,
@@ -3600,9 +3421,7 @@ class UnslothTrainer:
             # ========== START TRAINING ==========
             self._update_progress(status_message = "Starting training...")
             logger.info("Starting training...\n")
-            self.trainer.train(
-                resume_from_checkpoint = training_args.get("resume_from_checkpoint")
-            )
+            self.trainer.train(resume_from_checkpoint = training_args.get("resume_from_checkpoint"))
 
             # ========== SAVE MODEL ==========
             self._finalize_training(output_dir)
@@ -3641,9 +3460,7 @@ class UnslothTrainer:
                 method = "lora"
 
             config["unsloth_training_method"] = method
-            logger.info(
-                f"Patching adapter_config.json with unsloth_training_method='{method}'"
-            )
+            logger.info(f"Patching adapter_config.json with unsloth_training_method='{method}'")
 
             with open(config_path, "w") as f:
                 json.dump(config, f, indent = 2)
@@ -3657,9 +3474,7 @@ class UnslothTrainer:
         self.should_stop = True
         self.save_on_stop = save
         stop_msg = (
-            "Stopping training and saving checkpoint..."
-            if save
-            else "Cancelling training..."
+            "Stopping training and saving checkpoint..." if save else "Cancelling training..."
         )
         self._update_progress(status_message = stop_msg)
 
@@ -3700,16 +3515,13 @@ def _ensure_deepseek_ocr_installed():
     try:
         # Try importing to see if already available
         from deepseek_ocr.modeling_deepseekocr import format_messages
-
         logger.info("DeepSeek OCR module already available")
         return True
     except ImportError:
         pass
 
     try:
-        logger.info(
-            "DeepSeek OCR module not found. Auto-installing from HuggingFace..."
-        )
+        logger.info("DeepSeek OCR module not found. Auto-installing from HuggingFace...")
         logger.info("\n Downloading DeepSeek OCR module from HuggingFace...\n")
 
         from huggingface_hub import snapshot_download
@@ -3723,9 +3535,7 @@ def _ensure_deepseek_ocr_installed():
         # Download to project root as 'deepseek_ocr' folder
         local_dir = os.path.join(parent_dir, "deepseek_ocr")
 
-        snapshot_download(
-            "unsloth/DeepSeek-OCR", local_dir = local_dir, local_dir_use_symlinks = False
-        )
+        snapshot_download("unsloth/DeepSeek-OCR", local_dir = local_dir, local_dir_use_symlinks = False)
 
         # Add to sys.path if not already there
         if parent_dir not in sys.path:
diff --git a/studio/backend/core/training/training.py b/studio/backend/core/training/training.py
index 0af3349c6f..d27109aedb 100644
--- a/studio/backend/core/training/training.py
+++ b/studio/backend/core/training/training.py
@@ -180,9 +180,7 @@ class TrainingBackend:
         if self._pump_thread is not None and self._pump_thread.is_alive():
             self._pump_thread.join(timeout = 5.0)
             if self._pump_thread.is_alive():
-                logger.warning(
-                    "Previous pump thread did not exit within 5s — refusing to start"
-                )
+                logger.warning("Previous pump thread did not exit within 5s — refusing to start")
                 return False
         self._pump_thread = None
 
@@ -234,9 +232,7 @@ class TrainingBackend:
             "train_on_completions": kwargs.get("train_on_completions", False),
             "finetune_vision_layers": kwargs.get("finetune_vision_layers", True),
             "finetune_language_layers": kwargs.get("finetune_language_layers", True),
-            "finetune_attention_modules": kwargs.get(
-                "finetune_attention_modules", True
-            ),
+            "finetune_attention_modules": kwargs.get("finetune_attention_modules", True),
             "finetune_mlp_modules": kwargs.get("finetune_mlp_modules", True),
             "enable_wandb": kwargs.get("enable_wandb", False),
             "wandb_token": kwargs.get("wandb_token"),
@@ -321,9 +317,7 @@ class TrainingBackend:
         self._run_finalized = False
         self._db_run_created = False
         self._db_total_steps_set = False
-        self._db_config = {
-            k: v for k, v in config.items() if k not in {"hf_token", "wandb_token"}
-        }
+        self._db_config = {k: v for k, v in config.items() if k not in {"hf_token", "wandb_token"}}
         self._db_started_at = datetime.now(timezone.utc).isoformat()
 
         # Assign subprocess handles after state reset
@@ -353,9 +347,7 @@ class TrainingBackend:
                     pass
             # Update progress immediately for responsive UI
             self._progress.status_message = (
-                "Stopping training and saving checkpoint..."
-                if save
-                else "Cancelling training..."
+                "Stopping training and saving checkpoint..." if save else "Cancelling training..."
             )
         return True
 
@@ -363,9 +355,7 @@ class TrainingBackend:
         """Force-kill the training subprocess so state can be reset immediately."""
         with self._lock:
             if self._proc is not None and self._proc.is_alive():
-                logger.info(
-                    "Force-terminating training subprocess (pid=%s)", self._proc.pid
-                )
+                logger.info("Force-terminating training subprocess (pid=%s)", self._proc.pid)
                 self._proc.terminate()
             proc = self._proc
             cancelled = self._cancel_requested
@@ -525,8 +515,7 @@ class TrainingBackend:
                     else:
                         self._progress.is_training = False
                         self._progress.error = (
-                            self._progress.error
-                            or "Training process exited unexpectedly"
+                            self._progress.error or "Training process exited unexpectedly"
                         )
 
             self._ensure_db_run_created()
@@ -566,9 +555,7 @@ class TrainingBackend:
                 try:
                     _safe_lr = float(_raw_lr) if _raw_lr is not None else None
                 except (TypeError, ValueError):
-                    logger.debug(
-                        "Could not convert learning_rate to float: %s", _raw_lr
-                    )
+                    logger.debug("Could not convert learning_rate to float: %s", _raw_lr)
                     _safe_lr = None
                 if _safe_lr is not None and not math.isfinite(_safe_lr):
                     _safe_lr = None
@@ -576,9 +563,7 @@ class TrainingBackend:
                     self._progress.loss = _safe_loss
                 if _safe_lr is not None:
                     self._progress.learning_rate = _safe_lr
-                self._progress.total_steps = event.get(
-                    "total_steps", self._progress.total_steps
-                )
+                self._progress.total_steps = event.get("total_steps", self._progress.total_steps)
                 self._progress.elapsed_seconds = event.get("elapsed_seconds")
                 self._progress.eta_seconds = event.get("eta_seconds")
                 self._progress.grad_norm = event.get("grad_norm")
@@ -622,9 +607,7 @@ class TrainingBackend:
                     try:
                         eval_loss = float(eval_loss)
                     except (TypeError, ValueError):
-                        logger.debug(
-                            "Could not convert eval_loss to float: %s", eval_loss
-                        )
+                        logger.debug("Could not convert eval_loss to float: %s", eval_loss)
                         eval_loss = None
                     if step > 0 and eval_loss is not None and math.isfinite(eval_loss):
                         self.eval_loss_history.append(eval_loss)
@@ -654,12 +637,9 @@ class TrainingBackend:
                         "job_id": self.current_job_id,
                         "model_name": self._db_config["model_name"],
                         "dataset_name": self._db_config.get("hf_dataset")
-                        or next(
-                            iter(self._db_config.get("local_datasets") or []), "unknown"
-                        ),
+                        or next(iter(self._db_config.get("local_datasets") or []), "unknown"),
                         "config_json": _json.dumps(self._db_config),
-                        "started_at": self._db_started_at
-                        or datetime.now(timezone.utc).isoformat(),
+                        "started_at": self._db_started_at or datetime.now(timezone.utc).isoformat(),
                         "total_steps": event.get("total_steps"),
                     }
                 elif (
@@ -737,10 +717,7 @@ class TrainingBackend:
         elif db_action == "update_total_steps":
             try:
                 from storage.studio_db import update_run_total_steps
-
-                update_run_total_steps(
-                    db_action_kwargs["job_id"], db_action_kwargs["total_steps"]
-                )
+                update_run_total_steps(db_action_kwargs["job_id"], db_action_kwargs["total_steps"])
                 self._db_total_steps_set = True
             except Exception:
                 logger.warning("Failed to update total_steps in DB", exc_info = True)
@@ -764,15 +741,12 @@ class TrainingBackend:
                 model_name = self._db_config["model_name"],
                 dataset_name = dataset_name,
                 config_json = _json.dumps(self._db_config),
-                started_at = self._db_started_at
-                or datetime.now(timezone.utc).isoformat(),
+                started_at = self._db_started_at or datetime.now(timezone.utc).isoformat(),
                 total_steps = self._progress.total_steps or None,
             )
             self._db_run_created = True
         except Exception:
-            logger.warning(
-                "Failed to create DB run record for early failure", exc_info = True
-            )
+            logger.warning("Failed to create DB run record for early failure", exc_info = True)
 
     def _finalize_run_in_db(
         self,
@@ -795,10 +769,7 @@ class TrainingBackend:
                 ended_at = datetime.now(timezone.utc).isoformat(),
                 final_step = self._progress.step,
                 final_loss = self._progress.loss
-                if (
-                    self._progress.loss is not None
-                    and math.isfinite(self._progress.loss)
-                )
+                if (self._progress.loss is not None and math.isfinite(self._progress.loss))
                 else None,
                 duration_seconds = self._progress.elapsed_seconds,
                 loss_sparkline = _json.dumps(sparkline),
@@ -807,17 +778,11 @@ class TrainingBackend:
             )
             self._run_finalized = True
         except Exception:
-            logger.warning(
-                "Failed to finalize run in DB (status=%s)", status, exc_info = True
-            )
+            logger.warning("Failed to finalize run in DB (status=%s)", status, exc_info = True)
 
     def _flush_metrics_to_db(self) -> None:
         """Flush buffered metrics to the database and update live progress."""
-        if (
-            not self._metric_buffer
-            or not self.current_job_id
-            or not self._db_run_created
-        ):
+        if not self._metric_buffer or not self.current_job_id or not self._db_run_created:
             return
         # Cap buffer to prevent unbounded memory growth
         if len(self._metric_buffer) > 500:
@@ -837,10 +802,7 @@ class TrainingBackend:
                 id = self.current_job_id,
                 step = self._progress.step,
                 loss = self._progress.loss
-                if (
-                    self._progress.loss is not None
-                    and math.isfinite(self._progress.loss)
-                )
+                if (self._progress.loss is not None and math.isfinite(self._progress.loss))
                 else None,
                 duration_seconds = self._progress.elapsed_seconds,
             )
@@ -873,7 +835,9 @@ class TrainingBackend:
     # ------------------------------------------------------------------
 
     def _create_loss_plot(
-        self, progress: TrainingProgress, theme: str = "light"
+        self,
+        progress: TrainingProgress,
+        theme: str = "light",
     ) -> plt.Figure:
         """Create training loss plot with theme-aware styling."""
         plt.close("all")
@@ -956,9 +920,7 @@ class TrainingBackend:
             else:
                 title = "Training Loss"
 
-            ax.set_title(
-                title, fontsize = 11, fontweight = "bold", pad = 10, color = style["text"]
-            )
+            ax.set_title(title, fontsize = 11, fontweight = "bold", pad = 10, color = style["text"])
             ax.grid(True, alpha = 0.4, linestyle = "--", color = style["grid_color"])
             ax.tick_params(colors = style["text"], which = "both")
             ax.spines["top"].set_visible(False)
diff --git a/studio/backend/core/training/worker.py b/studio/backend/core/training/worker.py
index e4ef95a375..d5d8186815 100644
--- a/studio/backend/core/training/worker.py
+++ b/studio/backend/core/training/worker.py
@@ -40,9 +40,7 @@ from utils.wheel_utils import (
 )
 
 
-def _output_dir_from_resume_checkpoint(
-    resume_from_checkpoint: str | None,
-) -> str | None:
+def _output_dir_from_resume_checkpoint(resume_from_checkpoint: str | None) -> str | None:
     if not resume_from_checkpoint:
         return None
     path = Path(resume_from_checkpoint)
@@ -107,9 +105,7 @@ if sys.platform == "win32":
 
         try:
             if os.path.isdir(_default_root):
-                for _ver in sorted(
-                    os.listdir(_default_root), key = _ver_key, reverse = True
-                ):
+                for _ver in sorted(os.listdir(_default_root), key = _ver_key, reverse = True):
                     _bin = os.path.join(_default_root, _ver, "bin")
                     if os.path.isdir(_bin):
                         _candidates.append(_bin)
@@ -259,9 +255,7 @@ def _install_package_wheel_first(
                 "(this may take several minutes)..."
             )
         else:
-            pypi_status_message = (
-                f"Installing {display_name} from PyPI for faster training..."
-            )
+            pypi_status_message = f"Installing {display_name} from PyPI for faster training..."
 
     _send_status(event_queue, pypi_status_message)
 
@@ -353,8 +347,7 @@ def _install_package_wheel_first(
         )
         _send_status(
             event_queue,
-            f"{display_name} installation timed out after "
-            f"{_run_kwargs.get('timeout')}s",
+            f"{display_name} installation timed out after " f"{_run_kwargs.get('timeout')}s",
         )
         return False
 
@@ -435,7 +428,6 @@ def _flash_linear_attention_importable() -> bool:
     try:
         import fla.modules  # noqa: F401
         import fla.ops.gated_delta_rule  # noqa: F401
-
         return True
     except Exception as exc:
         logger.warning(
@@ -473,9 +465,7 @@ def _ensure_flash_linear_attention_unconditional(event_queue: Any) -> bool:
     if os.getenv(_FLA_SKIP_ENV) == "1":
         return False
     if sys.platform == "win32":
-        logger.info(
-            "Skipping flash-linear-attention install: no prebuilt wheel for Windows"
-        )
+        logger.info("Skipping flash-linear-attention install: no prebuilt wheel for Windows")
         return False
     if sys.version_info < _FLA_MIN_PYTHON:
         logger.info(
@@ -550,9 +540,7 @@ def _ensure_flash_linear_attention_unconditional(event_queue: Any) -> bool:
         )
     except _sp.TimeoutExpired:
         logger.warning("flash-linear-attention install timed out; continuing")
-        _send_status(
-            event_queue, "flash-linear-attention install timed out; continuing"
-        )
+        _send_status(event_queue, "flash-linear-attention install timed out; continuing")
         return False
 
     if result.returncode != 0:
@@ -635,7 +623,6 @@ def _discover_fla_model_types() -> frozenset[str]:
     found: set[str] = set()
     try:
         import transformers
-
         models_root = Path(transformers.__file__).parent / "models"
         for modeling in models_root.glob("*/modeling_*.py"):
             try:
@@ -665,7 +652,6 @@ def _installed_tvm_ffi_version() -> str | None:
     """Installed apache-tvm-ffi version, or None if missing/unimportable."""
     try:
         from importlib.metadata import version as _pkg_version
-
         return _pkg_version("apache-tvm-ffi")
     except Exception:
         return None
@@ -676,7 +662,6 @@ def _tilelang_importable() -> bool:
     try:
         import tilelang  # noqa: F401
         import tvm_ffi  # noqa: F401
-
         return True
     except Exception as exc:
         logger.warning(
@@ -694,7 +679,6 @@ def _torch_has_hip() -> bool:
     """
     try:
         import torch as _torch
-
         return bool(
             getattr(_torch.version, "hip", None)
             or "rocm" in getattr(_torch, "__version__", "").lower()
@@ -734,10 +718,7 @@ def _rocm_classify_unified_memory(props: Any) -> tuple[str, bool]:
     # Arch attrs absent — fall back to device-name matching.
     dev_lower = (getattr(props, "name", "") or "").lower()
     is_unified = (
-        "890m" in dev_lower
-        or "880m" in dev_lower
-        or "8060s" in dev_lower
-        or "8050s" in dev_lower
+        "890m" in dev_lower or "880m" in dev_lower or "8060s" in dev_lower or "8050s" in dev_lower
     )
     return gcn_arch, is_unified
 
@@ -780,9 +761,7 @@ def _run_pip(cmd: list[str], event_queue: Any, label: str) -> bool:
         _send_status(event_queue, f"{label} install timed out; continuing")
         return False
     if result.returncode != 0:
-        logger.warning(
-            "%s install failed (continuing without it):\n%s", label, result.stdout
-        )
+        logger.warning("%s install failed (continuing without it):\n%s", label, result.stdout)
         _send_status(event_queue, f"{label} install failed; continuing")
         return False
     return True
@@ -807,7 +786,6 @@ def _ensure_tilelang_backend_unconditional(event_queue: Any) -> bool:
         return False
     if not _tilelang_platform_supported():
         import platform as _platform
-
         logger.info(
             "Skipping tilelang install: no prebuilt wheel for %s/%s",
             sys.platform,
@@ -883,9 +861,7 @@ def _ensure_tilelang_backend(event_queue: Any, model_name: str) -> None:
 # UNSLOTH_STUDIO_SKIP_FAST_PATH_HOOKS=1 falls back to the legacy substring path.
 
 
-def _rebind_in_already_imported_modules(
-    *, attr_name: str, old_obj: Any, new_obj: Any
-) -> int:
+def _rebind_in_already_imported_modules(*, attr_name: str, old_obj: Any, new_obj: Any) -> int:
     """Rebind `attr_name -> new_obj` in every module that already imported `old_obj`.
 
     `from X import Y` creates a local binding that reassigning X.Y won't reach.
@@ -958,9 +934,7 @@ def _install_fast_path_hooks(event_queue: Any, model_name: str) -> None:
                 try:
                     ok = bool(install_fn(event_queue))
                 except Exception as exc:
-                    logger.warning(
-                        "%s install raised: %s; falling back to torch", gate_name, exc
-                    )
+                    logger.warning("%s install raised: %s; falling back to torch", gate_name, exc)
                     ok = False
                 logger.info("%s hook done; available=%s", gate_name, ok)
             # post_available_fn handles "gate already True but ancillary kernel broken" (e.g. tilelang
@@ -969,9 +943,7 @@ def _install_fast_path_hooks(event_queue: Any, model_name: str) -> None:
                 try:
                     post_available_fn(event_queue)
                 except Exception as exc:
-                    logger.warning(
-                        "%s post-available step raised: %s; continuing", gate_name, exc
-                    )
+                    logger.warning("%s post-available step raised: %s; continuing", gate_name, exc)
             state["installed"] = True
             return ok
 
@@ -982,9 +954,7 @@ def _install_fast_path_hooks(event_queue: Any, model_name: str) -> None:
     def _fla_install(eq: Any) -> bool:
         # FLA alone ~2.35x; +tilelang adds ~26%. tilelang is GDN-only (Qwen3.5 family).
         if not _ensure_flash_linear_attention_unconditional(eq):
-            logger.info(
-                "FLA install did not produce an importable runtime; skipping TileLang"
-            )
+            logger.info("FLA install did not produce an importable runtime; skipping TileLang")
             return False
         if _model_wants_tilelang(model_name):
             _ensure_tilelang_backend_unconditional(eq)
@@ -999,10 +969,7 @@ def _install_fast_path_hooks(event_queue: Any, model_name: str) -> None:
         # FLA already imports; repair tilelang if missing or on the broken tvm-ffi list.
         if not _model_wants_tilelang(model_name):
             return
-        if (
-            _installed_tvm_ffi_version() not in _TVM_FFI_BROKEN_VERSIONS
-            and _tilelang_importable()
-        ):
+        if _installed_tvm_ffi_version() not in _TVM_FFI_BROKEN_VERSIONS and _tilelang_importable():
             return
         _ensure_tilelang_backend_unconditional(eq)
 
@@ -1018,9 +985,7 @@ def _install_fast_path_hooks(event_queue: Any, model_name: str) -> None:
             pypi_version = _CAUSAL_CONV1D_PACKAGE_VERSION,
             filename_prefix = "causal_conv1d",
             release_tag = _CAUSAL_CONV1D_RELEASE_TAG,
-            release_base_url = (
-                "https://github.com/Dao-AILab/causal-conv1d/releases/download"
-            ),
+            release_base_url = ("https://github.com/Dao-AILab/causal-conv1d/releases/download"),
         )
         return bool(ok)
 
@@ -1040,9 +1005,7 @@ def _install_fast_path_hooks(event_queue: Any, model_name: str) -> None:
         rebound = _rebind_in_already_imported_modules(
             attr_name = gate_name, old_obj = original, new_obj = wrapped
         )
-        logger.info(
-            "Installed fast-path hook on %s (rebound %d modules)", gate_name, rebound
-        )
+        logger.info("Installed fast-path hook on %s (rebound %d modules)", gate_name, rebound)
 
 
 def _should_try_runtime_flash_attn_install(max_seq_length: int) -> bool:
@@ -1190,8 +1153,7 @@ def _normalize_mlx_studio_optimizer(value):
     except KeyError:
         supported = ", ".join(sorted(_MLX_STUDIO_OPTIM_MAP))
         raise ValueError(
-            f"Unsupported optimizer for MLX training: {value!r}. "
-            f"Supported values: {supported}."
+            f"Unsupported optimizer for MLX training: {value!r}. " f"Supported values: {supported}."
         )
 
 
@@ -1213,9 +1175,7 @@ def _resolve_mlx_local_dataset_files(file_paths: list) -> list[str]:
     all_files: list[str] = []
     for dataset_file in file_paths or []:
         file_path = (
-            dataset_file
-            if os.path.isabs(dataset_file)
-            else str(resolve_dataset_path(dataset_file))
+            dataset_file if os.path.isabs(dataset_file) else str(resolve_dataset_path(dataset_file))
         )
         file_path_obj = Path(file_path)
 
@@ -1313,9 +1273,7 @@ def _run_mlx_training(event_queue, stop_queue, config):
         raise NotImplementedError(message)
 
     optim_name = _normalize_mlx_studio_optimizer(config.get("optim", "adamw_8bit"))
-    lr_scheduler_type = _normalize_mlx_studio_scheduler(
-        config.get("lr_scheduler_type", "linear")
-    )
+    lr_scheduler_type = _normalize_mlx_studio_scheduler(config.get("lr_scheduler_type", "linear"))
 
     # ── 1. Load model ──
     # Force text-only if the dataset is not an image dataset, even if the model
@@ -1344,8 +1302,7 @@ def _run_mlx_training(event_queue, stop_queue, config):
         _send(
             "status",
             status_message = (
-                "MLX vision image resize ignored for DeepSeek OCR "
-                "(uses fixed Gundam preset)."
+                "MLX vision image resize ignored for DeepSeek OCR (uses fixed Gundam preset)."
             ),
         )
         vision_image_size = None
@@ -1391,15 +1348,9 @@ def _run_mlx_training(event_queue, stop_queue, config):
         finetune_language = config.get("finetune_language_layers", True)
         finetune_attention = config.get("finetune_attention_modules", True)
         finetune_mlp = config.get("finetune_mlp_modules", True)
-        finetune_vision = (
-            config.get("finetune_vision_layers", False) if is_vlm else False
-        )
+        finetune_vision = config.get("finetune_vision_layers", False) if is_vlm else False
 
-        if (
-            (finetune_attention or finetune_mlp)
-            and not finetune_language
-            and not finetune_vision
-        ):
+        if (finetune_attention or finetune_mlp) and not finetune_language and not finetune_vision:
             finetune_language = True
 
         peft_kwargs["finetune_language_layers"] = finetune_language
@@ -1432,9 +1383,7 @@ def _run_mlx_training(event_queue, stop_queue, config):
 
         if len(file_paths) == 1:
             p = Path(file_paths[0])
-            if p.is_dir() and (
-                (p / "dataset_info.json").exists() or (p / "state.json").exists()
-            ):
+            if p.is_dir() and ((p / "dataset_info.json").exists() or (p / "state.json").exists()):
                 return load_from_disk(str(p))
         all_files = _resolve_mlx_local_dataset_files(file_paths)
         if not all_files:
@@ -1474,7 +1423,6 @@ def _run_mlx_training(event_queue, stop_queue, config):
     format_type = config.get("format_type", "")
     try:
         from utils.datasets import format_and_template_dataset
-
         def _fmt_progress(status_message = "", **_kw):
             _send("status", status_message = status_message)
 
@@ -1495,9 +1443,7 @@ def _run_mlx_training(event_queue, stop_queue, config):
                 )
             else:
                 errors = vlm_info.get("errors", [])
-                raise ValueError(
-                    f"VLM dataset format conversion failed: {'; '.join(errors)}"
-                )
+                raise ValueError(f"VLM dataset format conversion failed: {'; '.join(errors)}")
             if eval_dataset is not None:
                 ev_info = format_and_template_dataset(
                     eval_dataset,
@@ -1629,11 +1575,7 @@ def _run_mlx_training(event_queue, stop_queue, config):
             )
 
             template_name = MODEL_TO_TEMPLATE_MAPPER.get(model_name.lower())
-            markers = (
-                TEMPLATE_TO_RESPONSES_MAPPER.get(template_name)
-                if template_name
-                else None
-            )
+            markers = TEMPLATE_TO_RESPONSES_MAPPER.get(template_name) if template_name else None
             if markers:
                 trainer = train_on_responses_only(
                     trainer,
@@ -1725,11 +1667,7 @@ def _run_mlx_training(event_queue, stop_queue, config):
                         "train/tokens_per_sec": tok_s,
                         "train/peak_gb": peak_gb,
                         "train/num_tokens": num_tokens,
-                        **(
-                            {"train/grad_norm": grad_norm}
-                            if grad_norm is not None
-                            else {}
-                        ),
+                        **({"train/grad_norm": grad_norm} if grad_norm is not None else {}),
                     },
                     step = step,
                 )
@@ -1752,9 +1690,7 @@ def _run_mlx_training(event_queue, stop_queue, config):
         _send("progress", step = step, eval_loss = eval_loss)
         if wandb_run is not None:
             try:
-                wandb_run.log(
-                    {"eval/loss": eval_loss, "eval/perplexity": perplexity}, step = step
-                )
+                wandb_run.log({"eval/loss": eval_loss, "eval/perplexity": perplexity}, step = step)
             except Exception:
                 pass
         if tb_writer is not None:
@@ -1813,12 +1749,7 @@ def _run_mlx_training(event_queue, stop_queue, config):
             pass
 
 
-def run_training_process(
-    *,
-    event_queue: Any,
-    stop_queue: Any,
-    config: dict,
-) -> None:
+def run_training_process(*, event_queue: Any, stop_queue: Any, config: dict) -> None:
     """Subprocess entrypoint. Fresh Python — no stale module state.
 
     Args:
@@ -1827,9 +1758,7 @@ def run_training_process(
         config: Training configuration dict with all parameters.
     """
     os.environ["TOKENIZERS_PARALLELISM"] = "false"
-    os.environ["PYTHONWARNINGS"] = (
-        "ignore"  # Suppress warnings at C-level before imports
-    )
+    os.environ["PYTHONWARNINGS"] = "ignore"  # Suppress warnings at C-level before imports
 
     # Offline auto-detect: skip ~25s of HF retries per call when DNS is
     # dead. Scoped to this subprocess (orchestrator spawns a fresh one).
@@ -2002,7 +1931,6 @@ def run_training_process(
     # do NOT override on macOS. Windows has no fork at all.
     if sys.platform == "linux":
         import multiprocessing as _mp
-
         try:
             _mp.set_start_method("fork", force = True)
         except RuntimeError:
@@ -2012,7 +1940,6 @@ def run_training_process(
     if sys.platform == "win32":
         try:
             import triton  # noqa: F401
-
             logger.info("Triton available — torch.compile enabled")
         except ImportError:
             os.environ["TORCHDYNAMO_DISABLE"] = "1"
@@ -2044,7 +1971,6 @@ def run_training_process(
 
     try:
         import torch.distributed as _td
-
         for _name, _stub in _td_stubs.items():
             if not hasattr(_td, _name):
                 setattr(_td, _name, _stub)
@@ -2055,7 +1981,6 @@ def run_training_process(
         sys.modules["torch.distributed"] = _td_mock
         try:
             import torch as _torch
-
             _torch.distributed = _td_mock
         except Exception:
             pass
@@ -2163,9 +2088,7 @@ def run_training_process(
             # (e.g. "2.11.0+rocm7.13.0" or "2.9.0+rocmsdk20251116"); fall back
             # to that string when version.hip is missing.
             def _hip_ver_at_least(major: int, minor: int) -> bool:
-                _hip_str = getattr(
-                    getattr(_torch_for_rocm, "version", None), "hip", None
-                )
+                _hip_str = getattr(getattr(_torch_for_rocm, "version", None), "hip", None)
                 if not _hip_str:
                     # Try the standard "+rocmX.Y.Z" embedded version first
                     # (e.g. "2.11.0+rocm7.13.0").
@@ -2227,7 +2150,11 @@ def run_training_process(
                     _gm_lib = _torch_for_rocm.library.Library("aten", "IMPL")
 
                     def _grouped_mm_safe_impl(
-                        self, mat2, offs = None, bias = None, out_dtype = None
+                        self,
+                        mat2,
+                        offs = None,
+                        bias = None,
+                        out_dtype = None,
                     ):
                         """Python mm/bmm fallback for _grouped_mm on gfx1200 (null HIP kernel, ROCm ≤ 7.12)."""
                         _t = _torch_for_rocm
@@ -2266,9 +2193,7 @@ def run_training_process(
                             if prev < self.shape[0]:
                                 a_tail = self[prev:].contiguous()
                                 b_tail = (
-                                    mat2[-1].contiguous()
-                                    if mat2.dim() == 3
-                                    else mat2.contiguous()
+                                    mat2[-1].contiguous() if mat2.dim() == 3 else mat2.contiguous()
                                 )
                                 pieces.append(_t.mm(a_tail, b_tail))
                             result = (
@@ -2329,7 +2254,6 @@ def run_training_process(
     if _hw.IS_ROCM:
         try:
             import torch as _torch_mem
-
             if _torch_mem.cuda.is_available():
                 # Classify unified vs discrete via _rocm_classify_unified_memory.
                 # See that function's docstring for classification priority.
@@ -2539,15 +2463,12 @@ def run_training_process(
 
         if dataset is None or trainer.should_stop:
             if trainer.should_stop:
-                event_queue.put(
-                    {"type": "complete", "output_dir": None, "ts": time.time()}
-                )
+                event_queue.put({"type": "complete", "output_dir": None, "ts": time.time()})
             else:
                 event_queue.put(
                     {
                         "type": "error",
-                        "error": trainer.training_progress.error
-                        or "Failed to load dataset",
+                        "error": trainer.training_progress.error or "Failed to load dataset",
                         "stack": "",
                         "ts": time.time(),
                     }
@@ -2561,7 +2482,6 @@ def run_training_process(
 
         def _monitor_tqdm():
             from tqdm.auto import tqdm as _tqdm_cls
-
             while not _tqdm_stop.is_set():
                 for bar in list(getattr(_tqdm_cls, "_instances", set())):
                     try:
@@ -2569,9 +2489,7 @@ def run_training_process(
                         desc = getattr(bar, "desc", "") or ""
                         if total > 0 and n > 0 and desc:
                             pct = min(int(n * 100 / total), 100)
-                            _send_status(
-                                event_queue, f"{desc.strip()} {pct}% ({n:,}/{total:,})"
-                            )
+                            _send_status(event_queue, f"{desc.strip()} {pct}% ({n:,}/{total:,})")
                     except (AttributeError, ReferenceError):
                         pass
                 _tqdm_stop.wait(3)
@@ -2599,9 +2517,7 @@ def run_training_process(
         )
         if not success or trainer.should_stop:
             if trainer.should_stop:
-                event_queue.put(
-                    {"type": "complete", "output_dir": None, "ts": time.time()}
-                )
+                event_queue.put({"type": "complete", "output_dir": None, "ts": time.time()})
             else:
                 error_msg = trainer.training_progress.error or "Failed to load model"
                 event_queue.put(
@@ -2642,9 +2558,7 @@ def run_training_process(
                 lora_r = config.get("lora_r", 128),
                 lora_alpha = config.get("lora_alpha", 32),
                 lora_dropout = config.get("lora_dropout", 0.0),
-                use_gradient_checkpointing = config.get(
-                    "gradient_checkpointing", "unsloth"
-                ),
+                use_gradient_checkpointing = config.get("gradient_checkpointing", "unsloth"),
                 use_rslora = config.get("use_rslora", False),
                 use_loftq = config.get("use_loftq", False),
             )
@@ -2654,17 +2568,13 @@ def run_training_process(
                 use_lora = True,
                 finetune_vision_layers = config.get("finetune_vision_layers", True),
                 finetune_language_layers = config.get("finetune_language_layers", True),
-                finetune_attention_modules = config.get(
-                    "finetune_attention_modules", True
-                ),
+                finetune_attention_modules = config.get("finetune_attention_modules", True),
                 finetune_mlp_modules = config.get("finetune_mlp_modules", True),
                 target_modules = config.get("target_modules"),
                 lora_r = config.get("lora_r", 16),
                 lora_alpha = config.get("lora_alpha", 16),
                 lora_dropout = config.get("lora_dropout", 0.0),
-                use_gradient_checkpointing = config.get(
-                    "gradient_checkpointing", "unsloth"
-                ),
+                use_gradient_checkpointing = config.get("gradient_checkpointing", "unsloth"),
                 use_rslora = config.get("use_rslora", False),
                 use_loftq = config.get("use_loftq", False),
             )
@@ -2674,15 +2584,12 @@ def run_training_process(
 
         if not success or trainer.should_stop:
             if trainer.should_stop:
-                event_queue.put(
-                    {"type": "complete", "output_dir": None, "ts": time.time()}
-                )
+                event_queue.put({"type": "complete", "output_dir": None, "ts": time.time()})
             else:
                 event_queue.put(
                     {
                         "type": "error",
-                        "error": trainer.training_progress.error
-                        or "Failed to prepare model",
+                        "error": trainer.training_progress.error or "Failed to prepare model",
                         "stack": "",
                         "ts": time.time(),
                     }
@@ -2738,9 +2645,7 @@ def run_training_process(
             ensure_dir(Path(tensorboard_dir))
 
         # Start training (directly — no inner thread, we ARE the subprocess)
-        dataset_display = (
-            config.get("hf_dataset", "") or config.get("uploaded_file", "") or ""
-        )
+        dataset_display = config.get("hf_dataset", "") or config.get("uploaded_file", "") or ""
         _send_status(
             event_queue,
             f'Training "{model_name}"'
@@ -2764,9 +2669,7 @@ def run_training_process(
             weight_decay = config.get("weight_decay", 0.001),
             random_seed = config.get("random_seed", 3407),
             packing = config.get("packing", False),
-            train_on_completions = False
-            if is_cpt
-            else config.get("train_on_completions", False),
+            train_on_completions = False if is_cpt else config.get("train_on_completions", False),
             enable_wandb = config.get("enable_wandb", False),
             wandb_project = config.get("wandb_project", "unsloth-training"),
             wandb_token = config.get("wandb_token"),
@@ -3039,9 +2942,7 @@ def _run_embedding_training(event_queue: Any, stop_queue: Any, config: dict) ->
                     if candidates:
                         all_files.extend(str(c) for c in candidates)
                         continue
-                    raise ValueError(
-                        f"No supported data files in directory: {file_path_obj}"
-                    )
+                    raise ValueError(f"No supported data files in directory: {file_path_obj}")
                 else:
                     all_files.append(file_path)
 
@@ -3054,9 +2955,7 @@ def _run_embedding_training(event_queue: Any, stop_queue: Any, config: dict) ->
                 elif first_ext == ".parquet":
                     loader = "parquet"
                 else:
-                    raise ValueError(
-                        f"Unsupported local dataset format: {all_files[0]}"
-                    )
+                    raise ValueError(f"Unsupported local dataset format: {all_files[0]}")
                 dataset = load_dataset(loader, data_files = all_files, split = "train")
         else:
             event_queue.put(
@@ -3116,9 +3015,7 @@ def _run_embedding_training(event_queue: Any, stop_queue: Any, config: dict) ->
         resume_from_checkpoint
     )
     if not output_dir:
-        output_dir = str(
-            resolve_output_dir(f"{model_name.replace('/', '_')}_{int(time.time())}")
-        )
+        output_dir = str(resolve_output_dir(f"{model_name.replace('/', '_')}_{int(time.time())}"))
     output_dir = str(resolve_output_dir(output_dir))
 
     num_epochs = config.get("num_epochs", 2)
@@ -3179,7 +3076,14 @@ def _run_embedding_training(event_queue: Any, stop_queue: Any, config: dict) ->
     class _EmbeddingProgressCallback(TrainerCallback):
         """Sends training progress events to the parent process via event_queue."""
 
-        def on_log(self, args, state, control, logs = None, **kwargs):
+        def on_log(
+            self,
+            args,
+            state,
+            control,
+            logs = None,
+            **kwargs,
+        ):
             if not logs:
                 return
             loss_value = logs.get("loss", logs.get("train_loss", None))
diff --git a/studio/backend/main.py b/studio/backend/main.py
index 10fbbfddf0..8e3a118e27 100644
--- a/studio/backend/main.py
+++ b/studio/backend/main.py
@@ -45,9 +45,7 @@ if sys.platform == "win32":
 
         try:
             if os.path.isdir(_default_root):
-                for _ver in sorted(
-                    os.listdir(_default_root), key = _ver_key, reverse = True
-                ):
+                for _ver in sorted(os.listdir(_default_root), key = _ver_key, reverse = True):
                     _bin = os.path.join(_default_root, _ver, "bin")
                     if os.path.isdir(_bin):
                         candidates.append(_bin)
@@ -83,7 +81,6 @@ if sys.platform == "win32":
         _found_rocm_bnb = False
         try:
             import importlib.util as _ilu
-
             _bnb_spec = _ilu.find_spec("bitsandbytes")
             # submodule_search_locations (not spec.origin) handles editable installs.
             if _bnb_spec and _bnb_spec.submodule_search_locations:
@@ -91,9 +88,7 @@ if sys.platform == "win32":
 
                 _all_vers_main: list[str] = []
                 for _pkg_dir in _bnb_spec.submodule_search_locations:
-                    for _dll in _glob.glob(
-                        os.path.join(_pkg_dir, "libbitsandbytes_rocm*.dll")
-                    ):
+                    for _dll in _glob.glob(os.path.join(_pkg_dir, "libbitsandbytes_rocm*.dll")):
                         _found_rocm_bnb = True
                         _km = _re_bnb.search(
                             r"libbitsandbytes_rocm(\d+)\.dll", os.path.basename(_dll)
@@ -129,9 +124,7 @@ try:
     configure_cpu_threads()
 except ValueError as exc:
     _raw = os.environ.get("UNSLOTH_CPU_THREADS")
-    raise SystemExit(
-        f"Error: Invalid UNSLOTH_CPU_THREADS value {_raw!r}: {exc}"
-    ) from None
+    raise SystemExit(f"Error: Invalid UNSLOTH_CPU_THREADS value {_raw!r}: {exc}") from None
 
 # Fix for Anaconda/conda-forge Python: seed platform._sys_version_cache before
 # any library imports that trigger attrs -> rich -> structlog -> platform crash.
@@ -183,9 +176,7 @@ def _read_studio_install_id() -> str:
     information for callers reaching /api/health (relevant when Studio
     is run with -H 0.0.0.0)."""
     try:
-        token = (
-            (_STUDIO_ROOT_RESOLVED / "share" / "studio_install_id").read_text().strip()
-        )
+        token = (_STUDIO_ROOT_RESOLVED / "share" / "studio_install_id").read_text().strip()
     except (OSError, ValueError):
         return ""
     return token if _STUDIO_INSTALL_ID_RE.fullmatch(token) else ""
@@ -269,9 +260,7 @@ def get_unsloth_version() -> str:
     except PackageNotFoundError:
         pass
 
-    version_file = (
-        _Path(__file__).resolve().parents[2] / "unsloth" / "models" / "_utils.py"
-    )
+    version_file = _Path(__file__).resolve().parents[2] / "unsloth" / "models" / "_utils.py"
     try:
         for line in version_file.read_text(encoding = "utf-8").splitlines():
             if line.startswith("__version__ = "):
@@ -355,10 +344,7 @@ async def lifespan(app: FastAPI):
             print(f"WARNING: {_msg}", flush = True)
     except Exception as _probe_exc:
         import structlog as _structlog
-
-        _structlog.get_logger(__name__).debug(
-            "llama.cpp startup probes failed: %s", _probe_exc
-        )
+        _structlog.get_logger(__name__).debug("llama.cpp startup probes failed: %s", _probe_exc)
 
     from storage.studio_db import cleanup_orphaned_runs
 
@@ -366,10 +352,7 @@ async def lifespan(app: FastAPI):
         cleanup_orphaned_runs()
     except Exception as exc:
         import structlog
-
-        structlog.get_logger(__name__).warning(
-            "cleanup_orphaned_runs failed at startup: %s", exc
-        )
+        structlog.get_logger(__name__).warning("cleanup_orphaned_runs failed at startup: %s", exc)
 
     # Pre-cache the helper GGUF model for LLM-assisted dataset detection.
     # Runs in a background thread so it doesn't block server startup.
@@ -378,7 +361,6 @@ async def lifespan(app: FastAPI):
     def _precache():
         try:
             from utils.datasets.llm_assist import precache_helper_gguf
-
             precache_helper_gguf()
         except Exception:
             pass  # non-critical
@@ -477,9 +459,7 @@ def _build_csp(script_nonce: "str | None" = None) -> str:
             "https://*.googleusercontent.com wss://*.googleusercontent.com"
         )
     else:
-        connect_src = (
-            "'self' https://huggingface.co https://datasets-server.huggingface.co"
-        )
+        connect_src = "'self' https://huggingface.co https://datasets-server.huggingface.co"
 
     return (
         "default-src 'self'; "
@@ -581,11 +561,7 @@ async def _send_411(send) -> None:
 
 async def _send_413(send, total_bytes: int, max_bytes: int) -> None:
     payload = _json_for_413.dumps(
-        {
-            "detail": (
-                f"Request body too large ({total_bytes:,} bytes; max {max_bytes:,})."
-            )
-        },
+        {"detail": (f"Request body too large ({total_bytes:,} bytes; max {max_bytes:,}).")},
     ).encode("utf-8")
     await send(
         {
@@ -768,9 +744,7 @@ app.include_router(mcp_servers_router, prefix = "/api/mcp/servers", tags = ["mcp
 app.include_router(datasets_router, prefix = "/api/datasets", tags = ["datasets"])
 app.include_router(data_recipe_router, prefix = "/api/data-recipe", tags = ["data-recipe"])
 app.include_router(export_router, prefix = "/api/export", tags = ["export"])
-app.include_router(
-    training_history_router, prefix = "/api/train", tags = ["training-history"]
-)
+app.include_router(training_history_router, prefix = "/api/train", tags = ["training-history"])
 
 
 # ============ Health and System Endpoints ============
@@ -808,9 +782,7 @@ async def health_check(request: Request):
         from auth.authentication import get_current_subject as _gcs
         from fastapi.security import HTTPAuthorizationCredentials
 
-        creds = HTTPAuthorizationCredentials(
-            scheme = "Bearer", credentials = auth.split(" ", 1)[1]
-        )
+        creds = HTTPAuthorizationCredentials(scheme = "Bearer", credentials = auth.split(" ", 1)[1])
         # Must await: a bare coroutine is truthy and would skip the auth check.
         subject = await _gcs(creds)
     except HTTPException:
@@ -843,10 +815,7 @@ def studio_update_status(_current_subject: str = Depends(get_current_subject)):
 
 
 @app.post("/api/shutdown")
-async def shutdown_server(
-    request: Request,
-    current_subject: str = Depends(get_current_subject),
-):
+async def shutdown_server(request: Request, current_subject: str = Depends(get_current_subject)):
     """Gracefully shut down the Unsloth Studio server.
 
     Called by the frontend quit dialog so users can stop the server from the UI
@@ -863,7 +832,6 @@ async def shutdown_server(
             # Fallback when not launched via run_server() (e.g. direct uvicorn)
             import signal
             import os
-
             os.kill(os.getpid(), signal.SIGTERM)
 
     request.app.state._shutdown_task = asyncio.create_task(_delayed_shutdown())
@@ -871,9 +839,7 @@ async def shutdown_server(
 
 
 @app.get("/api/system")
-async def get_system_info(
-    current_subject: str = Depends(get_current_subject),
-):
+async def get_system_info(current_subject: str = Depends(get_current_subject)):
     """Get system information.
 
     Gated behind auth: the response includes platform, Python version,
@@ -914,23 +880,18 @@ async def get_system_info(
 
 
 @app.get("/api/system/gpu-visibility")
-async def get_gpu_visibility(
-    current_subject: str = Depends(get_current_subject),
-):
+async def get_gpu_visibility(current_subject: str = Depends(get_current_subject)):
     return get_backend_visible_gpu_info()
 
 
 @app.get("/api/system/hardware")
-async def get_hardware_info(
-    current_subject: str = Depends(get_current_subject),
-):
+async def get_hardware_info(current_subject: str = Depends(get_current_subject)):
     """Return GPU name, total VRAM, and key ML package versions.
 
     Gated behind auth alongside /api/system -- same fingerprinting
     concern. /api/system/gpu-visibility is also auth-gated already.
     """
     from utils.hardware import get_gpu_summary, get_package_versions
-
     return {
         "gpu": get_gpu_summary(),
         "versions": get_package_versions(),
diff --git a/studio/backend/models/auth.py b/studio/backend/models/auth.py
index b7870379f7..9550e354a8 100644
--- a/studio/backend/models/auth.py
+++ b/studio/backend/models/auth.py
@@ -26,17 +26,13 @@ class DesktopLoginRequest(BaseModel):
 class RefreshTokenRequest(BaseModel):
     """Refresh token payload to obtain new access + refresh tokens."""
 
-    refresh_token: str = Field(
-        ..., description = "Refresh token from a previous login or refresh"
-    )
+    refresh_token: str = Field(..., description = "Refresh token from a previous login or refresh")
 
 
 class AuthStatusResponse(BaseModel):
     """Indicate whether the seeded admin auth flow is ready."""
 
-    initialized: bool = Field(
-        ..., description = "True if the auth database contains a login user"
-    )
+    initialized: bool = Field(..., description = "True if the auth database contains a login user")
     default_username: str = Field(
         "unsloth",
         description = "Default admin username for first-boot UI prefill.",
@@ -77,9 +73,7 @@ class ApiKeyResponse(BaseModel):
 
     id: int
     name: str
-    key_prefix: str = Field(
-        ..., description = "First 8 characters after sk-unsloth- for display"
-    )
+    key_prefix: str = Field(..., description = "First 8 characters after sk-unsloth- for display")
     created_at: str
     last_used_at: Optional[str] = None
     expires_at: Optional[str] = None
diff --git a/studio/backend/models/data_recipe.py b/studio/backend/models/data_recipe.py
index b382ddb3d0..f3faddf843 100644
--- a/studio/backend/models/data_recipe.py
+++ b/studio/backend/models/data_recipe.py
@@ -103,9 +103,7 @@ class SeedInspectUploadRequest(BaseModel):
             if not self.block_id:
                 raise ValueError("block_id is required when using file_ids")
             if self.file_names is None or len(self.file_ids) != len(self.file_names):
-                raise ValueError(
-                    "file_names must be provided and same length as file_ids"
-                )
+                raise ValueError("file_names must be provided and same length as file_ids")
         if has_legacy:
             if not self.filename:
                 raise ValueError("filename is required when using content_base64")
diff --git a/studio/backend/models/inference.py b/studio/backend/models/inference.py
index 5a846e536e..d2fa45dd92 100644
--- a/studio/backend/models/inference.py
+++ b/studio/backend/models/inference.py
@@ -28,9 +28,7 @@ class LoadRequest(BaseModel):
     native_path_lease: Optional[str] = Field(
         None, description = "Frontend-visible signed native path grant"
     )
-    hf_token: Optional[str] = Field(
-        None, description = "HuggingFace token for gated models"
-    )
+    hf_token: Optional[str] = Field(None, description = "HuggingFace token for gated models")
     max_seq_length: int = Field(
         0,
         ge = 0,
@@ -53,9 +51,7 @@ class LoadRequest(BaseModel):
 
     @field_validator("chat_template_override")
     @classmethod
-    def normalize_blank_chat_template_override(
-        cls, value: Optional[str]
-    ) -> Optional[str]:
+    def normalize_blank_chat_template_override(cls, value: Optional[str]) -> Optional[str]:
         if value is not None and value.strip() == "":
             return None
         return value
@@ -123,9 +119,7 @@ class ValidateModelRequest(BaseModel):
     native_path_lease: Optional[str] = Field(
         None, description = "Frontend-visible signed native path grant"
     )
-    hf_token: Optional[str] = Field(
-        None, description = "HuggingFace token for gated models"
-    )
+    hf_token: Optional[str] = Field(None, description = "HuggingFace token for gated models")
     gguf_variant: Optional[str] = Field(
         None, description = "GGUF quantization variant (e.g. 'Q4_K_M')"
     )
@@ -142,9 +136,7 @@ class ValidateModelResponse(BaseModel):
     valid: bool = Field(..., description = "Whether the model identifier looks valid")
     message: str = Field(..., description = "Human-readable validation message")
     identifier: Optional[str] = Field(None, description = "Resolved model identifier")
-    display_name: Optional[str] = Field(
-        None, description = "Display name derived from identifier"
-    )
+    display_name: Optional[str] = Field(None, description = "Display name derived from identifier")
     is_gguf: bool = Field(False, description = "Whether this is a GGUF model (llama.cpp)")
     is_lora: bool = Field(False, description = "Whether this is a LoRA adapter")
     is_vision: bool = Field(False, description = "Whether this is a vision-capable model")
@@ -162,16 +154,10 @@ class GenerateRequest(BaseModel):
     temperature: float = Field(0.6, ge = 0.0, le = 2.0, description = "Sampling temperature")
     top_p: float = Field(0.95, ge = 0.0, le = 1.0, description = "Top-p sampling")
     top_k: int = Field(20, ge = -1, le = 100, description = "Top-k sampling")
-    max_new_tokens: int = Field(
-        2048, ge = 1, le = 4096, description = "Maximum tokens to generate"
-    )
-    repetition_penalty: float = Field(
-        1.0, ge = 1.0, le = 2.0, description = "Repetition penalty"
-    )
+    max_new_tokens: int = Field(2048, ge = 1, le = 4096, description = "Maximum tokens to generate")
+    repetition_penalty: float = Field(1.0, ge = 1.0, le = 2.0, description = "Repetition penalty")
     presence_penalty: float = Field(0.0, ge = 0.0, le = 2.0, description = "Presence penalty")
-    image_base64: Optional[str] = Field(
-        None, description = "Base64 encoded image for vision models"
-    )
+    image_base64: Optional[str] = Field(None, description = "Base64 encoded image for vision models")
 
 
 class LoadResponse(BaseModel):
@@ -182,16 +168,10 @@ class LoadResponse(BaseModel):
     display_name: str = Field(..., description = "Display name of the model")
     is_vision: bool = Field(False, description = "Whether model is a vision model")
     is_lora: bool = Field(False, description = "Whether model is a LoRA adapter")
-    is_gguf: bool = Field(
-        False, description = "Whether model is a GGUF model (llama.cpp)"
-    )
+    is_gguf: bool = Field(False, description = "Whether model is a GGUF model (llama.cpp)")
     is_audio: bool = Field(False, description = "Whether model is a TTS audio model")
-    audio_type: Optional[str] = Field(
-        None, description = "Audio codec type: snac, csm, bicodec, dac"
-    )
-    has_audio_input: bool = Field(
-        False, description = "Whether model accepts audio input (ASR)"
-    )
+    audio_type: Optional[str] = Field(None, description = "Audio codec type: snac, csm, bicodec, dac")
+    has_audio_input: bool = Field(False, description = "Whether model accepts audio input (ASR)")
     inference: dict = Field(
         ..., description = "Inference parameters (temperature, top_p, top_k, min_p)"
     )
@@ -282,17 +262,14 @@ class LoadProgressResponse(BaseModel):
     bytes_loaded: int = Field(
         0,
         description = (
-            "Bytes of the model already resident in the llama-server "
-            "process (VmRSS on Linux)."
+            "Bytes of the model already resident in the llama-server process (VmRSS on Linux)."
         ),
     )
     bytes_total: int = Field(
         0,
         description = "Total bytes across all GGUF shards for the active model.",
     )
-    fraction: float = Field(
-        0.0, description = "bytes_loaded / bytes_total, clamped to 0..1."
-    )
+    fraction: float = Field(0.0, description = "bytes_loaded / bytes_total, clamped to 0..1.")
 
 
 class InferenceStatusResponse(BaseModel):
@@ -305,30 +282,14 @@ class InferenceStatusResponse(BaseModel):
         None,
         description = "Loadable identifier for the active model.",
     )
-    is_vision: bool = Field(
-        False, description = "Whether the active model is a vision model"
-    )
-    is_gguf: bool = Field(
-        False, description = "Whether the active model is a GGUF model (llama.cpp)"
-    )
-    gguf_variant: Optional[str] = Field(
-        None, description = "GGUF quantization variant (e.g. Q4_K_M)"
-    )
-    is_audio: bool = Field(
-        False, description = "Whether the active model is a TTS audio model"
-    )
-    audio_type: Optional[str] = Field(
-        None, description = "Audio codec type: snac, csm, bicodec, dac"
-    )
-    has_audio_input: bool = Field(
-        False, description = "Whether model accepts audio input (ASR)"
-    )
-    loading: List[str] = Field(
-        default_factory = list, description = "Models currently being loaded"
-    )
-    loaded: List[str] = Field(
-        default_factory = list, description = "Models currently loaded"
-    )
+    is_vision: bool = Field(False, description = "Whether the active model is a vision model")
+    is_gguf: bool = Field(False, description = "Whether the active model is a GGUF model (llama.cpp)")
+    gguf_variant: Optional[str] = Field(None, description = "GGUF quantization variant (e.g. Q4_K_M)")
+    is_audio: bool = Field(False, description = "Whether the active model is a TTS audio model")
+    audio_type: Optional[str] = Field(None, description = "Audio codec type: snac, csm, bicodec, dac")
+    has_audio_input: bool = Field(False, description = "Whether model accepts audio input (ASR)")
+    loading: List[str] = Field(default_factory = list, description = "Models currently being loaded")
+    loaded: List[str] = Field(default_factory = list, description = "Models currently loaded")
     inference: Optional[Dict[str, Any]] = Field(
         None, description = "Recommended inference parameters for the active model"
     )
@@ -353,9 +314,7 @@ class InferenceStatusResponse(BaseModel):
     supports_tools: bool = Field(
         False, description = "Whether the active model supports tool calling"
     )
-    context_length: Optional[int] = Field(
-        None, description = "Context length of the active model"
-    )
+    context_length: Optional[int] = Field(None, description = "Context length of the active model")
     max_context_length: Optional[int] = Field(
         None,
         description = "Maximum context length currently available for the active model",
@@ -563,9 +522,7 @@ class ChatMessage(BaseModel):
     ``ChatCompletionRequest`` layer by walking back to the preceding assistant.
     """
 
-    role: Literal["system", "user", "assistant", "tool"] = Field(
-        ..., description = "Message role"
-    )
+    role: Literal["system", "user", "assistant", "tool"] = Field(..., description = "Message role")
     content: Optional[Union[str, list[ContentPart]]] = Field(
         None, description = "Message content (string or multimodal parts)"
     )
@@ -666,9 +623,7 @@ class ChatCompletionRequest(BaseModel):
 
     # ── Unsloth extensions (ignored by standard OpenAI clients) ──
     top_k: int = Field(20, ge = -1, le = 100, description = "[x-unsloth] Top-k sampling")
-    min_p: float = Field(
-        0.01, ge = 0.0, le = 1.0, description = "[x-unsloth] Min-p sampling threshold"
-    )
+    min_p: float = Field(0.01, ge = 0.0, le = 1.0, description = "[x-unsloth] Min-p sampling threshold")
     repetition_penalty: float = Field(
         1.0, ge = 1.0, le = 2.0, description = "[x-unsloth] Repetition penalty"
     )
@@ -925,9 +880,7 @@ class ChatCompletionRequest(BaseModel):
                     if not tc_id:
                         continue
                     function = tc.get("function")
-                    function_name = (
-                        function.get("name") if isinstance(function, dict) else None
-                    )
+                    function_name = function.get("name") if isinstance(function, dict) else None
                     if msg.name and function_name == msg.name:
                         name_match = (tc_id, asst_idx, tc_idx)
                         break
@@ -940,7 +893,6 @@ class ChatCompletionRequest(BaseModel):
                     break
             if picked is None:
                 import secrets as _secrets
-
                 picked = f"call_{_secrets.token_hex(8)}"
             msg.tool_call_id = picked
         return self
@@ -1160,17 +1112,13 @@ class ResponsesFunctionCallInputItem(BaseModel):
     """
 
     type: Literal["function_call"]
-    id: Optional[str] = Field(
-        None, description = "Item id assigned by the server (e.g. fc_...)"
-    )
+    id: Optional[str] = Field(None, description = "Item id assigned by the server (e.g. fc_...)")
     call_id: str = Field(
         ...,
         description = "Correlation id matching a function_call_output on the next turn.",
     )
     name: str
-    arguments: str = Field(
-        ..., description = "JSON string of the arguments the model produced."
-    )
+    arguments: str = Field(..., description = "JSON string of the arguments the model produced.")
     status: Optional[Literal["in_progress", "completed", "incomplete"]] = None
 
 
@@ -1266,9 +1214,7 @@ class ResponsesRequest(BaseModel):
         default = [],
         description = "Input text or list of messages / function_call / function_call_output items",
     )
-    instructions: Optional[str] = Field(
-        None, description = "System / developer instructions"
-    )
+    instructions: Optional[str] = Field(None, description = "System / developer instructions")
     temperature: Optional[float] = Field(None, ge = 0.0, le = 2.0)
     top_p: Optional[float] = Field(None, ge = 0.0, le = 1.0)
     max_output_tokens: Optional[int] = Field(None, ge = 1)
@@ -1344,9 +1290,7 @@ class ResponsesOutputFunctionCall(BaseModel):
     id: str = Field(default_factory = lambda: f"fc_{uuid.uuid4().hex[:12]}")
     call_id: str
     name: str
-    arguments: str = Field(
-        ..., description = "JSON string of the arguments the model produced."
-    )
+    arguments: str = Field(..., description = "JSON string of the arguments the model produced.")
     status: Literal["completed", "in_progress", "incomplete"] = "completed"
 
 
@@ -1455,16 +1399,12 @@ def _merge_anthropic_system(system: Any, additions: list[str]) -> Any:
     if not additions:
         return system
 
-    addition_blocks = [
-        {"type": "text", "text": text} for text in additions if text.strip()
-    ]
+    addition_blocks = [{"type": "text", "text": text} for text in additions if text.strip()]
     if not addition_blocks:
         return system
 
     if system is None:
-        return (
-            addition_blocks[0]["text"] if len(addition_blocks) == 1 else addition_blocks
-        )
+        return addition_blocks[0]["text"] if len(addition_blocks) == 1 else addition_blocks
     if isinstance(system, str):
         return "\n\n".join([system, *[block["text"] for block in addition_blocks]])
     if isinstance(system, list):
@@ -1543,9 +1483,7 @@ class AnthropicMessagesRequest(BaseModel):
 
         normalized = dict(data)
         normalized["messages"] = normalized_messages
-        normalized["system"] = _merge_anthropic_system(
-            normalized.get("system"), system_additions
-        )
+        normalized["system"] = _merge_anthropic_system(normalized.get("system"), system_additions)
         return normalized
 
 
@@ -1569,9 +1507,7 @@ class AnthropicResponseToolUseBlock(BaseModel):
     input: dict
 
 
-AnthropicResponseBlock = Union[
-    AnthropicResponseTextBlock, AnthropicResponseToolUseBlock
-]
+AnthropicResponseBlock = Union[AnthropicResponseTextBlock, AnthropicResponseToolUseBlock]
 
 
 class AnthropicMessagesResponse(BaseModel):
diff --git a/studio/backend/models/models.py b/studio/backend/models/models.py
index a53569aaa1..3dd8e779f7 100644
--- a/studio/backend/models/models.py
+++ b/studio/backend/models/models.py
@@ -14,9 +14,7 @@ ModelType = Literal["text", "vision", "audio", "embeddings"]
 class CheckpointInfo(BaseModel):
     """Information about a discovered checkpoint directory."""
 
-    display_name: str = Field(
-        ..., description = "User-friendly checkpoint name (folder name)"
-    )
+    display_name: str = Field(..., description = "User-friendly checkpoint name (folder name)")
     path: str = Field(..., description = "Full path to the checkpoint directory")
     loss: Optional[float] = Field(None, description = "Training loss at this checkpoint")
 
@@ -65,33 +63,23 @@ class ModelDetails(BaseModel):
         None, description = "Model identifier (alias for id, for backward compatibility)"
     )
     name: Optional[str] = Field(None, description = "Display name for the model")
-    config: Optional[Dict[str, Any]] = Field(
-        None, description = "Model configuration dictionary"
-    )
+    config: Optional[Dict[str, Any]] = Field(None, description = "Model configuration dictionary")
     is_vision: bool = Field(False, description = "Whether model is a vision model")
     is_embedding: bool = Field(
         False, description = "Whether model is an embedding/sentence-transformer model"
     )
     is_lora: bool = Field(False, description = "Whether model is a LoRA adapter")
-    is_gguf: bool = Field(
-        False, description = "Whether model is a GGUF model (llama.cpp format)"
-    )
+    is_gguf: bool = Field(False, description = "Whether model is a GGUF model (llama.cpp format)")
     is_mlx: bool = Field(
         False, description = "Whether model is served via the MLX backend (Apple Silicon)"
     )
     is_audio: bool = Field(False, description = "Whether model is a TTS audio model")
-    audio_type: Optional[str] = Field(
-        None, description = "Audio codec type: snac, csm, bicodec, dac"
-    )
-    has_audio_input: bool = Field(
-        False, description = "Whether model accepts audio input (ASR)"
-    )
+    audio_type: Optional[str] = Field(None, description = "Audio codec type: snac, csm, bicodec, dac")
+    has_audio_input: bool = Field(False, description = "Whether model accepts audio input (ASR)")
     model_type: Optional[ModelType] = Field(
         None, description = "Collapsed model modality: text, vision, audio, or embeddings"
     )
-    base_model: Optional[str] = Field(
-        None, description = "Base model if this is a LoRA adapter"
-    )
+    base_model: Optional[str] = Field(None, description = "Base model if this is a LoRA adapter")
     max_position_embeddings: Optional[int] = Field(
         None, description = "Maximum context length supported by the model"
     )
@@ -104,9 +92,7 @@ class LoRAInfo(BaseModel):
     """LoRA adapter or exported model information"""
 
     display_name: str = Field(..., description = "Display name for the LoRA")
-    adapter_path: str = Field(
-        ..., description = "Path to the LoRA adapter or exported model"
-    )
+    adapter_path: str = Field(..., description = "Path to the LoRA adapter or exported model")
     base_model: Optional[str] = Field(None, description = "Base model identifier")
     source: Optional[str] = Field(None, description = "'training' or 'exported'")
     export_type: Optional[str] = Field(
@@ -117,29 +103,21 @@ class LoRAInfo(BaseModel):
 class LoRAScanResponse(BaseModel):
     """Response schema for scanning trained LoRA adapters"""
 
-    loras: List[LoRAInfo] = Field(
-        default_factory = list, description = "List of found LoRA adapters"
-    )
+    loras: List[LoRAInfo] = Field(default_factory = list, description = "List of found LoRA adapters")
     outputs_dir: str = Field(..., description = "Directory that was scanned")
 
 
 class ModelListResponse(BaseModel):
     """Response schema for listing models"""
 
-    models: List[ModelDetails] = Field(
-        default_factory = list, description = "List of models"
-    )
-    default_models: List[str] = Field(
-        default_factory = list, description = "List of default model IDs"
-    )
+    models: List[ModelDetails] = Field(default_factory = list, description = "List of models")
+    default_models: List[str] = Field(default_factory = list, description = "List of default model IDs")
 
 
 class GgufVariantDetail(BaseModel):
     """A single GGUF quantization variant in a HuggingFace repo."""
 
-    filename: str = Field(
-        ..., description = "GGUF filename (e.g., 'gemma-3-4b-it-Q4_K_M.gguf')"
-    )
+    filename: str = Field(..., description = "GGUF filename (e.g., 'gemma-3-4b-it-Q4_K_M.gguf')")
     quant: str = Field(..., description = "Quantization label (e.g., 'Q4_K_M')")
     size_bytes: int = Field(0, description = "File size in bytes")
     downloaded: bool = Field(
@@ -185,9 +163,7 @@ class LocalModelInfo(BaseModel):
 class LocalModelListResponse(BaseModel):
     """Response schema for listing local/cached models."""
 
-    models_dir: str = Field(
-        ..., description = "Directory scanned for custom local models"
-    )
+    models_dir: str = Field(..., description = "Directory scanned for custom local models")
     hf_cache_dir: Optional[str] = Field(
         None,
         description = "HF cache root that was scanned",
@@ -205,9 +181,7 @@ class LocalModelListResponse(BaseModel):
 class AddScanFolderRequest(BaseModel):
     """Request body for adding a custom scan folder."""
 
-    path: str = Field(
-        ..., description = "Absolute or relative directory path to scan for models"
-    )
+    path: str = Field(..., description = "Absolute or relative directory path to scan for models")
 
 
 class ScanFolderInfo(BaseModel):
diff --git a/studio/backend/models/providers.py b/studio/backend/models/providers.py
index 53ce981392..e9d2d859f5 100644
--- a/studio/backend/models/providers.py
+++ b/studio/backend/models/providers.py
@@ -16,9 +16,7 @@ from pydantic import BaseModel, Field
 class ProviderRegistryEntry(BaseModel):
     """A supported provider type with its default configuration."""
 
-    provider_type: str = Field(
-        ..., description = "Provider identifier (e.g. 'openai', 'mistral')"
-    )
+    provider_type: str = Field(..., description = "Provider identifier (e.g. 'openai', 'mistral')")
     display_name: str = Field(..., description = "Human-readable provider name")
     base_url: str = Field(..., description = "Default API base URL")
     default_models: list[str] = Field(
@@ -46,9 +44,7 @@ class ProviderCreate(BaseModel):
     """Request to create a saved provider configuration."""
 
     provider_type: str = Field(..., description = "Provider type from the registry")
-    display_name: str = Field(
-        ..., description = "User-chosen label (e.g. 'My OpenAI Key')"
-    )
+    display_name: str = Field(..., description = "User-chosen label (e.g. 'My OpenAI Key')")
     base_url: Optional[str] = Field(
         None,
         description = "Custom base URL (overrides registry default). Omit to use the default.",
@@ -60,9 +56,7 @@ class ProviderUpdate(BaseModel):
 
     display_name: Optional[str] = Field(None, description = "New display name")
     base_url: Optional[str] = Field(None, description = "New base URL")
-    is_enabled: Optional[bool] = Field(
-        None, description = "Enable or disable this provider"
-    )
+    is_enabled: Optional[bool] = Field(None, description = "Enable or disable this provider")
 
 
 class ProviderResponse(BaseModel):
@@ -85,9 +79,7 @@ class ProviderModelInfo(BaseModel):
 
     id: str = Field(..., description = "Model ID as expected by the provider API")
     display_name: str = Field("", description = "Human-readable model name")
-    context_length: Optional[int] = Field(
-        None, description = "Maximum context length in tokens"
-    )
+    context_length: Optional[int] = Field(None, description = "Maximum context length in tokens")
     owned_by: Optional[str] = Field(None, description = "Model owner/organization")
 
 
diff --git a/studio/backend/models/responses.py b/studio/backend/models/responses.py
index 3081f67422..f6357bf999 100644
--- a/studio/backend/models/responses.py
+++ b/studio/backend/models/responses.py
@@ -23,16 +23,10 @@ class TrainingStopResponse(BaseModel):
 class TrainingMetricsResponse(BaseModel):
     """Response for training metrics history"""
 
-    loss_history: List[float] = Field(
-        default_factory = list, description = "Loss values per step"
-    )
-    lr_history: List[float] = Field(
-        default_factory = list, description = "Learning rate per step"
-    )
+    loss_history: List[float] = Field(default_factory = list, description = "Loss values per step")
+    lr_history: List[float] = Field(default_factory = list, description = "Learning rate per step")
     step_history: List[int] = Field(default_factory = list, description = "Step numbers")
-    grad_norm_history: List[float] = Field(
-        default_factory = list, description = "Gradient norm values"
-    )
+    grad_norm_history: List[float] = Field(default_factory = list, description = "Gradient norm values")
     grad_norm_step_history: List[int] = Field(
         default_factory = list, description = "Step numbers for gradient norm values"
     )
diff --git a/studio/backend/models/training.py b/studio/backend/models/training.py
index c6be1eff4e..cef0b8f36f 100644
--- a/studio/backend/models/training.py
+++ b/studio/backend/models/training.py
@@ -41,9 +41,7 @@ def _parse_lr(v: Any) -> float:
     except (TypeError, ValueError):
         raise ValueError(f"learning_rate must be parseable as float (got {v!r})")
     if not (lr > 0.0):
-        raise ValueError(
-            f"learning_rate must be > 0 (got {lr!r}); " "typical range is 1e-6 .. 1e-3"
-        )
+        raise ValueError(f"learning_rate must be > 0 (got {lr!r}); typical range is 1e-6 .. 1e-3")
     if lr >= _MAX_LR_VALUE:
         raise ValueError(
             f"learning_rate must be < 1.0 (got {lr!r}); "
@@ -59,11 +57,9 @@ class TrainingStartRequest(BaseModel):
     model_name: str = Field(
         ..., description = "Model identifier (e.g., 'unsloth/llama-3-8b-bnb-4bit')"
     )
-    training_type: Literal["LoRA/QLoRA", "Full Finetuning", "Continued Pretraining"] = (
-        Field(
-            ...,
-            description = "Training type: 'LoRA/QLoRA', 'Full Finetuning', or 'Continued Pretraining'",
-        )
+    training_type: Literal["LoRA/QLoRA", "Full Finetuning", "Continued Pretraining"] = Field(
+        ...,
+        description = "Training type: 'LoRA/QLoRA', 'Full Finetuning', or 'Continued Pretraining'",
     )
     hf_token: Optional[str] = Field(None, description = "HuggingFace token")
     load_in_4bit: bool = Field(True, description = "Load model in 4-bit quantization")
@@ -78,9 +74,7 @@ class TrainingStartRequest(BaseModel):
     )
 
     # Dataset parameters
-    hf_dataset: Optional[str] = Field(
-        None, description = "HuggingFace dataset identifier"
-    )
+    hf_dataset: Optional[str] = Field(None, description = "HuggingFace dataset identifier")
     local_datasets: List[str] = Field(
         default_factory = list, description = "List of local dataset paths"
     )
@@ -90,12 +84,8 @@ class TrainingStartRequest(BaseModel):
     format_type: str = Field(..., description = "Dataset format type")
     subset: Optional[str] = None
     train_split: Optional[str] = Field("train", description = "Training split name")
-    eval_split: Optional[str] = Field(
-        None, description = "Eval split name. None = auto-detect"
-    )
-    eval_steps: float = Field(
-        0.00, description = "Fraction of total steps between evals (0-1)"
-    )
+    eval_split: Optional[str] = Field(None, description = "Eval split name. None = auto-detect")
+    eval_steps: float = Field(0.00, description = "Fraction of total steps between evals (0-1)")
     dataset_slice_start: Optional[int] = Field(
         None, description = "Inclusive start row index for dataset slicing"
     )
@@ -124,9 +114,7 @@ class TrainingStartRequest(BaseModel):
         if v is None:
             raise ValueError("batch_size is required")
         if v < 1 or v > _MAX_BATCH_SIZE:
-            raise ValueError(
-                f"batch_size must be in [1, {_MAX_BATCH_SIZE}] (got {v!r})"
-            )
+            raise ValueError(f"batch_size must be in [1, {_MAX_BATCH_SIZE}] (got {v!r})")
         return v
 
     @field_validator("gradient_accumulation_steps")
@@ -136,8 +124,7 @@ class TrainingStartRequest(BaseModel):
             return 1
         if v < 1 or v > _MAX_GRAD_ACCUM:
             raise ValueError(
-                f"gradient_accumulation_steps must be in [1, {_MAX_GRAD_ACCUM}] "
-                f"(got {v!r})"
+                f"gradient_accumulation_steps must be in [1, {_MAX_GRAD_ACCUM}] " f"(got {v!r})"
             )
         return v
 
@@ -159,18 +146,14 @@ class TrainingStartRequest(BaseModel):
         if v is None:
             return v
         if not isinstance(v, int) or v < 0 or v > _MAX_STEPS:
-            raise ValueError(
-                f"max_steps must be a non-negative int <= {_MAX_STEPS} (got {v!r})"
-            )
+            raise ValueError(f"max_steps must be a non-negative int <= {_MAX_STEPS} (got {v!r})")
         return v
 
     @field_validator("max_seq_length")
     @classmethod
     def _check_max_seq_length(cls, v: int) -> int:
         if v is None or v < 1 or v > _MAX_SEQ_LENGTH:
-            raise ValueError(
-                f"max_seq_length must be in [1, {_MAX_SEQ_LENGTH}] (got {v!r})"
-            )
+            raise ValueError(f"max_seq_length must be in [1, {_MAX_SEQ_LENGTH}] (got {v!r})")
         return v
 
     @field_validator("vision_image_size", mode = "before")
@@ -191,7 +174,6 @@ class TrainingStartRequest(BaseModel):
             # numpy ints / Integral subclasses, without a hard numpy import.
             try:
                 import numbers
-
                 if isinstance(v, numbers.Integral):
                     coerced = int(v)
                 elif isinstance(v, numbers.Real) and float(v).is_integer():
@@ -214,8 +196,7 @@ class TrainingStartRequest(BaseModel):
             return v
         if not isinstance(v, int) or v < 0 or v > _MAX_STEPS:
             raise ValueError(
-                f"warmup_steps must be a non-negative int <= {_MAX_STEPS} "
-                f"(got {v!r})"
+                f"warmup_steps must be a non-negative int <= {_MAX_STEPS} " f"(got {v!r})"
             )
         return v
 
@@ -251,9 +232,7 @@ class TrainingStartRequest(BaseModel):
         except (TypeError, ValueError):
             raise ValueError(f"weight_decay must be a number (got {v!r})")
         if wd < 0 or wd > 10.0:
-            raise ValueError(
-                f"weight_decay must be in [0, 10] (got {wd!r}); typical 0..0.1"
-            )
+            raise ValueError(f"weight_decay must be in [0, 10] (got {wd!r}); typical 0..0.1")
         return wd
 
     @field_validator("lora_r")
@@ -271,9 +250,7 @@ class TrainingStartRequest(BaseModel):
         if v is None:
             return 16
         if v < 1 or v > _MAX_LORA_ALPHA:
-            raise ValueError(
-                f"lora_alpha must be in [1, {_MAX_LORA_ALPHA}] (got {v!r})"
-            )
+            raise ValueError(f"lora_alpha must be in [1, {_MAX_LORA_ALPHA}] (got {v!r})")
         return v
 
     @field_validator("lora_dropout")
@@ -302,9 +279,7 @@ class TrainingStartRequest(BaseModel):
     num_epochs: int = Field(1, description = "Number of training epochs")
     learning_rate: str = Field("2e-4", description = "Learning rate")
     batch_size: int = Field(1, description = "Batch size")
-    gradient_accumulation_steps: int = Field(
-        1, description = "Gradient accumulation steps"
-    )
+    gradient_accumulation_steps: int = Field(1, description = "Gradient accumulation steps")
     warmup_steps: Optional[int] = Field(None, description = "Warmup steps")
     warmup_ratio: Optional[float] = Field(None, description = "Warmup ratio")
     max_steps: Optional[int] = Field(None, description = "Maximum training steps")
@@ -332,31 +307,19 @@ class TrainingStartRequest(BaseModel):
     lora_r: int = Field(16, description = "LoRA rank")
     lora_alpha: int = Field(16, description = "LoRA alpha")
     lora_dropout: float = Field(0.0, description = "LoRA dropout")
-    target_modules: List[str] = Field(
-        default_factory = list, description = "Target modules for LoRA"
-    )
-    gradient_checkpointing: str = Field(
-        "", description = "Gradient checkpointing setting"
-    )
+    target_modules: List[str] = Field(default_factory = list, description = "Target modules for LoRA")
+    gradient_checkpointing: str = Field("", description = "Gradient checkpointing setting")
     use_rslora: bool = Field(False, description = "Use RSLoRA")
     use_loftq: bool = Field(False, description = "Use LoftQ")
     train_on_completions: bool = Field(False, description = "Train on completions only")
 
     # Vision-specific LoRA parameters
     finetune_vision_layers: bool = Field(False, description = "Finetune vision layers")
-    finetune_language_layers: bool = Field(
-        False, description = "Finetune language layers"
-    )
-    finetune_attention_modules: bool = Field(
-        False, description = "Finetune attention modules"
-    )
+    finetune_language_layers: bool = Field(False, description = "Finetune language layers")
+    finetune_attention_modules: bool = Field(False, description = "Finetune attention modules")
     finetune_mlp_modules: bool = Field(False, description = "Finetune MLP modules")
-    is_dataset_image: bool = Field(
-        False, description = "Whether the dataset contains image data"
-    )
-    is_dataset_audio: bool = Field(
-        False, description = "Whether the dataset contains audio data"
-    )
+    is_dataset_image: bool = Field(False, description = "Whether the dataset contains image data")
+    is_dataset_audio: bool = Field(False, description = "Whether the dataset contains audio data")
     is_embedding: bool = Field(
         False, description = "Whether model is an embedding/sentence-transformer model"
     )
@@ -382,9 +345,7 @@ class TrainingStartRequest(BaseModel):
         # num_epochs and max_steps each accept 0 as a "use the other one"
         # sentinel. If both resolve to 0 there's nothing to train against.
         if (self.max_steps is None or self.max_steps == 0) and self.num_epochs == 0:
-            raise ValueError(
-                "Either num_epochs or max_steps must be > 0; both cannot be 0."
-            )
+            raise ValueError("Either num_epochs or max_steps must be > 0; both cannot be 0.")
         return self
 
 
@@ -411,9 +372,7 @@ class TrainingStatus(BaseModel):
         "error",
         "stopped",
     ] = Field(..., description = "Current phase of training pipeline")
-    is_training_running: bool = Field(
-        ..., description = "True if training loop is actively running"
-    )
+    is_training_running: bool = Field(..., description = "True if training loop is actively running")
     eval_enabled: bool = Field(
         False,
         description = "True if evaluation dataset is configured for this training run",
@@ -438,9 +397,7 @@ class TrainingProgress(BaseModel):
     total_steps: int = Field(..., description = "Total training steps")
     loss: Optional[float] = Field(None, description = "Current loss value")
     learning_rate: Optional[float] = Field(None, description = "Current learning rate")
-    progress_percent: float = Field(
-        ..., description = "Progress percentage (0.0 to 100.0)"
-    )
+    progress_percent: float = Field(..., description = "Progress percentage (0.0 to 100.0)")
     epoch: Optional[float] = Field(None, description = "Current epoch")
     elapsed_seconds: Optional[float] = Field(
         None, description = "Time elapsed since training started"
@@ -449,9 +406,7 @@ class TrainingProgress(BaseModel):
     grad_norm: Optional[float] = Field(
         None, description = "L2 norm of gradients, computed before gradient clipping"
     )
-    num_tokens: Optional[int] = Field(
-        None, description = "Total number of tokens processed so far"
-    )
+    num_tokens: Optional[int] = Field(None, description = "Total number of tokens processed so far")
     eval_loss: Optional[float] = Field(
         None, description = "Eval loss from the most recent evaluation step"
     )
diff --git a/studio/backend/plugins/data-designer-github-repo-seed/src/data_designer_github_repo_seed/scraper.py b/studio/backend/plugins/data-designer-github-repo-seed/src/data_designer_github_repo_seed/scraper.py
index 6acb985b5b..d468db70d2 100644
--- a/studio/backend/plugins/data-designer-github-repo-seed/src/data_designer_github_repo_seed/scraper.py
+++ b/studio/backend/plugins/data-designer-github-repo-seed/src/data_designer_github_repo_seed/scraper.py
@@ -91,18 +91,13 @@ def _read_jsonl(path: Path, max_rows: int | None = None):
 
 
 def _flatten_issue_row(r: dict, repo: str, include_comments: bool, max_c: int) -> dict:
-    labels = [
-        l.get("name")
-        for l in (r.get("labels", {}) or {}).get("nodes", [])
-        if l.get("name")
-    ]
+    labels = [l.get("name") for l in (r.get("labels", {}) or {}).get("nodes", []) if l.get("name")]
     comments_nodes = (r.get("comments") or {}).get("nodes") or []
     comments_text = ""
     if include_comments and comments_nodes:
         kept = comments_nodes[:max_c]
         comments_text = "\n\n".join(
-            f"[{(c.get('author') or {}).get('login', '?')}]: {c.get('body') or ''}"
-            for c in kept
+            f"[{(c.get('author') or {}).get('login', '?')}]: {c.get('body') or ''}" for c in kept
         )
     return {
         "item_type": "issue",
@@ -121,18 +116,13 @@ def _flatten_issue_row(r: dict, repo: str, include_comments: bool, max_c: int) -
 
 
 def _flatten_pr_row(r: dict, repo: str, include_comments: bool, max_c: int) -> dict:
-    labels = [
-        l.get("name")
-        for l in (r.get("labels", {}) or {}).get("nodes", [])
-        if l.get("name")
-    ]
+    labels = [l.get("name") for l in (r.get("labels", {}) or {}).get("nodes", []) if l.get("name")]
     comments_nodes = (r.get("comments") or {}).get("nodes") or []
     comments_text = ""
     if include_comments and comments_nodes:
         kept = comments_nodes[:max_c]
         comments_text = "\n\n".join(
-            f"[{(c.get('author') or {}).get('login', '?')}]: {c.get('body') or ''}"
-            for c in kept
+            f"[{(c.get('author') or {}).get('login', '?')}]: {c.get('body') or ''}" for c in kept
         )
     return {
         "item_type": "pull",
@@ -205,14 +195,8 @@ def scrape(cfg: ScrapeConfig, base_dir: Path):
                 scraper.scrape_prs()
             if "commits" in cfg.item_types:
                 default_ref = repo_meta.get("defaultBranchRef") or {}
-                default_branch = (
-                    default_ref.get("name") if isinstance(default_ref, dict) else None
-                )
-                branch = (
-                    f"refs/heads/{default_branch}"
-                    if default_branch
-                    else "refs/heads/main"
-                )
+                default_branch = default_ref.get("name") if isinstance(default_ref, dict) else None
+                branch = f"refs/heads/{default_branch}" if default_branch else "refs/heads/main"
                 scraper.scrape_commits(branch = branch)
         finally:
             scraper.close()
@@ -222,16 +206,12 @@ def scrape(cfg: ScrapeConfig, base_dir: Path):
         if "issues" in cfg.item_types:
             for row in _read_jsonl(repo_dir / "issues.jsonl", read_cap):
                 all_rows.append(
-                    _flatten_issue_row(
-                        row, repo, cfg.include_comments, cfg.max_comments_per_item
-                    )
+                    _flatten_issue_row(row, repo, cfg.include_comments, cfg.max_comments_per_item)
                 )
         if "pulls" in cfg.item_types:
             for row in _read_jsonl(repo_dir / "pull_requests.jsonl", read_cap):
                 all_rows.append(
-                    _flatten_pr_row(
-                        row, repo, cfg.include_comments, cfg.max_comments_per_item
-                    )
+                    _flatten_pr_row(row, repo, cfg.include_comments, cfg.max_comments_per_item)
                 )
         if "commits" in cfg.item_types:
             for row in _read_jsonl(repo_dir / "commits.jsonl", read_cap):
diff --git a/studio/backend/plugins/data-designer-github-repo-seed/src/data_designer_github_repo_seed/scraper_impl/gh_client.py b/studio/backend/plugins/data-designer-github-repo-seed/src/data_designer_github_repo_seed/scraper_impl/gh_client.py
index 696d0ccb98..eda242a6ea 100644
--- a/studio/backend/plugins/data-designer-github-repo-seed/src/data_designer_github_repo_seed/scraper_impl/gh_client.py
+++ b/studio/backend/plugins/data-designer-github-repo-seed/src/data_designer_github_repo_seed/scraper_impl/gh_client.py
@@ -60,9 +60,7 @@ class GitHubClient:
         token_source: str | None = None,
     ):
         if token:
-            self._token_source = (
-                token_source or "explicit token argument (recipe-level field)"
-            )
+            self._token_source = token_source or "explicit token argument (recipe-level field)"
         elif os.environ.get("GH_TOKEN"):
             self._token_source = "GH_TOKEN environment variable"
             token = os.environ["GH_TOKEN"]
@@ -72,9 +70,7 @@ class GitHubClient:
         else:
             raise RuntimeError("GH_TOKEN or GITHUB_TOKEN not set in environment")
         self.session = requests.Session()
-        self.session.headers.update(
-            {**BASE_HEADERS, "Authorization": f"Bearer {token}"}
-        )
+        self.session.headers.update({**BASE_HEADERS, "Authorization": f"Bearer {token}"})
         self.min_remaining_graphql = min_remaining_graphql
         self.min_remaining_rest = min_remaining_rest
         self.graphql_remaining: Optional[int] = None
@@ -85,7 +81,11 @@ class GitHubClient:
         self.calls_rest = 0
         self.retry_count = 0
 
-    def _sleep_until(self, reset_ts: int, buffer_s: int = 10) -> None:
+    def _sleep_until(
+        self,
+        reset_ts: int,
+        buffer_s: int = 10,
+    ) -> None:
         now = int(time.time())
         wait = max(0, reset_ts - now) + buffer_s
         log.warning("Rate limit hit. Sleeping %ds until reset.", wait)
@@ -209,9 +209,7 @@ class GitHubClient:
                     # Retry on RATE_LIMITED
                     for e in errs:
                         if e.get("type") == "RATE_LIMITED":
-                            self._sleep_until(
-                                (self.graphql_reset or int(time.time()) + 60)
-                            )
+                            self._sleep_until((self.graphql_reset or int(time.time()) + 60))
                             break
                     else:
                         # No rate-limit error, log and return partial
@@ -243,9 +241,7 @@ class GitHubClient:
         last_err = None
         for attempt in range(max_retries):
             try:
-                r = self.session.request(
-                    method, url, params = params, json = json_body, timeout = 120
-                )
+                r = self.session.request(method, url, params = params, json = json_body, timeout = 120)
                 self.calls_rest += 1
                 rem = r.headers.get("X-RateLimit-Remaining")
                 rst = r.headers.get("X-RateLimit-Reset")
@@ -269,9 +265,7 @@ class GitHubClient:
                 if r.status_code in (403, 429):
                     retry_after = _retry_after_seconds(r.headers.get("Retry-After"))
                     if retry_after is not None:
-                        log.warning(
-                            "Secondary rate limit on REST. Sleep %ds.", retry_after
-                        )
+                        log.warning("Secondary rate limit on REST. Sleep %ds.", retry_after)
                         time.sleep(retry_after + 2)
                         continue
                     # Check if primary rate
@@ -290,7 +284,10 @@ class GitHubClient:
         raise RuntimeError(f"REST failed after {max_retries} retries: {last_err}")
 
     def rest_paginate(
-        self, path: str, params: Optional[Dict[str, Any]] = None, per_page: int = 100
+        self,
+        path: str,
+        params: Optional[Dict[str, Any]] = None,
+        per_page: int = 100,
     ) -> Iterator[dict]:
         params = dict(params or {})
         params.setdefault("per_page", per_page)
@@ -298,9 +295,7 @@ class GitHubClient:
         while True:
             r = self.rest("GET", url, params = params if url == path else None)
             if r.status_code != 200:
-                log.error(
-                    "REST paginate got %s at %s: %s", r.status_code, url, r.text[:200]
-                )
+                log.error("REST paginate got %s at %s: %s", r.status_code, url, r.text[:200])
                 return
             items = r.json()
             if isinstance(items, dict):
diff --git a/studio/backend/plugins/data-designer-github-repo-seed/src/data_designer_github_repo_seed/scraper_impl/scraper.py b/studio/backend/plugins/data-designer-github-repo-seed/src/data_designer_github_repo_seed/scraper_impl/scraper.py
index 127129e18b..826ffc1256 100644
--- a/studio/backend/plugins/data-designer-github-repo-seed/src/data_designer_github_repo_seed/scraper_impl/scraper.py
+++ b/studio/backend/plugins/data-designer-github-repo-seed/src/data_designer_github_repo_seed/scraper_impl/scraper.py
@@ -86,11 +86,7 @@ class RepoScraper:
         return counter >= lim
 
     def _log_rate(self, where: str, data: Dict[str, Any]) -> None:
-        rl = (
-            data.get("data", {}).get("rateLimit")
-            if isinstance(data.get("data"), dict)
-            else None
-        )
+        rl = data.get("data", {}).get("rateLimit") if isinstance(data.get("data"), dict) else None
         if rl:
             log.debug(
                 "[%s] rate cost=%s remaining=%s resetAt=%s",
@@ -102,9 +98,7 @@ class RepoScraper:
 
     # ----- repo meta -----
     def scrape_repo_meta(self) -> Dict[str, Any]:
-        data = self.client.graphql(
-            Q.REPO_META_QUERY, {"owner": self.owner, "name": self.name}
-        )
+        data = self.client.graphql(Q.REPO_META_QUERY, {"owner": self.owner, "name": self.name})
         self._log_rate("repo_meta", data)
         repo = data.get("data", {}).get("repository") or {}
         repo["_fetchedAt"] = ts()
@@ -150,11 +144,7 @@ class RepoScraper:
                         self._paginate_issue_comments(
                             it["number"], it["comments"]["pageInfo"]["endCursor"]
                         )
-                    if (
-                        it.get("timelineItems", {})
-                        .get("pageInfo", {})
-                        .get("hasNextPage")
-                    ):
+                    if it.get("timelineItems", {}).get("pageInfo", {}).get("hasNextPage"):
                         self._paginate_issue_timeline(
                             it["number"],
                             it["timelineItems"]["pageInfo"]["endCursor"],
@@ -261,30 +251,16 @@ class RepoScraper:
                 num = pr["number"]
                 if not self.light:
                     if pr.get("comments", {}).get("pageInfo", {}).get("hasNextPage"):
-                        self._paginate_pr_comments(
-                            num, pr["comments"]["pageInfo"]["endCursor"]
-                        )
-                    if (
-                        pr.get("timelineItems", {})
-                        .get("pageInfo", {})
-                        .get("hasNextPage")
-                    ):
+                        self._paginate_pr_comments(num, pr["comments"]["pageInfo"]["endCursor"])
+                    if pr.get("timelineItems", {}).get("pageInfo", {}).get("hasNextPage"):
                         self._paginate_pr_timeline(
                             num, pr["timelineItems"]["pageInfo"]["endCursor"]
                         )
                     if pr.get("commits", {}).get("pageInfo", {}).get("hasNextPage"):
-                        self._paginate_pr_commits(
-                            num, pr["commits"]["pageInfo"]["endCursor"]
-                        )
+                        self._paginate_pr_commits(num, pr["commits"]["pageInfo"]["endCursor"])
                     if pr.get("files", {}).get("pageInfo", {}).get("hasNextPage"):
-                        self._paginate_pr_files(
-                            num, pr["files"]["pageInfo"]["endCursor"]
-                        )
-                    if (
-                        pr.get("reviewThreads", {})
-                        .get("pageInfo", {})
-                        .get("hasNextPage")
-                    ):
+                        self._paginate_pr_files(num, pr["files"]["pageInfo"]["endCursor"])
+                    if pr.get("reviewThreads", {}).get("pageInfo", {}).get("hasNextPage"):
                         self._paginate_pr_review_threads(
                             num, pr["reviewThreads"]["pageInfo"]["endCursor"]
                         )
@@ -342,9 +318,7 @@ class RepoScraper:
                 "after": cur,
             }
             data = self.client.graphql(Q.PR_TIMELINE_QUERY, vars_)
-            item = ((data.get("data") or {}).get("repository") or {}).get(
-                "pullRequest"
-            ) or {}
+            item = ((data.get("data") or {}).get("repository") or {}).get("pullRequest") or {}
             tl = item.get("timelineItems") or {}
             for ev in tl.get("nodes") or []:
                 ev["_owner"] = self.owner
@@ -367,9 +341,7 @@ class RepoScraper:
                 "after": cur,
             }
             data = self.client.graphql(Q.PR_COMMITS_QUERY, vars_)
-            item = ((data.get("data") or {}).get("repository") or {}).get(
-                "pullRequest"
-            ) or {}
+            item = ((data.get("data") or {}).get("repository") or {}).get("pullRequest") or {}
             cc = item.get("commits") or {}
             for c in cc.get("nodes") or []:
                 c["_owner"] = self.owner
@@ -392,9 +364,7 @@ class RepoScraper:
                 "after": cur,
             }
             data = self.client.graphql(Q.PR_FILES_QUERY, vars_)
-            item = ((data.get("data") or {}).get("repository") or {}).get(
-                "pullRequest"
-            ) or {}
+            item = ((data.get("data") or {}).get("repository") or {}).get("pullRequest") or {}
             ff = item.get("files") or {}
             for f in ff.get("nodes") or []:
                 f["_owner"] = self.owner
@@ -419,9 +389,7 @@ class RepoScraper:
                 "after": cur,
             }
             data = self.client.graphql(Q.PR_REVIEW_THREADS_QUERY, vars_)
-            item = ((data.get("data") or {}).get("repository") or {}).get(
-                "pullRequest"
-            ) or {}
+            item = ((data.get("data") or {}).get("repository") or {}).get("pullRequest") or {}
             rt = item.get("reviewThreads") or {}
             for th in rt.get("nodes") or []:
                 th["_owner"] = self.owner
@@ -461,9 +429,7 @@ class RepoScraper:
                 d["_fetchedAt"] = ts()
                 num = d["number"]
                 if d.get("comments", {}).get("pageInfo", {}).get("hasNextPage"):
-                    self._paginate_discussion_comments(
-                        num, d["comments"]["pageInfo"]["endCursor"]
-                    )
+                    self._paginate_discussion_comments(num, d["comments"]["pageInfo"]["endCursor"])
                 # paginate replies per comment if needed
                 for c in d.get("comments", {}).get("nodes", []) or []:
                     if c.get("replies", {}).get("pageInfo", {}).get("hasNextPage"):
@@ -501,9 +467,7 @@ class RepoScraper:
                 "after": cur,
             }
             data = self.client.graphql(Q.DISCUSSION_COMMENTS_QUERY, vars_)
-            disc = ((data.get("data") or {}).get("repository") or {}).get(
-                "discussion"
-            ) or {}
+            disc = ((data.get("data") or {}).get("repository") or {}).get("discussion") or {}
             cc = disc.get("comments") or {}
             for c in cc.get("nodes") or []:
                 c["_owner"] = self.owner
@@ -513,9 +477,7 @@ class RepoScraper:
             info = cc.get("pageInfo") or {}
             cur = info.get("endCursor") if info.get("hasNextPage") else None
 
-    def _paginate_discussion_replies(
-        self, comment_id: str, after: str, disc_number: int
-    ) -> None:
+    def _paginate_discussion_replies(self, comment_id: str, after: str, disc_number: int) -> None:
         cur = after
         while cur:
             vars_ = {
@@ -650,12 +612,8 @@ def setup_logging(log_file: Path) -> None:
 
 def main():
     ap = argparse.ArgumentParser()
-    ap.add_argument(
-        "--base-dir", default = "/mnt/disks/unslothai/ubuntu/workspace_34/github_scraper"
-    )
-    ap.add_argument(
-        "--repos", nargs = "+", default = ["unslothai/unsloth", "unslothai/unsloth-zoo"]
-    )
+    ap.add_argument("--base-dir", default = "/mnt/disks/unslothai/ubuntu/workspace_34/github_scraper")
+    ap.add_argument("--repos", nargs = "+", default = ["unslothai/unsloth", "unslothai/unsloth-zoo"])
     ap.add_argument("--trial", action = "store_true", help = "Small trial run")
     ap.add_argument(
         "--only",
@@ -688,7 +646,6 @@ def main():
     uploader = None
     if args.hf_upload_interval > 0:
         from hf_uploader import HFUploader
-
         uploader = HFUploader(data_dir, interval_s = args.hf_upload_interval)
         uploader.start()
 
@@ -729,15 +686,9 @@ def main():
                 if not only or "commits" in only:
                     default_ref = repo_meta.get("defaultBranchRef") or {}
                     default_branch = (
-                        default_ref.get("name")
-                        if isinstance(default_ref, dict)
-                        else None
-                    )
-                    branch = (
-                        f"refs/heads/{default_branch}"
-                        if default_branch
-                        else "refs/heads/main"
+                        default_ref.get("name") if isinstance(default_ref, dict) else None
                     )
+                    branch = f"refs/heads/{default_branch}" if default_branch else "refs/heads/main"
                     scraper.scrape_commits(branch = branch)
             finally:
                 scraper.close()
diff --git a/studio/backend/plugins/data-designer-github-repo-seed/src/data_designer_github_repo_seed/scraper_impl/state_store.py b/studio/backend/plugins/data-designer-github-repo-seed/src/data_designer_github_repo_seed/scraper_impl/state_store.py
index efa663db2f..de9ccca82b 100644
--- a/studio/backend/plugins/data-designer-github-repo-seed/src/data_designer_github_repo_seed/scraper_impl/state_store.py
+++ b/studio/backend/plugins/data-designer-github-repo-seed/src/data_designer_github_repo_seed/scraper_impl/state_store.py
@@ -25,7 +25,11 @@ class StateStore:
             except Exception:
                 self._data = {}
 
-    def get(self, key: str, default: Any = None) -> Any:
+    def get(
+        self,
+        key: str,
+        default: Any = None,
+    ) -> Any:
         with self._lock:
             return self._data.get(key, default)
 
diff --git a/studio/backend/plugins/data-designer-unstructured-seed/src/data_designer_unstructured_seed/chunking.py b/studio/backend/plugins/data-designer-unstructured-seed/src/data_designer_unstructured_seed/chunking.py
index f6fdf74612..4da46634e5 100644
--- a/studio/backend/plugins/data-designer-unstructured-seed/src/data_designer_unstructured_seed/chunking.py
+++ b/studio/backend/plugins/data-designer-unstructured-seed/src/data_designer_unstructured_seed/chunking.py
@@ -19,10 +19,7 @@ _MIN_BREAK_RATIO = 0.6
 _CACHE_DIR = unstructured_seed_cache_root()
 
 
-def resolve_chunking(
-    chunk_size: Any,
-    chunk_overlap: Any,
-) -> tuple[int, int]:
+def resolve_chunking(chunk_size: Any, chunk_overlap: Any) -> tuple[int, int]:
     size = _to_int(chunk_size, DEFAULT_CHUNK_SIZE)
     size = max(1, min(size, MAX_CHUNK_SIZE))
     overlap = _to_int(chunk_overlap, DEFAULT_CHUNK_OVERLAP)
@@ -31,11 +28,7 @@ def resolve_chunking(
 
 
 def build_unstructured_preview_rows(
-    *,
-    source_path: Path,
-    preview_size: int,
-    chunk_size: Any,
-    chunk_overlap: Any,
+    *, source_path: Path, preview_size: int, chunk_size: Any, chunk_overlap: Any
 ) -> list[dict[str, str]]:
     parquet_path, rows = materialize_unstructured_seed_dataset(
         source_path = source_path,
@@ -49,9 +42,7 @@ def build_unstructured_preview_rows(
     try:
         import pandas as pd
     except ImportError as exc:  # pragma: no cover
-        raise RuntimeError(
-            f"pandas is required for unstructured seed processing: {exc}"
-        ) from exc
+        raise RuntimeError(f"pandas is required for unstructured seed processing: {exc}") from exc
 
     dataframe = pd.read_parquet(parquet_path).head(count)
     return [
@@ -78,10 +69,7 @@ def build_multi_file_preview_rows(
     return _round_robin_preview(rows, preview_size)
 
 
-def _round_robin_preview(
-    rows: list[dict[str, str]],
-    preview_size: int,
-) -> list[dict[str, str]]:
+def _round_robin_preview(rows: list[dict[str, str]], preview_size: int) -> list[dict[str, str]]:
     """Pick preview rows round-robin across source files so every file is represented."""
     if not rows or preview_size <= 0:
         return []
@@ -115,10 +103,7 @@ def _round_robin_preview(
 
 
 def materialize_unstructured_seed_dataset(
-    *,
-    source_path: Path,
-    chunk_size: Any,
-    chunk_overlap: Any,
+    *, source_path: Path, chunk_size: Any, chunk_overlap: Any
 ) -> tuple[Path, list[dict[str, str]]]:
     resolved = source_path.expanduser().resolve()
     if not resolved.is_file():
@@ -148,9 +133,7 @@ def materialize_unstructured_seed_dataset(
     try:
         import pandas as pd
     except ImportError as exc:  # pragma: no cover
-        raise RuntimeError(
-            f"pandas is required for unstructured seed processing: {exc}"
-        ) from exc
+        raise RuntimeError(f"pandas is required for unstructured seed processing: {exc}") from exc
 
     tmp_path = _CACHE_DIR / f"{key}.tmp.parquet"
     pd.DataFrame(rows).to_parquet(tmp_path, index = False)
@@ -209,12 +192,7 @@ def normalize_unstructured_text(text: str) -> str:
     return re.sub(r"\n{3,}", "\n\n", normalized).strip()
 
 
-def split_text_into_chunks(
-    *,
-    text: str,
-    chunk_size: int,
-    chunk_overlap: int,
-) -> list[str]:
+def split_text_into_chunks(*, text: str, chunk_size: int, chunk_overlap: int) -> list[str]:
     if not text:
         return []
     if chunk_size <= 0:
@@ -268,12 +246,7 @@ def _to_int(value: Any, fallback: int) -> int:
     return parsed
 
 
-def _compute_cache_key(
-    *,
-    source_path: Path,
-    chunk_size: int,
-    chunk_overlap: int,
-) -> str:
+def _compute_cache_key(*, source_path: Path, chunk_size: int, chunk_overlap: int) -> str:
     stat = source_path.stat()
     payload = "|".join(
         [
@@ -288,9 +261,7 @@ def _compute_cache_key(
 
 
 def _compute_multi_file_cache_key(
-    file_entries: list[tuple[Path, str]],
-    chunk_size: int,
-    chunk_overlap: int,
+    file_entries: list[tuple[Path, str]], chunk_size: int, chunk_overlap: int
 ) -> str:
     parts: list[str] = []
     for path, name in sorted(file_entries, key = lambda e: e[1]):
diff --git a/studio/backend/routes/auth.py b/studio/backend/routes/auth.py
index 23112ca2f8..7c60545595 100644
--- a/studio/backend/routes/auth.py
+++ b/studio/backend/routes/auth.py
@@ -227,9 +227,7 @@ async def auth_status() -> AuthStatusResponse:
     return AuthStatusResponse(
         initialized = storage.is_initialized(),
         default_username = storage.DEFAULT_ADMIN_USERNAME,
-        requires_password_change = storage.requires_password_change(
-            storage.DEFAULT_ADMIN_USERNAME
-        )
+        requires_password_change = storage.requires_password_change(storage.DEFAULT_ADMIN_USERNAME)
         if storage.is_initialized()
         else True,
     )
@@ -246,10 +244,7 @@ async def login(payload: AuthLoginRequest, request: Request) -> Token:
             status_code = status.HTTP_429_TOO_MANY_REQUESTS,
             # IP is intentionally not interpolated into the body; behind a
             # proxy or NAT it is either misleading or an info leak.
-            detail = (
-                f"Too many failed login attempts. "
-                f"Try again in {blocked_for} seconds."
-            ),
+            detail = (f"Too many failed login attempts. " f"Try again in {blocked_for} seconds."),
             headers = {"Retry-After": str(blocked_for)},
         )
 
@@ -285,8 +280,7 @@ async def login(payload: AuthLoginRequest, request: Request) -> Token:
 
 @router.post("/logout", status_code = status.HTTP_204_NO_CONTENT)
 async def logout(
-    request: Request,
-    current_subject: str = Depends(get_current_subject_allow_password_change),
+    request: Request, current_subject: str = Depends(get_current_subject_allow_password_change)
 ) -> Response:
     """Revoke refresh tokens for the subject; the access token is stateless and expires on its own."""
     try:
@@ -335,9 +329,7 @@ async def refresh(payload: RefreshTokenRequest) -> Token:
         access_token = new_access_token,
         refresh_token = new_refresh_token,
         token_type = "bearer",
-        must_change_password = False
-        if is_desktop
-        else storage.requires_password_change(username),
+        must_change_password = False if is_desktop else storage.requires_password_change(username),
     )
 
 
@@ -402,8 +394,7 @@ def _row_to_api_key_response(row: dict) -> ApiKeyResponse:
 
 @router.post("/api-keys", response_model = CreateApiKeyResponse)
 async def create_api_key(
-    payload: CreateApiKeyRequest,
-    current_subject: str = Depends(get_current_subject),
+    payload: CreateApiKeyRequest, current_subject: str = Depends(get_current_subject)
 ) -> CreateApiKeyResponse:
     """Create a new API key. The raw key is returned once and cannot be retrieved later."""
     expires_at = None
@@ -424,9 +415,7 @@ async def create_api_key(
 
 
 @router.get("/api-keys", response_model = ApiKeyListResponse)
-async def list_api_keys(
-    current_subject: str = Depends(get_current_subject),
-) -> ApiKeyListResponse:
+async def list_api_keys(current_subject: str = Depends(get_current_subject)) -> ApiKeyListResponse:
     """List all API keys for the authenticated user (raw keys are never exposed)."""
     rows = storage.list_api_keys(current_subject)
     return ApiKeyListResponse(
@@ -435,10 +424,7 @@ async def list_api_keys(
 
 
 @router.delete("/api-keys/{key_id}")
-async def revoke_api_key(
-    key_id: int,
-    current_subject: str = Depends(get_current_subject),
-) -> dict:
+async def revoke_api_key(key_id: int, current_subject: str = Depends(get_current_subject)) -> dict:
     """Revoke (soft-delete) an API key."""
     if not storage.revoke_api_key(current_subject, key_id):
         raise HTTPException(
diff --git a/studio/backend/routes/chat_history.py b/studio/backend/routes/chat_history.py
index 4da3c7d621..68d2c67ec8 100644
--- a/studio/backend/routes/chat_history.py
+++ b/studio/backend/routes/chat_history.py
@@ -163,9 +163,7 @@ class ChatSettingsPayload(BaseModel):
     inferenceParams: Optional[ChatInferenceSettings] = None
     customPresets: Optional[list[ChatPreset]] = None
     activePreset: Optional[str] = None
-    activePresetSource: Optional[Literal["builtin-default", "custom", "modified"]] = (
-        None
-    )
+    activePresetSource: Optional[Literal["builtin-default", "custom", "modified"]] = None
     autoTitle: Optional[bool] = None
     reasoningEffort: Optional[
         Literal["none", "minimal", "low", "medium", "high", "max", "xhigh"]
@@ -228,10 +226,7 @@ async def list_threads(
 
 
 @router.post("/threads", response_model = ChatThread)
-async def save_thread(
-    payload: ChatThread,
-    current_subject: str = Depends(get_current_subject),
-):
+async def save_thread(payload: ChatThread, current_subject: str = Depends(get_current_subject)):
     if payload.projectId and get_chat_project(payload.projectId) is None:
         raise HTTPException(
             status_code = 404,
@@ -241,10 +236,7 @@ async def save_thread(
 
 
 @router.get("/threads/{thread_id}", response_model = ChatThread)
-async def get_thread(
-    thread_id: str,
-    current_subject: str = Depends(get_current_subject),
-):
+async def get_thread(thread_id: str, current_subject: str = Depends(get_current_subject)):
     thread = get_chat_thread(thread_id)
     if thread is None:
         raise HTTPException(status_code = 404, detail = f"Thread {thread_id} not found")
@@ -277,8 +269,7 @@ async def patch_thread(
 
 @router.delete("/threads")
 async def delete_threads(
-    payload: ChatDeleteRequest,
-    current_subject: str = Depends(get_current_subject),
+    payload: ChatDeleteRequest, current_subject: str = Depends(get_current_subject)
 ):
     delete_chat_threads(payload.ids)
     return {"status": "deleted"}
@@ -286,8 +277,7 @@ async def delete_threads(
 
 @router.get("/projects", response_model = ChatProjectListResponse)
 async def list_projects(
-    include_archived: bool = Query(False),
-    current_subject: str = Depends(get_current_subject),
+    include_archived: bool = Query(False), current_subject: str = Depends(get_current_subject)
 ):
     return ChatProjectListResponse(
         projects = [
@@ -298,18 +288,12 @@ async def list_projects(
 
 
 @router.post("/projects", response_model = ChatProject)
-async def save_project(
-    payload: ChatProject,
-    current_subject: str = Depends(get_current_subject),
-):
+async def save_project(payload: ChatProject, current_subject: str = Depends(get_current_subject)):
     return ChatProject(**upsert_chat_project(payload.model_dump()))
 
 
 @router.get("/projects/{project_id}", response_model = ChatProject)
-async def get_project(
-    project_id: str,
-    current_subject: str = Depends(get_current_subject),
-):
+async def get_project(project_id: str, current_subject: str = Depends(get_current_subject)):
     project = ensure_chat_project_workspace(project_id)
     if project is None:
         raise HTTPException(
@@ -356,10 +340,7 @@ async def delete_project(
 
 
 @router.get("/threads/{thread_id}/messages", response_model = ChatMessageListResponse)
-async def get_thread_messages(
-    thread_id: str,
-    current_subject: str = Depends(get_current_subject),
-):
+async def get_thread_messages(thread_id: str, current_subject: str = Depends(get_current_subject)):
     if get_chat_thread(thread_id) is None:
         raise HTTPException(status_code = 404, detail = f"Thread {thread_id} not found")
     return ChatMessageListResponse(
@@ -369,8 +350,7 @@ async def get_thread_messages(
 
 @router.post("/messages:batch", response_model = ChatMessagesBatchResponse)
 async def batch_thread_messages(
-    payload: ChatMessagesBatchRequest,
-    current_subject: str = Depends(get_current_subject),
+    payload: ChatMessagesBatchRequest, current_subject: str = Depends(get_current_subject)
 ):
     """One round-trip per sidebar/search rebuild instead of N. Unknown thread
     ids are returned as empty lists so callers don't need a pre-flight."""
@@ -425,14 +405,10 @@ async def replace_thread_messages(
     payload: ChatMessageSyncRequest,
     current_subject: str = Depends(get_current_subject),
 ):
-    mismatched_ids = [
-        message.id for message in payload.messages if message.threadId != thread_id
-    ]
+    mismatched_ids = [message.id for message in payload.messages if message.threadId != thread_id]
     if mismatched_ids:
         preview = ", ".join(mismatched_ids[:5])
-        suffix = (
-            "" if len(mismatched_ids) <= 5 else f" (+{len(mismatched_ids) - 5} more)"
-        )
+        suffix = "" if len(mismatched_ids) <= 5 else f" (+{len(mismatched_ids) - 5} more)"
         raise HTTPException(
             status_code = 400,
             detail = f"Message threadId mismatch: {preview}{suffix}",
@@ -478,8 +454,7 @@ async def get_import_ledger(current_subject: str = Depends(get_current_subject))
 
 @router.post("/import-ledger", response_model = ChatImportLedgerRecordResponse)
 async def record_import_ledger(
-    payload: ChatImportLedgerRecordRequest,
-    current_subject: str = Depends(get_current_subject),
+    payload: ChatImportLedgerRecordRequest, current_subject: str = Depends(get_current_subject)
 ):
     """Mark each legacy thread id as imported. Idempotent."""
     accepted, inserted = upsert_chat_legacy_imports(payload.threadIds)
@@ -499,8 +474,7 @@ async def get_settings(current_subject: str = Depends(get_current_subject)):
 
 @router.put("/settings", response_model = ChatSettingsResponse)
 async def put_settings(
-    payload: dict[str, Any],
-    current_subject: str = Depends(get_current_subject),
+    payload: dict[str, Any], current_subject: str = Depends(get_current_subject)
 ):
     try:
         parsed = ChatSettingsPayload.model_validate(payload)
diff --git a/studio/backend/routes/data_recipe/jobs.py b/studio/backend/routes/data_recipe/jobs.py
index 238ff08006..a2d41f87b0 100644
--- a/studio/backend/routes/data_recipe/jobs.py
+++ b/studio/backend/routes/data_recipe/jobs.py
@@ -159,9 +159,7 @@ def _ensure_selected_local_model_loaded(
 ) -> None:
     model_loaded, active_model, active_variant = _loaded_local_model_identity()
     if not model_loaded:
-        raise ValueError(
-            "No model loaded in Chat. Load a model first, then run the recipe."
-        )
+        raise ValueError("No model loaded in Chat. Load a model first, then run the recipe.")
 
     selection = _single_used_local_model_selection(recipe, local_provider_names)
     if selection is None:
@@ -171,9 +169,7 @@ def _ensure_selected_local_model_loaded(
     variant_matches = not gguf_variant or active_variant == gguf_variant
     if active_model.lower() != target.lower() or not variant_matches:
         selected = f"{target} ({gguf_variant})" if gguf_variant else target
-        active = (
-            f"{active_model} ({active_variant})" if active_variant else active_model
-        )
+        active = f"{active_model} ({active_variant})" if active_variant else active_model
         raise ValueError(
             "Selected local model is not loaded. "
             f"Selected {selected}; active {active or 'none'}. "
@@ -207,9 +203,7 @@ def _inject_local_structured_response_format(
     for mc in model_configs:
         if not isinstance(mc, dict):
             continue
-        if mc.get("provider") in local_provider_names and isinstance(
-            mc.get("alias"), str
-        ):
+        if mc.get("provider") in local_provider_names and isinstance(mc.get("alias"), str):
             alias_to_local_mc[mc["alias"]] = mc
 
     if not alias_to_local_mc:
@@ -307,18 +301,12 @@ def _inject_local_providers(recipe: dict[str, Any], request: Request) -> Optiona
     # from an LLM column through a model_config. Orphan model_config nodes
     # that reference a local provider but that no LLM column uses should
     # not block runs; the recipe would never call /v1 for them.
-    local_names = {
-        providers[i].get("name") for i in local_indices if providers[i].get("name")
-    }
+    local_names = {providers[i].get("name") for i in local_indices if providers[i].get("name")}
     used_aliases = _used_llm_model_aliases(recipe)
     referenced_providers = {
         mc.get("provider")
         for mc in recipe.get("model_configs", [])
-        if (
-            isinstance(mc, dict)
-            and mc.get("provider")
-            and mc.get("alias") in used_aliases
-        )
+        if (isinstance(mc, dict) and mc.get("provider") and mc.get("alias") in used_aliases)
     }
 
     token = ""
@@ -409,9 +397,7 @@ def _normalize_run_name(value: Any) -> str | None:
     if value is None:
         return None
     if not isinstance(value, str):
-        raise HTTPException(
-            status_code = 400, detail = "invalid run_name: must be a string"
-        )
+        raise HTTPException(status_code = 400, detail = "invalid run_name: must be a string")
     trimmed = value.strip()
     if not trimmed:
         return None
@@ -439,7 +425,6 @@ def create_job(payload: RecipePayload, request: Request):
     if run_config_raw is not None:
         try:
             from data_designer.config.run_config import RunConfig
-
             RunConfig.model_validate(run_config_raw)
         except (ImportError, ValidationError, TypeError, ValueError) as exc:
             raise log_and_http_error(
@@ -506,7 +491,6 @@ def _revoke_internal_api_key_safe(key_id: int) -> None:
     that revocation failures never mask the caller's own error path."""
     try:
         from auth import storage  # deferred: avoids circular import
-
         storage.revoke_internal_api_key(key_id)
     except Exception:
         pass
@@ -578,9 +562,7 @@ def publish_job_dataset(job_id: str, payload: PublishDatasetRequest):
     description = payload.description.strip()
     hf_token = payload.hf_token.strip() if isinstance(payload.hf_token, str) else None
     artifact_path = (
-        payload.artifact_path.strip()
-        if isinstance(payload.artifact_path, str)
-        else None
+        payload.artifact_path.strip() if isinstance(payload.artifact_path, str) else None
     )
 
     if not repo_id:
@@ -591,10 +573,7 @@ def publish_job_dataset(job_id: str, payload: PublishDatasetRequest):
     mgr = get_job_manager()
     status = mgr.get_status(job_id)
     if status is not None:
-        if (
-            status.get("status") != "completed"
-            or status.get("execution_type") != "full"
-        ):
+        if status.get("status") != "completed" or status.get("execution_type") != "full":
             raise HTTPException(
                 status_code = 409,
                 detail = "Only completed full runs can be published.",
diff --git a/studio/backend/routes/data_recipe/mcp.py b/studio/backend/routes/data_recipe/mcp.py
index 2c79d323f3..78a39877cc 100644
--- a/studio/backend/routes/data_recipe/mcp.py
+++ b/studio/backend/routes/data_recipe/mcp.py
@@ -69,9 +69,7 @@ def list_mcp_tools(payload: McpToolsListRequest) -> McpToolsListResponse:
         provider = built[0]
         try:
             tools = mcp_io.list_tools(provider, timeout_sec = payload.timeout_sec)
-            tool_names = sorted(
-                {tool.name for tool in tools if getattr(tool, "name", "")}
-            )
+            tool_names = sorted({tool.name for tool in tools if getattr(tool, "name", "")})
             for tool_name in tool_names:
                 tool_to_providers[tool_name].append(provider.name)
             providers.append(
diff --git a/studio/backend/routes/data_recipe/seed.py b/studio/backend/routes/data_recipe/seed.py
index 51ea37452e..6368585932 100644
--- a/studio/backend/routes/data_recipe/seed.py
+++ b/studio/backend/routes/data_recipe/seed.py
@@ -63,9 +63,7 @@ _SAFE_ID_RE = re.compile(r"^[a-zA-Z0-9_-]+$")
 
 def _validate_safe_id(value: str, label: str) -> str:
     if not value or not _SAFE_ID_RE.match(value):
-        raise HTTPException(
-            400, f"Invalid {label}: must be alphanumeric/dash/underscore only"
-        )
+        raise HTTPException(400, f"Invalid {label}: must be alphanumeric/dash/underscore only")
     return value
 
 
@@ -75,8 +73,7 @@ def _serialize_preview_value(value: Any) -> Any:
 
 def _serialize_preview_rows(rows: list[dict[str, Any]]) -> list[dict[str, Any]]:
     return [
-        {str(key): _serialize_preview_value(value) for key, value in row.items()}
-        for row in rows
+        {str(key): _serialize_preview_value(value) for key, value in row.items()} for row in rows
     ]
 
 
@@ -124,7 +121,9 @@ def _select_best_file(data_files: list[str], split: str = DEFAULT_SPLIT) -> str
 
 
 def _resolve_seed_hf_path(
-    dataset_name: str, data_files: list[str], split: str = DEFAULT_SPLIT
+    dataset_name: str,
+    data_files: list[str],
+    split: str = DEFAULT_SPLIT,
 ) -> str | None:
     selected = _select_best_file(data_files, split)
     if not selected:
@@ -164,10 +163,7 @@ def _build_stream_load_kwargs(
 
 
 def _load_preview_rows(
-    *,
-    load_dataset_fn,
-    load_kwargs: dict[str, Any],
-    preview_size: int,
+    *, load_dataset_fn, load_kwargs: dict[str, Any], preview_size: int
 ) -> list[dict[str, Any]]:
     streamed_ds = load_dataset_fn(**load_kwargs)
     return [row for row in islice(streamed_ds, preview_size)]
@@ -198,9 +194,7 @@ def _decode_base64_payload(content_base64: str) -> bytes:
         raise HTTPException(status_code = 400, detail = "invalid base64 payload") from exc
 
 
-def _read_preview_rows_from_local_file(
-    path: Path, preview_size: int
-) -> list[dict[str, Any]]:
+def _read_preview_rows_from_local_file(path: Path, preview_size: int) -> list[dict[str, Any]]:
     try:
         import pandas as pd
     except ImportError as exc:
@@ -251,11 +245,7 @@ def _read_preview_rows_from_local_file(
 
 
 def _read_preview_rows_from_unstructured_file(
-    *,
-    path: Path,
-    preview_size: int,
-    chunk_size: int | None,
-    chunk_overlap: int | None,
+    *, path: Path, preview_size: int, chunk_size: int | None, chunk_overlap: int | None
 ) -> list[dict[str, Any]]:
     if resolve_chunking is None or build_unstructured_preview_rows is None:
         raise HTTPException(
@@ -302,9 +292,7 @@ def _read_preview_rows_from_multi_files(
     for fid, fname in zip(file_ids, file_names):
         extracted = block_dir / f"{fid}.extracted.txt"
         if not extracted.exists():
-            raise HTTPException(
-                404, f"Extracted text not found for file: {fname} (id: {fid})"
-            )
+            raise HTTPException(404, f"Extracted text not found for file: {fname} (id: {fid})")
         file_entries.append((extracted, fname))
 
     return build_multi_file_preview_rows(
@@ -384,9 +372,7 @@ def inspect_seed_dataset(payload: SeedInspectRequest) -> SeedInspectResponse:
             ) from exc
 
     if not preview_rows:
-        raise HTTPException(
-            status_code = 422, detail = "dataset appears empty or unreadable"
-        )
+        raise HTTPException(status_code = 422, detail = "dataset appears empty or unreadable")
     preview_rows = _serialize_preview_rows(preview_rows)
     columns = _extract_columns(preview_rows)
 
@@ -395,9 +381,7 @@ def inspect_seed_dataset(payload: SeedInspectRequest) -> SeedInspectResponse:
     else:
         resolved_path = _resolve_seed_hf_path(dataset_name, data_files, split)
         if not resolved_path:
-            raise HTTPException(
-                status_code = 422, detail = "unable to resolve seed dataset path"
-            )
+            raise HTTPException(status_code = 422, detail = "unable to resolve seed dataset path")
 
     return SeedInspectResponse(
         dataset_name = dataset_name,
@@ -415,13 +399,11 @@ def _extract_text_from_file(file_path: Path, ext: str) -> str:
         raw = file_path.read_text(encoding = "utf-8", errors = "ignore")
     elif ext == ".pdf":
         import pymupdf4llm
-
         raw = pymupdf4llm.to_markdown(
             str(file_path), write_images = False, show_progress = False, use_ocr = False
         )
     elif ext == ".docx":
         import mammoth
-
         with open(str(file_path), "rb") as f:
             result = mammoth.convert_to_markdown(f)
             raw = result.value
@@ -449,8 +431,7 @@ def _get_block_total_size(block_dir: Path) -> int:
 
 @router.post("/seed/upload-unstructured-file")
 async def upload_unstructured_file(
-    file: UploadFile = FastAPIFile(...),
-    block_id: str = Form(...),
+    file: UploadFile = FastAPIFile(...), block_id: str = Form(...)
 ) -> UnstructuredFileUploadResponse:
     _validate_safe_id(block_id, "block_id")
 
@@ -519,9 +500,7 @@ async def upload_unstructured_file(
     try:
         meta_path = block_dir / f"{file_id}.meta.json"
         meta_path.write_text(
-            json.dumps(
-                {"original_filename": original_filename, "size_bytes": size_bytes}
-            ),
+            json.dumps({"original_filename": original_filename, "size_bytes": size_bytes}),
             encoding = "utf-8",
         )
     except OSError:
@@ -647,9 +626,7 @@ def inspect_seed_upload(payload: SeedInspectUploadRequest) -> SeedInspectRespons
             int(payload.preview_size),
         )
     if not preview_rows:
-        raise HTTPException(
-            status_code = 422, detail = "dataset appears empty or unreadable"
-        )
+        raise HTTPException(status_code = 422, detail = "dataset appears empty or unreadable")
     columns = _extract_columns(preview_rows)
 
     return SeedInspectResponse(
diff --git a/studio/backend/routes/data_recipe/validate.py b/studio/backend/routes/data_recipe/validate.py
index f6fd9e6046..e26093d6bf 100644
--- a/studio/backend/routes/data_recipe/validate.py
+++ b/studio/backend/routes/data_recipe/validate.py
@@ -21,7 +21,9 @@ from utils.utils import safe_error_detail, safe_curated_detail, log_and_http_err
 logger = get_logger(__name__)
 router = APIRouter()
 
-_GITHUB_VALIDATE_NOTE = "Recipe shape is valid. GitHub access and rate limits are checked when the run starts."
+_GITHUB_VALIDATE_NOTE = (
+    "Recipe shape is valid. GitHub access and rate limits are checked when the run starts."
+)
 _GITHUB_ITEM_TYPES = {"issues", "pulls", "commits"}
 
 
@@ -44,23 +46,17 @@ def _validate_github_seed_static(source: dict[str, Any]) -> list[ValidateError]:
     else:
         for repo in repos:
             if not isinstance(repo, str) or not repo.strip() or "/" not in repo:
-                errors.append(
-                    ValidateError(message = "GitHub repos must be owner/name strings.")
-                )
+                errors.append(ValidateError(message = "GitHub repos must be owner/name strings."))
                 break
 
     item_types = source.get("item_types")
     if not isinstance(item_types, list) or not item_types:
-        errors.append(
-            ValidateError(message = "GitHub seed requires at least one item type.")
-        )
+        errors.append(ValidateError(message = "GitHub seed requires at least one item type."))
     else:
         invalid_items = [item for item in item_types if item not in _GITHUB_ITEM_TYPES]
         if invalid_items:
             errors.append(
-                ValidateError(
-                    message = "GitHub item types must be issues, pulls, or commits."
-                )
+                ValidateError(message = "GitHub item types must be issues, pulls, or commits.")
             )
 
     try:
@@ -166,8 +162,7 @@ def validate(payload: RecipePayload) -> ValidateResponse:
             if not (exc.name or "").startswith("data_designer"):
                 raise
             logger.debug(
-                "data_designer not installed; deferring full config "
-                "validation to run start",
+                "data_designer not installed; deferring full config validation to run start",
                 missing_module = exc.name,
             )
         except Exception as exc:
diff --git a/studio/backend/routes/datasets.py b/studio/backend/routes/datasets.py
index 1ea696705c..711e9723d5 100644
--- a/studio/backend/routes/datasets.py
+++ b/studio/backend/routes/datasets.py
@@ -99,7 +99,6 @@ def _serialize_preview_value(value):
 
     try:
         from PIL.Image import Image as PILImage
-
         if isinstance(value, PILImage):
             buffer = io.BytesIO()
             value.convert("RGB").save(buffer, format = "JPEG", quality = 85)
@@ -261,9 +260,7 @@ def _build_local_dataset_items() -> list[LocalDatasetItem]:
     return items
 
 
-def _load_local_preview_slice(
-    *, dataset_path: Path, train_split: str, preview_size: int
-):
+def _load_local_preview_slice(*, dataset_path: Path, train_split: str, preview_size: int):
     from datasets import load_dataset
 
     if dataset_path.is_dir():
@@ -298,9 +295,7 @@ def _load_local_preview_slice(
     elif dataset_path.suffix == ".csv":
         dataset = load_dataset("csv", data_files = str(dataset_path), split = train_split)
     elif dataset_path.suffix == ".parquet":
-        dataset = load_dataset(
-            "parquet", data_files = str(dataset_path), split = train_split
-        )
+        dataset = load_dataset("parquet", data_files = str(dataset_path), split = train_split)
     else:
         raise HTTPException(
             status_code = 400, detail = f"Unsupported file format: {dataset_path.suffix}"
@@ -320,8 +315,7 @@ def _sanitize_filename(filename: str) -> str:
 
 @router.post("/upload", response_model = UploadDatasetResponse)
 async def upload_dataset(
-    file: UploadFile,
-    current_subject: str = Depends(get_current_subject),
+    file: UploadFile, current_subject: str = Depends(get_current_subject)
 ) -> UploadDatasetResponse:
     filename = _sanitize_filename(file.filename or "dataset_upload")
     ext = Path(filename).suffix.lower()
@@ -378,9 +372,7 @@ def list_local_datasets(
 
 @router.get("/download-progress")
 async def get_dataset_download_progress(
-    repo_id: str = Query(
-        ..., description = "HuggingFace dataset repo ID, e.g. 'unsloth/LaTeX_OCR'"
-    ),
+    repo_id: str = Query(..., description = "HuggingFace dataset repo ID, e.g. 'unsloth/LaTeX_OCR'"),
     current_subject: str = Depends(get_current_subject),
 ):
     """Return download progress for a HuggingFace dataset repo.
@@ -460,10 +452,7 @@ async def get_dataset_download_progress(
 
 
 @router.post("/check-format", response_model = CheckFormatResponse)
-def check_format(
-    request: CheckFormatRequest,
-    current_subject: str = Depends(get_current_subject),
-):
+def check_format(request: CheckFormatRequest, current_subject: str = Depends(get_current_subject)):
     """
     Check if a dataset requires manual column mapping.
 
@@ -511,25 +500,19 @@ def check_format(
                     repo_type = "dataset",
                     token = request.hf_token or None,
                 )
-                data_files = [
-                    f for f in repo_files if any(f.endswith(ext) for ext in DATA_EXTS)
-                ]
+                data_files = [f for f in repo_files if any(f.endswith(ext) for ext in DATA_EXTS)]
 
                 # Prefer tabular formats over archives (e.g. images.zip → ImageFolder
                 # with synthetic image/label columns that don't match the real schema).
                 tabular_files = [
-                    f
-                    for f in data_files
-                    if any(f.endswith(ext) for ext in _TABULAR_EXTS)
+                    f for f in data_files if any(f.endswith(ext) for ext in _TABULAR_EXTS)
                 ]
                 candidates = tabular_files or data_files
 
                 # When a subset is specified, narrow to files whose name matches
                 # (e.g. subset="testmini" → prefer "testmini.parquet").
                 if request.subset and candidates:
-                    subset_matches = [
-                        f for f in candidates if request.subset in Path(f).stem
-                    ]
+                    subset_matches = [f for f in candidates if request.subset in Path(f).stem]
                     if subset_matches:
                         candidates = subset_matches
 
@@ -601,9 +584,7 @@ def check_format(
                     processed = format_result["dataset"]
                     preview_samples = _serialize_preview_rows(processed)
                 except Exception as e:
-                    logger.warning(
-                        f"Processed preview generation failed (non-fatal): {e}"
-                    )
+                    logger.warning(f"Processed preview generation failed (non-fatal): {e}")
                     preview_samples = _serialize_preview_rows(preview_slice)
         else:
             preview_samples = _serialize_preview_rows(preview_slice)
@@ -614,9 +595,7 @@ def check_format(
         if image_col and image_col in (result.get("columns") or []):
             try:
                 sample_val = preview_slice[0][image_col]
-                if isinstance(sample_val, str) and sample_val.startswith(
-                    ("http://", "https://")
-                ):
+                if isinstance(sample_val, str) and sample_val.startswith(("http://", "https://")):
                     url_warning = (
                         "This dataset contains image URLs instead of embedded images. "
                         "Images will be downloaded during training, which may be slow for large datasets."
@@ -652,8 +631,7 @@ def check_format(
 
 @router.post("/ai-assist-mapping", response_model = AiAssistMappingResponse)
 def ai_assist_mapping(
-    request: AiAssistMappingRequest,
-    current_subject: str = Depends(get_current_subject),
+    request: AiAssistMappingRequest, current_subject: str = Depends(get_current_subject)
 ):
     """
     Run LLM-assisted dataset conversion advisor (user-triggered).
@@ -670,8 +648,7 @@ def ai_assist_mapping(
 
         # Truncate sample values for the LLM prompt
         truncated = [
-            {col: str(s.get(col, ""))[:200] for col in request.columns}
-            for s in request.samples[:5]
+            {col: str(s.get(col, ""))[:200] for col in request.columns} for s in request.samples[:5]
         ]
 
         result = llm_conversion_advisor(
diff --git a/studio/backend/routes/export.py b/studio/backend/routes/export.py
index 2bfca30cee..302d534874 100644
--- a/studio/backend/routes/export.py
+++ b/studio/backend/routes/export.py
@@ -54,8 +54,7 @@ logger = get_logger(__name__)
 
 @router.post("/load-checkpoint", response_model = ExportOperationResponse)
 async def load_checkpoint(
-    request: LoadCheckpointRequest,
-    current_subject: str = Depends(get_current_subject),
+    request: LoadCheckpointRequest, current_subject: str = Depends(get_current_subject)
 ):
     """
     Load a checkpoint into the export backend.
@@ -70,7 +69,6 @@ async def load_checkpoint(
         # before loading the export checkpoint (they'd compete for VRAM).
         try:
             from core.inference import get_inference_backend
-
             inf = get_inference_backend()
             if inf.active_model_name:
                 logger.info(
@@ -85,7 +83,6 @@ async def load_checkpoint(
 
         try:
             from core.training import get_training_backend
-
             trn = get_training_backend()
             if trn.is_training_active():
                 logger.info("Stopping active training to free GPU memory for export")
@@ -96,12 +93,9 @@ async def load_checkpoint(
                     if not trn.is_training_active():
                         break
                     import time
-
                     time.sleep(0.5)
                 else:
-                    logger.warning(
-                        "Training subprocess did not exit within 30s, proceeding anyway"
-                    )
+                    logger.warning("Training subprocess did not exit within 30s, proceeding anyway")
         except Exception as e:
             logger.warning("Could not stop training: %s", e)
 
@@ -132,9 +126,7 @@ async def load_checkpoint(
 
 
 @router.post("/cleanup", response_model = ExportOperationResponse)
-async def cleanup_export_memory(
-    current_subject: str = Depends(get_current_subject),
-):
+async def cleanup_export_memory(current_subject: str = Depends(get_current_subject)):
     """
     Cleanup export-related models from memory (GPU/CPU).
 
@@ -165,9 +157,7 @@ async def cleanup_export_memory(
 
 
 @router.get("/status", response_model = ExportStatusResponse)
-async def get_export_status(
-    current_subject: str = Depends(get_current_subject),
-):
+async def get_export_status(current_subject: str = Depends(get_current_subject)):
     """
     Get current export backend status (loaded checkpoint, model type, PEFT flag).
     """
@@ -203,8 +193,7 @@ def _export_details(output_path: Optional[str]) -> Optional[Dict[str, Any]]:
 
 @router.post("/export/merged", response_model = ExportOperationResponse)
 async def export_merged_model(
-    request: ExportMergedModelRequest,
-    current_subject: str = Depends(get_current_subject),
+    request: ExportMergedModelRequest, current_subject: str = Depends(get_current_subject)
 ):
     """
     Export a merged PEFT model (e.g., 16-bit or 4-bit) and optionally push to Hub.
@@ -243,8 +232,7 @@ async def export_merged_model(
 
 @router.post("/export/base", response_model = ExportOperationResponse)
 async def export_base_model(
-    request: ExportBaseModelRequest,
-    current_subject: str = Depends(get_current_subject),
+    request: ExportBaseModelRequest, current_subject: str = Depends(get_current_subject)
 ):
     """
     Export a non-PEFT base model and optionally push to Hub.
@@ -283,8 +271,7 @@ async def export_base_model(
 
 @router.post("/export/gguf", response_model = ExportOperationResponse)
 async def export_gguf(
-    request: ExportGGUFRequest,
-    current_subject: str = Depends(get_current_subject),
+    request: ExportGGUFRequest, current_subject: str = Depends(get_current_subject)
 ):
     """
     Export the current model to GGUF format and optionally push to Hub.
@@ -322,8 +309,7 @@ async def export_gguf(
 
 @router.post("/export/lora", response_model = ExportOperationResponse)
 async def export_lora_adapter(
-    request: ExportLoRAAdapterRequest,
-    current_subject: str = Depends(get_current_subject),
+    request: ExportLoRAAdapterRequest, current_subject: str = Depends(get_current_subject)
 ):
     """
     Export only the LoRA adapter (if the loaded model is PEFT).
@@ -377,7 +363,11 @@ async def export_lora_adapter(
 # directive, and `Last-Event-ID` is honored on reconnect.
 
 
-def _format_sse(data: str, event: str, event_id: Optional[int] = None) -> str:
+def _format_sse(
+    data: str,
+    event: str,
+    event_id: Optional[int] = None,
+) -> str:
     """Format a single SSE message with id/event/data fields."""
     lines = []
     if event_id is not None:
diff --git a/studio/backend/routes/inference.py b/studio/backend/routes/inference.py
index 5d22b3ff90..70a9aa27d0 100644
--- a/studio/backend/routes/inference.py
+++ b/studio/backend/routes/inference.py
@@ -92,7 +92,9 @@ def _friendly_error(exc: Exception) -> str:
     # subprocess is unreachable", which for Studio always means the
     # llama-server subprocess crashed or is still coming up.
     if isinstance(exc, httpx.RequestError):
-        return "Lost connection to the model server. It may have crashed -- try reloading the model."
+        return (
+            "Lost connection to the model server. It may have crashed -- try reloading the model."
+        )
     msg = str(exc)
     m = _re.search(
         r"request \((\d+) tokens?\) exceeds the available context size \((\d+) tokens?\)",
@@ -105,7 +107,9 @@ def _friendly_error(exc: Exception) -> str:
             f"or shorten the conversation."
         )
     if "Lost connection to llama-server" in msg:
-        return "Lost connection to the model server. It may have crashed -- try reloading the model."
+        return (
+            "Lost connection to the model server. It may have crashed -- try reloading the model."
+        )
     return "An internal error occurred"
 
 
@@ -353,9 +357,7 @@ async def artifact_preview_frame(
         await get_current_subject(creds)
 
     csp = (
-        _ARTIFACT_PREVIEW_FRAME_NETWORK_CSP
-        if allow_network
-        else _ARTIFACT_PREVIEW_FRAME_STRICT_CSP
+        _ARTIFACT_PREVIEW_FRAME_NETWORK_CSP if allow_network else _ARTIFACT_PREVIEW_FRAME_STRICT_CSP
     )
     return Response(
         content = _ARTIFACT_PREVIEW_FRAME_HTML,
@@ -446,9 +448,7 @@ _PENDING_CANCEL_TTL_S = 30.0
 
 
 def _prune_pending(now: float) -> None:
-    for k in [
-        k for k, ts in _PENDING_CANCELS.items() if now - ts > _PENDING_CANCEL_TTL_S
-    ]:
+    for k in [k for k, ts in _PENDING_CANCELS.items() if now - ts > _PENDING_CANCEL_TTL_S]:
         _PENDING_CANCELS.pop(k, None)
 
 
@@ -590,9 +590,7 @@ _TOOL_XML_RE = _re.compile(
 logger = get_logger(__name__)
 
 
-def _validate_native_mmproj_companion(
-    mmproj_path: str | None, gguf_path: str | None
-) -> None:
+def _validate_native_mmproj_companion(mmproj_path: str | None, gguf_path: str | None) -> None:
     if not mmproj_path or not gguf_path:
         return
     import stat as _stat_module
@@ -606,9 +604,7 @@ def _validate_native_mmproj_companion(
             status_code = 400,
             detail = "Native vision companion is no longer accessible.",
         ) from exc
-    if _stat_module.S_ISLNK(mm_lstat.st_mode) or not _stat_module.S_ISREG(
-        mm_lstat.st_mode
-    ):
+    if _stat_module.S_ISLNK(mm_lstat.st_mode) or not _stat_module.S_ISREG(mm_lstat.st_mode):
         raise HTTPException(
             status_code = 400,
             detail = "Native vision companion must be a regular file.",
@@ -636,9 +632,7 @@ def _normalise_settings_str(value: Optional[str]) -> Optional[str]:
     return value
 
 
-def _request_matches_loaded_settings(
-    request: LoadRequest, llama_backend: LlamaCppBackend
-) -> bool:
+def _request_matches_loaded_settings(request: LoadRequest, llama_backend: LlamaCppBackend) -> bool:
     """True iff every runtime setting on the request matches the loaded
     server. Caller has already checked model+variant+is_loaded. See #5401."""
     # Compare requested n_ctx (not effective) so VRAM-cap doesn't mask
@@ -664,9 +658,7 @@ def _request_matches_loaded_settings(
     if backend_mode in ("mtp", "mtp+ngram") and request.spec_draft_n_max is not None:
         if int(request.spec_draft_n_max) != (llama_backend.spec_draft_n_max or 0):
             return False
-    if (request.chat_template_override or None) != (
-        llama_backend.chat_template_override or None
-    ):
+    if (request.chat_template_override or None) != (llama_backend.chat_template_override or None):
         return False
     # llama_extra_args=None means "inherit"; only an explicit list that
     # differs forces a reload. On the inherit path, refuse to match if
@@ -683,9 +675,7 @@ def _request_matches_loaded_settings(
 
 
 def _resolve_model_identifier_for_request(
-    request: LoadRequest | ValidateModelRequest,
-    *,
-    operation: str,
+    request: LoadRequest | ValidateModelRequest, *, operation: str
 ) -> tuple[str, str, bool]:
     if not request.native_path_lease:
         return request.model_path, request.model_path, False
@@ -705,9 +695,7 @@ def _resolve_model_identifier_for_request(
             status_code = 400,
             detail = redact_native_paths(str(exc)),
         ) from exc
-    display_label = (
-        grant.display_label or Path(request.model_path).name or "Native model"
-    )
+    display_label = grant.display_label or Path(request.model_path).name or "Native model"
     return str(grant.canonical_path), display_label, True
 
 
@@ -788,9 +776,7 @@ async def load_model(
                 inference_config = load_inference_config(llama_backend.model_identifier)
 
                 _gguf_audio = (
-                    llama_backend._audio_type
-                    if hasattr(llama_backend, "_audio_type")
-                    else None
+                    llama_backend._audio_type if hasattr(llama_backend, "_audio_type") else None
                 )
                 _gguf_is_audio = getattr(llama_backend, "_is_audio", False)
                 return LoadResponse(
@@ -828,9 +814,7 @@ async def load_model(
                 backend.active_model_name
                 and backend.active_model_name.lower() == model_identifier.lower()
             ):
-                logger.info(
-                    f"Model already loaded (Unsloth): {model_log_label}, skipping reload"
-                )
+                logger.info(f"Model already loaded (Unsloth): {model_log_label}, skipping reload")
                 inference_config = load_inference_config(backend.active_model_name)
                 _model_info = backend.models.get(backend.active_model_name, {})
                 _chat_template = None
@@ -847,9 +831,7 @@ async def load_model(
                 _sf_reasoning_style = _sf_flags["reasoning_style"]
                 return LoadResponse(
                     status = "already_loaded",
-                    model = model_log_label
-                    if native_grant_backed
-                    else backend.active_model_name,
+                    model = model_log_label if native_grant_backed else backend.active_model_name,
                     display_name = model_log_label
                     if native_grant_backed
                     else backend.active_model_name,
@@ -932,8 +914,7 @@ async def load_model(
                 )
                 if not same_source:
                     logger.info(
-                        "Not inheriting llama_extra_args: stored args came "
-                        "from %s, loading %s",
+                        "Not inheriting llama_extra_args: stored args came from %s, loading %s",
                         source,
                         (model_identifier, resolved_variant),
                     )
@@ -951,8 +932,7 @@ async def load_model(
                         strip_context = "max_seq_length" in fields_set,
                         strip_cache = "cache_type_kv" in fields_set,
                         strip_spec = (
-                            "speculative_type" in fields_set
-                            or "spec_draft_n_max" in fields_set
+                            "speculative_type" in fields_set or "spec_draft_n_max" in fields_set
                         ),
                         strip_template = "chat_template_override" in fields_set,
                     )
@@ -1001,9 +981,7 @@ async def load_model(
             else:
                 # Local mode: llama-server loads via -m 
                 if native_grant_backed and config.gguf_mmproj_file:
-                    _validate_native_mmproj_companion(
-                        config.gguf_mmproj_file, config.gguf_file
-                    )
+                    _validate_native_mmproj_companion(config.gguf_mmproj_file, config.gguf_file)
                 success = await asyncio.to_thread(
                     llama_backend.load_model,
                     gguf_path = config.gguf_file,
@@ -1036,9 +1014,7 @@ async def load_model(
             # Audio detection moved into load_model under _serial_load_lock (#5642).
             _gguf_audio = llama_backend._audio_type
             _gguf_is_audio = llama_backend._is_audio
-            llama_backend._native_display_label = (
-                model_log_label if native_grant_backed else None
-            )
+            llama_backend._native_display_label = model_log_label if native_grant_backed else None
             llama_backend._native_grant_backed = bool(native_grant_backed)
             if _gguf_is_audio:
                 logger.info(f"GGUF model detected as audio: audio_type={_gguf_audio}")
@@ -1048,9 +1024,7 @@ async def load_model(
             return LoadResponse(
                 status = "loaded",
                 model = model_log_label if native_grant_backed else config.identifier,
-                display_name = model_log_label
-                if native_grant_backed
-                else config.display_name,
+                display_name = model_log_label if native_grant_backed else config.display_name,
                 is_vision = llama_backend.is_vision,
                 is_lora = False,
                 is_gguf = True,
@@ -1058,9 +1032,7 @@ async def load_model(
                 audio_type = _gguf_audio,
                 has_audio_input = llama_backend._has_audio_input,
                 inference = inference_config,
-                requires_trust_remote_code = bool(
-                    inference_config.get("trust_remote_code", False)
-                ),
+                requires_trust_remote_code = bool(inference_config.get("trust_remote_code", False)),
                 context_length = llama_backend.context_length,
                 max_context_length = llama_backend.max_context_length,
                 native_context_length = llama_backend.native_context_length,
@@ -1087,12 +1059,9 @@ async def load_model(
         # Shut down any export subprocess to free VRAM
         try:
             from core.export import get_export_backend
-
             exp_backend = get_export_backend()
             if exp_backend.current_checkpoint:
-                logger.info(
-                    "Shutting down export subprocess to free GPU memory for inference"
-                )
+                logger.info("Shutting down export subprocess to free GPU memory for inference")
                 exp_backend._shutdown_subprocess()
                 exp_backend.current_checkpoint = None
                 exp_backend.is_vision = False
@@ -1162,9 +1131,7 @@ async def load_model(
             # Check if YAML says this model needs trust_remote_code
             if not request.trust_remote_code:
                 model_defaults = load_model_defaults(config.identifier)
-                yaml_trust = model_defaults.get("inference", {}).get(
-                    "trust_remote_code", False
-                )
+                yaml_trust = model_defaults.get("inference", {}).get("trust_remote_code", False)
                 if yaml_trust:
                     raise HTTPException(
                         status_code = 400,
@@ -1200,9 +1167,7 @@ async def load_model(
         return LoadResponse(
             status = "loaded",
             model = model_log_label if native_grant_backed else config.identifier,
-            display_name = model_log_label
-            if native_grant_backed
-            else config.display_name,
+            display_name = model_log_label if native_grant_backed else config.display_name,
             is_vision = config.is_vision,
             is_lora = config.is_lora,
             is_gguf = False,
@@ -1210,9 +1175,7 @@ async def load_model(
             audio_type = config.audio_type,
             has_audio_input = config.has_audio_input,
             inference = inference_config,
-            requires_trust_remote_code = bool(
-                inference_config.get("trust_remote_code", False)
-            ),
+            requires_trust_remote_code = bool(inference_config.get("trust_remote_code", False)),
             supports_reasoning = _sf_flags["supports_reasoning"],
             reasoning_style = _sf_flags["reasoning_style"],
             reasoning_always_on = _sf_flags["reasoning_always_on"],
@@ -1266,8 +1229,7 @@ async def load_model(
 
 @router.post("/validate", response_model = ValidateModelResponse)
 async def validate_model(
-    request: ValidateModelRequest,
-    current_subject: str = Depends(get_current_subject),
+    request: ValidateModelRequest, current_subject: str = Depends(get_current_subject)
 ):
     """
     Lightweight validation endpoint for model identifiers.
@@ -1342,10 +1304,7 @@ async def validate_model(
 
 
 @router.post("/unload", response_model = UnloadResponse)
-async def unload_model(
-    request: UnloadRequest,
-    current_subject: str = Depends(get_current_subject),
-):
+async def unload_model(request: UnloadRequest, current_subject: str = Depends(get_current_subject)):
     """
     Unload a model from memory.
     Routes to the correct backend (llama-server for GGUF, Unsloth otherwise).
@@ -1355,9 +1314,7 @@ async def unload_model(
         llama_backend = get_llama_cpp_backend()
         if llama_backend.is_active and (
             llama_backend.model_identifier == request.model_path
-            or is_registered_native_path_label(
-                llama_backend.model_identifier, request.model_path
-            )
+            or is_registered_native_path_label(llama_backend.model_identifier, request.model_path)
             or not llama_backend.is_loaded
         ):
             llama_backend.unload_model()
@@ -1376,10 +1333,7 @@ async def unload_model(
 
 
 @studio_router.post("/cancel")
-async def cancel_inference(
-    request: Request,
-    current_subject: str = Depends(get_current_subject),
-):
+async def cancel_inference(request: Request, current_subject: str = Depends(get_current_subject)):
     """Cancel in-flight inference requests.
 
     Body (JSON, at least one key required):
@@ -1419,8 +1373,7 @@ async def cancel_inference(
 
 @router.post("/generate/stream")
 async def generate_stream(
-    request: GenerateRequest,
-    current_subject: str = Depends(get_current_subject),
+    request: GenerateRequest, current_subject: str = Depends(get_current_subject)
 ):
     """
     Generate a chat response with Server-Sent Events (SSE) streaming.
@@ -1496,9 +1449,7 @@ async def generate_stream(
 
 
 @router.get("/status", response_model = InferenceStatusResponse)
-async def get_status(
-    current_subject: str = Depends(get_current_subject),
-):
+async def get_status(current_subject: str = Depends(get_current_subject)):
     """
     Get current inference backend status.
     Reports whichever backend (Unsloth or llama-server) is currently active.
@@ -1516,7 +1467,6 @@ async def get_status(
             _supports_mtp = True  # fail open
         try:
             from utils.llama_cpp_freshness import check_prebuilt_freshness
-
             _freshness = check_prebuilt_freshness(_bin)
         except Exception:
             _freshness = {}
@@ -1590,17 +1540,13 @@ async def get_status(
             has_audio_input = model_info.get("has_audio_input", False)
         chat_template_info = model_info.get("chat_template_info", {})
         chat_template = (
-            chat_template_info.get("template")
-            if isinstance(chat_template_info, dict)
-            else None
+            chat_template_info.get("template") if isinstance(chat_template_info, dict) else None
         )
 
         # Non-GGUF: classify from the loaded template.
         _sf_flags = _detect_safetensors_features(backend, chat_template)
         inference_config = (
-            load_inference_config(backend.active_model_name)
-            if backend.active_model_name
-            else None
+            load_inference_config(backend.active_model_name) if backend.active_model_name else None
         )
 
         return InferenceStatusResponse(
@@ -1635,9 +1581,7 @@ async def get_status(
 
 
 @router.get("/load-progress", response_model = LoadProgressResponse)
-async def get_load_progress(
-    current_subject: str = Depends(get_current_subject),
-):
+async def get_load_progress(current_subject: str = Depends(get_current_subject)):
     """
     Return the active GGUF load's mmap/upload progress.
 
@@ -1684,9 +1628,7 @@ async def generate_audio(
     _, chat_messages, _ = _extract_content_parts(payload.messages)
     if not chat_messages:
         raise HTTPException(status_code = 400, detail = "No messages provided.")
-    last_user_msg = next(
-        (m for m in reversed(chat_messages) if m["role"] == "user"), None
-    )
+    last_user_msg = next((m for m in reversed(chat_messages) if m["role"] == "user"), None)
     if not last_user_msg:
         raise HTTPException(status_code = 400, detail = "No user message found.")
     text = last_user_msg["content"]
@@ -1711,9 +1653,7 @@ async def generate_audio(
             raise HTTPException(status_code = 400, detail = "No model loaded.")
         model_info = backend.models.get(backend.active_model_name, {})
         if not model_info.get("is_audio"):
-            raise HTTPException(
-                status_code = 400, detail = "Active model is not an audio model."
-            )
+            raise HTTPException(status_code = 400, detail = "Active model is not an audio model.")
         model_name = backend.active_model_name
         gen = lambda: backend.generate_audio_response(
             text = text,
@@ -1727,9 +1667,7 @@ async def generate_audio(
         )
 
     try:
-        wav_bytes, sample_rate = await asyncio.get_event_loop().run_in_executor(
-            None, gen
-        )
+        wav_bytes, sample_rate = await asyncio.get_event_loop().run_in_executor(None, gen)
     except Exception as e:
         logger.error(f"Audio generation error: {e}", exc_info = True)
         raise HTTPException(status_code = 500, detail = safe_error_detail(e))
@@ -1795,9 +1733,7 @@ def _decode_audio_base64(b64: str) -> np.ndarray:
     return waveform.squeeze(0).numpy()
 
 
-def _extract_content_parts(
-    messages: list,
-) -> tuple[str, list[dict], "Optional[str]"]:
+def _extract_content_parts(messages: list) -> tuple[str, list[dict], "Optional[str]"]:
     """
     Parse OpenAI-format messages into components the inference backend expects.
 
@@ -1820,9 +1756,7 @@ def _extract_content_parts(
                 system_prompt = msg.content
             elif isinstance(msg.content, list):
                 # Unlikely but handle: join text parts
-                system_prompt = "\n".join(
-                    p.text for p in msg.content if p.type == "text"
-                )
+                system_prompt = "\n".join(p.text for p in msg.content if p.type == "text")
             continue
 
         # ── User / assistant messages ─────────────────────────
@@ -1841,9 +1775,7 @@ def _extract_content_parts(
                         # data:image/png;base64, → extract 
                         first_image_b64 = url.split(",", 1)[1] if "," in url else None
                     else:
-                        logger.warning(
-                            f"Remote image URLs not yet supported: {url[:80]}..."
-                        )
+                        logger.warning(f"Remote image URLs not yet supported: {url[:80]}...")
             combined_text = "\n".join(text_parts) if text_parts else ""
             chat_messages.append({"role": msg.role, "content": combined_text})
 
@@ -1906,7 +1838,6 @@ def _build_external_messages(
     if provider_type == "gemini" and base_url:
         try:
             from urllib.parse import urlparse as _urlparse
-
             _host = (_urlparse(base_url).hostname or "").lower()
             _native_gemini = _host == "generativelanguage.googleapis.com"
         except Exception:
@@ -2015,11 +1946,7 @@ def _build_external_messages(
             # tool_calls (some providers reject empty assistant turns).
             # Preserve assistant turns whose only payload is tool_calls
             # so multi-turn function-call loops round-trip.
-            if (
-                msg.role == "assistant"
-                and not msg.content.strip()
-                and not msg.tool_calls
-            ):
+            if msg.role == "assistant" and not msg.content.strip() and not msg.tool_calls:
                 continue
             out: dict[str, Any] = {"role": msg.role, "content": msg.content}
             if msg.role == "assistant" and msg.tool_calls:
@@ -2073,9 +2000,7 @@ def _build_external_messages(
                                 "image_url": {"url": part.image_url.url},
                             }
                         )
-                    elif (
-                        part.type == "reasoning" and openai and msg.role == "assistant"
-                    ):
+                    elif part.type == "reasoning" and openai and msg.role == "assistant":
                         reasoning: dict[str, Any] = {
                             "type": "reasoning",
                             "id": part.id,
@@ -2085,9 +2010,7 @@ def _build_external_messages(
                             reasoning["status"] = part.status
                         parts.append(reasoning)
                     elif (
-                        part.type == "image_generation_call"
-                        and openai
-                        and msg.role == "assistant"
+                        part.type == "image_generation_call" and openai and msg.role == "assistant"
                     ):
                         # ExternalProviderClient maps this onto a top-level
                         # Responses input item after the current user prompt,
@@ -2158,11 +2081,7 @@ def _build_external_messages(
                         if p.status:
                             reasoning["status"] = p.status
                         preserved.append(reasoning)
-                    elif (
-                        p.type == "image_generation_call"
-                        and openai
-                        and msg.role == "assistant"
-                    ):
+                    elif p.type == "image_generation_call" and openai and msg.role == "assistant":
                         image_ref = {"type": "image_generation_call", "id": p.id}
                         if getattr(p, "response_id", None):
                             image_ref["response_id"] = p.response_id
@@ -2187,9 +2106,7 @@ def _build_external_messages(
                         _entry_content = entry.get("content")
                         _has_text = (
                             isinstance(_entry_content, str) and _entry_content.strip()
-                        ) or (
-                            isinstance(_entry_content, list) and len(_entry_content) > 0
-                        )
+                        ) or (isinstance(_entry_content, list) and len(_entry_content) > 0)
                         if not _has_text:
                             continue
                 if msg.role == "tool":
@@ -2204,8 +2121,7 @@ def _build_external_messages(
 
 
 async def _proxy_to_external_provider(
-    payload: ChatCompletionRequest,
-    request: Request,
+    payload: ChatCompletionRequest, request: Request
 ) -> StreamingResponse:
     """
     Proxy a chat completion request to an external LLM provider.
@@ -2343,9 +2259,7 @@ async def _proxy_to_external_provider(
 # ── OpenAI shell-tool container management ───────────────────────
 
 
-def _resolve_openai_cloud_client(
-    body: OpenAIContainerRequest,
-) -> ExternalProviderClient:
+def _resolve_openai_cloud_client(body: OpenAIContainerRequest) -> ExternalProviderClient:
     """
     Decrypt the API key + validate the base URL points at OpenAI cloud,
     then build an ExternalProviderClient for the three container CRUD
@@ -2388,9 +2302,7 @@ def _summarize_container(raw: dict) -> OpenAIContainerSummary:
     return OpenAIContainerSummary(
         id = str(raw.get("id") or ""),
         name = raw.get("name"),
-        created_at = raw.get("created_at")
-        if isinstance(raw.get("created_at"), int)
-        else None,
+        created_at = raw.get("created_at") if isinstance(raw.get("created_at"), int) else None,
         last_active_at = raw.get("last_active_at")
         if isinstance(raw.get("last_active_at"), int)
         else None,
@@ -2404,8 +2316,7 @@ def _summarize_container(raw: dict) -> OpenAIContainerSummary:
     response_model = ListOpenAIContainersResponse,
 )
 async def list_openai_containers(
-    body: OpenAIContainerRequest,
-    current_subject: str = Depends(get_current_subject),
+    body: OpenAIContainerRequest, current_subject: str = Depends(get_current_subject)
 ) -> ListOpenAIContainersResponse:
     """List the user's OpenAI shell-tool containers."""
     client = _resolve_openai_cloud_client(body)
@@ -2445,8 +2356,7 @@ async def list_openai_containers(
     response_model = OpenAIContainerSummary,
 )
 async def create_openai_container(
-    body: CreateOpenAIContainerBody,
-    current_subject: str = Depends(get_current_subject),
+    body: CreateOpenAIContainerBody, current_subject: str = Depends(get_current_subject)
 ) -> OpenAIContainerSummary:
     """Create a named container with the user-chosen idle TTL."""
     client = _resolve_openai_cloud_client(body)
@@ -2482,8 +2392,7 @@ async def create_openai_container(
 
 @router.post("/external/openai/containers/delete", status_code = 204)
 async def delete_openai_container(
-    body: DeleteOpenAIContainerBody,
-    current_subject: str = Depends(get_current_subject),
+    body: DeleteOpenAIContainerBody, current_subject: str = Depends(get_current_subject)
 ) -> None:
     """Delete a named container by id."""
     logger.info(
@@ -2671,9 +2580,7 @@ async def openai_chat_completions(
                             id = completion_id,
                             created = created,
                             model = model_name,
-                            choices = [
-                                ChunkChoice(delta = ChoiceDelta(), finish_reason = "stop")
-                            ],
+                            choices = [ChunkChoice(delta = ChoiceDelta(), finish_reason = "stop")],
                         )
                         yield f"data: {final_chunk.model_dump_json(exclude_none = True)}\n\n"
                         yield "data: [DONE]\n\n"
@@ -2681,9 +2588,7 @@ async def openai_chat_completions(
                         cancel_event.set()
                         raise
                     except Exception as e:
-                        logger.error(
-                            f"Error during audio input streaming: {e}", exc_info = True
-                        )
+                        logger.error(f"Error during audio input streaming: {e}", exc_info = True)
                         yield f"data: {json.dumps({'error': {'message': _friendly_error(e), 'type': 'server_error'}})}\n\n"
                     finally:
                         _tracker.__exit__(None, None, None)
@@ -2783,9 +2688,7 @@ async def openai_chat_completions(
         )
 
     # ── Parse messages (handles multimodal content parts) ─────
-    system_prompt, chat_messages, extracted_image_b64 = _extract_content_parts(
-        payload.messages
-    )
+    system_prompt, chat_messages, extracted_image_b64 = _extract_content_parts(payload.messages)
 
     if not chat_messages:
         raise HTTPException(
@@ -2835,9 +2738,7 @@ async def openai_chat_completions(
                 tools_to_use = []
             elif payload.enabled_tools is not None:
                 tools_to_use = [
-                    t
-                    for t in ALL_TOOLS
-                    if t["function"]["name"] in payload.enabled_tools
+                    t for t in ALL_TOOLS if t["function"]["name"] in payload.enabled_tools
                 ]
             else:
                 tools_to_use = ALL_TOOLS
@@ -2901,8 +2802,7 @@ async def openai_chat_completions(
                 _nudge = (
                     _date_line + " "
                     "You have access to tools. When appropriate, prefer using "
-                    "tools rather than answering from memory. "
-                    + " ".join(_tool_tip_parts)
+                    "tools rather than answering from memory. " + " ".join(_tool_tip_parts)
                 )
             else:
                 _nudge = ""
@@ -2914,15 +2814,11 @@ async def openai_chat_completions(
                     system_prompt = system_prompt.rstrip() + "\n\n" + _nudge
                 else:
                     system_prompt = _nudge
-                gguf_messages = _set_or_prepend_system_message(
-                    gguf_messages, system_prompt
-                )
+                gguf_messages = _set_or_prepend_system_message(gguf_messages, system_prompt)
 
             # ── Strip stale tool-call XML from conversation history ─
             for _msg in gguf_messages:
-                if _msg.get("role") == "assistant" and isinstance(
-                    _msg.get("content"), str
-                ):
+                if _msg.get("role") == "assistant" and isinstance(_msg.get("content"), str):
                     _msg["content"] = _TOOL_XML_RE.sub("", _msg["content"]).strip()
 
             def gguf_generate_with_tools():
@@ -3058,9 +2954,7 @@ async def openai_chat_completions(
                     if _stream_usage or _stream_timings:
                         usage_obj = CompletionUsage(
                             prompt_tokens = (_stream_usage or {}).get("prompt_tokens", 0),
-                            completion_tokens = (_stream_usage or {}).get(
-                                "completion_tokens", 0
-                            ),
+                            completion_tokens = (_stream_usage or {}).get("completion_tokens", 0),
                             total_tokens = (_stream_usage or {}).get("total_tokens", 0),
                         )
                         usage_chunk = ChatCompletionChunk(
@@ -3167,11 +3061,7 @@ async def openai_chat_completions(
                             else:
                                 logger.warning(
                                     "gguf_stream_chunks: unexpected dict event: %s",
-                                    {
-                                        k: v
-                                        for k, v in cumulative.items()
-                                        if k != "timings"
-                                    },
+                                    {k: v for k, v in cumulative.items() if k != "timings"},
                                 )
                             continue
                         new_text = cumulative[len(prev_text) :]
@@ -3208,9 +3098,7 @@ async def openai_chat_completions(
                     if _stream_usage or _stream_timings:
                         usage_obj = CompletionUsage(
                             prompt_tokens = (_stream_usage or {}).get("prompt_tokens", 0),
-                            completion_tokens = (_stream_usage or {}).get(
-                                "completion_tokens", 0
-                            ),
+                            completion_tokens = (_stream_usage or {}).get("completion_tokens", 0),
                             total_tokens = (_stream_usage or {}).get("total_tokens", 0),
                         )
                         usage_chunk = ChatCompletionChunk(
@@ -3270,12 +3158,8 @@ async def openai_chat_completions(
                         )
                     ],
                     usage = CompletionUsage(
-                        prompt_tokens = (completion_usage or {}).get("prompt_tokens")
-                        or 0,
-                        completion_tokens = (completion_usage or {}).get(
-                            "completion_tokens"
-                        )
-                        or 0,
+                        prompt_tokens = (completion_usage or {}).get("prompt_tokens") or 0,
+                        completion_tokens = (completion_usage or {}).get("completion_tokens") or 0,
                         total_tokens = (completion_usage or {}).get("total_tokens") or 0,
                     ),
                 )
@@ -3335,16 +3219,12 @@ async def openai_chat_completions(
     # XML -- gpt-oss tools still work via the GGUF path).
     _sf_is_gptoss = False
     try:
-        _sf_is_gptoss = bool(
-            hasattr(backend, "_is_gpt_oss_model") and backend._is_gpt_oss_model()
-        )
+        _sf_is_gptoss = bool(hasattr(backend, "_is_gpt_oss_model") and backend._is_gpt_oss_model())
     except Exception:
         _sf_is_gptoss = False
 
     _sf_tool_budget = (
-        payload.max_tool_calls_per_message
-        if payload.max_tool_calls_per_message is not None
-        else 25
+        payload.max_tool_calls_per_message if payload.max_tool_calls_per_message is not None else 25
     )
 
     # Match the GGUF path: mcp_enabled also opens the tool loop on its own
@@ -3426,8 +3306,7 @@ async def openai_chat_completions(
             _sf_nudge = (
                 _sf_date_line + " "
                 "You have access to tools. When appropriate, prefer using "
-                "tools rather than answering from memory. "
-                + " ".join(_sf_tool_tip_parts)
+                "tools rather than answering from memory. " + " ".join(_sf_tool_tip_parts)
             )
         else:
             _sf_nudge = ""
@@ -3940,9 +3819,7 @@ async def serve_sandbox_file(
 
 
 @router.get("/models")
-async def openai_list_models(
-    current_subject: str = Depends(get_current_subject),
-):
+async def openai_list_models(current_subject: str = Depends(get_current_subject)):
     """
     OpenAI-compatible model listing endpoint.
 
@@ -3982,10 +3859,7 @@ async def openai_list_models(
 
 
 @router.post("/completions")
-async def openai_completions(
-    request: Request,
-    current_subject: str = Depends(get_current_subject),
-):
+async def openai_completions(request: Request, current_subject: str = Depends(get_current_subject)):
     """
     OpenAI-compatible text completions endpoint (non-chat).
 
@@ -4059,10 +3933,7 @@ async def openai_completions(
 
 
 @router.post("/embeddings")
-async def openai_embeddings(
-    request: Request,
-    current_subject: str = Depends(get_current_subject),
-):
+async def openai_embeddings(request: Request, current_subject: str = Depends(get_current_subject)):
     """
     OpenAI-compatible embeddings endpoint.
 
@@ -4095,9 +3966,7 @@ async def openai_embeddings(
 # =====================================================================
 
 
-def _translate_responses_tools_to_chat(
-    tools: Optional[list[dict]],
-) -> Optional[list[dict]]:
+def _translate_responses_tools_to_chat(tools: Optional[list[dict]]) -> Optional[list[dict]]:
     """Translate Responses-shape function tools to the Chat Completions nested shape.
 
     Responses uses a flat shape per tool entry::
@@ -4371,9 +4240,7 @@ def _chat_tool_calls_to_responses_output(tool_calls: list[dict]) -> list[dict]:
 
 
 async def _responses_non_streaming(
-    payload: ResponsesRequest,
-    messages: list[ChatMessage],
-    request: Request,
+    payload: ResponsesRequest, messages: list[ChatMessage], request: Request
 ) -> JSONResponse:
     """Handle a non-streaming Responses API call."""
     chat_req = _build_chat_request(payload, messages, stream = False)
@@ -4439,9 +4306,7 @@ async def _responses_non_streaming(
 
 
 async def _responses_stream(
-    payload: ResponsesRequest,
-    messages: list[ChatMessage],
-    request: Request,
+    payload: ResponsesRequest, messages: list[ChatMessage], request: Request
 ):
     """Handle a streaming Responses API call, emitting named SSE events.
 
@@ -4491,8 +4356,7 @@ async def _responses_stream(
 
     # Direct pass-through bypasses the openai_chat_completions image gate.
     if not llama_backend.is_vision and any(
-        isinstance(m.content, list)
-        and any(isinstance(p, ImageContentPart) for p in m.content)
+        isinstance(m.content, list) and any(isinstance(p, ImageContentPart) for p in m.content)
         for m in messages
     ):
         raise HTTPException(
@@ -4500,9 +4364,7 @@ async def _responses_stream(
             detail = "Image provided but current GGUF model does not support vision.",
         )
 
-    body = _build_openai_passthrough_body(
-        chat_req, backend_ctx = llama_backend.context_length
-    )
+    body = _build_openai_passthrough_body(chat_req, backend_ctx = llama_backend.context_length)
     target_url = f"{llama_backend.base_url}/v1/chat/completions"
 
     async def event_generator():
@@ -4861,9 +4723,7 @@ def _anthropic_requested_studio_tools(tools: Optional[list]) -> set[str]:
 
 
 def _select_anthropic_server_tools(
-    all_tools: list[dict],
-    requested_studio_tools: set[str],
-    enabled_tools: Optional[list[str]],
+    all_tools: list[dict], requested_studio_tools: set[str], enabled_tools: Optional[list[str]]
 ) -> list[dict]:
     """Select Studio tools requested through Anthropic tools and extensions."""
     if not requested_studio_tools and enabled_tools is None:
@@ -4876,9 +4736,7 @@ def _select_anthropic_server_tools(
     return [tool for tool in all_tools if tool["function"]["name"] in selected_names]
 
 
-def _normalize_anthropic_openai_images(
-    openai_messages: list[dict], is_vision: bool
-) -> bool:
+def _normalize_anthropic_openai_images(openai_messages: list[dict], is_vision: bool) -> bool:
     """Enforce the vision guard on translated Anthropic messages and
     normalize any ``image_url`` parts with base64 data URLs to PNG.
 
@@ -4991,9 +4849,7 @@ async def anthropic_messages(
 
     # Enforce vision guard + re-encode embedded images to PNG so the
     # Anthropic endpoint matches the behavior of /v1/chat/completions.
-    _has_image = _normalize_anthropic_openai_images(
-        openai_messages, llama_backend.is_vision
-    )
+    _has_image = _normalize_anthropic_openai_images(openai_messages, llama_backend.is_vision)
 
     temperature = payload.temperature if payload.temperature is not None else 0.6
     top_p = payload.top_p if payload.top_p is not None else 0.95
@@ -5002,9 +4858,7 @@ async def anthropic_messages(
     repetition_penalty = (
         payload.repetition_penalty if payload.repetition_penalty is not None else 1.0
     )
-    presence_penalty = (
-        payload.presence_penalty if payload.presence_penalty is not None else 0.0
-    )
+    presence_penalty = payload.presence_penalty if payload.presence_penalty is not None else 0.0
     stop = payload.stop_sequences or None
 
     # Translate Anthropic tool_choice to OpenAI format for forwarding to
@@ -5083,9 +4937,7 @@ async def anthropic_messages(
         and not _has_image
     )
     client_tools = (
-        not server_tools
-        and len(openai_client_tools) > 0
-        and llama_backend.supports_tools
+        not server_tools and len(openai_client_tools) > 0 and llama_backend.supports_tools
     )
 
     # ── Client-side pass-through path ─────────────────────────
@@ -5265,13 +5117,7 @@ async def anthropic_messages(
     )
 
 
-async def _anthropic_tool_stream(
-    request,
-    cancel_event,
-    run_gen,
-    message_id,
-    model_name,
-):
+async def _anthropic_tool_stream(request, cancel_event, run_gen, message_id, model_name):
     """Streaming response for the tool-calling path."""
     _sentinel = object()
 
@@ -5312,13 +5158,7 @@ async def _anthropic_tool_stream(
     )
 
 
-async def _anthropic_plain_stream(
-    request,
-    cancel_event,
-    run_gen,
-    message_id,
-    model_name,
-):
+async def _anthropic_plain_stream(request, cancel_event, run_gen, message_id, model_name):
     """Streaming response for the no-tool path."""
     _sentinel = object()
 
@@ -5388,18 +5228,14 @@ async def _anthropic_tool_non_streaming(run_gen, message_id, model_name):
             new = clean[len(prev_text) :]
             prev_text = clean
             if new:
-                if content_blocks and isinstance(
-                    content_blocks[-1], AnthropicResponseTextBlock
-                ):
+                if content_blocks and isinstance(content_blocks[-1], AnthropicResponseTextBlock):
                     content_blocks[-1].text += new
                 else:
                     content_blocks.append(AnthropicResponseTextBlock(text = new))
         elif etype == "tool_start":
             tool_call_id = event["tool_call_id"]
             arguments = event.get("arguments", {})
-            existing_tool_block = (
-                tool_blocks_by_id.get(tool_call_id) if tool_call_id else None
-            )
+            existing_tool_block = tool_blocks_by_id.get(tool_call_id) if tool_call_id else None
             if existing_tool_block is not None:
                 if arguments or not existing_tool_block.input:
                     existing_tool_block.input = arguments
@@ -5500,9 +5336,7 @@ def _build_passthrough_payload(
     if stream:
         body["stream_options"] = {"include_usage": True}
     body["max_tokens"] = (
-        max_tokens
-        if max_tokens is not None
-        else (backend_ctx or _DEFAULT_MAX_TOKENS_FLOOR)
+        max_tokens if max_tokens is not None else (backend_ctx or _DEFAULT_MAX_TOKENS_FLOOR)
     )
     body["t_max_predict_ms"] = _DEFAULT_T_MAX_PREDICT_MS
     if stop:
@@ -5619,9 +5453,7 @@ async def _anthropic_passthrough_stream(
             # blocks during llama-server prefill, so the in-loop cancel
             # check is unreachable until the first SSE chunk arrives.
             # The watcher closes `resp` on cancel, raising in aiter_lines.
-            cancel_watcher = asyncio.create_task(
-                _await_cancel_then_close(cancel_event, resp)
-            )
+            cancel_watcher = asyncio.create_task(_await_cancel_then_close(cancel_event, resp))
             lines_iter = resp.aiter_lines()
             async for raw_line in lines_iter:
                 if cancel_event.is_set():
@@ -5855,9 +5687,7 @@ def _strip_provider_synthetic_tool_history(messages: list[dict]) -> list[dict]:
                     if args_obj.get("_server_tool") is True:
                         is_synthetic = True
                     google = args_obj.get("google")
-                    if isinstance(google, dict) and isinstance(
-                        google.get("native_part"), dict
-                    ):
+                    if isinstance(google, dict) and isinstance(google.get("native_part"), dict):
                         is_synthetic = True
                 if is_synthetic:
                     tc_id = tc.get("id")
@@ -5912,9 +5742,7 @@ def _openai_messages_for_passthrough(payload) -> list[dict]:
     transparently.
     """
     messages = _strip_provider_synthetic_tool_history(
-        _drop_empty_assistant_sentinels(
-            [m.model_dump(exclude_none = True) for m in payload.messages]
-        )
+        _drop_empty_assistant_sentinels([m.model_dump(exclude_none = True) for m in payload.messages])
     )
 
     if not payload.image_base64:
@@ -5964,9 +5792,7 @@ def _openai_messages_for_gguf_chat(payload, is_vision: bool) -> tuple[list[dict]
     image attached to its original turn.
     """
     messages = _strip_provider_synthetic_tool_history(
-        _drop_empty_assistant_sentinels(
-            [m.model_dump(exclude_none = True) for m in payload.messages]
-        )
+        _drop_empty_assistant_sentinels([m.model_dump(exclude_none = True) for m in payload.messages])
     )
     has_message_image = any(
         isinstance(msg.get("content"), list)
@@ -6048,12 +5874,7 @@ def _build_openai_passthrough_body(payload, backend_ctx = None) -> dict:
 
 
 async def _openai_passthrough_stream(
-    request,
-    cancel_event,
-    llama_backend,
-    payload,
-    model_name,
-    completion_id,
+    request, cancel_event, llama_backend, payload, model_name, completion_id
 ):
     """Streaming client-side pass-through for /v1/chat/completions.
 
@@ -6064,9 +5885,7 @@ async def _openai_passthrough_stream(
     observes a standard OpenAI response.
     """
     target_url = f"{llama_backend.base_url}/v1/chat/completions"
-    body = _build_openai_passthrough_body(
-        payload, backend_ctx = llama_backend.context_length
-    )
+    body = _build_openai_passthrough_body(payload, backend_ctx = llama_backend.context_length)
 
     _cancel_keys = (payload.cancel_id, payload.session_id, completion_id)
     _tracker = _TrackedCancel(cancel_event, *_cancel_keys)
@@ -6139,9 +5958,7 @@ async def _openai_passthrough_stream(
             # tiny watcher that closes `resp` as soon as cancel fires,
             # unblocking the iterator with a RemoteProtocolError caught
             # in the except clause below.
-            cancel_watcher = asyncio.create_task(
-                _await_cancel_then_close(cancel_event, resp)
-            )
+            cancel_watcher = asyncio.create_task(_await_cancel_then_close(cancel_event, resp))
             try:
                 lines_iter = resp.aiter_lines()
                 async for raw_line in lines_iter:
@@ -6209,11 +6026,7 @@ async def _openai_passthrough_stream(
         raise
 
 
-async def _openai_passthrough_non_streaming(
-    llama_backend,
-    payload,
-    model_name,
-):
+async def _openai_passthrough_non_streaming(llama_backend, payload, model_name):
     """Non-streaming client-side pass-through for /v1/chat/completions.
 
     Returns llama-server's JSON response verbatim (via JSONResponse) so the
@@ -6222,9 +6035,7 @@ async def _openai_passthrough_non_streaming(
     token counts.
     """
     target_url = f"{llama_backend.base_url}/v1/chat/completions"
-    body = _build_openai_passthrough_body(
-        payload, backend_ctx = llama_backend.context_length
-    )
+    body = _build_openai_passthrough_body(payload, backend_ctx = llama_backend.context_length)
 
     try:
         async with httpx.AsyncClient() as client:
diff --git a/studio/backend/routes/mcp_servers.py b/studio/backend/routes/mcp_servers.py
index 87cdcf9402..bf8550f583 100644
--- a/studio/backend/routes/mcp_servers.py
+++ b/studio/backend/routes/mcp_servers.py
@@ -112,16 +112,13 @@ def _row_to_response(row: dict) -> McpServerResponse:
 
 
 @router.get("/", response_model = list[McpServerResponse])
-async def list_mcp_servers(
-    current_subject: str = Depends(get_current_subject),
-):
+async def list_mcp_servers(current_subject: str = Depends(get_current_subject)):
     return [_row_to_response(row) for row in mcp_servers_db.list_servers()]
 
 
 @router.post("/", response_model = McpServerResponse, status_code = 201)
 async def create_mcp_server(
-    payload: McpServerCreate,
-    current_subject: str = Depends(get_current_subject),
+    payload: McpServerCreate, current_subject: str = Depends(get_current_subject)
 ):
     display_name = (payload.display_name or "").strip()
     if not display_name:
@@ -151,9 +148,7 @@ def _changes_from_payload(payload: McpServerUpdate) -> dict:
     if "display_name" in sent:
         name = (payload.display_name or "").strip()
         if not name:
-            raise HTTPException(
-                status_code = 400, detail = "display_name must not be empty"
-            )
+            raise HTTPException(status_code = 400, detail = "display_name must not be empty")
         changes["display_name"] = name
     if "url" in sent:
         changes["url"] = _validate_url(payload.url or "")
@@ -162,15 +157,11 @@ def _changes_from_payload(payload: McpServerUpdate) -> dict:
         changes["headers_json"] = json.dumps(headers) if headers else None
     if "is_enabled" in sent:
         if payload.is_enabled is None:
-            raise HTTPException(
-                status_code = 400, detail = "is_enabled must be true or false"
-            )
+            raise HTTPException(status_code = 400, detail = "is_enabled must be true or false")
         changes["is_enabled"] = payload.is_enabled
     if "use_oauth" in sent:
         if payload.use_oauth is None:
-            raise HTTPException(
-                status_code = 400, detail = "use_oauth must be true or false"
-            )
+            raise HTTPException(status_code = 400, detail = "use_oauth must be true or false")
         changes["use_oauth"] = payload.use_oauth
     # stdio is OAuth-less: drop a stale OAuth flag when switching to a command.
     if "url" in changes and is_stdio(changes["url"]):
@@ -203,8 +194,7 @@ async def update_mcp_server(
     # disabled; fastmcp keys tokens by URL and would otherwise let a
     # re-pointed server silently inherit the old account's credentials.
     if bool(old.get("use_oauth")) and (
-        ("url" in changes and changes["url"] != old["url"])
-        or changes.get("use_oauth") is False
+        ("url" in changes and changes["url"] != old["url"]) or changes.get("use_oauth") is False
     ):
         await clear_oauth_tokens_async(old["url"])
     mcp_servers_db.update_server(server_id, changes)
@@ -212,10 +202,7 @@ async def update_mcp_server(
 
 
 @router.delete("/{server_id}", status_code = 204)
-async def delete_mcp_server(
-    server_id: str,
-    current_subject: str = Depends(get_current_subject),
-):
+async def delete_mcp_server(server_id: str, current_subject: str = Depends(get_current_subject)):
     old = mcp_servers_db.get_server(server_id)
     if not old:
         raise HTTPException(status_code = 404, detail = "MCP server not found")
@@ -226,8 +213,7 @@ async def delete_mcp_server(
 
 @router.post("/{server_id}/refresh", response_model = McpServerProbeResult)
 async def refresh_mcp_server_tools(
-    server_id: str,
-    current_subject: str = Depends(get_current_subject),
+    server_id: str, current_subject: str = Depends(get_current_subject)
 ):
     server = mcp_servers_db.get_server(server_id)
     if not server:
@@ -235,9 +221,7 @@ async def refresh_mcp_server_tools(
     # Refresh uses the stored address, so re-check the stdio gate here too: a
     # stdio row from a desktop DB must not spawn on a hosted/network host.
     if is_stdio(server["url"]) and not stdio_mcp_enabled():
-        raise HTTPException(
-            status_code = 400, detail = "stdio MCP servers are disabled on this host"
-        )
+        raise HTTPException(status_code = 400, detail = "stdio MCP servers are disabled on this host")
 
     use_oauth = bool(server.get("use_oauth"))
     try:
@@ -261,8 +245,7 @@ async def refresh_mcp_server_tools(
 
 @router.post("/test", response_model = McpServerProbeResult)
 async def test_mcp_server(
-    payload: McpServerTestRequest,
-    current_subject: str = Depends(get_current_subject),
+    payload: McpServerTestRequest, current_subject: str = Depends(get_current_subject)
 ):
     # URL/header validation must surface as 400 like create/update so the
     # frontend's create-form pre-flight gets the same error semantics as
diff --git a/studio/backend/routes/models.py b/studio/backend/routes/models.py
index 0e1e491998..3871f579af 100644
--- a/studio/backend/routes/models.py
+++ b/studio/backend/routes/models.py
@@ -141,7 +141,9 @@ logger = get_logger(__name__)
 
 
 def derive_model_type(
-    is_vision: bool, audio_type: Optional[str], is_embedding: bool = False
+    is_vision: bool,
+    audio_type: Optional[str],
+    is_embedding: bool = False,
 ) -> ModelType:
     """Collapse individual capability flags into a single model modality string."""
     if is_embedding:
@@ -157,7 +159,6 @@ def _resolve_hf_cache_dir() -> Path:
     """Resolve local HF cache root used by hub downloads."""
     try:
         from huggingface_hub.constants import HF_HUB_CACHE
-
         return Path(HF_HUB_CACHE)
     except Exception:
         return Path.home() / ".cache" / "huggingface" / "hub"
@@ -194,9 +195,7 @@ def _is_model_directory(d: Path) -> bool:
         return False
 
     try:
-        has_config = (d / "config.json").exists() or (
-            d / "adapter_config.json"
-        ).exists()
+        has_config = (d / "config.json").exists() or (d / "adapter_config.json").exists()
         if not has_config:
             return False
         return any(_is_weight_file(f) for f in d.iterdir() if f.is_file())
@@ -204,11 +203,7 @@ def _is_model_directory(d: Path) -> bool:
         return False
 
 
-def _scan_models_dir(
-    models_dir: Path,
-    *,
-    limit: int | None = None,
-) -> List[LocalModelInfo]:
+def _scan_models_dir(models_dir: Path, *, limit: int | None = None) -> List[LocalModelInfo]:
     if not models_dir.exists() or not models_dir.is_dir():
         return []
 
@@ -449,8 +444,7 @@ def _ollama_links_dir(ollama_dir: Path) -> Optional[Path]:
         return primary
     except OSError as e:
         logger.debug(
-            "Ollama dir %s not writable for .studio_links (%s); "
-            "falling back to Studio cache",
+            "Ollama dir %s not writable for .studio_links (%s); falling back to Studio cache",
             ollama_dir,
             e,
         )
@@ -475,9 +469,7 @@ def _ollama_links_dir(ollama_dir: Path) -> Optional[Path]:
         return None
 
 
-def _scan_ollama_dir(
-    ollama_dir: Path, limit: Optional[int] = None
-) -> List[LocalModelInfo]:
+def _scan_ollama_dir(ollama_dir: Path, limit: Optional[int] = None) -> List[LocalModelInfo]:
     """Scan an Ollama models directory for downloaded models.
 
     Ollama stores models in a content-addressable layout::
@@ -571,9 +563,7 @@ def _scan_ollama_dir(
                 if tmp_path.is_symlink() or tmp_path.exists():
                     tmp_path.unlink()
             except OSError as cleanup_err:
-                logger.debug(
-                    "Could not clean up tmp path %s: %s", tmp_path, cleanup_err
-                )
+                logger.debug("Could not clean up tmp path %s: %s", tmp_path, cleanup_err)
             return None
 
     try:
@@ -590,11 +580,7 @@ def _scan_ollama_dir(
             repo_parts = list(parts[1:-1])
             tag = parts[-1]
 
-            if (
-                host == "registry.ollama.ai"
-                and repo_parts
-                and repo_parts[0] == "library"
-            ):
+            if host == "registry.ollama.ai" and repo_parts and repo_parts[0] == "library":
                 repo_name = "/".join(repo_parts[1:])
             elif host == "registry.ollama.ai":
                 repo_name = "/".join(repo_parts)
@@ -651,9 +637,7 @@ def _scan_ollama_dir(
                     candidate = blobs_dir / digest.replace(":", "-")
                     if candidate.is_file():
                         link_name = f"{safe_name}-{tag}{quant}.gguf"
-                        gguf_link_path = _make_link(
-                            model_link_dir, link_name, candidate
-                        )
+                        gguf_link_path = _make_link(model_link_dir, link_name, candidate)
 
                 elif media == "application/vnd.ollama.image.projector":
                     candidate = blobs_dir / digest.replace(":", "-")
@@ -726,7 +710,6 @@ async def list_local_models(
         allowed_roots.append(hf_default)
     try:
         from utils.paths import studio_root, outputs_root
-
         allowed_roots.extend([studio_root(), outputs_root()])
     except Exception:
         pass
@@ -785,10 +768,7 @@ async def list_local_models(
                         + _scan_hf_cache(folder_path)
                         + _scan_lmstudio_dir(folder_path)
                     )
-                    if not any(
-                        p in (".studio_links", "ollama_links")
-                        for p in Path(m.path).parts
-                    )
+                    if not any(p in (".studio_links", "ollama_links") for p in Path(m.path).parts)
                 ]
                 custom_models = _generic
                 if len(custom_models) < _MAX_MODELS_PER_FOLDER:
@@ -799,9 +779,7 @@ async def list_local_models(
             except OSError as e:
                 logger.warning("Skipping unreadable scan folder %s: %s", folder_path, e)
                 continue
-            local_models += [
-                m.model_copy(update = {"source": "custom"}) for m in custom_models
-            ]
+            local_models += [m.model_copy(update = {"source": "custom"}) for m in custom_models]
 
         # Deduplicate models, but always keep custom folder entries so they
         # appear in the "Custom Folders" UI section even when the same model
@@ -836,19 +814,15 @@ async def list_local_models(
 
 
 @router.get("/scan-folders")
-async def get_scan_folders(
-    current_subject: str = Depends(get_current_subject),
-):
+async def get_scan_folders(current_subject: str = Depends(get_current_subject)):
     """List all registered custom model scan folders."""
     from storage.studio_db import list_scan_folders
-
     return {"folders": list_scan_folders()}
 
 
 @router.post("/scan-folders", response_model = ScanFolderInfo, status_code = 201)
 async def add_scan_folder_endpoint(
-    body: AddScanFolderRequest,
-    current_subject: str = Depends(get_current_subject),
+    body: AddScanFolderRequest, current_subject: str = Depends(get_current_subject)
 ):
     """Register a new directory to scan for local models."""
     from storage.studio_db import add_scan_folder
@@ -867,8 +841,7 @@ async def add_scan_folder_endpoint(
 
 @router.delete("/scan-folders/{folder_id}")
 async def remove_scan_folder_endpoint(
-    folder_id: int,
-    current_subject: str = Depends(get_current_subject),
+    folder_id: int, current_subject: str = Depends(get_current_subject)
 ):
     """Remove a registered custom scan folder."""
     from storage.studio_db import remove_scan_folder
@@ -879,9 +852,7 @@ async def remove_scan_folder_endpoint(
 
 
 @router.get("/recommended-folders")
-async def get_recommended_folders(
-    current_subject: str = Depends(get_current_subject),
-):
+async def get_recommended_folders(current_subject: str = Depends(get_current_subject)):
     """Return well-known model directories that exist on this machine.
 
     Lightweight alternative to ``browse-folders`` for showing quick-pick
@@ -1191,9 +1162,7 @@ def _match_browse_child(current: Path, name: str) -> Optional[Path]:
             detail = f"Permission denied reading {current.name}",
         ) from None
     except OSError as exc:
-        logger.warning(
-            "browse-folders: could not read %s: %s", current, exc, exc_info = True
-        )
+        logger.warning("browse-folders: could not read %s: %s", current, exc, exc_info = True)
         raise HTTPException(
             status_code = 500,
             detail = f"Could not read {os.path.basename(str(current))}",
@@ -1344,9 +1313,7 @@ async def browse_folders(
             detail = f"Permission denied reading {os.path.basename(str(target))}",
         )
     except OSError as exc:
-        logger.warning(
-            "browse-folders: could not read %s: %s", target, exc, exc_info = True
-        )
+        logger.warning("browse-folders: could not read %s: %s", target, exc, exc_info = True)
         raise HTTPException(
             status_code = 500,
             detail = f"Could not read {os.path.basename(str(target))}",
@@ -1404,9 +1371,7 @@ async def browse_folders(
     # would 403 on click. Users can still hop to other allowed roots
     # via the suggestion chips below.
     parent: Optional[str]
-    if target.parent == target or not _is_path_inside_allowlist(
-        target.parent, allowed_roots
-    ):
+    if target.parent == target or not _is_path_inside_allowlist(target.parent, allowed_roots):
         parent = None
     else:
         parent = str(target.parent)
@@ -1475,9 +1440,7 @@ def _looks_like_mlx_repo(model_id: str) -> bool:
 
 
 @router.get("/list")
-async def list_models(
-    current_subject: str = Depends(get_current_subject),
-):
+async def list_models(current_subject: str = Depends(get_current_subject)):
     """
     List available models (default models and loaded models).
 
@@ -1565,16 +1528,12 @@ def _get_max_position_embeddings(config) -> Optional[int]:
     """Extract max_position_embeddings from a model config, checking text_config fallback."""
     if hasattr(config, "max_position_embeddings"):
         return config.max_position_embeddings
-    if hasattr(config, "text_config") and hasattr(
-        config.text_config, "max_position_embeddings"
-    ):
+    if hasattr(config, "text_config") and hasattr(config.text_config, "max_position_embeddings"):
         return config.text_config.max_position_embeddings
     return None
 
 
-def _get_model_size_bytes(
-    model_name: str, hf_token: Optional[str] = None
-) -> Optional[int]:
+def _get_model_size_bytes(model_name: str, hf_token: Optional[str] = None) -> Optional[int]:
     """Get total size of model weight files from HF Hub."""
     try:
         from huggingface_hub import HfApi
@@ -1587,9 +1546,7 @@ def _get_model_size_bytes(
         weight_exts = (".safetensors", ".bin", ".pt", ".pth", ".gguf")
         total = 0
         for sibling in info.siblings:
-            if sibling.rfilename and any(
-                sibling.rfilename.endswith(ext) for ext in weight_exts
-            ):
+            if sibling.rfilename and any(sibling.rfilename.endswith(ext) for ext in weight_exts):
                 if sibling.size is not None:
                     total += sibling.size
 
@@ -1777,15 +1734,10 @@ def _loaded_model_matches_deleted_path(active_model: str, deleted_path: Path) ->
         )
         active_lower = active_model.lower()
         target_lower = str(deleted_path).lower()
-        return active_lower == target_lower or active_lower.startswith(
-            f"{target_lower}{os.sep}"
-        )
+        return active_lower == target_lower or active_lower.startswith(f"{target_lower}{os.sep}")
 
 
-def _loading_model_matches_deleted_path(
-    loading_model: object,
-    deleted_path: Path,
-) -> bool:
+def _loading_model_matches_deleted_path(loading_model: object, deleted_path: Path) -> bool:
     if not loading_model:
         return False
     return _loaded_model_matches_deleted_path(str(loading_model), deleted_path)
@@ -1918,7 +1870,6 @@ async def delete_finetuned_model(
     if source == "training":
         try:
             from core.training import get_training_backend
-
             training_backend = get_training_backend()
             if training_backend.is_training_active():
                 raise HTTPException(
@@ -2005,9 +1956,7 @@ async def delete_finetuned_model(
     except HTTPException:
         raise
     except Exception as e:
-        logger.warning(
-            "Could not check inference backend loaded model before delete: %s", e
-        )
+        logger.warning("Could not check inference backend loaded model before delete: %s", e)
         raise HTTPException(
             status_code = 503,
             detail = "Could not verify model load status before deleting",
@@ -2079,10 +2028,7 @@ async def delete_finetuned_model(
 
 
 @router.get("/loras/{lora_path:path}/base-model", response_model = LoRABaseModelResponse)
-async def get_lora_base_model(
-    lora_path: str,
-    current_subject: str = Depends(get_current_subject),
-):
+async def get_lora_base_model(lora_path: str, current_subject: str = Depends(get_current_subject)):
     """
     Get the base model for a LoRA adapter.
 
@@ -2115,10 +2061,7 @@ async def get_lora_base_model(
 
 
 @router.get("/check-vision/{model_name:path}", response_model = VisionCheckResponse)
-async def check_vision_model(
-    model_name: str,
-    current_subject: str = Depends(get_current_subject),
-):
+async def check_vision_model(model_name: str, current_subject: str = Depends(get_current_subject)):
     """
     Check if a model is a vision model.
 
@@ -2159,9 +2102,7 @@ async def check_embedding_model(
         logger.info(f"Checking if embedding model: {model_name}")
         is_embedding = is_embedding_model(model_name, hf_token = hf_token)
 
-        logger.info(
-            f"Embedding check result for {model_name}: is_embedding={is_embedding}"
-        )
+        logger.info(f"Embedding check result for {model_name}: is_embedding={is_embedding}")
         return EmbeddingCheckResponse(
             model_name = model_name,
             is_embedding = is_embedding,
@@ -2182,9 +2123,7 @@ async def get_gguf_variants(
     repo_id: str = Query(
         ..., description = "HuggingFace repo ID (e.g. 'unsloth/gemma-3-4b-it-GGUF')"
     ),
-    hf_token: Optional[str] = Query(
-        None, description = "HuggingFace token for private repos"
-    ),
+    hf_token: Optional[str] = Query(None, description = "HuggingFace token for private repos"),
     current_subject: str = Depends(get_current_subject),
 ):
     """
@@ -2333,11 +2272,7 @@ async def get_gguf_download_progress(
                 break
 
         total_progress_bytes = downloaded_bytes + in_progress_bytes
-        progress = (
-            min(total_progress_bytes / expected_bytes, 0.99)
-            if expected_bytes > 0
-            else 0
-        )
+        progress = min(total_progress_bytes / expected_bytes, 0.99) if expected_bytes > 0 else 0
         # Only report 1.0 when all bytes are in completed files (not in-progress)
         if expected_bytes > 0 and downloaded_bytes >= expected_bytes:
             progress = 1.0
@@ -2480,7 +2415,6 @@ def _all_hf_cache_scans():
     try:
         # Resolve the active cache dir so we can dedup
         from huggingface_hub.constants import HF_HUB_CACHE
-
         seen.add(str(Path(HF_HUB_CACHE).resolve()))
     except Exception:
         pass
@@ -2553,9 +2487,7 @@ def _repo_has_gguf_files(repo_info) -> bool:
 
 
 @router.get("/cached-gguf")
-async def list_cached_gguf(
-    current_subject: str = Depends(get_current_subject),
-):
+async def list_cached_gguf(current_subject: str = Depends(get_current_subject)):
     """List GGUF repos downloaded to HF cache, legacy Unsloth cache, and HF default cache."""
     try:
         cache_scans = _all_hf_cache_scans()
@@ -2590,9 +2522,7 @@ async def list_cached_gguf(
 
 
 @router.get("/cached-models")
-async def list_cached_models(
-    current_subject: str = Depends(get_current_subject),
-):
+async def list_cached_models(current_subject: str = Depends(get_current_subject)):
     """List non-GGUF model repos downloaded to HF cache, legacy Unsloth cache, and HF default cache."""
     _WEIGHT_EXTENSIONS = (".safetensors", ".bin")
 
@@ -2609,9 +2539,7 @@ async def list_cached_models(
                     if _repo_has_gguf_files(repo_info):
                         continue
                     total_size = sum(
-                        (f.size_on_disk or 0)
-                        for rev in repo_info.revisions
-                        for f in rev.files
+                        (f.size_on_disk or 0) for rev in repo_info.revisions for f in rev.files
                     )
                     if total_size == 0:
                         continue
@@ -2658,7 +2586,6 @@ async def delete_cached_model(
     # Check if model is currently loaded
     try:
         from routes.inference import get_llama_cpp_backend
-
         llama_backend = get_llama_cpp_backend()
         if llama_backend.is_loaded and llama_backend.model_identifier:
             loaded_id = llama_backend.model_identifier.lower()
diff --git a/studio/backend/routes/providers.py b/studio/backend/routes/providers.py
index 4eaa007750..5dd7038330 100644
--- a/studio/backend/routes/providers.py
+++ b/studio/backend/routes/providers.py
@@ -51,9 +51,7 @@ router = APIRouter()
 
 
 @router.get("/public-key")
-async def get_public_key(
-    current_subject: str = Depends(get_current_subject),
-):
+async def get_public_key(current_subject: str = Depends(get_current_subject)):
     """Return the RSA public key PEM for client-side API key encryption.
 
     The ``fingerprint`` field is a short SHA256 of the PEM and is meant
@@ -72,9 +70,7 @@ async def get_public_key(
 
 
 @router.get("/registry", response_model = list[ProviderRegistryEntry])
-async def list_registry(
-    current_subject: str = Depends(get_current_subject),
-):
+async def list_registry(current_subject: str = Depends(get_current_subject)):
     """List all supported provider types with their default configurations."""
     return list_available_providers()
 
@@ -83,9 +79,7 @@ async def list_registry(
 
 
 @router.get("/pricing")
-async def get_pricing_snapshot(
-    current_subject: str = Depends(get_current_subject),
-):
+async def get_pricing_snapshot(current_subject: str = Depends(get_current_subject)):
     """Static per-MTok pricing table the frontend uses to convert
     upstream usage chunks into a per-turn USD cost. See
     ``core/inference/pricing.py`` for sourcing notes; values reflect
@@ -97,9 +91,7 @@ async def get_pricing_snapshot(
 
 
 @router.get("/", response_model = list[ProviderResponse])
-async def list_provider_configs(
-    current_subject: str = Depends(get_current_subject),
-):
+async def list_provider_configs(current_subject: str = Depends(get_current_subject)):
     """List all saved provider configurations."""
     rows = providers_db.list_providers()
     return [
@@ -118,8 +110,7 @@ async def list_provider_configs(
 
 @router.post("/", response_model = ProviderResponse, status_code = 201)
 async def create_provider_config(
-    payload: ProviderCreate,
-    current_subject: str = Depends(get_current_subject),
+    payload: ProviderCreate, current_subject: str = Depends(get_current_subject)
 ):
     """Create a new saved provider configuration (no API key stored)."""
     info = get_provider_info(payload.provider_type)
@@ -186,8 +177,7 @@ async def update_provider_config(
 
 @router.delete("/{provider_id}", status_code = 204)
 async def delete_provider_config(
-    provider_id: str,
-    current_subject: str = Depends(get_current_subject),
+    provider_id: str, current_subject: str = Depends(get_current_subject)
 ):
     """Delete a saved provider configuration."""
     deleted = providers_db.delete_provider(provider_id)
@@ -200,8 +190,7 @@ async def delete_provider_config(
 
 @router.post("/test", response_model = ProviderTestResult)
 async def test_provider(
-    payload: ProviderTestRequest,
-    current_subject: str = Depends(get_current_subject),
+    payload: ProviderTestRequest, current_subject: str = Depends(get_current_subject)
 ):
     """
     Test connectivity to an external provider.
@@ -221,9 +210,7 @@ async def test_provider(
         try:
             api_key = decrypt_api_key(payload.encrypted_api_key)
         except Exception as exc:
-            logger.warning(
-                "Failed to decrypt API key (%s): %s", type(exc).__name__, exc
-            )
+            logger.warning("Failed to decrypt API key (%s): %s", type(exc).__name__, exc)
             raise HTTPException(
                 status_code = 400,
                 detail = "Failed to decrypt API key. The public key may have changed — try refreshing the page.",
@@ -275,8 +262,7 @@ async def test_provider(
 
 @router.post("/models", response_model = list[ProviderModelInfo])
 async def list_provider_models(
-    payload: ProviderModelsRequest,
-    current_subject: str = Depends(get_current_subject),
+    payload: ProviderModelsRequest, current_subject: str = Depends(get_current_subject)
 ):
     """
     List models available from an external provider.
@@ -295,9 +281,7 @@ async def list_provider_models(
         try:
             api_key = decrypt_api_key(payload.encrypted_api_key)
         except Exception as exc:
-            logger.warning(
-                "Failed to decrypt API key (%s): %s", type(exc).__name__, exc
-            )
+            logger.warning("Failed to decrypt API key (%s): %s", type(exc).__name__, exc)
             raise HTTPException(
                 status_code = 400,
                 detail = "Failed to decrypt API key. The public key may have changed — try refreshing the page.",
@@ -338,7 +322,6 @@ async def list_provider_models(
         if payload.provider_type == "gemini":
             try:
                 from urllib.parse import urlparse as _urlparse
-
                 _host = (_urlparse(base_url).hostname or "").lower()
             except Exception:
                 _host = ""
@@ -349,9 +332,7 @@ async def list_provider_models(
             if allow_prefixes is not None:
                 prefix_tuple = tuple(str(p) for p in allow_prefixes if str(p))
                 if prefix_tuple:
-                    models = [
-                        m for m in models if m.get("id", "").startswith(prefix_tuple)
-                    ]
+                    models = [m for m in models if m.get("id", "").startswith(prefix_tuple)]
             allowlist = info.get("model_id_allowlist")
             if allowlist is not None:
                 models = [m for m in models if allowlist.match(m.get("id", ""))]
diff --git a/studio/backend/routes/settings.py b/studio/backend/routes/settings.py
index b6fbeeee7a..94ea4c7b6c 100644
--- a/studio/backend/routes/settings.py
+++ b/studio/backend/routes/settings.py
@@ -45,16 +45,13 @@ def _upload_limit_response(limit_mb: int) -> UploadLimitResponse:
 
 
 @router.get("/upload-limit", response_model = UploadLimitResponse)
-def get_upload_limit(
-    current_subject: str = Depends(get_current_subject),
-) -> UploadLimitResponse:
+def get_upload_limit(current_subject: str = Depends(get_current_subject)) -> UploadLimitResponse:
     return _upload_limit_response(get_upload_limit_mb())
 
 
 @router.put("/upload-limit", response_model = UploadLimitResponse)
 def update_upload_limit(
-    payload: UploadLimitPayload,
-    current_subject: str = Depends(get_current_subject),
+    payload: UploadLimitPayload, current_subject: str = Depends(get_current_subject)
 ) -> UploadLimitResponse:
     try:
         limit_mb = set_upload_limit_mb(payload.max_upload_size_mb)
diff --git a/studio/backend/routes/training.py b/studio/backend/routes/training.py
index 5b4267b2ef..d62e0209b0 100644
--- a/studio/backend/routes/training.py
+++ b/studio/backend/routes/training.py
@@ -71,9 +71,7 @@ router = APIRouter()
 logger = get_logger(__name__)
 
 
-def _validate_local_dataset_paths(
-    paths: list[str], label: str = "Local dataset"
-) -> list[str]:
+def _validate_local_dataset_paths(paths: list[str], label: str = "Local dataset") -> list[str]:
     """Resolve and validate a list of local dataset paths. Returns validated absolute paths."""
     validated = []
     missing = []
@@ -95,9 +93,7 @@ def _validate_local_dataset_paths(
 
 
 @router.get("/hardware")
-async def get_hardware_utilization(
-    current_subject: str = Depends(get_current_subject),
-):
+async def get_hardware_utilization(current_subject: str = Depends(get_current_subject)):
     """
     Get a live snapshot of GPU hardware utilization.
 
@@ -105,23 +101,18 @@ async def get_hardware_utilization(
     Returns live GPU memory usage information for the active backend.
     """
     from utils.hardware import get_gpu_utilization
-
     return get_gpu_utilization()
 
 
 @router.get("/hardware/visible")
-async def get_visible_hardware_utilization(
-    current_subject: str = Depends(get_current_subject),
-):
+async def get_visible_hardware_utilization(current_subject: str = Depends(get_current_subject)):
     from utils.hardware import get_visible_gpu_utilization
-
     return get_visible_gpu_utilization()
 
 
 @router.post("/start")
 async def start_training(
-    request: TrainingStartRequest,
-    current_subject: str = Depends(get_current_subject),
+    request: TrainingStartRequest, current_subject: str = Depends(get_current_subject)
 ):
     """
     Start a training job.
@@ -153,9 +144,7 @@ async def start_training(
 
         # Generate job ID — passed into start_training() which sets it on the
         # backend only after confirming the old pump thread is dead.
-        job_id = (
-            f"job_{datetime.now().strftime('%Y%m%d_%H%M%S')}_{_uuid.uuid4().hex[:8]}"
-        )
+        job_id = f"job_{datetime.now().strftime('%Y%m%d_%H%M%S')}_{_uuid.uuid4().hex[:8]}"
 
         # Validate dataset paths if provided
         if request.local_datasets:
@@ -169,9 +158,7 @@ async def start_training(
         resume_output_dir: Optional[str] = None
         if request.resume_from_checkpoint:
             try:
-                resume_output_dir = normalize_resume_output_dir(
-                    request.resume_from_checkpoint
-                )
+                resume_output_dir = normalize_resume_output_dir(request.resume_from_checkpoint)
             except ValueError as e:
                 # Deliberate user-facing validation message.
                 validation_message = str(e)
@@ -229,9 +216,7 @@ async def start_training(
             "lora_r": request.lora_r,
             "lora_alpha": request.lora_alpha,
             "lora_dropout": request.lora_dropout,
-            "target_modules": request.target_modules
-            if request.target_modules
-            else None,
+            "target_modules": request.target_modules if request.target_modules else None,
             "gradient_checkpointing": request.gradient_checkpointing.strip()
             if request.gradient_checkpointing and request.gradient_checkpointing.strip()
             else "unsloth",
@@ -261,20 +246,15 @@ async def start_training(
         # net, consult the YAML directly so models that need it always get it.
         if not training_kwargs["trust_remote_code"]:
             model_defaults = load_model_defaults(request.model_name)
-            yaml_trust = model_defaults.get("training", {}).get(
-                "trust_remote_code", False
-            )
+            yaml_trust = model_defaults.get("training", {}).get("trust_remote_code", False)
             if yaml_trust:
-                logger.info(
-                    f"YAML config sets trust_remote_code=True for {request.model_name}"
-                )
+                logger.info(f"YAML config sets trust_remote_code=True for {request.model_name}")
                 training_kwargs["trust_remote_code"] = True
 
         # Free GPU memory: shut down any running inference/export subprocesses
         # before training starts (they'd compete for VRAM otherwise)
         try:
             from core.inference import get_inference_backend
-
             inf_backend = get_inference_backend()
             if inf_backend.active_model_name:
                 logger.info(
@@ -289,12 +269,9 @@ async def start_training(
 
         try:
             from core.export import get_export_backend
-
             exp_backend = get_export_backend()
             if exp_backend.current_checkpoint:
-                logger.info(
-                    "Shutting down export subprocess to free GPU memory for training"
-                )
+                logger.info("Shutting down export subprocess to free GPU memory for training")
                 exp_backend._shutdown_subprocess()
                 exp_backend.current_checkpoint = None
                 exp_backend.is_vision = False
@@ -376,9 +353,7 @@ async def stop_training(
 
 
 @router.post("/reset")
-async def reset_training(
-    current_subject: str = Depends(get_current_subject),
-):
+async def reset_training(current_subject: str = Depends(get_current_subject)):
     """
     Reset training state so the user can return to configuration.
     """
@@ -389,14 +364,10 @@ async def reset_training(
         if is_active:
             if backend._cancel_requested:
                 # Cancel (save=False) was requested — force-terminate so we can reset immediately
-                logger.info(
-                    "Force-terminating subprocess for immediate reset (cancel path)"
-                )
+                logger.info("Force-terminating subprocess for immediate reset (cancel path)")
                 backend.force_terminate()
             else:
-                logger.warning(
-                    "Rejected reset while training active: is_active=%s", is_active
-                )
+                logger.warning("Rejected reset while training active: is_active=%s", is_active)
                 raise HTTPException(
                     status_code = 409,
                     detail = "Training is still running. Stop training and wait for it to finish before resetting.",
@@ -433,9 +404,7 @@ async def reset_training(
 
 
 @router.get("/status")
-async def get_training_status(
-    current_subject: str = Depends(get_current_subject),
-):
+async def get_training_status(current_subject: str = Depends(get_current_subject)):
     """
     Get the current training status.
     """
@@ -467,9 +436,7 @@ async def get_training_status(
             msg_lower = status_message.lower()
             if "loading" in msg_lower or "importing" in msg_lower:
                 phase = "loading_model"
-            elif any(
-                k in msg_lower for k in ["preparing", "initializing", "configuring"]
-            ):
+            elif any(k in msg_lower for k in ["preparing", "initializing", "configuring"]):
                 phase = "configuring"
             else:
                 phase = "training"
@@ -528,9 +495,7 @@ async def get_training_status(
 
 
 @router.get("/metrics", response_model = TrainingMetricsResponse)
-async def get_training_metrics(
-    current_subject: str = Depends(get_current_subject),
-):
+async def get_training_metrics(current_subject: str = Depends(get_current_subject)):
     """
     Get training metrics (loss, learning rate, steps).
     """
@@ -572,8 +537,7 @@ async def get_training_metrics(
 
 @router.get("/progress")
 async def stream_training_progress(
-    request: Request,
-    current_subject: str = Depends(get_current_subject),
+    request: Request, current_subject: str = Depends(get_current_subject)
 ):
     """
     Stream training progress updates using Server-Sent Events (SSE).
@@ -614,14 +578,10 @@ async def stream_training_progress(
             if step < 0 or total == 0:
                 progress_percent = 0.0
             else:
-                progress_percent = (
-                    float(step) / float(total) * 100.0 if total > 0 else 0.0
-                )
+                progress_percent = float(step) / float(total) * 100.0 if total > 0 else 0.0
 
             # Get actual values from progress object if available
-            elapsed_seconds = (
-                getattr(progress, "elapsed_seconds", None) if progress else None
-            )
+            elapsed_seconds = getattr(progress, "elapsed_seconds", None) if progress else None
             eta_seconds = getattr(progress, "eta_seconds", None) if progress else None
             grad_norm = grad_norm_override
             if grad_norm is None and progress:
@@ -677,25 +637,15 @@ async def stream_training_progress(
             }
             for i, step_val in enumerate(backend.step_history):
                 if step_val > resume_from_step:
-                    loss_val = (
-                        backend.loss_history[i]
-                        if i < len(backend.loss_history)
-                        else None
-                    )
-                    lr_val = (
-                        backend.lr_history[i] if i < len(backend.lr_history) else None
-                    )
+                    loss_val = backend.loss_history[i] if i < len(backend.loss_history) else None
+                    lr_val = backend.lr_history[i] if i < len(backend.lr_history) else None
                     tp_replay = getattr(
                         getattr(backend, "trainer", None), "training_progress", None
                     )
                     total_replay = (
-                        getattr(tp_replay, "total_steps", step_val)
-                        if tp_replay
-                        else step_val
-                    )
-                    epoch_replay = (
-                        getattr(tp_replay, "epoch", None) if tp_replay else None
+                        getattr(tp_replay, "total_steps", step_val) if tp_replay else step_val
                     )
+                    epoch_replay = getattr(tp_replay, "epoch", None) if tp_replay else None
                     payload = build_progress(
                         step_val,
                         loss_val,
@@ -705,9 +655,7 @@ async def stream_training_progress(
                         progress = tp_replay,
                         grad_norm_override = grad_norm_by_step.get(step_val),
                     )
-                    yield format_sse(
-                        payload.model_dump_json(), event = "progress", event_id = step_val
-                    )
+                    yield format_sse(payload.model_dump_json(), event = "progress", event_id = step_val)
                     replayed += 1
             if replayed:
                 logger.info(f"SSE reconnect: replayed {replayed} missed steps")
@@ -727,21 +675,15 @@ async def stream_training_progress(
                 epoch = initial_epoch,
                 progress = tp,
             )
-            yield format_sse(
-                initial_progress.model_dump_json(), event = "progress", event_id = 0
-            )
+            yield format_sse(initial_progress.model_dump_json(), event = "progress", event_id = 0)
 
             # If not active, send final state and exit
             if not is_active:
                 if backend.step_history:
                     final_step = backend.step_history[-1]
-                    final_loss = (
-                        backend.loss_history[-1] if backend.loss_history else None
-                    )
+                    final_loss = backend.loss_history[-1] if backend.loss_history else None
                     final_lr = backend.lr_history[-1] if backend.lr_history else None
-                    final_total_steps = (
-                        getattr(tp, "total_steps", final_step) if tp else final_step
-                    )
+                    final_total_steps = getattr(tp, "total_steps", final_step) if tp else final_step
                     final_epoch = getattr(tp, "epoch", None) if tp else None
                     payload = build_progress(
                         final_step,
@@ -756,9 +698,7 @@ async def stream_training_progress(
                     )
                 else:
                     yield format_sse(
-                        build_progress(
-                            -1, None, None, 0, progress = tp
-                        ).model_dump_json(),
+                        build_progress(-1, None, None, 0, progress = tp).model_dump_json(),
                         event = "complete",
                         event_id = 0,
                     )
@@ -767,29 +707,19 @@ async def stream_training_progress(
         # ── Live polling loop ────────────────────────────────────
         last_step = resume_from_step if resume_from_step is not None else -1
         no_update_count = 0
-        max_no_updates = (
-            1800  # Timeout after 30 minutes (large models need time for compilation)
-        )
+        max_no_updates = 1800  # Timeout after 30 minutes (large models need time for compilation)
 
         while backend.is_training_active():
             try:
                 if backend.step_history:
                     current_step = backend.step_history[-1]
-                    current_loss = (
-                        backend.loss_history[-1] if backend.loss_history else None
-                    )
+                    current_loss = backend.loss_history[-1] if backend.loss_history else None
                     current_lr = backend.lr_history[-1] if backend.lr_history else None
-                    tp_inner = getattr(
-                        getattr(backend, "trainer", None), "training_progress", None
-                    )
+                    tp_inner = getattr(getattr(backend, "trainer", None), "training_progress", None)
                     current_total_steps = (
-                        getattr(tp_inner, "total_steps", current_step)
-                        if tp_inner
-                        else current_step
-                    )
-                    current_epoch = (
-                        getattr(tp_inner, "epoch", None) if tp_inner else None
+                        getattr(tp_inner, "total_steps", current_step) if tp_inner else current_step
                     )
+                    current_epoch = getattr(tp_inner, "epoch", None) if tp_inner else None
 
                     # Only send if step changed
                     if current_step != last_step:
@@ -836,9 +766,7 @@ async def stream_training_progress(
                             "training_progress",
                             None,
                         )
-                        prep_total = (
-                            getattr(tp_prep, "total_steps", 0) if tp_prep else 0
-                        )
+                        prep_total = getattr(tp_prep, "total_steps", 0) if tp_prep else 0
                         preparing_payload = build_progress(
                             0,
                             None,
@@ -858,9 +786,7 @@ async def stream_training_progress(
                     tp_timeout = getattr(
                         getattr(backend, "trainer", None), "training_progress", None
                     )
-                    timeout_payload = build_progress(
-                        last_step, None, None, 0, progress = tp_timeout
-                    )
+                    timeout_payload = build_progress(last_step, None, None, 0, progress = tp_timeout)
                     yield format_sse(
                         timeout_payload.model_dump_json(),
                         event = "error",
@@ -872,9 +798,7 @@ async def stream_training_progress(
 
             except Exception as e:
                 logger.error(f"Error in progress stream: {e}", exc_info = True)
-                tp_error = getattr(
-                    getattr(backend, "trainer", None), "training_progress", None
-                )
+                tp_error = getattr(getattr(backend, "trainer", None), "training_progress", None)
                 error_payload = build_progress(0, None, None, 0, progress = tp_error)
                 yield format_sse(
                     error_payload.model_dump_json(),
@@ -888,9 +812,7 @@ async def stream_training_progress(
         final_loss = backend.loss_history[-1] if backend.loss_history else None
         final_lr = backend.lr_history[-1] if backend.lr_history else None
         final_tp = getattr(getattr(backend, "trainer", None), "training_progress", None)
-        final_total_steps = (
-            getattr(final_tp, "total_steps", final_step) if final_tp else final_step
-        )
+        final_total_steps = getattr(final_tp, "total_steps", final_step) if final_tp else final_step
         final_epoch = getattr(final_tp, "epoch", None) if final_tp else None
         final_payload = build_progress(
             final_step,
diff --git a/studio/backend/routes/training_history.py b/studio/backend/routes/training_history.py
index 771d9f1e35..1560c72767 100644
--- a/studio/backend/routes/training_history.py
+++ b/studio/backend/routes/training_history.py
@@ -42,19 +42,13 @@ async def list_training_runs(
     """List training runs, newest first."""
     result = list_runs(limit = limit, offset = offset)
     return TrainingRunListResponse(
-        runs = [
-            TrainingRunSummary(**{**r, "can_resume": can_resume_run(r)})
-            for r in result["runs"]
-        ],
+        runs = [TrainingRunSummary(**{**r, "can_resume": can_resume_run(r)}) for r in result["runs"]],
         total = result["total"],
     )
 
 
 @router.get("/runs/{run_id}", response_model = TrainingRunDetailResponse)
-async def get_training_run_detail(
-    run_id: str,
-    current_subject: str = Depends(get_current_subject),
-):
+async def get_training_run_detail(run_id: str, current_subject: str = Depends(get_current_subject)):
     """Get a single training run with full config and metrics."""
     run = get_run(run_id)
     if run is None:
@@ -109,18 +103,13 @@ async def update_training_run(
 
 
 @router.delete("/runs/{run_id}", response_model = TrainingRunDeleteResponse)
-async def delete_training_run(
-    run_id: str,
-    current_subject: str = Depends(get_current_subject),
-):
+async def delete_training_run(run_id: str, current_subject: str = Depends(get_current_subject)):
     """Delete a training run and its metrics (CASCADE)."""
     run = get_run(run_id)
     if run is None:
         raise HTTPException(status_code = 404, detail = f"Run {run_id} not found")
     if run["status"] == "running":
-        raise HTTPException(
-            status_code = 409, detail = "Cannot delete a running training run"
-        )
+        raise HTTPException(status_code = 409, detail = "Cannot delete a running training run")
     logger.info("Deleting training run %s", run_id)
     delete_run(run_id)
     return TrainingRunDeleteResponse(
diff --git a/studio/backend/run.py b/studio/backend/run.py
index 7e84c41075..5cfc1822f7 100644
--- a/studio/backend/run.py
+++ b/studio/backend/run.py
@@ -25,9 +25,7 @@ try:
     configure_cpu_threads()
 except ValueError as exc:
     configured = os.environ.get("UNSLOTH_CPU_THREADS")
-    raise SystemExit(
-        f"Error: Invalid UNSLOTH_CPU_THREADS value {configured!r}: {exc}"
-    ) from None
+    raise SystemExit(f"Error: Invalid UNSLOTH_CPU_THREADS value {configured!r}: {exc}") from None
 
 # Fix for Anaconda/conda-forge Python: seed platform._sys_version_cache before
 # any library imports that trigger attrs -> rich -> structlog -> platform crash.
@@ -93,9 +91,7 @@ def _install_uvicorn_startup_log_rewrite(bind_host: str, display_host: str) -> N
     import re
 
     rewrite_host = (
-        bind_host in ("0.0.0.0", "::")
-        and bool(display_host)
-        and display_host != bind_host
+        bind_host in ("0.0.0.0", "::") and bool(display_host) and display_host != bind_host
     )
     new_suffix = "(To stop: press Ctrl+C -- on macOS, Control+C not Command+C)"
     old_suffix_re = re.compile(r"\(Press CTRL\+C to quit\)")
@@ -136,10 +132,13 @@ def _install_uvicorn_startup_log_rewrite(bind_host: str, display_host: str) -> N
         logging.getLogger(name).addFilter(f)
 
 
-def _local_port_open(host: str, port: int, timeout: float = 1.0) -> bool:
+def _local_port_open(
+    host: str,
+    port: int,
+    timeout: float = 1.0,
+) -> bool:
     """Return True iff a TCP connection to (host, port) succeeds within timeout."""
     import socket
-
     try:
         with socket.create_connection((host, port), timeout = timeout):
             return True
@@ -178,9 +177,7 @@ def _localhost_ipv6_mismatch_url(bind_host: str, port: int) -> "str | None":
         return None
 
     try:
-        addr_info = socket.getaddrinfo(
-            "localhost", port, socket.AF_UNSPEC, socket.SOCK_STREAM
-        )
+        addr_info = socket.getaddrinfo("localhost", port, socket.AF_UNSPEC, socket.SOCK_STREAM)
     except Exception:
         return None
 
@@ -369,8 +366,7 @@ def _verify_global_reachability(display_host: str, port: int) -> None:
                 flush = True,
             )
             print(
-                f"{dim}        ssh -L {port}:localhost:{port} "
-                f"@{display_host}{reset}",
+                f"{dim}        ssh -L {port}:localhost:{port} " f"@{display_host}{reset}",
                 flush = True,
             )
             print(
@@ -499,15 +495,17 @@ def _is_port_free(host: str, port: int) -> bool:
     return True
 
 
-def _find_free_port(host: str, start: int, max_attempts: int = 20) -> int:
+def _find_free_port(
+    host: str,
+    start: int,
+    max_attempts: int = 20,
+) -> int:
     """Find a free port starting from `start`, trying up to max_attempts ports."""
     for offset in range(max_attempts):
         candidate = start + offset
         if _is_port_free(host, candidate):
             return candidate
-    raise RuntimeError(
-        f"Could not find a free port in range {start}-{start + max_attempts - 1}"
-    )
+    raise RuntimeError(f"Could not find a free port in range {start}-{start + max_attempts - 1}")
 
 
 from utils.paths.storage_roots import studio_root as _studio_root
@@ -570,7 +568,6 @@ def _graceful_shutdown(server = None):
     # 2. Clean up inference subprocess (if instantiated)
     try:
         from core.inference.orchestrator import _inference_backend
-
         if _inference_backend is not None:
             _inference_backend._shutdown_subprocess(timeout = 5.0)
     except Exception as e:
@@ -579,7 +576,6 @@ def _graceful_shutdown(server = None):
     # 3. Clean up export subprocess (if instantiated)
     try:
         from core.export.orchestrator import _export_backend
-
         if _export_backend is not None:
             _export_backend._shutdown_subprocess(timeout = 5.0)
     except Exception as e:
@@ -588,7 +584,6 @@ def _graceful_shutdown(server = None):
     # 4. Clean up training subprocess (if active)
     try:
         from core.training.training import _training_backend
-
         if _training_backend is not None:
             _training_backend.force_terminate()
     except Exception as e:
@@ -597,7 +592,6 @@ def _graceful_shutdown(server = None):
     # 5. Kill llama-server subprocess (if loaded)
     try:
         from routes.inference import _llama_cpp_backend
-
         if _llama_cpp_backend is not None:
             _llama_cpp_backend._kill_process()
     except Exception as e:
@@ -651,9 +645,7 @@ def _iter_frontend_fallback_candidates() -> "list[Path]":
                 # Tolerate single- or multi-line dict literals; [^}]* still
                 # rejects nested dicts, which the setuptools template never
                 # emits for editable installs.
-                m = re.search(
-                    r"^MAPPING\s*(?::[^=]*)?=\s*(\{[^}]*\})", src, re.M | re.S
-                )
+                m = re.search(r"^MAPPING\s*(?::[^=]*)?=\s*(\{[^}]*\})", src, re.M | re.S)
                 if not m:
                     continue
                 try:
@@ -760,9 +752,7 @@ def run_server(
             print("=" * 50)
             if blocker:
                 pid, name = blocker
-                print(
-                    f"Port {original_port} is already in use by " f"{name} (PID {pid})."
-                )
+                print(f"Port {original_port} is already in use by " f"{name} (PID {pid}).")
             else:
                 print(f"Port {original_port} is already in use.")
             print(f"Unsloth Studio will use port {port} instead.")
@@ -991,9 +981,7 @@ if __name__ == "__main__":
         sys.stderr.write("=" * 60 + "\n")
         traceback.print_exc(file = sys.stderr)
         sys.stderr.write("\n")
-        sys.stderr.write(
-            "If a package is missing, try re-running: unsloth studio setup\n"
-        )
+        sys.stderr.write("If a package is missing, try re-running: unsloth studio setup\n")
         sys.stderr.flush()
         sys.exit(1)
 
diff --git a/studio/backend/state/tool_policy.py b/studio/backend/state/tool_policy.py
index 9343a39806..9b0fc7d6cb 100644
--- a/studio/backend/state/tool_policy.py
+++ b/studio/backend/state/tool_policy.py
@@ -21,9 +21,7 @@ def get_tool_policy() -> Optional[bool]:
 
 def set_tool_policy(value: Optional[bool]) -> None:
     if value is not None and not isinstance(value, bool):
-        raise TypeError(
-            f"tool_policy must be Optional[bool], got {type(value).__name__}"
-        )
+        raise TypeError(f"tool_policy must be Optional[bool], got {type(value).__name__}")
     global _tool_policy
     _tool_policy = value
 
diff --git a/studio/backend/storage/mcp_servers_db.py b/studio/backend/storage/mcp_servers_db.py
index da2fa15423..9dd90a58bb 100644
--- a/studio/backend/storage/mcp_servers_db.py
+++ b/studio/backend/storage/mcp_servers_db.py
@@ -29,13 +29,9 @@ def _ensure_schema(conn: sqlite3.Connection) -> None:
         """
     )
     # use_oauth was added after the first release; backfill for pre-existing DBs.
-    cols = {
-        r["name"] for r in conn.execute("PRAGMA table_info(mcp_servers)").fetchall()
-    }
+    cols = {r["name"] for r in conn.execute("PRAGMA table_info(mcp_servers)").fetchall()}
     if "use_oauth" not in cols:
-        conn.execute(
-            "ALTER TABLE mcp_servers ADD COLUMN use_oauth INTEGER NOT NULL DEFAULT 0"
-        )
+        conn.execute("ALTER TABLE mcp_servers ADD COLUMN use_oauth INTEGER NOT NULL DEFAULT 0")
 
 
 def get_connection() -> sqlite3.Connection:
diff --git a/studio/backend/storage/providers_db.py b/studio/backend/storage/providers_db.py
index ca47fcbd80..3c6056fb8d 100644
--- a/studio/backend/storage/providers_db.py
+++ b/studio/backend/storage/providers_db.py
@@ -62,12 +62,7 @@ def get_connection() -> sqlite3.Connection:
     return conn
 
 
-def create_provider(
-    id: str,
-    provider_type: str,
-    display_name: str,
-    base_url: str,
-) -> None:
+def create_provider(id: str, provider_type: str, display_name: str, base_url: str) -> None:
     """Insert a new provider configuration."""
     now = datetime.now(timezone.utc).isoformat()
     conn = get_connection()
@@ -145,9 +140,7 @@ def list_providers() -> list[dict]:
     """List all provider configurations, ordered by creation time."""
     conn = get_connection()
     try:
-        rows = conn.execute(
-            "SELECT * FROM llm_providers ORDER BY created_at"
-        ).fetchall()
+        rows = conn.execute("SELECT * FROM llm_providers ORDER BY created_at").fetchall()
         return [dict(row) for row in rows]
     finally:
         conn.close()
diff --git a/studio/backend/storage/studio_db.py b/studio/backend/storage/studio_db.py
index 0175e54b35..5f0d6449d5 100644
--- a/studio/backend/storage/studio_db.py
+++ b/studio/backend/storage/studio_db.py
@@ -89,9 +89,7 @@ def _delete_project_workspace(project: dict) -> None:
     try:
         root_resolved = root.resolve(strict = False)
     except (OSError, RuntimeError, ValueError):
-        logger.warning(
-            "Skipping project workspace delete for invalid path %r", root_path
-        )
+        logger.warning("Skipping project workspace delete for invalid path %r", root_path)
         return
 
     project_id = str(project["id"])
@@ -155,9 +153,7 @@ def _ensure_schema(conn: sqlite3.Connection) -> None:
         )
         """
     )
-    existing_cols = {
-        row[1] for row in conn.execute("PRAGMA table_info(training_runs)").fetchall()
-    }
+    existing_cols = {row[1] for row in conn.execute("PRAGMA table_info(training_runs)").fetchall()}
     if "display_name" not in existing_cols:
         conn.execute("ALTER TABLE training_runs ADD COLUMN display_name TEXT")
     conn.execute(
@@ -177,9 +173,7 @@ def _ensure_schema(conn: sqlite3.Connection) -> None:
         )
         """
     )
-    conn.execute(
-        "CREATE INDEX IF NOT EXISTS idx_metrics_run_id ON training_metrics(run_id)"
-    )
+    conn.execute("CREATE INDEX IF NOT EXISTS idx_metrics_run_id ON training_metrics(run_id)")
     # Use COLLATE NOCASE on Windows so C:\Models and c:\models dedup via the
     # UNIQUE constraint.  On Linux/macOS (case-sensitive FS) keep the default
     # BINARY collation so /Models and /models remain distinct.
@@ -237,13 +231,9 @@ def _ensure_schema(conn: sqlite3.Connection) -> None:
     if "project_id" not in chat_thread_cols:
         conn.execute("ALTER TABLE chat_threads ADD COLUMN project_id TEXT")
     if "openai_code_exec_container_id" not in chat_thread_cols:
-        conn.execute(
-            "ALTER TABLE chat_threads ADD COLUMN openai_code_exec_container_id TEXT"
-        )
+        conn.execute("ALTER TABLE chat_threads ADD COLUMN openai_code_exec_container_id TEXT")
     if "anthropic_code_exec_container_id" not in chat_thread_cols:
-        conn.execute(
-            "ALTER TABLE chat_threads ADD COLUMN anthropic_code_exec_container_id TEXT"
-        )
+        conn.execute("ALTER TABLE chat_threads ADD COLUMN anthropic_code_exec_container_id TEXT")
     conn.execute(
         """
         CREATE TABLE IF NOT EXISTS chat_messages (
@@ -261,9 +251,7 @@ def _ensure_schema(conn: sqlite3.Connection) -> None:
     conn.execute(
         "CREATE INDEX IF NOT EXISTS idx_chat_threads_model_type_created_at ON chat_threads(model_type, created_at)"
     )
-    conn.execute(
-        "CREATE INDEX IF NOT EXISTS idx_chat_threads_pair_id ON chat_threads(pair_id)"
-    )
+    conn.execute("CREATE INDEX IF NOT EXISTS idx_chat_threads_pair_id ON chat_threads(pair_id)")
     conn.execute(
         "CREATE INDEX IF NOT EXISTS idx_chat_threads_project_id ON chat_threads(project_id)"
     )
@@ -513,9 +501,7 @@ def list_runs(limit: int = 50, offset: int = 0) -> dict:
                 try:
                     run["loss_sparkline"] = json.loads(sparkline)
                 except (json.JSONDecodeError, TypeError):
-                    logger.debug(
-                        "Failed to parse loss_sparkline for run %s", run.get("id")
-                    )
+                    logger.debug("Failed to parse loss_sparkline for run %s", run.get("id"))
                     run["loss_sparkline"] = None
             runs.append(run)
         return {"runs": runs, "total": total}
@@ -591,9 +577,7 @@ def get_resumable_run_by_output_dir(output_dir: str) -> Optional[dict]:
             try:
                 run["loss_sparkline"] = json.loads(sparkline)
             except (json.JSONDecodeError, TypeError):
-                logger.debug(
-                    "Failed to parse loss_sparkline for output_dir %s", output_dir
-                )
+                logger.debug("Failed to parse loss_sparkline for output_dir %s", output_dir)
                 run["loss_sparkline"] = None
         return run
     finally:
@@ -1130,9 +1114,7 @@ def _parse_chat_setting_json(key: str, value_json: str) -> tuple[bool, Any]:
         return False, None
 
 
-def _load_chat_settings_for_merge(
-    conn: sqlite3.Connection,
-) -> tuple[dict[str, Any], set[str]]:
+def _load_chat_settings_for_merge(conn: sqlite3.Connection) -> tuple[dict[str, Any], set[str]]:
     rows = conn.execute("SELECT key, value_json FROM chat_settings").fetchall()
     current: dict[str, Any] = {}
     corrupt: set[str] = set()
@@ -1159,9 +1141,7 @@ def _load_chat_settings_for_merge(
 
 
 def _raise_if_chat_message_thread_conflicts(
-    conn: sqlite3.Connection,
-    thread_id: str,
-    message_ids: list[str],
+    conn: sqlite3.Connection, thread_id: str, message_ids: list[str]
 ) -> None:
     unique_ids = list(dict.fromkeys(message_ids))
     if not unique_ids:
@@ -1270,12 +1250,8 @@ def sync_chat_messages(
                     m.get("parentId"),
                     m["role"],
                     json.dumps(m.get("content", [])),
-                    json.dumps(m.get("attachments"))
-                    if m.get("attachments") is not None
-                    else None,
-                    json.dumps(m.get("metadata"))
-                    if m.get("metadata") is not None
-                    else None,
+                    json.dumps(m.get("attachments")) if m.get("attachments") is not None else None,
+                    json.dumps(m.get("metadata")) if m.get("metadata") is not None else None,
                     int(m["createdAt"]),
                 )
                 for m in messages
@@ -1355,9 +1331,7 @@ def list_chat_messages_for_threads(thread_ids: list[str]) -> list[dict]:
 def get_app_setting(key: str, fallback = None):
     conn = get_connection()
     try:
-        row = conn.execute(
-            "SELECT value_json FROM app_settings WHERE key = ?", (key,)
-        ).fetchone()
+        row = conn.execute("SELECT value_json FROM app_settings WHERE key = ?", (key,)).fetchone()
         if row is None:
             return fallback
         return _json_loads(row["value_json"], fallback)
@@ -1382,9 +1356,7 @@ def upsert_app_settings(settings: dict[str, Any]) -> dict[str, Any]:
             [(key, json.dumps(value), now) for key, value in settings.items()],
         )
         conn.commit()
-        rows = conn.execute(
-            "SELECT key, value_json FROM app_settings ORDER BY key"
-        ).fetchall()
+        rows = conn.execute("SELECT key, value_json FROM app_settings ORDER BY key").fetchall()
         return {row["key"]: _json_loads(row["value_json"], None) for row in rows}
     finally:
         conn.close()
@@ -1393,9 +1365,7 @@ def upsert_app_settings(settings: dict[str, Any]) -> dict[str, Any]:
 def list_chat_settings() -> dict[str, Any]:
     conn = get_connection()
     try:
-        rows = conn.execute(
-            "SELECT key, value_json FROM chat_settings ORDER BY key"
-        ).fetchall()
+        rows = conn.execute("SELECT key, value_json FROM chat_settings ORDER BY key").fetchall()
         settings: dict[str, Any] = {}
         for row in rows:
             settings[row["key"]] = _json_loads(row["value_json"], None)
@@ -1426,9 +1396,7 @@ def upsert_chat_settings(settings: dict[str, Any]) -> dict[str, Any]:
         conn.close()
 
 
-def _deep_merge_settings(
-    current: dict[str, Any], updates: dict[str, Any]
-) -> dict[str, Any]:
+def _deep_merge_settings(current: dict[str, Any], updates: dict[str, Any]) -> dict[str, Any]:
     merged = dict(current)
     for key, value in updates.items():
         current_value = merged.get(key)
@@ -1449,9 +1417,7 @@ def upsert_chat_settings_merge(updates: dict[str, Any]) -> dict[str, Any]:
         conn.execute("BEGIN IMMEDIATE")
         current, corrupt = _load_chat_settings_for_merge(conn)
         unsafe_partial_keys = [
-            key
-            for key, value in updates.items()
-            if key in corrupt and isinstance(value, dict)
+            key for key, value in updates.items() if key in corrupt and isinstance(value, dict)
         ]
         if unsafe_partial_keys:
             conn.commit()
@@ -1496,9 +1462,7 @@ def list_chat_legacy_imports() -> list[str]:
     """
     conn = get_connection()
     try:
-        rows = conn.execute(
-            "SELECT legacy_thread_id FROM chat_legacy_imports"
-        ).fetchall()
+        rows = conn.execute("SELECT legacy_thread_id FROM chat_legacy_imports").fetchall()
         return [row[0] for row in rows]
     finally:
         conn.close()
diff --git a/studio/backend/tests/test_amd_apu_unified_memory.py b/studio/backend/tests/test_amd_apu_unified_memory.py
index e0b819d54b..104182a232 100644
--- a/studio/backend/tests/test_amd_apu_unified_memory.py
+++ b/studio/backend/tests/test_amd_apu_unified_memory.py
@@ -14,7 +14,12 @@ import pytest
 from core.inference.llama_cpp import LlamaCppBackend
 
 
-def _fake_torch(hip, archs, *, cuda_ok = True):
+def _fake_torch(
+    hip,
+    archs,
+    *,
+    cuda_ok = True,
+):
     t = types.ModuleType("torch")
     t.version = types.SimpleNamespace(hip = hip)
     t.cuda = types.SimpleNamespace(
diff --git a/studio/backend/tests/test_anthropic_citations_edge.py b/studio/backend/tests/test_anthropic_citations_edge.py
index be1b5f7922..6b10600847 100644
--- a/studio/backend/tests/test_anthropic_citations_edge.py
+++ b/studio/backend/tests/test_anthropic_citations_edge.py
@@ -80,8 +80,7 @@ def _capture(
         client = _make_client()
         try:
             async for line in client.stream_chat_completion(
-                messages = messages
-                or [{"role": "user", "content": "what color is grass?"}],
+                messages = messages or [{"role": "user", "content": "what color is grass?"}],
                 model = "claude-opus-4-7",
                 max_tokens = 64,
             ):
@@ -159,10 +158,7 @@ def _citation_payload(body: str) -> dict:
         except json.JSONDecodeError:
             continue
         tool_event = payload.get("_toolEvent") if isinstance(payload, dict) else None
-        if (
-            isinstance(tool_event, dict)
-            and tool_event.get("type") == "document_citations"
-        ):
+        if isinstance(tool_event, dict) and tool_event.get("type") == "document_citations":
             return tool_event
     raise AssertionError("document_citations event not parsed out of SSE body")
 
diff --git a/studio/backend/tests/test_anthropic_code_execution.py b/studio/backend/tests/test_anthropic_code_execution.py
index 5c88437d17..dd2f2eef6c 100644
--- a/studio/backend/tests/test_anthropic_code_execution.py
+++ b/studio/backend/tests/test_anthropic_code_execution.py
@@ -118,10 +118,7 @@ def test_code_execution_tool_appended_to_request_body(monkeypatch):
     tools = body.get("tools") or []
     # Opus 4.7 gets the newer date-pinned variant (`_20260120`) that
     # supports REPL state persistence + programmatic tool calling.
-    assert {
-        "type": "code_execution_20260120",
-        "name": "code_execution",
-    } in tools
+    assert {"type": "code_execution_20260120", "name": "code_execution"} in tools
     # No web_search entry when only code_execution is enabled.
     assert all("web_search" not in (t.get("type") or "") for t in tools)
     # Beta header still carries the documented flag; both `_20250825`
@@ -201,9 +198,7 @@ def test_no_code_execution_tool_when_pill_off(monkeypatch):
     assert all("code_execution" not in (t.get("type") or "") for t in tools)
     # Beta header must NOT mention code-execution when the tool isn't on
     # -- that flag is opt-in only.
-    assert "code-execution-2025-08-25" not in captured["headers"].get(
-        "anthropic-beta", ""
-    )
+    assert "code-execution-2025-08-25" not in captured["headers"].get("anthropic-beta", "")
 
 
 def test_bash_code_execution_emits_tool_start_and_end(monkeypatch):
@@ -277,11 +272,7 @@ def test_bash_code_execution_emits_tool_start_and_end(monkeypatch):
     assert start["tool_call_id"] == "srvtoolu_1"
     # `_server_tool: True` marks this as a provider-side synthetic
     # tool card for the frontend's history serializer.
-    assert start["arguments"] == {
-        "kind": "bash",
-        "command": "ls -la",
-        "_server_tool": True,
-    }
+    assert start["arguments"] == {"kind": "bash", "command": "ls -la", "_server_tool": True}
 
     assert end["type"] == "tool_end"
     assert end["tool_call_id"] == "srvtoolu_1"
@@ -308,8 +299,7 @@ def test_text_editor_create_emits_kind_and_status(monkeypatch):
             "delta": {
                 "type": "input_json_delta",
                 "partial_json": (
-                    '{"command": "create", "path": "new_file.txt", '
-                    '"file_text": "hi"}'
+                    '{"command": "create", "path": "new_file.txt", "file_text": "hi"}'
                 ),
             },
         },
diff --git a/studio/backend/tests/test_anthropic_compaction.py b/studio/backend/tests/test_anthropic_compaction.py
index 92b9280146..6da752eac4 100644
--- a/studio/backend/tests/test_anthropic_compaction.py
+++ b/studio/backend/tests/test_anthropic_compaction.py
@@ -40,7 +40,12 @@ def _make_client() -> ExternalProviderClient:
     )
 
 
-def _capture(monkeypatch, model: str, threshold, tools = None) -> dict:
+def _capture(
+    monkeypatch,
+    model: str,
+    threshold,
+    tools = None,
+) -> dict:
     captured: dict = {}
 
     def handler(request: httpx.Request) -> httpx.Response:
@@ -120,13 +125,9 @@ def test_supported_model_attaches_compaction_block_and_beta(monkeypatch):
 def test_threshold_clamped_to_50k_minimum(monkeypatch):
     # Below-min values get clamped UP so we don't 400 upstream.
     captured = _capture(monkeypatch, "claude-opus-4-7", 60_000)
-    assert (
-        captured["body"]["context_management"]["edits"][0]["trigger"]["value"] == 60_000
-    )
+    assert captured["body"]["context_management"]["edits"][0]["trigger"]["value"] == 60_000
     captured = _capture(monkeypatch, "claude-opus-4-7", 1)
-    assert (
-        captured["body"]["context_management"]["edits"][0]["trigger"]["value"] == 50_000
-    )
+    assert captured["body"]["context_management"]["edits"][0]["trigger"]["value"] == 50_000
 
 
 # ── beta header merge with code execution ────────────────────────────
@@ -151,10 +152,7 @@ def test_unsupported_model_silently_drops_compaction(monkeypatch):
     captured = _capture(monkeypatch, "claude-haiku-4-5-20251001", 150_000)
     assert "context_management" not in captured["body"]
     # The beta header must not carry compact-2026-01-12 either.
-    assert "compact-2026-01-12" not in captured["headers"].get(
-        "anthropic-beta",
-        "",
-    )
+    assert "compact-2026-01-12" not in captured["headers"].get("anthropic-beta", "")
 
 
 # ── omitted threshold leaves body untouched ─────────────────────────
@@ -163,10 +161,7 @@ def test_unsupported_model_silently_drops_compaction(monkeypatch):
 def test_omitted_threshold_no_body_field(monkeypatch):
     captured = _capture(monkeypatch, "claude-opus-4-7", None)
     assert "context_management" not in captured["body"]
-    assert "compact-2026-01-12" not in captured["headers"].get(
-        "anthropic-beta",
-        "",
-    )
+    assert "compact-2026-01-12" not in captured["headers"].get("anthropic-beta", "")
 
 
 # ── ChatCompletionRequest schema accepts sub-50k threshold ──────────
@@ -212,9 +207,7 @@ def test_chat_completion_request_accepts_sub_50k_compaction_threshold():
 # ── usage.iterations[] surfaces compaction tokens ──────────────────
 
 
-def test_message_delta_iterations_array_aggregates_compaction_tokens(
-    monkeypatch, capsys
-):
+def test_message_delta_iterations_array_aggregates_compaction_tokens(monkeypatch, capsys):
     # When Anthropic compacts mid-stream, the SSE message_delta usage
     # payload carries `iterations: [{type:"compaction", ...}, ...]`.
     # The top-level input_tokens / output_tokens only account for the
@@ -552,9 +545,7 @@ def test_build_external_messages_passes_compaction_for_anthropic_only():
             }
         )
     ]
-    out = _build_external_messages(
-        msgs, supports_vision = True, provider_type = "anthropic"
-    )
+    out = _build_external_messages(msgs, supports_vision = True, provider_type = "anthropic")
     assert len(out) == 1
     parts = out[0]["content"]
     assert parts[0] == {"type": "compaction", "content": "prior summary"}
@@ -582,9 +573,7 @@ def test_build_external_messages_strips_compaction_for_non_anthropic_providers()
         )
     ]
     for provider in ("openai", "deepseek", "mistral", "gemini", "kimi", "openrouter"):
-        out = _build_external_messages(
-            msgs, supports_vision = True, provider_type = provider
-        )
+        out = _build_external_messages(msgs, supports_vision = True, provider_type = provider)
         assert len(out) == 1, (provider, out)
         parts = out[0]["content"]
         types = [p.get("type") for p in parts if isinstance(p, dict)]
@@ -635,14 +624,10 @@ def test_build_external_messages_non_vision_anthropic_keeps_compaction():
             }
         )
     ]
-    out = _build_external_messages(
-        msgs, supports_vision = False, provider_type = "anthropic"
-    )
+    out = _build_external_messages(msgs, supports_vision = False, provider_type = "anthropic")
     parts = out[0]["content"]
     assert {"type": "compaction", "content": "prior summary"} in parts
     # Non-anthropic + non-vision -> compaction stripped, text collapsed
     # back to a string.
-    out2 = _build_external_messages(
-        msgs, supports_vision = False, provider_type = "deepseek"
-    )
+    out2 = _build_external_messages(msgs, supports_vision = False, provider_type = "deepseek")
     assert out2[0]["content"] == "answer", out2
diff --git a/studio/backend/tests/test_anthropic_fast_mode_and_refusal.py b/studio/backend/tests/test_anthropic_fast_mode_and_refusal.py
index e7e5ec64d4..94a1ca4e2c 100644
--- a/studio/backend/tests/test_anthropic_fast_mode_and_refusal.py
+++ b/studio/backend/tests/test_anthropic_fast_mode_and_refusal.py
@@ -58,7 +58,11 @@ def _refusal_sse() -> bytes:
     )
 
 
-def _capture(monkeypatch, sse: bytes = b"", **kwargs) -> tuple[dict, list[str]]:
+def _capture(
+    monkeypatch,
+    sse: bytes = b"",
+    **kwargs,
+) -> tuple[dict, list[str]]:
     """Install a MockTransport, drive one streamed call, return body+lines."""
     captured: dict = {}
 
diff --git a/studio/backend/tests/test_anthropic_fast_mode_edge.py b/studio/backend/tests/test_anthropic_fast_mode_edge.py
index 0052cb94ad..116f58f7f2 100644
--- a/studio/backend/tests/test_anthropic_fast_mode_edge.py
+++ b/studio/backend/tests/test_anthropic_fast_mode_edge.py
@@ -60,7 +60,11 @@ def _refusal_sse(model: str = "claude-opus-4-7") -> bytes:
     )
 
 
-def _capture(monkeypatch, sse: bytes = b"", **kwargs) -> tuple[dict, list[str]]:
+def _capture(
+    monkeypatch,
+    sse: bytes = b"",
+    **kwargs,
+) -> tuple[dict, list[str]]:
     """Install a MockTransport, drive one streamed call, return body+lines."""
     captured: dict = {}
 
@@ -266,9 +270,7 @@ def test_refusal_notice_appears_before_content_filter_chunk(monkeypatch):
     """The notice content delta must precede the finish_reason chunk."""
     _, lines = _capture(monkeypatch, sse = _refusal_sse(), model = "claude-opus-4-7")
     notice_idx = next(i for i, l in enumerate(lines) if "stopped by Anthropic" in l)
-    filter_idx = next(
-        i for i, l in enumerate(lines) if '"finish_reason": "content_filter"' in l
-    )
+    filter_idx = next(i for i, l in enumerate(lines) if '"finish_reason": "content_filter"' in l)
     assert notice_idx < filter_idx, (notice_idx, filter_idx, lines)
 
 
@@ -350,7 +352,6 @@ def test_fast_mode_prefix_tuple_matches_capability_doc(monkeypatch):
     """Tuple must exactly match the two families in the upstream docs:
     https://platform.claude.com/docs/en/build-with-claude/fast-mode."""
     from core.inference.external_provider import _ANTHROPIC_FAST_MODE_PREFIXES
-
     assert set(_ANTHROPIC_FAST_MODE_PREFIXES) == {
         "claude-opus-4-7",
         "claude-opus-4-6",
@@ -421,9 +422,7 @@ def test_usage_speed_propagates_to_final_usage_chunk_fast(monkeypatch):
 def test_usage_speed_propagates_to_final_usage_chunk_standard(monkeypatch):
     _, lines = _capture(monkeypatch, sse = _fast_speed_sse(speed = "standard"))
     parsed = [
-        json.loads(l[len("data: ") :])
-        for l in lines
-        if l.startswith("data: ") and '"usage"' in l
+        json.loads(l[len("data: ") :]) for l in lines if l.startswith("data: ") and '"usage"' in l
     ]
     speeds = [p["usage"].get("speed") for p in parsed if "usage" in p]
     assert "standard" in speeds, parsed
@@ -433,9 +432,7 @@ def test_usage_speed_absent_when_anthropic_does_not_report(monkeypatch):
     """Studio must not invent ``usage.speed`` when upstream omits it."""
     _, lines = _capture(monkeypatch)
     parsed = [
-        json.loads(l[len("data: ") :])
-        for l in lines
-        if l.startswith("data: ") and '"usage"' in l
+        json.loads(l[len("data: ") :]) for l in lines if l.startswith("data: ") and '"usage"' in l
     ]
     for p in parsed:
         usage = p.get("usage") or {}
diff --git a/studio/backend/tests/test_anthropic_messages.py b/studio/backend/tests/test_anthropic_messages.py
index dfabf27b68..ee19a96bca 100644
--- a/studio/backend/tests/test_anthropic_messages.py
+++ b/studio/backend/tests/test_anthropic_messages.py
@@ -372,10 +372,7 @@ class TestAnthropicMessagesToOpenAI:
         ]
         result = anthropic_messages_to_openai(msgs)
         parts = result[0]["content"]
-        assert parts[1] == {
-            "type": "image_url",
-            "image_url": {"url": "https://x/y.png"},
-        }
+        assert parts[1] == {"type": "image_url", "image_url": {"url": "https://x/y.png"}}
 
     def test_image_only_user_message_emits_no_text_part(self):
         msgs = [
@@ -440,12 +437,7 @@ class TestAnthropicMessagesToOpenAI:
         ]
         result = anthropic_messages_to_openai(msgs)
         parts = result[0]["content"]
-        assert [p["type"] for p in parts] == [
-            "text",
-            "image_url",
-            "text",
-            "image_url",
-        ]
+        assert [p["type"] for p in parts] == ["text", "image_url", "text", "image_url"]
         assert parts[0]["text"] == "before"
         assert parts[2]["text"] == "after"
         assert parts[1]["image_url"]["url"] == "data:image/png;base64,AA"
@@ -523,15 +515,10 @@ class TestAnthropicToolsToOpenAI:
             enabled_tools = ["python"],
         )
 
-        assert [tool["function"]["name"] for tool in result] == [
-            "web_search",
-            "python",
-        ]
+        assert [tool["function"]["name"] for tool in result] == ["web_search", "python"]
 
     def test_pydantic_model_input(self):
-        tool = AnthropicTool(
-            name = "test", description = "desc", input_schema = {"type": "object"}
-        )
+        tool = AnthropicTool(name = "test", description = "desc", input_schema = {"type": "object"})
         result = anthropic_tools_to_openai([tool])
         assert result[0]["function"]["name"] == "test"
 
@@ -631,12 +618,8 @@ class TestAnthropicStreamEmitter:
             }
         )
 
-        first_payloads = [
-            json.loads(event.split("data: ")[1]) for event in first_events
-        ]
-        second_payloads = [
-            json.loads(event.split("data: ")[1]) for event in second_events
-        ]
+        first_payloads = [json.loads(event.split("data: ")[1]) for event in first_events]
+        second_payloads = [json.loads(event.split("data: ")[1]) for event in second_events]
 
         tool_starts = [
             payload
@@ -652,9 +635,7 @@ class TestAnthropicStreamEmitter:
                 "index": tool_starts[0]["index"],
                 "delta": {
                     "type": "input_json_delta",
-                    "partial_json": json.dumps(
-                        {"code": ""}
-                    ),
+                    "partial_json": json.dumps({"code": ""}),
                 },
             }
         ]
@@ -811,9 +792,7 @@ class TestAnthropicToolNonStreaming:
 
         response = asyncio.run(_anthropic_tool_non_streaming(_run_gen, "msg_1", "m"))
         body = json.loads(response.body)
-        tool_blocks = [
-            block for block in body["content"] if block["type"] == "tool_use"
-        ]
+        tool_blocks = [block for block in body["content"] if block["type"] == "tool_use"]
 
         assert tool_blocks == [
             {
@@ -919,26 +898,14 @@ class TestAnthropicPassthroughEmitter:
         events1 = e.feed_chunk(
             {
                 "choices": [
-                    {
-                        "delta": {
-                            "tool_calls": [
-                                {"index": 0, "function": {"arguments": '{"cmd'}}
-                            ]
-                        }
-                    }
+                    {"delta": {"tool_calls": [{"index": 0, "function": {"arguments": '{"cmd'}}]}}
                 ]
             }
         )
         events2 = e.feed_chunk(
             {
                 "choices": [
-                    {
-                        "delta": {
-                            "tool_calls": [
-                                {"index": 0, "function": {"arguments": '": "ls"}'}}
-                            ]
-                        }
-                    }
+                    {"delta": {"tool_calls": [{"index": 0, "function": {"arguments": '": "ls"}'}}]}}
                 ]
             }
         )
@@ -1331,9 +1298,7 @@ class TestAnthropicMessagesToolRouting:
         assert exc.value.status_code == 400
         assert "Mixing Anthropic server tools" in exc.value.detail
 
-    def test_mixed_rejected_when_client_tool_name_collides_with_server_alias(
-        self, monkeypatch
-    ):
+    def test_mixed_rejected_when_client_tool_name_collides_with_server_alias(self, monkeypatch):
         # Regression: a client tool sharing a name with a mapped server
         # tool (e.g. user defines their own "web_search") must still
         # trigger the mixed-mode 400 — the post-name filter would
@@ -1392,9 +1357,7 @@ class TestAnthropicMessagesToolRouting:
         assert exc.value.status_code == 400
         assert "name" in exc.value.detail
 
-    def test_alias_named_client_tool_without_schema_rejected_with_400(
-        self, monkeypatch
-    ):
+    def test_alias_named_client_tool_without_schema_rejected_with_400(self, monkeypatch):
         # Regression: a typo'd client tool whose name happens to collide
         # with a Studio alias (e.g. user meant a custom "python" tool but
         # forgot input_schema) must surface a 400, not silently switch
diff --git a/studio/backend/tests/test_anthropic_tool_versions.py b/studio/backend/tests/test_anthropic_tool_versions.py
index 608977ab07..8f5d3f7f46 100644
--- a/studio/backend/tests/test_anthropic_tool_versions.py
+++ b/studio/backend/tests/test_anthropic_tool_versions.py
@@ -168,10 +168,7 @@ def test_outbound_body_uses_new_versions_on_opus_4_7(monkeypatch):
     # Beta header for code execution stays on the existing flag for
     # both _20250825 and _20260120; the API uses one header to gate
     # the feature, not the date.
-    assert "code-execution-2025-08-25" in captured["headers"].get(
-        "anthropic-beta",
-        "",
-    )
+    assert "code-execution-2025-08-25" in captured["headers"].get("anthropic-beta", "")
 
 
 def test_outbound_body_falls_back_on_haiku_4_5(monkeypatch):
diff --git a/studio/backend/tests/test_anthropic_web_fetch.py b/studio/backend/tests/test_anthropic_web_fetch.py
index 88a922e7eb..7d754872cd 100644
--- a/studio/backend/tests/test_anthropic_web_fetch.py
+++ b/studio/backend/tests/test_anthropic_web_fetch.py
@@ -104,11 +104,7 @@ def test_web_fetch_tool_appended_to_request_body(monkeypatch):
     body = captured["body"]
     tools = body.get("tools") or []
     # claude-opus-4-7 routes web_fetch to _20260209 (dynamic filtering).
-    assert {
-        "type": "web_fetch_20260209",
-        "name": "web_fetch",
-        "max_uses": 5,
-    } in tools
+    assert {"type": "web_fetch_20260209", "name": "web_fetch", "max_uses": 5} in tools
     # web_fetch is GA; no beta header is required.
     assert "web-fetch" not in captured["headers"].get("anthropic-beta", "")
 
@@ -183,9 +179,7 @@ def test_no_web_fetch_tool_when_pill_off(monkeypatch):
     _drive(run())
 
     tools = captured["body"].get("tools") or []
-    assert all(
-        t.get("type") not in ("web_fetch_20250910", "web_fetch_20260209") for t in tools
-    )
+    assert all(t.get("type") not in ("web_fetch_20250910", "web_fetch_20260209") for t in tools)
 
 
 # ── SSE translation ─────────────────────────────────────────────────
@@ -253,9 +247,7 @@ def test_web_fetch_success_emits_tool_start_and_end(monkeypatch):
         client = _make_client()
         return await _collect(
             client._stream_anthropic(
-                messages = [
-                    {"role": "user", "content": "Fetch https://example.com/article"}
-                ],
+                messages = [{"role": "user", "content": "Fetch https://example.com/article"}],
                 model = "claude-opus-4-7",
                 temperature = 0.7,
                 top_p = 0.95,
@@ -273,10 +265,7 @@ def test_web_fetch_success_emits_tool_start_and_end(monkeypatch):
     assert start["tool_call_id"] == "srvtoolu_wf1"
     # `_server_tool: True` marks this as a provider-side synthetic
     # tool card for the frontend's history serializer.
-    assert start["arguments"] == {
-        "url": "https://example.com/article",
-        "_server_tool": True,
-    }
+    assert start["arguments"] == {"url": "https://example.com/article", "_server_tool": True}
     assert end["type"] == "tool_end"
     assert end["tool_call_id"] == "srvtoolu_wf1"
     # The source pill uses Title / URL / snippet as parseSourcesFromResult expects.
diff --git a/studio/backend/tests/test_audio_token_detection.py b/studio/backend/tests/test_audio_token_detection.py
index a3ea7c89a7..bf1217b231 100644
--- a/studio/backend/tests/test_audio_token_detection.py
+++ b/studio/backend/tests/test_audio_token_detection.py
@@ -19,9 +19,7 @@ def _classify(tokens: list[str]) -> str | None:
 
 
 def test_gemma3n_audio_soft_token_is_audio_vlm():
-    assert (
-        _classify(["", "", ""]) == "audio_vlm"
-    )
+    assert _classify(["", "", ""]) == "audio_vlm"
 
 
 def test_gemma4_pipe_audio_token_is_audio_vlm():
diff --git a/studio/backend/tests/test_cached_gguf_routes.py b/studio/backend/tests/test_cached_gguf_routes.py
index 05aae8fb75..980de216db 100644
--- a/studio/backend/tests/test_cached_gguf_routes.py
+++ b/studio/backend/tests/test_cached_gguf_routes.py
@@ -66,9 +66,7 @@ def test_iter_gguf_paths_matches_extension_case_insensitively(tmp_path):
     assert result == ["Q4_K_M.gguf", "Q8_0.GGUF"]
 
 
-def test_list_cached_gguf_includes_non_suffix_repo_when_cache_contains_gguf(
-    monkeypatch, tmp_path
-):
+def test_list_cached_gguf_includes_non_suffix_repo_when_cache_contains_gguf(monkeypatch, tmp_path):
     repo = _repo(
         "HauhauCS/Gemma-4-E4B-Uncensored-HauhauCS-Aggressive",
         [_file("Q4_K_M.gguf", 5_000), _file("README.md", 10)],
@@ -130,9 +128,7 @@ def test_list_cached_gguf_skips_repos_without_positive_gguf_size(monkeypatch, tm
     assert result["cached"] == []
 
 
-def test_list_cached_gguf_keeps_largest_duplicate_repo_across_scans(
-    monkeypatch, tmp_path
-):
+def test_list_cached_gguf_keeps_largest_duplicate_repo_across_scans(monkeypatch, tmp_path):
     smaller = _repo(
         "Org/Dupe",
         [_file("Q4_K_M.gguf", 2_000)],
@@ -193,9 +189,7 @@ def test_list_cached_gguf_dedupes_shared_blobs_across_revisions(monkeypatch, tmp
     ]
 
 
-def test_list_cached_models_skips_non_suffix_repo_when_gguf_files_exist(
-    monkeypatch, tmp_path
-):
+def test_list_cached_models_skips_non_suffix_repo_when_gguf_files_exist(monkeypatch, tmp_path):
     mixed = _repo(
         "Org/MixedRepo",
         [
@@ -216,9 +210,7 @@ def test_list_cached_models_skips_non_suffix_repo_when_gguf_files_exist(
     assert result["cached"] == []
 
 
-def test_list_cached_gguf_includes_mixed_repo_with_gguf_and_safetensors(
-    monkeypatch, tmp_path
-):
+def test_list_cached_gguf_includes_mixed_repo_with_gguf_and_safetensors(monkeypatch, tmp_path):
     """Mirror of the _skips_ test: the mixed repo should still surface in
     cached-gguf so the picker can show it as a GGUF download."""
     mixed = _repo(
@@ -274,9 +266,7 @@ def test_list_cached_gguf_handles_none_size_on_disk(monkeypatch, tmp_path):
     ]
 
 
-def test_list_cached_gguf_skips_malformed_repo_without_wiping_response(
-    monkeypatch, tmp_path
-):
+def test_list_cached_gguf_skips_malformed_repo_without_wiping_response(monkeypatch, tmp_path):
     """One repo raising during classification must not poison the response
     for every other repo in the scan."""
 
@@ -357,17 +347,10 @@ def test_list_cached_models_includes_repo_with_only_mmproj_gguf(monkeypatch, tmp
 
     result = asyncio.run(models_route.list_cached_models(current_subject = "test-user"))
 
-    assert result["cached"] == [
-        {
-            "repo_id": "Org/MmprojAux",
-            "size_bytes": 15_000,
-        }
-    ]
+    assert result["cached"] == [{"repo_id": "Org/MmprojAux", "size_bytes": 15_000}]
 
 
-def test_list_cached_gguf_includes_vision_repo_with_main_gguf_and_mmproj(
-    monkeypatch, tmp_path
-):
+def test_list_cached_gguf_includes_vision_repo_with_main_gguf_and_mmproj(monkeypatch, tmp_path):
     """A vision-capable GGUF repo (main weight + mmproj adapter) is still
     a GGUF repo. The reported size is the main weight size; mmproj is
     excluded from the GGUF-size accounting because it is filtered out at
diff --git a/studio/backend/tests/test_chat_history_routes.py b/studio/backend/tests/test_chat_history_routes.py
index 62bcd05205..e3aeb4eb22 100644
--- a/studio/backend/tests/test_chat_history_routes.py
+++ b/studio/backend/tests/test_chat_history_routes.py
@@ -109,16 +109,13 @@ def test_chat_inference_settings_covers_frontend_persisted_fields():
         pytest.skip("frontend runtime.ts not present")
 
     with open(runtime_ts, encoding = "utf-8") as fh:
-        block = re.search(
-            r"interface InferenceParams \{(.*?)\n\}", fh.read(), re.DOTALL
-        )
+        block = re.search(r"interface InferenceParams \{(.*?)\n\}", fh.read(), re.DOTALL)
     assert block, "InferenceParams interface not found in runtime.ts"
     persisted = set(re.findall(r"^\s*(\w+)\??:", block.group(1), re.M)) - {"checkpoint"}
 
     backend = set(chat_history.ChatInferenceSettings.model_fields)
     assert persisted == backend, (
-        f"schema drift: frontend-only {persisted - backend}, "
-        f"backend-only {backend - persisted}"
+        f"schema drift: frontend-only {persisted - backend}, " f"backend-only {backend - persisted}"
     )
 
 
@@ -168,7 +165,6 @@ def test_record_import_ledger_returns_accepted_and_inserted(monkeypatch):
 
 def test_record_import_ledger_rejects_oversize_payload():
     from pydantic import ValidationError
-
     with pytest.raises(ValidationError):
         chat_history.ChatImportLedgerRecordRequest(
             threadIds = [f"id-{i}" for i in range(10_001)],
diff --git a/studio/backend/tests/test_chat_history_storage.py b/studio/backend/tests/test_chat_history_storage.py
index e88cac3276..b79f8f8119 100644
--- a/studio/backend/tests/test_chat_history_storage.py
+++ b/studio/backend/tests/test_chat_history_storage.py
@@ -13,7 +13,11 @@ import pytest
 from storage import studio_db
 
 
-def _reset_studio_db(tmp_path, monkeypatch, projects_home = None):
+def _reset_studio_db(
+    tmp_path,
+    monkeypatch,
+    projects_home = None,
+):
     monkeypatch.setenv("UNSLOTH_STUDIO_HOME", str(tmp_path))
     monkeypatch.setenv(
         "UNSLOTH_STUDIO_PROJECTS_HOME",
@@ -105,10 +109,7 @@ def test_sync_chat_messages_upserts_without_pruning(tmp_path, monkeypatch):
     assert by_id["msg-2"]["content"] == [{"type": "text", "text": "updated text"}]
 
 
-def test_chat_projects_delete_cascades_threads_and_messages(
-    tmp_path,
-    monkeypatch,
-):
+def test_chat_projects_delete_cascades_threads_and_messages(tmp_path, monkeypatch):
     _reset_studio_db(tmp_path, monkeypatch)
     project = studio_db.upsert_chat_project(_project())
     assert project["rootPath"].startswith(str(tmp_path / "Projects"))
@@ -231,23 +232,16 @@ def test_settings_merge_atomic_under_concurrency(tmp_path, monkeypatch):
 
 def test_settings_merge_preserves_nested_keys(tmp_path, monkeypatch):
     _reset_studio_db(tmp_path, monkeypatch)
-    studio_db.upsert_chat_settings_merge(
-        {"inferenceParams": {"temperature": 0.5, "topP": 0.8}}
-    )
+    studio_db.upsert_chat_settings_merge({"inferenceParams": {"temperature": 0.5, "topP": 0.8}})
     studio_db.upsert_chat_settings_merge({"inferenceParams": {"temperature": 0.9}})
 
     params = studio_db.list_chat_settings()["inferenceParams"]
     assert params == {"temperature": 0.9, "topP": 0.8}
 
 
-def test_settings_merge_quarantines_corrupt_json_and_rejects_partial_patch(
-    tmp_path,
-    monkeypatch,
-):
+def test_settings_merge_quarantines_corrupt_json_and_rejects_partial_patch(tmp_path, monkeypatch):
     _reset_studio_db(tmp_path, monkeypatch)
-    studio_db.upsert_chat_settings_merge(
-        {"inferenceParams": {"temperature": 0.5, "topP": 0.8}}
-    )
+    studio_db.upsert_chat_settings_merge({"inferenceParams": {"temperature": 0.5, "topP": 0.8}})
     conn = studio_db.get_connection()
     try:
         conn.execute(
@@ -295,9 +289,7 @@ def test_settings_merge_replaces_corrupt_scalar_after_quarantine(tmp_path, monke
     assert settings["autoTitle"] is True
     conn = studio_db.get_connection()
     try:
-        quarantined = conn.execute(
-            "SELECT key, reason FROM chat_settings_quarantine"
-        ).fetchall()
+        quarantined = conn.execute("SELECT key, reason FROM chat_settings_quarantine").fetchall()
     finally:
         conn.close()
     assert [(row["key"], row["reason"]) for row in quarantined] == [
@@ -353,11 +345,7 @@ def test_legacy_imports_records_and_lists(tmp_path, monkeypatch):
     )
     assert accepted == 3
     assert inserted == 3
-    assert set(studio_db.list_chat_legacy_imports()) == {
-        "legacy-a",
-        "legacy-b",
-        "legacy-c",
-    }
+    assert set(studio_db.list_chat_legacy_imports()) == {"legacy-a", "legacy-b", "legacy-c"}
 
 
 def test_legacy_imports_is_idempotent(tmp_path, monkeypatch):
@@ -371,11 +359,7 @@ def test_legacy_imports_is_idempotent(tmp_path, monkeypatch):
     assert (accepted1, inserted1) == (2, 2)
     # legacy-b is already in the ledger, only legacy-c is genuinely new.
     assert (accepted2, inserted2) == (2, 1)
-    assert set(studio_db.list_chat_legacy_imports()) == {
-        "legacy-a",
-        "legacy-b",
-        "legacy-c",
-    }
+    assert set(studio_db.list_chat_legacy_imports()) == {"legacy-a", "legacy-b", "legacy-c"}
 
 
 def test_legacy_imports_dedups_input(tmp_path, monkeypatch):
diff --git a/studio/backend/tests/test_cleanup_cancelled_checkpoints.py b/studio/backend/tests/test_cleanup_cancelled_checkpoints.py
index 0d09f027cf..3bb60336eb 100644
--- a/studio/backend/tests/test_cleanup_cancelled_checkpoints.py
+++ b/studio/backend/tests/test_cleanup_cancelled_checkpoints.py
@@ -130,7 +130,6 @@ def test_symlinked_output_dir_skipped(outputs_setup):
 
 def test_missing_output_dir_is_noop(outputs_setup):
     from core.training.training import _cleanup_cancelled_checkpoints
-
     _cleanup_cancelled_checkpoints(outputs_setup / "does-not-exist")
     # Should not raise; nothing to assert beyond non-failure.
 
diff --git a/studio/backend/tests/test_cpu_threads.py b/studio/backend/tests/test_cpu_threads.py
index 1224941622..b51d2bfb7d 100644
--- a/studio/backend/tests/test_cpu_threads.py
+++ b/studio/backend/tests/test_cpu_threads.py
@@ -63,9 +63,7 @@ def test_cpu_thread_cap_is_opt_in(raw):
 
 
 # Anything that is not a positive integer raises a clear ValueError.
-@pytest.mark.parametrize(
-    "raw", ["zero", "0", "-3", "1.5", "abc", "8a", "0x4", "1e3", "4 0"]
-)
+@pytest.mark.parametrize("raw", ["zero", "0", "-3", "1.5", "abc", "8a", "0x4", "1e3", "4 0"])
 def test_cpu_thread_cap_requires_positive_integer(raw):
     with pytest.raises(ValueError, match = "must be a positive integer"):
         configure_cpu_threads({"UNSLOTH_CPU_THREADS": raw})
diff --git a/studio/backend/tests/test_dataset_upload_limits.py b/studio/backend/tests/test_dataset_upload_limits.py
index 0991059318..dc6030edbf 100644
--- a/studio/backend/tests/test_dataset_upload_limits.py
+++ b/studio/backend/tests/test_dataset_upload_limits.py
@@ -40,9 +40,7 @@ def isolate_upload_dir(tmp_path, monkeypatch):
 def test_dataset_upload_under_configured_cap_succeeds(isolate_upload_dir):
     upload = FakeUploadFile("sample.csv", [b"a,b\n1,2\n"])
     response = asyncio.run(
-        datasets_route.upload_dataset(
-            cast(UploadFile, upload), current_subject = "test-user"
-        )
+        datasets_route.upload_dataset(cast(UploadFile, upload), current_subject = "test-user")
     )
     stored = Path(response.stored_path)
     assert response.filename == "sample.csv"
@@ -58,9 +56,7 @@ def test_dataset_upload_over_configured_cap_removes_partial_file(isolate_upload_
     )
     with pytest.raises(HTTPException) as exc:
         asyncio.run(
-            datasets_route.upload_dataset(
-                cast(UploadFile, upload), current_subject = "test-user"
-            )
+            datasets_route.upload_dataset(cast(UploadFile, upload), current_subject = "test-user")
         )
     assert exc.value.status_code == 413
     assert "Maximum is 1MB" in exc.value.detail
diff --git a/studio/backend/tests/test_desktop_auth.py b/studio/backend/tests/test_desktop_auth.py
index 3d01342a5c..219d64145f 100644
--- a/studio/backend/tests/test_desktop_auth.py
+++ b/studio/backend/tests/test_desktop_auth.py
@@ -51,12 +51,8 @@ def auth_client():
 
 
 def data_recipe_jobs_module():
-    route_path = (
-        Path(__file__).resolve().parents[1] / "routes" / "data_recipe" / "jobs.py"
-    )
-    spec = importlib.util.spec_from_file_location(
-        "_desktop_data_recipe_jobs", route_path
-    )
+    route_path = Path(__file__).resolve().parents[1] / "routes" / "data_recipe" / "jobs.py"
+    spec = importlib.util.spec_from_file_location("_desktop_data_recipe_jobs", route_path)
     jobs_route = importlib.util.module_from_spec(spec)
     assert spec.loader is not None
     spec.loader.exec_module(jobs_route)
@@ -265,9 +261,7 @@ def test_consume_refresh_token_concurrent_only_one_succeeds(tmp_path, monkeypatc
         results = list(pool.map(attempt, range(workers)))
 
     successes = [r for r in results if r is not None]
-    assert (
-        len(successes) == 1
-    ), f"expected exactly one consumer to win, got {len(successes)}"
+    assert len(successes) == 1, f"expected exactly one consumer to win, got {len(successes)}"
     assert successes[0] == (storage.DEFAULT_ADMIN_USERNAME, False)
 
 
@@ -285,9 +279,7 @@ def test_desktop_session_uses_real_admin_identity_for_api_keys():
     seed_user(must_change_password = True)
     raw = storage.create_desktop_secret()
     client = auth_client()
-    token = client.post("/api/auth/desktop-login", json = {"secret": raw}).json()[
-        "access_token"
-    ]
+    token = client.post("/api/auth/desktop-login", json = {"secret": raw}).json()["access_token"]
 
     response = client.post(
         "/api/auth/api-keys",
@@ -322,9 +314,7 @@ def test_local_recipe_token_authenticates_as_admin_for_desktop_user(loaded_local
         scheme = "Bearer",
         credentials = local_token,
     )
-    assert (
-        asyncio.run(get_current_subject(credentials)) == storage.DEFAULT_ADMIN_USERNAME
-    )
+    assert asyncio.run(get_current_subject(credentials)) == storage.DEFAULT_ADMIN_USERNAME
 
 
 def test_local_recipe_token_authenticates_as_admin_for_web_user(loaded_local_model):
@@ -345,9 +335,7 @@ def test_local_recipe_token_authenticates_as_admin_for_web_user(loaded_local_mod
         scheme = "Bearer",
         credentials = local_token,
     )
-    assert (
-        asyncio.run(get_current_subject(credentials)) == storage.DEFAULT_ADMIN_USERNAME
-    )
+    assert asyncio.run(get_current_subject(credentials)) == storage.DEFAULT_ADMIN_USERNAME
 
 
 def test_desktop_login_rejects_invalid_secret():
@@ -480,8 +468,7 @@ def test_health_response_reports_desktop_capability_fields(monkeypatch):
 
 
 def test_provision_desktop_auth_writes_secret_and_creates_db_without_backend_deps(
-    tmp_path,
-    monkeypatch,
+    tmp_path, monkeypatch
 ):
     auth_dir = tmp_path / "auth"
     auth_dir.mkdir()
@@ -536,12 +523,9 @@ if result.exit_code != 0:
             """
         ).fetchone()
         app_secrets = {
-            row["key"]: row["value"]
-            for row in conn.execute("SELECT key, value FROM app_secrets")
-        }
-        refresh_columns = {
-            row["name"] for row in conn.execute("PRAGMA table_info(refresh_tokens)")
+            row["key"]: row["value"] for row in conn.execute("SELECT key, value FROM app_secrets")
         }
+        refresh_columns = {row["name"] for row in conn.execute("PRAGMA table_info(refresh_tokens)")}
     finally:
         conn.close()
 
@@ -633,9 +617,7 @@ def test_update_password_clears_desktop_secret():
     raw = storage.create_desktop_secret()
     assert storage.validate_desktop_secret(raw) == storage.DEFAULT_ADMIN_USERNAME
 
-    changed = storage.update_password(
-        storage.DEFAULT_ADMIN_USERNAME, "new-admin-password"
-    )
+    changed = storage.update_password(storage.DEFAULT_ADMIN_USERNAME, "new-admin-password")
     assert changed is True
     assert storage.validate_desktop_secret(raw) is None
 
@@ -651,11 +633,7 @@ def test_update_password_on_unknown_user_leaves_desktop_secret_intact():
 
 def test_desktop_auth_provision_has_bounded_timeout():
     rs_path = (
-        Path(__file__).resolve().parents[3]
-        / "studio"
-        / "src-tauri"
-        / "src"
-        / "desktop_auth.rs"
+        Path(__file__).resolve().parents[3] / "studio" / "src-tauri" / "src" / "desktop_auth.rs"
     )
     src = rs_path.read_text()
     start = src.index("async fn provision_desktop_auth(")
diff --git a/studio/backend/tests/test_detect_mmproj_file.py b/studio/backend/tests/test_detect_mmproj_file.py
index cdb73448be..9487db1e5b 100644
--- a/studio/backend/tests/test_detect_mmproj_file.py
+++ b/studio/backend/tests/test_detect_mmproj_file.py
@@ -132,10 +132,7 @@ def test_family_token_mistral_does_not_match_ministral():
     assert _detect_family_token("Ministral-3-8B-Instruct-2512-BF16.gguf") == "ministral"
     assert _detect_family_token("Mistral-7B-Instruct-v0.3.gguf") == "mistral"
     assert _detect_family_token("Magistral-Small-2506-BF16.gguf") == "magistral"
-    assert (
-        _detect_family_token("Devstral-Small-2-24B-Instruct-2512-BF16.gguf")
-        == "devstral"
-    )
+    assert _detect_family_token("Devstral-Small-2-24B-Instruct-2512-BF16.gguf") == "devstral"
 
 
 def test_family_token_picks_leftmost_when_multiple_present():
@@ -160,9 +157,7 @@ def test_family_token_new_families_recognised():
 
 def test_blocks_cross_family_for_new_token_pair(tmp_path: Path):
     """Nemotron weight + lone Gemma projector returns None."""
-    model = _touch(
-        tmp_path / "NVIDIA-Nemotron-3-Nano-Omni-30B-A3B-Reasoning-MXFP4_MOE.gguf"
-    )
+    model = _touch(tmp_path / "NVIDIA-Nemotron-3-Nano-Omni-30B-A3B-Reasoning-MXFP4_MOE.gguf")
     _touch(tmp_path / "gemma-4-26B-A4B-it.mmproj-q8_0.gguf")
     assert detect_mmproj_file(str(model)) is None
 
diff --git a/studio/backend/tests/test_export_log_cursor.py b/studio/backend/tests/test_export_log_cursor.py
index 734ca522c9..253922ce74 100644
--- a/studio/backend/tests/test_export_log_cursor.py
+++ b/studio/backend/tests/test_export_log_cursor.py
@@ -66,11 +66,14 @@ sys.modules.setdefault("utils.paths", _utils_paths_stub)
 def orchestrator():
     """Fresh ExportOrchestrator with only the log-buffer state exercised."""
     from core.export.orchestrator import ExportOrchestrator
-
     return ExportOrchestrator()
 
 
-def _append(orch, line: str, stream: str = "stdout") -> None:
+def _append(
+    orch,
+    line: str,
+    stream: str = "stdout",
+) -> None:
     """Shortcut for simulating a worker log message."""
     orch._append_log({"type": "log", "stream": stream, "line": line, "ts": 0.0})
 
diff --git a/studio/backend/tests/test_external_provider_usage_chunk.py b/studio/backend/tests/test_external_provider_usage_chunk.py
index 82c641d049..afeb26e9e9 100644
--- a/studio/backend/tests/test_external_provider_usage_chunk.py
+++ b/studio/backend/tests/test_external_provider_usage_chunk.py
@@ -191,11 +191,7 @@ def _usage_chunks(lines: list[str]) -> list[dict]:
             parsed = json.loads(payload)
         except json.JSONDecodeError:
             continue
-        if (
-            isinstance(parsed, dict)
-            and "usage" in parsed
-            and parsed.get("choices") == []
-        ):
+        if isinstance(parsed, dict) and "usage" in parsed and parsed.get("choices") == []:
             out.append(parsed["usage"])
     return out
 
@@ -256,13 +252,9 @@ def test_anthropic_stream_emits_usage_chunk_before_done(monkeypatch):
 
     # Usage chunk must come before [DONE].
     data_lines = [ln for ln in lines if ln.startswith("data:")]
-    done_idx = next(
-        i for i, ln in enumerate(data_lines) if ln.strip().endswith("[DONE]")
-    )
+    done_idx = next(i for i, ln in enumerate(data_lines) if ln.strip().endswith("[DONE]"))
     usage_idx = next(
-        i
-        for i, ln in enumerate(data_lines)
-        if '"usage":' in ln and '"choices": []' in ln
+        i for i, ln in enumerate(data_lines) if '"usage":' in ln and '"choices": []' in ln
     )
     assert usage_idx < done_idx
 
diff --git a/studio/backend/tests/test_frontend_resolution.py b/studio/backend/tests/test_frontend_resolution.py
index 2b49763386..3cdc755f7f 100644
--- a/studio/backend/tests/test_frontend_resolution.py
+++ b/studio/backend/tests/test_frontend_resolution.py
@@ -130,13 +130,7 @@ def test_resolver_falls_back_to_windows_layout_site_packages(tmp_path, monkeypat
     alongside the POSIX `lib/python*/site-packages` path."""
     studio_home = tmp_path / "studio_home"
     sp_dist = (
-        studio_home
-        / "unsloth_studio"
-        / "Lib"
-        / "site-packages"
-        / "studio"
-        / "frontend"
-        / "dist"
+        studio_home / "unsloth_studio" / "Lib" / "site-packages" / "studio" / "frontend" / "dist"
     )
     sp_dist.mkdir(parents = True)
     (sp_dist / "index.html").write_text("", encoding = "utf-8")
diff --git a/studio/backend/tests/test_gemini_provider.py b/studio/backend/tests/test_gemini_provider.py
index 4dc97302e2..01ef2e16fd 100644
--- a/studio/backend/tests/test_gemini_provider.py
+++ b/studio/backend/tests/test_gemini_provider.py
@@ -545,9 +545,7 @@ def test_finish_reason_swaps_to_tool_calls_when_function_call_emitted(monkeypatc
                 {
                     "content": {
                         "role": "model",
-                        "parts": [
-                            {"functionCall": {"name": "lookup", "args": {"k": "v"}}}
-                        ],
+                        "parts": [{"functionCall": {"name": "lookup", "args": {"k": "v"}}}],
                     },
                     "finishReason": "STOP",
                 }
@@ -631,9 +629,7 @@ def test_thought_signature_emitted_in_tool_call_delta(monkeypatch):
     deltas = [
         tc
         for c in chunks
-        for tc in (c.get("choices", [{}])[0].get("delta", {}) or {}).get(
-            "tool_calls", []
-        )
+        for tc in (c.get("choices", [{}])[0].get("delta", {}) or {}).get("tool_calls", [])
     ]
     assert deltas, chunks
     sig = deltas[0].get("extra_content", {}).get("google", {}).get("thought_signature")
@@ -687,10 +683,7 @@ def test_image_generation_tool_on_image_model_drops_text_tools(monkeypatch):
         ],
     )
     assert "tools" not in captured["body"], captured["body"]
-    assert captured["body"]["generationConfig"].get("responseModalities") == [
-        "TEXT",
-        "IMAGE",
-    ]
+    assert captured["body"]["generationConfig"].get("responseModalities") == ["TEXT", "IMAGE"]
 
 
 def test_prompt_feedback_block_reason_surfaces_as_error(monkeypatch):
@@ -704,9 +697,7 @@ def test_prompt_feedback_block_reason_surfaces_as_error(monkeypatch):
     chunks = _parse_chunks(_collect(monkeypatch, sse))
     error_chunks = [c for c in chunks if "error" in c]
     assert error_chunks, chunks
-    assert "SAFETY" in (
-        error_chunks[0].get("error", {}).get("message") or ""
-    ), error_chunks
+    assert "SAFETY" in (error_chunks[0].get("error", {}).get("message") or ""), error_chunks
 
 
 def test_usage_chunk_includes_thoughts_tokens(monkeypatch):
@@ -794,10 +785,7 @@ def test_image_model_sets_response_modalities(monkeypatch):
         model = "gemini-2.5-flash-image",
         enabled_tools = ["image_generation"],
     )
-    assert captured["body"]["generationConfig"]["responseModalities"] == [
-        "TEXT",
-        "IMAGE",
-    ]
+    assert captured["body"]["generationConfig"]["responseModalities"] == ["TEXT", "IMAGE"]
 
 
 def test_image_generation_tool_sets_response_modalities_on_image_model(monkeypatch):
@@ -810,10 +798,7 @@ def test_image_generation_tool_sets_response_modalities_on_image_model(monkeypat
         model = "gemini-2.5-flash-image",
         enabled_tools = ["image_generation"],
     )
-    assert captured["body"]["generationConfig"]["responseModalities"] == [
-        "TEXT",
-        "IMAGE",
-    ]
+    assert captured["body"]["generationConfig"]["responseModalities"] == ["TEXT", "IMAGE"]
 
 
 def test_image_response_emits_image_b64_tool_event(monkeypatch):
@@ -1001,9 +986,7 @@ def test_parallel_function_calls_get_distinct_tool_call_indices(monkeypatch):
         )
     ]
     assert len(tool_call_chunks) == 2, tool_call_chunks
-    indices = [
-        c["choices"][0]["delta"]["tool_calls"][0]["index"] for c in tool_call_chunks
-    ]
+    indices = [c["choices"][0]["delta"]["tool_calls"][0]["index"] for c in tool_call_chunks]
     assert indices == [0, 1], indices
 
 
@@ -1050,10 +1033,7 @@ def test_function_call_ids_forwarded_into_gemini_function_call_part(monkeypatch)
     call_ids = [p["functionCall"]["id"] for p in assistant_parts if "functionCall" in p]
     assert call_ids == ["call_alpha", "call_beta"], assistant_parts
     response_ids = [
-        p["functionResponse"]["id"]
-        for c in contents
-        for p in c["parts"]
-        if "functionResponse" in p
+        p["functionResponse"]["id"] for c in contents for p in c["parts"] if "functionResponse" in p
     ]
     assert response_ids == ["call_alpha", "call_beta"], contents
 
@@ -1131,9 +1111,7 @@ def test_code_execution_parts_translate_to_code_execution_tool_events(monkeypatc
         if e.get("type") == "tool_start" and e.get("tool_name") == "code_execution"
     ]
     code_ends = [
-        e
-        for e in tool_events
-        if e.get("type") == "tool_end" and "4" in str(e.get("result", ""))
+        e for e in tool_events if e.get("type") == "tool_end" and "4" in str(e.get("result", ""))
     ]
     assert len(code_starts) == 1, tool_events
     assert code_starts[0]["arguments"]["code"] == "print(2+2)"
@@ -1277,10 +1255,7 @@ def test_vision_data_url_translates_to_inline_data(monkeypatch):
     parts = captured["body"]["contents"][0]["parts"]
     inline_parts = [p for p in parts if "inlineData" in p]
     assert len(inline_parts) == 1, parts
-    assert inline_parts[0]["inlineData"] == {
-        "mimeType": "image/jpeg",
-        "data": fake,
-    }
+    assert inline_parts[0]["inlineData"] == {"mimeType": "image/jpeg", "data": fake}
 
 
 # ── finish reason mapping ────────────────────────────────────────────
@@ -1412,14 +1387,8 @@ def test_custom_gemini_proxy_uses_openai_dispatch():
         )
         assert client._is_openai_compatible() is True, base
         headers = client._auth_headers()
-        assert "x-goog-api-key" not in {k.lower() for k in headers}, (
-            base,
-            headers,
-        )
-        assert headers["Authorization"] == "Bearer AIza-test-key", (
-            base,
-            headers,
-        )
+        assert "x-goog-api-key" not in {k.lower() for k in headers}, (base, headers)
+        assert headers["Authorization"] == "Bearer AIza-test-key", (base, headers)
 
 
 def test_google_hosted_gemini_still_uses_native_dispatch():
@@ -1493,9 +1462,7 @@ def test_text_model_image_generation_tool_silently_dropped(monkeypatch):
     assert "responseModalities" not in gc, gc
 
 
-def test_empty_text_part_with_thought_signature_emits_extra_content(
-    monkeypatch,
-):
+def test_empty_text_part_with_thought_signature_emits_extra_content(monkeypatch):
     """Gemini 3 can ship a content-free fragment whose only payload is
     `thoughtSignature`. The translator must still surface that signature
     on a delta.extra_content envelope so the next turn can replay it."""
@@ -1584,7 +1551,11 @@ def test_remote_image_url_downloads_and_inlines_as_base64(monkeypatch):
     inline them as base64 inlineData."""
     image_bytes = b"FAKEPNGBYTES"
 
-    async def fake_fetch(url, fallback_mime, max_bytes = None):
+    async def fake_fetch(
+        url,
+        fallback_mime,
+        max_bytes = None,
+    ):
         assert url == "https://cdn.example.com/diagram.png"
         return ("image/png", base64.b64encode(image_bytes).decode("ascii"))
 
@@ -1620,7 +1591,11 @@ def test_remote_image_url_dropped_when_fetch_returns_none(monkeypatch):
     image part is silently dropped instead of forwarding raw bytes
     or a fileData fallback."""
 
-    async def fake_fetch_reject(url, fallback_mime, max_bytes = None):
+    async def fake_fetch_reject(
+        url,
+        fallback_mime,
+        max_bytes = None,
+    ):
         return None
 
     monkeypatch.setattr(ep_mod, "_safe_fetch_image_for_gemini", fake_fetch_reject)
@@ -1677,9 +1652,7 @@ def test_safe_fetch_image_rejects_resolved_private_host(monkeypatch):
 
     monkeypatch.setattr(socket, "getaddrinfo", fake_getaddrinfo)
     res = asyncio.new_event_loop().run_until_complete(
-        ep_mod._safe_fetch_image_for_gemini(
-            "https://internal.example/x.png", "image/png"
-        )
+        ep_mod._safe_fetch_image_for_gemini("https://internal.example/x.png", "image/png")
     )
     assert res is None
 
@@ -1753,9 +1726,7 @@ def test_youtube_and_files_api_uris_stay_as_file_data(monkeypatch):
     parts = captured["body"]["contents"][-1]["parts"]
     file_uris = [p["fileData"]["fileUri"] for p in parts if "fileData" in p]
     assert "https://www.youtube.com/watch?v=abc123" in file_uris, parts
-    assert (
-        "https://generativelanguage.googleapis.com/v1beta/files/abc" in file_uris
-    ), parts
+    assert "https://generativelanguage.googleapis.com/v1beta/files/abc" in file_uris, parts
 
 
 def test_tool_use_prompt_tokens_added_to_input_tokens(monkeypatch):
@@ -1947,9 +1918,7 @@ def test_inline_image_tool_end_carries_thought_signature(monkeypatch):
     )
     chunks = _parse_chunks(lines)
     tool_events = [c["_toolEvent"] for c in chunks if "_toolEvent" in c]
-    image_ends = [
-        e for e in tool_events if e.get("type") == "tool_end" and e.get("image_b64")
-    ]
+    image_ends = [e for e in tool_events if e.get("type") == "tool_end" and e.get("image_b64")]
     assert image_ends, tool_events
     assert image_ends[0]["google"]["thought_signature"] == "SIG-IMG"
     # Multi-turn image edit must replay the original inlineData part with
@@ -2016,9 +1985,7 @@ def test_code_execution_plot_attaches_inline_image_native_part(monkeypatch):
     chunks = _parse_chunks(lines)
     tool_events = [c["_toolEvent"] for c in chunks if "_toolEvent" in c]
     code_ends = [
-        e
-        for e in tool_events
-        if e.get("type") == "tool_end" and e.get("tool_call_id") == "code_a"
+        e for e in tool_events if e.get("type") == "tool_end" and e.get("tool_call_id") == "code_a"
     ]
     # Two tool_end events on the same id: one for codeExecutionResult,
     # one merging in the inlineData plot. The plot one must carry the
@@ -2065,9 +2032,7 @@ def test_text_chunk_carries_thought_signature(monkeypatch):
     lines = _collect(monkeypatch, sse)
     chunks = _parse_chunks(lines)
     text_chunks = [
-        c
-        for c in chunks
-        if c.get("choices") and c["choices"][0]["delta"].get("content") == "hello"
+        c for c in chunks if c.get("choices") and c["choices"][0]["delta"].get("content") == "hello"
     ]
     assert text_chunks, chunks
     extra = text_chunks[0]["choices"][0]["delta"].get("extra_content")
@@ -2246,8 +2211,7 @@ def test_code_execution_tool_call_replays_native_executable_code(monkeypatch):
     assert "executableCode" in native_keys, parts
     assert "codeExecutionResult" in native_keys, parts
     assert not any(
-        "functionCall" in p
-        and (p["functionCall"] or {}).get("name") == "code_execution"
+        "functionCall" in p and (p["functionCall"] or {}).get("name") == "code_execution"
         for p in parts
     ), parts
     exec_part = next(p for p in parts if "executableCode" in p)
@@ -2303,8 +2267,7 @@ def test_image_generation_tool_call_replays_native_inline_data(monkeypatch):
     assert inline_parts[0]["inlineData"]["data"] == pixel
     assert inline_parts[0].get("thoughtSignature") == "SIG-IMG", inline_parts
     assert not any(
-        "functionCall" in p
-        and (p["functionCall"] or {}).get("name") == "image_generation"
+        "functionCall" in p and (p["functionCall"] or {}).get("name") == "image_generation"
         for p in parts
     ), parts
 
@@ -2371,11 +2334,7 @@ def test_function_declarations_strip_openai_only_schema_keys(monkeypatch):
     )
     tools_arr = captured["body"].get("tools") or []
     decls = next(
-        (
-            t.get("functionDeclarations")
-            for t in tools_arr
-            if "functionDeclarations" in t
-        ),
+        (t.get("functionDeclarations") for t in tools_arr if "functionDeclarations" in t),
         None,
     )
     assert decls is not None, captured["body"]
@@ -2428,11 +2387,7 @@ def test_function_declarations_inline_local_refs_into_gemini_schema(monkeypatch)
     )
     tools_arr = captured["body"].get("tools") or []
     decls = next(
-        (
-            t.get("functionDeclarations")
-            for t in tools_arr
-            if "functionDeclarations" in t
-        ),
+        (t.get("functionDeclarations") for t in tools_arr if "functionDeclarations" in t),
         None,
     )
     assert decls is not None, captured["body"]
@@ -2484,11 +2439,7 @@ def test_function_declarations_inline_local_refs_in_anyof_and_items(monkeypatch)
     )
     tools_arr = captured["body"].get("tools") or []
     decls = next(
-        (
-            t.get("functionDeclarations")
-            for t in tools_arr
-            if "functionDeclarations" in t
-        ),
+        (t.get("functionDeclarations") for t in tools_arr if "functionDeclarations" in t),
         None,
     )
     assert decls is not None
@@ -2503,10 +2454,7 @@ def test_function_declarations_inline_local_refs_in_anyof_and_items(monkeypatch)
     extras = params["properties"]["extras"]
     assert extras.get("type") == "array"
     assert extras.get("items", {}).get("type") == "object"
-    assert (
-        extras.get("items", {}).get("properties", {}).get("zip", {}).get("type")
-        == "string"
-    )
+    assert extras.get("items", {}).get("properties", {}).get("zip", {}).get("type") == "string"
 
 
 def test_function_declarations_self_referential_schema_terminates(monkeypatch):
@@ -2544,11 +2492,7 @@ def test_function_declarations_self_referential_schema_terminates(monkeypatch):
     )
     tools_arr = captured["body"].get("tools") or []
     decls = next(
-        (
-            t.get("functionDeclarations")
-            for t in tools_arr
-            if "functionDeclarations" in t
-        ),
+        (t.get("functionDeclarations") for t in tools_arr if "functionDeclarations" in t),
         None,
     )
     assert decls is not None
@@ -2557,9 +2501,7 @@ def test_function_declarations_self_referential_schema_terminates(monkeypatch):
     assert root.get("properties", {}).get("value", {}).get("type") == "string"
 
 
-def test_gemini_native_skips_orphan_function_response_for_dropped_builtin(
-    monkeypatch,
-):
+def test_gemini_native_skips_orphan_function_response_for_dropped_builtin(monkeypatch):
     """Round 26: when the assistant-side synthetic web_search/web_fetch
     tool_call is dropped from native Gemini history, the matching
     role="tool" follow-up must also be dropped. Otherwise the outbound
@@ -2613,9 +2555,7 @@ def test_gemini_native_skips_orphan_function_response_for_dropped_builtin(
                 assert fr.get("name") != "web_search", contents
 
 
-def test_gemini_native_skips_orphan_function_response_for_native_part_replay(
-    monkeypatch,
-):
+def test_gemini_native_skips_orphan_function_response_for_native_part_replay(monkeypatch):
     """Round 26: code_execution / image_generation tool_calls are
     replayed as Gemini-native executableCode / codeExecutionResult /
     inlineData parts. The matching role="tool" follow-up must NOT then
@@ -2824,9 +2764,7 @@ def test_chat_message_extra_content_round_trips_through_validation():
         }
     )
     assistant_msg = req.messages[1]
-    assert assistant_msg.extra_content == {
-        "google": {"thought_signature": "SIG-TEXT"},
-    }
+    assert assistant_msg.extra_content == {"google": {"thought_signature": "SIG-TEXT"}}
     built = _build_external_messages(
         req.messages,
         supports_vision = True,
@@ -2834,9 +2772,7 @@ def test_chat_message_extra_content_round_trips_through_validation():
         base_url = "https://generativelanguage.googleapis.com/v1beta",
     )
     assistant_out = built[1]
-    assert assistant_out["extra_content"] == {
-        "google": {"thought_signature": "SIG-TEXT"},
-    }
+    assert assistant_out["extra_content"] == {"google": {"thought_signature": "SIG-TEXT"}}
     # Non-Gemini providers must NOT receive extra_content; Google's
     # thought_signature field is unknown to OpenAI / Mistral / etc.
     built_openai = _build_external_messages(
@@ -2904,10 +2840,7 @@ def test_parallel_tool_results_group_into_one_user_block(monkeypatch):
         c
         for c in contents
         if c.get("role") == "user"
-        and all(
-            isinstance(p, dict) and "functionResponse" in p
-            for p in (c.get("parts") or [])
-        )
+        and all(isinstance(p, dict) and "functionResponse" in p for p in (c.get("parts") or []))
     ]
     assert len(tool_result_users) == 1, contents
     fr_parts = tool_result_users[0]["parts"]
@@ -2967,9 +2900,7 @@ def test_image_picker_model_with_search_off_pill_strips_text_tools(monkeypatch):
     )
     body = captured["body"]
     assert "tools" not in body, body.get("tools")
-    assert "thinkingConfig" not in body.get("generationConfig", {}), body[
-        "generationConfig"
-    ]
+    assert "thinkingConfig" not in body.get("generationConfig", {}), body["generationConfig"]
 
 
 def test_image_models_drop_function_declarations(monkeypatch):
@@ -2987,10 +2918,7 @@ def test_image_models_drop_function_declarations(monkeypatch):
         ],
     )
     assert captured["body"].get("tools") is None
-    assert captured["body"]["generationConfig"]["responseModalities"] == [
-        "TEXT",
-        "IMAGE",
-    ]
+    assert captured["body"]["generationConfig"]["responseModalities"] == ["TEXT", "IMAGE"]
 
 
 def test_safe_fetch_image_rejects_malformed_bracketed_url():
@@ -3001,9 +2929,7 @@ def test_safe_fetch_image_rejects_malformed_bracketed_url():
     assert res is None
 
 
-def test_safe_fetch_image_pins_validated_ip_no_hostname_in_request(
-    monkeypatch,
-):
+def test_safe_fetch_image_pins_validated_ip_no_hostname_in_request(monkeypatch):
     """Round 17: the fetch helper must pin the validated IP into the
     outgoing request URL (with a Host header carrying the original
     hostname). A second hostname-style getaddrinfo after the validate
@@ -3046,7 +2972,11 @@ def test_safe_fetch_image_pins_validated_ip_no_hostname_in_request(
             return b"PNG"
 
     class _StubOpener:
-        def open(self, req, timeout = None):
+        def open(
+            self,
+            req,
+            timeout = None,
+        ):
             captured["requests"].append(
                 {
                     "url": req.full_url,
@@ -3055,22 +2985,14 @@ def test_safe_fetch_image_pins_validated_ip_no_hostname_in_request(
             )
             return _StubResp()
 
-    monkeypatch.setattr(
-        "urllib.request.build_opener", lambda *_args, **_kw: _StubOpener()
-    )
+    monkeypatch.setattr("urllib.request.build_opener", lambda *_args, **_kw: _StubOpener())
 
-    res = _drive(
-        ep_mod._safe_fetch_image_for_gemini(
-            "https://cdn.example.com/x.png", "image/png"
-        )
-    )
+    res = _drive(ep_mod._safe_fetch_image_for_gemini("https://cdn.example.com/x.png", "image/png"))
     assert res is not None
     assert res[0] == "image/png"
     # The outgoing URL must use the pinned IP literal, not the hostname.
     assert any("8.8.8.8" in r["url"] for r in captured["requests"]), captured
-    assert all(
-        "cdn.example.com" not in r["url"] for r in captured["requests"]
-    ), captured
+    assert all("cdn.example.com" not in r["url"] for r in captured["requests"]), captured
     # Host header still carries the original hostname for vhost/SNI.
     assert captured["requests"][0]["host_header"] == "cdn.example.com"
 
@@ -3109,7 +3031,11 @@ def test_safe_fetch_image_redirect_to_private_host_rejected(monkeypatch):
     monkeypatch.setattr(socket, "getaddrinfo", fake_getaddrinfo)
 
     class _StubOpener:
-        def open(self, req, timeout = None):
+        def open(
+            self,
+            req,
+            timeout = None,
+        ):
             # Simulate a 302 to a private host.
             raise urllib.error.HTTPError(
                 req.full_url,
@@ -3119,15 +3045,9 @@ def test_safe_fetch_image_redirect_to_private_host_rejected(monkeypatch):
                 None,
             )
 
-    monkeypatch.setattr(
-        "urllib.request.build_opener", lambda *_args, **_kw: _StubOpener()
-    )
+    monkeypatch.setattr("urllib.request.build_opener", lambda *_args, **_kw: _StubOpener())
 
-    res = _drive(
-        ep_mod._safe_fetch_image_for_gemini(
-            "https://cdn.example.com/x.png", "image/png"
-        )
-    )
+    res = _drive(ep_mod._safe_fetch_image_for_gemini("https://cdn.example.com/x.png", "image/png"))
     assert res is None
 
 
@@ -3140,7 +3060,11 @@ def test_files_api_substring_url_not_misclassified_as_filedata(monkeypatch):
     captured_outbound: dict = {}
     fetch_calls: list[str] = []
 
-    async def fake_fetch(url, fallback_mime, max_bytes = None):
+    async def fake_fetch(
+        url,
+        fallback_mime,
+        max_bytes = None,
+    ):
         fetch_calls.append(url)
         return "image/png", base64.b64encode(b"DATA").decode("ascii")
 
@@ -3273,9 +3197,7 @@ def test_legacy_gemini3_pro_medium_coerced_to_high(monkeypatch):
         model = "gemini-3-pro-preview",
         reasoning_effort = "medium",
     )
-    assert captured["body"]["generationConfig"]["thinkingConfig"] == {
-        "thinkingLevel": "high",
-    }
+    assert captured["body"]["generationConfig"]["thinkingConfig"] == {"thinkingLevel": "high"}
 
 
 def test_gemini_3_1_pro_medium_passes_through(monkeypatch):
@@ -3286,9 +3208,7 @@ def test_gemini_3_1_pro_medium_passes_through(monkeypatch):
         model = "gemini-3.1-pro-preview",
         reasoning_effort = "medium",
     )
-    assert captured["body"]["generationConfig"]["thinkingConfig"] == {
-        "thinkingLevel": "medium",
-    }
+    assert captured["body"]["generationConfig"]["thinkingConfig"] == {"thinkingLevel": "medium"}
 
 
 def test_tool_calls_extra_content_stripped_for_non_native_gemini():
@@ -3385,9 +3305,7 @@ def test_user_function_named_with_server_tool_arg_not_dropped(monkeypatch):
                             "type": "function",
                             "function": {
                                 "name": "user_function",
-                                "arguments": json.dumps(
-                                    {"_server_tool": True, "q": "x"}
-                                ),
+                                "arguments": json.dumps({"_server_tool": True, "q": "x"}),
                             },
                         }
                     ],
@@ -3453,9 +3371,7 @@ def test_builtin_named_with_server_tool_marker_dropped(monkeypatch):
                             "type": "function",
                             "function": {
                                 "name": "web_search",
-                                "arguments": json.dumps(
-                                    {"_server_tool": True, "query": "x"}
-                                ),
+                                "arguments": json.dumps({"_server_tool": True, "query": "x"}),
                             },
                         }
                     ],
@@ -3507,9 +3423,7 @@ def test_gemini_tool_choice_none_disables_function_declarations(monkeypatch):
     assert captured["body"].get("tools") is None, captured["body"]
 
 
-def test_schema_anyof_multitype_with_null_keeps_anyof_and_nullable(
-    monkeypatch,
-):
+def test_schema_anyof_multitype_with_null_keeps_anyof_and_nullable(monkeypatch):
     """Round 18: multi-branch unions with null (e.g.
     `Union[str, int, None]`) must keep the slim anyOf without the null
     branch and add `nullable: true`; Gemini rejects
@@ -3546,9 +3460,7 @@ def test_schema_anyof_multitype_with_null_keeps_anyof_and_nullable(
     assert either.get("nullable") is True
     inner = either.get("anyOf")
     assert isinstance(inner, list) and len(inner) == 2, either
-    assert all(
-        not (isinstance(b, dict) and b.get("type") == "null") for b in inner
-    ), inner
+    assert all(not (isinstance(b, dict) and b.get("type") == "null") for b in inner), inner
 
 
 def test_safe_fetch_image_redirect_malformed_url_no_crash(monkeypatch):
@@ -3576,7 +3488,11 @@ def test_safe_fetch_image_redirect_malformed_url_no_crash(monkeypatch):
     monkeypatch.setattr(socket, "getaddrinfo", fake_getaddrinfo)
 
     class _StubOpener:
-        def open(self, req, timeout = None):
+        def open(
+            self,
+            req,
+            timeout = None,
+        ):
             raise urllib.error.HTTPError(
                 req.full_url,
                 302,
@@ -3585,26 +3501,16 @@ def test_safe_fetch_image_redirect_malformed_url_no_crash(monkeypatch):
                 None,
             )
 
-    monkeypatch.setattr(
-        "urllib.request.build_opener", lambda *_args, **_kw: _StubOpener()
-    )
+    monkeypatch.setattr("urllib.request.build_opener", lambda *_args, **_kw: _StubOpener())
 
-    res = _drive(
-        ep_mod._safe_fetch_image_for_gemini(
-            "https://cdn.example.com/x.png", "image/png"
-        )
-    )
+    res = _drive(ep_mod._safe_fetch_image_for_gemini("https://cdn.example.com/x.png", "image/png"))
     assert res is None
 
 
 def test_safe_fetch_image_malformed_port_no_crash():
     """Round 18: a URL with a non-numeric port (`https://h:bad/x.png`)
     must not raise; urlparse's port property lazily ValueErrors."""
-    res = _drive(
-        ep_mod._safe_fetch_image_for_gemini(
-            "https://example.com:bad/x.png", "image/png"
-        )
-    )
+    res = _drive(ep_mod._safe_fetch_image_for_gemini("https://example.com:bad/x.png", "image/png"))
     assert res is None
 
 
@@ -3646,17 +3552,17 @@ def test_safe_fetch_image_missing_content_type_uses_fallback(monkeypatch):
             return b"PNG"
 
     class _StubOpener:
-        def open(self, req, timeout = None):
+        def open(
+            self,
+            req,
+            timeout = None,
+        ):
             return _StubResp()
 
-    monkeypatch.setattr(
-        "urllib.request.build_opener", lambda *_args, **_kw: _StubOpener()
-    )
+    monkeypatch.setattr("urllib.request.build_opener", lambda *_args, **_kw: _StubOpener())
 
     res = _drive(
-        ep_mod._safe_fetch_image_for_gemini(
-            "https://cdn.example.com/cat.png", "image/png"
-        )
+        ep_mod._safe_fetch_image_for_gemini("https://cdn.example.com/cat.png", "image/png")
     )
     assert res is not None
     assert res[0] == "image/png"
@@ -3737,9 +3643,7 @@ def test_anthropic_translates_openai_tool_calls_into_tool_use_blocks(monkeypatch
     tool_results: list[dict] = []
     for m in msgs:
         if m.get("role") == "user" and isinstance(m.get("content"), list):
-            tool_results.extend(
-                b for b in m["content"] if b.get("type") == "tool_result"
-            )
+            tool_results.extend(b for b in m["content"] if b.get("type") == "tool_result")
     assert any(
         tr.get("tool_use_id") == "call_a" and tr.get("content") == "result_text"
         for tr in tool_results
@@ -4118,7 +4022,11 @@ def test_remote_image_fetch_attempt_cap_includes_failures(monkeypatch):
     failing/slow URLs runs 100 fetches each up to the 15s timeout."""
     fetch_calls: list[str] = []
 
-    async def fake_fetch(url, fallback_mime, max_bytes = None):
+    async def fake_fetch(
+        url,
+        fallback_mime,
+        max_bytes = None,
+    ):
         fetch_calls.append(url)
         return None
 
@@ -4218,9 +4126,7 @@ def test_orphan_function_call_output_dropped_when_call_skipped(monkeypatch):
                             "type": "function",
                             "function": {
                                 "name": "web_search",
-                                "arguments": json.dumps(
-                                    {"_server_tool": True, "query": "x"}
-                                ),
+                                "arguments": json.dumps({"_server_tool": True, "query": "x"}),
                             },
                         }
                     ],
@@ -4281,9 +4187,7 @@ def test_schema_multitype_union_with_null_preserves_anyof(monkeypatch):
     assert either.get("nullable") is True
     inner = either.get("anyOf")
     assert isinstance(inner, list) and len(inner) == 2, either
-    types = sorted(
-        b.get("type") for b in inner if isinstance(b, dict) and b.get("type")
-    )
+    types = sorted(b.get("type") for b in inner if isinstance(b, dict) and b.get("type"))
     assert types == ["integer", "string"], inner
 
 
@@ -4293,7 +4197,11 @@ def test_invalid_gemini_model_rejected_before_image_fetch(monkeypatch):
     runs."""
     fetch_calls: list[str] = []
 
-    async def fake_fetch(url, fallback_mime, max_bytes = None):
+    async def fake_fetch(
+        url,
+        fallback_mime,
+        max_bytes = None,
+    ):
         fetch_calls.append(url)
         return None
 
@@ -4429,9 +4337,7 @@ def test_role_tool_dropped_when_matching_synthetic_call_filtered():
     assert roles == ["user"], result
 
 
-def test_openrouter_no_synthetic_web_search_event_on_tool_choice_none(
-    monkeypatch,
-):
+def test_openrouter_no_synthetic_web_search_event_on_tool_choice_none(monkeypatch):
     """Round 20: OpenRouter dispatcher must not emit synthetic
     web_search tool_start / tool_end events when tool_choice="none";
     otherwise the chat UI shows a search card for a search that
@@ -4487,14 +4393,10 @@ def test_openrouter_no_synthetic_web_search_event_on_tool_choice_none(
 
     _drive(run())
     # No synthetic web_search tool_start / tool_end emitted.
-    assert all(
-        e.get("tool_name") != "web_search" for e in captured_events
-    ), captured_events
+    assert all(e.get("tool_name") != "web_search" for e in captured_events), captured_events
 
 
-def test_anthropic_role_tool_list_content_translates_to_tool_result(
-    monkeypatch,
-):
+def test_anthropic_role_tool_list_content_translates_to_tool_result(monkeypatch):
     """Round 20: an OpenAI-shape role=tool message with list content
     (`content=[{"type":"text","text":"result"}]`) must be translated
     into Anthropic's native tool_result block, not forwarded as an
@@ -4558,9 +4460,7 @@ def test_anthropic_role_tool_list_content_translates_to_tool_result(
     tool_results: list[dict] = []
     for m in msgs:
         if m.get("role") == "user" and isinstance(m.get("content"), list):
-            tool_results.extend(
-                b for b in m["content"] if b.get("type") == "tool_result"
-            )
+            tool_results.extend(b for b in m["content"] if b.get("type") == "tool_result")
     assert any(
         tr.get("tool_use_id") == "call_a" and tr.get("content") == "result_text"
         for tr in tool_results
@@ -4618,9 +4518,7 @@ def test_youtube_filedata_uses_video_mime(monkeypatch):
     assert yt["fileData"]["mimeType"].startswith("video/"), yt
 
 
-def test_openai_responses_assistant_text_serialized_before_function_call(
-    monkeypatch,
-):
+def test_openai_responses_assistant_text_serialized_before_function_call(monkeypatch):
     """Round 20: in OpenAI Responses history, the assistant's
     visible text for a turn that ALSO emitted a function_call must
     serialize BEFORE the function_call item, matching the prior
@@ -4689,13 +4587,7 @@ def test_openai_responses_assistant_text_serialized_before_function_call(
     #   function_call (get_weather)
     #   function_call_output (sunny)
     #   user ("thanks")
-    assert types == [
-        "user",
-        "assistant",
-        "function_call",
-        "function_call_output",
-        "user",
-    ], items
+    assert types == ["user", "assistant", "function_call", "function_call_output", "user"], items
 
 
 def test_gemini_tool_choice_none_disables_image_generation(monkeypatch):
@@ -4765,9 +4657,7 @@ def test_gemini_forced_function_tool_choice_drops_image_generation(monkeypatch):
     assert body["generationConfig"].get("responseModalities") == ["TEXT"], body
 
 
-def test_gemini_code_execution_native_part_list_replays_per_part_signatures(
-    monkeypatch,
-):
+def test_gemini_code_execution_native_part_list_replays_per_part_signatures(monkeypatch):
     """Round 21: merged code-execution history must replay per-part
     `thoughtSignature`s, not fan one top-level signature across every
     native subpart. Gemini 3 strict validators reject a signature
@@ -4832,9 +4722,7 @@ def test_gemini_code_execution_native_part_list_replays_per_part_signatures(
     assert "thoughtSignature" not in result_parts[0], result_parts[0]
 
 
-def test_gemini_code_execution_legacy_merged_signature_only_on_executable(
-    monkeypatch,
-):
+def test_gemini_code_execution_legacy_merged_signature_only_on_executable(monkeypatch):
     """Round 21: backward compatibility for pre-round-21 persisted
     history that stored merged `native_part` as a single object plus a
     top-level `thoughtSignature`. The replay branch must attach that
@@ -4978,12 +4866,14 @@ def test_safe_fetch_image_threads_per_request_byte_budget(monkeypatch):
             return b"\x00" * (5 * 1024 * 1024)
 
     class _StubOpener:
-        def open(self, req, timeout = None):
+        def open(
+            self,
+            req,
+            timeout = None,
+        ):
             return _StubResp()
 
-    monkeypatch.setattr(
-        "urllib.request.build_opener", lambda *_args, **_kw: _StubOpener()
-    )
+    monkeypatch.setattr("urllib.request.build_opener", lambda *_args, **_kw: _StubOpener())
 
     res = _drive(
         ep_mod._safe_fetch_image_for_gemini(
@@ -5006,9 +4896,7 @@ def test_openai_chat_delta_type_includes_tool_calls_and_extra_content():
     import os
 
     here = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
-    types_path = os.path.join(
-        here, "frontend", "src", "features", "chat", "types", "api.ts"
-    )
+    types_path = os.path.join(here, "frontend", "src", "features", "chat", "types", "api.ts")
     with open(types_path, "r", encoding = "utf-8") as f:
         src = f.read()
     assert "tool_calls?: OpenAIToolCallPart[]" in src, src[:200]
@@ -5215,9 +5103,7 @@ def test_openai_responses_forced_function_tool_choice_drops_hosted_tools(monkeyp
     assert not (hosted_seen & hosted_types), body
     # The user function declaration must still be present so the pin
     # has something to target.
-    user_function_seen = any(
-        isinstance(t, dict) and t.get("type") == "function" for t in tools
-    )
+    user_function_seen = any(isinstance(t, dict) and t.get("type") == "function" for t in tools)
     assert user_function_seen, body
     # And the forced-function tool_choice must be forwarded in Responses
     # shape: `{type:"function", name:"..."}`.
@@ -5442,9 +5328,7 @@ def test_strip_provider_synthetic_tool_history_drops_empty_assistant():
     assert roles == ["user", "user"], out
 
 
-def test_openrouter_no_synthetic_web_search_event_on_forced_function_tool_choice(
-    monkeypatch,
-):
+def test_openrouter_no_synthetic_web_search_event_on_forced_function_tool_choice(monkeypatch):
     """Round 22 sibling of the round-20 `tool_choice='none'` test: when
     the caller forces a specific function via `tool_choice={"type":
     "function", ...}` AND passes `enabled_tools=["web_search"]`, the
@@ -5456,10 +5340,7 @@ def test_openrouter_no_synthetic_web_search_event_on_forced_function_tool_choice
     def handler(request: httpx.Request) -> httpx.Response:
         return httpx.Response(
             200,
-            content = (
-                b'data: {"choices":[{"delta":{"content":"ok"}}]}\n\n'
-                b"data: [DONE]\n\n"
-            ),
+            content = (b'data: {"choices":[{"delta":{"content":"ok"}}]}\n\n' b"data: [DONE]\n\n"),
             headers = {"content-type": "text/event-stream"},
         )
 
diff --git a/studio/backend/tests/test_gguf_completion_usage.py b/studio/backend/tests/test_gguf_completion_usage.py
index b8cfaee7c7..9f9de80a84 100644
--- a/studio/backend/tests/test_gguf_completion_usage.py
+++ b/studio/backend/tests/test_gguf_completion_usage.py
@@ -30,12 +30,8 @@ class _GgufBackend:
 
 
 def _request_completion(monkeypatch, usage):
-    monkeypatch.setattr(
-        inference_route, "get_llama_cpp_backend", lambda: _GgufBackend(usage)
-    )
-    monkeypatch.setattr(
-        inference_route, "_effective_enable_tools", lambda payload: False
-    )
+    monkeypatch.setattr(inference_route, "get_llama_cpp_backend", lambda: _GgufBackend(usage))
+    monkeypatch.setattr(inference_route, "_effective_enable_tools", lambda payload: False)
 
     app = FastAPI()
     app.include_router(inference_route.router)
diff --git a/studio/backend/tests/test_gguf_metadata.py b/studio/backend/tests/test_gguf_metadata.py
index e5040e306c..08f22edb18 100644
--- a/studio/backend/tests/test_gguf_metadata.py
+++ b/studio/backend/tests/test_gguf_metadata.py
@@ -35,17 +35,11 @@ def _enc_kv_string(key: str, value: str) -> bytes:
 
 
 def _enc_kv_uint32(key: str, value: int) -> bytes:
-    return (
-        _enc_string(key) + struct.pack(" bytes:
-    return (
-        _enc_string(key)
-        + struct.pack(" bytes:
@@ -70,10 +64,7 @@ def _write_synthetic_gguf(
     extra_string_arrays = extra_string_arrays or {}
     extra_bools = extra_bools or {}
     kv_count = (
-        len(general_strings)
-        + len(extra_uint32)
-        + len(extra_string_arrays)
-        + len(extra_bools)
+        len(general_strings) + len(extra_uint32) + len(extra_string_arrays) + len(extra_bools)
     )
     body = b""
     for k, v in general_strings.items():
@@ -126,10 +117,7 @@ def test_extracts_general_string_fields(tmp_path: Path):
     assert meta is not None
     assert meta["general.architecture"] == "qwen2vl"
     assert meta["general.basename"] == "Qwen3.5"
-    assert (
-        meta["general.base_model.0.repo_url"]
-        == "https://huggingface.co/Qwen/Qwen3.5-9B"
-    )
+    assert meta["general.base_model.0.repo_url"] == "https://huggingface.co/Qwen/Qwen3.5-9B"
 
 
 def test_skips_unrelated_fields_without_breaking(tmp_path: Path):
diff --git a/studio/backend/tests/test_gpu_selection.py b/studio/backend/tests/test_gpu_selection.py
index a1fe5653ef..90020efe43 100644
--- a/studio/backend/tests/test_gpu_selection.py
+++ b/studio/backend/tests/test_gpu_selection.py
@@ -64,9 +64,7 @@ class TestResolveRequestedGpuIds(_GpuCacheResetMixin, unittest.TestCase):
 
     def test_parent_visibility_uses_empty_numeric_ids_for_uuid_masks(self):
         with (
-            patch.dict(
-                os.environ, {"CUDA_VISIBLE_DEVICES": "GPU-aaa,GPU-bbb"}, clear = True
-            ),
+            patch.dict(os.environ, {"CUDA_VISIBLE_DEVICES": "GPU-aaa,GPU-bbb"}, clear = True),
             patch("utils.hardware.hardware.get_physical_gpu_count", return_value = 8),
         ):
             self.assertEqual(get_parent_visible_gpu_ids(), [])
@@ -96,9 +94,7 @@ class TestResolveRequestedGpuIds(_GpuCacheResetMixin, unittest.TestCase):
 
     def test_explicit_ids_are_rejected_for_uuid_parent_visibility(self):
         with (
-            patch.dict(
-                os.environ, {"CUDA_VISIBLE_DEVICES": "GPU-aaa,GPU-bbb"}, clear = True
-            ),
+            patch.dict(os.environ, {"CUDA_VISIBLE_DEVICES": "GPU-aaa,GPU-bbb"}, clear = True),
             patch("utils.hardware.hardware.get_physical_gpu_count", return_value = 8),
         ):
             with self.assertRaisesRegex(
@@ -204,13 +200,9 @@ class TestVisibleGpuUtilization(_GpuCacheResetMixin, unittest.TestCase):
             },
         ]
         with (
-            patch.dict(
-                os.environ, {"CUDA_VISIBLE_DEVICES": "GPU-aaa,GPU-bbb"}, clear = True
-            ),
+            patch.dict(os.environ, {"CUDA_VISIBLE_DEVICES": "GPU-aaa,GPU-bbb"}, clear = True),
             patch("utils.hardware.hardware.get_device", return_value = DeviceType.CUDA),
-            patch(
-                "utils.hardware.hardware._torch_get_physical_gpu_count", return_value = 2
-            ),
+            patch("utils.hardware.hardware._torch_get_physical_gpu_count", return_value = 2),
             patch(
                 "utils.hardware.hardware._torch_get_per_device_info",
                 return_value = fake_torch_devices,
@@ -254,9 +246,7 @@ class TestGpuAutoSelection(_GpuCacheResetMixin, unittest.TestCase):
 
     def test_get_device_map_uses_all_inherited_visible_gpus_for_uuid_masks(self):
         with (
-            patch.dict(
-                os.environ, {"CUDA_VISIBLE_DEVICES": "GPU-aaa,GPU-bbb"}, clear = True
-            ),
+            patch.dict(os.environ, {"CUDA_VISIBLE_DEVICES": "GPU-aaa,GPU-bbb"}, clear = True),
             patch("utils.hardware.hardware.get_device", return_value = DeviceType.CUDA),
         ):
             self.assertEqual(get_device_map(None), "balanced")
@@ -376,9 +366,7 @@ class TestGpuAutoSelection(_GpuCacheResetMixin, unittest.TestCase):
                 return_value = 1234,
             ),
         ):
-            model_size_bytes, source = _hw_module.estimate_fp16_model_size_bytes(
-                "unsloth/test"
-            )
+            model_size_bytes, source = _hw_module.estimate_fp16_model_size_bytes("unsloth/test")
 
         self.assertEqual(model_size_bytes, 1234)
         self.assertEqual(source, "vllm_utils")
@@ -475,9 +463,7 @@ class TestGpuAutoSelection(_GpuCacheResetMixin, unittest.TestCase):
 
     def test_prepare_gpu_selection_preserves_uuid_parent_visibility_in_auto_mode(self):
         with (
-            patch.dict(
-                os.environ, {"CUDA_VISIBLE_DEVICES": "GPU-aaa,GPU-bbb"}, clear = True
-            ),
+            patch.dict(os.environ, {"CUDA_VISIBLE_DEVICES": "GPU-aaa,GPU-bbb"}, clear = True),
             patch(
                 "utils.hardware.hardware.estimate_required_model_memory_gb",
                 return_value = (
@@ -524,9 +510,7 @@ class TestPreSpawnGpuResolution(_GpuCacheResetMixin, unittest.TestCase):
             patch(
                 "core.training.training._CTX.Process", return_value = DummyProcess()
             ) as mock_process,
-            patch(
-                "core.training.training.threading.Thread", return_value = DummyThread()
-            ),
+            patch("core.training.training.threading.Thread", return_value = DummyThread()),
         ):
             backend.start_training(
                 job_id = "test-job-1",
@@ -567,9 +551,7 @@ class TestPreSpawnGpuResolution(_GpuCacheResetMixin, unittest.TestCase):
             patch(
                 "core.training.training._CTX.Process", return_value = DummyProcess()
             ) as mock_process,
-            patch(
-                "core.training.training.threading.Thread", return_value = DummyThread()
-            ),
+            patch("core.training.training.threading.Thread", return_value = DummyThread()),
         ):
             backend.start_training(
                 job_id = "test-job-2",
@@ -599,9 +581,7 @@ class TestPreSpawnGpuResolution(_GpuCacheResetMixin, unittest.TestCase):
         dummy_queue = object()
 
         with (
-            patch.dict(
-                os.environ, {"CUDA_VISIBLE_DEVICES": "GPU-aaa,GPU-bbb"}, clear = True
-            ),
+            patch.dict(os.environ, {"CUDA_VISIBLE_DEVICES": "GPU-aaa,GPU-bbb"}, clear = True),
             patch(
                 "core.training.training._CTX.Queue",
                 side_effect = [dummy_queue, dummy_queue],
@@ -609,9 +589,7 @@ class TestPreSpawnGpuResolution(_GpuCacheResetMixin, unittest.TestCase):
             patch(
                 "core.training.training._CTX.Process", return_value = DummyProcess()
             ) as mock_process,
-            patch(
-                "core.training.training.threading.Thread", return_value = DummyThread()
-            ),
+            patch("core.training.training.threading.Thread", return_value = DummyThread()),
             patch(
                 "utils.hardware.hardware.estimate_required_model_memory_gb",
                 return_value = (
@@ -629,9 +607,7 @@ class TestPreSpawnGpuResolution(_GpuCacheResetMixin, unittest.TestCase):
 
         config = mock_process.call_args.kwargs["kwargs"]["config"]
         self.assertIsNone(config["resolved_gpu_ids"])
-        self.assertEqual(
-            config["gpu_selection"]["selection_mode"], "inherit_parent_visible"
-        )
+        self.assertEqual(config["gpu_selection"]["selection_mode"], "inherit_parent_visible")
 
     def test_inference_orchestrator_resolves_explicit_gpu_ids_before_spawn(self):
         class DummyThread:
@@ -643,7 +619,6 @@ class TestPreSpawnGpuResolution(_GpuCacheResetMixin, unittest.TestCase):
 
         with patch("core.inference.orchestrator.threading.Thread", DummyThread):
             from core.inference.orchestrator import InferenceOrchestrator
-
             orchestrator = InferenceOrchestrator()
 
         config = SimpleNamespace(identifier = "unsloth/test", gguf_variant = None)
@@ -660,9 +635,7 @@ class TestPreSpawnGpuResolution(_GpuCacheResetMixin, unittest.TestCase):
                 "_wait_response",
                 return_value = {"success": True, "model_info": {}},
             ),
-            patch(
-                "utils.transformers_version.needs_transformers_5", return_value = False
-            ),
+            patch("utils.transformers_version.needs_transformers_5", return_value = False),
         ):
             self.assertTrue(orchestrator.load_model(config = config, gpu_ids = [1]))
 
@@ -681,7 +654,6 @@ class TestPreSpawnGpuResolution(_GpuCacheResetMixin, unittest.TestCase):
 
         with patch("core.inference.orchestrator.threading.Thread", DummyThread):
             from core.inference.orchestrator import InferenceOrchestrator
-
             orchestrator = InferenceOrchestrator()
 
         config = SimpleNamespace(identifier = "unsloth/test", gguf_variant = None)
@@ -698,9 +670,7 @@ class TestPreSpawnGpuResolution(_GpuCacheResetMixin, unittest.TestCase):
                 "_wait_response",
                 return_value = {"success": True, "model_info": {}},
             ),
-            patch(
-                "utils.transformers_version.needs_transformers_5", return_value = False
-            ),
+            patch("utils.transformers_version.needs_transformers_5", return_value = False),
         ):
             self.assertTrue(orchestrator.load_model(config = config, gpu_ids = None))
 
@@ -782,9 +752,7 @@ class TestRouteErrors(unittest.TestCase):
                 raise ValueError("Invalid gpu_ids [99]")
 
         with (
-            patch.object(
-                training_route, "get_training_backend", return_value = DummyBackend()
-            ),
+            patch.object(training_route, "get_training_backend", return_value = DummyBackend()),
             patch(
                 "core.inference.get_inference_backend",
                 return_value = SimpleNamespace(active_model_name = None),
@@ -795,9 +763,7 @@ class TestRouteErrors(unittest.TestCase):
             ),
         ):
             with self.assertRaises(HTTPException) as exc_info:
-                asyncio.run(
-                    training_route.start_training(request, current_subject = "test-user")
-                )
+                asyncio.run(training_route.start_training(request, current_subject = "test-user"))
 
         self.assertEqual(exc_info.exception.status_code, 400)
         self.assertIn("gpu_ids [99]", exc_info.exception.detail)
@@ -826,9 +792,7 @@ class TestRouteErrors(unittest.TestCase):
                 )
 
         with (
-            patch.object(
-                training_route, "get_training_backend", return_value = DummyBackend()
-            ),
+            patch.object(training_route, "get_training_backend", return_value = DummyBackend()),
             patch(
                 "core.inference.get_inference_backend",
                 return_value = SimpleNamespace(active_model_name = None),
@@ -839,9 +803,7 @@ class TestRouteErrors(unittest.TestCase):
             ),
         ):
             with self.assertRaises(HTTPException) as exc_info:
-                asyncio.run(
-                    training_route.start_training(request, current_subject = "test-user")
-                )
+                asyncio.run(training_route.start_training(request, current_subject = "test-user"))
 
         self.assertEqual(exc_info.exception.status_code, 400)
         self.assertIn("UUID/MIG", exc_info.exception.detail)
@@ -976,22 +938,17 @@ class TestRouteErrors(unittest.TestCase):
 class TestRaiseIfOffloaded(unittest.TestCase):
     def test_no_offload_is_noop(self):
         from utils.hardware import raise_if_offloaded
-
         model = SimpleNamespace(hf_device_map = {"model.embed_tokens": 0, "lm_head": 1})
         raise_if_offloaded(model, "balanced", "Test")
 
     def test_cpu_offload_raises(self):
         from utils.hardware import raise_if_offloaded
-
-        model = SimpleNamespace(
-            hf_device_map = {"model.layers.0": 0, "model.layers.1": "cpu"}
-        )
+        model = SimpleNamespace(hf_device_map = {"model.layers.0": 0, "model.layers.1": "cpu"})
         with self.assertRaisesRegex(ValueError, "offloaded"):
             raise_if_offloaded(model, "balanced", "Test")
 
     def test_no_device_map_attr_is_noop(self):
         from utils.hardware import raise_if_offloaded
-
         raise_if_offloaded(SimpleNamespace(), "sequential", "Test")
 
 
@@ -1314,7 +1271,6 @@ class TestEstimateFp16ModelSizeBytesPrefersLocalWeights(unittest.TestCase):
         config = object(),
     ):
         from utils.hardware import hardware as hardware_module
-
         with (
             patch.object(
                 hardware_module,
@@ -1395,7 +1351,6 @@ class TestEstimateFp16ModelSizeBytesPrefersLocalWeights(unittest.TestCase):
 
     def test_remote_safetensors_path_unaffected_by_local_weights(self):
         from utils.hardware import hardware as hardware_module
-
         with (
             patch.object(
                 hardware_module,
diff --git a/studio/backend/tests/test_gpu_selection_sandbox.py b/studio/backend/tests/test_gpu_selection_sandbox.py
index 830a98a2fb..073f8d9437 100644
--- a/studio/backend/tests/test_gpu_selection_sandbox.py
+++ b/studio/backend/tests/test_gpu_selection_sandbox.py
@@ -35,7 +35,6 @@ def _make_fake_config(
 ):
     """Create a fake HF config-like object for estimation tests."""
     from types import SimpleNamespace
-
     return SimpleNamespace(
         vocab_size = vocab_size,
         hidden_size = hidden_size,
@@ -122,7 +121,6 @@ class TestEstimateRequiredModelMemory(unittest.TestCase):
 
     def test_inference_fp16_uses_1_3x(self):
         from utils.hardware.hardware import estimate_required_model_memory_gb
-
         with patch(
             "utils.hardware.hardware.estimate_fp16_model_size_bytes",
             return_value = (10 * (1024**3), "config"),  # 10GB model
@@ -138,7 +136,6 @@ class TestEstimateRequiredModelMemory(unittest.TestCase):
 
     def test_inference_4bit_uses_reduced_estimate(self):
         from utils.hardware.hardware import estimate_required_model_memory_gb
-
         with patch(
             "utils.hardware.hardware.estimate_fp16_model_size_bytes",
             return_value = (30 * (1024**3), "config"),  # 30GB fp16 model
@@ -154,7 +151,6 @@ class TestEstimateRequiredModelMemory(unittest.TestCase):
 
     def test_4bit_training_reduces_base(self):
         from utils.hardware.hardware import estimate_required_model_memory_gb
-
         with patch(
             "utils.hardware.hardware.estimate_fp16_model_size_bytes",
             return_value = (30 * (1024**3), "config"),  # 30GB fp16 model
@@ -170,7 +166,6 @@ class TestEstimateRequiredModelMemory(unittest.TestCase):
 
     def test_full_finetune_uses_3_5x(self):
         from utils.hardware.hardware import estimate_required_model_memory_gb
-
         with patch(
             "utils.hardware.hardware.estimate_fp16_model_size_bytes",
             return_value = (10 * (1024**3), "config"),  # 10GB model
@@ -185,7 +180,6 @@ class TestEstimateRequiredModelMemory(unittest.TestCase):
 
     def test_returns_none_when_unavailable(self):
         from utils.hardware.hardware import estimate_required_model_memory_gb
-
         with patch(
             "utils.hardware.hardware.estimate_fp16_model_size_bytes",
             return_value = (None, "unavailable"),
@@ -214,7 +208,6 @@ class TestAutoSelectGpuIds(unittest.TestCase):
     def test_single_gpu_sufficient(self):
         from utils.hardware.hardware import auto_select_gpu_ids
         import utils.hardware.hardware as hw
-
         with (
             patch.object(hw, "get_device", return_value = hw.DeviceType.CUDA),
             patch.object(
@@ -261,7 +254,6 @@ class TestAutoSelectGpuIds(unittest.TestCase):
     def test_two_gpus_needed(self):
         from utils.hardware.hardware import auto_select_gpu_ids
         import utils.hardware.hardware as hw
-
         with (
             patch.object(hw, "get_device", return_value = hw.DeviceType.CUDA),
             patch.object(
@@ -305,7 +297,6 @@ class TestAutoSelectGpuIds(unittest.TestCase):
     def test_non_cuda_returns_none(self):
         from utils.hardware.hardware import auto_select_gpu_ids
         import utils.hardware.hardware as hw
-
         with patch.object(hw, "get_device", return_value = hw.DeviceType.CPU):
             selected, meta = auto_select_gpu_ids("test/model")
             self.assertIsNone(selected)
@@ -318,7 +309,6 @@ class TestGetDeviceMap(unittest.TestCase):
     def test_single_gpu_returns_sequential(self):
         from utils.hardware.hardware import get_device_map
         import utils.hardware.hardware as hw
-
         with (
             patch.object(hw, "get_device", return_value = hw.DeviceType.CUDA),
             patch.object(
@@ -338,7 +328,6 @@ class TestGetDeviceMap(unittest.TestCase):
     def test_multi_gpu_returns_balanced(self):
         from utils.hardware.hardware import get_device_map
         import utils.hardware.hardware as hw
-
         with patch.object(hw, "get_device", return_value = hw.DeviceType.CUDA):
             dm = get_device_map(gpu_ids = [0, 1])
             self.assertEqual(dm, "balanced")
@@ -346,7 +335,6 @@ class TestGetDeviceMap(unittest.TestCase):
     def test_cpu_returns_sequential(self):
         from utils.hardware.hardware import get_device_map
         import utils.hardware.hardware as hw
-
         with patch.object(hw, "get_device", return_value = hw.DeviceType.CPU):
             dm = get_device_map(gpu_ids = None)
             self.assertEqual(dm, "sequential")
@@ -357,7 +345,6 @@ class TestResolveRequestedGpuIds(unittest.TestCase):
 
     def test_none_returns_parent_visible(self):
         from utils.hardware.hardware import resolve_requested_gpu_ids
-
         with (
             patch.dict(os.environ, {"CUDA_VISIBLE_DEVICES": "2,3"}, clear = False),
             patch("utils.hardware.hardware.get_physical_gpu_count", return_value = 8),
@@ -367,7 +354,6 @@ class TestResolveRequestedGpuIds(unittest.TestCase):
 
     def test_empty_list_returns_parent_visible(self):
         from utils.hardware.hardware import resolve_requested_gpu_ids
-
         with (
             patch.dict(os.environ, {"CUDA_VISIBLE_DEVICES": "2,3"}, clear = False),
             patch("utils.hardware.hardware.get_physical_gpu_count", return_value = 8),
@@ -377,7 +363,6 @@ class TestResolveRequestedGpuIds(unittest.TestCase):
 
     def test_duplicates_rejected(self):
         from utils.hardware.hardware import resolve_requested_gpu_ids
-
         with (
             patch.dict(os.environ, {"CUDA_VISIBLE_DEVICES": "0,1,2"}, clear = False),
             patch("utils.hardware.hardware.get_physical_gpu_count", return_value = 8),
@@ -387,7 +372,6 @@ class TestResolveRequestedGpuIds(unittest.TestCase):
 
     def test_out_of_range_rejected(self):
         from utils.hardware.hardware import resolve_requested_gpu_ids
-
         with (
             patch.dict(os.environ, {"CUDA_VISIBLE_DEVICES": "0,1"}, clear = False),
             patch("utils.hardware.hardware.get_physical_gpu_count", return_value = 4),
@@ -397,11 +381,8 @@ class TestResolveRequestedGpuIds(unittest.TestCase):
 
     def test_uuid_env_var_rejects_explicit_ids(self):
         from utils.hardware.hardware import resolve_requested_gpu_ids
-
         with (
-            patch.dict(
-                os.environ, {"CUDA_VISIBLE_DEVICES": "GPU-abc,GPU-def"}, clear = False
-            ),
+            patch.dict(os.environ, {"CUDA_VISIBLE_DEVICES": "GPU-abc,GPU-def"}, clear = False),
             patch("utils.hardware.hardware.get_physical_gpu_count", return_value = 8),
         ):
             with self.assertRaises(ValueError):
@@ -413,7 +394,6 @@ class TestApplyGpuIds(unittest.TestCase):
 
     def test_apply_list(self):
         from utils.hardware.hardware import apply_gpu_ids
-
         with patch.dict(os.environ, {}, clear = False):
             apply_gpu_ids([3, 5])
             self.assertEqual(os.environ.get("CUDA_VISIBLE_DEVICES"), "3,5")
diff --git a/studio/backend/tests/test_host_defaults.py b/studio/backend/tests/test_host_defaults.py
index 8b81474e92..02bb54df56 100644
--- a/studio/backend/tests/test_host_defaults.py
+++ b/studio/backend/tests/test_host_defaults.py
@@ -20,10 +20,7 @@ def _parse_function_param_defaults(source: str, func_name: str) -> dict:
     """
     tree = ast.parse(source)
     for node in ast.walk(tree):
-        if (
-            isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))
-            and node.name == func_name
-        ):
+        if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)) and node.name == func_name:
             result = {}
             all_args = node.args.args
             defaults = node.args.defaults
@@ -71,9 +68,7 @@ def test_run_server_default_host_is_loopback():
     """
     source = _RUN_PY.read_text()
     defaults = _parse_function_param_defaults(source, "run_server")
-    assert (
-        "host" in defaults
-    ), "run_server() must have a 'host' parameter with a default"
+    assert "host" in defaults, "run_server() must have a 'host' parameter with a default"
     host_default = defaults["host"]
     assert host_default == "127.0.0.1", (
         f"run_server() host default must be '127.0.0.1' (loopback) "
@@ -90,9 +85,7 @@ def test_argparse_default_host_is_loopback():
     """
     source = _RUN_PY.read_text()
     host_default = _parse_argparse_add_argument_default(source, "--host")
-    assert (
-        host_default is not None
-    ), "Could not find add_argument('--host', ...) in run.py"
+    assert host_default is not None, "Could not find add_argument('--host', ...) in run.py"
     assert (
         host_default == "127.0.0.1"
     ), f"run.py argparse --host default must be '127.0.0.1', got '{host_default}'"
diff --git a/studio/backend/tests/test_index_bootstrap_origin.py b/studio/backend/tests/test_index_bootstrap_origin.py
index 89f7613ee4..b36e3fcedd 100644
--- a/studio/backend/tests/test_index_bootstrap_origin.py
+++ b/studio/backend/tests/test_index_bootstrap_origin.py
@@ -13,7 +13,11 @@ from unittest.mock import MagicMock
 import pytest
 
 
-def _build_request(host: str, origin: str | None, scheme: str = "http") -> MagicMock:
+def _build_request(
+    host: str,
+    origin: str | None,
+    scheme: str = "http",
+) -> MagicMock:
     request = MagicMock()
     request.url.scheme = scheme
     request.url.netloc = host
@@ -23,21 +27,18 @@ def _build_request(host: str, origin: str | None, scheme: str = "http") -> Magic
 
 def test_is_same_origin_request_missing_origin_is_same_origin(monkeypatch):
     from main import _is_same_origin_request
-
     req = _build_request("127.0.0.1:8888", origin = None)
     assert _is_same_origin_request(req) is True
 
 
 def test_is_same_origin_request_matching_origin_is_same_origin():
     from main import _is_same_origin_request
-
     req = _build_request("127.0.0.1:8888", origin = "http://127.0.0.1:8888")
     assert _is_same_origin_request(req) is True
 
 
 def test_is_same_origin_request_evil_origin_is_cross_origin():
     from main import _is_same_origin_request
-
     req = _build_request("127.0.0.1:8888", origin = "https://evil.example")
     assert _is_same_origin_request(req) is False
 
@@ -45,7 +46,6 @@ def test_is_same_origin_request_evil_origin_is_cross_origin():
 def test_is_same_origin_request_scheme_mismatch_is_cross_origin():
     # https origin against an http listener is not same-origin.
     from main import _is_same_origin_request
-
     req = _build_request("127.0.0.1:8888", origin = "https://127.0.0.1:8888")
     assert _is_same_origin_request(req) is False
 
@@ -53,7 +53,6 @@ def test_is_same_origin_request_scheme_mismatch_is_cross_origin():
 def test_is_same_origin_request_port_mismatch_is_cross_origin():
     # Same host different port is not same-origin per the web platform.
     from main import _is_same_origin_request
-
     req = _build_request("127.0.0.1:8888", origin = "http://127.0.0.1:5173")
     assert _is_same_origin_request(req) is False
 
@@ -67,15 +66,12 @@ def test_is_same_origin_request_https_default_port_stripped_on_origin():
     """
     from main import _is_same_origin_request
 
-    req = _build_request(
-        "example.com:443", origin = "https://example.com", scheme = "https"
-    )
+    req = _build_request("example.com:443", origin = "https://example.com", scheme = "https")
     assert _is_same_origin_request(req) is True
 
 
 def test_is_same_origin_request_http_default_port_stripped_on_origin():
     from main import _is_same_origin_request
-
     req = _build_request("example.com:80", origin = "http://example.com")
     assert _is_same_origin_request(req) is True
 
@@ -84,9 +80,7 @@ def test_is_same_origin_request_default_port_present_on_origin():
     """Mirror case: Origin carries the default port, netloc doesn't. Same-origin."""
     from main import _is_same_origin_request
 
-    req = _build_request(
-        "example.com", origin = "https://example.com:443", scheme = "https"
-    )
+    req = _build_request("example.com", origin = "https://example.com:443", scheme = "https")
     assert _is_same_origin_request(req) is True
 
 
@@ -138,7 +132,5 @@ def test_is_same_origin_request_explicit_non_default_port_still_mismatch():
     """Canonicalisation does NOT collapse non-default ports to default."""
     from main import _is_same_origin_request
 
-    req = _build_request(
-        "example.com", origin = "https://example.com:9999", scheme = "https"
-    )
+    req = _build_request("example.com", origin = "https://example.com:9999", scheme = "https")
     assert _is_same_origin_request(req) is False
diff --git a/studio/backend/tests/test_index_bootstrap_origin_extra.py b/studio/backend/tests/test_index_bootstrap_origin_extra.py
index aea6b36a96..71fdbad930 100644
--- a/studio/backend/tests/test_index_bootstrap_origin_extra.py
+++ b/studio/backend/tests/test_index_bootstrap_origin_extra.py
@@ -10,7 +10,11 @@ the ``localhost`` vs ``127.0.0.1`` distinct-origin rule.
 from unittest.mock import MagicMock
 
 
-def _build_request(host: str, origin, scheme: str = "http") -> MagicMock:
+def _build_request(
+    host: str,
+    origin,
+    scheme: str = "http",
+) -> MagicMock:
     request = MagicMock()
     request.url.scheme = scheme
     request.url.netloc = host
@@ -34,7 +38,6 @@ def test_is_same_origin_request_ipv6_loopback_same_origin():
 
 def test_is_same_origin_request_ipv6_full_address_same_origin():
     from main import _is_same_origin_request
-
     req = _build_request(
         "[2001:db8::1]:8443",
         origin = "https://[2001:db8::1]:8443",
@@ -65,21 +68,18 @@ def test_is_same_origin_request_ipv6_case_insensitive():
 
 def test_is_same_origin_request_ipv6_different_host_cross_origin():
     from main import _is_same_origin_request
-
     req = _build_request("[::1]:8902", origin = "http://[2001:db8::1]:8902")
     assert _is_same_origin_request(req) is False
 
 
 def test_is_same_origin_request_ipv6_port_mismatch_cross_origin():
     from main import _is_same_origin_request
-
     req = _build_request("[::1]:8902", origin = "http://[::1]:9999")
     assert _is_same_origin_request(req) is False
 
 
 def test_is_same_origin_request_ipv6_userinfo_stripped():
     from main import _is_same_origin_request
-
     req = _build_request("user:pass@[::1]:8902", origin = "http://[::1]:8902")
     assert _is_same_origin_request(req) is True
 
@@ -93,9 +93,7 @@ def test_is_same_origin_request_data_url_origin_is_cross_origin():
     """
     from main import _is_same_origin_request
 
-    req = _build_request(
-        "127.0.0.1:8902", origin = "data:text/html,"
-    )
+    req = _build_request("127.0.0.1:8902", origin = "data:text/html,")
     assert _is_same_origin_request(req) is False
 
 
@@ -150,7 +148,6 @@ def test_is_same_origin_request_localhost_vs_127_is_cross_origin():
 
 def test_is_same_origin_request_127_vs_localhost_is_cross_origin():
     from main import _is_same_origin_request
-
     req = _build_request("localhost:8902", origin = "http://127.0.0.1:8902")
     assert _is_same_origin_request(req) is False
 
diff --git a/studio/backend/tests/test_inference_model_validation.py b/studio/backend/tests/test_inference_model_validation.py
index ebd9c6c722..faf5a67873 100644
--- a/studio/backend/tests/test_inference_model_validation.py
+++ b/studio/backend/tests/test_inference_model_validation.py
@@ -202,10 +202,7 @@ def test_walkback_skips_explicitly_consumed_tool_call_id():
             {"role": "tool", "content": "second result"},
         ]
     )
-    assert [m.tool_call_id for m in req.messages if m.role == "tool"] == [
-        "call_a",
-        "call_b",
-    ]
+    assert [m.tool_call_id for m in req.messages if m.role == "tool"] == ["call_a", "call_b"]
 
 
 def test_walkback_handles_malformed_function_string():
diff --git a/studio/backend/tests/test_kv_cache_estimation.py b/studio/backend/tests/test_kv_cache_estimation.py
index d52a58a25c..001b5f1bee 100644
--- a/studio/backend/tests/test_kv_cache_estimation.py
+++ b/studio/backend/tests/test_kv_cache_estimation.py
@@ -128,7 +128,9 @@ def _make_gguf_bytes(arch: str, kv_pairs: dict) -> bytes:
 
 
 def _backend_from_gguf(
-    arch: str, fields: dict, general: dict | None = None
+    arch: str,
+    fields: dict,
+    general: dict | None = None,
 ) -> LlamaCppBackend:
     """Create a LlamaCppBackend with parsed GGUF metadata from given fields.
 
@@ -346,8 +348,7 @@ class TestArchSwaPatternDefaults:
         assert kv_default > 0
         assert kv_legacy > 0
         assert kv_default < kv_legacy, (
-            f"arch fallback should under-shoot legacy estimate: "
-            f"{kv_default} >= {kv_legacy}"
+            f"arch fallback should under-shoot legacy estimate: " f"{kv_default} >= {kv_legacy}"
         )
 
     def test_scalar_sliding_window_pattern_expanded(self):
@@ -430,25 +431,12 @@ class TestDynamicSwaResolver:
         from core.inference.llama_cpp import _period_from_layer_types
 
         # gemma3 (1 global per 6), gpt-oss (alternating), gemma3n (1 per 5).
-        assert (
-            _period_from_layer_types(
-                (["sliding_attention"] * 5 + ["full_attention"]) * 4
-            )
-            == 6
-        )
-        assert (
-            _period_from_layer_types(["sliding_attention", "full_attention"] * 12) == 2
-        )
-        assert (
-            _period_from_layer_types(
-                (["sliding_attention"] * 4 + ["full_attention"]) * 7
-            )
-            == 5
-        )
+        assert _period_from_layer_types((["sliding_attention"] * 5 + ["full_attention"]) * 4) == 6
+        assert _period_from_layer_types(["sliding_attention", "full_attention"] * 12) == 2
+        assert _period_from_layer_types((["sliding_attention"] * 4 + ["full_attention"]) * 7) == 5
 
     def test_period_from_layer_types_returns_none_for_aperiodic(self):
         from core.inference.llama_cpp import _period_from_layer_types
-
         lt = [
             "sliding_attention",
             "full_attention",
@@ -469,9 +457,7 @@ class TestDynamicSwaResolver:
             == "google/gemma-3-1b-it"
         )
         assert (
-            _hf_repo_from_url(
-                "https://huggingface.co/google/gemma-3-1b-it/blob/main/config.json"
-            )
+            _hf_repo_from_url("https://huggingface.co/google/gemma-3-1b-it/blob/main/config.json")
             == "google/gemma-3-1b-it"
         )
         for bad in [
@@ -524,9 +510,7 @@ class TestDynamicSwaResolver:
         b = _backend_from_gguf(
             "newmodel",
             _SWA_FIELDS,
-            general = {
-                "general.source.huggingface.repository": "vendor/newmodel-1b-instruct"
-            },
+            general = {"general.source.huggingface.repository": "vendor/newmodel-1b-instruct"},
         )
         assert b._sliding_window_pattern == [(i + 1) % 4 != 0 for i in range(12)]
         assert calls == ["vendor/newmodel-1b-instruct"]
@@ -573,9 +557,7 @@ class TestDynamicSwaResolver:
 
         monkeypatch.setattr(lc, "_fetch_swa_entry_from_hf", lambda repo_id: None)
         # Force the failure into the Tier 3 path; bypass Tier 2.5.
-        monkeypatch.setattr(
-            lc, "_resolve_swa_entry_from_transformers", lambda arch: None
-        )
+        monkeypatch.setattr(lc, "_resolve_swa_entry_from_transformers", lambda arch: None)
         b = _backend_from_gguf(
             "newmodel",
             _SWA_FIELDS,
@@ -621,18 +603,14 @@ class TestTransformersIntrospection:
 
         class _FakeLazyMapping(dict):
             def __getitem__(self, k):
-                return (
-                    _FakeBrokenConfig if k == "brokenarch" else super().__getitem__(k)
-                )
+                return _FakeBrokenConfig if k == "brokenarch" else super().__getitem__(k)
 
         import sys, types as _types
 
         fake_auto = _types.ModuleType("transformers.models.auto.configuration_auto")
         fake_auto.CONFIG_MAPPING_NAMES = {"brokenarch": "FakeBroken"}
         fake_auto.CONFIG_MAPPING = _FakeLazyMapping({"brokenarch": "FakeBroken"})
-        monkeypatch.setitem(
-            sys.modules, "transformers.models.auto.configuration_auto", fake_auto
-        )
+        monkeypatch.setitem(sys.modules, "transformers.models.auto.configuration_auto", fake_auto)
         assert lc._resolve_swa_entry_from_transformers("brokenarch") == 7
 
     def test_returns_none_when_transformers_unavailable(self, monkeypatch):
@@ -658,12 +636,9 @@ class TestTransformersIntrospection:
 
     def test_returns_none_for_arch_unknown_to_transformers(self):
         from core.inference.llama_cpp import _resolve_swa_entry_from_transformers
-
         assert _resolve_swa_entry_from_transformers("totally-fake-arch-xyz") is None
 
-    def test_full_resolver_uses_transformers_before_hf_fetch(
-        self, monkeypatch, tmp_path
-    ):
+    def test_full_resolver_uses_transformers_before_hf_fetch(self, monkeypatch, tmp_path):
         # With bootstrap empty, Tier 2.5 must answer before Tier 3 fires.
         self._isolate_cache(monkeypatch, tmp_path)
         from core.inference import llama_cpp as lc
@@ -1328,8 +1303,7 @@ class TestServerFlags:
             "_kv_key_length": 256,
             "_kv_value_length": 256,
             "_sliding_window": 512,
-            "_sliding_window_pattern": [True, True, True, True, True, False] * 4
-            + [True, True],
+            "_sliding_window_pattern": [True, True, True, True, True, False] * 4 + [True, True],
         }
         defaults.update(overrides)
         b = LlamaCppBackend()
@@ -1385,9 +1359,7 @@ class TestServerFlags:
     def test_swa_full_suppresses_checkpoint_term(self):
         b = self._swa_backend()
         with_cp = b._estimate_kv_cache_bytes(8192, "f16", ctx_checkpoints = 8)
-        with_cp_full = b._estimate_kv_cache_bytes(
-            8192, "f16", ctx_checkpoints = 8, swa_full = True
-        )
+        with_cp_full = b._estimate_kv_cache_bytes(8192, "f16", ctx_checkpoints = 8, swa_full = True)
         no_cp_full = b._estimate_kv_cache_bytes(8192, "f16", swa_full = True)
         # Checkpoints only matter when SWA layers don't already keep n_ctx.
         assert with_cp_full == no_cp_full
@@ -1405,9 +1377,7 @@ class TestServerFlags:
         for slots in (1, 2, 4, 8):
             for unified in (True, False):
                 assert (
-                    b._estimate_kv_cache_bytes(
-                        4096, "f16", n_parallel = slots, kv_unified = unified
-                    )
+                    b._estimate_kv_cache_bytes(4096, "f16", n_parallel = slots, kv_unified = unified)
                     == baseline
                 )
 
@@ -1416,9 +1386,7 @@ class TestServerFlags:
         baseline = b._estimate_kv_cache_bytes(4096, "f16")
         for unified in (True, False):
             assert (
-                b._estimate_kv_cache_bytes(
-                    4096, "f16", n_parallel = 0, kv_unified = unified
-                )
+                b._estimate_kv_cache_bytes(4096, "f16", n_parallel = 0, kv_unified = unified)
                 == baseline
             )
 
@@ -1432,9 +1400,7 @@ class TestServerFlags:
         per_token_swa = 4 * (256 + 256) * 2  # k_swa/val_swa fall back
         per_slot_swa_cells = min(ctx, 2 * swa)  # not clamped at parallel=1
         global_bytes = sum(
-            ctx * per_token_global
-            for f in b._sliding_window_pattern[: b._n_layers]
-            if not f
+            ctx * per_token_global for f in b._sliding_window_pattern[: b._n_layers] if not f
         )
         swa_bytes_per_slot = sum(
             per_slot_swa_cells * per_token_swa
@@ -1445,16 +1411,12 @@ class TestServerFlags:
         assert global_bytes + swa_bytes_per_slot == baseline
         # Only SWA portion scales by parallel
         for slots in (1, 2, 3, 4):
-            scaled = b._estimate_kv_cache_bytes(
-                ctx, "f16", n_parallel = slots, kv_unified = False
-            )
+            scaled = b._estimate_kv_cache_bytes(ctx, "f16", n_parallel = slots, kv_unified = False)
             # SWA cells get clamped to per_slot_ctx when ctx/slots < 2*swa
             per_slot_ctx = max(1, ctx // slots)
             cells = min(ctx, 2 * swa, per_slot_ctx)
             swa_bps = sum(
-                cells * per_token_swa
-                for f in b._sliding_window_pattern[: b._n_layers]
-                if f
+                cells * per_token_swa for f in b._sliding_window_pattern[: b._n_layers] if f
             )
             assert scaled == global_bytes + slots * swa_bps
 
@@ -1469,9 +1431,7 @@ class TestServerFlags:
         for slots in (1, 2, 4, 8):
             for unified in (True, False):
                 assert (
-                    b._estimate_kv_cache_bytes(
-                        8192, "f16", n_parallel = slots, kv_unified = unified
-                    )
+                    b._estimate_kv_cache_bytes(8192, "f16", n_parallel = slots, kv_unified = unified)
                     == baseline
                 )
 
@@ -1493,9 +1453,7 @@ class TestServerFlags:
         baseline = b._estimate_kv_cache_bytes(ctx, "f16")
         flagged = b._estimate_kv_cache_bytes(ctx, "f16", ctx_checkpoints = 4)
         # 22 SWA layers * 4 checkpoints * 512 cells * 4 heads * (256+256) * 2 bytes
-        n_swa_layers = sum(
-            1 for f in [True, True, True, True, True, False] * 4 + [True, True] if f
-        )
+        n_swa_layers = sum(1 for f in [True, True, True, True, True, False] * 4 + [True, True] if f)
         per_layer = 4 * 512 * 4 * (256 + 256) * 2
         assert flagged == baseline + n_swa_layers * per_layer
 
@@ -1529,9 +1487,7 @@ class TestServerFlags:
         flagged = b._estimate_kv_cache_bytes(
             ctx, "f16", ctx_checkpoints = 4, n_parallel = slots, kv_unified = False
         )
-        assert flagged == global_bytes + slots * (
-            swa_bytes_per_slot + cp_extra_per_slot
-        )
+        assert flagged == global_bytes + slots * (swa_bytes_per_slot + cp_extra_per_slot)
 
     # ── --kv-offload (kv_on_gpu) ───────────────────────────────────
 
@@ -1655,9 +1611,7 @@ class TestParallelSWAScaling:
             "_kv_value_length": 256,
             "_sliding_window": 512,
             # 15 SWA + 3 global, mirrors gemma-3-270m
-            "_sliding_window_pattern": [
-                t == "swa" for t in (["swa"] * 5 + ["global"]) * 3
-            ],
+            "_sliding_window_pattern": [t == "swa" for t in (["swa"] * 5 + ["global"]) * 3],
         }
         defaults.update(overrides)
         b = LlamaCppBackend()
@@ -1673,9 +1627,7 @@ class TestParallelSWAScaling:
         for slots in (1, 2, 4, 8):
             for unified in (True, False):
                 assert (
-                    b._estimate_kv_cache_bytes(
-                        8192, "f16", n_parallel = slots, kv_unified = unified
-                    )
+                    b._estimate_kv_cache_bytes(8192, "f16", n_parallel = slots, kv_unified = unified)
                     == baseline
                 )
 
@@ -1729,9 +1681,7 @@ class TestParallelSWAScaling:
             cells = min(ctx, 2 * swa, per_slot_ctx)
             swa_bps = n_swa * cells * per_token
             for unified in (True, False):
-                got = b._estimate_kv_cache_bytes(
-                    ctx, "f16", n_parallel = slots, kv_unified = unified
-                )
+                got = b._estimate_kv_cache_bytes(ctx, "f16", n_parallel = slots, kv_unified = unified)
                 assert got == global_bytes + slots * swa_bps
 
     def test_swa_fallback_scales_only_swa_portion(self):
@@ -1776,8 +1726,7 @@ class TestParallelSWAScaling:
         baseline = b._estimate_kv_cache_bytes(ctx, "f16", swa_full = True)
         for slots in (1, 2, 4, 8):
             assert (
-                b._estimate_kv_cache_bytes(ctx, "f16", swa_full = True, n_parallel = slots)
-                == baseline
+                b._estimate_kv_cache_bytes(ctx, "f16", swa_full = True, n_parallel = slots) == baseline
             )
 
     # ── kv_unified: no-op for memory math ──────────────────────────
@@ -1791,12 +1740,8 @@ class TestParallelSWAScaling:
         ]
         for label, b in backends:
             for slots in (1, 2, 4, 8):
-                u = b._estimate_kv_cache_bytes(
-                    8192, "f16", n_parallel = slots, kv_unified = True
-                )
-                nu = b._estimate_kv_cache_bytes(
-                    8192, "f16", n_parallel = slots, kv_unified = False
-                )
+                u = b._estimate_kv_cache_bytes(8192, "f16", n_parallel = slots, kv_unified = True)
+                nu = b._estimate_kv_cache_bytes(8192, "f16", n_parallel = slots, kv_unified = False)
                 assert u == nu, f"{label} parallel={slots} unified-mismatch"
 
     # ── Empirical Gemma-3 270m formula ─────────────────────────────
@@ -1937,9 +1882,7 @@ class TestSharedKVLayers:
         assert full_in_unshared == 4
         kv_per = 4 * (256 + 256) * 2
         swa_cells = min(ctx, 2 * 1024)
-        expected = (
-            full_in_unshared * ctx * kv_per + sliding_in_unshared * swa_cells * kv_per
-        )
+        expected = full_in_unshared * ctx * kv_per + sliding_in_unshared * swa_cells * kv_per
         assert b._estimate_kv_cache_bytes(ctx, "f16") == expected
 
     def test_shared_layers_reduces_estimate(self):
@@ -1995,9 +1938,7 @@ class TestSharedKVLayers:
         per_slot_ctx = max(1, ctx // slots)
         swa_cells = min(ctx, 2 * swa, per_slot_ctx)
         swa_bytes_per_slot = sliding_in_unshared * swa_cells * per_token
-        flagged = b._estimate_kv_cache_bytes(
-            ctx, "f16", n_parallel = slots, kv_unified = False
-        )
+        flagged = b._estimate_kv_cache_bytes(ctx, "f16", n_parallel = slots, kv_unified = False)
         assert flagged == global_bytes + slots * swa_bytes_per_slot
 
     def test_composes_with_ctx_checkpoints(self):
diff --git a/studio/backend/tests/test_lemonade_llamacpp_rocm_bins_mock.py b/studio/backend/tests/test_lemonade_llamacpp_rocm_bins_mock.py
index 5d2d672890..f887f7747c 100644
--- a/studio/backend/tests/test_lemonade_llamacpp_rocm_bins_mock.py
+++ b/studio/backend/tests/test_lemonade_llamacpp_rocm_bins_mock.py
@@ -134,12 +134,8 @@ def test_unknown_gpu_not_in_families():
 def test_asset_resolves_for_known_gpu(gfx, os_prefix, windows):
     host = _make_rocm_host(gfx, windows = windows)
     with patch.object(_mod, "fetch_json", return_value = _stub_lemonade_release()):
-        result = resolve_lemonade_rocm_choice(
-            host, os_prefix, "default", llama_tag = "latest"
-        )
-    assert (
-        result is not None
-    ), f"Installer will NOT fetch lemonade binary for {gfx} ({os_prefix})"
+        result = resolve_lemonade_rocm_choice(host, os_prefix, "default", llama_tag = "latest")
+    assert result is not None, f"Installer will NOT fetch lemonade binary for {gfx} ({os_prefix})"
     assert _lookup_family(gfx) in result.name
     assert result.url.startswith("https://github.com/lemonade-sdk/llamacpp-rocm")
 
@@ -213,9 +209,7 @@ def test_simple_policy_plans_lemonade_for_windows_hip_host():
         "assets": [],
     }
     with patch.object(_mod, "fetch_json", return_value = _stub_lemonade_release()):
-        plan = direct_upstream_release_plan(
-            release, host, "ggml-org/llama.cpp", "latest"
-        )
+        plan = direct_upstream_release_plan(release, host, "ggml-org/llama.cpp", "latest")
     assert plan is not None, "Windows ROCm host should plan a lemonade HIP attempt"
     kinds = [a.install_kind for a in plan.attempts]
     assert (
@@ -245,9 +239,7 @@ def test_simple_policy_windows_hip_falls_back_to_upstream_when_lemonade_unavaila
     plan = direct_upstream_release_plan(release, host, "ggml-org/llama.cpp", "latest")
     assert plan is not None
     kinds = [a.install_kind for a in plan.attempts]
-    assert (
-        "windows-hip" in kinds
-    ), f"upstream HIP asset not included as fallback; got {kinds}"
+    assert "windows-hip" in kinds, f"upstream HIP asset not included as fallback; got {kinds}"
     hip_attempt = next(a for a in plan.attempts if a.install_kind == "windows-hip")
     assert hip_attempt.source_label == "upstream"
 
@@ -294,9 +286,7 @@ def test_lemonade_resolver_rejects_non_github_url(monkeypatch):
     }
     host = _make_rocm_host("gfx1151")
     with patch.object(_mod, "fetch_json", return_value = bad_release):
-        res = resolve_lemonade_rocm_choice(
-            host, "ubuntu", "linux-rocm", llama_tag = "latest"
-        )
+        res = resolve_lemonade_rocm_choice(host, "ubuntu", "linux-rocm", llama_tag = "latest")
     assert res is None
 
 
@@ -349,9 +339,7 @@ def test_lemonade_resolver_rejects_empty_browser_download_url():
     }
     host = _make_rocm_host("gfx1151")
     with patch.object(_mod, "fetch_json", return_value = release):
-        res = resolve_lemonade_rocm_choice(
-            host, "ubuntu", "linux-rocm", llama_tag = "latest"
-        )
+        res = resolve_lemonade_rocm_choice(host, "ubuntu", "linux-rocm", llama_tag = "latest")
     assert res is None
 
 
diff --git a/studio/backend/tests/test_llama_cpp_context_fit.py b/studio/backend/tests/test_llama_cpp_context_fit.py
index 6fe5372147..ee8d54443a 100644
--- a/studio/backend/tests/test_llama_cpp_context_fit.py
+++ b/studio/backend/tests/test_llama_cpp_context_fit.py
@@ -143,7 +143,11 @@ def _drive(
     model_size = int(model_gib * GIB)
     cache_type_kv = None
 
-    def fake_estimate(n_ctx_, _type = None, **_kwargs):
+    def fake_estimate(
+        n_ctx_,
+        _type = None,
+        **_kwargs,
+    ):
         return 0 if n_ctx_ <= 0 else n_ctx_ * kv_per_token_bytes
 
     inst._estimate_kv_cache_bytes = fake_estimate
@@ -233,9 +237,7 @@ def _drive(
     elif gpus:
         gpu_indices, use_fit = inst._select_gpus(model_size, gpus)
         if use_fit and not explicit_ctx:
-            effective_ctx = (
-                min(FALLBACK_CTX, effective_ctx) if effective_ctx > 0 else FALLBACK_CTX
-            )
+            effective_ctx = min(FALLBACK_CTX, effective_ctx) if effective_ctx > 0 else FALLBACK_CTX
 
     return {
         "c_arg": effective_ctx if effective_ctx > 0 else 0,
diff --git a/studio/backend/tests/test_llama_cpp_freshness.py b/studio/backend/tests/test_llama_cpp_freshness.py
index b32aeefcdb..c7dd111ee3 100644
--- a/studio/backend/tests/test_llama_cpp_freshness.py
+++ b/studio/backend/tests/test_llama_cpp_freshness.py
@@ -172,9 +172,7 @@ def test_latest_published_release_returns_none_on_network_failure(monkeypatch):
     assert fr.latest_published_release("unslothai/llama.cpp") is None
 
 
-def test_latest_published_release_keeps_old_cache_on_transient_failure(
-    monkeypatch, tmp_path
-):
+def test_latest_published_release_keeps_old_cache_on_transient_failure(monkeypatch, tmp_path):
     # Disk entry older than TTL + network fail -> return cached value.
     cache_dir = tmp_path / ".freshness"
     cache_dir.mkdir()
@@ -188,9 +186,7 @@ def test_latest_published_release_keeps_old_cache_on_transient_failure(
 # check_prebuilt_freshness end-to-end.
 
 
-def test_check_prebuilt_freshness_reports_stale_when_old_and_behind(
-    monkeypatch, tmp_path
-):
+def test_check_prebuilt_freshness_reports_stale_when_old_and_behind(monkeypatch, tmp_path):
     install_dir = tmp_path / "llama.cpp"
     _write_marker(
         install_dir,
@@ -200,9 +196,7 @@ def test_check_prebuilt_freshness_reports_stale_when_old_and_behind(
         .replace("+00:00", "Z"),
     )
     bin_path = _fake_binary(install_dir, layout = "root")
-    monkeypatch.setattr(
-        fr, "_fetch_latest_release_tag", lambda repo, timeout = 5.0: "b9300"
-    )
+    monkeypatch.setattr(fr, "_fetch_latest_release_tag", lambda repo, timeout = 5.0: "b9300")
     info = fr.check_prebuilt_freshness(str(bin_path))
     assert info["has_marker"] is True
     assert info["stale"] is True
@@ -222,9 +216,7 @@ def test_check_prebuilt_freshness_not_stale_when_tag_matches(monkeypatch, tmp_pa
         .replace("+00:00", "Z"),
     )
     bin_path = _fake_binary(install_dir, layout = "root")
-    monkeypatch.setattr(
-        fr, "_fetch_latest_release_tag", lambda repo, timeout = 5.0: "b9300"
-    )
+    monkeypatch.setattr(fr, "_fetch_latest_release_tag", lambda repo, timeout = 5.0: "b9300")
     info = fr.check_prebuilt_freshness(str(bin_path))
     assert info["stale"] is False
     assert info["installed_tag"] == "b9300"
@@ -242,9 +234,7 @@ def test_check_prebuilt_freshness_not_stale_within_threshold(monkeypatch, tmp_pa
         .replace("+00:00", "Z"),
     )
     bin_path = _fake_binary(install_dir, layout = "root")
-    monkeypatch.setattr(
-        fr, "_fetch_latest_release_tag", lambda repo, timeout = 5.0: "b9300"
-    )
+    monkeypatch.setattr(fr, "_fetch_latest_release_tag", lambda repo, timeout = 5.0: "b9300")
     info = fr.check_prebuilt_freshness(str(bin_path))
     assert info["stale"] is False
     assert info["age_days"] == 1
@@ -257,9 +247,7 @@ def test_check_prebuilt_freshness_fails_open_without_marker(tmp_path):
     assert info["stale"] is False
 
 
-def test_check_prebuilt_freshness_fails_open_when_github_unreachable(
-    monkeypatch, tmp_path
-):
+def test_check_prebuilt_freshness_fails_open_when_github_unreachable(monkeypatch, tmp_path):
     install_dir = tmp_path / "llama.cpp"
     _write_marker(
         install_dir,
@@ -276,15 +264,11 @@ def test_check_prebuilt_freshness_fails_open_when_github_unreachable(
     assert info["latest_tag"] is None
 
 
-def test_check_prebuilt_freshness_handles_unparseable_install_timestamp(
-    monkeypatch, tmp_path
-):
+def test_check_prebuilt_freshness_handles_unparseable_install_timestamp(monkeypatch, tmp_path):
     install_dir = tmp_path / "llama.cpp"
     _write_marker(install_dir, tag = "b9190", installed_at_utc = "not-a-date")
     bin_path = _fake_binary(install_dir, layout = "root")
-    monkeypatch.setattr(
-        fr, "_fetch_latest_release_tag", lambda repo, timeout = 5.0: "b9300"
-    )
+    monkeypatch.setattr(fr, "_fetch_latest_release_tag", lambda repo, timeout = 5.0: "b9300")
     info = fr.check_prebuilt_freshness(str(bin_path))
     assert info["stale"] is False
     assert info["age_days"] is None
@@ -300,9 +284,7 @@ def test_check_prebuilt_freshness_respects_custom_threshold(monkeypatch, tmp_pat
         .replace("+00:00", "Z"),
     )
     bin_path = _fake_binary(install_dir, layout = "root")
-    monkeypatch.setattr(
-        fr, "_fetch_latest_release_tag", lambda repo, timeout = 5.0: "b9300"
-    )
+    monkeypatch.setattr(fr, "_fetch_latest_release_tag", lambda repo, timeout = 5.0: "b9300")
     info = fr.check_prebuilt_freshness(str(bin_path), threshold_days = 1)
     assert info["stale"] is True
 
@@ -311,9 +293,7 @@ def test_check_prebuilt_freshness_respects_custom_threshold(monkeypatch, tmp_pat
 
 
 def test_format_stale_warning_contains_actionable_command():
-    msg = fr.format_stale_warning(
-        {"installed_tag": "b9190", "latest_tag": "b9300", "age_days": 5}
-    )
+    msg = fr.format_stale_warning({"installed_tag": "b9190", "latest_tag": "b9300", "age_days": 5})
     assert "b9190" in msg
     assert "b9300" in msg
     assert "5 days" in msg
@@ -321,8 +301,6 @@ def test_format_stale_warning_contains_actionable_command():
 
 
 def test_format_stale_warning_singular_day():
-    msg = fr.format_stale_warning(
-        {"installed_tag": "b9190", "latest_tag": "b9300", "age_days": 1}
-    )
+    msg = fr.format_stale_warning({"installed_tag": "b9190", "latest_tag": "b9300", "age_days": 1})
     assert "1 day" in msg
     assert "1 days" not in msg
diff --git a/studio/backend/tests/test_llama_cpp_load_progress.py b/studio/backend/tests/test_llama_cpp_load_progress.py
index f46751b798..f95d8bf1a4 100644
--- a/studio/backend/tests/test_llama_cpp_load_progress.py
+++ b/studio/backend/tests/test_llama_cpp_load_progress.py
@@ -150,7 +150,6 @@ class TestLoadProgressSingleShard:
         def fake_open(path, *args, **kwargs):
             if str(path).startswith("/proc/"):
                 import io
-
                 return io.StringIO(f"Name:\ttest\nVmRSS:\t{10 * 1024 ** 2}\tkB\n")
             return open(path, *args, **kwargs)  # fall through
 
@@ -175,7 +174,6 @@ class TestLoadProgressSingleShard:
         def fake_open(path, *args, **kwargs):
             if str(path).startswith("/proc/"):
                 import io
-
                 return io.StringIO(f"VmRSS:\t{8 * 1024 ** 2}\tkB\n")
             return open(path, *args, **kwargs)
 
@@ -210,7 +208,6 @@ class TestLoadProgressMultiShard:
         def fake_open(path, *args, **kwargs):
             if str(path).startswith("/proc/"):
                 import io
-
                 return io.StringIO("VmRSS:\t0\tkB\n")
             return open(path, *args, **kwargs)
 
@@ -233,7 +230,6 @@ class TestLoadProgressDegradation:
         def fake_open(path, *args, **kwargs):
             if str(path).startswith("/proc/"):
                 import io
-
                 return io.StringIO("VmRSS:\t1024\tkB\n")
             return open(path, *args, **kwargs)
 
diff --git a/studio/backend/tests/test_llama_cpp_load_progress_live.py b/studio/backend/tests/test_llama_cpp_load_progress_live.py
index beed8713c1..44a8f00834 100644
--- a/studio/backend/tests/test_llama_cpp_load_progress_live.py
+++ b/studio/backend/tests/test_llama_cpp_load_progress_live.py
@@ -75,7 +75,11 @@ pytestmark = pytest.mark.skipif(
 )
 
 
-def _make_backend(pid: int, gguf_path: str, healthy: bool = False):
+def _make_backend(
+    pid: int,
+    gguf_path: str,
+    healthy: bool = False,
+):
     inst = LlamaCppBackend.__new__(LlamaCppBackend)
     inst._process = type("P", (), {"pid": pid})()
     inst._gguf_path = gguf_path
diff --git a/studio/backend/tests/test_llama_cpp_max_context_threshold.py b/studio/backend/tests/test_llama_cpp_max_context_threshold.py
index 22e4cda7d1..aa0198892f 100644
--- a/studio/backend/tests/test_llama_cpp_max_context_threshold.py
+++ b/studio/backend/tests/test_llama_cpp_max_context_threshold.py
@@ -109,7 +109,12 @@ def _make_backend(native_ctx = 131072):
     return inst
 
 
-def _compute_max_available_ctx(native_ctx, model_gib, gpus, kv_per_token_bytes = 325_000):
+def _compute_max_available_ctx(
+    native_ctx,
+    model_gib,
+    gpus,
+    kv_per_token_bytes = 325_000,
+):
     """Run the ceiling-probe block from load_model and return the final
     ``max_available_ctx`` value the backend would assign to
     ``_max_context_length``.
diff --git a/studio/backend/tests/test_llama_cpp_mtp_detection.py b/studio/backend/tests/test_llama_cpp_mtp_detection.py
index 4a8276adc0..9e7944913a 100644
--- a/studio/backend/tests/test_llama_cpp_mtp_detection.py
+++ b/studio/backend/tests/test_llama_cpp_mtp_detection.py
@@ -77,9 +77,7 @@ def _enc_kv_string(key: str, value: str) -> bytes:
 
 
 def _enc_kv_uint32(key: str, value: int) -> bytes:
-    return (
-        _enc_string(key) + struct.pack(" Path:
     """Bash stub that prints `help_text` on --help."""
-    path.write_text("#!/usr/bin/env bash\n" f"cat <<'EOF'\n{help_text}\nEOF\n")
+    path.write_text(f"#!/usr/bin/env bash\ncat <<'EOF'\n{help_text}\nEOF\n")
     path.chmod(0o755)
     return path
 
@@ -532,8 +530,7 @@ def test_probe_server_capabilities_detects_renamed_mtp(tmp_path):
     # Renamed upstream: draft-mtp -> mtp.
     fake = _make_fake_llama_server(
         tmp_path / "llama-server",
-        "--spec-type [none|mtp|ngram-cache|ngram-simple|ngram-map-k|"
-        "ngram-map-k4v|ngram-mod]",
+        "--spec-type [none|mtp|ngram-cache|ngram-simple|ngram-map-k|ngram-map-k4v|ngram-mod]",
     )
     _clear_caps_cache()
     caps = LlamaCppBackend.probe_server_capabilities(str(fake))
@@ -655,14 +652,7 @@ def test_build_ngram_mod_flags_new():
 
 def test_build_ngram_mod_flags_legacy():
     flags = _build_ngram_mod_flags({"ngram_mod_flavor": "legacy"})
-    assert flags == [
-        "--spec-ngram-size-n",
-        "24",
-        "--draft-min",
-        "48",
-        "--draft-max",
-        "64",
-    ]
+    assert flags == ["--spec-ngram-size-n", "24", "--draft-min", "48", "--draft-max", "64"]
 
 
 def test_build_ngram_mod_flags_empty_when_unsupported():
@@ -672,9 +662,7 @@ def test_build_ngram_mod_flags_empty_when_unsupported():
 
 
 def test_build_ngram_mod_flags_respects_custom_values():
-    flags = _build_ngram_mod_flags(
-        {"ngram_mod_flavor": "new"}, n_match = 16, n_min = 24, n_max = 32
-    )
+    flags = _build_ngram_mod_flags({"ngram_mod_flavor": "new"}, n_match = 16, n_min = 24, n_max = 32)
     assert flags == [
         "--spec-ngram-mod-n-match",
         "16",
@@ -826,9 +814,7 @@ def _patch_probe(monkeypatch, ngram_supported):
     )
 
 
-def test_already_in_target_state_sub_3b_falls_back_to_ngram_mod_when_supported(
-    monkeypatch,
-):
+def test_already_in_target_state_sub_3b_falls_back_to_ngram_mod_when_supported(monkeypatch):
     # 0.8B MTP request -- load_model would have promoted to ngram-mod
     # (no MTP head); reload check must match a ngram-mod backend.
     _patch_probe(monkeypatch, ngram_supported = True)
@@ -1011,7 +997,12 @@ def test_canonicalize_spec_mode(value, expected):
 # ── _build_speculative_flags resolver matrix ──────────────────────
 
 
-def _resolver_backend(monkeypatch, *, ngram_supported = True, mtp_token = "draft-mtp"):
+def _resolver_backend(
+    monkeypatch,
+    *,
+    ngram_supported = True,
+    mtp_token = "draft-mtp",
+):
     """Backend with a deterministic probe so the resolver is hermetic."""
     fake = {
         "found": True,
@@ -1093,13 +1084,7 @@ _SUB_3B_MTP_MODEL = "unsloth/Qwen3.5-0.8B-MTP-GGUF"
     ],
 )
 def test_build_speculative_flags_matrix(
-    monkeypatch,
-    requested,
-    gpus,
-    model,
-    expect_spec_type,
-    expect_n_max,
-    expect_ngram_knobs,
+    monkeypatch, requested, gpus, model, expect_spec_type, expect_n_max, expect_ngram_knobs
 ):
     backend = _resolver_backend(monkeypatch)
     flags = backend._build_speculative_flags(
diff --git a/studio/backend/tests/test_llama_cpp_start_failure_classification.py b/studio/backend/tests/test_llama_cpp_start_failure_classification.py
index e647ff2c7d..202fd36c86 100644
--- a/studio/backend/tests/test_llama_cpp_start_failure_classification.py
+++ b/studio/backend/tests/test_llama_cpp_start_failure_classification.py
@@ -30,9 +30,7 @@ sys.modules.setdefault("loggers", _loggers_stub)
 # Give the structlog stub a real get_logger: a bare ModuleType poisons
 # sys.modules for later tests that call structlog.get_logger at import time.
 _structlog_stub = _types.ModuleType("structlog")
-_structlog_stub.get_logger = lambda *a, **k: __import__("logging").getLogger(
-    "structlog"
-)
+_structlog_stub.get_logger = lambda *a, **k: __import__("logging").getLogger("structlog")
 sys.modules.setdefault("structlog", _structlog_stub)
 if not hasattr(sys.modules["structlog"], "get_logger"):
     sys.modules["structlog"].get_logger = _structlog_stub.get_logger
@@ -109,8 +107,7 @@ class TestUnsupportedNonDiffusionArchitecture:
 
 class TestOllamaAndFallback:
     _OLLAMA_GGUF = (
-        f"/home/u/.ollama{__import__('os').sep}ollama_links"
-        f"{__import__('os').sep}m.gguf"
+        f"/home/u/.ollama{__import__('os').sep}ollama_links" f"{__import__('os').sep}m.gguf"
     )
 
     def test_ollama_compat_message_still_works(self):
diff --git a/studio/backend/tests/test_llama_cpp_wait_for_vram_settle.py b/studio/backend/tests/test_llama_cpp_wait_for_vram_settle.py
index 00295d6283..125b13782a 100644
--- a/studio/backend/tests/test_llama_cpp_wait_for_vram_settle.py
+++ b/studio/backend/tests/test_llama_cpp_wait_for_vram_settle.py
@@ -131,9 +131,7 @@ def test_stale_kill_skips_wait():
         LlamaCppBackend._wait_for_vram_settle(
             **_kw(since_kill = long_ago, max_wait = 2.0, interval = 0.25)
         )
-    assert (
-        state["calls"] == 0
-    ), "kill older than _VRAM_SETTLE_WINDOW_S must skip the wait"
+    assert state["calls"] == 0, "kill older than _VRAM_SETTLE_WINDOW_S must skip the wait"
 
 
 def test_empty_first_sample_returns_immediately():
@@ -221,9 +219,7 @@ def test_max_wait_respected_when_probe_is_slow():
         elapsed = time.monotonic() - start
     # First probe (0.30 s) + at most one short clipped sleep + bail.
     # Hard cap well below the old behaviour of 0.30 + 0.25 + 0.30 = 0.85.
-    assert (
-        elapsed < 0.85
-    ), f"helper exceeded the deadline due to slow probes: {elapsed:.3f}s"
+    assert elapsed < 0.85, f"helper exceeded the deadline due to slow probes: {elapsed:.3f}s"
 
 
 def test_gpu_index_set_change_returns():
diff --git a/studio/backend/tests/test_llama_cpp_windows_nvidia_path.py b/studio/backend/tests/test_llama_cpp_windows_nvidia_path.py
index 7d4719c0e7..a5c9d2255f 100644
--- a/studio/backend/tests/test_llama_cpp_windows_nvidia_path.py
+++ b/studio/backend/tests/test_llama_cpp_windows_nvidia_path.py
@@ -185,9 +185,7 @@ class TestWindowsPipNvidiaDllDirs:
         # If sys.prefix points to a path that doesn't exist (unusual,
         # but possible during test setup), the resolver must just
         # return [] rather than raising.
-        result = LlamaCppBackend._windows_pip_nvidia_dll_dirs(
-            "/this/path/does/not/exist/anywhere"
-        )
+        result = LlamaCppBackend._windows_pip_nvidia_dll_dirs("/this/path/does/not/exist/anywhere")
         assert result == []
 
     def test_picks_up_cu13_bin_x86_64_layout(self, tmp_path):
@@ -196,9 +194,7 @@ class TestWindowsPipNvidiaDllDirs:
         # ``nvidia/cu13/bin/x86_64/`` instead of ``nvidia//bin/``.
         # Without this, users on the new CUDA 13 wheel generation hit
         # the original #5106 failure mode.
-        dll_dir = (
-            tmp_path / "Lib" / "site-packages" / "nvidia" / "cu13" / "bin" / "x86_64"
-        )
+        dll_dir = tmp_path / "Lib" / "site-packages" / "nvidia" / "cu13" / "bin" / "x86_64"
         dll_dir.mkdir(parents = True)
         for name in ("cudart64_13.dll", "cublas64_13.dll", "cublasLt64_13.dll"):
             (dll_dir / name).write_bytes(b"")
diff --git a/studio/backend/tests/test_llama_server_args.py b/studio/backend/tests/test_llama_server_args.py
index 2f7431497d..2c7362a9ff 100644
--- a/studio/backend/tests/test_llama_server_args.py
+++ b/studio/backend/tests/test_llama_server_args.py
@@ -20,12 +20,7 @@ import pytest
 # full backend chain (fastapi / structlog / loggers / utils.hardware)
 # via core/inference/__init__.py. The validator is intentionally
 # dependency-free and unit-tests should reflect that.
-_LSA_PATH = (
-    Path(__file__).resolve().parent.parent
-    / "core"
-    / "inference"
-    / "llama_server_args.py"
-)
+_LSA_PATH = Path(__file__).resolve().parent.parent / "core" / "inference" / "llama_server_args.py"
 _spec = importlib.util.spec_from_file_location("_lsa_test_only", _LSA_PATH)
 _lsa = importlib.util.module_from_spec(_spec)
 _spec.loader.exec_module(_lsa)
@@ -359,14 +354,7 @@ def test_strip_shadowing_flags_keeps_cache_when_cache_disabled():
         ["--cache-type-k", "q8_0", "--cache-type-v", "q8_0", "--top-k", "20"],
         strip_cache = False,
     )
-    assert out == [
-        "--cache-type-k",
-        "q8_0",
-        "--cache-type-v",
-        "q8_0",
-        "--top-k",
-        "20",
-    ]
+    assert out == ["--cache-type-k", "q8_0", "--cache-type-v", "q8_0", "--top-k", "20"]
 
 
 def test_strip_shadowing_flags_keeps_spec_when_spec_disabled():
@@ -374,14 +362,7 @@ def test_strip_shadowing_flags_keeps_spec_when_spec_disabled():
         ["--spec-type", "ngram-mod", "--draft-min", "48", "--top-k", "20"],
         strip_spec = False,
     )
-    assert out == [
-        "--spec-type",
-        "ngram-mod",
-        "--draft-min",
-        "48",
-        "--top-k",
-        "20",
-    ]
+    assert out == ["--spec-type", "ngram-mod", "--draft-min", "48", "--top-k", "20"]
 
 
 def test_strip_shadowing_flags_drops_mtp_flags_when_requested():
@@ -505,9 +486,7 @@ def test_strip_shadowing_flags_jinja_boolean_preserves_positional():
 
 
 def test_strip_shadowing_flags_no_jinja_boolean_preserves_positional():
-    out = strip_shadowing_flags(
-        ["--no-jinja", "trailing-positional"], strip_template = True
-    )
+    out = strip_shadowing_flags(["--no-jinja", "trailing-positional"], strip_template = True)
     assert out == ["trailing-positional"]
 
 
diff --git a/studio/backend/tests/test_login_rate_limit.py b/studio/backend/tests/test_login_rate_limit.py
index c8498d4857..1b084cf436 100644
--- a/studio/backend/tests/test_login_rate_limit.py
+++ b/studio/backend/tests/test_login_rate_limit.py
@@ -45,9 +45,12 @@ def env_trust_proxy(monkeypatch):
 
 
 class _FakeRequest:
-    def __init__(self, client_host = "127.0.0.1", headers = None):
+    def __init__(
+        self,
+        client_host = "127.0.0.1",
+        headers = None,
+    ):
         from starlette.datastructures import Headers
-
         self.client = type("Client", (), {"host": client_host})()
         self.headers = Headers(headers or {})
 
@@ -58,12 +61,10 @@ class _FakeRequest:
 class TestClientIp:
     def test_uses_request_client_host_by_default(self, env_no_proxy):
         from routes.auth import _client_ip
-
         assert _client_ip(_FakeRequest("203.0.113.5")) == "203.0.113.5"
 
     def test_ignores_xff_when_trust_off(self, env_no_proxy):
         from routes.auth import _client_ip
-
         req = _FakeRequest(
             "127.0.0.1",
             {"x-forwarded-for": "198.51.100.7, 10.0.0.1"},
@@ -74,7 +75,6 @@ class TestClientIp:
 
     def test_honours_first_xff_when_trust_on(self, env_trust_proxy):
         from routes.auth import _client_ip
-
         req = _FakeRequest(
             "127.0.0.1",
             {"x-forwarded-for": "198.51.100.7, 10.0.0.1"},
@@ -83,12 +83,10 @@ class TestClientIp:
 
     def test_falls_back_to_client_host_when_xff_missing(self, env_trust_proxy):
         from routes.auth import _client_ip
-
         assert _client_ip(_FakeRequest("203.0.113.9")) == "203.0.113.9"
 
     def test_honours_forwarded_header_when_trust_on(self, env_trust_proxy):
         from routes.auth import _client_ip
-
         req = _FakeRequest(
             "127.0.0.1",
             {"forwarded": 'for="198.51.100.42";proto=https'},
@@ -104,34 +102,22 @@ class TestClientIp:
 
     def test_xff_strips_ipv4_port(self, env_trust_proxy):
         from routes.auth import _client_ip
-
-        req = _FakeRequest(
-            "127.0.0.1", {"x-forwarded-for": "198.51.100.7:50001, 10.0.0.1"}
-        )
+        req = _FakeRequest("127.0.0.1", {"x-forwarded-for": "198.51.100.7:50001, 10.0.0.1"})
         assert _client_ip(req) == "198.51.100.7"
 
     def test_xff_strips_bracketed_ipv6_port(self, env_trust_proxy):
         from routes.auth import _client_ip
-
-        req = _FakeRequest(
-            "127.0.0.1", {"x-forwarded-for": "[2001:db8::1]:50001, 10.0.0.1"}
-        )
+        req = _FakeRequest("127.0.0.1", {"x-forwarded-for": "[2001:db8::1]:50001, 10.0.0.1"})
         assert _client_ip(req) == "2001:db8::1"
 
     def test_forwarded_strips_ipv4_port(self, env_trust_proxy):
         from routes.auth import _client_ip
-
-        req = _FakeRequest(
-            "127.0.0.1", {"forwarded": 'for="198.51.100.7:50001";proto=https'}
-        )
+        req = _FakeRequest("127.0.0.1", {"forwarded": 'for="198.51.100.7:50001";proto=https'})
         assert _client_ip(req) == "198.51.100.7"
 
     def test_forwarded_strips_bracketed_ipv6_port(self, env_trust_proxy):
         from routes.auth import _client_ip
-
-        req = _FakeRequest(
-            "127.0.0.1", {"forwarded": 'for="[2001:db8::1]:50001";proto=https'}
-        )
+        req = _FakeRequest("127.0.0.1", {"forwarded": 'for="[2001:db8::1]:50001";proto=https'})
         assert _client_ip(req) == "2001:db8::1"
 
     def test_forwarded_isolates_first_element(self, env_trust_proxy):
@@ -247,9 +233,7 @@ class TestLogin429Body:
         import secrets as _secrets
 
         monkeypatch.setattr(storage, "DB_PATH", tmp_path / "auth.db")
-        monkeypatch.setattr(
-            storage, "_BOOTSTRAP_PW_PATH", tmp_path / ".bootstrap_password"
-        )
+        monkeypatch.setattr(storage, "_BOOTSTRAP_PW_PATH", tmp_path / ".bootstrap_password")
         monkeypatch.setattr(storage, "_bootstrap_password", None)
         storage.create_initial_user(
             username = storage.DEFAULT_ADMIN_USERNAME,
diff --git a/studio/backend/tests/test_mcp_servers.py b/studio/backend/tests/test_mcp_servers.py
index 10a6eb012b..0d263d7630 100644
--- a/studio/backend/tests/test_mcp_servers.py
+++ b/studio/backend/tests/test_mcp_servers.py
@@ -45,9 +45,7 @@ def test_list_servers_ordered_by_created_at(tmp_path, monkeypatch):
 def test_update_server_coerces_bools(tmp_path, monkeypatch):
     _reset_db(tmp_path, monkeypatch)
     mcp_servers_db.create_server(id = "srv1", display_name = "A", url = "https://a/m")
-    assert mcp_servers_db.update_server(
-        "srv1", {"is_enabled": False, "use_oauth": True}
-    )
+    assert mcp_servers_db.update_server("srv1", {"is_enabled": False, "use_oauth": True})
     row = mcp_servers_db.get_server("srv1")
     assert row["is_enabled"] == 0
     assert row["use_oauth"] == 1
@@ -81,7 +79,6 @@ def test_validate_url_accepts_http_and_https():
 @pytest.mark.parametrize("bad", ["", "   ", "ftp://x", "http://", "noscheme.com"])
 def test_validate_url_rejects_bad(bad):
     from routes.mcp_servers import _validate_url
-
     with pytest.raises(HTTPException) as exc:
         _validate_url(bad)
     assert exc.value.status_code == 400
@@ -90,9 +87,7 @@ def test_validate_url_rejects_bad(bad):
 def test_normalize_headers():
     from routes.mcp_servers import _normalize_headers
 
-    assert _normalize_headers({"  Auth  ": "Bearer x", "": "ignored"}) == {
-        "Auth": "Bearer x"
-    }
+    assert _normalize_headers({"  Auth  ": "Bearer x", "": "ignored"}) == {"Auth": "Bearer x"}
     assert _normalize_headers({"X": 42}) == {"X": "42"}
     assert _normalize_headers({}) is None
     assert _normalize_headers(None) is None
@@ -104,15 +99,12 @@ def test_changes_from_payload_tristate_headers():
     from models.mcp_servers import McpServerUpdate
 
     # omitted → key absent
-    assert "headers_json" not in _changes_from_payload(
-        McpServerUpdate(display_name = "x")
-    )
+    assert "headers_json" not in _changes_from_payload(McpServerUpdate(display_name = "x"))
     # null → stored as None (clear all headers)
     assert _changes_from_payload(McpServerUpdate(headers = None))["headers_json"] is None
     # dict → serialised JSON
     assert (
-        _changes_from_payload(McpServerUpdate(headers = {"a": "1"}))["headers_json"]
-        == '{"a": "1"}'
+        _changes_from_payload(McpServerUpdate(headers = {"a": "1"}))["headers_json"] == '{"a": "1"}'
     )
 
 
@@ -135,7 +127,6 @@ def test_mcp_specs_skip_oversized_names():
 
 def test_execute_tool_malformed_mcp_name():
     from core.inference.tools import execute_tool
-
     out = execute_tool("mcp__no_double_underscore", {})
     assert out.startswith("Error: malformed MCP tool name")
 
@@ -143,11 +134,7 @@ def test_execute_tool_malformed_mcp_name():
 def test_execute_tool_unknown_server(tmp_path, monkeypatch):
     _reset_db(tmp_path, monkeypatch)
     from core.inference.tools import execute_tool
-
-    assert (
-        execute_tool("mcp__missing__do_thing", {})
-        == "Error: MCP server 'missing' not found"
-    )
+    assert execute_tool("mcp__missing__do_thing", {}) == "Error: MCP server 'missing' not found"
 
 
 def test_execute_tool_disabled_server(tmp_path, monkeypatch):
@@ -160,10 +147,7 @@ def test_execute_tool_disabled_server(tmp_path, monkeypatch):
     )
     from core.inference.tools import execute_tool
 
-    assert (
-        execute_tool("mcp__srv1__do_thing", {})
-        == "Error: MCP server 'srv1' is disabled"
-    )
+    assert execute_tool("mcp__srv1__do_thing", {}) == "Error: MCP server 'srv1' is disabled"
 
 
 def test_mcp_specs_skip_invalid_openai_function_names():
@@ -219,7 +203,6 @@ def test_call_tool_sync_respects_pre_set_cancel_event(monkeypatch):
 
         async def call_tool(self, name, args):
             import asyncio as _asyncio
-
             await _asyncio.sleep(30)  # never finishes within the test
 
     monkeypatch.setattr(mcp_client, "_client", lambda *a, **kw: _StubClient())
@@ -439,8 +422,7 @@ def test_tool_healing_strip_handles_hyphenated_function_names():
     from core.tool_healing import strip_tool_call_markup
 
     out = strip_tool_call_markup(
-        "before "
-        "x after"
+        "before x after"
     )
     assert out == "before  after"
 
@@ -558,9 +540,7 @@ def test_tool_xml_parser_handles_hyphenated_function_names():
     from core.inference.tool_call_parser import parse_tool_calls_from_text
 
     calls = parse_tool_calls_from_text(
-        ""
-        "octocat/hello"
-        ""
+        "octocat/hello"
     )
     assert len(calls) == 1
     assert calls[0]["function"]["name"] == "mcp__srv__list-issues"
@@ -584,8 +564,7 @@ def test_tool_xml_strip_handles_hyphenated_function_names():
     rx = ns["_TOOL_XML_RE"]
     stripped = rx.sub(
         "",
-        "before "
-        "x after",
+        "before x after",
     )
     assert stripped == "before  after"
 
diff --git a/studio/backend/tests/test_mcp_stdio_improvements.py b/studio/backend/tests/test_mcp_stdio_improvements.py
index e980e6a057..515e39d5b6 100644
--- a/studio/backend/tests/test_mcp_stdio_improvements.py
+++ b/studio/backend/tests/test_mcp_stdio_improvements.py
@@ -62,9 +62,7 @@ def test_create_forces_oauth_off_for_stdio(tmp_path, monkeypatch):
     _enable(monkeypatch)
     resp = asyncio.run(
         routes_mcp.create_mcp_server(
-            McpServerCreate(
-                display_name = "FS", url = "npx -y server /tmp", use_oauth = True
-            ),
+            McpServerCreate(display_name = "FS", url = "npx -y server /tmp", use_oauth = True),
             current_subject = "u",
         )
     )
@@ -94,12 +92,8 @@ def test_update_url_to_stdio_clears_oauth(tmp_path, monkeypatch):
     _reset_db(tmp_path, monkeypatch)
     _enable(monkeypatch)
     monkeypatch.setattr(mcp_client, "_oauth_token_store", None)
-    monkeypatch.setattr(
-        routes_mcp, "clear_oauth_tokens_async", lambda *a, **k: asyncio.sleep(0)
-    )
-    mcp_servers_db.create_server(
-        id = "s1", display_name = "A", url = "https://a/mcp", use_oauth = True
-    )
+    monkeypatch.setattr(routes_mcp, "clear_oauth_tokens_async", lambda *a, **k: asyncio.sleep(0))
+    mcp_servers_db.create_server(id = "s1", display_name = "A", url = "https://a/mcp", use_oauth = True)
     resp = asyncio.run(
         routes_mcp.update_mcp_server(
             "s1", McpServerUpdate(url = "npx -y server /tmp"), current_subject = "u"
@@ -148,9 +142,7 @@ def test_switch_keeps_explicitly_supplied_headers(tmp_path, monkeypatch):
     resp = asyncio.run(
         routes_mcp.update_mcp_server(
             "s1",
-            McpServerUpdate(
-                url = "https://remote/mcp", headers = {"Authorization": "Bearer new"}
-            ),
+            McpServerUpdate(url = "https://remote/mcp", headers = {"Authorization": "Bearer new"}),
             current_subject = "u",
         )
     )
@@ -171,9 +163,7 @@ def test_same_transport_edit_keeps_headers(tmp_path, monkeypatch):
     )
     # editing only the display name (still stdio) must not wipe env vars
     resp = asyncio.run(
-        routes_mcp.update_mcp_server(
-            "s1", McpServerUpdate(display_name = "B"), current_subject = "u"
-        )
+        routes_mcp.update_mcp_server("s1", McpServerUpdate(display_name = "B"), current_subject = "u")
     )
     assert resp.headers == {"API_KEY": "secret"}
 
@@ -183,7 +173,6 @@ def test_same_transport_edit_keeps_headers(tmp_path, monkeypatch):
 
 def test_validate_url_rejects_url_scheme_command_when_enabled(monkeypatch):
     from routes.mcp_servers import _validate_url
-
     _enable(monkeypatch)
     for bad in ["ftp://host/x", "file:///etc/passwd", "ws://h/y"]:
         with pytest.raises(HTTPException) as exc:
@@ -193,12 +182,9 @@ def test_validate_url_rejects_url_scheme_command_when_enabled(monkeypatch):
 
 def test_validate_url_allows_url_in_argument(monkeypatch):
     from routes.mcp_servers import _validate_url
-
     _enable(monkeypatch)
     # :// inside an ARGUMENT (not the first token) is still a valid command
-    assert _validate_url("npx server --url https://x/mcp") == (
-        "npx server --url https://x/mcp"
-    )
+    assert _validate_url("npx server --url https://x/mcp") == ("npx server --url https://x/mcp")
 
 
 # ── P6: Data Recipe stdio path obeys the same host gate ─────────────
diff --git a/studio/backend/tests/test_mcp_stdio_pr5863.py b/studio/backend/tests/test_mcp_stdio_pr5863.py
index f49edcdaae..277306836b 100644
--- a/studio/backend/tests/test_mcp_stdio_pr5863.py
+++ b/studio/backend/tests/test_mcp_stdio_pr5863.py
@@ -83,9 +83,7 @@ def transport(monkeypatch):
     monkeypatch.setattr(
         mcp_client,
         "_client",
-        lambda url, headers, use_oauth = False: _RecordingClient(
-            url, headers, use_oauth, recorder
-        ),
+        lambda url, headers, use_oauth = False: _RecordingClient(url, headers, use_oauth, recorder),
     )
     return recorder
 
@@ -130,9 +128,12 @@ def test_parse_basic_argv():
 
 def test_parse_keeps_url_argument_as_one_command():
     # gemini "high": a :// inside an ARGUMENT must not break the command.
-    assert mcp_client.parse_stdio_command(
-        "npx server --endpoint https://example.com/mcp"
-    ) == ["npx", "server", "--endpoint", "https://example.com/mcp"]
+    assert mcp_client.parse_stdio_command("npx server --endpoint https://example.com/mcp") == [
+        "npx",
+        "server",
+        "--endpoint",
+        "https://example.com/mcp",
+    ]
 
 
 def test_parse_quoted_arg():
@@ -158,9 +159,7 @@ def test_parse_windows_strips_wrapping_quotes(monkeypatch):
     # gemini "medium": posix=False keeps backslash paths but also the wrapping
     # quotes; the PR strips a matched pair so argv[0] reaches the OS clean.
     monkeypatch.setattr(sys, "platform", "win32")
-    parts = mcp_client.parse_stdio_command(
-        r'"C:\Program Files\node\node.exe" server.js'
-    )
+    parts = mcp_client.parse_stdio_command(r'"C:\Program Files\node\node.exe" server.js')
     assert parts[0] == r"C:\Program Files\node\node.exe"
     assert parts[1] == "server.js"
 
@@ -242,14 +241,10 @@ def test_validate_url_gate_on_accepts_stdio(monkeypatch):
     # http still works when stdio is on
     assert _validate_url("https://x/mcp") == "https://x/mcp"
     # url-bearing argument accepted as a command
-    assert _validate_url("npx server --url https://x/mcp") == (
-        "npx server --url https://x/mcp"
-    )
+    assert _validate_url("npx server --url https://x/mcp") == ("npx server --url https://x/mcp")
     # A lone token is ambiguous; keep the prior behaviour and accept it as a
     # command rather than guessing it's a URL (no regression for single binaries).
-    assert (
-        _validate_url("/usr/local/bin/my-mcp-server") == "/usr/local/bin/my-mcp-server"
-    )
+    assert _validate_url("/usr/local/bin/my-mcp-server") == "/usr/local/bin/my-mcp-server"
     assert _validate_url("mcp-server-sqlite") == "mcp-server-sqlite"
     # empty / unparseable still rejected
     for bad in ["   ", '"unclosed']:
@@ -336,9 +331,7 @@ def test_refresh_route_gate(tmp_path, monkeypatch, transport):
     assert transport == []
 
     _enable(monkeypatch)
-    res = asyncio.run(
-        routes_mcp.refresh_mcp_server_tools("stdio1", current_subject = "u")
-    )
+    res = asyncio.run(routes_mcp.refresh_mcp_server_tools("stdio1", current_subject = "u"))
     assert res.ok and res.tool_count == 2
     assert len(transport) == 1
 
@@ -349,9 +342,7 @@ def test_discovery_gate(tmp_path, monkeypatch, transport):
     from core.inference.tools import get_enabled_mcp_tools
 
     _reset_db(tmp_path, monkeypatch)
-    mcp_servers_db.create_server(
-        id = "stdio1", display_name = "FS", url = "npx server", is_enabled = True
-    )
+    mcp_servers_db.create_server(id = "stdio1", display_name = "FS", url = "npx server", is_enabled = True)
 
     _disable(monkeypatch)
     assert asyncio.run(get_enabled_mcp_tools()) == []
@@ -367,9 +358,7 @@ def test_execute_gate(tmp_path, monkeypatch, transport):
     from core.inference.tools import execute_tool
 
     _reset_db(tmp_path, monkeypatch)
-    mcp_servers_db.create_server(
-        id = "stdio1", display_name = "FS", url = "npx server", is_enabled = True
-    )
+    mcp_servers_db.create_server(id = "stdio1", display_name = "FS", url = "npx server", is_enabled = True)
 
     _disable(monkeypatch)
     out = execute_tool("mcp__stdio1__list_directory", {"path": "/tmp"})
diff --git a/studio/backend/tests/test_middleware.py b/studio/backend/tests/test_middleware.py
index 5e5b5a3c3b..2d6efa9f8b 100644
--- a/studio/backend/tests/test_middleware.py
+++ b/studio/backend/tests/test_middleware.py
@@ -24,7 +24,6 @@ if str(_BACKEND_ROOT) not in sys.path:
 @pytest.fixture(scope = "module")
 def main_module():
     import main as _main  # noqa: F401
-
     return _main
 
 
@@ -168,9 +167,7 @@ class TestMaxBodyMiddleware:
         assert r.status_code == 200
         assert r.json()["total"] == 512
 
-    def test_upload_passthrough_rejects_declared_body_over_dedicated_cap(
-        self, main_module
-    ):
+    def test_upload_passthrough_rejects_declared_body_over_dedicated_cap(self, main_module):
         app = _make_protected_app(
             128,
             main_module,
@@ -274,9 +271,7 @@ class TestSecurityHeadersMiddleware:
         csp = r.headers["content-security-policy"]
         assert f"'nonce-{nonce}'" in csp
         # Internal handoff header must not leak to clients.
-        assert main_module._CSP_SCRIPT_NONCE_HEADER not in {
-            k.lower() for k in r.headers.keys()
-        }
+        assert main_module._CSP_SCRIPT_NONCE_HEADER not in {k.lower() for k in r.headers.keys()}
 
     def test_build_csp_helper_shape(self, main_module):
         plain = main_module._build_csp()
@@ -290,9 +285,7 @@ class TestSecurityHeadersMiddleware:
         # this allowlist entry citation favicons fall back to gray initials.
         csp = main_module._build_csp()
         img_directive = next(
-            chunk.strip()
-            for chunk in csp.split(";")
-            if chunk.strip().startswith("img-src ")
+            chunk.strip() for chunk in csp.split(";") if chunk.strip().startswith("img-src ")
         )
         # Tokenise and compare with `==` so CodeQL's URL-substring rule does
         # not read directive-string `in` membership as URL sanitisation.
diff --git a/studio/backend/tests/test_mlx_inference_backend.py b/studio/backend/tests/test_mlx_inference_backend.py
index 16cca7dd40..49afab048d 100644
--- a/studio/backend/tests/test_mlx_inference_backend.py
+++ b/studio/backend/tests/test_mlx_inference_backend.py
@@ -103,8 +103,7 @@ def test_mlx_inference_text_load_forwards_studio_settings(monkeypatch):
 
 
 def test_mlx_inference_vlm_lora_uses_unsloth_loader_without_native_adapter_rewrite(
-    monkeypatch,
-    tmp_path,
+    monkeypatch, tmp_path
 ):
     _install_fake_mlx(monkeypatch)
     calls = []
@@ -199,7 +198,7 @@ def test_mlx_generate_text_forwards_kwargs_into_template_helper(monkeypatch):
         return ""
 
     monkeypatch.setattr(
-        "core.inference.chat_template_helpers." "apply_chat_template_for_generation",
+        "core.inference.chat_template_helpers.apply_chat_template_for_generation",
         _fake_apply,
         raising = True,
     )
@@ -228,7 +227,11 @@ def test_mlx_generate_text_forwards_kwargs_into_template_helper(monkeypatch):
     class _Tok:
         chat_template = "x"
 
-        def decode(self, ids, skip_special_tokens = False):
+        def decode(
+            self,
+            ids,
+            skip_special_tokens = False,
+        ):
             return "hi"
 
     backend = MLXInferenceBackend()
diff --git a/studio/backend/tests/test_mlx_training_worker_config.py b/studio/backend/tests/test_mlx_training_worker_config.py
index c36363b1ae..811971ec36 100644
--- a/studio/backend/tests/test_mlx_training_worker_config.py
+++ b/studio/backend/tests/test_mlx_training_worker_config.py
@@ -45,12 +45,8 @@ def _load_worker_module():
             setattr(wheel_utils, name, lambda *_args, **_kwargs: None)
         sys.modules["utils.wheel_utils"] = wheel_utils
 
-        worker_path = (
-            Path(__file__).resolve().parents[1] / "core" / "training" / "worker.py"
-        )
-        spec = importlib.util.spec_from_file_location(
-            "mlx_training_worker_under_test", worker_path
-        )
+        worker_path = Path(__file__).resolve().parents[1] / "core" / "training" / "worker.py"
+        spec = importlib.util.spec_from_file_location("mlx_training_worker_under_test", worker_path)
         module = importlib.util.module_from_spec(spec)
         assert spec.loader is not None
         spec.loader.exec_module(module)
diff --git a/studio/backend/tests/test_models_get_model_config_case_resolution.py b/studio/backend/tests/test_models_get_model_config_case_resolution.py
index 3481e29948..417ec74d17 100644
--- a/studio/backend/tests/test_models_get_model_config_case_resolution.py
+++ b/studio/backend/tests/test_models_get_model_config_case_resolution.py
@@ -50,9 +50,7 @@ def test_get_model_config_resolves_cached_case_before_model_checks(monkeypatch):
         return _DummyModelConfig()
 
     monkeypatch.setattr(models_route, "is_local_path", lambda _: False)
-    monkeypatch.setattr(
-        models_route, "resolve_cached_repo_id_case", lambda _: "Org/Model"
-    )
+    monkeypatch.setattr(models_route, "resolve_cached_repo_id_case", lambda _: "Org/Model")
     monkeypatch.setattr(models_route, "load_model_defaults", _record_load)
     monkeypatch.setattr(models_route, "is_vision_model", _record_vision)
     monkeypatch.setattr(models_route, "is_embedding_model", _record_embedding)
diff --git a/studio/backend/tests/test_multimodal_document.py b/studio/backend/tests/test_multimodal_document.py
index 4d7528d238..b2986f2c3a 100644
--- a/studio/backend/tests/test_multimodal_document.py
+++ b/studio/backend/tests/test_multimodal_document.py
@@ -317,11 +317,7 @@ def test_openai_base64_pdf_becomes_input_file(monkeypatch):
     user_msg = captured["body"]["input"][0]
     parts = user_msg["content"]
     fileblk = next(p for p in parts if p.get("type") == "input_file")
-    assert fileblk == {
-        "type": "input_file",
-        "file_data": _PDF_DATA_URI,
-        "filename": "paper.pdf",
-    }
+    assert fileblk == {"type": "input_file", "file_data": _PDF_DATA_URI, "filename": "paper.pdf"}
 
 
 def test_openai_url_pdf_becomes_input_file(monkeypatch):
@@ -344,10 +340,7 @@ def test_openai_url_pdf_becomes_input_file(monkeypatch):
     )
     parts = captured["body"]["input"][0]["content"]
     fileblk = next(p for p in parts if p.get("type") == "input_file")
-    assert fileblk == {
-        "type": "input_file",
-        "file_url": "https://example.com/doc.pdf",
-    }
+    assert fileblk == {"type": "input_file", "file_url": "https://example.com/doc.pdf"}
 
 
 def test_openai_empty_data_uri_falls_back_to_file_url(monkeypatch):
@@ -512,9 +505,7 @@ def test_build_external_messages_passes_input_document_for_anthropic_and_openai(
         )
     ]
     for provider in ("anthropic", "openai"):
-        out = _build_external_messages(
-            msgs, supports_vision = True, provider_type = provider
-        )
+        out = _build_external_messages(msgs, supports_vision = True, provider_type = provider)
         assert len(out) == 1, (provider, out)
         parts = out[0]["content"]
         assert parts[0] == {"type": "text", "text": "summarise"}, provider
@@ -550,9 +541,7 @@ def test_build_external_messages_strips_input_document_for_unmapped_providers():
         )
     ]
     for provider in ("gemini", "mistral", "kimi", "openrouter", "deepseek", "qwen"):
-        out = _build_external_messages(
-            msgs, supports_vision = True, provider_type = provider
-        )
+        out = _build_external_messages(msgs, supports_vision = True, provider_type = provider)
         assert len(out) == 1, (provider, out)
         parts = out[0]["content"]
         types = [p.get("type") for p in parts if isinstance(p, dict)]
diff --git a/studio/backend/tests/test_native_context_length.py b/studio/backend/tests/test_native_context_length.py
index 60622c776d..01c05d3ec6 100644
--- a/studio/backend/tests/test_native_context_length.py
+++ b/studio/backend/tests/test_native_context_length.py
@@ -332,9 +332,7 @@ class TestPydanticModels:
     def test_status_response_chat_template_roundtrip(self):
         """chat_template serializes and validates as part of status."""
         resp = InferenceStatusResponse(chat_template = "{{ messages }}")
-        roundtripped = InferenceStatusResponse.model_validate_json(
-            resp.model_dump_json()
-        )
+        roundtripped = InferenceStatusResponse.model_validate_json(resp.model_dump_json())
         assert roundtripped.chat_template == "{{ messages }}"
 
     def test_roundtrip_preserves_value(self):
@@ -390,9 +388,7 @@ class TestRouteCompleteness:
     def test_gguf_load_responses_have_field(self):
         """Every GGUF LoadResponse (is_gguf = True) includes native_context_length."""
         blocks = self._find_construction_blocks("LoadResponse")
-        gguf_blocks = [
-            b for b in blocks if "is_gguf = True" in b or "is_gguf=True" in b
-        ]
+        gguf_blocks = [b for b in blocks if "is_gguf = True" in b or "is_gguf=True" in b]
         assert (
             len(gguf_blocks) >= 2
         ), f"Expected at least 2 GGUF LoadResponse blocks, found {len(gguf_blocks)}"
@@ -404,9 +400,7 @@ class TestRouteCompleteness:
     def test_non_gguf_load_responses_omit_field(self):
         """Non-GGUF LoadResponse blocks do not set native_context_length (defaults to None)."""
         blocks = self._find_construction_blocks("LoadResponse")
-        non_gguf = [
-            b for b in blocks if "is_gguf = True" not in b and "is_gguf=True" not in b
-        ]
+        non_gguf = [b for b in blocks if "is_gguf = True" not in b and "is_gguf=True" not in b]
         # Non-GGUF paths should not reference native_context_length
         # (Pydantic defaults it to None, so not setting it is correct)
         for block in non_gguf:
@@ -422,7 +416,9 @@ class TestRouteCompleteness:
             if "llama_backend" in block and "native_context_length" in block:
                 found = True
                 break
-        assert found, "No InferenceStatusResponse block with llama_backend has native_context_length"
+        assert (
+            found
+        ), "No InferenceStatusResponse block with llama_backend has native_context_length"
 
 
 # =====================================================================
diff --git a/studio/backend/tests/test_offline_gguf_cache_fallback.py b/studio/backend/tests/test_offline_gguf_cache_fallback.py
index d3b2f553a2..df7652a590 100644
--- a/studio/backend/tests/test_offline_gguf_cache_fallback.py
+++ b/studio/backend/tests/test_offline_gguf_cache_fallback.py
@@ -149,8 +149,7 @@ def _siblings(items: dict[str, int]):
     """Mock ``hf_model_info(...).siblings`` payload."""
     return _types.SimpleNamespace(
         siblings = [
-            _types.SimpleNamespace(rfilename = name, size = size)
-            for name, size in items.items()
+            _types.SimpleNamespace(rfilename = name, size = size) for name, size in items.items()
         ],
     )
 
@@ -174,12 +173,8 @@ class TestIterHfCacheSnapshots:
         assert list(_iter_hf_cache_snapshots("unsloth/bare")) == []
 
     def test_yields_newest_first(self, hf_cache):
-        old = _build_cache(
-            hf_cache, "unsloth/multi", {"x.gguf": 1}, snapshot_sha = "a" * 40
-        )
-        new = _build_cache(
-            hf_cache, "unsloth/multi", {"y.gguf": 1}, snapshot_sha = "b" * 40
-        )
+        old = _build_cache(hf_cache, "unsloth/multi", {"x.gguf": 1}, snapshot_sha = "a" * 40)
+        new = _build_cache(hf_cache, "unsloth/multi", {"y.gguf": 1}, snapshot_sha = "b" * 40)
         os.utime(old, (1000, 1000))
         os.utime(new, (2000, 2000))
         out = list(_iter_hf_cache_snapshots("unsloth/multi"))
@@ -218,9 +213,7 @@ class TestListGgufVariantsFromCache:
 
 
 class TestListGgufVariantsOffline:
-    def test_offline_env_short_circuits_api(
-        self, hf_cache, clean_offline_env, monkeypatch
-    ):
+    def test_offline_env_short_circuits_api(self, hf_cache, clean_offline_env, monkeypatch):
         _build_cache(hf_cache, "unsloth/a", {"a-UD-Q4_K_XL.gguf": 1})
         monkeypatch.setenv("HF_HUB_OFFLINE", "1")
 
@@ -232,11 +225,7 @@ class TestListGgufVariantsOffline:
         assert len(variants) == 1
         assert variants[0].quant == "UD-Q4_K_XL"
 
-    def test_api_exception_falls_back_to_cache(
-        self,
-        hf_cache,
-        clean_offline_env,
-    ):
+    def test_api_exception_falls_back_to_cache(self, hf_cache, clean_offline_env):
         _build_cache(hf_cache, "unsloth/a", {"a-Q4_K_M.gguf": 1})
 
         def boom(*a, **k):
@@ -302,12 +291,7 @@ class TestDetectGgufFromCache:
 
 
 class TestDetectGgufModelRemoteOffline:
-    def test_offline_env_short_circuits_retries(
-        self,
-        hf_cache,
-        clean_offline_env,
-        monkeypatch,
-    ):
+    def test_offline_env_short_circuits_retries(self, hf_cache, clean_offline_env, monkeypatch):
         _build_cache(hf_cache, "unsloth/a", {"a-Q4_K_M.gguf": 1})
         monkeypatch.setenv("HF_HUB_OFFLINE", "1")
 
@@ -331,11 +315,7 @@ class TestDetectGgufModelRemoteOffline:
             out = detect_gguf_model_remote("unsloth/a")
         assert out == "a-Q4_K_M.gguf"
 
-    def test_repository_not_found_does_not_consult_cache(
-        self,
-        hf_cache,
-        clean_offline_env,
-    ):
+    def test_repository_not_found_does_not_consult_cache(self, hf_cache, clean_offline_env):
         # Cache has a file but the API explicitly says repo is gone.
         _build_cache(hf_cache, "unsloth/a", {"a-Q4_K_M.gguf": 1})
 
@@ -430,12 +410,7 @@ class TestHfOfflineIfDnsDead:
             assert did_set is False
             assert "HF_HUB_OFFLINE" not in os.environ
 
-    def test_user_set_hf_hub_offline_is_preserved(
-        self,
-        dns,
-        clean_offline_env,
-        monkeypatch,
-    ):
+    def test_user_set_hf_hub_offline_is_preserved(self, dns, clean_offline_env, monkeypatch):
         # User explicitly set offline before launching Studio.
         monkeypatch.setenv("HF_HUB_OFFLINE", "1")
         dns.fail()
@@ -445,12 +420,7 @@ class TestHfOfflineIfDnsDead:
         # Helper must not pop a variable it did not set.
         assert os.environ.get("HF_HUB_OFFLINE") == "1"
 
-    def test_user_set_transformers_offline_is_preserved(
-        self,
-        dns,
-        clean_offline_env,
-        monkeypatch,
-    ):
+    def test_user_set_transformers_offline_is_preserved(self, dns, clean_offline_env, monkeypatch):
         monkeypatch.setenv("TRANSFORMERS_OFFLINE", "1")
         dns.fail()
         with _hf_offline_if_dns_dead():
@@ -461,11 +431,7 @@ class TestHfOfflineIfDnsDead:
         # TRANSFORMERS_OFFLINE pre-existed -> preserved.
         assert os.environ.get("TRANSFORMERS_OFFLINE") == "1"
 
-    def test_exception_inside_block_still_restores_env(
-        self,
-        dns,
-        clean_offline_env,
-    ):
+    def test_exception_inside_block_still_restores_env(self, dns, clean_offline_env):
         dns.fail()
         with pytest.raises(RuntimeError, match = "boom"):
             with _hf_offline_if_dns_dead():
@@ -503,10 +469,7 @@ class TestDownloadMmprojOfflineCacheFallback:
     offline vision GGUF load path returns ``None`` even when the mmproj
     is present in cache."""
 
-    def test_cache_lookup_returns_cached_mmproj_when_list_repo_files_fails(
-        self,
-        hf_cache,
-    ):
+    def test_cache_lookup_returns_cached_mmproj_when_list_repo_files_fails(self, hf_cache):
         _build_cache(
             hf_cache,
             "unsloth/vision-GGUF",
@@ -520,7 +483,12 @@ class TestDownloadMmprojOfflineCacheFallback:
         def boom_list(*a, **k):
             raise OSError("offline")
 
-        def fake_download(*, repo_id, filename, token = None):
+        def fake_download(
+            *,
+            repo_id,
+            filename,
+            token = None,
+        ):
             # Echo back so the test can verify the cache-resolved filename
             return f"/fake/cache/{repo_id}/{filename}"
 
@@ -551,7 +519,12 @@ class TestDownloadMmprojOfflineCacheFallback:
 
         captured = {}
 
-        def fake_download(*, repo_id, filename, token = None):
+        def fake_download(
+            *,
+            repo_id,
+            filename,
+            token = None,
+        ):
             captured["filename"] = filename
             return f"/fake/{filename}"
 
@@ -655,9 +628,7 @@ class TestListGgufVariantsPermanentErrors:
                 list_gguf_variants("u/gated-gguf")
         assert type(exc_info.value).__name__ == "GatedRepoError"
 
-    def test_transient_error_still_falls_back_to_cache(
-        self, hf_cache, clean_offline_env
-    ):
+    def test_transient_error_still_falls_back_to_cache(self, hf_cache, clean_offline_env):
         from utils.models.model_config import list_gguf_variants
 
         _build_cache(hf_cache, "u/transient-gguf", {"foo-Q4_K_M.gguf": 1})
@@ -676,7 +647,6 @@ class TestDetectGgufFromCacheExcludesMmproj:
 
     def test_mmproj_only_returns_none(self, hf_cache):
         from utils.models.model_config import _detect_gguf_from_hf_cache
-
         _build_cache(
             hf_cache,
             "u/vision-only-mmproj",
@@ -739,7 +709,6 @@ class TestProbeDnsDeadNoGlobalTimeoutMutation:
         # Simulate a wedged resolver: thread blocks forever.
         def wedged(host):
             import threading
-
             threading.Event().wait()
 
         monkeypatch.setattr(_socket, "gethostbyname", wedged)
diff --git a/studio/backend/tests/test_offline_inference_parent.py b/studio/backend/tests/test_offline_inference_parent.py
index 088be4fcd5..fbb0aa8999 100644
--- a/studio/backend/tests/test_offline_inference_parent.py
+++ b/studio/backend/tests/test_offline_inference_parent.py
@@ -103,10 +103,7 @@ class TestEnvOffline:
 
 class TestTransformersVersionOfflineShortCircuits:
     def test_tokenizer_config_skips_urllib_when_offline(
-        self,
-        monkeypatch,
-        clean_offline_env,
-        tmp_path,
+        self, monkeypatch, clean_offline_env, tmp_path
     ):
         # No local config + offline env -> must NOT call urlopen.
         monkeypatch.setenv("HF_HUB_OFFLINE", "1")
@@ -118,12 +115,7 @@ class TestTransformersVersionOfflineShortCircuits:
         with patch("urllib.request.urlopen", boom):
             assert _check_tokenizer_config_needs_v5(unique) is False
 
-    def test_config_550_skips_urllib_when_offline(
-        self,
-        monkeypatch,
-        clean_offline_env,
-        tmp_path,
-    ):
+    def test_config_550_skips_urllib_when_offline(self, monkeypatch, clean_offline_env, tmp_path):
         monkeypatch.setenv("HF_HUB_OFFLINE", "1")
         unique = f"unsloth/never-cached-{tmp_path.name}-cfg"
 
@@ -139,9 +131,7 @@ class TestLoraDetectOffline:
     OfflineModeIsEnabled; cached adapter_config.json wins."""
 
     def test_hf_model_info_short_circuits_with_OfflineModeIsEnabled(
-        self,
-        monkeypatch,
-        clean_offline_env,
+        self, monkeypatch, clean_offline_env
     ):
         from unittest.mock import MagicMock
 
@@ -171,10 +161,7 @@ class TestLoraDetectOffline:
         )
 
     def test_cached_lora_detected_when_api_unreachable(
-        self,
-        monkeypatch,
-        clean_offline_env,
-        tmp_path,
+        self, monkeypatch, clean_offline_env, tmp_path
     ):
         """A cached adapter_config.json must still mark the repo as a
         LoRA when the HF API is unreachable."""
diff --git a/studio/backend/tests/test_openai_citation_markers_edge.py b/studio/backend/tests/test_openai_citation_markers_edge.py
index ffe8c6b6eb..e8d0be6246 100644
--- a/studio/backend/tests/test_openai_citation_markers_edge.py
+++ b/studio/backend/tests/test_openai_citation_markers_edge.py
@@ -320,9 +320,7 @@ def test_split_helper_buffers_only_after_last_open_byte():
     assert head == f"pre {complete} mid "
     assert tail == partial
     # And the head, once rewritten, drops every private-use byte.
-    rewritten = _replace_openai_citation_markers(
-        head, [{"source_id": "done", "url": "https://d"}]
-    )
+    rewritten = _replace_openai_citation_markers(head, [{"source_id": "done", "url": "https://d"}])
     assert rewritten == "pre [[1]](https://d) mid "
 
 
diff --git a/studio/backend/tests/test_openai_code_execution.py b/studio/backend/tests/test_openai_code_execution.py
index 0b1a65c69e..d4f814856b 100644
--- a/studio/backend/tests/test_openai_code_execution.py
+++ b/studio/backend/tests/test_openai_code_execution.py
@@ -117,10 +117,7 @@ def test_shell_tool_added_on_cloud_with_container_auto(monkeypatch):
     _drive(run())
 
     tools = captured["body"].get("tools") or []
-    assert {
-        "type": "shell",
-        "environment": {"type": "container_auto"},
-    } in tools
+    assert {"type": "shell", "environment": {"type": "container_auto"}} in tools
 
 
 def test_shell_tool_uses_container_reference_when_id_supplied(monkeypatch):
@@ -273,11 +270,7 @@ def test_shell_call_emits_tool_start_and_end(monkeypatch):
     # backend stamps onto every provider-side tool_start so the
     # frontend serializer can distinguish hosted tools from
     # user-declared functions on history replay.
-    assert starts[0]["arguments"] == {
-        "kind": "bash",
-        "command": "ls -la",
-        "_server_tool": True,
-    }
+    assert starts[0]["arguments"] == {"kind": "bash", "command": "ls -la", "_server_tool": True}
     assert ends[0]["tool_call_id"] == "scall_1"
     assert "total 24" in ends[0]["result"]
 
@@ -539,7 +532,5 @@ def test_expired_container_retries_only_once(monkeypatch):
     # infinite loop.
     assert call_count["n"] == 2
     # The second failure surfaces normally as an error SSE line.
-    error_lines = [
-        line for line in lines if '"error"' in line and "_toolEvent" not in line
-    ]
+    error_lines = [line for line in lines if '"error"' in line and "_toolEvent" not in line]
     assert len(error_lines) >= 1
diff --git a/studio/backend/tests/test_openai_container_crud.py b/studio/backend/tests/test_openai_container_crud.py
index 161a6fab83..48acf97e1f 100644
--- a/studio/backend/tests/test_openai_container_crud.py
+++ b/studio/backend/tests/test_openai_container_crud.py
@@ -80,17 +80,12 @@ def test_create_sends_openai_beta_header(monkeypatch):
         return httpx.Response(200, json = {"id": "cntr_new", "name": "analysis"})
 
     _mock_http_client(monkeypatch, handler)
-    result = _drive(
-        _make_client().create_openai_container(name = "analysis", ttl_minutes = 30)
-    )
+    result = _drive(_make_client().create_openai_container(name = "analysis", ttl_minutes = 30))
 
     assert result == {"id": "cntr_new", "name": "analysis"}
     assert seen["headers"].get("openai-beta") == "containers=v1"
     assert seen["body"]["name"] == "analysis"
-    assert seen["body"]["expires_after"] == {
-        "anchor": "last_active_at",
-        "minutes": 30,
-    }
+    assert seen["body"]["expires_after"] == {"anchor": "last_active_at", "minutes": 30}
 
 
 def test_delete_sends_openai_beta_header_and_accepts_confirmation(monkeypatch):
diff --git a/studio/backend/tests/test_openai_responses_translation.py b/studio/backend/tests/test_openai_responses_translation.py
index f177ed5ef3..95e9b2d63c 100644
--- a/studio/backend/tests/test_openai_responses_translation.py
+++ b/studio/backend/tests/test_openai_responses_translation.py
@@ -154,10 +154,7 @@ def test_responses_translates_image_parts(monkeypatch):
 
     parts = captured["body"]["input"][0]["content"]
     assert parts[0] == {"type": "input_text", "text": "What is this?"}
-    assert parts[1] == {
-        "type": "input_image",
-        "image_url": "data:image/png;base64,AAA",
-    }
+    assert parts[1] == {"type": "input_image", "image_url": "data:image/png;base64,AAA"}
     # No max_output_tokens key when caller passes max_tokens=None.
     assert "max_output_tokens" not in captured["body"]
 
@@ -497,8 +494,7 @@ def test_responses_response_incomplete_maps_to_length_finish_reason(monkeypatch)
     finish_reasons = [
         json.loads(line[len("data:") :].strip())["choices"][0]["finish_reason"]
         for line in lines
-        if line.startswith("data:")
-        and line[len("data:") :].strip() not in ("", "[DONE]")
+        if line.startswith("data:") and line[len("data:") :].strip() not in ("", "[DONE]")
     ]
     assert "length" in finish_reasons
 
@@ -730,8 +726,7 @@ def test_responses_reasoning_summary_wrapped_in_think_tags(monkeypatch):
     data_lines = [
         line[len("data:") :].strip()
         for line in lines
-        if line.startswith("data:")
-        and line[len("data:") :].strip() not in ("", "[DONE]")
+        if line.startswith("data:") and line[len("data:") :].strip() not in ("", "[DONE]")
     ]
     payloads = [json.loads(raw) for raw in data_lines]
     combined = "".join(
diff --git a/studio/backend/tests/test_openai_tool_passthrough.py b/studio/backend/tests/test_openai_tool_passthrough.py
index 05efee1595..7d488ae4c9 100644
--- a/studio/backend/tests/test_openai_tool_passthrough.py
+++ b/studio/backend/tests/test_openai_tool_passthrough.py
@@ -271,10 +271,7 @@ class TestChatCompletionRequestToolFields:
         assert self._make(stop = "\nUser:").stop == "\nUser:"
 
     def test_stop_list(self):
-        assert self._make(stop = ["\nUser:", "\nAssistant:"]).stop == [
-            "\nUser:",
-            "\nAssistant:",
-        ]
+        assert self._make(stop = ["\nUser:", "\nAssistant:"]).stop == ["\nUser:", "\nAssistant:"]
 
     def test_tools_default_none(self):
         req = self._make()
@@ -316,9 +313,7 @@ class TestChatCompletionRequestToolFields:
         req = self._make()
         assert req.stream is False
 
-    def test_post_without_stream_field_decodes_to_stream_false_over_http(
-        self, monkeypatch
-    ):
+    def test_post_without_stream_field_decodes_to_stream_false_over_http(self, monkeypatch):
         # Wire-level guard for the same default: a POST body that omits
         # `stream` entirely (the exact shape naive curl / .NET clients
         # send) must deserialise into stream=False *and* the response
@@ -419,13 +414,8 @@ class TestAnthropicToolChoiceToOpenAI:
         assert anthropic_tool_choice_to_openai({"type": "none"}) == "none"
 
     def test_tool_named(self):
-        result = anthropic_tool_choice_to_openai(
-            {"type": "tool", "name": "get_weather"}
-        )
-        assert result == {
-            "type": "function",
-            "function": {"name": "get_weather"},
-        }
+        result = anthropic_tool_choice_to_openai({"type": "tool", "name": "get_weather"})
+        assert result == {"type": "function", "function": {"name": "get_weather"}}
 
     def test_tool_missing_name_returns_none(self):
         assert anthropic_tool_choice_to_openai({"type": "tool"}) is None
@@ -528,15 +518,11 @@ class TestFriendlyErrorHttpx:
         # Non-httpx exceptions still fall through to the existing substring
         # heuristics — a context-size message must still produce the
         # "Message too long" path.
-        ctx_msg = (
-            "request (4096 tokens) exceeds the available context size (2048 tokens)"
-        )
+        ctx_msg = "request (4096 tokens) exceeds the available context size (2048 tokens)"
         assert "Message too long" in _friendly_error(ValueError(ctx_msg))
 
     def test_generic_exception_returns_generic_message(self):
-        assert (
-            _friendly_error(RuntimeError("unrelated")) == "An internal error occurred"
-        )
+        assert _friendly_error(RuntimeError("unrelated")) == "An internal error occurred"
 
 
 from routes.inference import (  # noqa: E402
@@ -554,10 +540,7 @@ class TestDropEmptyAssistantSentinels:
             {"role": "user", "content": "again"},
         ]
         out = _drop_empty_assistant_sentinels(msgs)
-        assert out == [
-            {"role": "user", "content": "hi"},
-            {"role": "user", "content": "again"},
-        ]
+        assert out == [{"role": "user", "content": "hi"}, {"role": "user", "content": "again"}]
 
     def test_drops_assistant_with_no_content_key(self):
         # exclude_none=True strips the content key entirely; filter must catch this.
@@ -567,10 +550,7 @@ class TestDropEmptyAssistantSentinels:
             {"role": "user", "content": "ok"},
         ]
         out = _drop_empty_assistant_sentinels(msgs)
-        assert out == [
-            {"role": "user", "content": "hi"},
-            {"role": "user", "content": "ok"},
-        ]
+        assert out == [{"role": "user", "content": "hi"}, {"role": "user", "content": "ok"}]
 
     def test_preserves_assistant_with_text(self):
         msgs = [
@@ -670,16 +650,10 @@ class TestGgufVisionMessages:
         messages, has_image = _openai_messages_for_gguf_chat(req, is_vision = True)
 
         assert has_image is True
-        assert messages[0]["content"][0] == {
-            "type": "text",
-            "text": "describe image one",
-        }
+        assert messages[0]["content"][0] == {"type": "text", "text": "describe image one"}
         assert messages[0]["content"][1]["type"] == "image_url"
         assert len(messages[0]["content"]) == 2
-        assert messages[2]["content"][0] == {
-            "type": "text",
-            "text": "describe image two",
-        }
+        assert messages[2]["content"][0] == {"type": "text", "text": "describe image two"}
         assert messages[2]["content"][1]["type"] == "image_url"
         assert len(messages[2]["content"]) == 2
         assert isinstance(messages[1]["content"], str)
@@ -702,14 +676,9 @@ class TestGgufVisionMessages:
         messages, has_image = _openai_messages_for_gguf_chat(req, is_vision = True)
 
         assert has_image is True
-        assert messages[0]["content"][0] == {
-            "type": "text",
-            "text": "describe this image",
-        }
+        assert messages[0]["content"][0] == {"type": "text", "text": "describe this image"}
         assert messages[0]["content"][1]["type"] == "image_url"
-        assert messages[0]["content"][1]["image_url"]["url"].startswith(
-            "data:image/png;base64,"
-        )
+        assert messages[0]["content"][1]["image_url"]["url"].startswith("data:image/png;base64,")
 
     def test_rejects_image_parts_for_text_only_gguf(self):
         req = ChatCompletionRequest(
@@ -775,9 +744,7 @@ class TestGgufVisionMessages:
             {"role": "user", "content": "now"},
         ]
 
-        updated = _set_or_prepend_system_message(
-            messages, "Mid instructions.\n\nUse tools."
-        )
+        updated = _set_or_prepend_system_message(messages, "Mid instructions.\n\nUse tools.")
 
         assert [m["role"] for m in updated] == ["system", "user", "user"]
         assert updated[0]["content"] == "Mid instructions.\n\nUse tools."
@@ -837,10 +804,7 @@ class TestGgufVisionToolRouting:
                         {
                             "type": "image_url",
                             "image_url": {
-                                "url": (
-                                    "data:image/png;base64,"
-                                    f"{TestGgufVisionMessages._PNG_B64}"
-                                ),
+                                "url": (f"data:image/png;base64,{TestGgufVisionMessages._PNG_B64}"),
                             },
                         },
                     ],
@@ -849,9 +813,7 @@ class TestGgufVisionToolRouting:
         )
 
         response = self._drive(
-            openai_chat_completions(
-                payload, request = self._Request(), current_subject = "test"
-            )
+            openai_chat_completions(payload, request = self._Request(), current_subject = "test")
         )
         self._consume_response(response)
 
diff --git a/studio/backend/tests/test_pricing.py b/studio/backend/tests/test_pricing.py
index 313c15a441..d669747b1a 100644
--- a/studio/backend/tests/test_pricing.py
+++ b/studio/backend/tests/test_pricing.py
@@ -21,7 +21,11 @@ from core.inference.pricing import (
 )
 
 
-def _isclose(a, b, tol = 1e-6):
+def _isclose(
+    a,
+    b,
+    tol = 1e-6,
+):
     return math.isclose(a, b, rel_tol = tol, abs_tol = tol)
 
 
@@ -241,9 +245,7 @@ def test_openai_cache_read_subtracted_from_input_at_discount():
     )
     # 20k charged at full price, 80k charged at 0.1x
     assert _isclose(out["input_usd"], 20_000 / 1_000_000.0 * base)
-    assert _isclose(
-        out["cache_read_usd"], 80_000 / 1_000_000.0 * base * OPENAI_CACHE_READ_MULT
-    )
+    assert _isclose(out["cache_read_usd"], 80_000 / 1_000_000.0 * base * OPENAI_CACHE_READ_MULT)
 
 
 def test_openai_billable_input_tokens_does_not_double_count_cache_read():
@@ -390,9 +392,7 @@ def test_openai_web_search_charged_per_thousand():
             "openai_tool_use": {"web_search_requests": 250},
         },
     )
-    assert _isclose(
-        out["server_tools_usd"], 250 / 1_000.0 * OPENAI_WEB_SEARCH_USD_PER_1K
-    )
+    assert _isclose(out["server_tools_usd"], 250 / 1_000.0 * OPENAI_WEB_SEARCH_USD_PER_1K)
     assert _isclose(out["total_usd"], 250 / 1_000.0 * OPENAI_WEB_SEARCH_USD_PER_1K)
 
 
@@ -426,8 +426,7 @@ def test_openai_tool_surcharges_added_to_total():
     expected_input = 100_000 / 1_000_000.0 * 5.0
     expected_output = 5_000 / 1_000_000.0 * 30.0
     expected_tools = (
-        3 / 1_000.0 * OPENAI_WEB_SEARCH_USD_PER_1K
-        + 0.25 * OPENAI_CONTAINER_USD_PER_HOUR
+        3 / 1_000.0 * OPENAI_WEB_SEARCH_USD_PER_1K + 0.25 * OPENAI_CONTAINER_USD_PER_HOUR
     )
     assert _isclose(
         out["total_usd"],
@@ -600,10 +599,7 @@ def test_openai_chat_style_envelope_reads_cache_from_prompt_tokens_details():
     )
     # Both envelopes must price identically.
     assert _isclose(chat_style["input_usd"], raw["input_usd"]), (chat_style, raw)
-    assert _isclose(chat_style["cache_read_usd"], raw["cache_read_usd"]), (
-        chat_style,
-        raw,
-    )
+    assert _isclose(chat_style["cache_read_usd"], raw["cache_read_usd"]), (chat_style, raw)
     # 80k at 0.1x base, 20k at full.
     assert _isclose(
         chat_style["cache_read_usd"],
diff --git a/studio/backend/tests/test_pricing_edge.py b/studio/backend/tests/test_pricing_edge.py
index ca4be258e0..5818b42e8a 100644
--- a/studio/backend/tests/test_pricing_edge.py
+++ b/studio/backend/tests/test_pricing_edge.py
@@ -18,7 +18,11 @@ from core.inference.pricing import (
 )
 
 
-def _isclose(a, b, tol = 1e-6):
+def _isclose(
+    a,
+    b,
+    tol = 1e-6,
+):
     return math.isclose(a, b, rel_tol = tol, abs_tol = tol)
 
 
@@ -188,9 +192,7 @@ def test_anthropic_chat_cache_read_exceeds_prompt_no_negative_billable():
     assert out["billable_input_tokens"] == 500  # 0 uncached + 500 cache_read
     # cache_read still priced at the discount rate.
     base = ANTHROPIC_PRICING["claude-opus-4-7"]["input_per_mtok"]
-    assert _isclose(
-        out["cache_read_usd"], 500 / 1_000_000.0 * base * ANTHROPIC_CACHE_READ_MULT
-    )
+    assert _isclose(out["cache_read_usd"], 500 / 1_000_000.0 * base * ANTHROPIC_CACHE_READ_MULT)
 
 
 def test_openai_raw_cached_tokens_exceeds_input_clamp_non_cached():
@@ -207,9 +209,7 @@ def test_openai_raw_cached_tokens_exceeds_input_clamp_non_cached():
     )
     assert out["input_usd"] == 0.0
     # Cache read still priced (the 0.1x bucket).
-    assert _isclose(
-        out["cache_read_usd"], 500 / 1_000_000.0 * base * OPENAI_CACHE_READ_MULT
-    )
+    assert _isclose(out["cache_read_usd"], 500 / 1_000_000.0 * base * OPENAI_CACHE_READ_MULT)
 
 
 # ── long-context tier crosses on billable, including cache_creation ──
diff --git a/studio/backend/tests/test_providers_api.py b/studio/backend/tests/test_providers_api.py
index 0e668944f4..88df886b6c 100644
--- a/studio/backend/tests/test_providers_api.py
+++ b/studio/backend/tests/test_providers_api.py
@@ -225,9 +225,7 @@ class TestAuth:
             json = {"username": USERNAME, "password": PASSWORD},
             timeout = 10,
         )
-        assert (
-            resp.status_code == 200
-        ), f"Login failed ({resp.status_code}): {resp.text}"
+        assert resp.status_code == 200, f"Login failed ({resp.status_code}): {resp.text}"
         body = resp.json()
         assert body.get("access_token"), "access_token is missing or empty"
         assert body.get("token_type") == "bearer"
@@ -237,9 +235,7 @@ class TestAuth:
 
 
 class TestPublicKey:
-    def test_public_key_is_valid_pem(
-        self, auth_headers: dict[str, str], public_key_pem: str
-    ):
+    def test_public_key_is_valid_pem(self, auth_headers: dict[str, str], public_key_pem: str):
         """GET /api/providers/public-key returns an importable RSA PEM key."""
         pem_bytes = public_key_pem.encode("utf-8")
         key = serialization.load_pem_public_key(pem_bytes)
@@ -261,9 +257,7 @@ class TestRegistry:
         )
         assert resp.status_code == 200, f"Registry failed: {resp.text}"
         providers = resp.json()
-        assert (
-            len(providers) == 9
-        ), f"Expected 9 providers, got {len(providers)}: {providers}"
+        assert len(providers) == 9, f"Expected 9 providers, got {len(providers)}: {providers}"
         print(f"\n  {'Provider':<12} {'Base URL'}")
         print(f"  {'-'*12} {'-'*45}")
         for p in providers:
@@ -283,9 +277,7 @@ class TestRegistry:
 
     def test_registry_entries_have_required_fields(self, auth_headers: dict[str, str]):
         """Each registry entry has provider_type, display_name, base_url, default_models."""
-        resp = requests.get(
-            _url("/api/providers/registry"), headers = auth_headers, timeout = 10
-        )
+        resp = requests.get(_url("/api/providers/registry"), headers = auth_headers, timeout = 10)
         assert resp.status_code == 200
         for entry in resp.json():
             for field in (
@@ -320,9 +312,7 @@ class TestProviderCRUD:
             json = {"provider_type": "openai", "display_name": "Test OpenAI (pytest)"},
             timeout = 10,
         )
-        assert (
-            resp.status_code == 201
-        ), f"Create failed ({resp.status_code}): {resp.text}"
+        assert resp.status_code == 201, f"Create failed ({resp.status_code}): {resp.text}"
         body = resp.json()
         assert body.get("id"), "No id in response"
         assert body["provider_type"] == "openai"
@@ -333,9 +323,7 @@ class TestProviderCRUD:
 
     def test_list_includes_created(self, auth_headers: dict[str, str]):
         """GET /api/providers/ includes the newly created config."""
-        assert (
-            TestProviderCRUD._created_id
-        ), "No created_id (run test_create_provider first)"
+        assert TestProviderCRUD._created_id, "No created_id (run test_create_provider first)"
         resp = requests.get(_url("/api/providers/"), headers = auth_headers, timeout = 10)
         assert resp.status_code == 200
         ids = [p["id"] for p in resp.json()]
@@ -354,9 +342,7 @@ class TestProviderCRUD:
             json = {"display_name": new_name},
             timeout = 10,
         )
-        assert (
-            resp.status_code == 200
-        ), f"Update failed ({resp.status_code}): {resp.text}"
+        assert resp.status_code == 200, f"Update failed ({resp.status_code}): {resp.text}"
         assert resp.json()["display_name"] == new_name
         print(f"\n  updated display_name to '{new_name}'")
 
@@ -368,14 +354,10 @@ class TestProviderCRUD:
             headers = auth_headers,
             timeout = 10,
         )
-        assert (
-            resp.status_code == 204
-        ), f"Delete failed ({resp.status_code}): {resp.text}"
+        assert resp.status_code == 204, f"Delete failed ({resp.status_code}): {resp.text}"
 
         # Confirm gone from list
-        list_resp = requests.get(
-            _url("/api/providers/"), headers = auth_headers, timeout = 10
-        )
+        list_resp = requests.get(_url("/api/providers/"), headers = auth_headers, timeout = 10)
         ids = [p["id"] for p in list_resp.json()]
         assert TestProviderCRUD._created_id not in ids, "Deleted provider still in list"
         print(f"\n  deleted id={TestProviderCRUD._created_id} confirmed gone")
@@ -423,9 +405,7 @@ class TestProviderInference:
             json = {"provider_type": provider_type, "encrypted_api_key": encrypted},
             timeout = 30,
         )
-        assert (
-            resp.status_code == 200
-        ), f"Request failed ({resp.status_code}): {resp.text}"
+        assert resp.status_code == 200, f"Request failed ({resp.status_code}): {resp.text}"
         body = resp.json()
         assert (
             body["success"] is True
@@ -449,9 +429,7 @@ class TestProviderInference:
             json = {"provider_type": provider_type, "encrypted_api_key": encrypted},
             timeout = 30,
         )
-        assert (
-            resp.status_code == 200
-        ), f"Request failed ({resp.status_code}): {resp.text}"
+        assert resp.status_code == 200, f"Request failed ({resp.status_code}): {resp.text}"
         models = resp.json()
         assert isinstance(models, list), f"Expected list, got {type(models)}"
         assert len(models) > 0, f"No models returned for {provider_type}"
@@ -498,9 +476,7 @@ class TestProviderInference:
 # ── TestVisionInference ─────────────────────────────────────────────
 
 # Sloth photo — used to test vision routing across providers
-_VISION_IMAGE_URL = (
-    "https://www.travelexcellence.com/images/where-to-see-sloths-in-costa-rica.jpg"
-)
+_VISION_IMAGE_URL = "https://www.travelexcellence.com/images/where-to-see-sloths-in-costa-rica.jpg"
 
 _VISION_PARAMS = [
     pytest.param(
@@ -602,8 +578,6 @@ class TestLocalInferenceUnaffected:
             f"This likely means the provider fields broke the base request schema."
         )
         status_label = (
-            "local model responded"
-            if resp.status_code == 200
-            else "no model loaded (expected)"
+            "local model responded" if resp.status_code == 200 else "no model loaded (expected)"
         )
         print(f"\n  status={resp.status_code} ({status_label}) — local path unaffected")
diff --git a/studio/backend/tests/test_responses_api.py b/studio/backend/tests/test_responses_api.py
index 5b55f87259..c0ec876ad0 100644
--- a/studio/backend/tests/test_responses_api.py
+++ b/studio/backend/tests/test_responses_api.py
@@ -173,9 +173,7 @@ class TestResponsesResponse:
         resp = ResponsesResponse(
             model = "test-model",
             output = [
-                ResponsesOutputMessage(
-                    content = [ResponsesOutputTextContent(text = "Hello!")]
-                ),
+                ResponsesOutputMessage(content = [ResponsesOutputTextContent(text = "Hello!")]),
             ],
             usage = ResponsesUsage(input_tokens = 10, output_tokens = 5, total_tokens = 15),
         )
@@ -324,5 +322,4 @@ class TestNormaliseResponsesInput:
 
 if __name__ == "__main__":
     import pytest
-
     pytest.main([__file__, "-v"])
diff --git a/studio/backend/tests/test_responses_tool_passthrough.py b/studio/backend/tests/test_responses_tool_passthrough.py
index 2f1161c329..146d6017d0 100644
--- a/studio/backend/tests/test_responses_tool_passthrough.py
+++ b/studio/backend/tests/test_responses_tool_passthrough.py
@@ -160,9 +160,7 @@ class TestResponsesMultiTurnInput:
 
     def test_function_call_output_missing_call_id_rejected(self):
         with pytest.raises(ValidationError):
-            ResponsesFunctionCallOutputInputItem(
-                type = "function_call_output", output = "x"
-            )
+            ResponsesFunctionCallOutputInputItem(type = "function_call_output", output = "x")
 
     def test_function_call_output_accepts_content_array(self):
         item = ResponsesFunctionCallOutputInputItem(
@@ -222,9 +220,7 @@ class TestToolsTranslation:
         assert _translate_responses_tools_to_chat([]) is None
 
     def test_only_builtin_tools_returns_none(self):
-        assert (
-            _translate_responses_tools_to_chat([{"type": "web_search_preview"}]) is None
-        )
+        assert _translate_responses_tools_to_chat([{"type": "web_search_preview"}]) is None
 
     def test_description_optional(self):
         out = _translate_responses_tools_to_chat(
@@ -256,9 +252,7 @@ class TestToolChoiceTranslation:
         """If a client happens to send the Chat Completions nested shape,
         we don't double-wrap it."""
         already_nested = {"type": "function", "function": {"name": "get_weather"}}
-        assert (
-            _translate_responses_tool_choice_to_chat(already_nested) == already_nested
-        )
+        assert _translate_responses_tool_choice_to_chat(already_nested) == already_nested
 
     def test_unknown_shape_passes_through(self):
         obj = {"type": "allowed_tools", "tools": [{"type": "function", "name": "x"}]}
@@ -625,9 +619,7 @@ class TestCodexStyleRequestShapes:
             input = [
                 {
                     "role": "assistant",
-                    "content": [
-                        {"type": "output_text", "text": "ok", "annotations": []}
-                    ],
+                    "content": [{"type": "output_text", "text": "ok", "annotations": []}],
                 },
                 {"role": "user", "content": "next"},
             ],
diff --git a/studio/backend/tests/test_rocm_oom_guard.py b/studio/backend/tests/test_rocm_oom_guard.py
index 2ce9b55789..d27ee83f1d 100644
--- a/studio/backend/tests/test_rocm_oom_guard.py
+++ b/studio/backend/tests/test_rocm_oom_guard.py
@@ -135,9 +135,7 @@ class TestDeviceNameFallback:
         props = _props(name = device_name)
         gcn, is_unified = _rocm_classify_unified_memory(props)
         assert gcn == "", f"expected empty gcn_arch, got {gcn!r}"
-        assert (
-            is_unified is True
-        ), f"device {device_name!r} should be classified as unified-memory"
+        assert is_unified is True, f"device {device_name!r} should be classified as unified-memory"
 
     # --- discrete devices that must NOT be mis-classified ---
 
diff --git a/studio/backend/tests/test_safetensors_capability_advertise.py b/studio/backend/tests/test_safetensors_capability_advertise.py
index c3ee5b9ff1..5e3d2cc9d1 100644
--- a/studio/backend/tests/test_safetensors_capability_advertise.py
+++ b/studio/backend/tests/test_safetensors_capability_advertise.py
@@ -369,11 +369,7 @@ def test_worker_load_reply_payload_includes_chat_template_info():
         "is_gguf": False,
     }
     _bm = getattr(backend, "models", {}) or {}
-    _entry = (
-        _bm.get(mc.identifier)
-        or _bm.get(getattr(backend, "active_model_name", None))
-        or {}
-    )
+    _entry = _bm.get(mc.identifier) or _bm.get(getattr(backend, "active_model_name", None)) or {}
     _tpl_info = _entry.get("chat_template_info")
     if isinstance(_tpl_info, dict):
         model_info["chat_template_info"] = {
diff --git a/studio/backend/tests/test_safetensors_tool_loop.py b/studio/backend/tests/test_safetensors_tool_loop.py
index 50f6011959..ff5653c742 100644
--- a/studio/backend/tests/test_safetensors_tool_loop.py
+++ b/studio/backend/tests/test_safetensors_tool_loop.py
@@ -53,9 +53,7 @@ from utils.datasets import is_gpt_oss_model_name
 
 class TestParser:
     def test_json_tool_call(self):
-        text = (
-            '{"name":"web_search","arguments":{"query":"hello"}}'
-        )
+        text = '{"name":"web_search","arguments":{"query":"hello"}}'
         result = parse_tool_calls_from_text(text)
         assert len(result) == 1
         tc = result[0]
@@ -214,7 +212,12 @@ def _collect_events(generator, max_events = 200):
     return events
 
 
-def _make_loop(*, turns, exec_results = None, **kwargs):
+def _make_loop(
+    *,
+    turns,
+    exec_results = None,
+    **kwargs,
+):
     """Build a configured loop with a multi-turn fake generator.
 
     ``turns`` is a list of chunk-lists; iteration N yields chunks from
@@ -342,9 +345,7 @@ class TestLoopBasic:
         assert exec_fn.calls[0][0] == "render_html"
         assert "" in exec_fn.calls[0][1]["code"]
 
-    def test_python_tool_containing_render_html_signal_does_not_emit_provisional_start(
-        self,
-    ):
+    def test_python_tool_containing_render_html_signal_does_not_emit_provisional_start(self):
         loop, exec_fn = _make_loop(
             turns = [
                 [
@@ -361,9 +362,7 @@ class TestLoopBasic:
 
         assert len(tool_starts) == 1
         assert tool_starts[0]["tool_name"] == "python"
-        assert exec_fn.calls == [
-            ("python", {"code": "print('')"})
-        ]
+        assert exec_fn.calls == [("python", {"code": "print('')"})]
 
     def test_render_html_success_blocks_second_artifact_call(self):
         exec_fn = FakeExecuteTool(["Rendered HTML artifact."])
@@ -398,10 +397,7 @@ class TestLoopBasic:
         tool_starts = [e for e in events if e["type"] == "tool_start"]
 
         assert exec_fn.calls == [("render_html", {"code": "one"})]
-        assert [e["arguments"] for e in tool_starts] == [
-            {},
-            {"code": "one"},
-        ]
+        assert [e["arguments"] for e in tool_starts] == [{}, {"code": "one"}]
 
     def test_truncated_unclosed_tool_call(self):
         loop, exec_fn = _make_loop(
@@ -425,9 +421,7 @@ class TestLoopBasic:
                 # ``arguments`` is a string that is not itself valid
                 # JSON for ``_coerce_arguments`` to parse, so the
                 # heal path runs.
-                [
-                    '{"name":"web_search","arguments":"hello world"}'
-                ],
+                ['{"name":"web_search","arguments":"hello world"}'],
                 ["ok"],
             ],
             exec_results = ["..."],
@@ -444,12 +438,8 @@ class TestLoopBehaviour:
         # called only once.
         loop, exec_fn = _make_loop(
             turns = [
-                [
-                    '{"name":"web_search","arguments":{"query":"x"}}'
-                ],
-                [
-                    '{"name":"web_search","arguments":{"query":"x"}}'
-                ],
+                ['{"name":"web_search","arguments":{"query":"x"}}'],
+                ['{"name":"web_search","arguments":{"query":"x"}}'],
                 ["final"],
             ],
             exec_results = ["search-result-1"],
@@ -467,9 +457,7 @@ class TestLoopBehaviour:
         # tool_end event still carries the raw result for the UI.
         loop, exec_fn = _make_loop(
             turns = [
-                [
-                    '{"name":"python","arguments":{"code":"plot()"}}'
-                ],
+                ['{"name":"python","arguments":{"code":"plot()"}}'],
                 ["see chart"],
             ],
             exec_results = ["chart\n__IMAGES__:/tmp/chart.png"],
@@ -507,9 +495,7 @@ class TestLoopBehaviour:
         tool_msgs = [m for m in captured[1] if m.get("role") == "tool"]
         assert tool_msgs, "no tool message reached the model"
         for tm in tool_msgs:
-            assert (
-                "__IMAGES__" not in tm["content"]
-            ), f"sentinel leaked to model: {tm['content']!r}"
+            assert "__IMAGES__" not in tm["content"], f"sentinel leaked to model: {tm['content']!r}"
 
     def test_image_sentinel_stripped_with_multiple_markers(self):
         # Consecutive sentinels: cut at the first, nothing leaks.
@@ -539,19 +525,13 @@ class TestLoopBehaviour:
         tool_msgs = [m for m in captured[1] if m.get("role") == "tool"]
         assert tool_msgs
         for tm in tool_msgs:
-            assert (
-                "__IMAGES__" not in tm["content"]
-            ), f"second sentinel leaked: {tm['content']!r}"
-            assert (
-                tm["content"] == "panel"
-            ), f"expected payload-only 'panel', got {tm['content']!r}"
+            assert "__IMAGES__" not in tm["content"], f"second sentinel leaked: {tm['content']!r}"
+            assert tm["content"] == "panel", f"expected payload-only 'panel', got {tm['content']!r}"
 
     def test_tool_execution_error_is_emitted_but_loop_continues(self):
         loop, exec_fn = _make_loop(
             turns = [
-                [
-                    '{"name":"web_search","arguments":{"query":"x"}}'
-                ],
+                ['{"name":"web_search","arguments":{"query":"x"}}'],
                 ["sorry, that failed"],
             ],
             exec_results = ["Error: network unreachable"],
@@ -566,9 +546,7 @@ class TestLoopBehaviour:
     def test_exception_in_executor_does_not_raise(self):
         loop, exec_fn = _make_loop(
             turns = [
-                [
-                    '{"name":"web_search","arguments":{"query":"x"}}'
-                ],
+                ['{"name":"web_search","arguments":{"query":"x"}}'],
                 ["recovered"],
             ],
             exec_results = [RuntimeError("boom")],
@@ -588,8 +566,7 @@ class TestLoopControl:
         events = list(
             run_safetensors_tool_loop(
                 single_turn = _const_stream(
-                    '{"name":"web_search",'
-                    '"arguments":{"query":"x"}}'
+                    '{"name":"web_search","arguments":{"query":"x"}}'
                 ),
                 messages = [{"role": "user", "content": "hi"}],
                 tools = [],
@@ -606,9 +583,7 @@ class TestLoopControl:
         loop, exec_fn = _make_loop(
             turns = [
                 # : tool call (executes once)
-                [
-                    '{"name":"web_search","arguments":{"query":"a"}}'
-                ],
+                ['{"name":"web_search","arguments":{"query":"a"}}'],
                 # : model gives a final answer when nudged.
                 ["here is the final answer"],
             ],
@@ -625,24 +600,19 @@ class TestStatusFormatting:
     def test_status_for_known_tools(self):
         # Use the private helper directly to verify status formatting.
         assert (
-            safetensors_agentic._status_for_tool("web_search", {"query": "abc"})
-            == "Searching: abc"
+            safetensors_agentic._status_for_tool("web_search", {"query": "abc"}) == "Searching: abc"
         )
         assert (
-            safetensors_agentic._status_for_tool(
-                "web_search", {"url": "https://www.example.com/x"}
-            )
+            safetensors_agentic._status_for_tool("web_search", {"url": "https://www.example.com/x"})
             == "Reading: example.com"
         )
-        assert safetensors_agentic._status_for_tool(
-            "python", {"code": "x = 1"}
-        ).startswith("Running Python:")
-        assert safetensors_agentic._status_for_tool(
-            "terminal", {"command": "ls"}
-        ).startswith("Running:")
-        assert safetensors_agentic._status_for_tool("unknown_tool", {}).startswith(
-            "Calling:"
+        assert safetensors_agentic._status_for_tool("python", {"code": "x = 1"}).startswith(
+            "Running Python:"
         )
+        assert safetensors_agentic._status_for_tool("terminal", {"command": "ls"}).startswith(
+            "Running:"
+        )
+        assert safetensors_agentic._status_for_tool("unknown_tool", {}).startswith("Calling:")
 
 
 class TestProseMentioningToolCall:
@@ -655,9 +625,7 @@ class TestProseMentioningToolCall:
             turns = [
                 # : a real tool call so the loop moves to
                 # .
-                [
-                    '{"name":"web_search","arguments":{"query":"x"}}'
-                ],
+                ['{"name":"web_search","arguments":{"query":"x"}}'],
                 # : prose that mentions the literal text.
                 ["the docs say  means an LLM tool call wrapper"],
             ],
@@ -677,9 +645,7 @@ class TestProseMentioningToolCall:
         # result, so we should see exactly one call.
         loop, exec_fn = _make_loop(
             turns = [
-                [
-                    '{"name":"web_search","arguments":{"query":"x"}}'
-                ],
+                ['{"name":"web_search","arguments":{"query":"x"}}'],
                 ["the docs mention  wrappers"],
             ],
             exec_results = ["Page text:  appears here in the docs"],
@@ -695,7 +661,6 @@ class TestChatTemplateHelper:
         from core.inference.chat_template_helpers import (
             apply_chat_template_for_generation,
         )
-
         self.apply = apply_chat_template_for_generation
 
     class _Tok:
@@ -705,7 +670,12 @@ class TestChatTemplateHelper:
             self.last_kwargs = None
 
         def apply_chat_template(
-            self, messages, *, tokenize = False, add_generation_prompt = True, **kw
+            self,
+            messages,
+            *,
+            tokenize = False,
+            add_generation_prompt = True,
+            **kw,
         ):
             self.call_count += 1
             unknown = set(kw) - self.accepted
@@ -758,9 +728,7 @@ class TestGuardrails:
         exec_fn = FakeExecuteTool([])
         loop = run_safetensors_tool_loop(
             single_turn = _fake_stream(
-                [
-                    '{"name":"terminal","arguments":{"command":"echo bypass"}}'
-                ]
+                ['{"name":"terminal","arguments":{"command":"echo bypass"}}']
             ),
             messages = [{"role": "user", "content": "hi"}],
             tools = [{"type": "function", "function": {"name": "web_search"}}],
@@ -776,9 +744,7 @@ class TestGuardrails:
         exec_fn = FakeExecuteTool(["OK"])
         loop = run_safetensors_tool_loop(
             single_turn = _fake_stream(
-                [
-                    '{"name":"python","arguments":{"code":"print(1)"}}'
-                ]
+                ['{"name":"python","arguments":{"code":"print(1)"}}']
             ),
             messages = [{"role": "user", "content": "hi"}],
             tools = [],
@@ -790,11 +756,7 @@ class TestGuardrails:
 
     def test_max_iterations_zero_executes_no_tools(self):
         loop, exec_fn = _make_loop(
-            turns = [
-                [
-                    '{"name":"web_search","arguments":{"query":"x"}}'
-                ]
-            ],
+            turns = [['{"name":"web_search","arguments":{"query":"x"}}']],
             exec_results = ["OK"],
             max_tool_iterations = 0,
         )
@@ -825,9 +787,7 @@ class TestGuardrails:
     def test_auto_heal_disabled_still_parses_valid_tool_call(self):
         loop, exec_fn = _make_loop(
             turns = [
-                [
-                    '{"name":"web_search","arguments":{"query":"x"}}'
-                ],
+                ['{"name":"web_search","arguments":{"query":"x"}}'],
                 ["done"],
             ],
             exec_results = ["OK"],
@@ -840,47 +800,30 @@ class TestGuardrails:
     def test_non_consecutive_duplicate_is_short_circuited(self):
         loop, exec_fn = _make_loop(
             turns = [
-                [
-                    '{"name":"web_search","arguments":{"query":"A"}}'
-                ],
-                [
-                    '{"name":"web_search","arguments":{"query":"B"}}'
-                ],
-                [
-                    '{"name":"web_search","arguments":{"query":"A"}}'
-                ],
+                ['{"name":"web_search","arguments":{"query":"A"}}'],
+                ['{"name":"web_search","arguments":{"query":"B"}}'],
+                ['{"name":"web_search","arguments":{"query":"A"}}'],
                 ["final"],
             ],
             exec_results = ["res-A", "res-B"],
             max_tool_iterations = 4,
         )
         events = _collect_events(loop)
-        assert exec_fn.calls == [
-            ("web_search", {"query": "A"}),
-            ("web_search", {"query": "B"}),
-        ]
+        assert exec_fn.calls == [("web_search", {"query": "A"}), ("web_search", {"query": "B"})]
         tool_ends = [e for e in events if e["type"] == "tool_end"]
         assert "already made this exact call" in tool_ends[-1]["result"]
 
     def test_coerce_string_args_python_uses_code_key(self):
-        assert _coerce_arguments("print(1)", heal = True, tool_name = "python") == {
-            "code": "print(1)"
-        }
+        assert _coerce_arguments("print(1)", heal = True, tool_name = "python") == {"code": "print(1)"}
 
     def test_coerce_string_args_terminal_uses_command_key(self):
-        assert _coerce_arguments("ls -la", heal = True, tool_name = "terminal") == {
-            "command": "ls -la"
-        }
+        assert _coerce_arguments("ls -la", heal = True, tool_name = "terminal") == {"command": "ls -la"}
 
     def test_tool_call_ids_unique_across_loop_iterations(self):
         loop, _exec = _make_loop(
             turns = [
-                [
-                    '{"name":"web_search","arguments":{"query":"A"}}'
-                ],
-                [
-                    '{"name":"web_search","arguments":{"query":"B"}}'
-                ],
+                ['{"name":"web_search","arguments":{"query":"A"}}'],
+                ['{"name":"web_search","arguments":{"query":"B"}}'],
                 ["done"],
             ],
             exec_results = ["A", "B"],
diff --git a/studio/backend/tests/test_sandbox_tools.py b/studio/backend/tests/test_sandbox_tools.py
index cd8957c3dd..92fee2e8e5 100644
--- a/studio/backend/tests/test_sandbox_tools.py
+++ b/studio/backend/tests/test_sandbox_tools.py
@@ -88,9 +88,7 @@ class TestTrustedHostAllowlist:
         _ok(f"import requests; requests.get({url!r})")
 
     def test_wikipedia_subdomain_passes(self):
-        _ok(
-            'import urllib.request; urllib.request.urlopen("https://m.en.wikipedia.org/wiki/Foo")'
-        )
+        _ok('import urllib.request; urllib.request.urlopen("https://m.en.wikipedia.org/wiki/Foo")')
 
     def test_hf_co_short_form_passes(self):
         _ok('import requests; requests.get("https://hf.co/unsloth/Qwen3.5-4B-GGUF")')
@@ -221,10 +219,7 @@ class TestUploadDenylist:
         )
 
     def test_plain_post_json_not_blocked(self):
-        _ok(
-            "import requests\n"
-            'requests.post("https://api.weather.gov/lookup", json={"k": "v"})'
-        )
+        _ok("import requests\n" 'requests.post("https://api.weather.gov/lookup", json={"k": "v"})')
 
 
 class TestSandboxEnvIsolation:
@@ -361,7 +356,6 @@ class TestBashBlocklistPosition:
     @staticmethod
     def _find():
         from core.inference.tools import _find_blocked_commands
-
         return _find_blocked_commands
 
     # ---- argument-position: must NOT be blocked ----
@@ -526,7 +520,7 @@ class TestHfUploadImportGate:
 
     def test_bare_name_upload_file_without_hf_import_allowed(self):
         # No HF import -- local helper named upload_file should pass.
-        _ok("def upload_file(*a, **k):\n    pass\n" "upload_file('x', 'y', 'z')")
+        _ok("def upload_file(*a, **k):\n    pass\nupload_file('x', 'y', 'z')")
 
 
 class TestHfUploadSandboxLocalPaths:
diff --git a/studio/backend/tests/test_studio_api.py b/studio/backend/tests/test_studio_api.py
index 521c99e126..70a103a2f8 100644
--- a/studio/backend/tests/test_studio_api.py
+++ b/studio/backend/tests/test_studio_api.py
@@ -72,11 +72,7 @@ DEFAULT_VARIANT = "UD-Q4_K_XL"
 PORT = 18222  # high port unlikely to collide
 HOST = "127.0.0.1"
 STARTUP_TIMEOUT = 120  # seconds to wait for banner
-LOG_FILE = (
-    Path(__file__).resolve().parent.parent.parent.parent
-    / "temp"
-    / "test_studio_api.log"
-)
+LOG_FILE = Path(__file__).resolve().parent.parent.parent.parent / "temp" / "test_studio_api.log"
 
 
 # ── Helpers ──────────────────────────────────────────────────────────
@@ -219,9 +215,7 @@ def test_openai_sdk(base_url: str, api_key: str):
     client = OpenAI(base_url = f"{base_url}/v1", api_key = api_key)
     response = client.chat.completions.create(
         model = "current",
-        messages = [
-            {"role": "user", "content": "What is 2+2? Answer with just the number."}
-        ],
+        messages = [{"role": "user", "content": "What is 2+2? Answer with just the number."}],
         stream = True,
     )
     content_parts = []
@@ -390,9 +384,7 @@ def test_openai_tools_nonstream(base_url: str, api_key: str):
     assert "city" in parsed, f"Tool call missing required 'city' arg: {parsed}"
     # Usage must be non-zero (was 0 before the fix)
     usage = data.get("usage") or {}
-    assert (
-        usage.get("prompt_tokens", 0) > 0
-    ), f"Expected non-zero prompt_tokens; got {usage}"
+    assert usage.get("prompt_tokens", 0) > 0, f"Expected non-zero prompt_tokens; got {usage}"
     assert data.get("id"), "Missing response id"
     print(
         f"  PASS  openai tools non-stream: "
@@ -417,8 +409,7 @@ def test_openai_tools_stream(base_url: str, api_key: str):
     assert status == 200, f"Expected 200, got {status}"
     assert len(chunks) > 0, "No SSE chunks received"
     assert _final_finish_reason(chunks) == "tool_calls", (
-        f"Expected final finish_reason='tool_calls', got "
-        f"{_final_finish_reason(chunks)!r}"
+        f"Expected final finish_reason='tool_calls', got " f"{_final_finish_reason(chunks)!r}"
     )
     assembled = _collect_streamed_tool_calls(chunks)
     assert len(assembled) >= 1, "No tool_calls reassembled from stream"
@@ -501,8 +492,7 @@ def test_openai_sdk_tool_calling(base_url: str, api_key: str):
         stream = False,
     )
     assert resp.choices[0].finish_reason == "tool_calls", (
-        f"Expected finish_reason='tool_calls', got "
-        f"{resp.choices[0].finish_reason!r}"
+        f"Expected finish_reason='tool_calls', got " f"{resp.choices[0].finish_reason!r}"
     )
     tool_calls = resp.choices[0].message.tool_calls
     assert tool_calls and len(tool_calls) >= 1, "No tool_calls from SDK"
@@ -510,9 +500,7 @@ def test_openai_sdk_tool_calling(base_url: str, api_key: str):
     assert tc.function.name == "get_weather"
     parsed = json.loads(tc.function.arguments)
     assert "city" in parsed
-    print(
-        f"  PASS  openai SDK tool calling: " f"tool={tc.function.name}, args={parsed}"
-    )
+    print(f"  PASS  openai SDK tool calling: " f"tool={tc.function.name}, args={parsed}")
 
 
 def test_invalid_key_rejected(base_url: str):
@@ -655,9 +643,7 @@ def test_anthropic_sdk(base_url: str, api_key: str):
     message = client.messages.create(
         model = "default",
         max_tokens = 100,
-        messages = [
-            {"role": "user", "content": "What is 2+2? Answer with just the number."}
-        ],
+        messages = [{"role": "user", "content": "What is 2+2? Answer with just the number."}],
     )
     assert message.role == "assistant"
     assert len(message.content) > 0, "Empty content"
@@ -708,9 +694,7 @@ def test_anthropic_with_tools(base_url: str, api_key: str):
     assert "message_stop" in event_types, "Missing message_stop"
 
     full = _collect_anthropic_text(events)
-    print(
-        f"  PASS  anthropic with tools: {len(events)} events, {len(full)} chars content"
-    )
+    print(f"  PASS  anthropic with tools: {len(events)} events, {len(full)} chars content")
 
 
 def test_anthropic_tool_choice_any(base_url: str, api_key: str):
@@ -770,8 +754,7 @@ def test_anthropic_tool_choice_any(base_url: str, api_key: str):
     tool_use_starts = [
         e
         for e in events
-        if e[0] == "content_block_start"
-        and e[1].get("content_block", {}).get("type") == "tool_use"
+        if e[0] == "content_block_start" and e[1].get("content_block", {}).get("type") == "tool_use"
     ]
     assert len(tool_use_starts) >= 1, "No tool_use content block emitted"
     print(
@@ -821,9 +804,7 @@ def _start_server(model: str, variant: str | None) -> tuple[subprocess.Popen, st
         if proc.poll() is not None:
             log_fh.flush()
             log_text = LOG_FILE.read_text()
-            raise RuntimeError(
-                f"Server exited early (code {proc.returncode}):\n{log_text[-2000:]}"
-            )
+            raise RuntimeError(f"Server exited early (code {proc.returncode}):\n{log_text[-2000:]}")
         log_text = LOG_FILE.read_text()
         m = re.search(r"API Key:\s+(sk-unsloth-[a-f0-9]+)", log_text)
         if m:
@@ -833,9 +814,7 @@ def _start_server(model: str, variant: str | None) -> tuple[subprocess.Popen, st
     if not api_key:
         log_text = LOG_FILE.read_text()
         _kill_server(proc)
-        raise RuntimeError(
-            f"Timed out waiting for API key in server output:\n{log_text[-2000:]}"
-        )
+        raise RuntimeError(f"Timed out waiting for API key in server output:\n{log_text[-2000:]}")
 
     # Wait a moment for the model to be fully loaded
     time.sleep(2)
@@ -862,9 +841,7 @@ def _kill_server(proc: subprocess.Popen):
 
 
 def main():
-    parser = argparse.ArgumentParser(
-        description = "End-to-end tests for unsloth studio run"
-    )
+    parser = argparse.ArgumentParser(description = "End-to-end tests for unsloth studio run")
     parser.add_argument(
         "--model",
         default = DEFAULT_MODEL,
@@ -898,9 +875,7 @@ def main():
     run_test(test_help_output)
 
     # ── 2-16. Start server and run API tests ─────────────────────────
-    print(
-        f"\nStarting server: {args.model} (variant={args.gguf_variant}) on port {PORT}..."
-    )
+    print(f"\nStarting server: {args.model} (variant={args.gguf_variant}) on port {PORT}...")
     proc = None
     try:
         proc, api_key = _start_server(args.model, args.gguf_variant)
diff --git a/studio/backend/tests/test_tool_xml_strip.py b/studio/backend/tests/test_tool_xml_strip.py
index 8b90a46d5a..857302d543 100644
--- a/studio/backend/tests/test_tool_xml_strip.py
+++ b/studio/backend/tests/test_tool_xml_strip.py
@@ -77,9 +77,7 @@ def test_strips_orphan_tool_call_no_close():
 
 
 def test_strips_orphan_function_no_close():
-    text = (
-        "I'll call python:\n\n\nprint(1)\n"
-    )
+    text = "I'll call python:\n\n\nprint(1)\n"
     cleaned = _TOOL_XML_RE.sub("", text)
     assert "")
         self.assertEqual(result.dataset[1]["text"], "world")
         self.assertTrue(
-            any(
-                "null or non-string 'text' values" in notice.message
-                for notice in result.notices
-            )
+            any("null or non-string 'text' values" in notice.message for notice in result.notices)
         )
 
 
diff --git a/studio/backend/tests/test_training_worker_flash_attn.py b/studio/backend/tests/test_training_worker_flash_attn.py
index 94279c28b4..edc47c705e 100644
--- a/studio/backend/tests/test_training_worker_flash_attn.py
+++ b/studio/backend/tests/test_training_worker_flash_attn.py
@@ -15,7 +15,13 @@ from core.training import worker
 def _missing_flash_attn_import():
     real_import = builtins.__import__
 
-    def fake_import(name, globals = None, locals = None, fromlist = (), level = 0):
+    def fake_import(
+        name,
+        globals = None,
+        locals = None,
+        fromlist = (),
+        level = 0,
+    ):
         if name == "flash_attn":
             raise ImportError
         return real_import(name, globals, locals, fromlist, level)
@@ -26,7 +32,13 @@ def _missing_flash_attn_import():
 def _missing_module_import(missing: str):
     real_import = builtins.__import__
 
-    def fake_import(name, globals = None, locals = None, fromlist = (), level = 0):
+    def fake_import(
+        name,
+        globals = None,
+        locals = None,
+        fromlist = (),
+        level = 0,
+    ):
         if name == missing:
             raise ImportError
         return real_import(name, globals, locals, fromlist, level)
@@ -37,9 +49,7 @@ def _missing_module_import(missing: str):
 def test_should_try_runtime_flash_attn_install_threshold_and_skip(monkeypatch):
     monkeypatch.delenv(worker._FLASH_ATTN_SKIP_ENV, raising = False)
     assert worker._should_try_runtime_flash_attn_install(32767) is False
-    assert worker._should_try_runtime_flash_attn_install(
-        32768
-    ) is sys.platform.startswith("linux")
+    assert worker._should_try_runtime_flash_attn_install(32768) is sys.platform.startswith("linux")
 
     monkeypatch.setenv(worker._FLASH_ATTN_SKIP_ENV, "1")
     assert worker._should_try_runtime_flash_attn_install(32768) is False
@@ -105,7 +115,12 @@ def test_runtime_flash_attn_falls_back_to_pypi(monkeypatch):
     )
     monkeypatch.setattr(worker, "install_wheel", mock.Mock())
 
-    def fake_run(cmd, stdout = None, stderr = None, text = None):
+    def fake_run(
+        cmd,
+        stdout = None,
+        stderr = None,
+        text = None,
+    ):
         calls.append(list(cmd))
         return subprocess.CompletedProcess(cmd, 0, "")
 
@@ -131,9 +146,7 @@ def test_runtime_flash_attn_skips_on_blackwell(monkeypatch):
     install_mock = mock.Mock()
 
     monkeypatch.delenv(worker._FLASH_ATTN_SKIP_ENV, raising = False)
-    monkeypatch.setattr(
-        worker, "_should_try_runtime_flash_attn_install", lambda max_seq: True
-    )
+    monkeypatch.setattr(worker, "_should_try_runtime_flash_attn_install", lambda max_seq: True)
     monkeypatch.setattr(worker, "has_blackwell_gpu", lambda: True)
     monkeypatch.setattr(worker, "_install_package_wheel_first", install_mock)
     monkeypatch.setattr(
@@ -504,14 +517,10 @@ def test_tilelang_backend_reinstalls_when_tvm_ffi_is_broken(monkeypatch):
 
     # Repair: --force-reinstall --no-deps, apache-tvm-ffi ONLY (no tilelang).
     assert "--force-reinstall" in repair_args
-    assert (
-        "--no-deps" in repair_args
-    ), "Repair MUST use --no-deps to avoid replacing torch / CUDA"
+    assert "--no-deps" in repair_args, "Repair MUST use --no-deps to avoid replacing torch / CUDA"
     assert "--only-binary=:all:" in repair_args
     assert f"apache-tvm-ffi=={worker._APACHE_TVM_FFI_PACKAGE_VERSION}" in repair_args
-    assert all(
-        "tilelang" not in a for a in repair_args
-    ), "Repair MUST only touch apache-tvm-ffi"
+    assert all("tilelang" not in a for a in repair_args), "Repair MUST only touch apache-tvm-ffi"
 
     # Install: regular dep-resolving install, NO --force-reinstall.
     assert "--force-reinstall" not in install_args
@@ -689,16 +698,12 @@ def test_hook_installs_when_gate_returns_false(monkeypatch):
 
     conv_install = mock.Mock(side_effect = _conv_install_side_effect)
 
-    monkeypatch.setattr(
-        worker, "_ensure_flash_linear_attention_unconditional", fla_install
-    )
+    monkeypatch.setattr(worker, "_ensure_flash_linear_attention_unconditional", fla_install)
     monkeypatch.setattr(worker, "_ensure_tilelang_backend_unconditional", tile_install)
     monkeypatch.setattr(worker, "_install_package_wheel_first", conv_install)
     monkeypatch.delenv(worker._FAST_PATH_HOOKS_SKIP_ENV, raising = False)
 
-    worker._install_fast_path_hooks(
-        event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B"
-    )
+    worker._install_fast_path_hooks(event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B")
 
     from transformers.utils import import_utils as _iu
 
@@ -722,9 +727,7 @@ def test_hook_skips_install_when_gate_already_true(monkeypatch):
     fla_install = mock.Mock()
     tile_install = mock.Mock()
     conv_install = mock.Mock()
-    monkeypatch.setattr(
-        worker, "_ensure_flash_linear_attention_unconditional", fla_install
-    )
+    monkeypatch.setattr(worker, "_ensure_flash_linear_attention_unconditional", fla_install)
     monkeypatch.setattr(worker, "_ensure_tilelang_backend_unconditional", tile_install)
     monkeypatch.setattr(worker, "_install_package_wheel_first", conv_install)
     # Tilelang healthy so the post_available path is a no-op (otherwise
@@ -734,9 +737,7 @@ def test_hook_skips_install_when_gate_already_true(monkeypatch):
     monkeypatch.setattr(worker, "_installed_tvm_ffi_version", lambda: "0.1.9")
     monkeypatch.delenv(worker._FAST_PATH_HOOKS_SKIP_ENV, raising = False)
 
-    worker._install_fast_path_hooks(
-        event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B"
-    )
+    worker._install_fast_path_hooks(event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B")
 
     from transformers.utils import import_utils as _iu
 
@@ -764,16 +765,12 @@ def test_hook_idempotent_on_repeat_call(monkeypatch):
         return True
 
     conv_install = mock.Mock(side_effect = _conv_install_side_effect)
-    monkeypatch.setattr(
-        worker, "_ensure_flash_linear_attention_unconditional", fla_install
-    )
+    monkeypatch.setattr(worker, "_ensure_flash_linear_attention_unconditional", fla_install)
     monkeypatch.setattr(worker, "_ensure_tilelang_backend_unconditional", tile_install)
     monkeypatch.setattr(worker, "_install_package_wheel_first", conv_install)
     monkeypatch.delenv(worker._FAST_PATH_HOOKS_SKIP_ENV, raising = False)
 
-    worker._install_fast_path_hooks(
-        event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B"
-    )
+    worker._install_fast_path_hooks(event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B")
 
     from transformers.utils import import_utils as _iu
 
@@ -794,18 +791,12 @@ def test_hook_handles_install_failure_gracefully(monkeypatch):
     def raising_install(eq):
         raise RuntimeError("pip failed to fetch wheel")
 
-    monkeypatch.setattr(
-        worker, "_ensure_flash_linear_attention_unconditional", raising_install
-    )
-    monkeypatch.setattr(
-        worker, "_ensure_tilelang_backend_unconditional", lambda eq: None
-    )
+    monkeypatch.setattr(worker, "_ensure_flash_linear_attention_unconditional", raising_install)
+    monkeypatch.setattr(worker, "_ensure_tilelang_backend_unconditional", lambda eq: None)
     monkeypatch.setattr(worker, "_install_package_wheel_first", lambda **kw: None)
     monkeypatch.delenv(worker._FAST_PATH_HOOKS_SKIP_ENV, raising = False)
 
-    worker._install_fast_path_hooks(
-        event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B"
-    )
+    worker._install_fast_path_hooks(event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B")
 
     from transformers.utils import import_utils as _iu
 
@@ -819,14 +810,10 @@ def test_hook_can_be_disabled_via_env(monkeypatch):
     _patch_iu_gates(monkeypatch, fla_gate, conv_gate)
 
     fla_install = mock.Mock()
-    monkeypatch.setattr(
-        worker, "_ensure_flash_linear_attention_unconditional", fla_install
-    )
+    monkeypatch.setattr(worker, "_ensure_flash_linear_attention_unconditional", fla_install)
     monkeypatch.setenv(worker._FAST_PATH_HOOKS_SKIP_ENV, "1")
 
-    worker._install_fast_path_hooks(
-        event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B"
-    )
+    worker._install_fast_path_hooks(event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B")
 
     from transformers.utils import import_utils as _iu
 
@@ -841,18 +828,12 @@ def test_hook_clears_lru_cache_before_first_check(monkeypatch):
     conv_gate = _make_fake_gate(initial_return = True)
     _patch_iu_gates(monkeypatch, fla_gate, conv_gate)
 
-    monkeypatch.setattr(
-        worker, "_ensure_flash_linear_attention_unconditional", lambda eq: None
-    )
-    monkeypatch.setattr(
-        worker, "_ensure_tilelang_backend_unconditional", lambda eq: None
-    )
+    monkeypatch.setattr(worker, "_ensure_flash_linear_attention_unconditional", lambda eq: None)
+    monkeypatch.setattr(worker, "_ensure_tilelang_backend_unconditional", lambda eq: None)
     monkeypatch.setattr(worker, "_install_package_wheel_first", lambda **kw: None)
     monkeypatch.delenv(worker._FAST_PATH_HOOKS_SKIP_ENV, raising = False)
 
-    worker._install_fast_path_hooks(
-        event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B"
-    )
+    worker._install_fast_path_hooks(event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B")
     from transformers.utils import import_utils as _iu
 
     _iu.is_flash_linear_attention_available()
@@ -880,18 +861,12 @@ def test_hook_rewrites_previously_imported_module_bindings(monkeypatch):
         fla_gate.next_return = True
         return True
 
-    monkeypatch.setattr(
-        worker, "_ensure_flash_linear_attention_unconditional", fake_install
-    )
-    monkeypatch.setattr(
-        worker, "_ensure_tilelang_backend_unconditional", lambda eq: True
-    )
+    monkeypatch.setattr(worker, "_ensure_flash_linear_attention_unconditional", fake_install)
+    monkeypatch.setattr(worker, "_ensure_tilelang_backend_unconditional", lambda eq: True)
     monkeypatch.setattr(worker, "_install_package_wheel_first", lambda **kw: True)
     monkeypatch.delenv(worker._FAST_PATH_HOOKS_SKIP_ENV, raising = False)
 
-    worker._install_fast_path_hooks(
-        event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B"
-    )
+    worker._install_fast_path_hooks(event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B")
 
     # The fake module's local binding has been rewritten to the wrapper.
     assert fake_mod.is_flash_linear_attention_available is not fla_gate
@@ -915,30 +890,20 @@ def test_hook_skips_when_import_utils_unavailable(monkeypatch):
     monkeypatch.delenv(worker._FAST_PATH_HOOKS_SKIP_ENV, raising = False)
 
     # Should not raise.
-    worker._install_fast_path_hooks(
-        event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B"
-    )
+    worker._install_fast_path_hooks(event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B")
 
 
 def test_substring_fallback_unchanged_when_hook_skipped(monkeypatch):
     """Hook disabled -> legacy gate falls back to auto-discovered model types."""
     install_mock = mock.Mock()
-    monkeypatch.setattr(
-        worker, "_ensure_flash_linear_attention_unconditional", install_mock
-    )
-    monkeypatch.setattr(
-        worker, "_discover_fla_model_types", lambda: frozenset({"qwen3_5"})
-    )
+    monkeypatch.setattr(worker, "_ensure_flash_linear_attention_unconditional", install_mock)
+    monkeypatch.setattr(worker, "_discover_fla_model_types", lambda: frozenset({"qwen3_5"}))
     monkeypatch.setenv(worker._FAST_PATH_HOOKS_SKIP_ENV, "1")
 
-    worker._ensure_flash_linear_attention(
-        event_queue = [], model_name = "unsloth/Qwen3.5-2B"
-    )
+    worker._ensure_flash_linear_attention(event_queue = [], model_name = "unsloth/Qwen3.5-2B")
     assert install_mock.call_count == 1
 
-    worker._ensure_flash_linear_attention(
-        event_queue = [], model_name = "meta-llama/Llama-3.1-8B"
-    )
+    worker._ensure_flash_linear_attention(event_queue = [], model_name = "meta-llama/Llama-3.1-8B")
     assert install_mock.call_count == 1
 
 
@@ -968,13 +933,9 @@ def test_hook_does_not_install_tilelang_for_model_outside_allowlist(monkeypatch)
 
     fla_install = mock.Mock(side_effect = _fla_install)
     tile_install = mock.Mock(return_value = True)
-    monkeypatch.setattr(
-        worker, "_ensure_flash_linear_attention_unconditional", fla_install
-    )
+    monkeypatch.setattr(worker, "_ensure_flash_linear_attention_unconditional", fla_install)
     monkeypatch.setattr(worker, "_ensure_tilelang_backend_unconditional", tile_install)
-    monkeypatch.setattr(
-        worker, "_install_package_wheel_first", mock.Mock(return_value = True)
-    )
+    monkeypatch.setattr(worker, "_install_package_wheel_first", mock.Mock(return_value = True))
     monkeypatch.delenv(worker._FAST_PATH_HOOKS_SKIP_ENV, raising = False)
     # Hermetize the auto-discovered set so the test stays valid as new
     # transformers releases add FLA-using model_types (eg olmo_hybrid in
@@ -1009,18 +970,12 @@ def test_hook_does_install_tilelang_for_qwen35(monkeypatch):
 
     fla_install = mock.Mock(side_effect = _fla_install)
     tile_install = mock.Mock(return_value = True)
-    monkeypatch.setattr(
-        worker, "_ensure_flash_linear_attention_unconditional", fla_install
-    )
+    monkeypatch.setattr(worker, "_ensure_flash_linear_attention_unconditional", fla_install)
     monkeypatch.setattr(worker, "_ensure_tilelang_backend_unconditional", tile_install)
-    monkeypatch.setattr(
-        worker, "_install_package_wheel_first", mock.Mock(return_value = True)
-    )
+    monkeypatch.setattr(worker, "_install_package_wheel_first", mock.Mock(return_value = True))
     monkeypatch.delenv(worker._FAST_PATH_HOOKS_SKIP_ENV, raising = False)
 
-    worker._install_fast_path_hooks(
-        event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B"
-    )
+    worker._install_fast_path_hooks(event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B")
 
     from transformers.utils import import_utils as _iu
 
@@ -1079,20 +1034,14 @@ def test_hook_trusts_installer_bool_not_metadata(monkeypatch):
         return False  # but deep import is broken
 
     fake_fla_install = mock.Mock(side_effect = _bad_install)
-    monkeypatch.setattr(
-        worker, "_ensure_flash_linear_attention_unconditional", fake_fla_install
-    )
+    monkeypatch.setattr(worker, "_ensure_flash_linear_attention_unconditional", fake_fla_install)
     monkeypatch.setattr(
         worker, "_ensure_tilelang_backend_unconditional", mock.Mock(return_value = True)
     )
-    monkeypatch.setattr(
-        worker, "_install_package_wheel_first", mock.Mock(return_value = True)
-    )
+    monkeypatch.setattr(worker, "_install_package_wheel_first", mock.Mock(return_value = True))
     monkeypatch.delenv(worker._FAST_PATH_HOOKS_SKIP_ENV, raising = False)
 
-    worker._install_fast_path_hooks(
-        event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B"
-    )
+    worker._install_fast_path_hooks(event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B")
 
     from transformers.utils import import_utils as _iu
 
@@ -1145,14 +1094,10 @@ def test_hook_skips_tilelang_when_fla_install_is_skipped(monkeypatch):
     monkeypatch.setenv(worker._FLA_SKIP_ENV, "1")
     tile_install = mock.Mock(return_value = True)
     monkeypatch.setattr(worker, "_ensure_tilelang_backend_unconditional", tile_install)
-    monkeypatch.setattr(
-        worker, "_install_package_wheel_first", mock.Mock(return_value = True)
-    )
+    monkeypatch.setattr(worker, "_install_package_wheel_first", mock.Mock(return_value = True))
     monkeypatch.delenv(worker._FAST_PATH_HOOKS_SKIP_ENV, raising = False)
 
-    worker._install_fast_path_hooks(
-        event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B"
-    )
+    worker._install_fast_path_hooks(event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B")
 
     from transformers.utils import import_utils as _iu
 
@@ -1172,21 +1117,15 @@ def test_hook_runs_tilelang_repair_when_fla_already_true(monkeypatch):
 
     fla_install = mock.Mock(return_value = True)
     tile_install = mock.Mock(return_value = True)
-    monkeypatch.setattr(
-        worker, "_ensure_flash_linear_attention_unconditional", fla_install
-    )
+    monkeypatch.setattr(worker, "_ensure_flash_linear_attention_unconditional", fla_install)
     monkeypatch.setattr(worker, "_ensure_tilelang_backend_unconditional", tile_install)
-    monkeypatch.setattr(
-        worker, "_install_package_wheel_first", mock.Mock(return_value = True)
-    )
+    monkeypatch.setattr(worker, "_install_package_wheel_first", mock.Mock(return_value = True))
     # tilelang missing AND tvm-ffi is on broken list — both trigger repair.
     monkeypatch.setattr(worker, "_tilelang_importable", lambda: False)
     monkeypatch.setattr(worker, "_installed_tvm_ffi_version", lambda: "0.1.11")
     monkeypatch.delenv(worker._FAST_PATH_HOOKS_SKIP_ENV, raising = False)
 
-    worker._install_fast_path_hooks(
-        event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B"
-    )
+    worker._install_fast_path_hooks(event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B")
 
     from transformers.utils import import_utils as _iu
 
@@ -1290,17 +1229,11 @@ def test_install_fast_path_hooks_sets_fla_tilelang_zero_on_hip(monkeypatch):
     monkeypatch.delenv("FLA_TILELANG", raising = False)
     monkeypatch.delenv(worker._FAST_PATH_HOOKS_SKIP_ENV, raising = False)
     monkeypatch.setattr(worker, "_torch_has_hip", lambda: True)
-    monkeypatch.setattr(
-        worker, "_ensure_flash_linear_attention_unconditional", lambda eq: True
-    )
-    monkeypatch.setattr(
-        worker, "_ensure_tilelang_backend_unconditional", lambda eq: True
-    )
+    monkeypatch.setattr(worker, "_ensure_flash_linear_attention_unconditional", lambda eq: True)
+    monkeypatch.setattr(worker, "_ensure_tilelang_backend_unconditional", lambda eq: True)
     monkeypatch.setattr(worker, "_install_package_wheel_first", lambda **kw: True)
 
-    worker._install_fast_path_hooks(
-        event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B"
-    )
+    worker._install_fast_path_hooks(event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B")
 
     assert _os.environ.get("FLA_TILELANG") == "0"
 
@@ -1314,17 +1247,11 @@ def test_install_fast_path_hooks_respects_user_fla_tilelang_override(monkeypatch
     monkeypatch.setenv("FLA_TILELANG", "1")
     monkeypatch.delenv(worker._FAST_PATH_HOOKS_SKIP_ENV, raising = False)
     monkeypatch.setattr(worker, "_torch_has_hip", lambda: True)
-    monkeypatch.setattr(
-        worker, "_ensure_flash_linear_attention_unconditional", lambda eq: True
-    )
-    monkeypatch.setattr(
-        worker, "_ensure_tilelang_backend_unconditional", lambda eq: True
-    )
+    monkeypatch.setattr(worker, "_ensure_flash_linear_attention_unconditional", lambda eq: True)
+    monkeypatch.setattr(worker, "_ensure_tilelang_backend_unconditional", lambda eq: True)
     monkeypatch.setattr(worker, "_install_package_wheel_first", lambda **kw: True)
 
-    worker._install_fast_path_hooks(
-        event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B"
-    )
+    worker._install_fast_path_hooks(event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B")
 
     assert _os.environ["FLA_TILELANG"] == "1"
 
@@ -1336,17 +1263,11 @@ def test_install_fast_path_hooks_does_not_set_fla_tilelang_on_cuda(monkeypatch):
     monkeypatch.delenv("FLA_TILELANG", raising = False)
     monkeypatch.delenv(worker._FAST_PATH_HOOKS_SKIP_ENV, raising = False)
     monkeypatch.setattr(worker, "_torch_has_hip", lambda: False)
-    monkeypatch.setattr(
-        worker, "_ensure_flash_linear_attention_unconditional", lambda eq: True
-    )
-    monkeypatch.setattr(
-        worker, "_ensure_tilelang_backend_unconditional", lambda eq: True
-    )
+    monkeypatch.setattr(worker, "_ensure_flash_linear_attention_unconditional", lambda eq: True)
+    monkeypatch.setattr(worker, "_ensure_tilelang_backend_unconditional", lambda eq: True)
     monkeypatch.setattr(worker, "_install_package_wheel_first", lambda **kw: True)
 
-    worker._install_fast_path_hooks(
-        event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B"
-    )
+    worker._install_fast_path_hooks(event_queue = _FakeQueue(), model_name = "unsloth/Qwen3.5-2B")
 
     assert _os.environ.get("FLA_TILELANG") is None
 
@@ -1356,9 +1277,7 @@ def test_install_fast_path_hooks_does_not_set_fla_tilelang_on_cuda(monkeypatch):
 # ───────────────────────────────────────────────────────────────────
 
 
-def _make_fake_transformers_tree(
-    tmp_path, fla_types: list[str], non_fla_types: list[str]
-):
+def _make_fake_transformers_tree(tmp_path, fla_types: list[str], non_fla_types: list[str]):
     """Lay out a tmp dir as `transformers/models/{type}/modeling_{type}.py`."""
     pkg = tmp_path / "transformers"
     models = pkg / "models"
@@ -1401,9 +1320,7 @@ def test_discover_fla_model_types_returns_only_fla_users(tmp_path, monkeypatch):
 
 
 def test_discover_fla_model_types_caches_across_calls(tmp_path, monkeypatch):
-    pkg = _make_fake_transformers_tree(
-        tmp_path, fla_types = ["qwen3_5"], non_fla_types = []
-    )
+    pkg = _make_fake_transformers_tree(tmp_path, fla_types = ["qwen3_5"], non_fla_types = [])
     fake = mock.MagicMock(__file__ = str(pkg / "__init__.py"))
     monkeypatch.setitem(sys.modules, "transformers", fake)
     _reset_fla_cache(monkeypatch)
@@ -1432,7 +1349,13 @@ def test_discover_fla_model_types_handles_missing_transformers(monkeypatch):
 
     real_import = builtins.__import__
 
-    def fake_import(name, globals = None, locals = None, fromlist = (), level = 0):
+    def fake_import(
+        name,
+        globals = None,
+        locals = None,
+        fromlist = (),
+        level = 0,
+    ):
         if name == "transformers":
             raise ImportError("transformers not installed")
         return real_import(name, globals, locals, fromlist, level)
@@ -1443,9 +1366,7 @@ def test_discover_fla_model_types_handles_missing_transformers(monkeypatch):
 
 
 def test_discover_fla_model_types_handles_unreadable_file(tmp_path, monkeypatch):
-    pkg = _make_fake_transformers_tree(
-        tmp_path, fla_types = ["qwen3_5"], non_fla_types = []
-    )
+    pkg = _make_fake_transformers_tree(tmp_path, fla_types = ["qwen3_5"], non_fla_types = [])
     fake = mock.MagicMock(__file__ = str(pkg / "__init__.py"))
     monkeypatch.setitem(sys.modules, "transformers", fake)
     _reset_fla_cache(monkeypatch)
@@ -1491,9 +1412,7 @@ def test_model_wants_tilelang_empty_when_transformers_has_no_fla(monkeypatch):
 
 
 def test_model_wants_tilelang_normalizes_separators(monkeypatch):
-    monkeypatch.setattr(
-        worker, "_discover_fla_model_types", lambda: frozenset({"qwen3_next"})
-    )
+    monkeypatch.setattr(worker, "_discover_fla_model_types", lambda: frozenset({"qwen3_next"}))
     for variant in (
         "qwen3-next",
         "Qwen3.Next",
diff --git a/studio/backend/tests/test_transformers_version.py b/studio/backend/tests/test_transformers_version.py
index c031c2fea3..ff5e1f1381 100644
--- a/studio/backend/tests/test_transformers_version.py
+++ b/studio/backend/tests/test_transformers_version.py
@@ -295,9 +295,7 @@ class TestGetTransformersTier:
             "utils.transformers_version._check_config_needs_550",
             return_value = False,
         ):
-            assert (
-                get_transformers_tier("mistralai/Ministral-3-8B-Instruct-2512") == "530"
-            )
+            assert get_transformers_tier("mistralai/Ministral-3-8B-Instruct-2512") == "530"
 
     def test_llama_returns_default(self):
         with (
diff --git a/studio/backend/tests/test_utils.py b/studio/backend/tests/test_utils.py
index 64c9907119..bdb1cd2ce8 100644
--- a/studio/backend/tests/test_utils.py
+++ b/studio/backend/tests/test_utils.py
@@ -25,14 +25,12 @@ import pytest
 # --- Conditional framework imports ---
 try:
     import torch
-
     HAS_TORCH = True
 except ImportError:
     HAS_TORCH = False
 
 try:
     import mlx.core as mx
-
     HAS_MLX = True
 except ImportError:
     HAS_MLX = False
@@ -196,15 +194,12 @@ class TestGetGpuMemoryInfo:
         # can render the correct label. On CUDA / XPU / MLX / CPU hosts
         # it is equivalent to `get_device().value`.
         from utils.hardware.hardware import _backend_label
-
         result = get_gpu_memory_info()
         assert result["backend"] == _backend_label(get_device())
 
     # --- When a GPU IS available ---
 
-    @pytest.mark.skipif(
-        _actual_device() == "cpu", reason = "No GPU available on this machine"
-    )
+    @pytest.mark.skipif(_actual_device() == "cpu", reason = "No GPU available on this machine")
     def test_gpu_available_fields(self):
         result = get_gpu_memory_info()
         assert result["available"] is True
@@ -302,9 +297,7 @@ class TestLogGpuMemory:
             "free_gb": 14.0,
         }
 
-        with patch(
-            "utils.hardware.hardware.get_gpu_memory_info", return_value = fake_info
-        ):
+        with patch("utils.hardware.hardware.get_gpu_memory_info", return_value = fake_info):
             log_gpu_memory("unit-test")
 
         captured = capfd.readouterr()
@@ -315,9 +308,7 @@ class TestLogGpuMemory:
     def test_logs_cpu_fallback_when_no_gpu(self, capfd):
         fake_info = {"available": False, "backend": "cpu"}
 
-        with patch(
-            "utils.hardware.hardware.get_gpu_memory_info", return_value = fake_info
-        ):
+        with patch("utils.hardware.hardware.get_gpu_memory_info", return_value = fake_info):
             log_gpu_memory("cpu-test")
 
         captured = capfd.readouterr()
diff --git a/studio/backend/tests/test_vision_cache.py b/studio/backend/tests/test_vision_cache.py
index 9e7bbdd1fb..2af64dac91 100644
--- a/studio/backend/tests/test_vision_cache.py
+++ b/studio/backend/tests/test_vision_cache.py
@@ -209,9 +209,7 @@ class TestVisionCacheDirectPath:
 
     @patch("utils.transformers_version.needs_transformers_5", return_value = False)
     @patch("utils.models.model_config.load_model_config")
-    def test_vision_config_attr_detected_and_cached(
-        self, mock_load_config, mock_needs_t5
-    ):
+    def test_vision_config_attr_detected_and_cached(self, mock_load_config, mock_needs_t5):
         """Models with vision_config (LLaVA, Qwen2-VL, etc.) should be cached as True."""
         cfg = MagicMock(spec = [])  # strict: only explicitly set attrs exist
         cfg.model_type = "qwen2_vl"
diff --git a/studio/backend/tests/test_vram_estimation.py b/studio/backend/tests/test_vram_estimation.py
index e54ae6dcf8..65964908d7 100644
--- a/studio/backend/tests/test_vram_estimation.py
+++ b/studio/backend/tests/test_vram_estimation.py
@@ -316,12 +316,8 @@ class TestLoraParams(unittest.TestCase):
         self.assertLess(qv_only, all_mods)
 
     def test_moe_mlp_modules_scale_with_experts(self):
-        dense_lora = compute_lora_params(
-            LLAMA_8B, 16, ["gate_proj", "up_proj", "down_proj"]
-        )
-        moe_lora = compute_lora_params(
-            MOE_CONFIG, 16, ["gate_proj", "up_proj", "down_proj"]
-        )
+        dense_lora = compute_lora_params(LLAMA_8B, 16, ["gate_proj", "up_proj", "down_proj"])
+        moe_lora = compute_lora_params(MOE_CONFIG, 16, ["gate_proj", "up_proj", "down_proj"])
         ratio = moe_lora / dense_lora
         self.assertAlmostEqual(ratio, 8.0, delta = 0.5)
 
@@ -338,12 +334,8 @@ class TestLoraParams(unittest.TestCase):
         self.assertGreater(moe_lora, dense_lora * 20)
 
     def test_attention_modules_same_for_moe(self):
-        dense_attn = compute_lora_params(
-            LLAMA_8B, 16, ["q_proj", "k_proj", "v_proj", "o_proj"]
-        )
-        moe_attn = compute_lora_params(
-            MOE_CONFIG, 16, ["q_proj", "k_proj", "v_proj", "o_proj"]
-        )
+        dense_attn = compute_lora_params(LLAMA_8B, 16, ["q_proj", "k_proj", "v_proj", "o_proj"])
+        moe_attn = compute_lora_params(MOE_CONFIG, 16, ["q_proj", "k_proj", "v_proj", "o_proj"])
         self.assertEqual(dense_attn, moe_attn)
 
     def test_all_linear_uses_default_text_modules(self):
@@ -466,9 +458,7 @@ class TestActivationBytes(unittest.TestCase):
 
     def test_non_flash_attention_uses_quadratic_path(self):
         seq_len = 4096
-        expected_quadratic = (
-            1 * STRUCTURED_MIXED.num_attention_heads * seq_len * seq_len * 2 * 12.0
-        )
+        expected_quadratic = 1 * STRUCTURED_MIXED.num_attention_heads * seq_len * seq_len * 2 * 12.0
         for attention_implementation in ("eager", "unknown_impl", None):
             with self.subTest(attention_implementation = attention_implementation):
                 non_flash = compute_activation_bytes(
@@ -483,9 +473,7 @@ class TestActivationBytes(unittest.TestCase):
 
     def test_non_flash_attention_without_gc_scales_quadratic_path_by_layers(self):
         seq_len = 4096
-        one_layer = (
-            1 * STRUCTURED_MIXED.num_attention_heads * seq_len * seq_len * 2 * 12.0
-        )
+        one_layer = 1 * STRUCTURED_MIXED.num_attention_heads * seq_len * seq_len * 2 * 12.0
         non_flash = compute_activation_bytes(
             STRUCTURED_MIXED,
             1,
@@ -717,9 +705,7 @@ class TestEstimateTrainingVram(unittest.TestCase):
         )
         v8 = estimate_training_vram(LLAMA_8B, opt8)
         v32 = estimate_training_vram(LLAMA_8B, opt32)
-        self.assertAlmostEqual(
-            v32.optimizer_states / v8.optimizer_states, 1.5, delta = 0.1
-        )
+        self.assertAlmostEqual(v32.optimizer_states / v8.optimizer_states, 1.5, delta = 0.1)
 
     def test_min_gpu_vram_treats_activations_as_per_gpu_fixed(self):
         config = TrainingVramConfig(training_method = "qlora", load_in_4bit = True)
@@ -769,9 +755,7 @@ class TestEstimateTrainingVram(unittest.TestCase):
             optimizer = "adamw_8bit",
             load_in_4bit = False,
         )
-        expected_floor = int(
-            compute_model_weights_bytes(LLAMA_8B, "full", False) * 0.15
-        )
+        expected_floor = int(compute_model_weights_bytes(LLAMA_8B, "full", False) * 0.15)
         with patch(
             "utils.hardware.vram_estimation.compute_gradient_bytes",
             return_value = 1,
@@ -1059,7 +1043,6 @@ class TestDenseLayerIndices(unittest.TestCase):
 class TestKvSharedLayer(unittest.TestCase):
     def test_fully_shared_kv_returns_false_matching_upstream(self):
         from utils.hardware.vram_estimation import _is_kv_shared_layer
-
         arch = ModelArchConfig(
             hidden_size = 512,
             num_hidden_layers = 4,
@@ -1293,9 +1276,7 @@ class TestSharedExperts(unittest.TestCase):
         delta_per_layer = 4096 * 1407 * 3 * 2
         expected_delta = delta_per_layer * 32 * 2
         actual_delta = w_yes - w_no
-        self.assertAlmostEqual(
-            actual_delta, expected_delta, delta = expected_delta * 0.01
-        )
+        self.assertAlmostEqual(actual_delta, expected_delta, delta = expected_delta * 0.01)
 
     def test_deepseek_v3_params_in_range(self):
         total = compute_total_params(DEEPSEEK_V3)
@@ -1411,9 +1392,7 @@ class TestDenseMoEMix(unittest.TestCase):
             moe_intermediate_size = 1024,
             num_dense_layers = 5,
         )
-        lora_all = compute_lora_params(
-            all_moe, 16, ["gate_proj", "up_proj", "down_proj"]
-        )
+        lora_all = compute_lora_params(all_moe, 16, ["gate_proj", "up_proj", "down_proj"])
         lora_mix = compute_lora_params(mixed, 16, ["gate_proj", "up_proj", "down_proj"])
         self.assertNotEqual(lora_all, lora_mix)
 
@@ -1497,9 +1476,7 @@ class TestPerLayerInputSkipAlias(unittest.TestCase):
         delta = _compute_skipped_quantizable_elements(arch)
         self.assertEqual(
             delta,
-            arch.hidden_size
-            * arch.num_hidden_layers
-            * arch.hidden_size_per_layer_input,
+            arch.hidden_size * arch.num_hidden_layers * arch.hidden_size_per_layer_input,
         )
 
     def test_layer_aggregate_skip_includes_per_layer_input_modules(self):
@@ -1578,9 +1555,7 @@ class TestSharedExpertVariants(unittest.TestCase):
     def test_shared_expert_size_separate_from_routed_changes_weight_count(self):
         from utils.hardware.vram_estimation import _compute_moe_mlp_elements
 
-        arch_separate = extract_arch_config(
-            self._hf(shared_expert_intermediate_size = 64)
-        )
+        arch_separate = extract_arch_config(self._hf(shared_expert_intermediate_size = 64))
         arch_implicit = extract_arch_config(self._hf(n_shared_experts = 1))
         # Different shared sizes (64 vs default moe_intermediate_size=128) must
         # produce different MoE element counts.
@@ -1624,9 +1599,7 @@ class TestSharedExpertActivation(unittest.TestCase):
             moe_intermediate_size = 64,
             **fields,
         )
-        return extract_arch_config(
-            SimpleNamespace(text_config = text_config, quantization_config = {})
-        )
+        return extract_arch_config(SimpleNamespace(text_config = text_config, quantization_config = {}))
 
     def test_shared_expert_increases_activation_bytes(self):
         with_shared = self._make(shared_expert_intermediate_size = 64)
@@ -1678,9 +1651,7 @@ class TestPerLayerInputActivation(unittest.TestCase):
             tie_word_embeddings = False,
             **fields,
         )
-        return extract_arch_config(
-            SimpleNamespace(text_config = text_config, quantization_config = {})
-        )
+        return extract_arch_config(SimpleNamespace(text_config = text_config, quantization_config = {}))
 
     def test_ple_increases_activation_bytes(self):
         with_ple = self._make(
@@ -1744,9 +1715,7 @@ class TestKvSharedActivation(unittest.TestCase):
             num_kv_shared_layers = kv_shared,
             layer_types = ["full_attention"] * 4,
         )
-        return extract_arch_config(
-            SimpleNamespace(text_config = text_config, quantization_config = {})
-        )
+        return extract_arch_config(SimpleNamespace(text_config = text_config, quantization_config = {}))
 
     def test_kv_shared_layers_keep_activation_bytes(self):
         shared = self._make(kv_shared = 2)
@@ -1792,10 +1761,7 @@ class TestSparseMoeSkipAliases(unittest.TestCase):
 
     def test_gemma4_layers_experts_alias_pulls_routed(self):
         from utils.hardware.vram_estimation import _compute_skipped_quantizable_elements
-
-        arch = extract_arch_config(
-            self._hf(["model.layers.0.experts"], enable_moe_block = True)
-        )
+        arch = extract_arch_config(self._hf(["model.layers.0.experts"], enable_moe_block = True))
         self.assertGreater(_compute_skipped_quantizable_elements(arch), 0)
 
     def test_qwen_shared_expert_skip_pulls_only_shared(self):
@@ -1823,7 +1789,6 @@ class TestSparseMoeSkipAliases(unittest.TestCase):
 
     def test_exaone_shared_experts_plural_alias(self):
         from utils.hardware.vram_estimation import _compute_skipped_quantizable_elements
-
         arch = extract_arch_config(
             self._hf(
                 ["model.layers.0.mlp.shared_experts"],
@@ -1847,9 +1812,7 @@ class TestAllLinearMoELoraExclusion(unittest.TestCase):
             moe_intermediate_size = 64,
             **fields,
         )
-        return extract_arch_config(
-            SimpleNamespace(text_config = text_config, quantization_config = {})
-        )
+        return extract_arch_config(SimpleNamespace(text_config = text_config, quantization_config = {}))
 
     def test_all_linear_drops_routed_moe_expert_lora(self):
         arch = self._arch()
@@ -1867,9 +1830,7 @@ class TestAllLinearMoELoraExclusion(unittest.TestCase):
     def test_all_linear_includes_attention_lora(self):
         arch = self._arch()
         all_linear = compute_lora_params(arch, 8, "all-linear")
-        attn_only = compute_lora_params(
-            arch, 8, ["q_proj", "k_proj", "v_proj", "o_proj"]
-        )
+        attn_only = compute_lora_params(arch, 8, ["q_proj", "k_proj", "v_proj", "o_proj"])
         # all-linear still attaches to attention nn.Linear modules.
         self.assertGreaterEqual(all_linear, attn_only)
 
@@ -1887,9 +1848,7 @@ class TestExplicitPerLayerInputLora(unittest.TestCase):
             hidden_size_per_layer_input = 32,
             vocab_size_per_layer_input = 128,
         )
-        return extract_arch_config(
-            SimpleNamespace(text_config = text_config, quantization_config = {})
-        )
+        return extract_arch_config(SimpleNamespace(text_config = text_config, quantization_config = {}))
 
     def test_explicit_per_layer_input_gate_returns_nonzero(self):
         arch = self._arch()
@@ -1928,9 +1887,7 @@ class TestTopKExpertActivation(unittest.TestCase):
             moe_intermediate_size = 64,
             **fields,
         )
-        return extract_arch_config(
-            SimpleNamespace(text_config = text_config, quantization_config = {})
-        )
+        return extract_arch_config(SimpleNamespace(text_config = text_config, quantization_config = {}))
 
     def test_num_experts_per_tok_extracted(self):
         arch = self._make(num_experts_per_tok = 4)
@@ -2180,13 +2137,11 @@ class TestLlama4ArchExtraction(unittest.TestCase):
 
     def test_llama4_moe_layers_dispatch_uses_explicit_indices(self):
         from utils.hardware.vram_estimation import _compute_dense_layer_indices
-
         cfg = SimpleNamespace(num_hidden_layers = 4, moe_layers = [1, 3])
         self.assertEqual(_compute_dense_layer_indices(cfg, 4), (0, 2))
 
     def test_llama4_moe_layers_takes_priority_over_first_k_dense_replace(self):
         from utils.hardware.vram_estimation import _compute_dense_layer_indices
-
         cfg = SimpleNamespace(
             num_hidden_layers = 6,
             moe_layers = [2, 4],
@@ -2288,7 +2243,6 @@ class TestDbrxFfnConfigExtraction(unittest.TestCase):
 class TestErniePhaseModuloDispatch(unittest.TestCase):
     def test_phase_modulo_with_interval_two_matches_decoder(self):
         from utils.hardware.vram_estimation import _compute_dense_layer_indices
-
         cfg = SimpleNamespace(
             num_hidden_layers = 10,
             moe_layer_start_index = 2,
@@ -2300,7 +2254,6 @@ class TestErniePhaseModuloDispatch(unittest.TestCase):
 
     def test_phase_modulo_with_interval_three(self):
         from utils.hardware.vram_estimation import _compute_dense_layer_indices
-
         cfg = SimpleNamespace(
             num_hidden_layers = 9,
             moe_layer_start_index = 0,
diff --git a/studio/backend/tests/test_windows_gpu_detection_mock.py b/studio/backend/tests/test_windows_gpu_detection_mock.py
index 023630fb9a..bc887f8cc5 100644
--- a/studio/backend/tests/test_windows_gpu_detection_mock.py
+++ b/studio/backend/tests/test_windows_gpu_detection_mock.py
@@ -169,14 +169,14 @@ def _populate_studio_install(install_dir: Path, runtime: str = "13.1") -> None:
 
 
 def _build_path_dirs_like_start_llama_server(
-    binary_dir: Path, prefix: Path, cuda_path: str = ""
+    binary_dir: Path,
+    prefix: Path,
+    cuda_path: str = "",
 ) -> list[str]:
     """Path-friendly wrapper around LlamaCppBackend._build_windows_path_dirs.
     Asserting against the staticmethod (not a hand-copy) is the point:
     if the win32 PATH order drops _windows_pip_nvidia_dll_dirs, tests fail."""
-    return LlamaCppBackend._build_windows_path_dirs(
-        str(binary_dir), str(prefix), cuda_path
-    )
+    return LlamaCppBackend._build_windows_path_dirs(str(binary_dir), str(prefix), cuda_path)
 
 
 def _mock_nvidia_smi_run(fake_output: str, returncode: int = 0) -> "mock._patch":
@@ -210,9 +210,7 @@ class TestWindowsGpuDetectionAfter5106Fix:
         fake_csv = "0, 22805\n"
         with _mock_nvidia_smi_run(fake_csv):
             gpus = LlamaCppBackend._get_gpu_free_memory()
-        assert gpus == [
-            (0, 22805)
-        ], f"GPU probe failed to parse mocked nvidia-smi output: {gpus}"
+        assert gpus == [(0, 22805)], f"GPU probe failed to parse mocked nvidia-smi output: {gpus}"
 
     def test_nvidia_smi_probe_respects_cuda_visible_devices(self, monkeypatch):
         """CUDA_VISIBLE_DEVICES=1 -> only GPU 1 visible."""
@@ -247,9 +245,7 @@ class TestWindowsGpuDetectionAfter5106Fix:
             site / "nvidia" / "cu13" / "bin" / "x86_64",
             site / "torch" / "lib",
         ):
-            assert (
-                str(expected) in out
-            ), f"resolver missed {expected.relative_to(prefix)}: {out}"
+            assert str(expected) in out, f"resolver missed {expected.relative_to(prefix)}: {out}"
 
     def test_path_assembly_makes_cudart_reachable_without_toolkit(self, tmp_path):
         """The #5106 scenario: GPU detected, pip nvidia wheels present,
@@ -260,9 +256,7 @@ class TestWindowsGpuDetectionAfter5106Fix:
         _populate_studio_venv(prefix)
         _populate_studio_install(install, runtime = "13.1")
         binary_dir = install / "build" / "bin" / "Release"
-        path_dirs = _build_path_dirs_like_start_llama_server(
-            binary_dir, prefix, cuda_path = ""
-        )
+        path_dirs = _build_path_dirs_like_start_llama_server(binary_dir, prefix, cuda_path = "")
         # binary_dir first -- Windows DLL search step 1.
         assert path_dirs[0] == str(
             binary_dir
@@ -278,9 +272,7 @@ class TestWindowsGpuDetectionAfter5106Fix:
         )
         # Defence in depth: both fix paths contribute cudart.
         sources = {Path(e).relative_to(tmp_path).parts[0] for e, _ in cudart_locations}
-        assert (
-            "studio_install" in sources
-        ), f"#5322's cudart drop not reachable: {cudart_locations}"
+        assert "studio_install" in sources, f"#5322's cudart drop not reachable: {cudart_locations}"
         assert (
             "studio_venv" in sources
         ), f"#5324's pip nvidia dir not contributing cudart: {cudart_locations}"
@@ -297,8 +289,7 @@ class TestWindowsGpuDetectionAfter5106Fix:
         for required in REAL_UPSTREAM_CUDART_BUNDLE["13.1"]:
             reachable = any((Path(d) / required).exists() for d in path_dirs)
             assert reachable, (
-                f"{required} unreachable from PATH; #5106 not fixed.\n"
-                f"PATH entries: {path_dirs}"
+                f"{required} unreachable from PATH; #5106 not fixed.\n" f"PATH entries: {path_dirs}"
             )
 
     def test_no_pip_nvidia_wheels_still_works_via_install_dir(self, tmp_path):
@@ -310,9 +301,7 @@ class TestWindowsGpuDetectionAfter5106Fix:
         _populate_studio_install(install, runtime = "13.1")
         binary_dir = install / "build" / "bin" / "Release"
         path_dirs = _build_path_dirs_like_start_llama_server(binary_dir, prefix)
-        assert path_dirs == [
-            str(binary_dir)
-        ], f"bare venv produced unexpected PATH: {path_dirs}"
+        assert path_dirs == [str(binary_dir)], f"bare venv produced unexpected PATH: {path_dirs}"
         for required in REAL_UPSTREAM_CUDART_BUNDLE["13.1"]:
             assert (
                 binary_dir / required
@@ -336,8 +325,7 @@ class TestWindowsGpuDetectionAfter5106Fix:
             (rel / fn).write_bytes(b"PE-stub")
         path_dirs = _build_path_dirs_like_start_llama_server(rel, prefix)
         cudart_reachable = any(
-            (Path(d) / "cudart64_12.dll").exists()
-            or (Path(d) / "cudart64_13.dll").exists()
+            (Path(d) / "cudart64_12.dll").exists() or (Path(d) / "cudart64_13.dll").exists()
             for d in path_dirs
         )
         assert cudart_reachable, (
@@ -345,8 +333,7 @@ class TestWindowsGpuDetectionAfter5106Fix:
             f"on cudart-less install. PATH entries: {path_dirs}"
         )
         cublas_reachable = any(
-            (Path(d) / "cublas64_12.dll").exists()
-            or (Path(d) / "cublas64_13.dll").exists()
+            (Path(d) / "cublas64_12.dll").exists() or (Path(d) / "cublas64_13.dll").exists()
             for d in path_dirs
         )
         assert cublas_reachable, "cublas unreachable on cudart-less install"
@@ -365,8 +352,7 @@ class TestWindowsGpuDetectionAfter5106Fix:
         # Pre-PR PATH: binary_dir only. No pip nvidia dirs, no toolkit.
         pre_pr_path_dirs = [str(rel)]
         cudart_reachable_pre = any(
-            (Path(d) / "cudart64_12.dll").exists()
-            or (Path(d) / "cudart64_13.dll").exists()
+            (Path(d) / "cudart64_12.dll").exists() or (Path(d) / "cudart64_13.dll").exists()
             for d in pre_pr_path_dirs
         )
         assert not cudart_reachable_pre, (
@@ -387,7 +373,5 @@ class TestWindowsSysPlatformMocked:
         out = LlamaCppBackend._windows_pip_nvidia_dll_dirs(str(prefix))
         assert out, f"resolver returned empty under sys.platform=win32: {out}"
         # cu13 arch dir must be in the output.
-        cu13_arch = (
-            prefix / "Lib" / "site-packages" / "nvidia" / "cu13" / "bin" / "x86_64"
-        )
+        cu13_arch = prefix / "Lib" / "site-packages" / "nvidia" / "cu13" / "bin" / "x86_64"
         assert str(cu13_arch) in out
diff --git a/studio/backend/utils/cache_cleanup.py b/studio/backend/utils/cache_cleanup.py
index 4c8e6239a0..9d01b40add 100644
--- a/studio/backend/utils/cache_cleanup.py
+++ b/studio/backend/utils/cache_cleanup.py
@@ -75,8 +75,7 @@ def clear_unsloth_compiled_cache(preserve_patterns: Optional[List[str]] = None)
 
         if preserve_patterns:
             logger.info(
-                f"Cleaning unsloth compiled cache (preserving {preserve_patterns}): "
-                f"{cache_dir}"
+                f"Cleaning unsloth compiled cache (preserving {preserve_patterns}): " f"{cache_dir}"
             )
 
             for item in cache_dir.iterdir():
diff --git a/studio/backend/utils/datasets/data_collators.py b/studio/backend/utils/datasets/data_collators.py
index 687da74c21..2955ec9023 100644
--- a/studio/backend/utils/datasets/data_collators.py
+++ b/studio/backend/utils/datasets/data_collators.py
@@ -28,19 +28,13 @@ class DataCollatorSpeechSeq2SeqWithPadding:
     processor: Any
 
     def __call__(self, features: List[dict]) -> dict:
-        input_features = [
-            {"input_features": feature["input_features"]} for feature in features
-        ]
-        batch = self.processor.feature_extractor.pad(
-            input_features, return_tensors = "pt"
-        )
+        input_features = [{"input_features": feature["input_features"]} for feature in features]
+        batch = self.processor.feature_extractor.pad(input_features, return_tensors = "pt")
 
         label_features = [{"input_ids": feature["labels"]} for feature in features]
         labels_batch = self.processor.tokenizer.pad(label_features, return_tensors = "pt")
 
-        labels = labels_batch["input_ids"].masked_fill(
-            labels_batch.attention_mask.ne(1), -100
-        )
+        labels = labels_batch["input_ids"].masked_fill(labels_batch.attention_mask.ne(1), -100)
 
         if (labels[:, 0] == self.processor.tokenizer.bos_token_id).all().cpu().item():
             labels = labels[:, 1:]
@@ -169,9 +163,7 @@ class VLMDataCollator:
 
         # Apply chat template
         texts = [
-            self.processor.apply_chat_template(
-                msgs, tokenize = False, add_generation_prompt = False
-            )
+            self.processor.apply_chat_template(msgs, tokenize = False, add_generation_prompt = False)
             for msgs in all_messages
         ]
 
diff --git a/studio/backend/utils/datasets/dataset_none_detect.py b/studio/backend/utils/datasets/dataset_none_detect.py
index 1e884271cc..e48e153fb8 100644
--- a/studio/backend/utils/datasets/dataset_none_detect.py
+++ b/studio/backend/utils/datasets/dataset_none_detect.py
@@ -75,9 +75,7 @@ def _probe_conversation(dataset: Dataset, candidates = None):
             # a list holding a dict/None turn); scalars and list-of-strings must
             # not look like chatml. Upgrade a non-plausible fallback when a later
             # candidate is plausible, so probe order keeps the best match.
-            if all_corrupt_fallback is None or not all_corrupt_fallback.get(
-                "has_plausible_turns"
-            ):
+            if all_corrupt_fallback is None or not all_corrupt_fallback.get("has_plausible_turns"):
                 has_plausible_turns = False
                 for i in range(min(len(dataset), 100)):
                     cell = dataset[i][col]
@@ -122,9 +120,7 @@ def _probe_conversation(dataset: Dataset, candidates = None):
         _CONV_KEYS = {"role", "from", "content", "value"}
         if not any(keys <= turn_keys for keys in _CHAT_KEY_SETS):
             schema_less_plausible = bool(turn_keys & _CONV_KEYS)
-            if all_corrupt_fallback is None or not all_corrupt_fallback.get(
-                "has_plausible_turns"
-            ):
+            if all_corrupt_fallback is None or not all_corrupt_fallback.get("has_plausible_turns"):
                 all_corrupt_fallback = {
                     "column": col,
                     "turn_keys": turn_keys,
@@ -167,14 +163,11 @@ def is_none_or_empty(value) -> bool:
         non_text_blocks = [item for item in dict_blocks if item.get("type") != "text"]
         if non_text_blocks:
             return False
-        text_values = [
-            item.get("text") for item in dict_blocks if item.get("type") == "text"
-        ]
+        text_values = [item.get("text") for item in dict_blocks if item.get("type") == "text"]
         if text_values and all(
             t is None
             or (
-                isinstance(t, str)
-                and not t.strip().strip("\ufeff\u200b\u200c\u200d\u2060").strip()
+                isinstance(t, str) and not t.strip().strip("\ufeff\u200b\u200c\u200d\u2060").strip()
             )
             for t in text_values
         ):
@@ -285,9 +278,7 @@ def find_none_chatml(dataset: Dataset, col: str = None) -> dict:
             stats["rows_with_none_turns"] += 1
             stats["total_none_turns"] += 1
             stats["rows_all_none"] += 1
-            stats["none_by_role"]["unknown"] = (
-                stats["none_by_role"].get("unknown", 0) + 1
-            )
+            stats["none_by_role"]["unknown"] = stats["none_by_role"].get("unknown", 0) + 1
             stats["none_by_type"][vtype] = stats["none_by_type"].get(vtype, 0) + 1
             stats["findings"].append(
                 {
@@ -306,9 +297,7 @@ def find_none_chatml(dataset: Dataset, col: str = None) -> dict:
             stats["rows_with_none_turns"] += 1
             stats["total_none_turns"] += 1
             stats["rows_all_none"] += 1
-            stats["none_by_role"]["unknown"] = (
-                stats["none_by_role"].get("unknown", 0) + 1
-            )
+            stats["none_by_role"]["unknown"] = stats["none_by_role"].get("unknown", 0) + 1
             stats["none_by_type"]["empty_conversation"] = (
                 stats["none_by_type"].get("empty_conversation", 0) + 1
             )
@@ -336,9 +325,7 @@ def find_none_chatml(dataset: Dataset, col: str = None) -> dict:
                         "raw_value": repr(turn),
                     }
                 )
-                stats["none_by_role"]["unknown"] = (
-                    stats["none_by_role"].get("unknown", 0) + 1
-                )
+                stats["none_by_role"]["unknown"] = stats["none_by_role"].get("unknown", 0) + 1
                 vtype = "None" if turn is None else "invalid_type"
                 stats["none_by_type"][vtype] = stats["none_by_type"].get(vtype, 0) + 1
                 continue
@@ -359,20 +346,14 @@ def find_none_chatml(dataset: Dataset, col: str = None) -> dict:
             if "from" in turn and "value" in turn:
                 content = turn.get("value")
             elif "role" in turn:
-                content = (
-                    turn.get("content") if "content" in turn else turn.get("value")
-                )
+                content = turn.get("content") if "content" in turn else turn.get("value")
             elif "from" in turn:
                 content = turn.get("value")
             else:
-                content = (
-                    turn.get("content") if "content" in turn else turn.get("value")
-                )
+                content = turn.get("content") if "content" in turn else turn.get("value")
             # Assistant tool-call turns carry empty content + tool_calls and are
             # valid; the exemption is assistant-only.
-            if is_none_or_empty(content) and not (
-                role == "assistant" and turn.get("tool_calls")
-            ):
+            if is_none_or_empty(content) and not (role == "assistant" and turn.get("tool_calls")):
                 vtype = _classify_empty(content)
                 row_findings.append(
                     {
@@ -469,9 +450,7 @@ FORMAT_REGISTRY = [
     },
     {
         "name": "sharegpt",
-        "match": lambda ds, conv: (
-            conv is not None and {"from", "value"} <= conv["turn_keys"]
-        ),
+        "match": lambda ds, conv: (conv is not None and {"from", "value"} <= conv["turn_keys"]),
         "scan": find_none_sharegpt,
     },
     {
@@ -532,13 +511,11 @@ def scan_dataset(dataset: Dataset, fmt: str = "auto") -> dict:
     _dict_types = []
     try:
         from datasets import DatasetDict as _DatasetDict
-
         _dict_types.append(_DatasetDict)
     except ImportError:
         pass
     try:
         from datasets import IterableDatasetDict as _IterableDatasetDict
-
         _dict_types.append(_IterableDatasetDict)
     except ImportError:
         pass
@@ -552,7 +529,6 @@ def scan_dataset(dataset: Dataset, fmt: str = "auto") -> dict:
     # instead of a confusing TypeError downstream.
     try:
         from datasets import IterableDataset as _IterableDataset
-
         if isinstance(dataset, _IterableDataset):
             raise ValueError(
                 "scan_dataset requires a materialized Dataset, not an IterableDataset. "
@@ -658,7 +634,11 @@ def _print_summary_header(stats: dict, fmt: str) -> bool:
     return True
 
 
-def print_report(stats: dict, fmt: str, summary_only: bool = False):
+def print_report(
+    stats: dict,
+    fmt: str,
+    summary_only: bool = False,
+):
     """Print a human-readable summary, optionally with full findings list."""
     has_findings = _print_summary_header(stats, fmt)
     if not has_findings or summary_only:
@@ -689,7 +669,12 @@ def print_report(stats: dict, fmt: str, summary_only: bool = False):
     print(f"{'=' * 64}")
 
 
-def show_row(dataset: Dataset, row_indices: list[int], fmt: str, col: str = None):
+def show_row(
+    dataset: Dataset,
+    row_indices: list[int],
+    fmt: str,
+    col: str = None,
+):
     """Print the full contents of specific rows for inspection.
 
     Used by test_codex_fixes.py to verify row rendering behaviour.
@@ -750,9 +735,7 @@ def show_row(dataset: Dataset, row_indices: list[int], fmt: str, col: str = None
                     # Mirror scanner logic: tool_calls exemption is assistant-only;
                     # other roles with empty content + tool_calls are still bad.
                     r = t.get("role") if t.get("role") is not None else t.get("from")
-                    if is_none_or_empty(c) and not (
-                        str(r) == "assistant" and t.get("tool_calls")
-                    ):
+                    if is_none_or_empty(c) and not (str(r) == "assistant" and t.get("tool_calls")):
                         return True
                     return False
 
@@ -773,19 +756,11 @@ def show_row(dataset: Dataset, row_indices: list[int], fmt: str, col: str = None
                     if "from" in turn and "value" in turn:
                         content = turn.get("value")
                     elif "role" in turn:
-                        content = (
-                            turn.get("content")
-                            if "content" in turn
-                            else turn.get("value")
-                        )
+                        content = turn.get("content") if "content" in turn else turn.get("value")
                     elif "from" in turn:
                         content = turn.get("value")
                     else:
-                        content = (
-                            turn.get("content")
-                            if "content" in turn
-                            else turn.get("value")
-                        )
+                        content = turn.get("content") if "content" in turn else turn.get("value")
                     if is_none_or_empty(content) and not (
                         role == "assistant" and turn.get("tool_calls")
                     ):
@@ -827,12 +802,8 @@ examples:
   python dataset_none_detect.py org/my-dataset --token hf_...
         """,
     )
-    parser.add_argument(
-        "dataset", help = "HuggingFace dataset repo id (e.g. org/my-dataset)"
-    )
-    parser.add_argument(
-        "--split", default = "train", help = "Dataset split to load (default: train)"
-    )
+    parser.add_argument("dataset", help = "HuggingFace dataset repo id (e.g. org/my-dataset)")
+    parser.add_argument("--split", default = "train", help = "Dataset split to load (default: train)")
     parser.add_argument(
         "--format",
         default = "auto",
diff --git a/studio/backend/utils/datasets/dataset_utils.py b/studio/backend/utils/datasets/dataset_utils.py
index 26378d64ee..792e0ea9bc 100644
--- a/studio/backend/utils/datasets/dataset_utils.py
+++ b/studio/backend/utils/datasets/dataset_utils.py
@@ -202,7 +202,11 @@ _CHATML_ROLE_ORDER = ("system", "user", "assistant")
 _CHATML_TO_ALPACA = {"user": "instruction", "system": "input", "assistant": "output"}
 
 
-def _apply_user_mapping(dataset, mapping: dict, batch_size: int = 1000):
+def _apply_user_mapping(
+    dataset,
+    mapping: dict,
+    batch_size: int = 1000,
+):
     """
     Apply user-provided column mapping to convert dataset to conversations format.
 
@@ -279,7 +283,10 @@ def _extract_column_value(val, col: str, label_mapping: dict) -> str:
 
 
 def _apply_template_mapping(
-    dataset, column_roles: dict, meta: dict, batch_size: int = 1000
+    dataset,
+    column_roles: dict,
+    meta: dict,
+    batch_size: int = 1000,
 ):
     """
     Apply advisor-driven mapping for non-conversational datasets.
@@ -324,9 +331,7 @@ def _apply_template_mapping(
             user_parts = []
             for col in role_groups["user"]:
                 if col in examples:
-                    user_parts.append(
-                        _extract_column_value(examples[col][i], col, label_mapping)
-                    )
+                    user_parts.append(_extract_column_value(examples[col][i], col, label_mapping))
             if user_parts:
                 convo.append({"role": "user", "content": "\n".join(user_parts)})
 
@@ -334,9 +339,7 @@ def _apply_template_mapping(
             asst_parts = []
             for col in role_groups["assistant"]:
                 if col in examples:
-                    asst_parts.append(
-                        _extract_column_value(examples[col][i], col, label_mapping)
-                    )
+                    asst_parts.append(_extract_column_value(examples[col][i], col, label_mapping))
             if asst_parts:
                 convo.append({"role": "assistant", "content": "\n".join(asst_parts)})
 
@@ -351,7 +354,11 @@ def _apply_template_mapping(
     )
 
 
-def _apply_user_mapping_alpaca(dataset, mapping: dict, batch_size: int = 1000):
+def _apply_user_mapping_alpaca(
+    dataset,
+    mapping: dict,
+    batch_size: int = 1000,
+):
     """
     Apply user-provided column mapping to convert dataset to Alpaca format.
 
@@ -382,11 +389,7 @@ def _apply_user_mapping_alpaca(dataset, mapping: dict, batch_size: int = 1000):
                 ("output", outputs),
             ):
                 col = col_for[field]
-                val = (
-                    str(examples[col][i])
-                    if col and col in examples and examples[col][i]
-                    else ""
-                )
+                val = str(examples[col][i]) if col and col in examples and examples[col][i] else ""
                 dest.append(val)
         return {"instruction": instructions, "input": inputs, "output": outputs}
 
@@ -464,9 +467,7 @@ def format_dataset(
             else:
                 # auto / chatml / sharegpt / conversational — all produce chatml conversations
                 # (sharegpt is always standardized to role/content internally)
-                mapped_dataset = _apply_user_mapping(
-                    dataset, custom_format_mapping, batch_size
-                )
+                mapped_dataset = _apply_user_mapping(dataset, custom_format_mapping, batch_size)
                 final_format = "chatml_conversations"
                 chat_column = "conversations"
 
@@ -578,9 +579,7 @@ def format_dataset(
 
         # Unknown - try standardization, if fails pass as is
         else:
-            warnings.append(
-                f"Unknown format detected. Keys found: {detected['sample_keys']}"
-            )
+            warnings.append(f"Unknown format detected. Keys found: {detected['sample_keys']}")
 
             # NEW: Try heuristic detection
             if auto_detect_custom:
@@ -606,9 +605,7 @@ def format_dataset(
                                     if role == target_role and col_name in examples:
                                         content = examples[col_name][i]
                                         if content and str(content).strip():
-                                            convo.append(
-                                                {"role": role, "content": str(content)}
-                                            )
+                                            convo.append({"role": role, "content": str(content)})
                             conversations.append(convo)
 
                         return {"conversations": conversations, **preserved_columns}
@@ -656,9 +653,7 @@ def format_dataset(
                         "warnings": warnings,
                     }
                 except Exception as e:
-                    warnings.append(
-                        f"Could not standardize: {e}. Passing dataset as-is."
-                    )
+                    warnings.append(f"Could not standardize: {e}. Passing dataset as-is.")
 
             # Return as-is with warnings
             return {
@@ -928,9 +923,7 @@ def format_and_template_dataset(
                         f"text='{user_vlm_text_column}') failed: {e} — "
                         f"falling back to auto-detection"
                     )
-                    logger.info(
-                        f"⚠️ User VLM mapping failed, falling back to auto-detection..."
-                    )
+                    logger.info(f"⚠️ User VLM mapping failed, falling back to auto-detection...")
                     custom_format_mapping = None  # clear so auto-detection runs below
             else:
                 errors.append(
@@ -984,9 +977,7 @@ def format_and_template_dataset(
                     dataset_name = dataset_name,
                     progress_callback = progress_callback,
                 )
-                warnings.append(
-                    "Converted from ShareGPT+image format to standard VLM format"
-                )
+                warnings.append("Converted from ShareGPT+image format to standard VLM format")
             except Exception as e:
                 errors.append(f"Failed to convert ShareGPT+image format: {e}")
                 import traceback
@@ -1020,7 +1011,6 @@ def format_and_template_dataset(
                 friendly = None
                 try:
                     from .llm_assist import llm_generate_dataset_warning
-
                     friendly = llm_generate_dataset_warning(
                         issues,
                         dataset_name = dataset_name,
@@ -1055,13 +1045,9 @@ def format_and_template_dataset(
                 )
 
                 if vlm_instruction:
-                    warnings.append(
-                        f"Using user-provided instruction: '{vlm_instruction}'"
-                    )
+                    warnings.append(f"Using user-provided instruction: '{vlm_instruction}'")
                 else:
-                    warnings.append(
-                        "Auto-generated instruction based on dataset analysis"
-                    )
+                    warnings.append("Auto-generated instruction based on dataset analysis")
 
             except Exception as e:
                 errors.append(f"Failed to convert to VLM format: {e}")
@@ -1166,9 +1152,7 @@ def format_and_template_dataset(
         summary = get_dataset_info_summary(dataset_info)
 
         # Combine results
-        all_warnings = dataset_info.get("warnings", []) + template_result.get(
-            "warnings", []
-        )
+        all_warnings = dataset_info.get("warnings", []) + template_result.get("warnings", [])
         all_errors = template_result.get("errors", [])
 
         # If format_dataset returned "unknown" but apply_chat_template rescued
diff --git a/studio/backend/utils/datasets/format_conversion.py b/studio/backend/utils/datasets/format_conversion.py
index 289b30e55e..5433d3115c 100644
--- a/studio/backend/utils/datasets/format_conversion.py
+++ b/studio/backend/utils/datasets/format_conversion.py
@@ -140,7 +140,11 @@ def standardize_chat_format(
     return dataset.map(_standardize_dataset, **dataset_map_kwargs)
 
 
-def convert_chatml_to_alpaca(dataset, batch_size = 1000, num_proc = None):
+def convert_chatml_to_alpaca(
+    dataset,
+    batch_size = 1000,
+    num_proc = None,
+):
     """
     Converts ChatML format (messages OR conversations) to Alpaca format.
     Handles both standardized and ShareGPT formats.
@@ -151,7 +155,6 @@ def convert_chatml_to_alpaca(dataset, batch_size = 1000, num_proc = None):
     """
     try:
         from torch.utils.data import IterableDataset
-
         _is_torch_iterable = isinstance(dataset, IterableDataset)
     except ImportError:
         _is_torch_iterable = False
@@ -159,15 +162,11 @@ def convert_chatml_to_alpaca(dataset, batch_size = 1000, num_proc = None):
     def _convert(examples):
         # Auto-detect which column name is used
         chatml_data = (
-            examples.get("messages")
-            or examples.get("conversations")
-            or examples.get("texts")
+            examples.get("messages") or examples.get("conversations") or examples.get("texts")
         )
 
         if chatml_data is None:
-            raise ValueError(
-                "No 'messages' or 'conversations' or 'texts' column found."
-            )
+            raise ValueError("No 'messages' or 'conversations' or 'texts' column found.")
 
         instructions = []
         outputs = []
@@ -215,7 +214,11 @@ def convert_chatml_to_alpaca(dataset, batch_size = 1000, num_proc = None):
     return dataset.map(_convert, **dataset_map_kwargs)
 
 
-def convert_alpaca_to_chatml(dataset, batch_size = 1000, num_proc = None):
+def convert_alpaca_to_chatml(
+    dataset,
+    batch_size = 1000,
+    num_proc = None,
+):
     """
     Converts Alpaca format to ChatML format.
 
@@ -223,7 +226,6 @@ def convert_alpaca_to_chatml(dataset, batch_size = 1000, num_proc = None):
     """
     try:
         from torch.utils.data import IterableDataset
-
         _is_torch_iterable = isinstance(dataset, IterableDataset)
     except ImportError:
         _is_torch_iterable = False
@@ -328,16 +330,12 @@ def convert_to_vlm_format(
         instruction_column = instruction_info.get("instruction_column")
         uses_dynamic = instruction_info["uses_dynamic_instruction"]
 
-        logger.info(
-            f"📝 Auto-detected instruction type: {instruction_info['instruction_type']}"
-        )
+        logger.info(f"📝 Auto-detected instruction type: {instruction_info['instruction_type']}")
         logger.info(f"📝 Confidence: {instruction_info['confidence']:.2f}")
         if not uses_dynamic:
             logger.info(f"📝 Using instruction: '{instruction}'")
         else:
-            logger.info(
-                f"📝 Using dynamic instructions from column: '{instruction_column}'"
-            )
+            logger.info(f"📝 Using dynamic instructions from column: '{instruction_column}'")
     else:
         instruction_column = None
         uses_dynamic = False
@@ -351,13 +349,11 @@ def convert_to_vlm_format(
             if image_data.startswith(("http://", "https://")):
                 import fsspec
                 from io import BytesIO
-
                 with fsspec.open(image_data, "rb", expand = True) as f:
                     image_data = Image.open(BytesIO(f.read())).convert("RGB")
             elif _image_lookup is not None and image_data in _image_lookup:
                 # Bare filename → resolve via HF repo lookup
                 from huggingface_hub import hf_hub_download
-
                 local_path = hf_hub_download(
                     dataset_name,
                     _image_lookup[image_data],
@@ -371,7 +367,6 @@ def convert_to_vlm_format(
         text_data = sample[text_column]
         if isinstance(text_data, list) and len(text_data) > 0:
             import random
-
             text_data = random.choice(text_data)
 
         # Get instruction (static or dynamic)
@@ -397,9 +392,7 @@ def convert_to_vlm_format(
 
     total = len(dataset)
     first_image = next(iter(dataset))[image_column]
-    has_urls = isinstance(first_image, str) and first_image.startswith(
-        ("http://", "https://")
-    )
+    has_urls = isinstance(first_image, str) and first_image.startswith(("http://", "https://"))
 
     # ── Bare-filename detection: images stored as filenames (e.g. "img_001.png")
     #    that don't exist locally.  Build a basename→repo_path lookup so we can
@@ -449,9 +442,7 @@ def convert_to_vlm_format(
 
         num_workers = safe_thread_num_proc()
         _notify(f"Probing {PROBE_SIZE} image URLs with {num_workers} workers...")
-        logger.info(
-            f"🔍 Probing {PROBE_SIZE}/{total} image URLs with {num_workers} workers..."
-        )
+        logger.info(f"🔍 Probing {PROBE_SIZE}/{total} image URLs with {num_workers} workers...")
 
         probe_samples = [dataset[i] for i in range(PROBE_SIZE)]
         probe_ok = 0
@@ -459,9 +450,7 @@ def convert_to_vlm_format(
         probe_start = time.time()
 
         with ThreadPoolExecutor(max_workers = num_workers) as executor:
-            futures = {
-                executor.submit(_convert_single_sample, s): s for s in probe_samples
-            }
+            futures = {executor.submit(_convert_single_sample, s): s for s in probe_samples}
             for future in as_completed(futures):
                 try:
                     future.result()
@@ -483,7 +472,6 @@ def convert_to_vlm_format(
             friendly = None
             try:
                 from .llm_assist import llm_generate_dataset_warning
-
                 friendly = llm_generate_dataset_warning(
                     issues,
                     dataset_name = dataset_name,
@@ -554,9 +542,7 @@ def convert_to_vlm_format(
                     except Exception as e:
                         failed_count += 1
                         if failed_count == 1:
-                            logger.info(
-                                f"First VLM conversion failure: {type(e).__name__}: {e}"
-                            )
+                            logger.info(f"First VLM conversion failure: {type(e).__name__}: {e}")
 
             converted_list.extend(r for r in batch_results if r is not None)
 
@@ -581,9 +567,7 @@ def convert_to_vlm_format(
                 failed_count += 1
                 if failed_count == 1:
                     # Log the first failure to aid debugging
-                    logger.info(
-                        f"First VLM conversion failure: {type(e).__name__}: {e}"
-                    )
+                    logger.info(f"First VLM conversion failure: {type(e).__name__}: {e}")
             pbar.set_postfix(ok = len(converted_list), failed = failed_count, refresh = False)
         pbar.close()
 
@@ -601,7 +585,6 @@ def convert_to_vlm_format(
             friendly = None
             try:
                 from .llm_assist import llm_generate_dataset_warning
-
                 friendly = llm_generate_dataset_warning(
                     issues,
                     dataset_name = dataset_name,
@@ -627,7 +610,6 @@ def convert_to_vlm_format(
         friendly = None
         try:
             from .llm_assist import llm_generate_dataset_warning
-
             friendly = llm_generate_dataset_warning(
                 issues,
                 dataset_name = dataset_name,
@@ -739,12 +721,10 @@ def convert_sharegpt_with_images_to_vlm_format(
             if image_data.startswith(("http://", "https://")):
                 import fsspec
                 from io import BytesIO
-
                 with fsspec.open(image_data, "rb", expand = True) as f:
                     return Image.open(BytesIO(f.read())).convert("RGB")
             elif _image_lookup is not None and image_data in _image_lookup:
                 from huggingface_hub import hf_hub_download
-
                 local_path = hf_hub_download(
                     dataset_name,
                     _image_lookup[image_data],
@@ -753,12 +733,9 @@ def convert_sharegpt_with_images_to_vlm_format(
                 return Image.open(local_path).convert("RGB")
             else:
                 return Image.open(image_data).convert("RGB")
-        if isinstance(image_data, dict) and (
-            "bytes" in image_data or "path" in image_data
-        ):
+        if isinstance(image_data, dict) and ("bytes" in image_data or "path" in image_data):
             if image_data.get("bytes"):
                 from io import BytesIO
-
                 return Image.open(BytesIO(image_data["bytes"])).convert("RGB")
             if image_data.get("path"):
                 return Image.open(image_data["path"]).convert("RGB")
@@ -812,9 +789,7 @@ def convert_sharegpt_with_images_to_vlm_format(
     pbar.close()
 
     if failed_count > 0:
-        logger.info(
-            f"⚠️ Skipped {failed_count}/{total} ({failed_count*100//total}%) samples"
-        )
+        logger.info(f"⚠️ Skipped {failed_count}/{total} ({failed_count*100//total}%) samples")
 
     if len(converted_list) == 0:
         raise ValueError(
@@ -840,9 +815,7 @@ def convert_llava_to_vlm_format(dataset):
     """
     from PIL import Image
 
-    logger.info(
-        f"🔄 Converting {len(dataset)} samples from Llava format to standard VLM format..."
-    )
+    logger.info(f"🔄 Converting {len(dataset)} samples from Llava format to standard VLM format...")
 
     def _convert_single_sample(sample):
         """Convert a single llava sample to standard VLM format."""
diff --git a/studio/backend/utils/datasets/format_detection.py b/studio/backend/utils/datasets/format_detection.py
index 7b70ff3a76..829838064a 100644
--- a/studio/backend/utils/datasets/format_detection.py
+++ b/studio/backend/utils/datasets/format_detection.py
@@ -13,10 +13,7 @@ import re
 
 def _keyword_in_column(keyword: str, col_name: str) -> bool:
     """Word-boundary keyword match to avoid false positives like 'pic' in 'topic'."""
-    return (
-        re.search(r"\b" + re.escape(keyword) + r"\b", col_name, re.IGNORECASE)
-        is not None
-    )
+    return re.search(r"\b" + re.escape(keyword) + r"\b", col_name, re.IGNORECASE) is not None
 
 
 def detect_dataset_format(dataset):
@@ -220,10 +217,7 @@ def detect_custom_format_heuristic(dataset):
             return True
 
         for pattern in metadata_prefix_patterns:
-            if (
-                col_lower.startswith(pattern.split("_")[0] + "_")
-                and col_lower != pattern
-            ):
+            if col_lower.startswith(pattern.split("_")[0] + "_") and col_lower != pattern:
                 if "_" in col_lower:
                     prefix = col_lower.split("_")[0]
                     if prefix in ["generation", "pass", "inference"]:
@@ -267,9 +261,7 @@ def detect_custom_format_heuristic(dataset):
         if role_type == "user":
             col_lower = col_name.lower()
             # If column is ONLY "task" (or task_xxx), give it lower priority for user role
-            if "task" in col_lower and not any(
-                kw in col_lower for kw in user_words_high_priority
-            ):
+            if "task" in col_lower and not any(kw in col_lower for kw in user_words_high_priority):
                 score -= 15  # Significant penalty so other user columns win
 
         priority_bonus = get_priority_score(col_name)
@@ -301,17 +293,13 @@ def detect_custom_format_heuristic(dataset):
     content_columns = [col for col in all_columns if not is_metadata(col)]
 
     # Count candidates first
-    assistant_potential = [
-        col for col in content_columns if has_keyword(col, assistant_words)
-    ]
+    assistant_potential = [col for col in content_columns if has_keyword(col, assistant_words)]
     user_potential = [col for col in content_columns if has_keyword(col, user_words)]
 
     # STEP 1: Find best ASSISTANT column
     assistant_candidates = []
     for col in assistant_potential:
-        score = score_column(
-            col, assistant_words, "assistant", len(assistant_potential)
-        )
+        score = score_column(col, assistant_words, "assistant", len(assistant_potential))
         if score > 0:
             assistant_candidates.append((col, score))
 
@@ -518,7 +506,6 @@ def _is_image_value(value) -> bool:
     # PIL Image instance
     try:
         from PIL.Image import Image as PILImage
-
         if isinstance(value, PILImage):
             return True
     except ImportError:
@@ -647,9 +634,7 @@ def detect_vlm_dataset_structure(dataset):
                     if isinstance(content[0], dict) and "type" in content[0]:
                         # Check for llava format
                         has_index = any(
-                            "index" in item
-                            for item in content
-                            if isinstance(item, dict)
+                            "index" in item for item in content if isinstance(item, dict)
                         )
                         has_images_column = "images" in column_names
 
@@ -664,9 +649,7 @@ def detect_vlm_dataset_structure(dataset):
 
                         # Standard VLM format
                         has_image = any(
-                            "image" in item
-                            for item in content
-                            if isinstance(item, dict)
+                            "image" in item for item in content if isinstance(item, dict)
                         )
                         if has_image:
                             return {
@@ -777,9 +760,7 @@ def detect_vlm_dataset_structure(dataset):
             return True
 
         # Check prefixes
-        if any(
-            col_lower.startswith(prefix) for prefix in metadata_patterns["prefixes"]
-        ):
+        if any(col_lower.startswith(prefix) for prefix in metadata_patterns["prefixes"]):
             return True
 
         return False
@@ -791,9 +772,7 @@ def detect_vlm_dataset_structure(dataset):
             return 100
 
         # Dict with image data (bytes/path from HF Image feature)
-        if isinstance(sample_value, dict) and (
-            "bytes" in sample_value or "path" in sample_value
-        ):
+        if isinstance(sample_value, dict) and ("bytes" in sample_value or "path" in sample_value):
             return 75
 
         if isinstance(sample_value, str):
@@ -818,9 +797,7 @@ def detect_vlm_dataset_structure(dataset):
 
         # Local file — check it exists
         if not sample_value.startswith(("http://", "https://")):
-            return os.path.exists(
-                sample_value
-            )  # bare filenames return False here, that's OK
+            return os.path.exists(sample_value)  # bare filenames return False here, that's OK
 
         # URL — quick HEAD request with short timeout
         try:
diff --git a/studio/backend/utils/datasets/llm_assist.py b/studio/backend/utils/datasets/llm_assist.py
index 758717f76b..10004ce3db 100644
--- a/studio/backend/utils/datasets/llm_assist.py
+++ b/studio/backend/utils/datasets/llm_assist.py
@@ -68,9 +68,7 @@ def precache_helper_gguf():
         return
 
     repo = os.environ.get("UNSLOTH_HELPER_MODEL_REPO", DEFAULT_HELPER_MODEL_REPO)
-    variant = os.environ.get(
-        "UNSLOTH_HELPER_MODEL_VARIANT", DEFAULT_HELPER_MODEL_VARIANT
-    )
+    variant = os.environ.get("UNSLOTH_HELPER_MODEL_VARIANT", DEFAULT_HELPER_MODEL_VARIANT)
 
     try:
         from huggingface_hub import HfApi, hf_hub_download
@@ -86,9 +84,7 @@ def precache_helper_gguf():
 
         # Find all GGUF files matching the variant (may be split into shards)
         variant_lower = variant.lower().replace("-", "_")
-        matching = sorted(
-            f for f in gguf_files if variant_lower in f.lower().replace("-", "_")
-        )
+        matching = sorted(f for f in gguf_files if variant_lower in f.lower().replace("-", "_"))
 
         if matching:
             logger.info(
@@ -119,9 +115,7 @@ def _run_with_helper(prompt: str, max_tokens: int = 256) -> Optional[str]:
         return None
 
     repo = os.environ.get("UNSLOTH_HELPER_MODEL_REPO", DEFAULT_HELPER_MODEL_REPO)
-    variant = os.environ.get(
-        "UNSLOTH_HELPER_MODEL_VARIANT", DEFAULT_HELPER_MODEL_VARIANT
-    )
+    variant = os.environ.get("UNSLOTH_HELPER_MODEL_VARIANT", DEFAULT_HELPER_MODEL_VARIANT)
 
     backend = None
     try:
@@ -143,9 +137,7 @@ def _run_with_helper(prompt: str, max_tokens: int = 256) -> Optional[str]:
             return None
 
         messages = [{"role": "user", "content": prompt}]
-        logger.info(
-            "Helper model request: enable_thinking=False (per-request override)"
-        )
+        logger.info("Helper model request: enable_thinking=False (per-request override)")
         cumulative = ""
         for chunk in backend.generate_chat_completion(
             messages = messages,
@@ -240,10 +232,7 @@ def llm_generate_vlm_instruction(
     }
 
 
-def llm_classify_columns(
-    column_names: list[str],
-    samples: list[dict],
-) -> Optional[dict[str, str]]:
+def llm_classify_columns(column_names: list[str], samples: list[dict]) -> Optional[dict[str, str]]:
     """
     Ask a helper LLM to classify dataset columns into roles.
 
@@ -294,7 +283,6 @@ def llm_classify_columns(
     except json.JSONDecodeError:
         # Try to find JSON object in the response
         import re
-
         match = re.search(r"\{[^}]+\}", text)
         if match:
             try:
@@ -313,11 +301,7 @@ def llm_classify_columns(
     valid_roles = {"user", "assistant", "system", "metadata"}
     cleaned = {}
     for col, role in mapping.items():
-        if (
-            col in column_names
-            and isinstance(role, str)
-            and role.lower() in valid_roles
-        ):
+        if col in column_names and isinstance(role, str) and role.lower() in valid_roles:
             cleaned[col] = role.lower()
 
     if not cleaned:
@@ -420,7 +404,11 @@ def _parse_json_response(text: str) -> Optional[dict]:
     return None
 
 
-def _generate_with_backend(backend, messages: list[dict], max_tokens: int = 512) -> str:
+def _generate_with_backend(
+    backend,
+    messages: list[dict],
+    max_tokens: int = 512,
+) -> str:
     """Run one chat completion on an already-loaded backend. Returns raw text."""
     logger.info("Advisor request: enable_thinking=False (per-request override)")
     cumulative = ""
@@ -480,9 +468,7 @@ def fetch_hf_dataset_card(
                 if val is not None:
                     metadata[key] = val
 
-        logger.info(
-            f"Fetched dataset card: {len(readme)} chars, {len(metadata)} metadata fields"
-        )
+        logger.info(f"Fetched dataset card: {len(readme)} chars, {len(metadata)} metadata fields")
         return readme, metadata
 
     except Exception as e:
@@ -509,9 +495,7 @@ def _run_multi_pass_advisor(
         return None
 
     repo = os.environ.get("UNSLOTH_HELPER_MODEL_REPO", DEFAULT_HELPER_MODEL_REPO)
-    variant = os.environ.get(
-        "UNSLOTH_HELPER_MODEL_VARIANT", DEFAULT_HELPER_MODEL_VARIANT
-    )
+    variant = os.environ.get("UNSLOTH_HELPER_MODEL_VARIANT", DEFAULT_HELPER_MODEL_VARIANT)
 
     backend = None
     try:
@@ -541,9 +525,7 @@ def _run_multi_pass_advisor(
             samples_text += f"Row {i}:\n" + "\n".join(parts) + "\n"
 
         metadata_str = (
-            json.dumps(dataset_metadata, indent = 2, default = str)[:500]
-            if dataset_metadata
-            else "N/A"
+            json.dumps(dataset_metadata, indent = 2, default = str)[:500] if dataset_metadata else "N/A"
         )
         card_excerpt = (dataset_card or "")[:1200] or "N/A"
 
@@ -745,9 +727,7 @@ def _run_multi_pass_advisor(
         # Validate: must have at least one user AND one assistant
         roles_present = set(column_roles.values())
         if "user" not in roles_present or "assistant" not in roles_present:
-            logger.warning(
-                f"Pass 2 sanity fail: missing user or assistant role: {column_roles}"
-            )
+            logger.warning(f"Pass 2 sanity fail: missing user or assistant role: {column_roles}")
             return None  # triggers fallback to simple classification
 
         # ── Pass 3: System prompt (non-conversational datasets only) ──
diff --git a/studio/backend/utils/datasets/raw_text.py b/studio/backend/utils/datasets/raw_text.py
index 353145fd5a..86b1963fc1 100644
--- a/studio/backend/utils/datasets/raw_text.py
+++ b/studio/backend/utils/datasets/raw_text.py
@@ -40,10 +40,7 @@ def _split_scope(split_name: str | None) -> str:
 
 
 def _drop_invalid_text_rows(
-    dataset: Dataset,
-    *,
-    mode_title: str,
-    split_scope: str,
+    dataset: Dataset, *, mode_title: str, split_scope: str
 ) -> tuple[Dataset, list[RawTextNotice]]:
     filtered_dataset = dataset.filter(lambda ex: isinstance(ex["text"], str))
     dropped_rows = len(dataset) - len(filtered_dataset)
@@ -105,8 +102,7 @@ def prepare_raw_text_dataset(
         notices.append(
             RawTextNotice(
                 message = (
-                    f"{mode_title}: renaming column '{renamed_col}' -> 'text' "
-                    f"for {split_scope}"
+                    f"{mode_title}: renaming column '{renamed_col}' -> 'text' " f"for {split_scope}"
                 ),
                 level = "info",
             )
diff --git a/studio/backend/utils/datasets/vlm_processing.py b/studio/backend/utils/datasets/vlm_processing.py
index 7b63152ede..a0f1fd9f99 100644
--- a/studio/backend/utils/datasets/vlm_processing.py
+++ b/studio/backend/utils/datasets/vlm_processing.py
@@ -66,9 +66,7 @@ def generate_smart_vlm_instruction(
         # OCR / Transcription
         "ocr": {
             "keywords": ["ocr", "transcribe", "transcript"],
-            "content_hints": [
-                r"[A-Za-z\u0600-\u06FF]{10,}"
-            ],  # Long text passages (Latin/Arabic)
+            "content_hints": [r"[A-Za-z\u0600-\u06FF]{10,}"],  # Long text passages (Latin/Arabic)
             "instruction": "Transcribe all the text shown in this image.",
             "confidence": 0.9,
         },
@@ -220,7 +218,6 @@ def generate_smart_vlm_instruction(
             }
     except Exception as e:
         import logging
-
         logging.getLogger(__name__).debug(f"LLM-assisted instruction skipped: {e}")
 
     # ===== LEVEL 5: Generic Fallback =====
diff --git a/studio/backend/utils/downsample.py b/studio/backend/utils/downsample.py
index bccf6a23b7..2d340ca248 100644
--- a/studio/backend/utils/downsample.py
+++ b/studio/backend/utils/downsample.py
@@ -12,7 +12,5 @@ def downsample(values: list[float], target_count: int) -> list[float]:
         return []
     if target_count == 1:
         return [values[-1]]
-    indices = [
-        round(i * (len(values) - 1) / (target_count - 1)) for i in range(target_count)
-    ]
+    indices = [round(i * (len(values) - 1) / (target_count - 1)) for i in range(target_count)]
     return [values[i] for i in indices]
diff --git a/studio/backend/utils/hardware/amd.py b/studio/backend/utils/hardware/amd.py
index 48d5890399..04b9494a29 100644
--- a/studio/backend/utils/hardware/amd.py
+++ b/studio/backend/utils/hardware/amd.py
@@ -160,9 +160,7 @@ def _extract_gpu_metrics(gpu_data: dict) -> dict[str, Any]:
     # amd-smi metric output structure varies by version; try common paths
     usage = gpu_data.get("usage", gpu_data.get("gpu_activity", {}))
     if isinstance(usage, dict):
-        gpu_util = _parse_numeric(
-            usage.get("gfx_activity", usage.get("gpu_use_percent"))
-        )
+        gpu_util = _parse_numeric(usage.get("gfx_activity", usage.get("gpu_use_percent")))
     else:
         gpu_util = _parse_numeric(usage)
 
@@ -188,9 +186,7 @@ def _extract_gpu_metrics(gpu_data: dict) -> dict[str, Any]:
                 power_data.get("average_socket_power", power_data.get("socket_power")),
             )
         )
-        power_limit = _parse_numeric(
-            power_data.get("power_cap", power_data.get("max_power_limit"))
-        )
+        power_limit = _parse_numeric(power_data.get("power_cap", power_data.get("max_power_limit")))
     else:
         power_draw = None
         power_limit = None
@@ -205,14 +201,10 @@ def _extract_gpu_metrics(gpu_data: dict) -> dict[str, Any]:
     )
     if isinstance(vram_data, dict):
         vram_used_mb = _parse_memory_mb(
-            vram_data.get(
-                "used_vram", vram_data.get("vram_used", vram_data.get("used"))
-            )
+            vram_data.get("used_vram", vram_data.get("vram_used", vram_data.get("used")))
         )
         vram_total_mb = _parse_memory_mb(
-            vram_data.get(
-                "total_vram", vram_data.get("vram_total", vram_data.get("total"))
-            )
+            vram_data.get("total_vram", vram_data.get("vram_total", vram_data.get("total")))
         )
     else:
         vram_used_mb = None
@@ -220,9 +212,7 @@ def _extract_gpu_metrics(gpu_data: dict) -> dict[str, Any]:
 
     # Build the standardized dict (same shape as nvidia._build_gpu_metrics)
     vram_used_gb = round(vram_used_mb / 1024, 2) if vram_used_mb is not None else None
-    vram_total_gb = (
-        round(vram_total_mb / 1024, 2) if vram_total_mb is not None else None
-    )
+    vram_total_gb = round(vram_total_mb / 1024, 2) if vram_total_mb is not None else None
     vram_util = (
         round((vram_used_mb / vram_total_mb) * 100, 1)
         if vram_used_mb is not None and vram_total_mb is not None and vram_total_mb > 0
@@ -340,8 +330,7 @@ def get_primary_gpu_utilization() -> dict[str, Any]:
 
 
 def get_visible_gpu_utilization(
-    parent_visible_ids: Optional[list[int]],
-    parent_cuda_visible_devices: Optional[str] = None,
+    parent_visible_ids: Optional[list[int]], parent_cuda_visible_devices: Optional[str] = None
 ) -> dict[str, Any]:
     """Return utilization metrics for visible AMD GPUs."""
     if parent_visible_ids is None:
@@ -391,14 +380,11 @@ def get_visible_gpu_utilization(
         # "unit": "none"}``, so route raw_id through ``_parse_numeric``
         # which already handles bare ints, floats, strings, and that
         # dict shape uniformly.
-        raw_id = gpu_data.get(
-            "gpu", gpu_data.get("gpu_id", gpu_data.get("id", fallback_idx))
-        )
+        raw_id = gpu_data.get("gpu", gpu_data.get("gpu_id", gpu_data.get("id", fallback_idx)))
         parsed_id = _parse_numeric(raw_id)
         if parsed_id is None:
             logger.warning(
-                "amd-smi GPU id %r could not be parsed; falling back to "
-                "enumeration index %d",
+                "amd-smi GPU id %r could not be parsed; falling back to enumeration index %d",
                 raw_id,
                 fallback_idx,
             )
diff --git a/studio/backend/utils/hardware/hardware.py b/studio/backend/utils/hardware/hardware.py
index 180fde8f13..3f2823302a 100644
--- a/studio/backend/utils/hardware/hardware.py
+++ b/studio/backend/utils/hardware/hardware.py
@@ -51,9 +51,7 @@ class DeviceType(str, Enum):
 
 DEVICE: Optional[DeviceType] = None
 CHAT_ONLY: bool = True  # No CUDA GPU -> GGUF chat only (Mac, CPU-only, etc.)
-IS_ROCM: bool = (
-    False  # True when running on AMD ROCm (HIP) -- routes GPU monitoring to amd.py
-)
+IS_ROCM: bool = False  # True when running on AMD ROCm (HIP) -- routes GPU monitoring to amd.py
 
 
 def _backend_label(device: DeviceType) -> str:
@@ -85,7 +83,6 @@ def _has_torch() -> bool:
     """Check if PyTorch is importable."""
     try:
         import torch
-
         return True
     except ImportError:
         return False
@@ -95,7 +92,6 @@ def _has_mlx() -> bool:
     """Check if MLX is importable."""
     try:
         import mlx.core
-
         return True
     except ImportError:
         return False
@@ -120,7 +116,6 @@ def detect_hardware() -> DeviceType:
     # --- CUDA / ROCm: try PyTorch ---
     if _has_torch():
         import torch
-
         if torch.cuda.is_available():
             DEVICE = DeviceType.CUDA
             CHAT_ONLY = False
@@ -142,7 +137,6 @@ def detect_hardware() -> DeviceType:
     # --- XPU: Intel GPU ---
     if _has_torch():
         import torch
-
         if hasattr(torch, "xpu") and torch.xpu.is_available():
             DEVICE = DeviceType.XPU
             CHAT_ONLY = False
@@ -198,7 +192,6 @@ def clear_gpu_cache():
         torch.cuda.ipc_collect()
     elif device == DeviceType.XPU:
         import torch
-
         torch.xpu.synchronize()
         torch.xpu.empty_cache()
     elif device == DeviceType.MLX:
@@ -379,7 +372,6 @@ def get_package_versions() -> Dict[str, Optional[str]]:
     # GPU runtime version bundled with torch
     try:
         import torch
-
         versions["cuda"] = getattr(torch.version, "cuda", None)
         versions["rocm"] = getattr(torch.version, "hip", None)
     except Exception:
@@ -646,9 +638,7 @@ def get_gpu_utilization() -> Dict[str, Any]:
             result["backend"] = _backend_label(device)
             if IS_ROCM:
                 # Fix unified-memory VRAM on AMD iGPUs (Strix Halo etc.)
-                _reconcile_primary_rocm_unified_memory(
-                    result, _get_parent_visible_gpu_spec()
-                )
+                _reconcile_primary_rocm_unified_memory(result, _get_parent_visible_gpu_spec())
             return result
         # SMI tool unavailable or returned no usable data. On Windows, query
         # the Performance Counter API (same source as Task Manager) for
@@ -709,9 +699,7 @@ def get_gpu_utilization() -> Dict[str, Any]:
                 "temperature_c": None,
                 "vram_used_gb": _used,
                 "vram_total_gb": _total,
-                "vram_utilization_pct": round((_used / _total) * 100, 1)
-                if _total > 0
-                else None,
+                "vram_utilization_pct": round((_used / _total) * 100, 1) if _total > 0 else None,
                 "power_draw_w": None,
                 "power_limit_w": None,
                 "power_utilization_pct": None,
@@ -722,7 +710,6 @@ def get_gpu_utilization() -> Dict[str, Any]:
     if device == DeviceType.MLX:
         try:
             import psutil
-
             agx = _read_apple_gpu_stats()
             total_bytes = psutil.virtual_memory().total
         except Exception as e:
@@ -795,9 +782,7 @@ def _apply_unified_memory_correction(
         device_metrics["vram_total_gb"] = torch_total_gb
         device_metrics["vram_used_gb"] = torch_used_gb
         device_metrics["vram_utilization_pct"] = (
-            round((torch_used_gb / torch_total_gb) * 100, 1)
-            if torch_total_gb > 0
-            else None
+            round((torch_used_gb / torch_total_gb) * 100, 1) if torch_total_gb > 0 else None
         )
         logger.debug(
             "ROCm unified memory: replaced amd-smi VRAM (%.2f GB) with "
@@ -808,9 +793,7 @@ def _apply_unified_memory_correction(
         )
 
 
-def _reconcile_rocm_unified_memory(
-    utilization: Dict[str, Any], device_indices: list[int]
-) -> None:
+def _reconcile_rocm_unified_memory(utilization: Dict[str, Any], device_indices: list[int]) -> None:
     """Fix amd-smi VRAM for ROCm unified-memory GPUs (e.g. Strix Halo).
 
     amd-smi reports only the dedicated slice (~512 MB); torch sees the full
@@ -969,9 +952,7 @@ def _get_parent_visible_gpu_spec() -> Dict[str, Any]:
     # stale HIP_VISIBLE_DEVICES on an NVIDIA host can't override CUDA_VISIBLE_DEVICES.
     _is_rocm_spec = IS_ROCM or (
         "CUDA_VISIBLE_DEVICES" not in os.environ
-        and (
-            "HIP_VISIBLE_DEVICES" in os.environ or "ROCR_VISIBLE_DEVICES" in os.environ
-        )
+        and ("HIP_VISIBLE_DEVICES" in os.environ or "ROCR_VISIBLE_DEVICES" in os.environ)
     )
     if _is_rocm_spec:
         hip_vis = os.environ.get("HIP_VISIBLE_DEVICES")
@@ -1064,9 +1045,7 @@ def resolve_requested_gpu_ids(gpu_ids: Optional[list[int]]) -> list[int]:
         max_parent_id = max(parent_visible_ids)
         if physical_gpu_count > max_parent_id:
             # Count is plausibly physical (not just visible), so enforce it
-            out_of_range = [
-                gpu_id for gpu_id in requested_ids if gpu_id >= physical_gpu_count
-            ]
+            out_of_range = [gpu_id for gpu_id in requested_ids if gpu_id >= physical_gpu_count]
             if out_of_range:
                 raise ValueError(
                     f"Invalid gpu_ids {requested_ids}: IDs must be physical GPU IDs "
@@ -1074,9 +1053,7 @@ def resolve_requested_gpu_ids(gpu_ids: Optional[list[int]]) -> list[int]:
                     f"Rejected IDs: {out_of_range}. Parent-visible GPUs: {parent_visible_ids}"
                 )
 
-    disallowed_ids = [
-        gpu_id for gpu_id in requested_ids if gpu_id not in parent_visible_ids
-    ]
+    disallowed_ids = [gpu_id for gpu_id in requested_ids if gpu_id not in parent_visible_ids]
     if disallowed_ids:
         raise ValueError(
             f"Invalid gpu_ids {requested_ids}: requested GPUs {disallowed_ids} are "
@@ -1097,9 +1074,7 @@ def _resolve_model_identifier_for_gpu_estimate(
             return config.base_model
         return config.identifier if config else model_name
     except Exception as e:
-        logger.debug(
-            "Could not resolve base model for GPU estimate '%s': %s", model_name, e
-        )
+        logger.debug("Could not resolve base model for GPU estimate '%s': %s", model_name, e)
         return model_name
 
 
@@ -1136,7 +1111,6 @@ def _get_hf_safetensors_total_params(
 def _load_config_for_gpu_estimate(model_name: str, hf_token: Optional[str] = None):
     try:
         from transformers import AutoConfig
-
         trust_remote_code = model_name.lower().startswith("unsloth/")
         return AutoConfig.from_pretrained(
             model_name,
@@ -1188,7 +1162,6 @@ def _determine_attention_impl_for_gpu_estimate(config) -> str:
 
     try:
         import torch.distributed as _td
-
         for _attr, _stub in (
             ("is_initialized", lambda: False),
             ("is_available", lambda: False),
@@ -1251,17 +1224,15 @@ def _estimate_fp16_model_size_bytes_from_vllm_utils(config) -> Optional[int]:
                 synthetic_total_bytes,
                 synthetic_total_bytes,
             )
-            _, _, _, memory_left_for_kv_cache_gb = (
-                _vllm_utils.approximate_vllm_memory_usage(
-                    config,
-                    load_in_4bit = False,
-                    load_in_8bit = False,
-                    max_seq_length = 1,
-                    gpu_memory_utilization = 1.0,
-                    enable_lora = False,
-                    account_for_gradients = False,
-                    cuda_graph_overhead = False,
-                )
+            _, _, _, memory_left_for_kv_cache_gb = _vllm_utils.approximate_vllm_memory_usage(
+                config,
+                load_in_4bit = False,
+                load_in_8bit = False,
+                max_seq_length = 1,
+                gpu_memory_utilization = 1.0,
+                enable_lora = False,
+                account_for_gradients = False,
+                cuda_graph_overhead = False,
             )
         finally:
             _vllm_utils.get_mem_info = original_get_mem_info
@@ -1283,15 +1254,11 @@ def _estimate_fp16_model_size_bytes_from_vllm_utils(config) -> Optional[int]:
 def estimate_fp16_model_size_bytes(
     model_name: str, hf_token: Optional[str] = None
 ) -> tuple[Optional[int], str]:
-    estimate_model = _resolve_model_identifier_for_gpu_estimate(
-        model_name, hf_token = hf_token
-    )
+    estimate_model = _resolve_model_identifier_for_gpu_estimate(model_name, hf_token = hf_token)
 
     total_params = None
     if "/" in estimate_model and not Path(estimate_model).exists():
-        total_params = _get_hf_safetensors_total_params(
-            estimate_model, hf_token = hf_token
-        )
+        total_params = _get_hf_safetensors_total_params(estimate_model, hf_token = hf_token)
     if total_params:
         return int(total_params * 2), "safetensors"
 
@@ -1346,9 +1313,7 @@ def estimate_required_model_memory_gb(
         DEFAULT_TARGET_MODULES,
     )
 
-    model_size_bytes, source = estimate_fp16_model_size_bytes(
-        model_name, hf_token = hf_token
-    )
+    model_size_bytes, source = estimate_fp16_model_size_bytes(model_name, hf_token = hf_token)
     metadata: Dict[str, Any] = {
         "mode": "inference" if training_type is None else "training",
         "model_size_source": source,
@@ -1371,9 +1336,7 @@ def estimate_required_model_memory_gb(
         return required_gb, metadata
 
     training_method = (
-        "full"
-        if training_type == "Full Finetuning"
-        else ("qlora" if load_in_4bit else "lora")
+        "full" if training_type == "Full Finetuning" else ("qlora" if load_in_4bit else "lora")
     )
     vram_config = TrainingVramConfig(
         training_method = training_method,
@@ -1386,14 +1349,12 @@ def estimate_required_model_memory_gb(
         load_in_4bit = load_in_4bit,
     )
 
-    estimate_model = _resolve_model_identifier_for_gpu_estimate(
-        model_name, hf_token = hf_token
-    )
+    estimate_model = _resolve_model_identifier_for_gpu_estimate(model_name, hf_token = hf_token)
     config = _load_config_for_gpu_estimate(estimate_model, hf_token = hf_token)
     if config is not None:
         try:
-            vram_config.attention_implementation = (
-                _determine_attention_impl_for_gpu_estimate(config)
+            vram_config.attention_implementation = _determine_attention_impl_for_gpu_estimate(
+                config
             )
         except Exception as e:
             # Log at debug: on Windows ROCm the torch.distributed stub does
@@ -1587,9 +1548,7 @@ def auto_select_gpu_ids(
             return selected, metadata
 
     # Use only GPUs with verified VRAM data (from gpu_candidates, not raw devices)
-    fallback_all = (
-        [c["index"] for c in gpu_candidates] if gpu_candidates else parent_ids
-    )
+    fallback_all = [c["index"] for c in gpu_candidates] if gpu_candidates else parent_ids
     metadata["selection_mode"] = "fallback_all"
     if ranked:
         fallback_usable = ranked[0]["free_gb"] + sum(
@@ -1853,7 +1812,6 @@ def get_visible_gpu_count() -> int:
     # No visibility env var set -- try torch, fall back to physical count
     try:
         import torch
-
         if get_device() == DeviceType.XPU and hasattr(torch, "xpu"):
             _visible_gpu_count = torch.xpu.device_count()
         else:
@@ -1902,7 +1860,6 @@ def apply_gpu_ids(gpu_ids) -> None:
         # Broad except: a probe failure must never crash a training worker.
         try:
             import torch as _torch
-
             _is_rocm = (
                 getattr(_torch.version, "hip", None) is not None
                 or "rocm" in getattr(_torch, "__version__", "").lower()
@@ -1923,9 +1880,7 @@ def apply_gpu_ids(gpu_ids) -> None:
         logger.info("Applied gpu_ids: CUDA_VISIBLE_DEVICES='%s'", value)
 
 
-def get_device_map(
-    gpu_ids: Optional[list[int]] = None,
-) -> str:
+def get_device_map(gpu_ids: Optional[list[int]] = None) -> str:
     """Return the Hugging Face ``device_map`` string for model loading.
 
     Returns ``"balanced"`` (shard evenly across GPUs) when:
@@ -1949,10 +1904,7 @@ def get_device_map(
             # UUID/MIG masks cannot be split into numeric IDs, so if multiple
             # GPUs are visible we assume multi-GPU sharding is intended.
             parent_visible_spec = _get_parent_visible_gpu_spec()
-            if (
-                parent_visible_spec["numeric_ids"] is None
-                and get_visible_gpu_count() > 1
-            ):
+            if parent_visible_spec["numeric_ids"] is None and get_visible_gpu_count() > 1:
                 multi_gpu = True
 
         if multi_gpu:
@@ -1972,14 +1924,16 @@ def get_offloaded_device_map_entries(model) -> dict[str, str]:
     }
 
 
-def raise_if_offloaded(model, device_map: str, context: str = "Loading") -> None:
+def raise_if_offloaded(
+    model,
+    device_map: str,
+    context: str = "Loading",
+) -> None:
     """Raise ``ValueError`` if *model* has modules offloaded to CPU or disk."""
     offloaded = get_offloaded_device_map_entries(model)
     if not offloaded:
         return
-    example = ", ".join(
-        f"{name}={placement}" for name, placement in list(offloaded.items())[:5]
-    )
+    example = ", ".join(f"{name}={placement}" for name, placement in list(offloaded.items())[:5])
     raise ValueError(
         f"{context} does not support models loaded with CPU or disk offload. "
         f"device_map='{device_map}' produced offloaded modules: {example}"
diff --git a/studio/backend/utils/hardware/nvidia.py b/studio/backend/utils/hardware/nvidia.py
index 099c5fa3a5..6cead61f08 100644
--- a/studio/backend/utils/hardware/nvidia.py
+++ b/studio/backend/utils/hardware/nvidia.py
@@ -25,20 +25,12 @@ def _parse_smi_value(raw: str):
 
 
 def _build_gpu_metrics(
-    vram_used_mb,
-    vram_total_mb,
-    power_draw,
-    power_limit,
-    **extra,
+    vram_used_mb, vram_total_mb, power_draw, power_limit, **extra
 ) -> dict[str, Any]:
     return {
         **extra,
-        "vram_used_gb": round(vram_used_mb / 1024, 2)
-        if vram_used_mb is not None
-        else None,
-        "vram_total_gb": round(vram_total_mb / 1024, 2)
-        if vram_total_mb is not None
-        else None,
+        "vram_used_gb": round(vram_used_mb / 1024, 2) if vram_used_mb is not None else None,
+        "vram_total_gb": round(vram_total_mb / 1024, 2) if vram_total_mb is not None else None,
         "vram_utilization_pct": round((vram_used_mb / vram_total_mb) * 100, 1)
         if vram_used_mb is not None and vram_total_mb and vram_total_mb > 0
         else None,
@@ -50,9 +42,7 @@ def _build_gpu_metrics(
     }
 
 
-def _visible_ordinal_map(
-    parent_visible_ids: Optional[list[int]],
-) -> Optional[dict[int, int]]:
+def _visible_ordinal_map(parent_visible_ids: Optional[list[int]]) -> Optional[dict[int, int]]:
     if parent_visible_ids is None:
         return None
     return {gpu_id: ordinal for ordinal, gpu_id in enumerate(parent_visible_ids)}
@@ -118,8 +108,7 @@ def get_primary_gpu_utilization() -> dict[str, Any]:
 
 
 def get_visible_gpu_utilization(
-    parent_visible_ids: Optional[list[int]],
-    parent_cuda_visible_devices: Optional[str] = None,
+    parent_visible_ids: Optional[list[int]], parent_cuda_visible_devices: Optional[str] = None
 ) -> dict[str, Any]:
     # When parent_visible_ids is None (UUID/MIG mask), we cannot safely
     # map nvidia-smi rows to the process's visible devices. Return empty
@@ -188,9 +177,7 @@ def get_visible_gpu_utilization(
                 index = idx,
                 index_kind = "physical",
                 visible_ordinal = (
-                    visible_ordinals[idx]
-                    if visible_ordinals is not None
-                    else len(devices)
+                    visible_ordinals[idx] if visible_ordinals is not None else len(devices)
                 ),
                 gpu_utilization_pct = _parse_smi_value(parts[1]),
                 temperature_c = _parse_smi_value(parts[2]),
@@ -207,8 +194,7 @@ def get_visible_gpu_utilization(
 
 
 def get_backend_visible_gpu_info(
-    parent_visible_ids: Optional[list[int]],
-    backend_cuda_visible_devices: Optional[str],
+    parent_visible_ids: Optional[list[int]], backend_cuda_visible_devices: Optional[str]
 ) -> dict[str, Any]:
     # When parent_visible_ids is None (UUID/MIG mask), we cannot safely
     # map nvidia-smi rows to the process's visible devices.
@@ -274,9 +260,7 @@ def get_backend_visible_gpu_info(
                 "index": idx,
                 "index_kind": "physical",
                 "visible_ordinal": (
-                    visible_ordinals[idx]
-                    if visible_ordinals is not None
-                    else len(devices)
+                    visible_ordinals[idx] if visible_ordinals is not None else len(devices)
                 ),
                 "name": name,
                 "memory_total_gb": round(mem_total_mb / 1024, 2),
diff --git a/studio/backend/utils/hardware/vram_estimation.py b/studio/backend/utils/hardware/vram_estimation.py
index ba1b1dfe61..ddc39733e3 100644
--- a/studio/backend/utils/hardware/vram_estimation.py
+++ b/studio/backend/utils/hardware/vram_estimation.py
@@ -16,9 +16,7 @@ from dataclasses import dataclass, field
 from typing import Dict, Optional
 
 QUANT_4BIT_FACTOR = 16 / 5
-DOUBLE_QUANT_4BIT_FACTOR = (
-    3.6  # bnb_4bit_use_double_quant; see VRAM_ESTIMATION.md section 1
-)
+DOUBLE_QUANT_4BIT_FACTOR = 3.6  # bnb_4bit_use_double_quant; see VRAM_ESTIMATION.md section 1
 CUDA_OVERHEAD_BYTES = int(1.4 * 1024**3)  # calibrated on RTX 5070 Ti
 NON_FLASH_ATTENTION_FACTOR = (
     12.0  # eager attention score+workspace overhead; see VRAM_ESTIMATION.md section 5
@@ -148,12 +146,7 @@ class VramBreakdown:
         Weights/LoRA/optimizer/gradients shard across GPUs.
         Activations do NOT shard (the GPU running a layer holds them).
         """
-        shardable = (
-            self.model_weights
-            + self.lora_adapters
-            + self.optimizer_states
-            + self.gradients
-        )
+        shardable = self.model_weights + self.lora_adapters + self.optimizer_states + self.gradients
         per_gpu_fixed = self.activations + self.cuda_overhead
         return shardable // max(n_gpus, 1) + per_gpu_fixed
 
@@ -194,9 +187,7 @@ def _compute_dense_layer_indices(text_config, total_layers: int) -> tuple:
     layer_types = getattr(text_config, "mlp_layer_types", None)
     if layer_types:
         return tuple(
-            i
-            for i, t in enumerate(layer_types[:total_layers])
-            if str(t).lower() == "dense"
+            i for i, t in enumerate(layer_types[:total_layers]) if str(t).lower() == "dense"
         )
 
     # why: Llama4TextConfig.__init__ auto-populates self.moe_layers from
@@ -234,9 +225,7 @@ def _compute_dense_layer_indices(text_config, total_layers: int) -> tuple:
     if sparse_step is not None and sparse_step > 0:
         mlp_only_set = {int(i) for i in mlp_only}
         return tuple(
-            i
-            for i in range(total_layers)
-            if i in mlp_only_set or (i + 1) % sparse_step != 0
+            i for i in range(total_layers) if i in mlp_only_set or (i + 1) % sparse_step != 0
         )
     return ()
 
@@ -264,8 +253,7 @@ def extract_arch_config(hf_config) -> Optional[ModelArchConfig]:
         intermediate_size = hidden_size * 4
 
     if not all(
-        v is not None
-        for v in (hidden_size, num_layers, num_heads, intermediate_size, vocab_size)
+        v is not None for v in (hidden_size, num_layers, num_heads, intermediate_size, vocab_size)
     ):
         return None
     if num_heads <= 0:
@@ -330,9 +318,7 @@ def extract_arch_config(hf_config) -> Optional[ModelArchConfig]:
     # per MoE layer (modeling_llama4.py).
     intermediate_size_mlp_raw = _first_scalar(_moe_attr("intermediate_size_mlp"))
     dense_intermediate_size = (
-        int(intermediate_size_mlp_raw)
-        if intermediate_size_mlp_raw is not None
-        else None
+        int(intermediate_size_mlp_raw) if intermediate_size_mlp_raw is not None else None
     )
     if (
         intermediate_size_mlp_raw is not None
@@ -391,9 +377,7 @@ def extract_arch_config(hf_config) -> Optional[ModelArchConfig]:
             None,
         )
         or 0,
-        quantization_skip_modules = list(
-            quantization_config.get("llm_int8_skip_modules", []) or []
-        ),
+        quantization_skip_modules = list(quantization_config.get("llm_int8_skip_modules", []) or []),
         quant_4bit_factor = quant_4bit_factor,
         moe_has_dense_mlp = bool(getattr(text_config, "enable_moe_block", False)),
         dense_layer_indices = dense_layer_indices,
@@ -475,11 +459,7 @@ def _per_layer_input_norm_elements(arch: ModelArchConfig) -> int:
     return hd * n_layers + pli
 
 
-def _per_layer_input_lora_params(
-    arch: ModelArchConfig,
-    r: int,
-    target_modules,
-) -> int:
+def _per_layer_input_lora_params(arch: ModelArchConfig, r: int, target_modules) -> int:
     # why: Unsloth's get_peft_regex (unsloth_zoo/peft_utils.py) requires module
     # names to contain a component tag (mlp/attn/...); PLE module names lack
     # any tag, so all-linear training does NOT attach LoRA to them. Only count
@@ -487,11 +467,7 @@ def _per_layer_input_lora_params(
     pli = arch.hidden_size_per_layer_input
     if pli <= 0:
         return 0
-    targets = (
-        {target_modules}
-        if isinstance(target_modules, str)
-        else set(target_modules or [])
-    )
+    targets = {target_modules} if isinstance(target_modules, str) else set(target_modules or [])
     n_layers = arch.num_hidden_layers
     hd = arch.hidden_size
     total = 0
@@ -508,11 +484,7 @@ def _layer_attention_dims(arch: ModelArchConfig, layer_idx: int) -> tuple:
     layer_types = _layer_types(arch)
     layer_type = layer_types[layer_idx]
     is_sliding = layer_type == "sliding_attention"
-    head_dim = (
-        arch.global_head_dim
-        if not is_sliding and arch.global_head_dim
-        else _head_dim(arch)
-    )
+    head_dim = arch.global_head_dim if not is_sliding and arch.global_head_dim else _head_dim(arch)
     use_alt_attention = arch.attention_k_eq_v and not is_sliding
     num_kv_heads = (
         arch.num_global_key_value_heads
@@ -532,10 +504,7 @@ def _layer_mlp_size(arch: ModelArchConfig, layer_idx: int) -> int:
     return _dense_mlp_size(arch)
 
 
-def _text_linear_dims(
-    arch: ModelArchConfig,
-    layer_idx: int,
-) -> Dict[str, tuple[int, int]]:
+def _text_linear_dims(arch: ModelArchConfig, layer_idx: int) -> Dict[str, tuple[int, int]]:
     hd = arch.hidden_size
     if _uses_structured_layer_shapes(arch):
         q_size, kv_size, has_k, has_v = _layer_attention_dims(arch, layer_idx)
@@ -589,11 +558,7 @@ def _module_path_matches(skip_module: str, alias: str) -> bool:
     return ".".join(prefix_parts) in _SKIP_MODULE_TEXT_PREFIXES
 
 
-def _add_module_aliases(
-    aliases: Dict[str, str],
-    canonical: str,
-    suffix: str,
-) -> None:
+def _add_module_aliases(aliases: Dict[str, str], canonical: str, suffix: str) -> None:
     for prefix in (
         "",
         "model",
@@ -607,9 +572,7 @@ def _add_module_aliases(
         aliases[alias] = canonical
 
 
-def _build_text_module_elements(
-    arch: ModelArchConfig,
-) -> tuple[Dict[str, int], Dict[str, str]]:
+def _build_text_module_elements(arch: ModelArchConfig) -> tuple[Dict[str, int], Dict[str, str]]:
     elements: Dict[str, int] = {}
     aliases: Dict[str, str] = {}
 
@@ -620,12 +583,8 @@ def _build_text_module_elements(
     for layer_idx in range(arch.num_hidden_layers):
         layer_modules: Dict[str, int] = {}
         dims = _text_linear_dims(arch, layer_idx)
-        attn_dims = {
-            name: dim for name, dim in dims.items() if name in ATTENTION_TARGET_MODULES
-        }
-        mlp_dims = {
-            name: dim for name, dim in dims.items() if name in MLP_TARGET_MODULES
-        }
+        attn_dims = {name: dim for name, dim in dims.items() if name in ATTENTION_TARGET_MODULES}
+        mlp_dims = {name: dim for name, dim in dims.items() if name in MLP_TARGET_MODULES}
 
         if is_mla:
             # why: _text_linear_dims uses (hd, hd) for q/o; MLA actually splits
@@ -677,10 +636,7 @@ def _build_text_module_elements(
                     )
         else:
             layer_modules.update(
-                {
-                    f"mlp.{name}": in_dim * out_dim
-                    for name, (in_dim, out_dim) in mlp_dims.items()
-                }
+                {f"mlp.{name}": in_dim * out_dim for name, (in_dim, out_dim) in mlp_dims.items()}
             )
 
         if pli > 0:
@@ -704,10 +660,7 @@ def _build_text_module_elements(
             for name, value in layer_modules.items()
             if (
                 name == "mlp"
-                or (
-                    name.startswith("mlp.")
-                    and not (is_sibling_experts and name == "mlp.experts")
-                )
+                or (name.startswith("mlp.") and not (is_sibling_experts and name == "mlp.experts"))
             )
         )
         experts_total = layer_modules.get("mlp.experts", 0) if is_sibling_experts else 0
@@ -764,10 +717,7 @@ def _compute_skipped_quantizable_elements(arch: ModelArchConfig) -> int:
     pruned = {
         canonical
         for canonical in matched
-        if not any(
-            canonical != parent and canonical.startswith(f"{parent}.")
-            for parent in matched
-        )
+        if not any(canonical != parent and canonical.startswith(f"{parent}.") for parent in matched)
     }
     return sum(module_elements[canonical] for canonical in pruned)
 
@@ -900,9 +850,7 @@ def _compute_layer_elements(arch: ModelArchConfig):
         mlp_total = _compute_dense_mlp_elements(arch) * n_layers
 
     layernorms = 2 * hd
-    per_layer_embed = (
-        arch.vocab_size_per_layer_input * arch.hidden_size_per_layer_input * n_layers
-    )
+    per_layer_embed = arch.vocab_size_per_layer_input * arch.hidden_size_per_layer_input * n_layers
     ple_text_linear = _per_layer_input_quantizable(arch)
     ple_norms = _per_layer_input_norm_elements(arch)
     embed_tokens = arch.vocab_size * hd + per_layer_embed + ple_norms
@@ -911,9 +859,7 @@ def _compute_layer_elements(arch: ModelArchConfig):
 
 
 def compute_model_weights_bytes(
-    arch: ModelArchConfig,
-    training_method: str,
-    load_in_4bit: bool,
+    arch: ModelArchConfig, training_method: str, load_in_4bit: bool
 ) -> int:
     total_quantizable, layernorms, embed_tokens, lm_head = _compute_layer_elements(arch)
     n_layers = arch.num_hidden_layers
@@ -926,9 +872,7 @@ def compute_model_weights_bytes(
         )
         quantized = total_quantizable - skipped_quantizable
         return int(
-            quantized * 2 / arch.quant_4bit_factor
-            + skipped_quantizable * 2
-            + non_quantizable * 2
+            quantized * 2 / arch.quant_4bit_factor + skipped_quantizable * 2 + non_quantizable * 2
         )
 
     return int((total_quantizable + non_quantizable) * 2)
@@ -940,11 +884,7 @@ def compute_total_params(arch: ModelArchConfig) -> int:
     return total_quantizable + layernorms * n_layers + embed_tokens + lm_head
 
 
-def _lora_attn_elements(
-    arch: ModelArchConfig,
-    r: int,
-    target_modules: list,
-) -> int:
+def _lora_attn_elements(arch: ModelArchConfig, r: int, target_modules: list) -> int:
     hd = arch.hidden_size
     if arch.q_lora_rank is not None:
         # MLA: q_proj->q_b, k_proj->kv_a, v_proj->kv_b, o_proj->o
@@ -974,11 +914,7 @@ def _lora_attn_elements(
 
 
 def _lora_mlp_elements(
-    hd: int,
-    mlp_size: int,
-    r: int,
-    target_modules: list,
-    expert_mult: int,
+    hd: int, mlp_size: int, r: int, target_modules: list, expert_mult: int
 ) -> int:
     module_ab = {
         "gate_proj": (hd * r, r * mlp_size),
@@ -992,11 +928,7 @@ def _lora_mlp_elements(
     return total
 
 
-def compute_lora_params(
-    arch: ModelArchConfig,
-    lora_rank: int,
-    target_modules: list,
-) -> int:
+def compute_lora_params(arch: ModelArchConfig, lora_rank: int, target_modules: list) -> int:
     all_linear = _targets_all_linear(target_modules)
     selected_modules = list(DEFAULT_TARGET_MODULES) if all_linear else target_modules
     hd = arch.hidden_size
@@ -1062,11 +994,7 @@ def compute_lora_params(
                 mlp_total = moe_mlp * n_moe + dense_only
         else:
             mlp_total = structured_dense_mlp
-        return (
-            attn_total
-            + mlp_total
-            + _per_layer_input_lora_params(arch, r, target_modules)
-        )
+        return attn_total + mlp_total + _per_layer_input_lora_params(arch, r, target_modules)
     elif n_experts > 1:
         attn_total = _lora_attn_elements(arch, r, selected_modules) * n_layers
         n_dense = arch.num_dense_layers
@@ -1118,9 +1046,7 @@ def compute_lora_params(
             * n_layers
         )
 
-    return (
-        attn_total + mlp_total + _per_layer_input_lora_params(arch, r, target_modules)
-    )
+    return attn_total + mlp_total + _per_layer_input_lora_params(arch, r, target_modules)
 
 
 def compute_lora_adapter_bytes(lora_params: int) -> int:
@@ -1144,10 +1070,7 @@ def _is_linear_attention(attention_implementation: Optional[str]) -> bool:
 
 
 def _compute_non_flash_attention_bytes(
-    arch: ModelArchConfig,
-    batch_size: int,
-    seq_len: int,
-    effective_layers: float,
+    arch: ModelArchConfig, batch_size: int, seq_len: int, effective_layers: float
 ) -> int:
     score_elements = batch_size * arch.num_attention_heads * seq_len * seq_len
     return int(score_elements * 2 * NON_FLASH_ATTENTION_FACTOR * effective_layers)
@@ -1190,10 +1113,7 @@ def _layer_qkv_mlp_sizes(arch: ModelArchConfig, layer_idx: int) -> tuple:
 
 
 def _per_layer_activation_bytes(
-    arch: ModelArchConfig,
-    layer_idx: int,
-    batch_size: int,
-    seq_len: int,
+    arch: ModelArchConfig, layer_idx: int, batch_size: int, seq_len: int
 ) -> int:
     qkv_size, mlp_size = _layer_qkv_mlp_sizes(arch, layer_idx)
     activation_qkv = seq_len * batch_size * qkv_size
@@ -1204,9 +1124,7 @@ def _per_layer_activation_bytes(
     # is set; see gemma4/modular_gemma4.py:1141-1145.
     pli = arch.hidden_size_per_layer_input
     activation_ple = seq_len * batch_size * (arch.hidden_size + pli) if pli > 0 else 0
-    return int(
-        (activation_qkv + residual_memory + activation_mlp + activation_ple) * 2 * 1.25
-    )
+    return int((activation_qkv + residual_memory + activation_mlp + activation_ple) * 2 * 1.25)
 
 
 def compute_activation_bytes(
@@ -1227,14 +1145,12 @@ def compute_activation_bytes(
     if gc_multiplier is None:
         effective_layers = n_layers
         linear_bytes = sum(
-            _per_layer_activation_bytes(arch, i, batch_size, seq_len)
-            for i in range(n_layers)
+            _per_layer_activation_bytes(arch, i, batch_size, seq_len) for i in range(n_layers)
         )
     else:
         effective_layers = gc_multiplier
         max_layer_bytes = max(
-            _per_layer_activation_bytes(arch, i, batch_size, seq_len)
-            for i in range(n_layers)
+            _per_layer_activation_bytes(arch, i, batch_size, seq_len) for i in range(n_layers)
         )
         linear_bytes = int(max_layer_bytes * effective_layers)
 
@@ -1257,10 +1173,7 @@ def compute_activation_bytes(
     )
 
 
-def estimate_training_vram(
-    arch: ModelArchConfig,
-    config: TrainingVramConfig,
-) -> VramBreakdown:
+def estimate_training_vram(arch: ModelArchConfig, config: TrainingVramConfig) -> VramBreakdown:
     method = config.training_method.lower()
     is_lora = method in ("qlora", "lora")
     load_in_4bit = config.load_in_4bit or method == "qlora"
diff --git a/studio/backend/utils/inference/inference_config.py b/studio/backend/utils/inference/inference_config.py
index 9efc281b0b..e07bc62cfd 100644
--- a/studio/backend/utils/inference/inference_config.py
+++ b/studio/backend/utils/inference/inference_config.py
@@ -34,10 +34,7 @@ def _load_family_defaults():
         return
 
     json_path = (
-        Path(__file__).parent.parent.parent
-        / "assets"
-        / "configs"
-        / "inference_defaults.json"
+        Path(__file__).parent.parent.parent / "assets" / "configs" / "inference_defaults.json"
     )
     try:
         with open(json_path, "r", encoding = "utf-8") as f:
diff --git a/studio/backend/utils/llama_cpp_freshness.py b/studio/backend/utils/llama_cpp_freshness.py
index 2c781f4a7b..f0e642a38e 100644
--- a/studio/backend/utils/llama_cpp_freshness.py
+++ b/studio/backend/utils/llama_cpp_freshness.py
@@ -38,7 +38,6 @@ def _cache_dir() -> Path:
     """Lazy import so tests can stub storage_roots."""
     try:
         from utils.paths.storage_roots import cache_root
-
         return cache_root() / "llama_cpp_freshness"
     except Exception:
         return Path.home() / ".unsloth" / "studio" / "cache" / "llama_cpp_freshness"
@@ -136,9 +135,7 @@ def _fetch_latest_release_tag(repo: str, timeout: float = 5.0) -> Optional[str]:
     return tag if isinstance(tag, str) and tag else None
 
 
-def latest_published_release(
-    repo: str, *, force_refresh: bool = False
-) -> Optional[str]:
+def latest_published_release(repo: str, *, force_refresh: bool = False) -> Optional[str]:
     """Latest release tag for `repo`. Memo + disk-cached (24h TTL).
     None when offline and never previously cached."""
     if not repo:
diff --git a/studio/backend/utils/models/checkpoints.py b/studio/backend/utils/models/checkpoints.py
index b6b2e11c2e..99770ce7a6 100644
--- a/studio/backend/utils/models/checkpoints.py
+++ b/studio/backend/utils/models/checkpoints.py
@@ -99,9 +99,7 @@ def scan_checkpoints(
                     name_part = parts[0]
                     idx = name_part.find("_")
                     if idx > 0:
-                        metadata["base_model"] = (
-                            name_part[:idx] + "/" + name_part[idx + 1 :]
-                        )
+                        metadata["base_model"] = name_part[:idx] + "/" + name_part[idx + 1 :]
                     else:
                         metadata["base_model"] = name_part
 
@@ -131,9 +129,7 @@ def scan_checkpoints(
                 )
 
             models.append((item.name, checkpoints, metadata))
-            logger.debug(
-                f"Found model: {item.name} with {len(checkpoints)} checkpoint(s)"
-            )
+            logger.debug(f"Found model: {item.name} with {len(checkpoints)} checkpoint(s)")
 
         # Sort by modification time (newest first)
         models.sort(key = lambda x: Path(x[1][0][1]).stat().st_mtime, reverse = True)
diff --git a/studio/backend/utils/models/gguf_metadata.py b/studio/backend/utils/models/gguf_metadata.py
index dc9c21226e..32618773b7 100644
--- a/studio/backend/utils/models/gguf_metadata.py
+++ b/studio/backend/utils/models/gguf_metadata.py
@@ -282,8 +282,7 @@ def is_mmproj_by_metadata(meta: Optional[Dict[str, str]]) -> Optional[bool]:
 
 
 def pairing_score(
-    weight_meta: Optional[Dict[str, str]],
-    mmproj_meta: Optional[Dict[str, str]],
+    weight_meta: Optional[Dict[str, str]], mmproj_meta: Optional[Dict[str, str]]
 ) -> int:
     """Pairing confidence: 100 = base_model URL match, 80 = basename + org,
     60 = basename, -1 = definitive mismatch, 0 = decide from filename."""
diff --git a/studio/backend/utils/models/model_config.py b/studio/backend/utils/models/model_config.py
index b488a19953..92960485a4 100644
--- a/studio/backend/utils/models/model_config.py
+++ b/studio/backend/utils/models/model_config.py
@@ -57,13 +57,9 @@ def _env_offline() -> bool:
 # ── Model size extraction ────────────────────────────────────
 import re as _re
 
-_MODEL_SIZE_RE = _re.compile(
-    r"(?:^|[-_/])(\d+\.?\d*)\s*([bm])(?:$|[-_/])", _re.IGNORECASE
-)
+_MODEL_SIZE_RE = _re.compile(r"(?:^|[-_/])(\d+\.?\d*)\s*([bm])(?:$|[-_/])", _re.IGNORECASE)
 # MoE active-parameter pattern: matches "A3B", "A3.5B", etc.
-_ACTIVE_SIZE_RE = _re.compile(
-    r"(?:^|[-_/])a(\d+\.?\d*)\s*([bm])(?:$|[-_/])", _re.IGNORECASE
-)
+_ACTIVE_SIZE_RE = _re.compile(r"(?:^|[-_/])a(\d+\.?\d*)\s*([bm])(?:$|[-_/])", _re.IGNORECASE)
 
 
 def extract_model_size_b(model_id: str) -> float | None:
@@ -571,9 +567,7 @@ except Exception as exc:
 """
 
 
-def _is_vision_model_subprocess(
-    model_name: str, hf_token: Optional[str] = None
-) -> Optional[bool]:
+def _is_vision_model_subprocess(model_name: str, hf_token: Optional[str] = None) -> Optional[bool]:
     """Run is_vision_model check in a subprocess with transformers 5.x.
 
     Same pattern as training/inference workers: spawn a clean subprocess
@@ -715,9 +709,7 @@ def is_vision_model(model_name: str, hf_token: Optional[str] = None) -> bool:
     return False
 
 
-def _is_vision_model_uncached(
-    model_name: str, hf_token: Optional[str] = None
-) -> Optional[bool]:
+def _is_vision_model_uncached(model_name: str, hf_token: Optional[str] = None) -> Optional[bool]:
     """Uncached vision model detection -- called by is_vision_model().
 
     Returns True/False for definitive results, or None when detection failed
@@ -775,9 +767,7 @@ def _is_vision_model_uncached(
         # Check 5: Known VLM model_type values that may not match above checks
         if hasattr(config, "model_type"):
             if config.model_type in _VLM_MODEL_TYPES:
-                logger.info(
-                    f"Model {model_name} detected as VLM: model_type={config.model_type}"
-                )
+                logger.info(f"Model {model_name} detected as VLM: model_type={config.model_type}")
                 return True
 
         return False
@@ -823,9 +813,7 @@ _AUDIO_TOKEN_PATTERNS = {
         and "<|text_start|>" in tokens
         and "<|text_end|>" in tokens
     ),
-    "snac": lambda tokens: (
-        sum(1 for t in tokens if t.startswith(" 10000
-    ),
+    "snac": lambda tokens: (sum(1 for t in tokens if t.startswith(" 10000),
 }
 
 
@@ -849,9 +837,7 @@ def detect_audio_type(model_name: str, hf_token: Optional[str] = None) -> Option
     return result
 
 
-def _detect_audio_from_tokenizer(
-    model_name: str, hf_token: Optional[str] = None
-) -> Optional[str]:
+def _detect_audio_from_tokenizer(model_name: str, hf_token: Optional[str] = None) -> Optional[str]:
     """Detect audio type from tokenizer special tokens (for LLM-based audio models).
 
     First checks local HF cache, then fetches tokenizer_config.json from HuggingFace.
@@ -913,9 +899,7 @@ def _detect_audio_from_tokenizer(
 
         return None
     except Exception as e:
-        logger.debug(
-            f"Could not detect audio type from tokenizer for {model_name}: {e}"
-        )
+        logger.debug(f"Could not detect audio type from tokenizer for {model_name}: {e}")
         return None
 
 
@@ -1346,9 +1330,7 @@ def _iter_hf_cache_snapshots(repo_id: str):
     yield from snap_dirs
 
 
-def _list_gguf_variants_from_hf_cache(
-    repo_id: str,
-) -> Optional[tuple[list[GgufVariantInfo], bool]]:
+def _list_gguf_variants_from_hf_cache(repo_id: str) -> Optional[tuple[list[GgufVariantInfo], bool]]:
     """Variants from the local HF cache snapshot, or None if not cached."""
     for snap in _iter_hf_cache_snapshots(repo_id):
         variants, has_vision = list_local_gguf_variants(str(snap))
@@ -1358,8 +1340,7 @@ def _list_gguf_variants_from_hf_cache(
 
 
 def list_gguf_variants(
-    repo_id: str,
-    hf_token: Optional[str] = None,
+    repo_id: str, hf_token: Optional[str] = None
 ) -> tuple[list[GgufVariantInfo], bool]:
     """
     List all GGUF quantization variants in a HuggingFace repo.
@@ -1462,9 +1443,7 @@ def _resolve_gguf_dir(p: Path) -> Optional[Path]:
     return None
 
 
-def list_local_gguf_variants(
-    directory: str,
-) -> tuple[list[GgufVariantInfo], bool]:
+def list_local_gguf_variants(directory: str) -> tuple[list[GgufVariantInfo], bool]:
     """List GGUF quantization variants in a local directory.
 
     Mirrors :func:`list_gguf_variants` but reads from the filesystem
@@ -1533,8 +1512,7 @@ def _find_local_gguf_by_variant(directory: str, variant: str) -> Optional[str]:
     matches = sorted(
         f
         for f in _iter_gguf_files(p, recursive = True)
-        if not _is_mmproj(f.name)
-        and _extract_quant_label(f.relative_to(p).as_posix()) == variant
+        if not _is_mmproj(f.name) and _extract_quant_label(f.relative_to(p).as_posix()) == variant
     )
     if matches:
         return str(matches[0].resolve())
@@ -1558,10 +1536,7 @@ def _detect_gguf_from_hf_cache(repo_id: str) -> Optional[str]:
     return None
 
 
-def detect_gguf_model_remote(
-    repo_id: str,
-    hf_token: Optional[str] = None,
-) -> Optional[str]:
+def detect_gguf_model_remote(repo_id: str, hf_token: Optional[str] = None) -> Optional[str]:
     """
     Check if a HuggingFace repo contains GGUF files.
 
@@ -1617,9 +1592,7 @@ def detect_gguf_model_remote(
         )
         return cached
 
-    logger.warning(
-        f"Could not check GGUF files for '{repo_id}' after 3 attempts: {last_err}"
-    )
+    logger.warning(f"Could not check GGUF files for '{repo_id}' after 3 attempts: {last_err}")
     return None
 
 
@@ -1752,9 +1725,7 @@ def _looks_like_lora_adapter(model_dir: Path) -> bool:
     )
 
 
-def scan_trained_models(
-    outputs_dir: str = str(outputs_root()),
-) -> List[Tuple[str, str, str]]:
+def scan_trained_models(outputs_dir: str = str(outputs_root())) -> List[Tuple[str, str, str]]:
     """
     Scan outputs folder for trained Studio models.
 
@@ -1823,9 +1794,7 @@ def scan_exported_models(
 
             # Check for flat GGUF export (e.g. exports/gemma-3-4b-it-finetune-gguf/)
             # Filter out mmproj (vision projection) files — they aren't loadable as main models
-            gguf_files = [
-                f for f in _iter_gguf_files(run_dir) if not _is_mmproj(f.name)
-            ]
+            gguf_files = [f for f in _iter_gguf_files(run_dir) if not _is_mmproj(f.name)]
             if gguf_files:
                 base_model = None
                 export_meta = run_dir / "export_metadata.json"
@@ -1900,9 +1869,7 @@ def scan_exported_models(
                 # Fallback: read base model from the original training run's
                 # adapter_config.json in ./outputs/{run_name}/
                 if not base_model:
-                    outputs_adapter_cfg = (
-                        resolve_output_dir(run_dir.name) / "adapter_config.json"
-                    )
+                    outputs_adapter_cfg = resolve_output_dir(run_dir.name) / "adapter_config.json"
                     try:
                         if outputs_adapter_cfg.exists():
                             cfg = json.loads(outputs_adapter_cfg.read_text())
@@ -1935,9 +1902,7 @@ def get_base_model_from_checkpoint(checkpoint_path: str) -> Optional[str]:
                 config = json.load(f)
                 base_model = config.get("base_model_name_or_path")
                 if base_model:
-                    logger.info(
-                        "Detected base model from adapter_config.json: %s", base_model
-                    )
+                    logger.info("Detected base model from adapter_config.json: %s", base_model)
                     return base_model
 
         config_path = checkpoint_path_obj / "config.json"
@@ -2010,9 +1975,7 @@ def get_base_model_from_lora(lora_path: str) -> Optional[str]:
                 config = json.load(f)
                 base_model = config.get("base_model_name_or_path")
                 if base_model:
-                    logger.info(
-                        f"Detected base model from adapter_config.json: {base_model}"
-                    )
+                    logger.info(f"Detected base model from adapter_config.json: {base_model}")
                     return base_model
 
         # Fallback: try training_args.bin (requires torch)
@@ -2084,9 +2047,7 @@ def load_model_defaults(model_name: str) -> Dict[str, Any]:
                 if config_path.is_file():
                     with open(config_path, "r", encoding = "utf-8") as f:
                         config = yaml.safe_load(f) or {}
-                        logger.info(
-                            f"Loaded model defaults from {config_path} (via mapping)"
-                        )
+                        logger.info(f"Loaded model defaults from {config_path} (via mapping)")
                         return config
 
         # If model_name is a local path (e.g. /home/.../Spark-TTS-0.5B/LLM from
@@ -2156,14 +2117,10 @@ class ModelConfig:
     is_lora: bool  # Is this a lora adapter?
     is_gguf: bool = False  # Is this a GGUF model?
     is_audio: bool = False  # Is this a TTS audio model?
-    audio_type: Optional[str] = (
-        None  # Audio codec type: 'snac', 'csm', 'bicodec', 'dac'
-    )
+    audio_type: Optional[str] = None  # Audio codec type: 'snac', 'csm', 'bicodec', 'dac'
     has_audio_input: bool = False  # Accepts audio input (ASR/speech understanding)
     gguf_file: Optional[str] = None  # Full path to the .gguf file (local mode)
-    gguf_mmproj_file: Optional[str] = (
-        None  # Full path to the mmproj .gguf file (vision projection)
-    )
+    gguf_mmproj_file: Optional[str] = None  # Full path to the mmproj .gguf file (vision projection)
     gguf_hf_repo: Optional[str] = (
         None  # HF repo ID for -hf mode (e.g. "unsloth/gemma-3-4b-it-GGUF")
     )
@@ -2172,7 +2129,9 @@ class ModelConfig:
 
     @classmethod
     def from_lora_path(
-        cls, lora_path: str, hf_token: Optional[str] = None
+        cls,
+        lora_path: str,
+        hf_token: Optional[str] = None,
     ) -> Optional["ModelConfig"]:
         """
         Create ModelConfig from a local LoRA adapter path.
@@ -2321,9 +2280,7 @@ class ModelConfig:
                     gguf_is_vision = True
                     logger.info(f"Detected mmproj for vision: {mmproj_file}")
                 elif base_is_vision:
-                    logger.warning(
-                        f"Base model is vision but no mmproj file found in {gguf_dir}"
-                    )
+                    logger.warning(f"Base model is vision but no mmproj file found in {gguf_dir}")
 
                 return cls(
                     identifier = identifier,
@@ -2385,15 +2342,11 @@ class ModelConfig:
         # Auto-detect LoRA for local paths (check adapter_config.json on disk)
         if not is_lora and is_local:
             detected_base = (
-                get_base_model_from_lora(path)
-                if _looks_like_lora_adapter(Path(path))
-                else None
+                get_base_model_from_lora(path) if _looks_like_lora_adapter(Path(path)) else None
             )
             if detected_base:
                 is_lora = True
-                logger.info(
-                    f"Auto-detected local LoRA adapter at '{path}' (base: {detected_base})"
-                )
+                logger.info(f"Auto-detected local LoRA adapter at '{path}' (base: {detected_base})")
 
         # Auto-detect LoRA for remote HF models. When offline, huggingface_hub
         # raises OfflineModeIsEnabled in ~0ms; we fall through to the cache.
@@ -2407,18 +2360,14 @@ class ModelConfig:
                     is_lora = True
                     logger.info(f"Auto-detected remote LoRA adapter: '{identifier}'")
             except Exception as e:
-                logger.debug(
-                    f"Could not check remote LoRA status for '{identifier}': {e}"
-                )
+                logger.debug(f"Could not check remote LoRA status for '{identifier}': {e}")
 
             # API may have failed; adapter_config.json may still be cached.
             if not is_lora:
                 for snap in _iter_hf_cache_snapshots(identifier):
                     if (snap / "adapter_config.json").is_file():
                         is_lora = True
-                        logger.info(
-                            f"Auto-detected cached LoRA adapter: '{identifier}'"
-                        )
+                        logger.info(f"Auto-detected cached LoRA adapter: '{identifier}'")
                         break
 
         # Handle LoRA adapters
@@ -2432,9 +2381,7 @@ class ModelConfig:
                 try:
                     from huggingface_hub import hf_hub_download
 
-                    config_path = hf_hub_download(
-                        identifier, "adapter_config.json", token = hf_token
-                    )
+                    config_path = hf_hub_download(identifier, "adapter_config.json", token = hf_token)
                     with open(config_path, "r") as f:
                         adapter_config = json.load(f)
                     base_model = adapter_config.get("base_model_name_or_path")
@@ -2498,9 +2445,7 @@ class ModelConfig:
 
         #  Use the correct 'local_models' parameter to resolve display names
         if " (Active)" in selected or " (Ready)" in selected:
-            clean_display_name = selected.replace(" (Active)", "").replace(
-                " (Ready)", ""
-            )
+            clean_display_name = selected.replace(" (Active)", "").replace(" (Ready)", "")
             if local_models:
                 for local_display, local_path in local_models:
                     if local_display == clean_display_name:
diff --git a/studio/backend/utils/native_path_leases.py b/studio/backend/utils/native_path_leases.py
index a69dfab532..7d8514abc8 100644
--- a/studio/backend/utils/native_path_leases.py
+++ b/studio/backend/utils/native_path_leases.py
@@ -68,9 +68,7 @@ def native_path_leases_supported() -> bool:
     return True
 
 
-def child_env_without_native_path_secret(
-    env: Mapping[str, str] | None = None,
-) -> dict[str, str]:
+def child_env_without_native_path_secret(env: Mapping[str, str] | None = None) -> dict[str, str]:
     """Return a child-process env with the native path lease secret removed."""
 
     if env is None:
@@ -82,11 +80,7 @@ def child_env_without_native_path_secret(
     return cleaned
 
 
-def run_without_native_path_secret(
-    target: Callable[..., Any],
-    *args: Any,
-    **kwargs: Any,
-) -> Any:
+def run_without_native_path_secret(target: Callable[..., Any], *args: Any, **kwargs: Any) -> Any:
     """Run a multiprocessing child target without the native path lease secret."""
 
     global _CACHED_LEASE_SECRET, _SCRUB_SAVED_SECRET
@@ -153,9 +147,7 @@ def verify_native_path_lease(
         raise NativePathLeaseError("Native path is no longer accessible.") from exc
     _reject_network_or_device_path(resolved)
     if not _same_native_path(resolved, path):
-        raise NativePathLeaseError(
-            "Native path grant no longer resolves to the selected path."
-        )
+        raise NativePathLeaseError("Native path grant no longer resolves to the selected path.")
 
     grant = NativePathGrant(
         operation = str(payload["operation"]),
@@ -219,9 +211,7 @@ def _decode_secret() -> bytes:
             if encoded is None and _SCRUB_SAVED_SECRET is not None:
                 encoded = _SCRUB_SAVED_SECRET
         if not encoded:
-            raise NativePathLeaseError(
-                "Native path grants require the managed desktop backend."
-            )
+            raise NativePathLeaseError("Native path grants require the managed desktop backend.")
         try:
             secret = _b64decode(encoded)
         except Exception as exc:
@@ -272,9 +262,7 @@ def _validate_payload(
     )
     missing = [key for key in required if key not in payload]
     if missing:
-        raise NativePathLeaseError(
-            "Native path grant payload is missing required fields."
-        )
+        raise NativePathLeaseError("Native path grant payload is missing required fields.")
     if _required_int(payload, "version") != 1:
         raise NativePathLeaseError("Native path grant version is unsupported.")
     if payload["operation"] != operation:
@@ -353,19 +341,13 @@ def _reject_network_or_device_path(path: Path) -> None:
             rest = normalized[4:]
             is_local_drive = len(rest) >= 3 and rest[0].isalpha() and rest[1:3] == ":\\"
             if not is_local_drive:
-                raise NativePathLeaseError(
-                    "Network paths are not supported for native grants."
-                )
+                raise NativePathLeaseError("Network paths are not supported for native grants.")
         elif normalized.startswith("\\\\"):
-            raise NativePathLeaseError(
-                "Network paths are not supported for native grants."
-            )
+            raise NativePathLeaseError("Network paths are not supported for native grants.")
     if os.name != "nt":
         for root in ("/dev", "/proc", "/sys"):
             if path.is_relative_to(root):
-                raise NativePathLeaseError(
-                    "Device and virtual filesystem paths are not supported."
-                )
+                raise NativePathLeaseError("Device and virtual filesystem paths are not supported.")
     if "\x00" in text:
         raise NativePathLeaseError("Native path contains invalid characters.")
 
@@ -397,9 +379,7 @@ def _optional_int(value: Any) -> int | None:
 def _required_int(payload: dict[str, Any], key: str) -> int:
     raw = payload.get(key)
     if raw is None:
-        raise NativePathLeaseError(
-            "Native path grant payload is missing required fields."
-        )
+        raise NativePathLeaseError("Native path grant payload is missing required fields.")
     try:
         return int(raw)
     except (TypeError, ValueError) as exc:
diff --git a/studio/backend/utils/paths/path_utils.py b/studio/backend/utils/paths/path_utils.py
index 9ef9a2dd92..22c6c46ee1 100644
--- a/studio/backend/utils/paths/path_utils.py
+++ b/studio/backend/utils/paths/path_utils.py
@@ -134,7 +134,6 @@ def _hf_hub_cache_dir() -> Path:
     """Return HF cache root honoring HF_HUB_CACHE when available."""
     try:
         from huggingface_hub.constants import HF_HUB_CACHE
-
         return Path(HF_HUB_CACHE)
     except Exception as exc:
         logger.debug(
diff --git a/studio/backend/utils/paths/storage_roots.py b/studio/backend/utils/paths/storage_roots.py
index 6319452ed2..b254c20f97 100644
--- a/studio/backend/utils/paths/storage_roots.py
+++ b/studio/backend/utils/paths/storage_roots.py
@@ -263,9 +263,7 @@ def _setup_cache_env() -> None:
     Works on Linux, macOS, and Windows.
     """
     root = cache_root()
-    xdg_cache = Path(
-        os.environ.get("XDG_CACHE_HOME", Path.home() / ".cache")
-    ).expanduser()
+    xdg_cache = Path(os.environ.get("XDG_CACHE_HOME", Path.home() / ".cache")).expanduser()
     hf_default = xdg_cache / "huggingface"
     defaults: dict[str, str] = {
         "HF_HOME": str(hf_default),
@@ -298,9 +296,7 @@ def ensure_studio_directories() -> None:
     _setup_cache_env()
 
 
-def _clean_relative_path(
-    path_value: str, *, strip_prefixes: tuple[str, ...] = ()
-) -> Path:
+def _clean_relative_path(path_value: str, *, strip_prefixes: tuple[str, ...] = ()) -> Path:
     path = Path(path_value).expanduser()
     parts = [part for part in path.parts if part not in ("", ".")]
     while parts and parts[0] in strip_prefixes:
@@ -319,8 +315,7 @@ def _assert_contained(resolved: Path, root: Path) -> None:
         resolved_real.relative_to(root_real)
     except ValueError as exc:
         raise ValueError(
-            f"path escapes root: {resolved!s} -> {resolved_real!s} "
-            f"is not under {root_real!s}"
+            f"path escapes root: {resolved!s} -> {resolved_real!s} " f"is not under {root_real!s}"
         ) from exc
 
 
@@ -394,9 +389,7 @@ def resolve_dataset_path(path_value: str) -> Path:
                 return path
             except ValueError:
                 continue
-        raise ValueError(
-            f"dataset path must be relative or under a dataset root: {raw!r}"
-        )
+        raise ValueError(f"dataset path must be relative or under a dataset root: {raw!r}")
 
     parts = [part for part in Path(path_value).parts if part not in ("", ".")]
     if parts[:2] == ["assets", "datasets"]:
diff --git a/studio/backend/utils/studio_version.py b/studio/backend/utils/studio_version.py
index 70059f8a3c..e59439a2cc 100644
--- a/studio/backend/utils/studio_version.py
+++ b/studio/backend/utils/studio_version.py
@@ -39,9 +39,7 @@ def _path_is_in_site_packages(path: Path) -> bool:
 
 
 def _is_source_checkout(repo_root: Path) -> bool:
-    return (repo_root / ".git").exists() and not _path_is_in_site_packages(
-        Path(__file__).resolve()
-    )
+    return (repo_root / ".git").exists() and not _path_is_in_site_packages(Path(__file__).resolve())
 
 
 def _exact_git_studio_tag(repo_root: Path) -> str | None:
diff --git a/studio/backend/utils/transformers_version.py b/studio/backend/utils/transformers_version.py
index c23857e0a4..16f964d628 100644
--- a/studio/backend/utils/transformers_version.py
+++ b/studio/backend/utils/transformers_version.py
@@ -201,7 +201,6 @@ def _resolve_base_model(model_name: str) -> str:
     if local_path.is_dir():
         try:
             from utils.models import get_base_model_from_lora
-
             base = get_base_model_from_lora(model_name)
             if base:
                 logger.info(
@@ -275,9 +274,7 @@ def _check_tokenizer_config_needs_v5(model_name: str) -> bool:
         _tokenizer_class_cache[model_name] = result
         return result
     except Exception as exc:
-        logger.debug(
-            "Could not fetch tokenizer_config.json for '%s': %s", model_name, exc
-        )
+        logger.debug("Could not fetch tokenizer_config.json for '%s': %s", model_name, exc)
         _tokenizer_class_cache[model_name] = False
         return False
 
@@ -467,8 +464,7 @@ def _venv_dir_is_valid(venv_dir: str, packages: tuple[str, ...]) -> bool:
         pkg_name_norm = pkg_name.replace("-", "_")
         # Check directory exists
         if not any(
-            (Path(venv_dir) / d).is_dir()
-            for d in (pkg_name_norm, pkg_name_norm.replace("_", "-"))
+            (Path(venv_dir) / d).is_dir() for d in (pkg_name_norm, pkg_name_norm.replace("_", "-"))
         ):
             return False
         # For unpinned packages, existence is enough
@@ -563,9 +559,7 @@ def _ensure_venv_dir(venv_dir: str, packages: tuple[str, ...], label: str) -> bo
     if _venv_dir_is_valid(venv_dir, packages):
         return True
 
-    logger.warning(
-        "%s not found or incomplete at %s -- installing at runtime", label, venv_dir
-    )
+    logger.warning("%s not found or incomplete at %s -- installing at runtime", label, venv_dir)
     shutil.rmtree(venv_dir, ignore_errors = True)
     os.makedirs(venv_dir, exist_ok = True)
     for pkg in packages:
@@ -577,16 +571,12 @@ def _ensure_venv_dir(venv_dir: str, packages: tuple[str, ...], label: str) -> bo
 
 def _ensure_venv_t5_530_exists() -> bool:
     """Ensure .venv_t5_530/ exists with transformers 5.3.0."""
-    return _ensure_venv_dir(
-        _VENV_T5_530_DIR, _VENV_T5_530_PACKAGES, "transformers 5.3.0"
-    )
+    return _ensure_venv_dir(_VENV_T5_530_DIR, _VENV_T5_530_PACKAGES, "transformers 5.3.0")
 
 
 def _ensure_venv_t5_550_exists() -> bool:
     """Ensure .venv_t5_550/ exists with transformers 5.5.0."""
-    return _ensure_venv_dir(
-        _VENV_T5_550_DIR, _VENV_T5_550_PACKAGES, "transformers 5.5.0"
-    )
+    return _ensure_venv_dir(_VENV_T5_550_DIR, _VENV_T5_550_PACKAGES, "transformers 5.5.0")
 
 
 def _ensure_venv_t5_exists() -> bool:
@@ -693,15 +683,12 @@ def ensure_transformers_version(model_name: str) -> None:
         _deactivate_5x()
         if not ensure_fn():
             raise RuntimeError(
-                f"Cannot activate transformers {target_version}: "
-                f"venv missing at {venv_dir}"
+                f"Cannot activate transformers {target_version}: " f"venv missing at {venv_dir}"
             )
         logger.info("Activating transformers %s…", target_version)
         _activate_venv(venv_dir, f"transformers {target_version}")
     else:
-        logger.info(
-            "Reverting to default transformers %s…", TRANSFORMERS_DEFAULT_VERSION
-        )
+        logger.info("Reverting to default transformers %s…", TRANSFORMERS_DEFAULT_VERSION)
         _deactivate_5x()
 
     final = _get_in_memory_version()
diff --git a/studio/backend/utils/update_status.py b/studio/backend/utils/update_status.py
index 9142203a69..9b71ff31a0 100644
--- a/studio/backend/utils/update_status.py
+++ b/studio/backend/utils/update_status.py
@@ -73,11 +73,7 @@ def detect_install_source() -> str:
     try:
         dist = distribution(PACKAGE_NAME)
     except PackageNotFoundError:
-        return (
-            "local_repo"
-            if _path_has_git_parent(_repo_root_from_this_file())
-            else "unknown"
-        )
+        return "local_repo" if _path_has_git_parent(_repo_root_from_this_file()) else "unknown"
 
     try:
         direct_url = dist.read_text("direct_url.json")
@@ -146,9 +142,7 @@ def get_studio_update_status(current_version: str) -> dict[str, Any]:
             current_version = current_version,
             latest_version = None,
             install_source = install_source,
-            reason = "invalid_current_version"
-            if current_version != "dev"
-            else "dev_build",
+            reason = "invalid_current_version" if current_version != "dev" else "dev_build",
         )
     latest_result = get_latest_pypi_version()
     if latest_result.latest_version is None:
@@ -216,9 +210,7 @@ def get_latest_pypi_version() -> LatestVersionResult:
             error = "Could not check PyPI update metadata.",
         )
 
-    ttl = (
-        PYPI_SUCCESS_TTL_SECONDS if result.latest_version else PYPI_FAILURE_TTL_SECONDS
-    )
+    ttl = PYPI_SUCCESS_TTL_SECONDS if result.latest_version else PYPI_FAILURE_TTL_SECONDS
     with _cache_condition:
         _latest_version_cache = _LatestVersionCacheEntry(
             result = result,
@@ -262,9 +254,7 @@ def _fetch_latest_pypi_version() -> LatestVersionResult:
             error = "Could not reach PyPI for update metadata.",
         )
 
-    latest = (
-        payload.get("info", {}).get("version") if isinstance(payload, dict) else None
-    )
+    latest = payload.get("info", {}).get("version") if isinstance(payload, dict) else None
     if not isinstance(latest, str) or not latest.strip():
         return LatestVersionResult(
             latest_version = None,
@@ -366,9 +356,4 @@ def _parse_current_version(current_version: str) -> Version | None:
 
 
 def _utc_now_iso() -> str:
-    return (
-        datetime.now(timezone.utc)
-        .replace(microsecond = 0)
-        .isoformat()
-        .replace("+00:00", "Z")
-    )
+    return datetime.now(timezone.utc).replace(microsecond = 0).isoformat().replace("+00:00", "Z")
diff --git a/studio/backend/utils/upload_limits.py b/studio/backend/utils/upload_limits.py
index b8a6a2474b..c21ea69af7 100644
--- a/studio/backend/utils/upload_limits.py
+++ b/studio/backend/utils/upload_limits.py
@@ -52,7 +52,6 @@ def validate_upload_limit_mb(value: Any) -> int:
 def get_upload_limit_mb() -> int:
     try:
         from storage.studio_db import get_app_setting
-
         stored = get_app_setting(UPLOAD_LIMIT_SETTING_KEY, None)
     except Exception:
         stored = None
diff --git a/studio/backend/utils/utils.py b/studio/backend/utils/utils.py
index e95ef08a7d..7a7774be40 100644
--- a/studio/backend/utils/utils.py
+++ b/studio/backend/utils/utils.py
@@ -22,9 +22,7 @@ logger = get_logger(__name__)
 # log the full exception server-side and return a generic message.
 
 
-def safe_error_detail(
-    error: Exception, fallback: str = "An internal error occurred"
-) -> str:
+def safe_error_detail(error: Exception, fallback: str = "An internal error occurred") -> str:
     """Map a caught exception to a generic, client-safe message.
 
     Never includes raw ``str(error)`` (which can leak internal paths or stack
@@ -44,9 +42,7 @@ def safe_error_detail(
     return fallback
 
 
-def safe_curated_detail(
-    error: Exception, fallback: str = "An internal error occurred"
-) -> str:
+def safe_curated_detail(error: Exception, fallback: str = "An internal error occurred") -> str:
     """Client-safe text for curated domain/validation exceptions meant for the user.
 
     Keeps the message (paths stripped) instead of a generic fallback; use for known
diff --git a/studio/backend/utils/wheel_utils.py b/studio/backend/utils/wheel_utils.py
index e0ce02261b..cca30bfd44 100644
--- a/studio/backend/utils/wheel_utils.py
+++ b/studio/backend/utils/wheel_utils.py
@@ -19,9 +19,7 @@ from utils.subprocess_compat import windows_hidden_subprocess_kwargs
 
 _logger = logging.getLogger(__name__)
 
-FLASH_ATTN_RELEASE_BASE_URL = (
-    "https://github.com/Dao-AILab/flash-attention/releases/download"
-)
+FLASH_ATTN_RELEASE_BASE_URL = "https://github.com/Dao-AILab/flash-attention/releases/download"
 
 
 @functools.lru_cache(maxsize = 1)
diff --git a/studio/install_llama_prebuilt.py b/studio/install_llama_prebuilt.py
index 62b7b2b290..09953843f0 100644
--- a/studio/install_llama_prebuilt.py
+++ b/studio/install_llama_prebuilt.py
@@ -70,7 +70,12 @@ def windows_hidden_subprocess_kwargs() -> dict[str, object]:
     return kwargs
 
 
-def env_int(name: str, default: int, *, minimum: int | None = None) -> int:
+def env_int(
+    name: str,
+    default: int,
+    *,
+    minimum: int | None = None,
+) -> int:
     raw = os.environ.get(name)
     if raw is None:
         value = default
@@ -104,9 +109,7 @@ UPSTREAM_REPO = "ggml-org/llama.cpp"
 UPSTREAM_RELEASES_API = f"https://api.github.com/repos/{UPSTREAM_REPO}/releases/latest"
 
 LEMONADE_ROCM_REPO = "lemonade-sdk/llamacpp-rocm"
-LEMONADE_ROCM_RELEASES_API = (
-    f"https://api.github.com/repos/{LEMONADE_ROCM_REPO}/releases/latest"
-)
+LEMONADE_ROCM_RELEASES_API = f"https://api.github.com/repos/{LEMONADE_ROCM_REPO}/releases/latest"
 
 
 def _lemonade_release_api_for(llama_tag: str) -> str:
@@ -135,9 +138,7 @@ def _lemonade_release_api_for(llama_tag: str) -> str:
     )
 
 
-TEST_MODEL_URL = (
-    "https://huggingface.co/ggml-org/models/resolve/main/tinyllamas/stories260K.gguf"
-)
+TEST_MODEL_URL = "https://huggingface.co/ggml-org/models/resolve/main/tinyllamas/stories260K.gguf"
 TEST_MODEL_SHA256 = "270cba1bd5109f42d03350f60406024560464db173c0e387d91f0426d3bd256d"
 VALIDATION_MODEL_CACHE_DIRNAME = ".cache"
 VALIDATION_MODEL_CACHE_FILENAME = "stories260K.gguf"
@@ -256,12 +257,8 @@ _BLACKWELL_MIN_SM = 120
 # windows-cuda build at or above this already covers Blackwell and makes the
 # older pinned 13.1 fallback unnecessary (cuda-12.4 is below it).
 _BLACKWELL_MIN_TOOLKIT = (12, 8)
-_PINNED_BLACKWELL_LLAMA_SHA256 = (
-    "31ddb8b42d7ab4a47cab8c48c397519f580ca502df7e73f3ab396eacc16c8e8d"
-)
-_PINNED_BLACKWELL_CUDART_SHA256 = (
-    "f96935e7e385e3b2d0189239077c10fe8fd7e95690fea4afec455b1b6c7e3f18"
-)
+_PINNED_BLACKWELL_LLAMA_SHA256 = "31ddb8b42d7ab4a47cab8c48c397519f580ca502df7e73f3ab396eacc16c8e8d"
+_PINNED_BLACKWELL_CUDART_SHA256 = "f96935e7e385e3b2d0189239077c10fe8fd7e95690fea4afec455b1b6c7e3f18"
 
 
 def _cuda_runtime_lines_for_major(major: int) -> list[str]:
@@ -279,9 +276,7 @@ def _resolve_linux_bundle_profile(bundle_profile: str) -> "dict[str, Any] | None
     known = DIRECT_LINUX_BUNDLE_PROFILES.get(bundle_profile)
     if known is not None:
         return known
-    m = re.fullmatch(
-        r"cuda(?P\d+)-(?Polder|newer|portable)", bundle_profile
-    )
+    m = re.fullmatch(r"cuda(?P\d+)-(?Polder|newer|portable)", bundle_profile)
     if not m:
         return None
     base_key = max(
@@ -788,9 +783,9 @@ def refs_match(candidate_ref: str | None, requested_ref: str | None) -> bool:
     candidate_commit = normalize_source_commit(candidate_ref)
     requested_commit = normalize_source_commit(requested_ref)
     if candidate_commit and requested_commit:
-        return candidate_commit.startswith(
-            requested_commit
-        ) or requested_commit.startswith(candidate_commit)
+        return candidate_commit.startswith(requested_commit) or requested_commit.startswith(
+            candidate_commit
+        )
     return False
 
 
@@ -820,9 +815,7 @@ def windows_cuda_upstream_asset_names(llama_tag: str, runtime: str) -> list[str]
 
 
 def windows_cuda_asset_aliases(
-    asset_name: str,
-    *,
-    compatibility_tag: str | None = None,
+    asset_name: str, *, compatibility_tag: str | None = None
 ) -> list[str]:
     aliases: list[str] = []
     legacy_match = re.fullmatch(
@@ -886,11 +879,7 @@ class DownloadProgress:
         self.last_emit = 0.0
         term_ok = os.environ.get("TERM", "").lower() != "dumb"
         self.stream = (
-            sys.stderr
-            if sys.stderr.isatty()
-            else sys.stdout
-            if sys.stdout.isatty()
-            else sys.stderr
+            sys.stderr if sys.stderr.isatty() else sys.stdout if sys.stdout.isatty() else sys.stderr
         )
         self.is_tty = term_ok and self.stream.isatty()
         self.completed = False
@@ -898,7 +887,12 @@ class DownloadProgress:
         self.last_milestone_bytes = 0
         self.has_rendered_tty_progress = False
 
-    def _render(self, downloaded_bytes: int, *, final: bool = False) -> str:
+    def _render(
+        self,
+        downloaded_bytes: int,
+        *,
+        final: bool = False,
+    ) -> str:
         elapsed = max(time.monotonic() - self.start_time, 1e-6)
         speed = downloaded_bytes / elapsed
         speed_text = f"{format_byte_count(speed)}/s"
@@ -918,10 +912,7 @@ class DownloadProgress:
         if self.is_tty:
             elapsed = now - self.start_time
             if not self.has_rendered_tty_progress:
-                if (
-                    self.total_bytes is not None
-                    and downloaded_bytes >= self.total_bytes
-                ):
+                if self.total_bytes is not None and downloaded_bytes >= self.total_bytes:
                     return
                 if elapsed < TTY_PROGRESS_START_DELAY_SECONDS:
                     return
@@ -943,10 +934,7 @@ class DownloadProgress:
         if self.total_bytes is not None:
             percent = int((downloaded_bytes * 100) / max(self.total_bytes, 1))
             milestone_percent = min((percent // 25) * 25, 100)
-            if (
-                milestone_percent > self.last_milestone_percent
-                and milestone_percent < 100
-            ):
+            if milestone_percent > self.last_milestone_percent and milestone_percent < 100:
                 self.last_milestone_percent = milestone_percent
                 should_emit = True
         else:
@@ -999,11 +987,7 @@ def download_bytes(
                 content_length = response.headers.get("Content-Length")
                 if content_length and content_length.isdigit():
                     total_bytes = int(content_length)
-                progress = (
-                    DownloadProgress(progress_label, total_bytes)
-                    if progress_label
-                    else None
-                )
+                progress = DownloadProgress(progress_label, total_bytes) if progress_label else None
                 data = bytearray()
                 while True:
                     chunk = response.read(1024 * 1024)
@@ -1033,17 +1017,13 @@ def fetch_json(url: str) -> Any:
             data = download_bytes(
                 url,
                 timeout = 30,
-                headers = github_api_headers(url)
-                if is_github_api_url(url)
-                else auth_headers(url),
+                headers = github_api_headers(url) if is_github_api_url(url) else auth_headers(url),
             )
         except urllib.error.HTTPError as exc:
             if exc.code == 403 and is_github_api_url(url):
                 hint = ""
                 if not (os.environ.get("GH_TOKEN") or os.environ.get("GITHUB_TOKEN")):
-                    hint = (
-                        "; set GH_TOKEN or GITHUB_TOKEN to avoid GitHub API rate limits"
-                    )
+                    hint = "; set GH_TOKEN or GITHUB_TOKEN to avoid GitHub API rate limits"
                 raise RuntimeError(f"GitHub API returned 403 for {url}{hint}") from exc
             raise
         if not data:
@@ -1052,9 +1032,7 @@ def fetch_json(url: str) -> Any:
             try:
                 payload = json.loads(data.decode("utf-8"))
             except (UnicodeDecodeError, json.JSONDecodeError) as exc:
-                last_decode_exc = RuntimeError(
-                    f"downloaded invalid JSON from {url}: {exc}"
-                )
+                last_decode_exc = RuntimeError(f"downloaded invalid JSON from {url}: {exc}")
             else:
                 if not isinstance(payload, dict) and not isinstance(payload, list):
                     raise RuntimeError(
@@ -1088,9 +1066,7 @@ def download_file(url: str, destination: Path) -> None:
                     content_length = response.headers.get("Content-Length")
                     if content_length and content_length.isdigit():
                         total_bytes = int(content_length)
-                    progress = DownloadProgress(
-                        f"Downloading {destination.name}", total_bytes
-                    )
+                    progress = DownloadProgress(f"Downloading {destination.name}", total_bytes)
                     downloaded_bytes = 0
                     while True:
                         chunk = response.read(1024 * 1024)
@@ -1115,27 +1091,19 @@ def download_file(url: str, destination: Path) -> None:
                     pass
             if attempt >= HTTP_FETCH_ATTEMPTS or not is_retryable_url_error(exc):
                 raise
-            log(
-                f"download failed ({attempt}/{HTTP_FETCH_ATTEMPTS}) for {url}: {exc}; retrying"
-            )
+            log(f"download failed ({attempt}/{HTTP_FETCH_ATTEMPTS}) for {url}: {exc}; retrying")
             sleep_backoff(attempt, exc = exc)
     assert last_exc is not None
     raise last_exc
 
 
 def download_file_verified(
-    url: str,
-    destination: Path,
-    *,
-    expected_sha256: str | None,
-    label: str,
+    url: str, destination: Path, *, expected_sha256: str | None, label: str
 ) -> None:
     normalized_expected = normalize_sha256_digest(expected_sha256)
     if not normalized_expected:
         download_file(url, destination)
-        log(
-            f"downloaded {label} without a published sha256; relying on install validation"
-        )
+        log(f"downloaded {label} without a published sha256; relying on install validation")
         return
 
     for attempt in range(1, 3):
@@ -1219,9 +1187,7 @@ def latest_upstream_release_tag() -> str:
     payload = fetch_json(UPSTREAM_RELEASES_API)
     tag = payload.get("tag_name")
     if not isinstance(tag, str) or not tag:
-        raise RuntimeError(
-            f"latest release tag was missing from {UPSTREAM_RELEASES_API}"
-        )
+        raise RuntimeError(f"latest release tag was missing from {UPSTREAM_RELEASES_API}")
     return tag
 
 
@@ -1256,19 +1222,13 @@ def iter_release_payloads_by_time(
         yield github_release(repo, published_release_tag)
         return
 
-    if (
-        requested_tag
-        and requested_tag != "latest"
-        and is_release_tag_like(requested_tag)
-    ):
+    if requested_tag and requested_tag != "latest" and is_release_tag_like(requested_tag):
         try:
             yield github_release(repo, requested_tag)
             return
         except urllib.error.HTTPError as exc:
             if exc.code == 404:
-                log(
-                    f"release tag {requested_tag} not found in {repo}; scanning recent releases"
-                )
+                log(f"release tag {requested_tag} not found in {repo}; scanning recent releases")
             else:
                 raise
         except Exception:
@@ -1276,21 +1236,15 @@ def iter_release_payloads_by_time(
 
     releases = [
         release
-        for release in github_releases(
-            repo, max_pages = DEFAULT_GITHUB_RELEASE_SCAN_MAX_PAGES
-        )
-        if isinstance(release, dict)
-        and not release.get("draft")
-        and not release.get("prerelease")
+        for release in github_releases(repo, max_pages = DEFAULT_GITHUB_RELEASE_SCAN_MAX_PAGES)
+        if isinstance(release, dict) and not release.get("draft") and not release.get("prerelease")
     ]
     releases.sort(key = release_time_sort_key, reverse = True)
     for release in releases:
         yield release
 
 
-def direct_release_matches_request(
-    *, release_tag: str, llama_tag: str, requested_tag: str
-) -> bool:
+def direct_release_matches_request(*, release_tag: str, llama_tag: str, requested_tag: str) -> bool:
     if requested_tag == "latest":
         return True
     for candidate in (release_tag, llama_tag):
@@ -1392,10 +1346,7 @@ def parse_direct_linux_release_bundle(
 
 
 def direct_linux_release_plan(
-    release: dict[str, Any],
-    host: HostInfo,
-    repo: str,
-    requested_tag: str,
+    release: dict[str, Any], host: HostInfo, repo: str, requested_tag: str
 ) -> InstallReleasePlan | None:
     bundle = parse_direct_linux_release_bundle(repo, release)
     if bundle is None:
@@ -1477,10 +1428,7 @@ def direct_linux_release_plan(
 
 
 def direct_upstream_release_plan(
-    release: dict[str, Any],
-    host: HostInfo,
-    repo: str,
-    requested_tag: str,
+    release: dict[str, Any], host: HostInfo, repo: str, requested_tag: str
 ) -> InstallReleasePlan | None:
     release_tag = release.get("tag_name")
     if not isinstance(release_tag, str) or not release_tag:
@@ -1674,9 +1622,7 @@ def resolve_simple_install_release_plans(
             f"{repo} ships only linux-x64 prebuilts; "
             f"{host.machine or 'non-x64'} Linux falls back to source build"
         )
-    allow_older_release_fallback = (
-        requested_tag == "latest" and not published_release_tag
-    )
+    allow_older_release_fallback = requested_tag == "latest" and not published_release_tag
     # macOS: pin the last upstream build that loads on a pre-26 host instead of
     # fetching the latest (macOS 26 only) build and walking back release by
     # release. No-op on macOS 26+, unknown version, non-macOS, and the fork.
@@ -1690,17 +1636,13 @@ def resolve_simple_install_release_plans(
     last_error: PrebuiltFallback | None = None
 
     try:
-        releases = iter_release_payloads_by_time(
-            repo, published_release_tag, requested_tag
-        )
+        releases = iter_release_payloads_by_time(repo, published_release_tag, requested_tag)
         for release in releases:
             try:
                 if host.is_linux and repo == "unslothai/llama.cpp":
                     plan = direct_linux_release_plan(release, host, repo, requested_tag)
                 else:
-                    plan = direct_upstream_release_plan(
-                        release, host, repo, requested_tag
-                    )
+                    plan = direct_upstream_release_plan(release, host, repo, requested_tag)
                 if plan is None:
                     continue
             except PrebuiltFallback as exc:
@@ -1720,17 +1662,13 @@ def resolve_simple_install_release_plans(
     except PrebuiltFallback:
         raise
     except Exception as exc:
-        raise PrebuiltFallback(
-            f"failed to inspect published releases in {repo}: {exc}"
-        ) from exc
+        raise PrebuiltFallback(f"failed to inspect published releases in {repo}: {exc}") from exc
 
     if plans:
         return requested_tag, plans
     if last_error is not None:
         raise last_error
-    raise PrebuiltFallback(
-        f"no installable published llama.cpp releases were found in {repo}"
-    )
+    raise PrebuiltFallback(f"no installable published llama.cpp releases were found in {repo}")
 
 
 def normalized_requested_llama_tag(requested_tag: str | None) -> str:
@@ -1782,9 +1720,7 @@ def parse_cuda_visible_devices(value: str | None) -> list[str] | None:
     return [token.strip() for token in raw.split(",") if token.strip()]
 
 
-def supports_explicit_visible_device_matching(
-    visible_devices: list[str] | None,
-) -> bool:
+def supports_explicit_visible_device_matching(visible_devices: list[str] | None) -> bool:
     if not visible_devices:
         return False
     for token in visible_devices:
@@ -1796,8 +1732,7 @@ def supports_explicit_visible_device_matching(
 
 
 def select_visible_gpu_rows(
-    gpu_rows: Iterable[tuple[str, str, str]],
-    visible_devices: list[str] | None,
+    gpu_rows: Iterable[tuple[str, str, str]], visible_devices: list[str] | None
 ) -> list[tuple[str, str, str]]:
     rows = list(gpu_rows)
     if visible_devices is None:
@@ -1835,9 +1770,7 @@ def dir_provides_exact_library(directory: str | Path, library: str) -> bool:
     return candidate.exists() and (candidate.is_file() or candidate.is_symlink())
 
 
-def linux_runtime_dirs_for_required_libraries(
-    required_libraries: Iterable[str],
-) -> list[str]:
+def linux_runtime_dirs_for_required_libraries(required_libraries: Iterable[str]) -> list[str]:
     required = [library for library in required_libraries if library]
     candidates: list[str | Path] = []
 
@@ -1853,9 +1786,7 @@ def linux_runtime_dirs_for_required_libraries(
         value = os.environ.get(name)
         if value:
             cuda_roots.append(Path(value))
-    cuda_roots.extend(
-        Path(path) for path in glob_paths("/usr/local/cuda", "/usr/local/cuda-*")
-    )
+    cuda_roots.extend(Path(path) for path in glob_paths("/usr/local/cuda", "/usr/local/cuda-*"))
 
     for root in cuda_roots:
         candidates.extend(
@@ -1880,8 +1811,7 @@ def linux_runtime_dirs_for_required_libraries(
         )
     )
     candidates.extend(
-        Path(path)
-        for path in glob_paths("/usr/local/lib/ollama/cuda_v*", "/usr/lib/wsl/lib")
+        Path(path) for path in glob_paths("/usr/local/lib/ollama/cuda_v*", "/usr/lib/wsl/lib")
     )
     candidates.extend(Path(path) for path in python_runtime_dirs())
     candidates.extend(Path(path) for path in ldconfig_runtime_dirs(required))
@@ -1893,9 +1823,7 @@ def linux_runtime_dirs_for_required_libraries(
     matched: list[tuple[int, str]] = []
     for directory in resolved:
         base = Path(directory)
-        provided = sum(
-            1 for library in required if dir_provides_exact_library(directory, library)
-        )
+        provided = sum(1 for library in required if dir_provides_exact_library(directory, library))
         if provided:
             matched.append((provided, directory))
 
@@ -1916,9 +1844,7 @@ def detected_linux_runtime_lines() -> tuple[list[str], dict[str, list[str]]]:
         matching_dirs: list[str] = []
         for library in required:
             matched_dirs = [
-                directory
-                for directory in dirs
-                if any(Path(directory).glob(f"{library}*"))
+                directory for directory in dirs if any(Path(directory).glob(f"{library}*"))
             ]
             if not matched_dirs:
                 library_matches = {}
@@ -1955,17 +1881,13 @@ def parse_published_artifact(raw: Any) -> PublishedLlamaArtifact | None:
     if not isinstance(asset_name, str) or not asset_name:
         raise ValueError("artifact.asset_name was missing or not a string")
     if not isinstance(install_kind, str) or not install_kind:
-        raise ValueError(
-            f"artifact {asset_name} install_kind was missing or not a string"
-        )
+        raise ValueError(f"artifact {asset_name} install_kind was missing or not a string")
 
     supported_sms_raw = raw.get("supported_sms", [])
     if not isinstance(supported_sms_raw, (list, tuple)):
         raise ValueError(f"artifact {asset_name} supported_sms must be a list or tuple")
     if any(not isinstance(value, (int, str)) for value in supported_sms_raw):
-        raise ValueError(
-            f"artifact {asset_name} supported_sms entries must be ints or strings"
-        )
+        raise ValueError(f"artifact {asset_name} supported_sms entries must be ints or strings")
     supported_sms = normalize_compute_caps(supported_sms_raw)
 
     min_sm_raw = raw.get("min_sm")
@@ -1974,9 +1896,7 @@ def parse_published_artifact(raw: Any) -> PublishedLlamaArtifact | None:
         min_sm = int(min_sm_raw) if min_sm_raw is not None else None
         max_sm = int(max_sm_raw) if max_sm_raw is not None else None
     except (TypeError, ValueError) as exc:
-        raise ValueError(
-            f"artifact {asset_name} min_sm/max_sm were not integers"
-        ) from exc
+        raise ValueError(f"artifact {asset_name} min_sm/max_sm were not integers") from exc
     runtime_line = raw.get("runtime_line")
     coverage_class = raw.get("coverage_class")
     bundle_profile = raw.get("bundle_profile")
@@ -1994,9 +1914,7 @@ def parse_published_artifact(raw: Any) -> PublishedLlamaArtifact | None:
     return PublishedLlamaArtifact(
         asset_name = asset_name,
         install_kind = install_kind,
-        runtime_line = runtime_line
-        if isinstance(runtime_line, str) and runtime_line
-        else None,
+        runtime_line = runtime_line if isinstance(runtime_line, str) and runtime_line else None,
         coverage_class = coverage_class
         if isinstance(coverage_class, str) and coverage_class
         else None,
@@ -2071,9 +1989,7 @@ def parse_published_release_bundle(
         try:
             artifact = parse_published_artifact(raw_artifact)
         except ValueError as exc:
-            log(
-                f"published artifact ignored for {repo}@{release_tag} artifact[{index}]: {exc}"
-            )
+            log(f"published artifact ignored for {repo}@{release_tag} artifact[{index}]: {exc}")
             continue
         if artifact is not None:
             artifacts.append(artifact)
@@ -2092,9 +2008,7 @@ def parse_published_release_bundle(
         release_tag = release_tag,
         upstream_tag = upstream_tag,
         manifest_sha256 = manifest_sha256,
-        source_repo = source_repo
-        if isinstance(source_repo, str) and source_repo
-        else None,
+        source_repo = source_repo if isinstance(source_repo, str) and source_repo else None,
         source_repo_url = source_repo_url
         if isinstance(source_repo_url, str) and source_repo_url
         else None,
@@ -2117,9 +2031,7 @@ def parse_published_release_bundle(
 
 
 def parse_approved_release_checksums(
-    repo: str,
-    release_tag: str,
-    payload: Any,
+    repo: str, release_tag: str, payload: Any
 ) -> ApprovedReleaseChecksums:
     if not isinstance(payload, dict):
         raise RuntimeError(
@@ -2157,18 +2069,12 @@ def parse_approved_release_checksums(
     artifacts: dict[str, ApprovedArtifactHash] = {}
     for asset_name, raw_entry in artifacts_payload.items():
         if not isinstance(asset_name, str) or not asset_name:
-            raise RuntimeError(
-                "published checksum asset used a non-string artifact key"
-            )
+            raise RuntimeError("published checksum asset used a non-string artifact key")
         if not isinstance(raw_entry, dict):
-            raise RuntimeError(
-                f"published checksum entry for {asset_name} was not an object"
-            )
+            raise RuntimeError(f"published checksum entry for {asset_name} was not an object")
         digest = normalize_sha256_digest(raw_entry.get("sha256"))
         if not digest:
-            raise RuntimeError(
-                f"published checksum entry for {asset_name} omitted a valid sha256"
-            )
+            raise RuntimeError(f"published checksum entry for {asset_name} omitted a valid sha256")
         repo_value = raw_entry.get("repo")
         kind_value = raw_entry.get("kind")
         artifacts[asset_name] = ApprovedArtifactHash(
@@ -2189,9 +2095,7 @@ def parse_approved_release_checksums(
         repo = repo,
         release_tag = release_tag,
         upstream_tag = upstream_tag,
-        source_repo = source_repo
-        if isinstance(source_repo, str) and source_repo
-        else None,
+        source_repo = source_repo if isinstance(source_repo, str) and source_repo else None,
         source_repo_url = source_repo_url
         if isinstance(source_repo_url, str) and source_repo_url
         else None,
@@ -2210,9 +2114,7 @@ def parse_approved_release_checksums(
     )
 
 
-def load_approved_release_checksums(
-    repo: str, release_tag: str
-) -> ApprovedReleaseChecksums:
+def load_approved_release_checksums(repo: str, release_tag: str) -> ApprovedReleaseChecksums:
     try:
         release = github_release(repo, release_tag)
     except Exception as exc:
@@ -2246,9 +2148,7 @@ def iter_published_release_bundles(
         else github_releases(repo, max_pages = DEFAULT_GITHUB_RELEASE_SCAN_MAX_PAGES)
     )
     for release in releases:
-        if not published_release_tag and (
-            release.get("draft") or release.get("prerelease")
-        ):
+        if not published_release_tag and (release.get("draft") or release.get("prerelease")):
             continue
         try:
             bundle = parse_published_release_bundle(repo, release)
@@ -2301,13 +2201,9 @@ def linux_cuda_choice_from_release(
             )
         )
     published_artifacts = [
-        artifact
-        for artifact in release.artifacts
-        if artifact.install_kind == "linux-cuda"
+        artifact for artifact in release.artifacts if artifact.install_kind == "linux-cuda"
     ]
-    published_asset_names = sorted(
-        artifact.asset_name for artifact in published_artifacts
-    )
+    published_asset_names = sorted(artifact.asset_name for artifact in published_artifacts)
     selection_log.append(
         "linux_cuda_selection: published_assets="
         + (",".join(published_asset_names) if published_asset_names else "none")
@@ -2343,9 +2239,7 @@ def linux_cuda_choice_from_release(
     attempts: list[AssetChoice] = []
     seen_attempts: set[str] = set()
 
-    def add_attempt(
-        artifact: PublishedLlamaArtifact, asset_url: str, reason: str
-    ) -> None:
+    def add_attempt(artifact: PublishedLlamaArtifact, asset_url: str, reason: str) -> None:
         asset_name = artifact.asset_name
         if asset_name in seen_attempts:
             return
@@ -2382,9 +2276,7 @@ def linux_cuda_choice_from_release(
             asset_name = artifact.asset_name
             asset_url = release.assets.get(asset_name)
             if not asset_url:
-                selection_log.append(
-                    f"linux_cuda_selection: reject {asset_name} missing asset"
-                )
+                selection_log.append(f"linux_cuda_selection: reject {asset_name} missing asset")
                 continue
             if not host_sms and artifact.coverage_class != "portable":
                 selection_log.append(
@@ -2412,9 +2304,7 @@ def linux_cuda_choice_from_release(
             supported_sms = {str(value) for value in artifact.supported_sms}
             missing_sms = [sm for sm in host_sms if sm not in supported_sms]
             out_of_range_sms = [
-                sm
-                for sm in host_sms
-                if not (artifact.min_sm <= int(sm) <= artifact.max_sm)
+                sm for sm in host_sms if not (artifact.min_sm <= int(sm) <= artifact.max_sm)
             ]
             reasons: list[str] = []
             if missing_sms:
@@ -2458,8 +2348,7 @@ def linux_cuda_choice_from_release(
         return None
 
     selection_log.append(
-        "linux_cuda_selection: attempt_order="
-        + ",".join(choice.name for choice in attempts)
+        "linux_cuda_selection: attempt_order=" + ",".join(choice.name for choice in attempts)
     )
     for attempt in attempts:
         attempt.selection_log = list(selection_log) + [
@@ -2477,9 +2366,7 @@ def latest_published_linux_cuda_tag(host: HostInfo, published_repo: str) -> str
 
 
 def iter_upstream_releases() -> Iterable[dict[str, Any]]:
-    for release in github_releases(
-        UPSTREAM_REPO, max_pages = DEFAULT_GITHUB_RELEASE_SCAN_MAX_PAGES
-    ):
+    for release in github_releases(UPSTREAM_REPO, max_pages = DEFAULT_GITHUB_RELEASE_SCAN_MAX_PAGES):
         if release.get("draft") or release.get("prerelease"):
             continue
         yield release
@@ -2514,9 +2401,7 @@ def validated_checksums_for_bundle(
     return checksums
 
 
-def published_release_matches_request(
-    bundle: PublishedReleaseBundle, requested_ref: str
-) -> bool:
+def published_release_matches_request(bundle: PublishedReleaseBundle, requested_ref: str) -> bool:
     if requested_ref == "latest":
         return True
     for candidate in (
@@ -2571,9 +2456,7 @@ def resolve_published_release(
             raise PrebuiltFallback(
                 f"no usable published llama.cpp releases were available in {repo}"
             )
-        raise PrebuiltFallback(
-            f"no published llama.cpp releases were available in {repo}"
-        )
+        raise PrebuiltFallback(f"no published llama.cpp releases were available in {repo}")
 
     raise PrebuiltFallback(
         f"no published prebuilt release in {repo} matched upstream tag {normalized_requested}"
@@ -2632,9 +2515,7 @@ def iter_resolved_published_releases(
         return
 
     if normalized_requested == "latest":
-        raise PrebuiltFallback(
-            f"no published llama.cpp releases were available in {repo}"
-        )
+        raise PrebuiltFallback(f"no published llama.cpp releases were available in {repo}")
 
     raise PrebuiltFallback(
         f"no published prebuilt release in {repo} matched upstream tag {normalized_requested}"
@@ -2692,33 +2573,23 @@ def resolve_requested_install_tag(
     ).bundle.upstream_tag
 
 
-def exact_source_archive_hash(
-    checksums: ApprovedReleaseChecksums,
-) -> ApprovedArtifactHash | None:
+def exact_source_archive_hash(checksums: ApprovedReleaseChecksums) -> ApprovedArtifactHash | None:
     if not checksums.source_commit:
         return None
-    return checksums.artifacts.get(
-        exact_source_archive_logical_name(checksums.source_commit)
-    )
+    return checksums.artifacts.get(exact_source_archive_logical_name(checksums.source_commit))
 
 
 def source_clone_url_from_checksums(checksums: ApprovedReleaseChecksums) -> str | None:
     return source_repo_clone_url(checksums.source_repo, checksums.source_repo_url)
 
 
-def source_build_plan_for_release(
-    release: ResolvedPublishedRelease,
-) -> SourceBuildPlan:
+def source_build_plan_for_release(release: ResolvedPublishedRelease) -> SourceBuildPlan:
     checksums = release.checksums
     exact_source = exact_source_archive_hash(checksums)
     source_repo = checksums.source_repo or release.bundle.source_repo
     source_repo_url = checksums.source_repo_url or release.bundle.source_repo_url
-    requested_source_ref = (
-        checksums.requested_source_ref or release.bundle.requested_source_ref
-    )
-    resolved_source_ref = (
-        checksums.resolved_source_ref or release.bundle.resolved_source_ref
-    )
+    requested_source_ref = checksums.requested_source_ref or release.bundle.requested_source_ref
+    resolved_source_ref = checksums.resolved_source_ref or release.bundle.resolved_source_ref
     source_commit = checksums.source_commit or release.bundle.source_commit
     source_ref_kind = checksums.source_ref_kind or release.bundle.source_ref_kind
     source_url = source_repo_clone_url(source_repo, source_repo_url)
@@ -2734,14 +2605,8 @@ def source_build_plan_for_release(
             resolved_source_ref = resolved_source_ref,
             source_commit = source_commit,
         )
-    source_ref = checkout_friendly_ref(
-        source_ref_kind, resolved_source_ref or requested_source_ref
-    )
-    if (
-        source_url
-        and source_ref
-        and source_ref_kind in {"tag", "branch", "pull", "commit"}
-    ):
+    source_ref = checkout_friendly_ref(source_ref_kind, resolved_source_ref or requested_source_ref)
+    if source_url and source_ref and source_ref_kind in {"tag", "branch", "pull", "commit"}:
         return SourceBuildPlan(
             source_url = source_url,
             source_ref = source_ref,
@@ -2925,9 +2790,7 @@ def detect_host() -> HostInfo:
         # ROCm host as NVIDIA and short-circuit the ROCm path.
         try:
             listing = run_capture([nvidia_smi, "-L"], timeout = 20)
-            gpu_lines = [
-                line for line in listing.stdout.splitlines() if line.startswith("GPU ")
-            ]
+            gpu_lines = [line for line in listing.stdout.splitlines() if line.startswith("GPU ")]
             if gpu_lines:
                 has_physical_nvidia = True
                 has_usable_nvidia = visible_device_tokens != []
@@ -3225,9 +3088,7 @@ def detect_torch_cuda_runtime_preference(host: HostInfo) -> CudaRuntimePreferenc
     try:
         cuda_available = bool(torch.cuda.is_available())
     except Exception as exc:
-        selection_log.append(
-            f"torch_cuda_preference: torch.cuda.is_available() failed: {exc}"
-        )
+        selection_log.append(f"torch_cuda_preference: torch.cuda.is_available() failed: {exc}")
         return CudaRuntimePreference(runtime_line = None, selection_log = selection_log)
 
     if not cuda_available:
@@ -3315,14 +3176,10 @@ def windows_cuda_attempts(
             f"{preferred_runtime_line} unavailable_or_incompatible"
         )
     else:
-        selection_log.append(
-            "windows_cuda_selection: no Torch runtime preference available"
-        )
+        selection_log.append("windows_cuda_selection: no Torch runtime preference available")
 
     runtime_order.extend(
-        runtime_line
-        for runtime_line in normal_runtime_lines
-        if runtime_line not in runtime_order
+        runtime_line for runtime_line in normal_runtime_lines if runtime_line not in runtime_order
     )
     # Keep every driver-compatible line reachable as a fallback, so a line gated
     # out by the driver version still drops to an older major (cuda13 -> cuda12).
@@ -3346,9 +3203,7 @@ def windows_cuda_attempts(
         # Track whatever minor llama.cpp actually ships for this major
         # (cuda13 -> 13.1, 13.3, ...). Skip the line when the release has no
         # matching asset instead of guessing a now-missing name.
-        runtime = _published_windows_cuda_runtime(
-            upstream_assets, major, host.driver_cuda_version
-        )
+        runtime = _published_windows_cuda_runtime(upstream_assets, major, host.driver_cuda_version)
         if runtime is None:
             selection_log.append(
                 f"windows_cuda_selection: no driver-supported asset for {runtime_line}"
@@ -3414,9 +3269,7 @@ def _windows_cuda_attempt_covers_blackwell(attempt: AssetChoice) -> bool:
     if attempt.install_kind != "windows-cuda":
         return False
     m = re.search(r"-bin-win-cuda-(\d+)\.(\d+)-x64\.zip$", attempt.name)
-    return (
-        m is not None and (int(m.group(1)), int(m.group(2))) >= _BLACKWELL_MIN_TOOLKIT
-    )
+    return m is not None and (int(m.group(1)), int(m.group(2))) >= _BLACKWELL_MIN_TOOLKIT
 
 
 def _pinned_windows_cuda_fallback(
@@ -3441,10 +3294,7 @@ def _pinned_windows_cuda_fallback(
     caps = normalize_compute_caps(host.compute_caps)
     if not caps or int(caps[-1]) < _BLACKWELL_MIN_SM:
         return None
-    if any(
-        _windows_cuda_attempt_covers_blackwell(attempt)
-        for attempt in existing_cuda_attempts
-    ):
+    if any(_windows_cuda_attempt_covers_blackwell(attempt) for attempt in existing_cuda_attempts):
         return None
     tag = _PINNED_BLACKWELL_FALLBACK_TAG
     runtime = _PINNED_BLACKWELL_FALLBACK_RUNTIME
@@ -3499,9 +3349,7 @@ def _augment_checksums_with_pin(
 
 
 def _with_pinned_windows_cuda_fallback(
-    host: HostInfo,
-    attempts: list[AssetChoice],
-    checksums: ApprovedReleaseChecksums,
+    host: HostInfo, attempts: list[AssetChoice], checksums: ApprovedReleaseChecksums
 ) -> tuple[list[AssetChoice], ApprovedReleaseChecksums]:
     """Insert the Blackwell pin ahead of the Windows CUDA attempts and keep it
     through apply_approved_hashes, or return the inputs unchanged when dormant.
@@ -3544,9 +3392,7 @@ def published_windows_cuda_attempts(
         selection_log,
     )
     published_artifacts = [
-        artifact
-        for artifact in release.artifacts
-        if artifact.install_kind == "windows-cuda"
+        artifact for artifact in release.artifacts if artifact.install_kind == "windows-cuda"
     ]
     artifacts_by_runtime: dict[str, list[PublishedLlamaArtifact]] = {}
     for artifact in published_artifacts:
@@ -3642,15 +3488,10 @@ def resolve_linux_cuda_choice(
 
 
 def published_asset_choice_for_kind(
-    release: PublishedReleaseBundle,
-    install_kind: str,
+    release: PublishedReleaseBundle, install_kind: str
 ) -> AssetChoice | None:
     candidates = sorted(
-        (
-            artifact
-            for artifact in release.artifacts
-            if artifact.install_kind == install_kind
-        ),
+        (artifact for artifact in release.artifacts if artifact.install_kind == install_kind),
         key = lambda artifact: (artifact.rank, artifact.asset_name),
     )
     for artifact in candidates:
@@ -3666,9 +3507,7 @@ def published_asset_choice_for_kind(
             install_kind = install_kind,
             runtime_line = artifact.runtime_line,
             selection_log = list(release.selection_log)
-            + [
-                f"published_selection: selected {artifact.asset_name} install_kind={install_kind}"
-            ],
+            + [f"published_selection: selected {artifact.asset_name} install_kind={install_kind}"],
         )
     return None
 
@@ -3725,11 +3564,7 @@ def _detect_host_rocm_version() -> tuple[int, int] | None:
             if result.returncode == 0:
                 raw = (result.stdout or "").strip().split("\n")[0]
                 parts = raw.split(".")
-                if (
-                    len(parts) >= 2
-                    and parts[0].isdigit()
-                    and parts[1].split("-")[0].isdigit()
-                ):
+                if len(parts) >= 2 and parts[0].isdigit() and parts[1].split("-")[0].isdigit():
                     return int(parts[0]), int(parts[1].split("-")[0])
         except Exception:
             pass
@@ -3888,9 +3723,7 @@ def resolve_lemonade_rocm_choice(
         return None
     release_tag = release.get("tag_name") if isinstance(release, dict) else None
     if not isinstance(release_tag, str) or not release_tag:
-        log(
-            f"Unexpected {LEMONADE_ROCM_REPO} release payload; skipping lemonade prebuilt"
-        )
+        log(f"Unexpected {LEMONADE_ROCM_REPO} release payload; skipping lemonade prebuilt")
         return None
     assets = release_asset_map(release)
     asset_name = f"llama-{release_tag}-{os_prefix}-rocm-{gfx_family}-x64.zip"
@@ -3986,9 +3819,7 @@ def resolve_upstream_asset_choice(host: HostInfo, llama_tag: str) -> AssetChoice
             _compatible: list[tuple[tuple[int, ...], str]] = rocm_candidates
             if _host_rocm_version is not None:
                 _compatible = [
-                    item
-                    for item in rocm_candidates
-                    if item[0][:2] <= _host_rocm_version
+                    item for item in rocm_candidates if item[0][:2] <= _host_rocm_version
                 ]
             if rocm_candidates and not _compatible:
                 # Fall back to the newest candidate so a source build is
@@ -4052,9 +3883,7 @@ def resolve_upstream_asset_choice(host: HostInfo, llama_tag: str) -> AssetChoice
 
             hip_name = f"llama-{llama_tag}-bin-win-hip-radeon-x64.zip"
             if hip_name in upstream_assets:
-                log(
-                    f"AMD ROCm detected on Windows -- trying upstream HIP prebuilt {hip_name}"
-                )
+                log(f"AMD ROCm detected on Windows -- trying upstream HIP prebuilt {hip_name}")
                 return AssetChoice(
                     repo = UPSTREAM_REPO,
                     tag = llama_tag,
@@ -4063,9 +3892,7 @@ def resolve_upstream_asset_choice(host: HostInfo, llama_tag: str) -> AssetChoice
                     source_label = "upstream",
                     install_kind = "windows-hip",
                 )
-            log(
-                "AMD ROCm detected on Windows but no HIP prebuilt found -- falling back to CPU"
-            )
+            log("AMD ROCm detected on Windows but no HIP prebuilt found -- falling back to CPU")
 
         upstream_name = f"llama-{llama_tag}-bin-win-cpu-x64.zip"
         if upstream_name not in upstream_assets:
@@ -4105,9 +3932,7 @@ def resolve_upstream_asset_choice(host: HostInfo, llama_tag: str) -> AssetChoice
             install_kind = "macos-x64",
         )
 
-    raise PrebuiltFallback(
-        f"no prebuilt policy exists for {host.system} {host.machine}"
-    )
+    raise PrebuiltFallback(f"no prebuilt policy exists for {host.system} {host.machine}")
 
 
 def resolve_asset_choice(host: HostInfo, llama_tag: str) -> AssetChoice:
@@ -4185,18 +4010,14 @@ def extract_archive(archive_path: Path, destination: Path) -> None:
         normalized = member_name.replace("\\", "/")
         member_path = Path(normalized)
         if member_path.is_absolute():
-            raise PrebuiltFallback(
-                f"archive member used an absolute path: {member_name}"
-            )
+            raise PrebuiltFallback(f"archive member used an absolute path: {member_name}")
 
         target = (base / member_path).resolve()
         base_resolved = base.resolve()
         try:
             target.relative_to(base_resolved)
         except ValueError as exc:
-            raise PrebuiltFallback(
-                f"archive member escaped destination: {member_name}"
-            ) from exc
+            raise PrebuiltFallback(f"archive member escaped destination: {member_name}") from exc
         return target
 
     def _try_repair_missing_slash(
@@ -4242,11 +4063,7 @@ def extract_archive(archive_path: Path, destination: Path) -> None:
         return candidates[0][len(prefix) :]
 
     def safe_link_target(
-        base: Path,
-        member_name: str,
-        link_name: str,
-        target: Path,
-        archive_names: set[str],
+        base: Path, member_name: str, link_name: str, target: Path, archive_names: set[str]
     ) -> tuple[str, Path]:
         normalized = link_name.replace("\\", "/")
         repaired = _try_repair_missing_slash(member_name, normalized, archive_names)
@@ -4306,9 +4123,7 @@ def extract_archive(archive_path: Path, destination: Path) -> None:
                 target.parent.mkdir(parents = True, exist_ok = True)
                 extracted = archive.extractfile(member)
                 if extracted is None:
-                    raise PrebuiltFallback(
-                        f"tar archive entry could not be read: {member.name}"
-                    )
+                    raise PrebuiltFallback(f"tar archive entry could not be read: {member.name}")
                 with extracted, target.open("wb") as dst:
                     shutil.copyfileobj(extracted, dst)
 
@@ -4342,9 +4157,7 @@ def extract_archive(archive_path: Path, destination: Path) -> None:
                 details = ", ".join(
                     f"{member.name} -> {member.linkname}" for member, _ in next_round
                 )
-                raise PrebuiltFallback(
-                    f"tar archive contained unresolved link entries: {details}"
-                )
+                raise PrebuiltFallback(f"tar archive contained unresolved link entries: {details}")
             unresolved = next_round
 
     destination.mkdir(parents = True, exist_ok = True)
@@ -4358,7 +4171,11 @@ def extract_archive(archive_path: Path, destination: Path) -> None:
 
 
 def copy_globs(
-    source_dir: Path, destination: Path, patterns: list[str], *, required: bool = True
+    source_dir: Path,
+    destination: Path,
+    patterns: list[str],
+    *,
+    required: bool = True,
 ) -> None:
     destination.mkdir(parents = True, exist_ok = True)
     matched_sources: dict[str, Path] = {}
@@ -4457,9 +4274,7 @@ def hydrate_source_tree(
         for index, source_url in enumerate(source_urls):
             try:
                 if index > 0:
-                    log(
-                        f"retrying source tree download from fallback URL: {source_url}"
-                    )
+                    log(f"retrying source tree download from fallback URL: {source_url}")
                 download_file_verified(
                     source_url,
                     archive_path,
@@ -4484,14 +4299,11 @@ def hydrate_source_tree(
             source_root / "gguf-py",
         ]
         missing = [
-            str(path.relative_to(source_root))
-            for path in required_paths
-            if not path.exists()
+            str(path.relative_to(source_root)) for path in required_paths if not path.exists()
         ]
         if missing:
             raise PrebuiltFallback(
-                "upstream source archive was missing required repo files: "
-                + ", ".join(missing)
+                "upstream source archive was missing required repo files: " + ", ".join(missing)
             )
         copy_directory_contents(source_root, install_dir)
     except PrebuiltFallback:
@@ -4518,9 +4330,7 @@ def discover_installed_executable(install_dir: Path, executable_name: str) -> Pa
     direct = install_dir / executable_name
     if direct.exists() and direct.is_file():
         return direct
-    candidate = next(
-        (path for path in install_dir.rglob(executable_name) if path.is_file()), None
-    )
+    candidate = next((path for path in install_dir.rglob(executable_name) if path.is_file()), None)
     if candidate is None:
         raise PrebuiltFallback(f"{executable_name} was not installed")
     return candidate
@@ -4550,9 +4360,7 @@ def create_exec_entrypoint(entrypoint: Path, target: Path) -> None:
         write_exec_wrapper(entrypoint, target)
 
 
-def overlay_directory_for_choice(
-    install_dir: Path, choice: AssetChoice, host: HostInfo
-) -> Path:
+def overlay_directory_for_choice(install_dir: Path, choice: AssetChoice, host: HostInfo) -> Path:
     if host.is_windows or choice.install_kind.startswith("windows"):
         path = install_dir / "build" / "bin" / "Release"
     else:
@@ -4590,9 +4398,7 @@ def runtime_patterns_for_choice(choice: AssetChoice) -> list[str]:
         "windows-arm64",
     }:
         return ["llama-server.exe", "llama-quantize.exe", "*.dll"]
-    raise PrebuiltFallback(
-        f"unsupported install kind for runtime overlay: {choice.install_kind}"
-    )
+    raise PrebuiltFallback(f"unsupported install kind for runtime overlay: {choice.install_kind}")
 
 
 def runtime_subdirs_for_choice(choice: AssetChoice) -> list[str]:
@@ -4801,9 +4607,7 @@ def confirm_install_tree(install_dir: Path, host: HostInfo) -> None:
     expected.append(install_dir / "UNSLOTH_PREBUILT_INFO.json")
     missing = [str(path) for path in expected if not path.exists()]
     if missing:
-        raise RuntimeError(
-            "activated install was missing expected files: " + ", ".join(missing)
-        )
+        raise RuntimeError("activated install was missing expected files: " + ", ".join(missing))
 
 
 def activate_install_tree(staging_dir: Path, install_dir: Path, host: HostInfo) -> None:
@@ -4926,15 +4730,11 @@ def install_from_archives(
                 expected_sha256 = choice.runtime_sha256,
                 label = f"prebuilt runtime archive {choice.runtime_name}",
             )
-            runtime_extract_dir = Path(
-                tempfile.mkdtemp(prefix = "extract-runtime-", dir = work_dir)
-            )
+            runtime_extract_dir = Path(tempfile.mkdtemp(prefix = "extract-runtime-", dir = work_dir))
             extract_archive(runtime_archive, runtime_extract_dir)
         source_dir = extract_dir
         overlay_dir = overlay_directory_for_choice(install_dir, choice, host)
-        copy_globs(
-            source_dir, overlay_dir, runtime_patterns_for_choice(choice), required = True
-        )
+        copy_globs(source_dir, overlay_dir, runtime_patterns_for_choice(choice), required = True)
         for _subdir in runtime_subdirs_for_choice(choice):
             _src_subdir = source_dir / _subdir
             if _src_subdir.is_dir():
@@ -4979,9 +4779,7 @@ def install_from_archives(
     source_server = build_bin / "llama-server"
     source_quantize = build_bin / "llama-quantize"
     if not source_server.exists() or not source_quantize.exists():
-        raise PrebuiltFallback(
-            "unix executables were not installed correctly into build/bin"
-        )
+        raise PrebuiltFallback("unix executables were not installed correctly into build/bin")
     os.chmod(source_server, 0o755)
     os.chmod(source_quantize, 0o755)
 
@@ -5007,13 +4805,9 @@ def ensure_repo_shape(install_dir: Path) -> None:
         install_dir / "convert_hf_to_gguf.py",
         install_dir / "gguf-py",
     ]
-    missing = [
-        str(path.relative_to(install_dir)) for path in required if not path.exists()
-    ]
+    missing = [str(path.relative_to(install_dir)) for path in required if not path.exists()]
     if missing:
-        raise PrebuiltFallback(
-            "hydrated llama.cpp source tree was missing: " + ", ".join(missing)
-        )
+        raise PrebuiltFallback("hydrated llama.cpp source tree was missing: " + ", ".join(missing))
 
 
 def validation_model_cache_path(install_dir: Path) -> Path:
@@ -5028,8 +4822,7 @@ def validated_validation_model_bytes(data: bytes) -> bytes:
     digest = hashlib.sha256(data).hexdigest()
     if digest != TEST_MODEL_SHA256:
         raise RuntimeError(
-            "validation model checksum mismatch: "
-            f"expected={TEST_MODEL_SHA256} actual={digest}"
+            f"validation model checksum mismatch: expected={TEST_MODEL_SHA256} actual={digest}"
         )
     return data
 
@@ -5042,9 +4835,7 @@ def download_validation_model(path: Path, cache_path: Path | None = None) -> Non
                 data = validated_validation_model_bytes(cache_path.read_bytes())
                 log(f"using cached tiny GGUF validation model from {cache_path}")
             except Exception as exc:
-                log(
-                    f"cached tiny GGUF validation model was invalid; refreshing cache ({exc})"
-                )
+                log(f"cached tiny GGUF validation model was invalid; refreshing cache ({exc})")
                 data = None
         if data is None:
             log("downloading tiny GGUF validation model")
@@ -5133,9 +4924,7 @@ def dedupe_existing_dirs(paths: Iterable[str | Path]) -> list[str]:
     return unique
 
 
-def linux_missing_libraries(
-    binary_path: Path, *, env: dict[str, str] | None = None
-) -> list[str]:
+def linux_missing_libraries(binary_path: Path, *, env: dict[str, str] | None = None) -> list[str]:
     try:
         result = run_capture(["ldd", str(binary_path)], timeout = 20, env = env)
     except Exception:
@@ -5292,9 +5081,7 @@ def _macho_slice_minos(data: bytes, offset: int) -> tuple[int, int] | None:
     return None
 
 
-def macho_minimum_macos(
-    path: Path, host: HostInfo | None = None
-) -> tuple[int, int] | None:
+def macho_minimum_macos(path: Path, host: HostInfo | None = None) -> tuple[int, int] | None:
     """Minimum macOS (major, minor) a Mach-O binary or dylib requires.
 
     Pure-Python so it works on consumer Macs without the Xcode command line
@@ -5333,9 +5120,7 @@ def macho_minimum_macos(
             return None
         if host is not None:
             want = (
-                _CPU_TYPE_ARM64
-                if host.is_arm64
-                else (_CPU_TYPE_X86_64 if host.is_x86_64 else None)
+                _CPU_TYPE_ARM64 if host.is_arm64 else (_CPU_TYPE_X86_64 if host.is_x86_64 else None)
             )
             for cputype, minos in slices:
                 if cputype == want:
@@ -5355,9 +5140,7 @@ def looks_like_macos_incompatibility(text: str) -> bool:
 
 
 def macos_binary_minos_issues(
-    binaries: Iterable[Path],
-    install_dir: Path,
-    host: HostInfo,
+    binaries: Iterable[Path], install_dir: Path, host: HostInfo
 ) -> list[str]:
     """Issue strings for every installed Mach-O whose minimum macOS exceeds the
     host. Scans the given executables plus every bundled .dylib next to them --
@@ -5387,9 +5170,7 @@ def macos_binary_minos_issues(
 
 
 def preflight_macos_installed_binaries(
-    binaries: Iterable[Path],
-    install_dir: Path,
-    host: HostInfo,
+    binaries: Iterable[Path], install_dir: Path, host: HostInfo
 ) -> None:
     """Reject a macos prebuilt whose minimum-OS is newer than the host. The
     upstream selector pins a loadable release up front, so here this is the
@@ -5400,15 +5181,12 @@ def preflight_macos_installed_binaries(
     issues = macos_binary_minos_issues(binaries, install_dir, host)
     if issues:
         raise PrebuiltFallback(
-            "macos prebuilt requires a newer macOS than this host:\n"
-            + "\n".join(issues)
+            "macos prebuilt requires a newer macOS than this host:\n" + "\n".join(issues)
         )
 
 
 def preflight_linux_installed_binaries(
-    binaries: Iterable[Path],
-    install_dir: Path,
-    host: HostInfo,
+    binaries: Iterable[Path], install_dir: Path, host: HostInfo
 ) -> None:
     if not host.is_linux:
         return
@@ -5419,18 +5197,14 @@ def preflight_linux_installed_binaries(
         missing = linux_missing_libraries(binary_path, env = env)
         if not missing:
             continue
-        runtime_dirs = [
-            part for part in env.get("LD_LIBRARY_PATH", "").split(os.pathsep) if part
-        ]
+        runtime_dirs = [part for part in env.get("LD_LIBRARY_PATH", "").split(os.pathsep) if part]
         issues.append(
             f"{binary_path.name}: missing={','.join(missing)} "
             f"ld_library_path={','.join(runtime_dirs) if runtime_dirs else 'none'}"
         )
 
     if issues:
-        raise PrebuiltFallback(
-            "linux extracted binary preflight failed:\n" + "\n".join(issues)
-        )
+        raise PrebuiltFallback("linux extracted binary preflight failed:\n" + "\n".join(issues))
 
 
 def glob_paths(*patterns: str) -> list[str]:
@@ -5474,12 +5248,9 @@ def windows_runtime_dirs() -> list[str]:
 
 
 def windows_runtime_dirs_for_patterns(
-    required_patterns: Iterable[str],
-    candidate_dirs: Iterable[str] | None = None,
+    required_patterns: Iterable[str], candidate_dirs: Iterable[str] | None = None
 ) -> list[str]:
-    directories = (
-        list(candidate_dirs) if candidate_dirs is not None else windows_runtime_dirs()
-    )
+    directories = list(candidate_dirs) if candidate_dirs is not None else windows_runtime_dirs()
     matching_dirs: list[str] = []
     for pattern in required_patterns:
         matched_dirs = [
@@ -5523,20 +5294,12 @@ def binary_env(
             str(install_dir),
             *linux_runtime_dirs(binary_path),
         ]
-        existing = [
-            part for part in env.get("LD_LIBRARY_PATH", "").split(os.pathsep) if part
-        ]
-        env["LD_LIBRARY_PATH"] = os.pathsep.join(
-            dedupe_existing_dirs([*ld_dirs, *existing])
-        )
+        existing = [part for part in env.get("LD_LIBRARY_PATH", "").split(os.pathsep) if part]
+        env["LD_LIBRARY_PATH"] = os.pathsep.join(dedupe_existing_dirs([*ld_dirs, *existing]))
     elif host.is_macos:
         dyld_dirs = [str(binary_path.parent), str(install_dir)]
-        existing = [
-            part for part in env.get("DYLD_LIBRARY_PATH", "").split(os.pathsep) if part
-        ]
-        env["DYLD_LIBRARY_PATH"] = os.pathsep.join(
-            dedupe_existing_dirs([*dyld_dirs, *existing])
-        )
+        existing = [part for part in env.get("DYLD_LIBRARY_PATH", "").split(os.pathsep) if part]
+        env["DYLD_LIBRARY_PATH"] = os.pathsep.join(dedupe_existing_dirs([*dyld_dirs, *existing]))
     return env
 
 
@@ -5558,11 +5321,7 @@ def validate_quantize(
         env = binary_env(quantize_path, install_dir, host, runtime_line = runtime_line),
         **windows_hidden_subprocess_kwargs(),
     )
-    if (
-        result.returncode != 0
-        or not quantized_path.exists()
-        or quantized_path.stat().st_size == 0
-    ):
+    if result.returncode != 0 or not quantized_path.exists() or quantized_path.stat().st_size == 0:
         combined = result.stdout + ("\n" + result.stderr if result.stderr else "")
         # Backstop for prebuilts the static minos scan could not read: a dyld
         # "built for macOS N" / missing Metal symbol failure means this binary
@@ -5572,9 +5331,7 @@ def validate_quantize(
             if looks_like_macos_incompatibility(combined)
             else ""
         )
-        raise PrebuiltFallback(
-            prefix + "llama-quantize validation failed:\n" + combined
-        )
+        raise PrebuiltFallback(prefix + "llama-quantize validation failed:\n" + combined)
 
 
 def validate_server(
@@ -5630,9 +5387,7 @@ def validate_server(
             # is exercised against the actual hardware rather than the
             # CPU fallback. NVIDIA and macOS-arm64 are already covered.
             _enable_gpu_layers = (
-                host.has_usable_nvidia
-                or host.has_rocm
-                or (host.is_macos and host.is_arm64)
+                host.has_usable_nvidia or host.has_rocm or (host.is_macos and host.is_arm64)
             )
         if _enable_gpu_layers:
             command.extend(["--n-gpu-layers", "1"])
@@ -5648,9 +5403,7 @@ def validate_server(
                     stdout = log_handle,
                     stderr = subprocess.STDOUT,
                     text = True,
-                    env = binary_env(
-                        server_path, install_dir, host, runtime_line = runtime_line
-                    ),
+                    env = binary_env(server_path, install_dir, host, runtime_line = runtime_line),
                     **windows_hidden_subprocess_kwargs(),
                 )
                 deadline = time.time() + 60
@@ -5665,9 +5418,7 @@ def validate_server(
                         exited_quickly = (
                             time.time() - startup_started
                         ) <= SERVER_BIND_RETRY_WINDOW_SECONDS
-                        failure = PrebuiltFallback(
-                            "llama-server exited during startup:\n" + output
-                        )
+                        failure = PrebuiltFallback("llama-server exited during startup:\n" + output)
                         if (
                             port_attempt < SERVER_PORT_BIND_ATTEMPTS
                             and is_retryable_server_bind_error(
@@ -5684,9 +5435,7 @@ def validate_server(
                             break
                         raise failure
 
-                    payload = json.dumps({"prompt": "a", "n_predict": 1}).encode(
-                        "utf-8"
-                    )
+                    payload = json.dumps({"prompt": "a", "n_predict": 1}).encode("utf-8")
                     request = urllib.request.Request(
                         f"http://127.0.0.1:{port}/completion",
                         data = payload,
@@ -5698,9 +5447,7 @@ def validate_server(
                             response_body = response.read().decode("utf-8", "replace")
                             if status_code == 200:
                                 return
-                            last_error = RuntimeError(
-                                f"unexpected HTTP status {status_code}"
-                            )
+                            last_error = RuntimeError(f"unexpected HTTP status {status_code}")
                     except urllib.error.HTTPError as exc:
                         response_body = exc.read().decode("utf-8", "replace")
                         last_error = exc
@@ -5734,9 +5481,7 @@ def validate_server(
     raise PrebuiltFallback("llama-server validation failed unexpectedly")
 
 
-def collect_system_report(
-    host: HostInfo, choice: AssetChoice | None, install_dir: Path
-) -> str:
+def collect_system_report(host: HostInfo, choice: AssetChoice | None, install_dir: Path) -> str:
     lines = [
         f"platform={host.system} machine={host.machine}",
         f"driver_cuda_version={host.driver_cuda_version}",
@@ -5750,8 +5495,7 @@ def collect_system_report(
     if host.is_linux and host.has_physical_nvidia:
         runtime_lines, runtime_dirs = detected_linux_runtime_lines()
         lines.append(
-            "linux_runtime_lines="
-            + (",".join(runtime_lines) if runtime_lines else "none")
+            "linux_runtime_lines=" + (",".join(runtime_lines) if runtime_lines else "none")
         )
         for runtime_line in ("cuda13", "cuda12"):
             lines.append(
@@ -5780,10 +5524,7 @@ def collect_system_report(
             server_env = binary_env(server_binary, install_dir, host)
             lines.append(
                 "linux_missing_libs="
-                + (
-                    ",".join(linux_missing_libraries(server_binary, env = server_env))
-                    or "none"
-                )
+                + (",".join(linux_missing_libraries(server_binary, env = server_env)) or "none")
             )
             lines.append(
                 "linux_runtime_dirs="
@@ -5791,9 +5532,7 @@ def collect_system_report(
                     ",".join(
                         [
                             part
-                            for part in server_env.get("LD_LIBRARY_PATH", "").split(
-                                os.pathsep
-                            )
+                            for part in server_env.get("LD_LIBRARY_PATH", "").split(os.pathsep)
                             if part
                         ]
                     )
@@ -5801,21 +5540,16 @@ def collect_system_report(
                 )
             )
             try:
-                ldd = run_capture(
-                    ["ldd", str(server_binary)], timeout = 20, env = server_env
-                )
+                ldd = run_capture(["ldd", str(server_binary)], timeout = 20, env = server_env)
                 lines.append("ldd llama-server:")
                 lines.append((ldd.stdout + ldd.stderr).strip())
             except Exception as exc:
                 lines.append(f"ldd error: {exc}")
     elif host.is_windows:
-        lines.append(
-            "windows_runtime_dirs=" + (",".join(windows_runtime_dirs()) or "none")
-        )
+        lines.append("windows_runtime_dirs=" + (",".join(windows_runtime_dirs()) or "none"))
         runtime_lines, runtime_dirs = detected_windows_runtime_lines()
         lines.append(
-            "windows_runtime_lines="
-            + (",".join(runtime_lines) if runtime_lines else "none")
+            "windows_runtime_lines=" + (",".join(runtime_lines) if runtime_lines else "none")
         )
         for runtime_line in ("cuda13", "cuda12"):
             lines.append(
@@ -5840,8 +5574,7 @@ def collect_system_report(
 
 
 def apply_approved_hashes(
-    attempts: Iterable[AssetChoice],
-    checksums: ApprovedReleaseChecksums,
+    attempts: Iterable[AssetChoice], checksums: ApprovedReleaseChecksums
 ) -> list[AssetChoice]:
     def approved_hash_for_attempt(attempt: AssetChoice) -> ApprovedArtifactHash | None:
         candidate_names = [attempt.name]
@@ -5949,8 +5682,7 @@ def preferred_source_archive(
 
 
 def selected_source_archive_metadata(
-    checksums: ApprovedReleaseChecksums,
-    llama_tag: str,
+    checksums: ApprovedReleaseChecksums, llama_tag: str
 ) -> tuple[str, str | None]:
     _source_repo, _source_ref, source_archive, _exact_source = preferred_source_archive(
         checksums, llama_tag
@@ -5961,10 +5693,7 @@ def selected_source_archive_metadata(
 
 
 def resolve_install_attempts(
-    llama_tag: str,
-    host: HostInfo,
-    published_repo: str,
-    published_release_tag: str,
+    llama_tag: str, host: HostInfo, published_repo: str, published_release_tag: str
 ) -> tuple[str, str, list[AssetChoice], ApprovedReleaseChecksums]:
     requested_tag, plans = resolve_install_release_plans(
         llama_tag,
@@ -5987,17 +5716,11 @@ def resolve_install_release_plans(
     max_release_fallbacks: int = DEFAULT_MAX_PREBUILT_RELEASE_FALLBACKS,
 ) -> tuple[str, list[InstallReleasePlan]]:
     requested_tag = normalized_requested_llama_tag(llama_tag)
-    allow_older_release_fallback = (
-        requested_tag == "latest" and not published_release_tag
-    )
+    allow_older_release_fallback = requested_tag == "latest" and not published_release_tag
     release_limit = max(1, max_release_fallbacks)
     # macOS may need to walk past a run of too-new prebuilts. Only when the host
     # version is known; otherwise keep the default (cannot tell up front).
-    if (
-        host.is_macos
-        and allow_older_release_fallback
-        and host.macos_version is not None
-    ):
+    if host.is_macos and allow_older_release_fallback and host.macos_version is not None:
         release_limit = max(release_limit, DEFAULT_MAX_MACOS_RELEASE_FALLBACKS)
     plans: list[InstallReleasePlan] = []
     last_error: PrebuiltFallback | None = None
@@ -6013,9 +5736,7 @@ def resolve_install_release_plans(
         try:
             if host.is_linux and host.is_x86_64 and host.has_usable_nvidia:
                 linux_cuda_selection = resolve_linux_cuda_choice(host, bundle)
-                attempts = apply_approved_hashes(
-                    linux_cuda_selection.attempts, checksums
-                )
+                attempts = apply_approved_hashes(linux_cuda_selection.attempts, checksums)
                 if not attempts:
                     raise PrebuiltFallback("no compatible Linux CUDA asset was found")
                 log_lines(linux_cuda_selection.selection_log)
@@ -6117,9 +5838,7 @@ def write_prebuilt_metadata(
         "prebuilt_fallback_used": prebuilt_fallback_used,
         "installed_at_utc": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
     }
-    (install_dir / "UNSLOTH_PREBUILT_INFO.json").write_text(
-        json.dumps(metadata, indent = 2) + "\n"
-    )
+    (install_dir / "UNSLOTH_PREBUILT_INFO.json").write_text(json.dumps(metadata, indent = 2) + "\n")
 
 
 def expected_install_fingerprint(
@@ -6236,9 +5955,7 @@ def install_runtime_dir(install_dir: Path, host: HostInfo) -> Path:
     return install_dir / "build" / "bin"
 
 
-def runtime_payload_is_healthy(
-    install_dir: Path, host: HostInfo, choice: AssetChoice
-) -> bool:
+def runtime_payload_is_healthy(install_dir: Path, host: HostInfo, choice: AssetChoice) -> bool:
     runtime_dir = install_runtime_dir(install_dir, host)
     if not runtime_dir.exists():
         return False
@@ -6326,9 +6043,7 @@ def existing_install_matches_choice(
 
 
 def existing_install_matches_plan(
-    install_dir: Path,
-    host: HostInfo,
-    plan: InstallReleasePlan,
+    install_dir: Path, host: HostInfo, plan: InstallReleasePlan
 ) -> bool:
     if not plan.attempts:
         return False
@@ -6360,9 +6075,7 @@ def validate_prebuilt_choice(
         approved_checksums, llama_tag
     )
     if exact_source:
-        log(
-            f"hydrating exact llama.cpp source for {source_repo}@{source_ref} into {install_dir}"
-        )
+        log(f"hydrating exact llama.cpp source for {source_repo}@{source_ref} into {install_dir}")
     else:
         log(f"hydrating upstream llama.cpp source for {llama_tag} into {install_dir}")
     hydrate_source_tree(
@@ -6379,9 +6092,7 @@ def validate_prebuilt_choice(
         exact_source = exact_source,
     )
     log(f"overlaying prebuilt bundle {choice.name} into {install_dir}")
-    server_path, quantize_path = install_from_archives(
-        choice, host, install_dir, work_dir
-    )
+    server_path, quantize_path = install_from_archives(choice, host, install_dir, work_dir)
     preflight_linux_installed_binaries((server_path, quantize_path), install_dir, host)
     preflight_macos_installed_binaries((server_path, quantize_path), install_dir, host)
     ensure_repo_shape(install_dir)
@@ -6539,9 +6250,7 @@ def install_prebuilt(
                     published_repo,
                     published_release_tag,
                 )
-            if release_plans and existing_install_matches_plan(
-                install_dir, host, release_plans[0]
-            ):
+            if release_plans and existing_install_matches_plan(install_dir, host, release_plans[0]):
                 current = release_plans[0]
                 log(
                     "existing llama.cpp install already matches selected release "
@@ -6551,9 +6260,7 @@ def install_prebuilt(
             with tempfile.TemporaryDirectory(prefix = "unsloth-llama-prebuilt-") as tmp:
                 work_dir = Path(tmp)
                 probe_path = work_dir / "stories260K.gguf"
-                download_validation_model(
-                    probe_path, validation_model_cache_path(install_dir)
-                )
+                download_validation_model(probe_path, validation_model_cache_path(install_dir))
                 release_count = len(release_plans)
                 for release_index, plan in enumerate(release_plans):
                     choice = plan.attempts[0]
@@ -6759,9 +6466,7 @@ def main() -> int:
         )
         emit_resolver_output(
             {
-                "requested_tag": normalized_requested_llama_tag(
-                    args.resolve_install_tag
-                ),
+                "requested_tag": normalized_requested_llama_tag(args.resolve_install_tag),
                 "llama_tag": resolved,
             },
             output_format = args.output_format,
@@ -6776,9 +6481,7 @@ def main() -> int:
         )
         emit_resolver_output(
             {
-                "requested_tag": normalized_requested_llama_tag(
-                    args.resolve_source_build
-                ),
+                "requested_tag": normalized_requested_llama_tag(args.resolve_source_build),
                 "source_url": plan.source_url,
                 "source_ref_kind": plan.source_ref_kind,
                 "source_ref": plan.source_ref,
diff --git a/studio/install_python_stack.py b/studio/install_python_stack.py
index da202f7ce6..5ff8e8572b 100644
--- a/studio/install_python_stack.py
+++ b/studio/install_python_stack.py
@@ -176,7 +176,6 @@ def _detect_rocm_version() -> tuple[int, int] | None:
             )
             if result.returncode == 0:
                 import re
-
                 m = re.search(r"ROCm version:\s*(\d+)\.(\d+)", result.stdout)
                 if m:
                     return int(m.group(1)), int(m.group(2))
@@ -196,11 +195,7 @@ def _detect_rocm_version() -> tuple[int, int] | None:
             if result.returncode == 0:
                 raw = result.stdout.decode().strip().split("\n")[0]
                 parts = raw.split(".")
-                if (
-                    len(parts) >= 2
-                    and parts[0].isdigit()
-                    and parts[1].split("-")[0].isdigit()
-                ):
+                if len(parts) >= 2 and parts[0].isdigit() and parts[1].split("-")[0].isdigit():
                     return int(parts[0]), int(parts[1].split("-")[0])
         except Exception:
             pass
@@ -309,8 +304,7 @@ def _detect_windows_gfx_arch() -> str | None:
                 # findall picks every gcnArchName line so multi-GPU hosts
                 # are enumerable and HIP_VISIBLE_DEVICES selects correctly.
                 _tokens = [
-                    t.strip().lower()
-                    for t in re.findall(r"(?im)^\s*gcnArchName\s*:\s*(\S+)", text)
+                    t.strip().lower() for t in re.findall(r"(?im)^\s*gcnArchName\s*:\s*(\S+)", text)
                 ]
                 _pick = _dedup_pick(_tokens)
                 if _pick:
@@ -612,9 +606,7 @@ def _ensure_rocm_torch() -> None:
         if not _torch_already_rocm:
             index_url = _windows_rocm_index_url(gfx_arch)
             if index_url is None:
-                print(
-                    f"   No AMD Windows torch index for GPU arch {gfx_arch} -- skipping"
-                )
+                print(f"   No AMD Windows torch index for GPU arch {gfx_arch} -- skipping")
                 return
             print(f"   {gfx_arch} (Windows) -- installing torch from {index_url}")
             pip_install(
@@ -688,9 +680,7 @@ def _ensure_rocm_torch() -> None:
     except (OSError, subprocess.TimeoutExpired):
         probe = None
     has_hip_torch = (
-        probe is not None
-        and probe.returncode == 0
-        and probe.stdout.decode().strip() != ""
+        probe is not None and probe.returncode == 0 and probe.stdout.decode().strip() != ""
     )
 
     rocm_torch_ready = has_hip_torch
@@ -714,14 +704,11 @@ def _ensure_rocm_torch() -> None:
             # specific index into gfx_codes, use that gfx; else default to the
             # first listed GPU. Skip the override unless the resolved GPU is
             # Strix.
-            _runtime_gfx = (
-                gfx_codes[_pick_visible_index(len(gfx_codes))] if gfx_codes else None
-            )
+            _runtime_gfx = gfx_codes[_pick_visible_index(len(gfx_codes))] if gfx_codes else None
             if _runtime_gfx in _strix_gfx:
                 _selected_gfx = _runtime_gfx
                 _amd_mirror = (
-                    os.environ.get("UNSLOTH_AMD_ROCM_MIRROR")
-                    or "https://repo.amd.com/rocm/whl"
+                    os.environ.get("UNSLOTH_AMD_ROCM_MIRROR") or "https://repo.amd.com/rocm/whl"
                 ).rstrip("/")
                 _strix_override_url = f"{_amd_mirror}/{_selected_gfx}/"
                 _strix_override_pkgs = (
@@ -782,10 +769,7 @@ def _ensure_rocm_torch() -> None:
             None,
         )
         if tag is None:
-            print(
-                f"   No PyTorch wheel for ROCm {ver[0]}.{ver[1]} -- "
-                f"skipping torch reinstall"
-            )
+            print(f"   No PyTorch wheel for ROCm {ver[0]}.{ver[1]} -- " f"skipping torch reinstall")
         else:
             index_url = f"{_PYTORCH_WHL_BASE}/{tag}"
             print(f"   ROCm {ver[0]}.{ver[1]} -- installing torch from {index_url}")
@@ -922,9 +906,7 @@ CONSTRAINTS = SINGLE_ENV / "constraints.txt"
 LOCAL_DD_UNSTRUCTURED_PLUGIN = (
     SCRIPT_DIR / "backend" / "plugins" / "data-designer-unstructured-seed"
 )
-LOCAL_DD_GITHUB_PLUGIN = (
-    SCRIPT_DIR / "backend" / "plugins" / "data-designer-github-repo-seed"
-)
+LOCAL_DD_GITHUB_PLUGIN = SCRIPT_DIR / "backend" / "plugins" / "data-designer-github-repo-seed"
 
 # Apple Silicon: override mlx-vlm/mlx-lm's transformers pin (see overrides file).
 _MLX_OVERRIDES = SINGLE_ENV / "overrides-darwin-arm64.txt"
@@ -1026,7 +1008,11 @@ def _title(msg: str) -> str:
 _RULE = "\u2500" * 52
 
 
-def _step(label: str, value: str, color_fn = None) -> None:
+def _step(
+    label: str,
+    value: str,
+    color_fn = None,
+) -> None:
     """Print a single step line in the column format."""
     if color_fn is None:
         color_fn = _green
@@ -1046,16 +1032,17 @@ def _progress(label: str) -> None:
     pad = " " * (_COL - len(_LABEL))
     end = "\n" if _STEP >= _TOTAL else ""
     try:
-        sys.stdout.write(
-            f"\r  {_dim(_LABEL)}{pad}[{bar}] {_STEP:2}/{_TOTAL}  {label:<20}{end}"
-        )
+        sys.stdout.write(f"\r  {_dim(_LABEL)}{pad}[{bar}] {_STEP:2}/{_TOTAL}  {label:<20}{end}")
         sys.stdout.flush()
     except OSError:
         pass
 
 
 def run(
-    label: str, cmd: list[str], *, quiet: bool = True
+    label: str,
+    cmd: list[str],
+    *,
+    quiet: bool = True,
 ) -> subprocess.CompletedProcess[bytes]:
     """Run a command; on failure print output and exit."""
     if VERBOSE:
@@ -1107,9 +1094,7 @@ def _build_flash_attn_wheel_url(env: dict[str, str]) -> str | None:
     return flash_attn_wheel_url(env)
 
 
-def _print_optional_install_failure(
-    label: str, result: subprocess.CompletedProcess[str]
-) -> None:
+def _print_optional_install_failure(label: str, result: subprocess.CompletedProcess[str]) -> None:
     _step("warning", f"{label} failed (exit code {result.returncode})", _cyan)
     if result.stdout:
         print(result.stdout.strip())
@@ -1204,9 +1189,7 @@ def _filter_requirements(req: Path, skip: set[str]) -> Path:
     """Return a temp copy of a requirements file with certain packages removed."""
     lines = req.read_text(encoding = "utf-8").splitlines(keepends = True)
     filtered = [
-        line
-        for line in lines
-        if not any(line.strip().lower().startswith(pkg) for pkg in skip)
+        line for line in lines if not any(line.strip().lower().startswith(pkg) for pkg in skip)
     ]
     tmp = tempfile.NamedTemporaryFile(
         mode = "w",
@@ -1416,9 +1399,7 @@ def install_python_stack() -> int:
     if not IS_MACOS and not NO_TORCH:
         base_total += 1  # ROCm torch check (line 1526) -- all non-macOS platforms
         if not IS_WINDOWS:
-            base_total += (
-                2  # flash-attn (line 1620) + ROCm torch final (line 1705) -- Linux only
-            )
+            base_total += 2  # flash-attn (line 1620) + ROCm torch final (line 1705) -- Linux only
     _TOTAL = (base_total - 1) if skip_base else base_total
 
     # 1. Try to use uv for faster installs (must happen before pip upgrade
diff --git a/tests/_zoo_aggressive_cuda_spoof.py b/tests/_zoo_aggressive_cuda_spoof.py
index eaafe445fb..9111aa9519 100644
--- a/tests/_zoo_aggressive_cuda_spoof.py
+++ b/tests/_zoo_aggressive_cuda_spoof.py
@@ -159,7 +159,11 @@ def apply() -> None:
         if _orig is None:
             continue
 
-        def _wrap(*args: Any, _orig = _orig, **kwargs: Any):
+        def _wrap(
+            *args: Any,
+            _orig = _orig,
+            **kwargs: Any,
+        ):
             kwargs.pop("pin_memory", None)
             return _orig(*args, **kwargs)
 
diff --git a/tests/conftest.py b/tests/conftest.py
index 2d7038d5d4..ad58cb9706 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -105,13 +105,11 @@ def _patch_torch_cuda_for_import() -> None:
     CPU like normal."""
     try:
         import torch.cuda.memory as _cuda_memory  # type: ignore
-
         _cuda_memory.mem_get_info = lambda *a, **k: (0, 80 * 1024**3)
     except Exception:
         pass
     try:
         import torch
-
         torch.cuda.get_device_capability = lambda *a, **k: (8, 0)
         torch.cuda.is_bf16_supported = lambda *a, **k: True
     except Exception:
diff --git a/tests/python/conftest.py b/tests/python/conftest.py
index 9129e384e5..f7b125edf6 100644
--- a/tests/python/conftest.py
+++ b/tests/python/conftest.py
@@ -2,9 +2,5 @@
 
 
 def pytest_configure(config):
-    config.addinivalue_line(
-        "markers", "server: heavyweight tests requiring studio venv"
-    )
-    config.addinivalue_line(
-        "markers", "e2e: end-to-end tests requiring network and venv creation"
-    )
+    config.addinivalue_line("markers", "server: heavyweight tests requiring studio venv")
+    config.addinivalue_line("markers", "e2e: end-to-end tests requiring network and venv creation")
diff --git a/tests/python/test_cross_platform_parity.py b/tests/python/test_cross_platform_parity.py
index 7b9868c1f2..6c504579ce 100644
--- a/tests/python/test_cross_platform_parity.py
+++ b/tests/python/test_cross_platform_parity.py
@@ -28,17 +28,11 @@ class TestNoTorchBackendAutoInInstallSh:
         for i, line in enumerate(lines):
             if fallback_start is None and "GPU detection failed" in line:
                 fallback_start = i
-            elif (
-                fallback_start is not None
-                and fallback_end is None
-                and line.strip() == "fi"
-            ):
+            elif fallback_start is not None and fallback_end is None and line.strip() == "fi":
                 fallback_end = i
                 break
         fallback_range = (
-            range(fallback_start or 0, (fallback_end or 0) + 1)
-            if fallback_start
-            else range(0)
+            range(fallback_start or 0, (fallback_end or 0) + 1) if fallback_start else range(0)
         )
 
         matches = [
diff --git a/tests/python/test_dpo_vision_processor_passthrough.py b/tests/python/test_dpo_vision_processor_passthrough.py
index a4f2e2e12a..a320cab935 100644
--- a/tests/python/test_dpo_vision_processor_passthrough.py
+++ b/tests/python/test_dpo_vision_processor_passthrough.py
@@ -33,7 +33,11 @@ class _Tok:
     eos_token_id = 99
     bos_token_id = None
 
-    def __call__(self, t, add_special_tokens = False):
+    def __call__(
+        self,
+        t,
+        add_special_tokens = False,
+    ):
         return {"input_ids": [10]}
 
 
@@ -46,7 +50,12 @@ class _Capture:
         self.last_text = None
         self.last_images = "__sentinel__"
 
-    def __call__(self, images = None, text = None, add_special_tokens = False):
+    def __call__(
+        self,
+        images = None,
+        text = None,
+        add_special_tokens = False,
+    ):
         self.last_text = text
         self.last_images = images
         out = {"input_ids": [[1, 2]]}
diff --git a/tests/python/test_e2e_no_torch_sandbox.py b/tests/python/test_e2e_no_torch_sandbox.py
index f36f69201d..382d0afe4e 100644
--- a/tests/python/test_e2e_no_torch_sandbox.py
+++ b/tests/python/test_e2e_no_torch_sandbox.py
@@ -247,12 +247,8 @@ class TestBeforeAfterImportChain:
             exec(source)
         """)
         result = _run_in_sandbox(no_torch_venv, code)
-        assert (
-            result.returncode != 0
-        ), "BEFORE chat_templates.py should crash without torch"
-        assert (
-            b"ModuleNotFoundError" in result.stderr or b"ImportError" in result.stderr
-        )
+        assert result.returncode != 0, "BEFORE chat_templates.py should crash without torch"
+        assert b"ModuleNotFoundError" in result.stderr or b"ImportError" in result.stderr
 
     def test_before_data_collators_crashes(self, no_torch_venv, sandbox_dir):
         """BEFORE: data_collators.py with top-level 'import torch' crashes."""
@@ -270,12 +266,8 @@ class TestBeforeAfterImportChain:
             exec(open({str(before_file)!r}).read())
         """)
         result = _run_in_sandbox(no_torch_venv, code)
-        assert (
-            result.returncode != 0
-        ), "BEFORE data_collators.py should crash without torch"
-        assert (
-            b"ModuleNotFoundError" in result.stderr or b"ImportError" in result.stderr
-        )
+        assert result.returncode != 0, "BEFORE data_collators.py should crash without torch"
+        assert b"ModuleNotFoundError" in result.stderr or b"ImportError" in result.stderr
 
     def test_before_full_import_chain_crashes(self, no_torch_venv, sandbox_dir):
         """BEFORE: full utils/datasets/ package with top-level torch imports crashes."""
@@ -320,12 +312,8 @@ class TestBeforeAfterImportChain:
             from utils.datasets import detect_dataset_format
         """)
         result = _run_in_sandbox(no_torch_venv, code)
-        assert (
-            result.returncode != 0
-        ), "BEFORE full import chain should crash without torch"
-        assert (
-            b"ModuleNotFoundError" in result.stderr or b"ImportError" in result.stderr
-        )
+        assert result.returncode != 0, "BEFORE full import chain should crash without torch"
+        assert b"ModuleNotFoundError" in result.stderr or b"ImportError" in result.stderr
 
     # -- AFTER: succeeds --
 
@@ -539,9 +527,7 @@ class TestEdgeCasesBrokenTorch:
             print("OK: data_collators works despite broken torch on sys.path")
         """)
         result = _run_in_sandbox(no_torch_venv, code)
-        assert (
-            result.returncode == 0
-        ), f"Should work with broken torch:\n{result.stderr.decode()}"
+        assert result.returncode == 0, f"Should work with broken torch:\n{result.stderr.decode()}"
         assert b"OK:" in result.stdout
 
     def test_torch_import_error_hardware_fallback(self, no_torch_venv, sandbox_dir):
@@ -604,14 +590,10 @@ class TestEdgeCasesBrokenTorch:
             print("OK: detect_hardware returned CPU with fake torch (no CUDA)")
         """)
         result = _run_in_sandbox(no_torch_venv, code)
-        assert (
-            result.returncode == 0
-        ), f"Should fall back to CPU:\n{result.stderr.decode()}"
+        assert result.returncode == 0, f"Should fall back to CPU:\n{result.stderr.decode()}"
         assert b"OK:" in result.stdout
 
-    def test_lazy_torch_fails_at_call_time_not_import_time(
-        self, no_torch_venv, sandbox_dir
-    ):
+    def test_lazy_torch_fails_at_call_time_not_import_time(self, no_torch_venv, sandbox_dir):
         """apply_chat_template_to_dataset is importable without torch.
 
         Calling the alpaca branch triggers the lazy 'from torch.utils.data' inside
@@ -657,9 +639,7 @@ class TestEdgeCasesBrokenTorch:
                 print("OK: call succeeded (unexpected but not a crash)")
         """)
         result = _run_in_sandbox(no_torch_venv, code)
-        assert (
-            result.returncode == 0
-        ), f"Should not crash at import time:\n{result.stderr.decode()}"
+        assert result.returncode == 0, f"Should not crash at import time:\n{result.stderr.decode()}"
         assert b"OK: import succeeded" in result.stdout
 
 
@@ -1011,9 +991,7 @@ class TestInstallPythonStackFiltering:
         source = Path(ips.__file__).read_text(encoding = "utf-8")
 
         # NO_TORCH guard before overrides
-        assert (
-            "if NO_TORCH:" in source
-        ), "NO_TORCH guard not found in install_python_stack.py"
+        assert "if NO_TORCH:" in source, "NO_TORCH guard not found in install_python_stack.py"
 
         # macOS guard for triton
         assert (
@@ -1037,7 +1015,6 @@ def _studio_venv_python() -> Path | None:
 def _server_port() -> int:
     """Find an available port for the test server."""
     import socket
-
     with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
         s.bind(("", 0))
         return s.getsockname()[1]
@@ -1117,9 +1094,7 @@ class TestLiveServerStartup:
         for _ in range(30):
             time.sleep(1)
             try:
-                resp = urllib.request.urlopen(
-                    f"http://127.0.0.1:{port}/api/health", timeout = 2
-                )
+                resp = urllib.request.urlopen(f"http://127.0.0.1:{port}/api/health", timeout = 2)
                 if resp.status == 200:
                     ready = True
                     break
@@ -1143,12 +1118,8 @@ class TestLiveServerStartup:
                     capture_output = True,
                     timeout = 300,
                 )
-            server_output = stdout.decode(errors = "replace") + stderr.decode(
-                errors = "replace"
-            )
-            pytest.skip(
-                f"Server failed to start within 30 seconds. Output:\n{server_output}"
-            )
+            server_output = stdout.decode(errors = "replace") + stderr.decode(errors = "replace")
+            pytest.skip(f"Server failed to start within 30 seconds. Output:\n{server_output}")
 
         yield proc, port
 
@@ -1192,9 +1163,7 @@ class TestLiveServerStartup:
         import urllib.request
 
         _, port = server_process
-        resp = urllib.request.urlopen(
-            f"http://127.0.0.1:{port}/openapi.json", timeout = 5
-        )
+        resp = urllib.request.urlopen(f"http://127.0.0.1:{port}/openapi.json", timeout = 5)
         spec = json.loads(resp.read())
         assert (
             len(spec.get("paths", {})) >= 20
diff --git a/tests/python/test_fast_sentence_transformer_redirect_lifecycle.py b/tests/python/test_fast_sentence_transformer_redirect_lifecycle.py
index 31d86b09a4..3f5f235aae 100644
--- a/tests/python/test_fast_sentence_transformer_redirect_lifecycle.py
+++ b/tests/python/test_fast_sentence_transformer_redirect_lifecycle.py
@@ -62,7 +62,6 @@ class _RecordingTransformerOk:
 
     def __init__(self, model_name, **kwargs):
         from transformers import AutoModel, AutoProcessor, AutoTokenizer
-
         type(self).last_calls = {
             "model": AutoModel.from_pretrained(model_name),
             "processor": AutoProcessor.from_pretrained(model_name),
@@ -73,7 +72,6 @@ class _RecordingTransformerOk:
 class _RaisingTransformer:
     def __init__(self, *a, **kw):
         from transformers import AutoModel
-
         AutoModel.from_pretrained(a[0] if a else kw.get("model_name_or_path"))
         raise RuntimeError("simulated init failure")
 
@@ -129,18 +127,10 @@ def _build_driver(transformer_class):
             return model if is_requested_model_name(a, kw) else original_model(*a, **kw)
 
         def return_existing_tokenizer(*a, **kw):
-            return (
-                tokenizer
-                if is_requested_model_name(a, kw)
-                else original_tokenizer(*a, **kw)
-            )
+            return tokenizer if is_requested_model_name(a, kw) else original_tokenizer(*a, **kw)
 
         def return_existing_processor(*a, **kw):
-            return (
-                tokenizer
-                if is_requested_model_name(a, kw)
-                else original_processor(*a, **kw)
-            )
+            return tokenizer if is_requested_model_name(a, kw) else original_processor(*a, **kw)
 
         try:
             AutoModel.from_pretrained = return_existing_model
@@ -190,7 +180,6 @@ def test_redirect_passes_through_for_other_model_names():
 
         def __init__(self, model_name, **kw):
             from transformers import AutoModel
-
             type(self).captured = AutoModel.from_pretrained("some-other/aux-model")
 
     driver, *_ = _build_driver(_OtherNameTransformer)
@@ -210,7 +199,6 @@ def test_is_requested_model_name_handles_pathlib_path(tmp_path):
 
         def __init__(self, model_name, **kw):
             from transformers import AutoModel
-
             type(self).last_calls = AutoModel.from_pretrained(pathlib.Path(model_name))
 
     driver, *_ = _build_driver(_PathTransformer)
@@ -228,7 +216,6 @@ def test_is_requested_model_name_trailing_slash_local_path(tmp_path):
 
         def __init__(self, model_name, **kw):
             from transformers import AutoModel
-
             type(self).last_calls = AutoModel.from_pretrained(str(target) + "/")
 
     driver, *_ = _build_driver(_SlashTransformer)
@@ -243,7 +230,6 @@ def test_is_requested_model_name_returns_false_when_no_identifier():
     class _NoNameTransformer:
         def __init__(self, model_name, **kw):
             from transformers import AutoModel
-
             captured["args"] = AutoModel.from_pretrained(some_other_kwarg = "x")
 
     driver, *_ = _build_driver(_NoNameTransformer)
diff --git a/tests/python/test_flash_attn_install_python_stack.py b/tests/python/test_flash_attn_install_python_stack.py
index 49f4350a7b..26ff03505a 100644
--- a/tests/python/test_flash_attn_install_python_stack.py
+++ b/tests/python/test_flash_attn_install_python_stack.py
@@ -33,64 +33,42 @@ class TestHasBlackwellGpu:
 
     def test_returns_true_for_sm_100(self):
         with (
-            mock.patch.object(
-                wheel_utils.shutil, "which", return_value = "/usr/bin/nvidia-smi"
-            ),
-            mock.patch.object(
-                wheel_utils.subprocess, "run", return_value = _smi_result("10.0\n")
-            ),
+            mock.patch.object(wheel_utils.shutil, "which", return_value = "/usr/bin/nvidia-smi"),
+            mock.patch.object(wheel_utils.subprocess, "run", return_value = _smi_result("10.0\n")),
         ):
             assert wheel_utils.has_blackwell_gpu() is True
 
     def test_returns_true_for_sm_120(self):
         with (
-            mock.patch.object(
-                wheel_utils.shutil, "which", return_value = "/usr/bin/nvidia-smi"
-            ),
-            mock.patch.object(
-                wheel_utils.subprocess, "run", return_value = _smi_result("12.0\n")
-            ),
+            mock.patch.object(wheel_utils.shutil, "which", return_value = "/usr/bin/nvidia-smi"),
+            mock.patch.object(wheel_utils.subprocess, "run", return_value = _smi_result("12.0\n")),
         ):
             assert wheel_utils.has_blackwell_gpu() is True
 
     def test_returns_true_for_sm_121(self):
         with (
-            mock.patch.object(
-                wheel_utils.shutil, "which", return_value = "/usr/bin/nvidia-smi"
-            ),
-            mock.patch.object(
-                wheel_utils.subprocess, "run", return_value = _smi_result("12.1\n")
-            ),
+            mock.patch.object(wheel_utils.shutil, "which", return_value = "/usr/bin/nvidia-smi"),
+            mock.patch.object(wheel_utils.subprocess, "run", return_value = _smi_result("12.1\n")),
         ):
             assert wheel_utils.has_blackwell_gpu() is True
 
     def test_returns_false_for_sm_90(self):
         with (
-            mock.patch.object(
-                wheel_utils.shutil, "which", return_value = "/usr/bin/nvidia-smi"
-            ),
-            mock.patch.object(
-                wheel_utils.subprocess, "run", return_value = _smi_result("9.0\n")
-            ),
+            mock.patch.object(wheel_utils.shutil, "which", return_value = "/usr/bin/nvidia-smi"),
+            mock.patch.object(wheel_utils.subprocess, "run", return_value = _smi_result("9.0\n")),
         ):
             assert wheel_utils.has_blackwell_gpu() is False
 
     def test_returns_false_for_sm_89(self):
         with (
-            mock.patch.object(
-                wheel_utils.shutil, "which", return_value = "/usr/bin/nvidia-smi"
-            ),
-            mock.patch.object(
-                wheel_utils.subprocess, "run", return_value = _smi_result("8.9\n")
-            ),
+            mock.patch.object(wheel_utils.shutil, "which", return_value = "/usr/bin/nvidia-smi"),
+            mock.patch.object(wheel_utils.subprocess, "run", return_value = _smi_result("8.9\n")),
         ):
             assert wheel_utils.has_blackwell_gpu() is False
 
     def test_mixed_gpus_with_one_blackwell_returns_true(self):
         with (
-            mock.patch.object(
-                wheel_utils.shutil, "which", return_value = "/usr/bin/nvidia-smi"
-            ),
+            mock.patch.object(wheel_utils.shutil, "which", return_value = "/usr/bin/nvidia-smi"),
             mock.patch.object(
                 wheel_utils.subprocess,
                 "run",
@@ -101,9 +79,7 @@ class TestHasBlackwellGpu:
 
     def test_returns_false_when_nvidia_smi_fails(self):
         with (
-            mock.patch.object(
-                wheel_utils.shutil, "which", return_value = "/usr/bin/nvidia-smi"
-            ),
+            mock.patch.object(wheel_utils.shutil, "which", return_value = "/usr/bin/nvidia-smi"),
             mock.patch.object(
                 wheel_utils.subprocess,
                 "run",
@@ -114,9 +90,7 @@ class TestHasBlackwellGpu:
 
     def test_returns_false_on_subprocess_timeout(self):
         with (
-            mock.patch.object(
-                wheel_utils.shutil, "which", return_value = "/usr/bin/nvidia-smi"
-            ),
+            mock.patch.object(wheel_utils.shutil, "which", return_value = "/usr/bin/nvidia-smi"),
             mock.patch.object(
                 wheel_utils.subprocess,
                 "run",
@@ -127,9 +101,7 @@ class TestHasBlackwellGpu:
 
     def test_returns_false_on_malformed_output(self):
         with (
-            mock.patch.object(
-                wheel_utils.shutil, "which", return_value = "/usr/bin/nvidia-smi"
-            ),
+            mock.patch.object(wheel_utils.shutil, "which", return_value = "/usr/bin/nvidia-smi"),
             mock.patch.object(
                 wheel_utils.subprocess,
                 "run",
@@ -161,10 +133,7 @@ class TestFlashAttnWheelSelection:
         )
         assert url is not None
         assert "v2.8.1" in url
-        assert (
-            "flash_attn-2.8.1+cu12torch2.10cxx11abiTRUE-cp313-cp313-linux_x86_64.whl"
-            in url
-        )
+        assert "flash_attn-2.8.1+cu12torch2.10cxx11abiTRUE-cp313-cp313-linux_x86_64.whl" in url
 
     def test_missing_cuda_major_disables_wheel_lookup(self):
         assert (
@@ -262,7 +231,11 @@ class TestEnsureFlashAttn:
         step_messages: list[tuple[str, str]] = []
         printed_failures: list[str] = []
 
-        def fake_step(label: str, value: str, color_fn = None):
+        def fake_step(
+            label: str,
+            value: str,
+            color_fn = None,
+        ):
             step_messages.append((label, value))
 
         with (
@@ -313,7 +286,11 @@ class TestEnsureFlashAttn:
     def test_wheel_missing_skips_install_at_setup_time(self):
         step_messages: list[tuple[str, str]] = []
 
-        def fake_step(label: str, value: str, color_fn = None):
+        def fake_step(
+            label: str,
+            value: str,
+            color_fn = None,
+        ):
             step_messages.append((label, value))
 
         with (
@@ -339,10 +316,7 @@ class TestEnsureFlashAttn:
             ips._ensure_flash_attn()
 
         mock_install_wheel.assert_not_called()
-        assert (
-            "warning",
-            "No published flash-attn prebuilt wheel found",
-        ) in step_messages
+        assert ("warning", "No published flash-attn prebuilt wheel found") in step_messages
 
     def test_skip_env_disables_setup_install(self):
         with (
@@ -362,7 +336,11 @@ class TestEnsureFlashAttn:
     def test_blackwell_gpu_skips_install_with_warning(self):
         step_messages: list[tuple[str, str]] = []
 
-        def fake_step(label: str, value: str, color_fn = None):
+        def fake_step(
+            label: str,
+            value: str,
+            color_fn = None,
+        ):
             step_messages.append((label, value))
 
         with (
@@ -379,14 +357,16 @@ class TestEnsureFlashAttn:
 
         mock_probe.assert_not_called()
         mock_install_wheel.assert_not_called()
-        assert any(
-            label == "warning" and "Blackwell" in msg for label, msg in step_messages
-        )
+        assert any(label == "warning" and "Blackwell" in msg for label, msg in step_messages)
 
     def test_blackwell_gpu_on_windows_emits_blackwell_warning(self):
         step_messages: list[tuple[str, str]] = []
 
-        def fake_step(label: str, value: str, color_fn = None):
+        def fake_step(
+            label: str,
+            value: str,
+            color_fn = None,
+        ):
             step_messages.append((label, value))
 
         with (
@@ -403,14 +383,16 @@ class TestEnsureFlashAttn:
 
         mock_probe.assert_not_called()
         mock_install_wheel.assert_not_called()
-        assert any(
-            label == "warning" and "Blackwell" in msg for label, msg in step_messages
-        )
+        assert any(label == "warning" and "Blackwell" in msg for label, msg in step_messages)
 
     def test_non_blackwell_windows_does_not_emit_blackwell_warning(self):
         step_messages: list[tuple[str, str]] = []
 
-        def fake_step(label: str, value: str, color_fn = None):
+        def fake_step(
+            label: str,
+            value: str,
+            color_fn = None,
+        ):
             step_messages.append((label, value))
 
         with (
@@ -453,9 +435,7 @@ class TestInstallPythonStackFlashAttnIntegration:
             mock.patch("subprocess.run", side_effect = fake_run),
             mock.patch.object(ips, "_has_usable_nvidia_gpu", return_value = False),
             mock.patch.object(ips, "_has_rocm_gpu", return_value = False),
-            mock.patch.object(
-                ips, "LOCAL_DD_UNSTRUCTURED_PLUGIN", Path("/fake/plugin")
-            ),
+            mock.patch.object(ips, "LOCAL_DD_UNSTRUCTURED_PLUGIN", Path("/fake/plugin")),
             mock.patch("pathlib.Path.is_dir", return_value = True),
             mock.patch("pathlib.Path.is_file", return_value = True),
             mock.patch.dict(os.environ, {"SKIP_STUDIO_BASE": "1"}, clear = False),
diff --git a/tests/python/test_gpu_init_ldconfig_guard.py b/tests/python/test_gpu_init_ldconfig_guard.py
index 081a6132b4..248bb84faa 100644
--- a/tests/python/test_gpu_init_ldconfig_guard.py
+++ b/tests/python/test_gpu_init_ldconfig_guard.py
@@ -19,9 +19,7 @@ def _find_geteuid_guard(tree: ast.AST):
 def test_gpu_init_has_geteuid_guard():
     tree = ast.parse(GPU_INIT.read_text())
     guard = _find_geteuid_guard(tree)
-    assert (
-        guard is not None
-    ), "_gpu_init.py must guard ldconfig recovery on os.geteuid()"
+    assert guard is not None, "_gpu_init.py must guard ldconfig recovery on os.geteuid()"
 
 
 def test_ldconfig_calls_only_inside_geteuid_guard():
diff --git a/tests/python/test_no_torch_filtering.py b/tests/python/test_no_torch_filtering.py
index 29cadf87ae..f7a90fc6a8 100644
--- a/tests/python/test_no_torch_filtering.py
+++ b/tests/python/test_no_torch_filtering.py
@@ -156,9 +156,7 @@ class TestFilterRequirements:
         )
         # First filter Windows packages, then NO_TORCH packages
         intermediate = ips._filter_requirements(req, ips.WINDOWS_SKIP_PACKAGES)
-        result = ips._filter_requirements(
-            Path(intermediate), ips.NO_TORCH_SKIP_PACKAGES
-        )
+        result = ips._filter_requirements(Path(intermediate), ips.NO_TORCH_SKIP_PACKAGES)
         lines = Path(result).read_text(encoding = "utf-8").splitlines()
         non_blank = [l.strip() for l in lines if l.strip()]
         assert non_blank == [
@@ -177,9 +175,7 @@ class TestFilterRequirements:
         result = ips._filter_requirements(req, ips.NO_TORCH_SKIP_PACKAGES)
         lines = Path(result).read_text(encoding = "utf-8").splitlines()
         non_blank = [l.strip() for l in lines if l.strip()]
-        assert non_blank == [
-            "numpy"
-        ], f"VCS URL line should be filtered, got: {non_blank}"
+        assert non_blank == ["numpy"], f"VCS URL line should be filtered, got: {non_blank}"
 
     def test_env_marker_line_filtered(self, tmp_path):
         """Package lines with env markers are still filtered by prefix."""
@@ -193,9 +189,7 @@ class TestFilterRequirements:
         result = ips._filter_requirements(req, ips.NO_TORCH_SKIP_PACKAGES)
         lines = Path(result).read_text(encoding = "utf-8").splitlines()
         non_blank = [l.strip() for l in lines if l.strip()]
-        assert non_blank == [
-            "numpy"
-        ], f"Env marker line should be filtered, got: {non_blank}"
+        assert non_blank == ["numpy"], f"Env marker line should be filtered, got: {non_blank}"
 
     def test_git_plus_url_not_over_matched(self, tmp_path):
         """A git+ URL whose path contains a skip package name but does NOT start with it."""
@@ -247,9 +241,7 @@ class TestRealRequirementsFiltering:
         expected = [
             l
             for l in original
-            if not any(
-                l.strip().lower().startswith(p) for p in ips.NO_TORCH_SKIP_PACKAGES
-            )
+            if not any(l.strip().lower().startswith(p) for p in ips.NO_TORCH_SKIP_PACKAGES)
         ]
         assert filtered == expected, (
             f"Filtered extras.txt should match expected.\n"
@@ -259,9 +251,7 @@ class TestRealRequirementsFiltering:
 
     def test_extras_no_deps_txt_torchcodec_and_dlpack_removed(self):
         """extras-no-deps.txt: torchcodec and torch-c-dlpack-ext must be removed."""
-        result = ips._filter_requirements(
-            EXTRAS_NO_DEPS_TXT, ips.NO_TORCH_SKIP_PACKAGES
-        )
+        result = ips._filter_requirements(EXTRAS_NO_DEPS_TXT, ips.NO_TORCH_SKIP_PACKAGES)
         filtered = self._non_blank_non_comment(Path(result))
         original = self._non_blank_non_comment(EXTRAS_NO_DEPS_TXT)
 
@@ -273,9 +263,7 @@ class TestRealRequirementsFiltering:
         expected = [
             l
             for l in original
-            if not any(
-                l.strip().lower().startswith(p) for p in ips.NO_TORCH_SKIP_PACKAGES
-            )
+            if not any(l.strip().lower().startswith(p) for p in ips.NO_TORCH_SKIP_PACKAGES)
         ]
         assert filtered == expected
 
@@ -291,9 +279,7 @@ class TestRealRequirementsFiltering:
 
     def test_extras_no_deps_txt_trl_preserved(self):
         """trl should survive NO_TORCH filtering in extras-no-deps.txt."""
-        result = ips._filter_requirements(
-            EXTRAS_NO_DEPS_TXT, ips.NO_TORCH_SKIP_PACKAGES
-        )
+        result = ips._filter_requirements(EXTRAS_NO_DEPS_TXT, ips.NO_TORCH_SKIP_PACKAGES)
         filtered_text = Path(result).read_text(encoding = "utf-8").lower()
         assert "trl" in filtered_text, "trl should survive NO_TORCH filtering"
 
@@ -370,7 +356,6 @@ class TestIsMacosConstant:
 
     def test_is_macos_matches_platform(self):
         import sys
-
         expected = sys.platform == "darwin"
         assert ips.IS_MACOS is expected
 
@@ -405,9 +390,7 @@ class TestInstallPythonStackSubprocessMock:
         captured_cmds: list[list[str]] = []
 
         def mock_run(cmd, **kw):
-            captured_cmds.append(
-                list(cmd) if isinstance(cmd, (list, tuple)) else [str(cmd)]
-            )
+            captured_cmds.append(list(cmd) if isinstance(cmd, (list, tuple)) else [str(cmd)])
             return subprocess.CompletedProcess(cmd, 0, b"", b"")
 
         env = {"SKIP_STUDIO_BASE": "1"} if skip_base else {}
@@ -424,9 +407,7 @@ class TestInstallPythonStackSubprocessMock:
             mock.patch.object(ips, "_has_rocm_gpu", return_value = False),
             mock.patch("subprocess.run", side_effect = mock_run),
             mock.patch.object(ips, "_bootstrap_uv", return_value = True),
-            mock.patch.object(
-                ips, "LOCAL_DD_UNSTRUCTURED_PLUGIN", Path("/fake/plugin")
-            ),
+            mock.patch.object(ips, "LOCAL_DD_UNSTRUCTURED_PLUGIN", Path("/fake/plugin")),
             mock.patch("pathlib.Path.is_dir", return_value = True),
             mock.patch("pathlib.Path.is_file", return_value = True),
         ):
@@ -469,9 +450,7 @@ class TestInstallPythonStackSubprocessMock:
         has_extras_nd = self._cmds_contain_file(cmds, "extras-no-deps.txt") or any(
             "-r" in cmd and "tmp" in cmd.lower() for cmd in cmds
         )
-        assert (
-            has_extras_nd
-        ), "extras-no-deps.txt (or its filtered temp) should be called"
+        assert has_extras_nd, "extras-no-deps.txt (or its filtered temp) should be called"
 
     # -- IS_WINDOWS=True + NO_TORCH=True (stacked) --
 
@@ -570,17 +549,13 @@ class TestOverridesSkip:
     def test_no_torch_guard_exists_in_source(self):
         """The install_python_stack source must contain a NO_TORCH guard around overrides."""
         source = Path(ips.__file__).read_text(encoding = "utf-8")
-        assert (
-            "if NO_TORCH:" in source
-        ), "NO_TORCH guard not found in install_python_stack.py"
+        assert "if NO_TORCH:" in source, "NO_TORCH guard not found in install_python_stack.py"
 
     def test_overrides_skipped_when_no_torch(self):
         """With NO_TORCH=True on the module, pip_install should NOT be called for overrides."""
         source = Path(ips.__file__).read_text(encoding = "utf-8")
         overrides_match = re.search(r"if NO_TORCH:.*?overrides", source, re.DOTALL)
-        assert (
-            overrides_match is not None
-        ), "Expected NO_TORCH conditional before overrides install"
+        assert overrides_match is not None, "Expected NO_TORCH conditional before overrides install"
 
 
 # ── install.sh --no-torch flag tests ──────────────────────────────────
@@ -599,33 +574,21 @@ class TestInstallShNoTorchFlag:
 
     def test_no_torch_flag_in_case_statement(self):
         """--no-torch must appear in the flag parser case statement."""
-        assert (
-            "--no-torch)" in self.source
-        ), "--no-torch not found in install.sh flag parser"
+        assert "--no-torch)" in self.source, "--no-torch not found in install.sh flag parser"
 
     def test_no_torch_flag_variable_initialized(self):
         """_NO_TORCH_FLAG must be initialized to false."""
-        assert (
-            "_NO_TORCH_FLAG=false" in self.source
-        ), "_NO_TORCH_FLAG=false not found in install.sh"
+        assert "_NO_TORCH_FLAG=false" in self.source, "_NO_TORCH_FLAG=false not found in install.sh"
 
     def test_skip_torch_variable_exists(self):
         """SKIP_TORCH variable must be defined."""
-        assert (
-            "SKIP_TORCH=false" in self.source
-        ), "SKIP_TORCH=false not found in install.sh"
-        assert (
-            "SKIP_TORCH=true" in self.source
-        ), "SKIP_TORCH=true not found in install.sh"
+        assert "SKIP_TORCH=false" in self.source, "SKIP_TORCH=false not found in install.sh"
+        assert "SKIP_TORCH=true" in self.source, "SKIP_TORCH=true not found in install.sh"
 
     def test_skip_torch_driven_by_flag_and_mac_intel(self):
         """SKIP_TORCH must check both _NO_TORCH_FLAG and MAC_INTEL."""
-        assert (
-            "_NO_TORCH_FLAG" in self.source
-        ), "_NO_TORCH_FLAG not referenced in SKIP_TORCH logic"
-        assert (
-            "MAC_INTEL" in self.source
-        ), "MAC_INTEL not referenced in SKIP_TORCH logic"
+        assert "_NO_TORCH_FLAG" in self.source, "_NO_TORCH_FLAG not referenced in SKIP_TORCH logic"
+        assert "MAC_INTEL" in self.source, "MAC_INTEL not referenced in SKIP_TORCH logic"
 
     def test_unsloth_no_torch_uses_skip_torch(self):
         """UNSLOTH_NO_TORCH must reference $SKIP_TORCH, not $MAC_INTEL."""
@@ -633,18 +596,12 @@ class TestInstallShNoTorchFlag:
 
         matches = re.findall(r'UNSLOTH_NO_TORCH="\$(\w+)"', self.source)
         for var in matches:
-            assert (
-                var == "SKIP_TORCH"
-            ), f"UNSLOTH_NO_TORCH references ${var} instead of $SKIP_TORCH"
+            assert var == "SKIP_TORCH", f"UNSLOTH_NO_TORCH references ${var} instead of $SKIP_TORCH"
 
     def test_cpu_hint_message_exists(self):
         """CPU hint message must exist in install.sh."""
-        assert (
-            "No GPU detected" in self.source
-        ), "CPU hint message not found in install.sh"
-        assert (
-            "--no-torch" in self.source
-        ), "--no-torch suggestion not found in CPU hint"
+        assert "No GPU detected" in self.source, "CPU hint message not found in install.sh"
+        assert "--no-torch" in self.source, "--no-torch suggestion not found in CPU hint"
 
     def test_no_torch_flag_parsing_subprocess(self):
         """--no-torch flag sets _NO_TORCH_FLAG=true (subprocess test)."""
diff --git a/tests/python/test_orpo_processor_text_tokenizer.py b/tests/python/test_orpo_processor_text_tokenizer.py
index 44c4e26a86..9ae205c6b9 100644
--- a/tests/python/test_orpo_processor_text_tokenizer.py
+++ b/tests/python/test_orpo_processor_text_tokenizer.py
@@ -34,7 +34,12 @@ class _Tokenizer:
     def __init__(self):
         self.calls = []
 
-    def __call__(self, text, add_special_tokens = False, **kwargs):
+    def __call__(
+        self,
+        text,
+        add_special_tokens = False,
+        **kwargs,
+    ):
         self.calls.append((text, add_special_tokens, kwargs))
         ids = [ord(c) % 31 + 3 for c in text]
         return {"input_ids": ids, "attention_mask": [1] * len(ids)}
@@ -60,7 +65,11 @@ class _Trainer:
         self.padding_value = 0
 
 
-def _exec_rewritten(function_name, source, extra_ns = None):
+def _exec_rewritten(
+    function_name,
+    source,
+    extra_ns = None,
+):
     rewriter = _load_orpo_rewriter()
     rewritten = rewriter(function_name, source)
     ns = {} if extra_ns is None else dict(extra_ns)
diff --git a/tests/python/test_studio_import_no_torch.py b/tests/python/test_studio_import_no_torch.py
index 5592a282ff..c8b67023f5 100644
--- a/tests/python/test_studio_import_no_torch.py
+++ b/tests/python/test_studio_import_no_torch.py
@@ -23,15 +23,9 @@ from pathlib import Path
 import pytest
 
 REPO_ROOT = Path(__file__).resolve().parents[2]
-DATA_COLLATORS = (
-    REPO_ROOT / "studio" / "backend" / "utils" / "datasets" / "data_collators.py"
-)
-CHAT_TEMPLATES = (
-    REPO_ROOT / "studio" / "backend" / "utils" / "datasets" / "chat_templates.py"
-)
-FORMAT_CONVERSION = (
-    REPO_ROOT / "studio" / "backend" / "utils" / "datasets" / "format_conversion.py"
-)
+DATA_COLLATORS = REPO_ROOT / "studio" / "backend" / "utils" / "datasets" / "data_collators.py"
+CHAT_TEMPLATES = REPO_ROOT / "studio" / "backend" / "utils" / "datasets" / "chat_templates.py"
+FORMAT_CONVERSION = REPO_ROOT / "studio" / "backend" / "utils" / "datasets" / "format_conversion.py"
 
 
 def _has_uv() -> bool:
@@ -72,9 +66,7 @@ def no_torch_venv(request, tmp_path_factory):
         [str(venv_python), "-c", "import torch"],
         capture_output = True,
     )
-    assert (
-        check.returncode != 0
-    ), f"torch should NOT be importable in fresh {py_version} venv"
+    assert check.returncode != 0, f"torch should NOT be importable in fresh {py_version} venv"
 
     return str(venv_python)
 
@@ -223,9 +215,7 @@ class TestDataCollatorsNoTorchVenv:
             capture_output = True,
             timeout = 30,
         )
-        assert (
-            result.returncode == 0
-        ), f"DeepSeekOCRDataCollator failed:\n{result.stderr.decode()}"
+        assert result.returncode == 0, f"DeepSeekOCRDataCollator failed:\n{result.stderr.decode()}"
         assert b"OK: DeepSeekOCRDataCollator instantiated" in result.stdout
 
     def test_dataclass_vlm_collator_instantiable(self, no_torch_venv):
@@ -246,9 +236,7 @@ class TestDataCollatorsNoTorchVenv:
             capture_output = True,
             timeout = 30,
         )
-        assert (
-            result.returncode == 0
-        ), f"VLMDataCollator failed:\n{result.stderr.decode()}"
+        assert result.returncode == 0, f"VLMDataCollator failed:\n{result.stderr.decode()}"
         assert b"OK: VLMDataCollator instantiated" in result.stdout
 
 
@@ -529,12 +517,9 @@ class TestNegativeControls:
                 capture_output = True,
                 timeout = 30,
             )
+            assert result.returncode != 0, "Expected failure when 'import torch' is prepended"
             assert (
-                result.returncode != 0
-            ), "Expected failure when 'import torch' is prepended"
-            assert (
-                b"ModuleNotFoundError" in result.stderr
-                or b"ImportError" in result.stderr
+                b"ModuleNotFoundError" in result.stderr or b"ImportError" in result.stderr
             ), f"Expected ImportError, got:\n{result.stderr.decode()}"
         finally:
             os.unlink(temp_file)
@@ -577,6 +562,4 @@ class TestNegativeControls:
             timeout = 30,
         )
         assert result.returncode != 0, "import torch should fail in no-torch venv"
-        assert (
-            b"ModuleNotFoundError" in result.stderr or b"ImportError" in result.stderr
-        )
+        assert b"ModuleNotFoundError" in result.stderr or b"ImportError" in result.stderr
diff --git a/tests/python/test_tokenizers_and_torch_constraint.py b/tests/python/test_tokenizers_and_torch_constraint.py
index 4be53d2d03..17f2d17f94 100644
--- a/tests/python/test_tokenizers_and_torch_constraint.py
+++ b/tests/python/test_tokenizers_and_torch_constraint.py
@@ -18,9 +18,7 @@ _TESTS_DIR = pathlib.Path(__file__).resolve().parent.parent  # tests/
 _REPO_ROOT = _TESTS_DIR.parent  # unsloth/
 _INSTALL_SH = _REPO_ROOT / "install.sh"
 _INSTALL_PS1 = _REPO_ROOT / "install.ps1"
-_NO_TORCH_RT = (
-    _REPO_ROOT / "studio" / "backend" / "requirements" / "no-torch-runtime.txt"
-)
+_NO_TORCH_RT = _REPO_ROOT / "studio" / "backend" / "requirements" / "no-torch-runtime.txt"
 
 
 def _read(path: pathlib.Path) -> str:
@@ -45,30 +43,23 @@ class TestStructuralTokenizers:
     def test_tokenizers_present(self):
         """tokenizers must be a standalone package line."""
         pkgs = _lines(_NO_TORCH_RT)
-        bare_names = [
-            p.split(">")[0].split("<")[0].split("!")[0].split("=")[0] for p in pkgs
-        ]
+        bare_names = [p.split(">")[0].split("<")[0].split("!")[0].split("=")[0] for p in pkgs]
         assert "tokenizers" in bare_names
 
     def test_tokenizers_before_transformers(self):
         """tokenizers should appear before transformers (install order intent)."""
         pkgs = _lines(_NO_TORCH_RT)
-        bare_names = [
-            p.split(">")[0].split("<")[0].split("!")[0].split("=")[0] for p in pkgs
-        ]
+        bare_names = [p.split(">")[0].split("<")[0].split("!")[0].split("=")[0] for p in pkgs]
         idx_tok = bare_names.index("tokenizers")
         idx_tf = bare_names.index("transformers")
         assert idx_tok < idx_tf, (
-            f"tokenizers at index {idx_tok} should appear before "
-            f"transformers at index {idx_tf}"
+            f"tokenizers at index {idx_tok} should appear before " f"transformers at index {idx_tf}"
         )
 
     def test_torch_not_in_no_torch_file(self):
         """torch itself must NOT be listed in the no-torch requirements."""
         pkgs = _lines(_NO_TORCH_RT)
-        bare_names = [
-            p.split(">")[0].split("<")[0].split("!")[0].split("=")[0] for p in pkgs
-        ]
+        bare_names = [p.split(">")[0].split("<")[0].split("!")[0].split("=")[0] for p in pkgs]
         assert "torch" not in bare_names
 
 
@@ -409,9 +400,7 @@ class TestE2ETokenizersFix:
         r = self._pip_install(venv, "--no-deps", "-r", str(_NO_TORCH_RT))
         assert r.returncode == 0, f"Install failed: {r.stderr}"
 
-        result = self._run_python(
-            venv, "from transformers import AutoConfig; print('OK')"
-        )
+        result = self._run_python(venv, "from transformers import AutoConfig; print('OK')")
         assert (
             result.returncode == 0
         ), f"AutoConfig import failed:\nstdout: {result.stdout}\nstderr: {result.stderr}"
@@ -441,22 +430,15 @@ class TestE2ETokenizersFix:
         req_no_tokenizers = tmp_path / "no-tokenizers.txt"
         req_no_tokenizers.write_text(
             "\n".join(
-                line
-                for line in _read(_NO_TORCH_RT).splitlines()
-                if line.strip() != "tokenizers"
+                line for line in _read(_NO_TORCH_RT).splitlines() if line.strip() != "tokenizers"
             ),
             encoding = "utf-8",
         )
         r = self._pip_install(venv, "--no-deps", "-r", str(req_no_tokenizers))
         assert r.returncode == 0, f"Install failed: {r.stderr}"
         result = self._run_python(venv, "from transformers import AutoConfig")
-        assert (
-            result.returncode != 0
-        ), "AutoConfig should fail without tokenizers installed"
-        assert (
-            "tokenizers" in result.stderr.lower()
-            or "ModuleNotFoundError" in result.stderr
-        )
+        assert result.returncode != 0, "AutoConfig should fail without tokenizers installed"
+        assert "tokenizers" in result.stderr.lower() or "ModuleNotFoundError" in result.stderr
 
 
 # ======================================================================
@@ -535,9 +517,7 @@ class TestE2EFullNoTorchSandbox:
         venv = self._create_venv(tmp_path, "full-no-torch")
         r = self._pip_install(venv, "--no-deps", "-r", str(_NO_TORCH_RT))
         assert r.returncode == 0, f"Install failed: {r.stderr}"
-        result = self._run_python(
-            venv, "from transformers import AutoConfig; print('OK')"
-        )
+        result = self._run_python(venv, "from transformers import AutoConfig; print('OK')")
         assert (
             result.returncode == 0
         ), f"AutoConfig failed:\nstdout: {result.stdout}\nstderr: {result.stderr}"
diff --git a/tests/python/test_unsloth_run_tool_policy_resolver.py b/tests/python/test_unsloth_run_tool_policy_resolver.py
index 6aff02494b..6e3e3a722d 100644
--- a/tests/python/test_unsloth_run_tool_policy_resolver.py
+++ b/tests/python/test_unsloth_run_tool_policy_resolver.py
@@ -141,15 +141,11 @@ class TestZeroHost:
 
 
 class TestIsExternalHost:
-    @pytest.mark.parametrize(
-        "host", ["127.0.0.1", "localhost", "::1", "LOCALHOST", "Localhost"]
-    )
+    @pytest.mark.parametrize("host", ["127.0.0.1", "localhost", "::1", "LOCALHOST", "Localhost"])
     def test_loopback_aliases_are_local(self, host):
         assert is_external_host(host) is False
 
-    @pytest.mark.parametrize(
-        "host", ["0.0.0.0", "::", "192.168.1.5", "10.0.0.1", "example.com"]
-    )
+    @pytest.mark.parametrize("host", ["0.0.0.0", "::", "192.168.1.5", "10.0.0.1", "example.com"])
     def test_non_loopback_is_external(self, host):
         assert is_external_host(host) is True
 
diff --git a/tests/qlora/test_hf_qlora_train_and_merge.py b/tests/qlora/test_hf_qlora_train_and_merge.py
index ae975b0266..0892627c46 100644
--- a/tests/qlora/test_hf_qlora_train_and_merge.py
+++ b/tests/qlora/test_hf_qlora_train_and_merge.py
@@ -91,9 +91,7 @@ if __name__ == "__main__":
         print(training_args)
         print(peft_config)
 
-    trainer = setup_trainer(
-        model, tokenizer, dataset, training_args, peft_config = peft_config
-    )
+    trainer = setup_trainer(model, tokenizer, dataset, training_args, peft_config = peft_config)
 
     with header_footer_context("Model"):
         print(type(model.model))
diff --git a/tests/saving/gpt-oss-merge/test_merged_model.py b/tests/saving/gpt-oss-merge/test_merged_model.py
index 48f0ed2d3d..497c74debf 100644
--- a/tests/saving/gpt-oss-merge/test_merged_model.py
+++ b/tests/saving/gpt-oss-merge/test_merged_model.py
@@ -42,9 +42,7 @@ inputs = merged_tokenizer.apply_chat_template(
     reasoning_effort = "low",  # **NEW!** Set reasoning effort to low, medium or high
 ).to(merged_model.device)
 
-_ = merged_model.generate(
-    **inputs, max_new_tokens = 512, streamer = TextStreamer(merged_tokenizer)
-)
+_ = merged_model.generate(**inputs, max_new_tokens = 512, streamer = TextStreamer(merged_tokenizer))
 print("\n✅ Inference complete.")
 
 # --- Final Cleanup ---
@@ -54,7 +52,5 @@ torch.cuda.empty_cache()
 gc.collect()
 
 safe_remove_directory("./gpt-oss-finetuned-merged")
-safe_remove_directory(
-    "./unsloth_compiled_cache"
-)  # Clean up cache created by this process
+safe_remove_directory("./unsloth_compiled_cache")  # Clean up cache created by this process
 print("✅ Final cleanup complete. Exiting inference script.")
diff --git a/tests/saving/gpt-oss-merge/train_and_merge.py b/tests/saving/gpt-oss-merge/train_and_merge.py
index 308d19bfb4..8c76ff9662 100644
--- a/tests/saving/gpt-oss-merge/train_and_merge.py
+++ b/tests/saving/gpt-oss-merge/train_and_merge.py
@@ -28,9 +28,7 @@ tokenizer = None
 def formatting_prompts_func(examples):
     convos = examples["messages"]
     texts = [
-        tokenizer.apply_chat_template(
-            convo, tokenize = False, add_generation_prompt = False
-        )
+        tokenizer.apply_chat_template(convo, tokenize = False, add_generation_prompt = False)
         for convo in convos
     ]
     return {"text": texts}
@@ -84,9 +82,7 @@ print("Fine-tuning complete.")
 
 # --- Merge and Save ---
 print("\n💾 Merging and saving the 16-bit model to './gpt-oss-finetuned-merged'...")
-model.save_pretrained_merged(
-    save_directory = "./gpt-oss-finetuned-merged", tokenizer = tokenizer
-)
+model.save_pretrained_merged(save_directory = "./gpt-oss-finetuned-merged", tokenizer = tokenizer)
 print("✅ Model merged and saved.")
 
 # --- Cleanup ---
@@ -96,7 +92,5 @@ torch.cuda.empty_cache()
 gc.collect()
 
 safe_remove_directory("./outputs")
-safe_remove_directory(
-    "./unsloth_compiled_cache"
-)  # Clean up the cache created by this process
+safe_remove_directory("./unsloth_compiled_cache")  # Clean up the cache created by this process
 print("✅ Cleanup complete. Exiting training script.")
diff --git a/tests/saving/language_models/test_merge_4bit_validation.py b/tests/saving/language_models/test_merge_4bit_validation.py
index 343e737710..c889001706 100644
--- a/tests/saving/language_models/test_merge_4bit_validation.py
+++ b/tests/saving/language_models/test_merge_4bit_validation.py
@@ -16,9 +16,7 @@ from tests.utils.cleanup_utils import safe_remove_directory
 def formatting_prompts_func(examples):
     convos = examples["messages"]
     texts = [
-        tokenizer.apply_chat_template(
-            convo, tokenize = False, add_generation_prompt = False
-        )
+        tokenizer.apply_chat_template(convo, tokenize = False, add_generation_prompt = False)
         for convo in convos
     ]
     return {"text": texts}
@@ -51,9 +49,7 @@ tokenizer = get_chat_template(
 )
 
 # Load small dataset for quick training
-dataset_train = load_dataset(
-    "allenai/openassistant-guanaco-reformatted", split = "train[:100]"
-)
+dataset_train = load_dataset("allenai/openassistant-guanaco-reformatted", split = "train[:100]")
 dataset_train = dataset_train.map(formatting_prompts_func, batched = True)
 
 print("✅ Base model loaded successfully!")
diff --git a/tests/saving/language_models/test_merge_model_perplexity_llama-3.2.py b/tests/saving/language_models/test_merge_model_perplexity_llama-3.2.py
index dd0e8c25c6..3f2b811b07 100644
--- a/tests/saving/language_models/test_merge_model_perplexity_llama-3.2.py
+++ b/tests/saving/language_models/test_merge_model_perplexity_llama-3.2.py
@@ -35,15 +35,17 @@ from tests.utils.perplexity_eval import (
 def formatting_prompts_func(examples):
     convos = examples["messages"]
     texts = [
-        tokenizer.apply_chat_template(
-            convo, tokenize = False, add_generation_prompt = False
-        )
+        tokenizer.apply_chat_template(convo, tokenize = False, add_generation_prompt = False)
         for convo in convos
     ]
     return {"text": texts}
 
 
-def load_and_compute_8bit_ppl(result_queue, load_in_4bit = False, load_in_8bit = False):
+def load_and_compute_8bit_ppl(
+    result_queue,
+    load_in_4bit = False,
+    load_in_8bit = False,
+):
     """Load model and compute perplexity in subprocess"""
     from unsloth import FastLanguageModel
     from unsloth.chat_templates import get_chat_template
@@ -63,17 +65,13 @@ def load_and_compute_8bit_ppl(result_queue, load_in_4bit = False, load_in_8bit =
     )
 
     # Load dataset fresh in subprocess
-    dataset_ppl = load_dataset(
-        "allenai/openassistant-guanaco-reformatted", split = "eval"
-    )
+    dataset_ppl = load_dataset("allenai/openassistant-guanaco-reformatted", split = "eval")
 
     # Format the dataset
     def formatting_prompts_func(examples):
         convos = examples["messages"]
         texts = [
-            merged_tokenizer.apply_chat_template(
-                convo, tokenize = False, add_generation_prompt = False
-            )
+            merged_tokenizer.apply_chat_template(convo, tokenize = False, add_generation_prompt = False)
             for convo in convos
         ]
         return {"text": texts}
@@ -130,12 +128,8 @@ if __name__ == "__main__":
 
     from unsloth.chat_templates import standardize_sharegpt
 
-    dataset_train = load_dataset(
-        "allenai/openassistant-guanaco-reformatted", split = "train"
-    )
-    dataset_ppl = load_dataset(
-        "allenai/openassistant-guanaco-reformatted", split = "eval"
-    )
+    dataset_train = load_dataset("allenai/openassistant-guanaco-reformatted", split = "train")
+    dataset_ppl = load_dataset("allenai/openassistant-guanaco-reformatted", split = "eval")
 
     dataset_train = dataset_train.map(formatting_prompts_func, batched = True)
     dataset_ppl = dataset_ppl.map(formatting_prompts_func, batched = True)
diff --git a/tests/saving/language_models/test_merge_model_perplexity_mistral.py b/tests/saving/language_models/test_merge_model_perplexity_mistral.py
index 14e657c68a..d17a20d755 100644
--- a/tests/saving/language_models/test_merge_model_perplexity_mistral.py
+++ b/tests/saving/language_models/test_merge_model_perplexity_mistral.py
@@ -30,7 +30,11 @@ from tests.utils.perplexity_eval import (
 )
 
 
-def load_and_compute_8bit_ppl(result_queue, load_in_4bit = False, load_in_8bit = False):
+def load_and_compute_8bit_ppl(
+    result_queue,
+    load_in_4bit = False,
+    load_in_8bit = False,
+):
     """Load model and compute perplexity in subprocess"""
     from unsloth import FastLanguageModel
     from tests.utils.perplexity_eval import ppl_model
@@ -49,9 +53,7 @@ def load_and_compute_8bit_ppl(result_queue, load_in_4bit = False, load_in_8bit =
     # )
 
     # Load dataset fresh in subprocess
-    dataset_ppl = load_dataset(
-        "allenai/openassistant-guanaco-reformatted", split = "eval"
-    )
+    dataset_ppl = load_dataset("allenai/openassistant-guanaco-reformatted", split = "eval")
 
     alpaca_prompt = """Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.
 
@@ -90,10 +92,7 @@ def load_and_compute_8bit_ppl(result_queue, load_in_4bit = False, load_in_8bit =
             outputs.append(assistant_message)
 
             # Create formatted text
-            text = (
-                alpaca_prompt.format(instruction, user_message, assistant_message)
-                + EOS_TOKEN
-            )
+            text = alpaca_prompt.format(instruction, user_message, assistant_message) + EOS_TOKEN
             texts.append(text)
 
         return {
@@ -186,10 +185,7 @@ if __name__ == "__main__":
             outputs.append(assistant_message)
 
             # Create formatted text
-            text = (
-                alpaca_prompt.format(instruction, user_message, assistant_message)
-                + EOS_TOKEN
-            )
+            text = alpaca_prompt.format(instruction, user_message, assistant_message) + EOS_TOKEN
             texts.append(text)
 
         return {
@@ -199,12 +195,8 @@ if __name__ == "__main__":
             "text": texts,
         }
 
-    dataset_train = load_dataset(
-        "allenai/openassistant-guanaco-reformatted", split = "train"
-    )
-    dataset_ppl = load_dataset(
-        "allenai/openassistant-guanaco-reformatted", split = "eval"
-    )
+    dataset_train = load_dataset("allenai/openassistant-guanaco-reformatted", split = "train")
+    dataset_ppl = load_dataset("allenai/openassistant-guanaco-reformatted", split = "eval")
 
     dataset_train = dataset_train.map(formatting_prompts_func, batched = True)
     dataset_ppl = dataset_ppl.map(formatting_prompts_func, batched = True)
diff --git a/tests/saving/language_models/test_merge_model_perplexity_phi_4.py b/tests/saving/language_models/test_merge_model_perplexity_phi_4.py
index bebea8168e..6dbdf36032 100644
--- a/tests/saving/language_models/test_merge_model_perplexity_phi_4.py
+++ b/tests/saving/language_models/test_merge_model_perplexity_phi_4.py
@@ -35,9 +35,7 @@ from tests.utils.perplexity_eval import (
 def formatting_prompts_func(examples):
     convos = examples["messages"]
     texts = [
-        tokenizer.apply_chat_template(
-            convo, tokenize = False, add_generation_prompt = False
-        )
+        tokenizer.apply_chat_template(convo, tokenize = False, add_generation_prompt = False)
         for convo in convos
     ]
     return {
@@ -45,7 +43,11 @@ def formatting_prompts_func(examples):
     }
 
 
-def load_and_compute_8bit_ppl(result_queue, load_in_4bit = False, load_in_8bit = False):
+def load_and_compute_8bit_ppl(
+    result_queue,
+    load_in_4bit = False,
+    load_in_8bit = False,
+):
     """Load model and compute perplexity in subprocess"""
     from unsloth import FastLanguageModel
     from unsloth.chat_templates import get_chat_template
@@ -65,17 +67,13 @@ def load_and_compute_8bit_ppl(result_queue, load_in_4bit = False, load_in_8bit =
     )
 
     # Load dataset fresh in subprocess
-    dataset_ppl = load_dataset(
-        "allenai/openassistant-guanaco-reformatted", split = "eval"
-    )
+    dataset_ppl = load_dataset("allenai/openassistant-guanaco-reformatted", split = "eval")
 
     # Format the dataset
     def formatting_prompts_func(examples):
         convos = examples["messages"]
         texts = [
-            merged_tokenizer.apply_chat_template(
-                convo, tokenize = False, add_generation_prompt = False
-            )
+            merged_tokenizer.apply_chat_template(convo, tokenize = False, add_generation_prompt = False)
             for convo in convos
         ]
         return {"text": texts}
@@ -130,12 +128,8 @@ if __name__ == "__main__":
         chat_template = "phi-4",
     )
 
-    dataset_train = load_dataset(
-        "allenai/openassistant-guanaco-reformatted", split = "train"
-    )
-    dataset_ppl = load_dataset(
-        "allenai/openassistant-guanaco-reformatted", split = "eval"
-    )
+    dataset_train = load_dataset("allenai/openassistant-guanaco-reformatted", split = "train")
+    dataset_ppl = load_dataset("allenai/openassistant-guanaco-reformatted", split = "eval")
 
     dataset_train = dataset_train.map(formatting_prompts_func, batched = True)
     dataset_ppl = dataset_ppl.map(formatting_prompts_func, batched = True)
diff --git a/tests/saving/language_models/test_merged_model_perplexity_llama-3.1-8b.py b/tests/saving/language_models/test_merged_model_perplexity_llama-3.1-8b.py
index c6da9e2ca6..a0624f0c2c 100644
--- a/tests/saving/language_models/test_merged_model_perplexity_llama-3.1-8b.py
+++ b/tests/saving/language_models/test_merged_model_perplexity_llama-3.1-8b.py
@@ -34,15 +34,17 @@ from tests.utils.perplexity_eval import (
 def formatting_prompts_func(examples):
     convos = examples["messages"]
     texts = [
-        tokenizer.apply_chat_template(
-            convo, tokenize = False, add_generation_prompt = False
-        )
+        tokenizer.apply_chat_template(convo, tokenize = False, add_generation_prompt = False)
         for convo in convos
     ]
     return {"text": texts}
 
 
-def load_and_compute_8bit_ppl(result_queue, load_in_4bit = False, load_in_8bit = False):
+def load_and_compute_8bit_ppl(
+    result_queue,
+    load_in_4bit = False,
+    load_in_8bit = False,
+):
     """Load model and compute perplexity in subprocess"""
     from unsloth import FastLanguageModel
     from unsloth.chat_templates import get_chat_template
@@ -62,17 +64,13 @@ def load_and_compute_8bit_ppl(result_queue, load_in_4bit = False, load_in_8bit =
     )
 
     # Load dataset fresh in subprocess
-    dataset_ppl = load_dataset(
-        "allenai/openassistant-guanaco-reformatted", split = "eval"
-    )
+    dataset_ppl = load_dataset("allenai/openassistant-guanaco-reformatted", split = "eval")
 
     # Format the dataset
     def formatting_prompts_func(examples):
         convos = examples["messages"]
         texts = [
-            merged_tokenizer.apply_chat_template(
-                convo, tokenize = False, add_generation_prompt = False
-            )
+            merged_tokenizer.apply_chat_template(convo, tokenize = False, add_generation_prompt = False)
             for convo in convos
         ]
         return {"text": texts}
@@ -129,12 +127,8 @@ if __name__ == "__main__":
 
     from unsloth.chat_templates import standardize_sharegpt
 
-    dataset_train = load_dataset(
-        "allenai/openassistant-guanaco-reformatted", split = "train"
-    )
-    dataset_ppl = load_dataset(
-        "allenai/openassistant-guanaco-reformatted", split = "eval"
-    )
+    dataset_train = load_dataset("allenai/openassistant-guanaco-reformatted", split = "train")
+    dataset_ppl = load_dataset("allenai/openassistant-guanaco-reformatted", split = "eval")
 
     dataset_train = dataset_train.map(formatting_prompts_func, batched = True)
     dataset_ppl = dataset_ppl.map(formatting_prompts_func, batched = True)
diff --git a/tests/saving/language_models/test_merged_model_perplexity_qwen_2.5.py b/tests/saving/language_models/test_merged_model_perplexity_qwen_2.5.py
index d63bb9fe09..0b377eca81 100644
--- a/tests/saving/language_models/test_merged_model_perplexity_qwen_2.5.py
+++ b/tests/saving/language_models/test_merged_model_perplexity_qwen_2.5.py
@@ -78,7 +78,11 @@ def formatting_prompts_func(examples):
     }
 
 
-def load_and_compute_8bit_ppl(result_queue, load_in_4bit = False, load_in_8bit = False):
+def load_and_compute_8bit_ppl(
+    result_queue,
+    load_in_4bit = False,
+    load_in_8bit = False,
+):
     """Load model and compute perplexity in subprocess"""
     from unsloth import FastLanguageModel
     from tests.utils.perplexity_eval import ppl_model
@@ -97,9 +101,7 @@ def load_and_compute_8bit_ppl(result_queue, load_in_4bit = False, load_in_8bit =
     # )
 
     # Load dataset fresh in subprocess
-    dataset_ppl = load_dataset(
-        "allenai/openassistant-guanaco-reformatted", split = "eval"
-    )
+    dataset_ppl = load_dataset("allenai/openassistant-guanaco-reformatted", split = "eval")
 
     alpaca_prompt = """Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.
 
@@ -191,12 +193,8 @@ if __name__ == "__main__":
         attn_implementation = attn_implementation,
     )
 
-    dataset_train = load_dataset(
-        "allenai/openassistant-guanaco-reformatted", split = "train"
-    )
-    dataset_ppl = load_dataset(
-        "allenai/openassistant-guanaco-reformatted", split = "eval"
-    )
+    dataset_train = load_dataset("allenai/openassistant-guanaco-reformatted", split = "train")
+    dataset_ppl = load_dataset("allenai/openassistant-guanaco-reformatted", split = "eval")
 
     dataset_train = dataset_train.map(formatting_prompts_func, batched = True)
     dataset_ppl = dataset_ppl.map(formatting_prompts_func, batched = True)
diff --git a/tests/saving/language_models/test_push_to_hub_merged.py b/tests/saving/language_models/test_push_to_hub_merged.py
index 58d589305a..aa79394556 100644
--- a/tests/saving/language_models/test_push_to_hub_merged.py
+++ b/tests/saving/language_models/test_push_to_hub_merged.py
@@ -36,9 +36,7 @@ from tests.utils.perplexity_eval import (
 def formatting_prompts_func(examples):
     convos = examples["messages"]
     texts = [
-        tokenizer.apply_chat_template(
-            convo, tokenize = False, add_generation_prompt = False
-        )
+        tokenizer.apply_chat_template(convo, tokenize = False, add_generation_prompt = False)
         for convo in convos
     ]
     return {"text": texts}
@@ -176,9 +174,7 @@ try:
     print("=== TESTING MODEL DOWNLOAD ===".center(80))
     print("=" * 80 + "\n")
     # Force download even if cached
-    model, tokenizer = FastLanguageModel.from_pretrained(
-        f"{hf_username}/merged_llama_text_model"
-    )
+    model, tokenizer = FastLanguageModel.from_pretrained(f"{hf_username}/merged_llama_text_model")
     success["download"] = True
     print("✅ Model downloaded successfully!")
 except Exception as e:
diff --git a/tests/saving/language_models/test_push_to_hub_merged_sharded_index_file.py b/tests/saving/language_models/test_push_to_hub_merged_sharded_index_file.py
index 038565d170..38b82c5469 100644
--- a/tests/saving/language_models/test_push_to_hub_merged_sharded_index_file.py
+++ b/tests/saving/language_models/test_push_to_hub_merged_sharded_index_file.py
@@ -36,9 +36,7 @@ from tests.utils.perplexity_eval import (
 def formatting_prompts_func(examples):
     convos = examples["messages"]
     texts = [
-        tokenizer.apply_chat_template(
-            convo, tokenize = False, add_generation_prompt = False
-        )
+        tokenizer.apply_chat_template(convo, tokenize = False, add_generation_prompt = False)
         for convo in convos
     ]
     return {"text": texts}
@@ -195,9 +193,7 @@ try:
     print("=== TESTING MODEL DOWNLOAD ===".center(80))
     print("=" * 80 + "\n")
     # Force download even if cached
-    model, tokenizer = FastLanguageModel.from_pretrained(
-        f"{hf_username}/merged_llama_text_model"
-    )
+    model, tokenizer = FastLanguageModel.from_pretrained(f"{hf_username}/merged_llama_text_model")
     success["download"] = True
     print("✅ Model downloaded successfully!")
 except Exception as e:
diff --git a/tests/saving/language_models/test_save_merged_grpo_model.py b/tests/saving/language_models/test_save_merged_grpo_model.py
index 67b649305a..b5d8025fcb 100644
--- a/tests/saving/language_models/test_save_merged_grpo_model.py
+++ b/tests/saving/language_models/test_save_merged_grpo_model.py
@@ -24,7 +24,11 @@ max_seq_length = 2048  # Can increase for longer reasoning traces
 lora_rank = 64  # Larger rank = smarter, but slower
 
 
-def evaluate_merged_model(result_queue, load_in_4bit = False, load_in_8bit = False):
+def evaluate_merged_model(
+    result_queue,
+    load_in_4bit = False,
+    load_in_8bit = False,
+):
     from unsloth import FastLanguageModel
     from tests.utils.aime_eval import evaluate_model_aime
 
@@ -176,12 +180,14 @@ def training_run(result_queue):
         avg_length = sum(lengths) / len(lengths)
         min_length = min(lengths)
 
-        print(
-            f"Prompt lengths - Min: {min_length}, Max: {max_length}, Avg: {avg_length:.1f}"
-        )
+        print(f"Prompt lengths - Min: {min_length}, Max: {max_length}, Avg: {avg_length:.1f}")
         return max_length, avg_length
 
-    def extract_unsloth_answer(text, start_tag = "", end_tag = ""):
+    def extract_unsloth_answer(
+        text,
+        start_tag = "",
+        end_tag = "",
+    ):
         """Extract answer from Unsloth SOLUTION tags"""
         pattern = re.escape(start_tag) + r"(.*?)" + re.escape(end_tag)
         matches = re.findall(pattern, text, re.DOTALL)
@@ -265,9 +271,7 @@ def training_run(result_queue):
             ground_truth_num = float(norm_ground_truth)
 
             if ground_truth_num != 0:
-                relative_error = abs(extracted_num - ground_truth_num) / abs(
-                    ground_truth_num
-                )
+                relative_error = abs(extracted_num - ground_truth_num) / abs(ground_truth_num)
 
                 if relative_error < 0.01:
                     return True, True, 0.9
@@ -302,10 +306,7 @@ def training_run(result_queue):
         )
 
         responses = [completion[0]["content"] for completion in completions]
-        rewards = [
-            3.0 if re.match(pattern, response, re.DOTALL) else 0.0
-            for response in responses
-        ]
+        rewards = [3.0 if re.match(pattern, response, re.DOTALL) else 0.0 for response in responses]
         return rewards
 
     def match_format_approximately(completions, **kwargs):
@@ -405,9 +406,7 @@ def training_run(result_queue):
                 format_improvement = (
                     result["correct_format_pct"] - base_result["correct_format_pct"]
                 )
-                exact_improvement = (
-                    result["exact_match_pct"] - base_result["exact_match_pct"]
-                )
+                exact_improvement = result["exact_match_pct"] - base_result["exact_match_pct"]
                 plausible_improvement = (
                     result["plausible_match_pct"] - base_result["plausible_match_pct"]
                 )
@@ -440,9 +439,7 @@ def training_run(result_queue):
         if torch.cuda.is_available():
             allocated = torch.cuda.memory_allocated() / 1024**3
             reserved = torch.cuda.memory_reserved() / 1024**3
-            print(
-                f"GPU memory - Allocated: {allocated:.2f} GB, Reserved: {reserved:.2f} GB"
-            )
+            print(f"GPU memory - Allocated: {allocated:.2f} GB, Reserved: {reserved:.2f} GB")
 
     """#### Data Loading and Preparation"""
 
@@ -486,9 +483,7 @@ def training_run(result_queue):
     def formatting_prompts_func(examples):
         convos = examples["prompt"]
         texts = [
-            tokenizer.apply_chat_template(
-                convo, tokenize = False, add_generation_prompt = False
-            )
+            tokenizer.apply_chat_template(convo, tokenize = False, add_generation_prompt = False)
             for convo in convos
         ]
         return {
@@ -715,9 +710,7 @@ def training_run(result_queue):
 
     # Save as merged model
     try:
-        model.save_pretrained_merged(
-            "final_merged_model", tokenizer, save_method = "merged_16bit"
-        )
+        model.save_pretrained_merged("final_merged_model", tokenizer, save_method = "merged_16bit")
         print("✅ Merged model saved to: final_merged_model/")
     except Exception as e:
         print(f"⚠️ Could not save merged model: {e}")
diff --git a/tests/saving/test_fix_sentencepiece_gguf_robustness.py b/tests/saving/test_fix_sentencepiece_gguf_robustness.py
index 49bd70fa2f..9c61ca4067 100644
--- a/tests/saving/test_fix_sentencepiece_gguf_robustness.py
+++ b/tests/saving/test_fix_sentencepiece_gguf_robustness.py
@@ -44,9 +44,7 @@ def test_user_defined_special_piece_is_not_retyped(tmp_path):
     ]
     (tmp_path / "tokenizer.model").write_bytes(_build(pieces))
     (tmp_path / "tokenizer.json").write_text(
-        json.dumps(
-            {"added_tokens": [{"id": 2, "content": "", "special": True}]}
-        )
+        json.dumps({"added_tokens": [{"id": 2, "content": "", "special": True}]})
     )
     fix_sentencepiece_gguf(str(tmp_path))
     got = dict(_read(str(tmp_path / "tokenizer.model")))
@@ -87,10 +85,7 @@ def test_save_py_except_clause_is_broad_exception():
     with open(_SAVE_PY) as f:
         tree = ast.parse(f.read())
     for node in ast.walk(tree):
-        if (
-            isinstance(node, ast.FunctionDef)
-            and node.name == "unsloth_save_pretrained_gguf"
-        ):
+        if isinstance(node, ast.FunctionDef) and node.name == "unsloth_save_pretrained_gguf":
             for subnode in ast.walk(node):
                 if isinstance(subnode, ast.Try):
                     body_src = "\n".join(ast.unparse(s) for s in subnode.body)
diff --git a/tests/saving/test_preserve_tokenizer_eos_token.py b/tests/saving/test_preserve_tokenizer_eos_token.py
index 6e2f8c7f9d..2ea40ab778 100644
--- a/tests/saving/test_preserve_tokenizer_eos_token.py
+++ b/tests/saving/test_preserve_tokenizer_eos_token.py
@@ -16,8 +16,7 @@ def _load_preserve_helper():
     helper = next(
         node
         for node in tree.body
-        if isinstance(node, ast.FunctionDef)
-        and node.name == "_preserve_tokenizer_eos_token"
+        if isinstance(node, ast.FunctionDef) and node.name == "_preserve_tokenizer_eos_token"
     )
     module = ast.Module(body = [helper], type_ignores = [])
     ast.fix_missing_locations(module)
@@ -46,9 +45,7 @@ def test_preserve_tokenizer_eos_token_supports_processor_tokenizer(tmp_path):
     preserve = _load_preserve_helper()
     tokenizer_config = tmp_path / "tokenizer_config.json"
     tokenizer_config.write_text(json.dumps({"eos_token": ""}), encoding = "utf-8")
-    processor = types.SimpleNamespace(
-        tokenizer = types.SimpleNamespace(eos_token = "")
-    )
+    processor = types.SimpleNamespace(tokenizer = types.SimpleNamespace(eos_token = ""))
 
     preserve(processor, tmp_path)
 
diff --git a/tests/saving/test_save_shell_injection.py b/tests/saving/test_save_shell_injection.py
index c6c2c8fe15..b02748c250 100644
--- a/tests/saving/test_save_shell_injection.py
+++ b/tests/saving/test_save_shell_injection.py
@@ -19,10 +19,7 @@ def _assert_safe_ggml_calls(calls: list[ast.Call]) -> None:
     popen_calls = []
     for call in calls:
         if isinstance(call.func, ast.Attribute) and call.func.attr == "Popen":
-            if (
-                isinstance(call.func.value, ast.Name)
-                and call.func.value.id == "subprocess"
-            ):
+            if isinstance(call.func.value, ast.Name) and call.func.value.id == "subprocess":
                 popen_calls.append(call)
 
     assert popen_calls, "Expected at least one subprocess.Popen call"
@@ -54,9 +51,7 @@ def _assert_safe_ggml_calls(calls: list[ast.Call]) -> None:
 
         assert call.args, "subprocess.Popen must receive argv as a positional argument"
         argv = call.args[0]
-        assert isinstance(
-            argv, ast.List
-        ), "subprocess.Popen must be called with an argv list"
+        assert isinstance(argv, ast.List), "subprocess.Popen must be called with an argv list"
         assert len(argv.elts) == 5, "GGML conversion argv should have five elements"
 
         second_arg = argv.elts[1]
diff --git a/tests/saving/test_unsloth_save.py b/tests/saving/test_unsloth_save.py
index 35fdad6ba0..c7dd712734 100644
--- a/tests/saving/test_unsloth_save.py
+++ b/tests/saving/test_unsloth_save.py
@@ -132,20 +132,14 @@ def test_save_merged_16bit(model, tokenizer, temp_save_dir: str):
         model.config._name_or_path.replace("/", "_"),
     )
 
-    model.save_pretrained_merged(
-        save_path, tokenizer = tokenizer, save_method = "merged_16bit"
-    )
+    model.save_pretrained_merged(save_path, tokenizer = tokenizer, save_method = "merged_16bit")
 
     # Check model files
     assert os.path.isdir(save_path), f"Directory {save_path} does not exist."
-    assert os.path.isfile(
-        os.path.join(save_path, "config.json")
-    ), "config.json not found."
+    assert os.path.isfile(os.path.join(save_path, "config.json")), "config.json not found."
 
     weight_files = [
-        f
-        for f in os.listdir(save_path)
-        if f.endswith(".bin") or f.endswith(".safetensors")
+        f for f in os.listdir(save_path) if f.endswith(".bin") or f.endswith(".safetensors")
     ]
     assert len(weight_files) > 0, "No weight files found in the save directory."
 
@@ -160,9 +154,7 @@ def test_save_merged_16bit(model, tokenizer, temp_save_dir: str):
     with open(config_path, "r") as f:
         config = json.load(f)
 
-    assert (
-        "quantization_config" not in config
-    ), "Quantization config not found in the model config."
+    assert "quantization_config" not in config, "Quantization config not found in the model config."
 
     # Store the size of the model files
     total_size = sum(os.path.getsize(os.path.join(save_path, f)) for f in weight_files)
@@ -185,20 +177,14 @@ def test_save_merged_4bit(model, tokenizer, temp_save_dir: str):
         model.config._name_or_path.replace("/", "_"),
     )
 
-    model.save_pretrained_merged(
-        save_path, tokenizer = tokenizer, save_method = "merged_4bit_forced"
-    )
+    model.save_pretrained_merged(save_path, tokenizer = tokenizer, save_method = "merged_4bit_forced")
 
     # Check model files
     assert os.path.isdir(save_path), f"Directory {save_path} does not exist."
-    assert os.path.isfile(
-        os.path.join(save_path, "config.json")
-    ), "config.json not found."
+    assert os.path.isfile(os.path.join(save_path, "config.json")), "config.json not found."
 
     weight_files = [
-        f
-        for f in os.listdir(save_path)
-        if f.endswith(".bin") or f.endswith(".safetensors")
+        f for f in os.listdir(save_path) if f.endswith(".bin") or f.endswith(".safetensors")
     ]
     assert len(weight_files) > 0, "No weight files found in the save directory."
 
@@ -223,9 +209,7 @@ def test_save_merged_4bit(model, tokenizer, temp_save_dir: str):
     with open(config_path, "r") as f:
         config = json.load(f)
 
-    assert (
-        "quantization_config" in config
-    ), "Quantization config not found in the model config."
+    assert "quantization_config" in config, "Quantization config not found in the model config."
 
     # Test loading the model from the saved path
     loaded_model, loaded_tokenizer = FastModel.from_pretrained(
@@ -257,29 +241,19 @@ def test_save_torchao(fp16_model_tokenizer, temp_save_dir: str):
     )
 
     weight_files_16bit = [
-        f
-        for f in os.listdir(save_path)
-        if f.endswith(".bin") or f.endswith(".safetensors")
+        f for f in os.listdir(save_path) if f.endswith(".bin") or f.endswith(".safetensors")
     ]
-    total_16bit_size = sum(
-        os.path.getsize(os.path.join(save_path, f)) for f in weight_files_16bit
-    )
+    total_16bit_size = sum(os.path.getsize(os.path.join(save_path, f)) for f in weight_files_16bit)
     save_file_sizes["merged_16bit"][model.config._name_or_path] = total_16bit_size
 
     torchao_save_path = save_path + "-torchao"
 
     # Check model files
-    assert os.path.isdir(
-        torchao_save_path
-    ), f"Directory {torchao_save_path} does not exist."
-    assert os.path.isfile(
-        os.path.join(torchao_save_path, "config.json")
-    ), "config.json not found."
+    assert os.path.isdir(torchao_save_path), f"Directory {torchao_save_path} does not exist."
+    assert os.path.isfile(os.path.join(torchao_save_path, "config.json")), "config.json not found."
 
     weight_files = [
-        f
-        for f in os.listdir(torchao_save_path)
-        if f.endswith(".bin") or f.endswith(".safetensors")
+        f for f in os.listdir(torchao_save_path) if f.endswith(".bin") or f.endswith(".safetensors")
     ]
     assert len(weight_files) > 0, "No weight files found in the save directory."
 
@@ -290,9 +264,7 @@ def test_save_torchao(fp16_model_tokenizer, temp_save_dir: str):
         ), f"{file} not found in the save directory."
 
     # Store the size of the model files
-    total_size = sum(
-        os.path.getsize(os.path.join(torchao_save_path, f)) for f in weight_files
-    )
+    total_size = sum(os.path.getsize(os.path.join(torchao_save_path, f)) for f in weight_files)
     save_file_sizes["torchao"][model.config._name_or_path] = total_size
 
     assert (
@@ -304,9 +276,7 @@ def test_save_torchao(fp16_model_tokenizer, temp_save_dir: str):
     with open(config_path, "r") as f:
         config = json.load(f)
 
-    assert (
-        "quantization_config" in config
-    ), "Quantization config not found in the model config."
+    assert "quantization_config" in config, "Quantization config not found in the model config."
 
     # Test loading the model from the saved path
     # can't set `load_in_4bit` to True because the model is torchao quantized
@@ -332,9 +302,7 @@ def test_save_and_inference_torchao(fp16_model_tokenizer, temp_save_dir: str):
 
     print(f"Testing TorchAO save and inference for: {model_name}")
 
-    save_path = os.path.join(
-        temp_save_dir, "torchao_models", model_name.replace("/", "_")
-    )
+    save_path = os.path.join(temp_save_dir, "torchao_models", model_name.replace("/", "_"))
 
     from torchao.quantization import Int8DynamicActivationInt8WeightConfig
 
diff --git a/tests/saving/text_to_speech_models/test_csm.py b/tests/saving/text_to_speech_models/test_csm.py
index c1a892a8d3..dd2287d1d6 100644
--- a/tests/saving/text_to_speech_models/test_csm.py
+++ b/tests/saving/text_to_speech_models/test_csm.py
@@ -134,9 +134,7 @@ import torch
 
 output_audio_path = "csm_audio.wav"
 try:
-    text = (
-        "We just finished fine tuning a text to speech model... and it's pretty good!"
-    )
+    text = "We just finished fine tuning a text to speech model... and it's pretty good!"
     speaker_id = 0
     inputs = processor(f"[{speaker_id}]{text}", add_special_tokens = True).to("cuda")
     audio_values = model.generate(
diff --git a/tests/saving/text_to_speech_models/test_lasa.py b/tests/saving/text_to_speech_models/test_lasa.py
index 804ff512f9..c0c4f80e0e 100644
--- a/tests/saving/text_to_speech_models/test_lasa.py
+++ b/tests/saving/text_to_speech_models/test_lasa.py
@@ -167,9 +167,7 @@ def extract_speech_ids(speech_tokens_str):
 # TTS start!
 with torch.inference_mode():
     with torch.amp.autocast("cuda", dtype = model.dtype):
-        formatted_text = (
-            f"<|TEXT_UNDERSTANDING_START|>{input_text}<|TEXT_UNDERSTANDING_END|>"
-        )
+        formatted_text = f"<|TEXT_UNDERSTANDING_START|>{input_text}<|TEXT_UNDERSTANDING_END|>"
 
         # Tokenize the text
         chat = [
diff --git a/tests/saving/text_to_speech_models/test_orpheus.py b/tests/saving/text_to_speech_models/test_orpheus.py
index bd8bf14979..2915749d99 100644
--- a/tests/saving/text_to_speech_models/test_orpheus.py
+++ b/tests/saving/text_to_speech_models/test_orpheus.py
@@ -152,9 +152,7 @@ for prompt in prompts_:
     all_input_ids.append(input_ids)
 
 start_token = torch.tensor([[128259]], dtype = torch.int64)  # Start of human
-end_tokens = torch.tensor(
-    [[128009, 128260]], dtype = torch.int64
-)  # End of text, End of human
+end_tokens = torch.tensor([[128009, 128260]], dtype = torch.int64)  # End of text, End of human
 
 all_modified_input_ids = []
 for input_ids in all_input_ids:
@@ -165,9 +163,7 @@ for input_ids in all_input_ids:
 
 all_padded_tensors = []
 all_attention_masks = []
-max_length = max(
-    [modified_input_ids.shape[1] for modified_input_ids in all_modified_input_ids]
-)
+max_length = max([modified_input_ids.shape[1] for modified_input_ids in all_modified_input_ids])
 for modified_input_ids in all_modified_input_ids:
     padding = max_length - modified_input_ids.shape[1]
     padded_tensor = torch.cat(
diff --git a/tests/saving/text_to_speech_models/test_whisper.py b/tests/saving/text_to_speech_models/test_whisper.py
index 55f6d98ca0..d0eeb49d17 100644
--- a/tests/saving/text_to_speech_models/test_whisper.py
+++ b/tests/saving/text_to_speech_models/test_whisper.py
@@ -181,13 +181,9 @@ expected_phrases = [
 ]
 
 transcribed_lower = transcribed_text["text"].lower()
-all_phrases_found = all(
-    phrase.lower() in transcribed_lower for phrase in expected_phrases
-)
+all_phrases_found = all(phrase.lower() in transcribed_lower for phrase in expected_phrases)
 
-assert (
-    all_phrases_found
-), f"Expected phrases not found in transcription: {transcribed_text['text']}"
+assert all_phrases_found, f"Expected phrases not found in transcription: {transcribed_text['text']}"
 print("✅ Transcription contains all expected phrases!")
 
 
diff --git a/tests/saving/vision_models/test_index_file_sharded_model.py b/tests/saving/vision_models/test_index_file_sharded_model.py
index 8d107463e0..79a25ec666 100644
--- a/tests/saving/vision_models/test_index_file_sharded_model.py
+++ b/tests/saving/vision_models/test_index_file_sharded_model.py
@@ -138,9 +138,7 @@ try:
             per_device_train_batch_size = 2,
             gradient_accumulation_steps = 4,
             gradient_checkpointing = True,
-            gradient_checkpointing_kwargs = {
-                "use_reentrant": False
-            },  # use reentrant checkpointing
+            gradient_checkpointing_kwargs = {"use_reentrant": False},  # use reentrant checkpointing
             max_grad_norm = 0.3,  # max gradient norm based on QLoRA paper
             warmup_ratio = 0.03,
             # num_train_epochs = 2, # Set this instead of max_steps for full training runs
diff --git a/tests/saving/vision_models/test_push_to_hub_merged.py b/tests/saving/vision_models/test_push_to_hub_merged.py
index fb2af4b4fe..86c7b56cf2 100644
--- a/tests/saving/vision_models/test_push_to_hub_merged.py
+++ b/tests/saving/vision_models/test_push_to_hub_merged.py
@@ -139,9 +139,7 @@ try:
             per_device_train_batch_size = 2,
             gradient_accumulation_steps = 4,
             gradient_checkpointing = True,
-            gradient_checkpointing_kwargs = {
-                "use_reentrant": False
-            },  # use reentrant checkpointing
+            gradient_checkpointing_kwargs = {"use_reentrant": False},  # use reentrant checkpointing
             max_grad_norm = 0.3,  # max gradient norm based on QLoRA paper
             warmup_ratio = 0.03,
             # num_train_epochs = 2, # Set this instead of max_steps for full training runs
diff --git a/tests/saving/vision_models/test_save_merge_qwen2.5vl32B_model_ocr_benchmark.py b/tests/saving/vision_models/test_save_merge_qwen2.5vl32B_model_ocr_benchmark.py
index 2b24bc4a32..391d7bacca 100644
--- a/tests/saving/vision_models/test_save_merge_qwen2.5vl32B_model_ocr_benchmark.py
+++ b/tests/saving/vision_models/test_save_merge_qwen2.5vl32B_model_ocr_benchmark.py
@@ -134,9 +134,7 @@ trainer = SFTTrainer(
         per_device_train_batch_size = 2,
         gradient_accumulation_steps = 4,
         gradient_checkpointing = True,
-        gradient_checkpointing_kwargs = {
-            "use_reentrant": False
-        },  # use reentrant checkpointing
+        gradient_checkpointing_kwargs = {"use_reentrant": False},  # use reentrant checkpointing
         max_grad_norm = 0.3,  # max gradient norm based on QLoRA paper
         warmup_ratio = 0.03,
         # num_train_epochs = 2, # Set this instead of max_steps for full training runs
diff --git a/tests/saving/vision_models/test_save_merge_vision_model_ocr_benchmark.py b/tests/saving/vision_models/test_save_merge_vision_model_ocr_benchmark.py
index 16914707c2..b4812cdfa8 100644
--- a/tests/saving/vision_models/test_save_merge_vision_model_ocr_benchmark.py
+++ b/tests/saving/vision_models/test_save_merge_vision_model_ocr_benchmark.py
@@ -134,9 +134,7 @@ trainer = SFTTrainer(
         per_device_train_batch_size = 2,
         gradient_accumulation_steps = 4,
         gradient_checkpointing = True,
-        gradient_checkpointing_kwargs = {
-            "use_reentrant": False
-        },  # use reentrant checkpointing
+        gradient_checkpointing_kwargs = {"use_reentrant": False},  # use reentrant checkpointing
         max_grad_norm = 0.3,  # max gradient norm based on QLoRA paper
         warmup_ratio = 0.03,
         # num_train_epochs = 2, # Set this instead of max_steps for full training runs
diff --git a/tests/security/test_lockfile_supply_chain_audit.py b/tests/security/test_lockfile_supply_chain_audit.py
index 483bb9e763..cec07aea28 100644
--- a/tests/security/test_lockfile_supply_chain_audit.py
+++ b/tests/security/test_lockfile_supply_chain_audit.py
@@ -143,7 +143,6 @@ def test_lockfile_auditor_blocked_versions_match_scanner():
     comment until the next PR factors them into a shared module).
     """
     from scripts import scan_npm_packages as snp
-
     assert (
         lsa.BLOCKED_NPM_VERSIONS == snp.BLOCKED_NPM_VERSIONS
     ), "auditor and scanner BLOCKED_NPM_VERSIONS tables drifted"
@@ -275,9 +274,7 @@ def test_advisory_finding_emitted_as_single_line_annotation(tmp_path):
         npm_lockfiles = [FIXTURES / "clean_lockfile.json"],
         cargo_lockfiles = [lockfile],
     )
-    warning_lines = [
-        line for line in proc.stderr.splitlines() if line.startswith("::warning::")
-    ]
+    warning_lines = [line for line in proc.stderr.splitlines() if line.startswith("::warning::")]
     assert warning_lines, (
         "expected at least one ::warning:: annotation; " f"stderr was:\n{proc.stderr}"
     )
diff --git a/tests/security/test_new_install_scripts.py b/tests/security/test_new_install_scripts.py
index 32340d2536..9a73f4b0d9 100644
--- a/tests/security/test_new_install_scripts.py
+++ b/tests/security/test_new_install_scripts.py
@@ -18,7 +18,12 @@ REPO_ROOT = Path(__file__).resolve().parents[2]
 SCRIPT = REPO_ROOT / "scripts" / "check_new_install_scripts.py"
 
 
-def _run(base: Path, head: Path, *, timeout: int = 30) -> subprocess.CompletedProcess:
+def _run(
+    base: Path,
+    head: Path,
+    *,
+    timeout: int = 30,
+) -> subprocess.CompletedProcess:
     return subprocess.run(
         [
             sys.executable,
@@ -103,9 +108,7 @@ def test_new_dep_with_postinstall_exits_1(tmp_path: Path):
     head_pkgs = dict(base_pkgs)
     head_pkgs["node_modules/evil-postinstall"] = {
         "version": "1.0.0",
-        "resolved": (
-            "https://registry.npmjs.org/evil-postinstall/-/evil-postinstall-1.0.0.tgz"
-        ),
+        "resolved": ("https://registry.npmjs.org/evil-postinstall/-/evil-postinstall-1.0.0.tgz"),
         "integrity": "sha512-fake",
         "hasInstallScript": True,
     }
@@ -166,8 +169,7 @@ def test_v2_v3_lockfile_format_support(tmp_path: Path):
         "node_modules/v2-postinstall-dep": {
             "version": "2.0.0",
             "resolved": (
-                "https://registry.npmjs.org/v2-postinstall-dep/-/"
-                "v2-postinstall-dep-2.0.0.tgz"
+                "https://registry.npmjs.org/v2-postinstall-dep/-/v2-postinstall-dep-2.0.0.tgz"
             ),
             "integrity": "sha512-fake",
             "hasInstallScript": True,
@@ -177,8 +179,7 @@ def test_v2_v3_lockfile_format_support(tmp_path: Path):
         "v2-postinstall-dep": {
             "version": "2.0.0",
             "resolved": (
-                "https://registry.npmjs.org/v2-postinstall-dep/-/"
-                "v2-postinstall-dep-2.0.0.tgz"
+                "https://registry.npmjs.org/v2-postinstall-dep/-/v2-postinstall-dep-2.0.0.tgz"
             ),
             "integrity": "sha512-fake",
         },
@@ -187,8 +188,7 @@ def test_v2_v3_lockfile_format_support(tmp_path: Path):
     head = _write(tmp_path / "head.json", _v2_lockfile(head_pkgs, head_deps))
     result = _run(base, head)
     assert result.returncode == 1, (
-        f"expected exit 1 for v2 lockfile, got {result.returncode}; "
-        f"stderr:\n{result.stderr}"
+        f"expected exit 1 for v2 lockfile, got {result.returncode}; " f"stderr:\n{result.stderr}"
     )
     assert "v2-postinstall-dep" in result.stderr
 
diff --git a/tests/security/test_scan_npm_packages.py b/tests/security/test_scan_npm_packages.py
index c632c618b0..fb575b730d 100644
--- a/tests/security/test_scan_npm_packages.py
+++ b/tests/security/test_scan_npm_packages.py
@@ -106,16 +106,10 @@ def test_blocked_npm_versions_complete():
     table = snp.BLOCKED_NPM_VERSIONS
     tanstack_keys = [k for k in table if k.startswith("@tanstack/")]
     assert len(tanstack_keys) == 42, (
-        f"expected 42 @tanstack/* entries, got {len(tanstack_keys)}: "
-        f"{sorted(tanstack_keys)}"
+        f"expected 42 @tanstack/* entries, got {len(tanstack_keys)}: " f"{sorted(tanstack_keys)}"
     )
     assert "@opensearch-project/opensearch" in table
-    assert table["@opensearch-project/opensearch"] == {
-        "3.5.3",
-        "3.6.2",
-        "3.7.0",
-        "3.8.0",
-    }
+    assert table["@opensearch-project/opensearch"] == {"3.5.3", "3.6.2", "3.7.0", "3.8.0"}
     squawk = [k for k in table if k.startswith("@squawk/")]
     assert len(squawk) >= 22, (
         f"expected at least 22 @squawk/* entries (full safedep.io enumeration), "
diff --git a/tests/security/test_scan_packages.py b/tests/security/test_scan_packages.py
index 6ef10f12eb..b35d89ce48 100644
--- a/tests/security/test_scan_packages.py
+++ b/tests/security/test_scan_packages.py
@@ -118,9 +118,7 @@ def test_clean_wheel_no_findings():
         str(FIXTURES / "clean_wheel.whl"),
         "clean_fixture",
     )
-    assert (
-        findings == []
-    ), f"unexpected findings on clean wheel: {[str(f) for f in findings]}"
+    assert findings == [], f"unexpected findings on clean wheel: {[str(f) for f in findings]}"
 
 
 # ---------------------------------------------------------------------------
@@ -245,8 +243,7 @@ def test_archive_corruption_produces_critical_finding(tmp_path):
     assert findings, "scan_archive returned 0 findings on corrupt wheel"
     corrupted = [f for f in findings if f.check == "archive_corrupted"]
     assert corrupted, (
-        "no archive_corrupted finding; got "
-        f"{[(f.severity, f.check) for f in findings]}"
+        "no archive_corrupted finding; got " f"{[(f.severity, f.check) for f in findings]}"
     )
     assert all(f.severity == sp.CRITICAL for f in corrupted)
 
diff --git a/tests/studio/_playwright_robust.py b/tests/studio/_playwright_robust.py
index b190b2b3e1..831153bf96 100644
--- a/tests/studio/_playwright_robust.py
+++ b/tests/studio/_playwright_robust.py
@@ -182,9 +182,7 @@ def wait_for_health(
         # but accept any 200 -- different Studio builds report differently.
         if status == 200:
             if info is not None:
-                info(
-                    f"health pre-flight OK: status=200, body keys={list((body or {}).keys())}"
-                )
+                info(f"health pre-flight OK: status=200, body keys={list((body or {}).keys())}")
             return True
         time.sleep(0.5)
     if info is not None:
@@ -230,9 +228,7 @@ def recover_or_replace_page(
             info(f"recovery: page.is_closed() check failed: {exc!r}")
     if goto_url is not None:
         try:
-            page.goto(
-                goto_url, wait_until = "domcontentloaded", timeout = default_timeout_ms
-            )
+            page.goto(goto_url, wait_until = "domcontentloaded", timeout = default_timeout_ms)
             if settle_networkidle:
                 try:
                     page.wait_for_load_state("networkidle", timeout = 30_000)
diff --git a/tests/studio/install/smoke_test_llama_prebuilt.py b/tests/studio/install/smoke_test_llama_prebuilt.py
index d87537dc94..f7fd58aaa4 100644
--- a/tests/studio/install/smoke_test_llama_prebuilt.py
+++ b/tests/studio/install/smoke_test_llama_prebuilt.py
@@ -15,9 +15,7 @@ INSTALLER_PATH = PACKAGE_ROOT / "studio" / "install_llama_prebuilt.py"
 
 
 def load_installer_module():
-    spec = importlib.util.spec_from_file_location(
-        "studio_install_llama_prebuilt", INSTALLER_PATH
-    )
+    spec = importlib.util.spec_from_file_location("studio_install_llama_prebuilt", INSTALLER_PATH)
     if spec is None or spec.loader is None:
         raise RuntimeError(f"unable to load installer module from {INSTALLER_PATH}")
     module = importlib.util.module_from_spec(spec)
@@ -112,17 +110,13 @@ def main() -> int:
             published_release_tag = args.published_release_tag,
         )
         print(f"[smoke] PASS install_dir={install_dir}")
-        print(
-            "[smoke] note=This was a real prebuilt install into an isolated temp directory."
-        )
+        print("[smoke] note=This was a real prebuilt install into an isolated temp directory.")
         return installer.EXIT_SUCCESS
     except SystemExit as exc:
         code = int(exc.code) if isinstance(exc.code, int) else installer.EXIT_ERROR
         if code == installer.EXIT_FALLBACK:
             print(f"[smoke] FALLBACK install_dir={install_dir}")
-            print(
-                "[smoke] note=Prebuilt path failed and would fall back to source build in setup."
-            )
+            print("[smoke] note=Prebuilt path failed and would fall back to source build in setup.")
             print(installer.collect_system_report(host, choice, install_dir))
         else:
             print(f"[smoke] ERROR exit_code={code} install_dir={install_dir}")
diff --git a/tests/studio/install/smoke_test_parallel_studio_home.py b/tests/studio/install/smoke_test_parallel_studio_home.py
index 133591fb33..c4fc250655 100644
--- a/tests/studio/install/smoke_test_parallel_studio_home.py
+++ b/tests/studio/install/smoke_test_parallel_studio_home.py
@@ -86,12 +86,7 @@ def _free_port() -> int:
 
 
 def _run_one_install(
-    label: str,
-    repo: Path,
-    studio_home: Path,
-    fake_home: Path,
-    uv_cache: Path,
-    log_path: Path,
+    label: str, repo: Path, studio_home: Path, fake_home: Path, uv_cache: Path, log_path: Path
 ) -> tuple[str, int]:
     studio_home.mkdir(parents = True, exist_ok = True)
     fake_home.mkdir(parents = True, exist_ok = True)
@@ -159,12 +154,14 @@ def _wait_for_health(port: int, timeout: float) -> dict:
         except (urllib.error.URLError, ConnectionError, OSError) as e:
             last_err = e
         time.sleep(HEALTH_POLL_INTERVAL_S)
-    raise TestFailure(
-        f"port {port}: /api/health never returned 200 (last_err={last_err})"
-    )
+    raise TestFailure(f"port {port}: /api/health never returned 200 (last_err={last_err})")
 
 
-def _http_status(port: int, path: str, timeout: float = 5.0) -> int:
+def _http_status(
+    port: int,
+    path: str,
+    timeout: float = 5.0,
+) -> int:
     url = f"http://127.0.0.1:{port}{path}"
     try:
         with urllib.request.urlopen(url, timeout = timeout) as r:
@@ -211,9 +208,7 @@ def _check_install_layout(label: str, studio_home: Path) -> dict:
         raise TestFailure(f"[{label}] launch-studio.sh kept @@DATA_DIR@@ placeholder")
     expected_data_dir_line = f"DATA_DIR='{studio_home}/share'"
     if expected_data_dir_line not in launcher:
-        raise TestFailure(
-            f"[{label}] launch-studio.sh missing {expected_data_dir_line!r}"
-        )
+        raise TestFailure(f"[{label}] launch-studio.sh missing {expected_data_dir_line!r}")
 
     return {"label": label, "studio_home": str(studio_home), "install_id": install_id}
 
@@ -230,9 +225,7 @@ def _check_fake_home_clean(fake_home: Path) -> None:
     ]
     leaked = [str(p) for p in forbidden if (fake_home / p).exists()]
     if leaked:
-        raise TestFailure(
-            f"redirected HOME picked up persistent install pollution: {leaked}"
-        )
+        raise TestFailure(f"redirected HOME picked up persistent install pollution: {leaked}")
 
 
 def _backend_pid_python(pid: int) -> Path | None:
@@ -256,9 +249,7 @@ def run(n_installs: int, keep: bool) -> int:
 
     repo = PACKAGE_ROOT
     if not (repo / "install.sh").is_file():
-        raise TestFailure(
-            f"install.sh not found at {repo}; " "run from a clone of unslothai/unsloth"
-        )
+        raise TestFailure(f"install.sh not found at {repo}; run from a clone of unslothai/unsloth")
 
     test_root = Path(tempfile.mkdtemp(prefix = "unsloth_studio_clash_"))
     _log(f"test root: {test_root}")
@@ -346,8 +337,7 @@ def run(n_installs: int, keep: bool) -> int:
                 raise TestFailure(f"[{label}] chat_only is not true under --no-torch")
             if health["studio_root_id"] in seen_root_ids:
                 raise TestFailure(
-                    f"[{label}] studio_root_id collision at runtime: "
-                    f"{health['studio_root_id']}"
+                    f"[{label}] studio_root_id collision at runtime: " f"{health['studio_root_id']}"
                 )
             seen_root_ids.add(health["studio_root_id"])
 
@@ -358,9 +348,7 @@ def run(n_installs: int, keep: bool) -> int:
 
             exe = _backend_pid_python(proc.pid)
             if exe is not None:
-                expected_python = (
-                    studio_home / "unsloth_studio" / "bin" / "python"
-                ).resolve()
+                expected_python = (studio_home / "unsloth_studio" / "bin" / "python").resolve()
                 if exe != expected_python:
                     raise TestFailure(
                         f"[{label}] PID {proc.pid} exe={exe}, expected {expected_python}"
@@ -370,10 +358,7 @@ def run(n_installs: int, keep: bool) -> int:
         if len(versions) != 1:
             raise TestFailure(f"version mismatch across installs: {versions}")
 
-        _log(
-            f"PASS: all install + runtime invariants hold "
-            f"(version={next(iter(versions))})"
-        )
+        _log(f"PASS: all install + runtime invariants hold " f"(version={next(iter(versions))})")
         return 0
 
     except TestFailure as e:
diff --git a/tests/studio/install/test_install_llama_prebuilt_logic.py b/tests/studio/install/test_install_llama_prebuilt_logic.py
index 4a427d6f54..de3808469c 100644
--- a/tests/studio/install/test_install_llama_prebuilt_logic.py
+++ b/tests/studio/install/test_install_llama_prebuilt_logic.py
@@ -12,9 +12,7 @@ import pytest
 
 PACKAGE_ROOT = Path(__file__).resolve().parents[3]
 MODULE_PATH = PACKAGE_ROOT / "studio" / "install_llama_prebuilt.py"
-SPEC = importlib.util.spec_from_file_location(
-    "studio_install_llama_prebuilt", MODULE_PATH
-)
+SPEC = importlib.util.spec_from_file_location("studio_install_llama_prebuilt", MODULE_PATH)
 assert SPEC is not None and SPEC.loader is not None
 INSTALL_LLAMA_PREBUILT = importlib.util.module_from_spec(SPEC)
 sys.modules[SPEC.name] = INSTALL_LLAMA_PREBUILT
@@ -274,12 +272,8 @@ def test_validate_prebuilt_choice_creates_repo_shaped_linux_install(
         "preflight_linux_installed_binaries",
         lambda *args, **kwargs: None,
     )
-    monkeypatch.setattr(
-        INSTALL_LLAMA_PREBUILT, "validate_quantize", lambda *args, **kwargs: None
-    )
-    monkeypatch.setattr(
-        INSTALL_LLAMA_PREBUILT, "validate_server", lambda *args, **kwargs: None
-    )
+    monkeypatch.setattr(INSTALL_LLAMA_PREBUILT, "validate_quantize", lambda *args, **kwargs: None)
+    monkeypatch.setattr(INSTALL_LLAMA_PREBUILT, "validate_server", lambda *args, **kwargs: None)
 
     host = HostInfo(
         system = "Linux",
@@ -381,9 +375,7 @@ def test_simple_linux_direct_release_uses_published_source_checksums_for_branch(
             INSTALL_LLAMA_PREBUILT.exact_source_archive_logical_name(
                 source_commit
             ): ApprovedArtifactHash(
-                asset_name = INSTALL_LLAMA_PREBUILT.exact_source_archive_logical_name(
-                    source_commit
-                ),
+                asset_name = INSTALL_LLAMA_PREBUILT.exact_source_archive_logical_name(source_commit),
                 sha256 = "b" * 64,
                 repo = "ggml-org/llama.cpp",
                 kind = "exact-source",
@@ -429,9 +421,7 @@ def test_simple_linux_direct_release_uses_published_source_checksums_for_branch(
     assert plan.approved_checksums.source_commit == source_commit
     assert plan.attempts[0].expected_sha256 == "a" * 64
     source_repo, source_ref, _source_archive, exact_source = (
-        INSTALL_LLAMA_PREBUILT.preferred_source_archive(
-            plan.approved_checksums, plan.llama_tag
-        )
+        INSTALL_LLAMA_PREBUILT.preferred_source_archive(plan.approved_checksums, plan.llama_tag)
     )
     assert source_repo == "ggml-org/llama.cpp"
     assert source_ref == source_commit
@@ -468,9 +458,7 @@ def test_simple_linux_direct_release_honors_torch_cudart_preference(
             ["cuda13", "cuda12"],
             {
                 "cuda13": ["/usr/local/lib/python3.13/site-packages/nvidia/cu13/lib"],
-                "cuda12": [
-                    "/venv/lib/python3.13/site-packages/nvidia/cuda_runtime/lib"
-                ],
+                "cuda12": ["/venv/lib/python3.13/site-packages/nvidia/cuda_runtime/lib"],
             },
         ),
     )
@@ -517,24 +505,20 @@ def test_simple_linux_direct_release_honors_torch_cudart_preference(
     [
         # Missing source_commit.
         (
-            lambda c: setattr(c, "source_commit", None)
-            or setattr(c, "source_commit_short", None),
+            lambda c: setattr(c, "source_commit", None) or setattr(c, "source_commit_short", None),
             "exact source provenance",
         ),
         # source_commit present, but no exact-source archive hash.
         (
             lambda c: c.artifacts.pop(
-                INSTALL_LLAMA_PREBUILT.exact_source_archive_logical_name(
-                    c.source_commit
-                ),
+                INSTALL_LLAMA_PREBUILT.exact_source_archive_logical_name(c.source_commit),
                 None,
             ),
             "exact source provenance",
         ),
         # source_commit + exact-source archive present, but no source_repo.
         (
-            lambda c: setattr(c, "source_repo", None)
-            or setattr(c, "source_repo_url", None),
+            lambda c: setattr(c, "source_repo", None) or setattr(c, "source_repo_url", None),
             "exact source provenance",
         ),
     ],
@@ -545,9 +529,7 @@ def test_simple_linux_direct_release_honors_torch_cudart_preference(
     ],
 )
 def test_simple_linux_direct_release_rejects_branch_without_exact_source_metadata(
-    monkeypatch: pytest.MonkeyPatch,
-    mutate,
-    expected_match,
+    monkeypatch: pytest.MonkeyPatch, mutate, expected_match
 ):
     source_commit = "25b1bc9c2f9aa0a390b968ee1ffd9ff01340a3fe"
     release = {
@@ -583,9 +565,7 @@ def test_simple_linux_direct_release_rejects_branch_without_exact_source_metadat
             INSTALL_LLAMA_PREBUILT.exact_source_archive_logical_name(
                 source_commit
             ): ApprovedArtifactHash(
-                asset_name = INSTALL_LLAMA_PREBUILT.exact_source_archive_logical_name(
-                    source_commit
-                ),
+                asset_name = INSTALL_LLAMA_PREBUILT.exact_source_archive_logical_name(source_commit),
                 sha256 = "b" * 64,
                 repo = "ggml-org/llama.cpp",
                 kind = "exact-source",
@@ -646,9 +626,7 @@ def test_simple_linux_direct_release_keeps_legacy_b_tag_path_without_checksums(
     }
 
     def unexpected_checksum_load(repo: str, release_tag: str):
-        raise AssertionError(
-            "legacy b-tag direct releases should not require checksum metadata"
-        )
+        raise AssertionError("legacy b-tag direct releases should not require checksum metadata")
 
     monkeypatch.setattr(
         INSTALL_LLAMA_PREBUILT,
@@ -741,12 +719,8 @@ def test_validate_prebuilt_choice_creates_repo_shaped_windows_install(
         "preflight_linux_installed_binaries",
         lambda *args, **kwargs: None,
     )
-    monkeypatch.setattr(
-        INSTALL_LLAMA_PREBUILT, "validate_quantize", lambda *args, **kwargs: None
-    )
-    monkeypatch.setattr(
-        INSTALL_LLAMA_PREBUILT, "validate_server", lambda *args, **kwargs: None
-    )
+    monkeypatch.setattr(INSTALL_LLAMA_PREBUILT, "validate_quantize", lambda *args, **kwargs: None)
+    monkeypatch.setattr(INSTALL_LLAMA_PREBUILT, "validate_server", lambda *args, **kwargs: None)
 
     host = HostInfo(
         system = "Windows",
@@ -809,9 +783,7 @@ def test_validate_prebuilt_choice_creates_repo_shaped_windows_install(
 
 
 def test_activate_install_tree_restores_existing_install_after_activation_failure(
-    tmp_path: Path,
-    monkeypatch: pytest.MonkeyPatch,
-    capsys: pytest.CaptureFixture[str],
+    tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
 ):
     install_dir = tmp_path / "llama.cpp"
     install_dir.mkdir()
@@ -839,9 +811,7 @@ def test_activate_install_tree_restores_existing_install_after_activation_failur
     monkeypatch.setattr(
         INSTALL_LLAMA_PREBUILT,
         "confirm_install_tree",
-        lambda *_args, **_kwargs: (_ for _ in ()).throw(
-            RuntimeError("activation confirm failed")
-        ),
+        lambda *_args, **_kwargs: (_ for _ in ()).throw(RuntimeError("activation confirm failed")),
     )
 
     with pytest.raises(
@@ -862,9 +832,7 @@ def test_activate_install_tree_restores_existing_install_after_activation_failur
 
 
 def test_activate_install_tree_cleans_all_paths_when_rollback_restore_fails(
-    tmp_path: Path,
-    monkeypatch: pytest.MonkeyPatch,
-    capsys: pytest.CaptureFixture[str],
+    tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
 ):
     install_dir = tmp_path / "llama.cpp"
     install_dir.mkdir()
@@ -892,9 +860,7 @@ def test_activate_install_tree_cleans_all_paths_when_rollback_restore_fails(
     monkeypatch.setattr(
         INSTALL_LLAMA_PREBUILT,
         "confirm_install_tree",
-        lambda *_args, **_kwargs: (_ for _ in ()).throw(
-            RuntimeError("activation confirm failed")
-        ),
+        lambda *_args, **_kwargs: (_ for _ in ()).throw(RuntimeError("activation confirm failed")),
     )
 
     original_replace = INSTALL_LLAMA_PREBUILT.os.replace
@@ -921,10 +887,7 @@ def test_activate_install_tree_cleans_all_paths_when_rollback_restore_fails(
     captured = capsys.readouterr()
     output = captured.out + captured.err
     assert "rollback after failed activation also failed: restore failed" in output
-    assert (
-        "cleaning staging, install, and rollback paths before source build fallback"
-        in output
-    )
+    assert "cleaning staging, install, and rollback paths before source build fallback" in output
     assert "removing failed install path" in output
     assert "removing rollback path" in output
 
@@ -1108,9 +1071,7 @@ def write_linux_install_shape(install_dir: Path) -> None:
     (runtime_dir / "libggml-base.so.0").write_bytes(b"DLL")
     (runtime_dir / "libggml-cpu-x64.so.0").write_bytes(b"DLL")
     (runtime_dir / "libmtmd.so.0").write_bytes(b"DLL")
-    (install_dir / "convert_hf_to_gguf.py").write_text(
-        "#!/usr/bin/env python3\n", encoding = "utf-8"
-    )
+    (install_dir / "convert_hf_to_gguf.py").write_text("#!/usr/bin/env python3\n", encoding = "utf-8")
     (install_dir / "gguf-py" / "gguf").mkdir(parents = True, exist_ok = True)
 
 
@@ -1134,9 +1095,7 @@ def write_windows_install_shape(
         (runtime_dir / "cudart64_12.dll").write_bytes(b"DLL")
         (runtime_dir / "cublas64_12.dll").write_bytes(b"DLL")
         (runtime_dir / "cublasLt64_12.dll").write_bytes(b"DLL")
-    (install_dir / "convert_hf_to_gguf.py").write_text(
-        "#!/usr/bin/env python3\n", encoding = "utf-8"
-    )
+    (install_dir / "convert_hf_to_gguf.py").write_text("#!/usr/bin/env python3\n", encoding = "utf-8")
     (install_dir / "gguf-py" / "gguf").mkdir(parents = True, exist_ok = True)
 
 
@@ -1159,9 +1118,7 @@ def write_macos_install_shape(
         (runtime_dir / "libggml.0.dylib").write_bytes(b"DLL")
     if include_libmtmd:
         (runtime_dir / "libmtmd.0.dylib").write_bytes(b"DLL")
-    (install_dir / "convert_hf_to_gguf.py").write_text(
-        "#!/usr/bin/env python3\n", encoding = "utf-8"
-    )
+    (install_dir / "convert_hf_to_gguf.py").write_text("#!/usr/bin/env python3\n", encoding = "utf-8")
     (install_dir / "gguf-py" / "gguf").mkdir(parents = True, exist_ok = True)
 
 
@@ -1240,8 +1197,7 @@ def test_existing_install_matches_plan_false_without_fingerprint(tmp_path: Path)
     install_dir.mkdir()
     write_linux_install_shape(install_dir)
     (install_dir / "UNSLOTH_PREBUILT_INFO.json").write_text(
-        json.dumps({"tag": "b9001", "asset": "llama-b9001-bin-ubuntu-x64.tar.gz"})
-        + "\n",
+        json.dumps({"tag": "b9001", "asset": "llama-b9001-bin-ubuntu-x64.tar.gz"}) + "\n",
         encoding = "utf-8",
     )
 
@@ -1304,9 +1260,7 @@ def test_existing_install_matches_plan_false_with_malformed_metadata(tmp_path: P
     install_dir = tmp_path / "llama.cpp"
     install_dir.mkdir()
     write_linux_install_shape(install_dir)
-    (install_dir / "UNSLOTH_PREBUILT_INFO.json").write_text(
-        "{not-json\n", encoding = "utf-8"
-    )
+    (install_dir / "UNSLOTH_PREBUILT_INFO.json").write_text("{not-json\n", encoding = "utf-8")
 
     host = HostInfo(
         system = "Linux",
@@ -1437,9 +1391,7 @@ def test_existing_install_matches_plan_windows_cpu_requires_llama_dll(tmp_path:
 def test_existing_install_matches_plan_windows_cuda_requires_cuda_dll(tmp_path: Path):
     install_dir = tmp_path / "llama.cpp"
     install_dir.mkdir()
-    write_windows_install_shape(
-        install_dir, include_llama_dll = True, include_cuda_dll = True
-    )
+    write_windows_install_shape(install_dir, include_llama_dll = True, include_cuda_dll = True)
 
     host = HostInfo(
         system = "Windows",
@@ -1508,9 +1460,7 @@ def test_existing_install_matches_plan_windows_cuda_requires_cuda_dll(tmp_path:
     assert existing_install_matches_plan(install_dir, host, plan) is False
 
 
-def test_existing_install_matches_plan_windows_cuda_paired_requires_cudart(
-    tmp_path: Path,
-):
+def test_existing_install_matches_plan_windows_cuda_paired_requires_cudart(tmp_path: Path):
     """When the choice ships a paired cudart bundle (#5106), the install
     is considered stale unless cudart64_*.dll and cublas64_*.dll are
     actually on disk. Otherwise existing broken installs would keep
@@ -1626,9 +1576,7 @@ def test_existing_install_matches_plan_windows_cuda_paired_requires_cudart(
     assert existing_install_matches_plan(install_dir, host, plan) is False
 
 
-def test_existing_install_matches_plan_windows_cuda_unpaired_skips_cudart_check(
-    tmp_path: Path,
-):
+def test_existing_install_matches_plan_windows_cuda_unpaired_skips_cudart_check(tmp_path: Path):
     """If the choice has no paired runtime archive (manifest dropped it,
     or upstream did not ship cudart), legacy installs without cudart on
     disk must still pass the health check -- otherwise the installer
@@ -1708,9 +1656,7 @@ def test_existing_install_matches_plan_windows_cuda_unpaired_skips_cudart_check(
     assert existing_install_matches_plan(install_dir, host, plan) is True
 
 
-def test_existing_install_fingerprint_changes_when_cudart_pair_added(
-    tmp_path: Path,
-):
+def test_existing_install_fingerprint_changes_when_cudart_pair_added(tmp_path: Path):
     """Existing pre-#5322 Windows CUDA installs (no paired cudart) must
     be treated as stale once the choice gains a runtime archive,
     otherwise the fingerprint match would keep skipping the reinstall
@@ -1985,9 +1931,7 @@ def test_install_prebuilt_skips_download_when_existing_install_matches(
         INSTALL_LLAMA_PREBUILT,
         "download_validation_model",
         lambda *args, **kwargs: (_ for _ in ()).throw(
-            AssertionError(
-                "matching install should skip before validation model download"
-            )
+            AssertionError("matching install should skip before validation model download")
         ),
     )
 
@@ -2503,9 +2447,7 @@ def test_install_prebuilt_same_tag_upstream_failure_uses_older_unsloth_release_p
         (staging_dir / "marker.txt").write_text("ready\n")
         return attempts[0], staging_dir, initial_fallback_used
 
-    monkeypatch.setattr(
-        INSTALL_LLAMA_PREBUILT, "validate_prebuilt_attempts", fake_validate
-    )
+    monkeypatch.setattr(INSTALL_LLAMA_PREBUILT, "validate_prebuilt_attempts", fake_validate)
 
     activated = {}
     monkeypatch.setattr(
@@ -2523,10 +2465,7 @@ def test_install_prebuilt_same_tag_upstream_failure_uses_older_unsloth_release_p
 
     install_prebuilt(install_dir, "latest", "unslothai/llama.cpp", "")
 
-    assert attempted == [
-        ("b9002", "release-2", "upstream"),
-        ("b9001", "release-1", "upstream"),
-    ]
+    assert attempted == [("b9002", "release-2", "upstream"), ("b9001", "release-1", "upstream")]
     assert activated["install_dir"] == install_dir
 
 
@@ -2535,7 +2474,11 @@ def io_bytes(data: bytes):
 
 
 def add_bytes_to_tar(
-    archive: tarfile.TarFile, name: str, data: bytes, *, mode: int = 0o644
+    archive: tarfile.TarFile,
+    name: str,
+    data: bytes,
+    *,
+    mode: int = 0o644,
 ) -> None:
     info = tarfile.TarInfo(name)
     info.size = len(data)
@@ -2550,9 +2493,7 @@ def add_symlink_to_tar(archive: tarfile.TarFile, name: str, target: str) -> None
     archive.addfile(info)
 
 
-def test_existing_install_matches_choice_fails_when_install_tree_incomplete(
-    tmp_path: Path,
-):
+def test_existing_install_matches_choice_fails_when_install_tree_incomplete(tmp_path: Path):
     """confirm_install_tree guard rejects installs missing critical files."""
     install_dir = tmp_path / "llama.cpp"
     install_dir.mkdir()
@@ -2641,9 +2582,7 @@ def test_existing_install_matches_choice_fails_when_install_tree_incomplete(
     )
 
 
-def test_existing_install_matches_choice_fails_when_install_tree_incomplete_macos(
-    tmp_path: Path,
-):
+def test_existing_install_matches_choice_fails_when_install_tree_incomplete_macos(tmp_path: Path):
     """confirm_install_tree guard rejects macOS arm64 installs missing critical files."""
     install_dir = tmp_path / "llama.cpp"
     install_dir.mkdir()
@@ -2780,9 +2719,7 @@ def test_paired_runtime_dll_patterns_excludes_executables() -> None:
         assert paired_runtime_dll_patterns(non_windows) == []
 
 
-def test_runtime_overlay_cannot_overwrite_main_archive_payload(
-    tmp_path: Path,
-) -> None:
+def test_runtime_overlay_cannot_overwrite_main_archive_payload(tmp_path: Path) -> None:
     """End-to-end: a malformed runtime archive containing
     ``llama-server.exe`` alongside the real cudart DLLs must NOT
     replace the main archive's ``llama-server.exe``.
@@ -2846,15 +2783,20 @@ def test_runtime_overlay_cannot_overwrite_main_archive_payload(
 
     orig_download = INSTALL_LLAMA_PREBUILT.download_file_verified
 
-    def fake_download(url, target_path, *, expected_sha256 = None, label = None, **kw):
+    def fake_download(
+        url,
+        target_path,
+        *,
+        expected_sha256 = None,
+        label = None,
+        **kw,
+    ):
         src = main_zip if "cudart" not in url else runtime_zip
         _shutil.copy2(src, target_path)
         if expected_sha256:
             actual = hashlib.sha256(Path(target_path).read_bytes()).hexdigest()
             if actual != expected_sha256:
-                raise INSTALL_LLAMA_PREBUILT.PrebuiltFallback(
-                    f"sha256 mismatch on {label}"
-                )
+                raise INSTALL_LLAMA_PREBUILT.PrebuiltFallback(f"sha256 mismatch on {label}")
 
     INSTALL_LLAMA_PREBUILT.download_file_verified = fake_download
     try:
@@ -2866,16 +2808,13 @@ def test_runtime_overlay_cannot_overwrite_main_archive_payload(
     server = release_dir / "llama-server.exe"
     assert server.exists()
     assert server.read_bytes() == b"MAIN-SERVER", (
-        "runtime archive overwrote main llama-server.exe; "
-        f"got {server.read_bytes()!r}"
+        "runtime archive overwrote main llama-server.exe; " f"got {server.read_bytes()!r}"
     )
     for name in ("cudart64_12.dll", "cublas64_12.dll", "cublasLt64_12.dll"):
         assert (release_dir / name).exists(), f"missing {name}"
 
 
-def test_linux_runtime_overlay_copies_llama_tool_impl_libraries(
-    tmp_path: Path,
-) -> None:
+def test_linux_runtime_overlay_copies_llama_tool_impl_libraries(tmp_path: Path) -> None:
     install_from_archives = INSTALL_LLAMA_PREBUILT.install_from_archives
 
     work = tmp_path / "work"
@@ -2939,14 +2878,19 @@ def test_linux_runtime_overlay_copies_llama_tool_impl_libraries(
 
     orig_download = INSTALL_LLAMA_PREBUILT.download_file_verified
 
-    def fake_download(url, target_path, *, expected_sha256 = None, label = None, **kw):
+    def fake_download(
+        url,
+        target_path,
+        *,
+        expected_sha256 = None,
+        label = None,
+        **kw,
+    ):
         _shutil.copy2(bundle, target_path)
         if expected_sha256:
             actual = hashlib.sha256(Path(target_path).read_bytes()).hexdigest()
             if actual != expected_sha256:
-                raise INSTALL_LLAMA_PREBUILT.PrebuiltFallback(
-                    f"sha256 mismatch on {label}"
-                )
+                raise INSTALL_LLAMA_PREBUILT.PrebuiltFallback(f"sha256 mismatch on {label}")
 
     INSTALL_LLAMA_PREBUILT.download_file_verified = fake_download
     try:
@@ -2964,9 +2908,7 @@ def test_linux_runtime_overlay_copies_llama_tool_impl_libraries(
     assert not (runtime_dir / "llama-cli").exists()
 
 
-def test_python_runtime_dirs_covers_cu13_and_library_bin(
-    monkeypatch, tmp_path: Path
-) -> None:
+def test_python_runtime_dirs_covers_cu13_and_library_bin(monkeypatch, tmp_path: Path) -> None:
     """Installer-side runtime DLL discovery must scan the same path
     set as the backend ``_windows_pip_nvidia_dll_dirs``: legacy
     ``nvidia//bin``, current ``nvidia//bin/x86_64``
diff --git a/tests/studio/install/test_llama_pr_force_and_source.py b/tests/studio/install/test_llama_pr_force_and_source.py
index 2d7c038861..17c58cba51 100644
--- a/tests/studio/install/test_llama_pr_force_and_source.py
+++ b/tests/studio/install/test_llama_pr_force_and_source.py
@@ -35,7 +35,10 @@ requires_pwsh = pytest.mark.skipif(not PWSH_AVAILABLE, reason = "pwsh not availa
 # Helpers
 # ---------------------------------------------------------------------------
 def run_bash(
-    script: str, *, timeout: int = 60, env: dict | None = None
+    script: str,
+    *,
+    timeout: int = 60,
+    env: dict | None = None,
 ) -> subprocess.CompletedProcess:
     """Run a bash script fragment and return the CompletedProcess.
     60s default tolerates slow shell startup on heavily-loaded CI
@@ -53,7 +56,10 @@ def run_bash(
 
 
 def run_pwsh(
-    script: str, *, timeout: int = 60, env: dict | None = None
+    script: str,
+    *,
+    timeout: int = 60,
+    env: dict | None = None,
 ) -> subprocess.CompletedProcess:
     """Run a PowerShell script fragment and return the CompletedProcess.
     60s default tolerates slow pwsh startup on heavily-loaded CI
@@ -383,10 +389,7 @@ class TestSourcePatternsSh:
         assert '_DEFAULT_LLAMA_PR_FORCE=""' in self.content
 
     def test_has_default_source(self):
-        assert (
-            '_DEFAULT_LLAMA_SOURCE="https://github.com/ggml-org/llama.cpp"'
-            in self.content
-        )
+        assert '_DEFAULT_LLAMA_SOURCE="https://github.com/ggml-org/llama.cpp"' in self.content
 
     def test_has_pr_force_env_read(self):
         assert "UNSLOTH_LLAMA_PR_FORCE" in self.content
@@ -416,8 +419,7 @@ class TestSourcePatternsSh:
     def test_clone_urls_parameterized_pr_path(self):
         """PR clone path uses ${_LLAMA_SOURCE}.git, not hardcoded URL."""
         pr_clone_idx = self.content.index(
-            'if [ -n "$_LLAMA_PR" ]; then\n'
-            '            run_quiet_no_exit "clone llama.cpp"'
+            'if [ -n "$_LLAMA_PR" ]; then\n            run_quiet_no_exit "clone llama.cpp"'
         )
         else_idx = self.content.index("else\n", pr_clone_idx)
         pr_block = self.content[pr_clone_idx:else_idx]
@@ -437,9 +439,7 @@ class TestSourcePatternsSh:
         lines = self.content.splitlines()
         for i, line in enumerate(lines, 1):
             if "git clone" in line and "ggml-org/llama.cpp.git" in line:
-                pytest.fail(
-                    f"Line {i} has hardcoded ggml-org clone URL: {line.strip()}"
-                )
+                pytest.fail(f"Line {i} has hardcoded ggml-org clone URL: {line.strip()}")
 
 
 # =========================================================================
@@ -456,10 +456,7 @@ class TestSourcePatternsPs1:
         assert '$DefaultLlamaPrForce = ""' in self.content
 
     def test_has_default_source(self):
-        assert (
-            '$DefaultLlamaSource = "https://github.com/ggml-org/llama.cpp"'
-            in self.content
-        )
+        assert '$DefaultLlamaSource = "https://github.com/ggml-org/llama.cpp"' in self.content
 
     def test_has_pr_force_env_read(self):
         assert "$env:UNSLOTH_LLAMA_PR_FORCE" in self.content
@@ -469,10 +466,7 @@ class TestSourcePatternsPs1:
         assert "$LlamaSource = $DefaultLlamaSource" in self.content
 
     def test_release_repo_override_removed(self):
-        assert (
-            "$HelperReleaseRepo = if ($env:UNSLOTH_LLAMA_RELEASE_REPO)"
-            not in self.content
-        )
+        assert "$HelperReleaseRepo = if ($env:UNSLOTH_LLAMA_RELEASE_REPO)" not in self.content
         assert '$HelperReleaseRepo = "ggml-org/llama.cpp"' in self.content
 
     def test_force_compile_skips_prebuilt_resolution_early(self):
@@ -491,9 +485,7 @@ class TestSourcePatternsPs1:
 
     def test_clone_urls_parameterized_pr_path(self):
         """PR clone path uses $LlamaSource.git, not hardcoded URL."""
-        pr_idx = self.content.index(
-            "if ($LlamaPr) {\n", self.content.index("Cloning llama.cpp")
-        )
+        pr_idx = self.content.index("if ($LlamaPr) {\n", self.content.index("Cloning llama.cpp"))
         else_idx = self.content.index("} else {", pr_idx)
         pr_block = self.content[pr_idx:else_idx]
         assert '"$LlamaSource.git"' in pr_block
@@ -511,9 +503,7 @@ class TestSourcePatternsPs1:
         lines = self.content.splitlines()
         for i, line in enumerate(lines, 1):
             if "git clone" in line and "ggml-org/llama.cpp.git" in line:
-                pytest.fail(
-                    f"Line {i} has hardcoded ggml-org clone URL: {line.strip()}"
-                )
+                pytest.fail(f"Line {i} has hardcoded ggml-org clone URL: {line.strip()}")
 
 
 # =========================================================================
diff --git a/tests/studio/install/test_macos_version_compat.py b/tests/studio/install/test_macos_version_compat.py
index 1b87e5af65..7f93b295eb 100644
--- a/tests/studio/install/test_macos_version_compat.py
+++ b/tests/studio/install/test_macos_version_compat.py
@@ -20,9 +20,7 @@ import pytest
 
 PACKAGE_ROOT = Path(__file__).resolve().parents[3]
 MODULE_PATH = PACKAGE_ROOT / "studio" / "install_llama_prebuilt.py"
-SPEC = importlib.util.spec_from_file_location(
-    "studio_install_llama_prebuilt_macos", MODULE_PATH
-)
+SPEC = importlib.util.spec_from_file_location("studio_install_llama_prebuilt_macos", MODULE_PATH)
 assert SPEC is not None and SPEC.loader is not None
 ILP = importlib.util.module_from_spec(SPEC)
 sys.modules[SPEC.name] = ILP
@@ -54,7 +52,12 @@ def make_macos_host(macos_version, *, arm64 = True):
     )
 
 
-def thin_macho(minos = (14, 0), *, cputype = _CPU_TYPE_ARM64, build_version = True):
+def thin_macho(
+    minos = (14, 0),
+    *,
+    cputype = _CPU_TYPE_ARM64,
+    build_version = True,
+):
     """Synthesize a minimal little-endian 64-bit Mach-O carrying a macOS
     minimum-version load command."""
     encoded = (minos[0] << 16) | (minos[1] << 8)
@@ -139,10 +142,7 @@ class TestMachoMinimumMacos:
             )
         )
         assert ILP.macho_minimum_macos(path, make_macos_host((14, 0))) == (14, 0)
-        assert ILP.macho_minimum_macos(path, make_macos_host((26, 0), arm64 = False)) == (
-            26,
-            0,
-        )
+        assert ILP.macho_minimum_macos(path, make_macos_host((26, 0), arm64 = False)) == (26, 0)
 
     def test_non_macho_returns_none(self, tmp_path):
         path = tmp_path / "script.sh"
@@ -185,23 +185,17 @@ class TestPreflightMacosInstalledBinaries:
     def test_rejects_too_new_dylib(self, tmp_path):
         install_dir, binaries = self._install_dir(tmp_path, (26, 0))
         with pytest.raises(PrebuiltFallback, match = "newer macOS"):
-            ILP.preflight_macos_installed_binaries(
-                binaries, install_dir, make_macos_host((14, 0))
-            )
+            ILP.preflight_macos_installed_binaries(binaries, install_dir, make_macos_host((14, 0)))
 
     def test_accepts_compatible_prebuilt(self, tmp_path):
         install_dir, binaries = self._install_dir(tmp_path, (14, 0))
         # Must not raise on a macOS 15 host.
-        ILP.preflight_macos_installed_binaries(
-            binaries, install_dir, make_macos_host((15, 5))
-        )
+        ILP.preflight_macos_installed_binaries(binaries, install_dir, make_macos_host((15, 5)))
 
     def test_skips_when_host_version_unknown(self, tmp_path):
         install_dir, binaries = self._install_dir(tmp_path, (26, 0))
         # Unknown host version -> defer to runtime validation, do not raise.
-        ILP.preflight_macos_installed_binaries(
-            binaries, install_dir, make_macos_host(None)
-        )
+        ILP.preflight_macos_installed_binaries(binaries, install_dir, make_macos_host(None))
 
     def test_noop_on_non_macos_host(self, tmp_path):
         install_dir, binaries = self._install_dir(tmp_path, (26, 0))
diff --git a/tests/studio/install/test_pr4562_bugfixes.py b/tests/studio/install/test_pr4562_bugfixes.py
index 34b144a905..5b1c4a44e5 100644
--- a/tests/studio/install/test_pr4562_bugfixes.py
+++ b/tests/studio/install/test_pr4562_bugfixes.py
@@ -29,9 +29,7 @@ import pytest
 # ---------------------------------------------------------------------------
 PACKAGE_ROOT = Path(__file__).resolve().parents[3]
 MODULE_PATH = PACKAGE_ROOT / "studio" / "install_llama_prebuilt.py"
-SPEC = importlib.util.spec_from_file_location(
-    "studio_install_llama_prebuilt", MODULE_PATH
-)
+SPEC = importlib.util.spec_from_file_location("studio_install_llama_prebuilt", MODULE_PATH)
 assert SPEC is not None and SPEC.loader is not None
 MOD = importlib.util.module_from_spec(SPEC)
 sys.modules[SPEC.name] = MOD
@@ -74,7 +72,12 @@ def make_host(*, system: str) -> HostInfo:
 BASH = "/bin/bash"
 
 
-def run_bash(script: str, *, timeout: int = 10, env: dict | None = None) -> str:
+def run_bash(
+    script: str,
+    *,
+    timeout: int = 10,
+    env: dict | None = None,
+) -> str:
     """Run a bash script fragment and return its stdout."""
     run_env = os.environ.copy()
     if env:
@@ -113,9 +116,7 @@ class TestBinaryEnvCrossPlatform:
         env = binary_env(binary_path, install_dir, host)
         ld_dirs = env["LD_LIBRARY_PATH"].split(os.pathsep)
         assert str(bin_dir) in ld_dirs, f"build/bin not in LD_LIBRARY_PATH: {ld_dirs}"
-        assert (
-            str(install_dir) in ld_dirs
-        ), f"install_dir not in LD_LIBRARY_PATH: {ld_dirs}"
+        assert str(install_dir) in ld_dirs, f"install_dir not in LD_LIBRARY_PATH: {ld_dirs}"
 
     def test_linux_binary_parent_comes_before_install_dir(
         self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
@@ -134,9 +135,7 @@ class TestBinaryEnvCrossPlatform:
         ld_dirs = env["LD_LIBRARY_PATH"].split(os.pathsep)
         bin_idx = ld_dirs.index(str(bin_dir))
         install_idx = ld_dirs.index(str(install_dir))
-        assert (
-            bin_idx < install_idx
-        ), "binary_path.parent should come before install_dir"
+        assert bin_idx < install_idx, "binary_path.parent should come before install_dir"
 
     def test_linux_deduplicates_when_binary_parent_equals_install_dir(
         self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
@@ -195,17 +194,13 @@ class TestBinaryEnvCrossPlatform:
         binary_path.write_bytes(b"MZ")
 
         host = make_host(system = "Windows")
-        monkeypatch.setattr(
-            MOD, "windows_runtime_dirs_for_runtime_line", lambda _rt: []
-        )
+        monkeypatch.setattr(MOD, "windows_runtime_dirs_for_runtime_line", lambda _rt: [])
 
         env = binary_env(binary_path, install_dir, host)
         path_dirs = env["PATH"].split(os.pathsep)
         assert str(bin_dir) in path_dirs, f"build/bin/Release not in PATH: {path_dirs}"
 
-    def test_macos_sets_dyld_library_path(
-        self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
-    ):
+    def test_macos_sets_dyld_library_path(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
         install_dir = tmp_path / "llama.cpp"
         install_dir.mkdir(parents = True)
         bin_dir = install_dir / "build" / "bin"
@@ -218,12 +213,8 @@ class TestBinaryEnvCrossPlatform:
 
         env = binary_env(binary_path, install_dir, host)
         dyld_parts = [p for p in env["DYLD_LIBRARY_PATH"].split(os.pathsep) if p]
-        assert (
-            str(bin_dir) in dyld_parts
-        ), f"build/bin not in DYLD_LIBRARY_PATH: {dyld_parts}"
-        assert (
-            str(install_dir) in dyld_parts
-        ), f"install_dir not in DYLD_LIBRARY_PATH: {dyld_parts}"
+        assert str(bin_dir) in dyld_parts, f"build/bin not in DYLD_LIBRARY_PATH: {dyld_parts}"
+        assert str(install_dir) in dyld_parts, f"install_dir not in DYLD_LIBRARY_PATH: {dyld_parts}"
         # binary_path.parent (build/bin) should come before install_dir
         assert dyld_parts.index(str(bin_dir)) < dyld_parts.index(str(install_dir))
 
@@ -303,7 +294,11 @@ class TestResolveRequestedLlamaTag:
     ):
         captured = {}
 
-        def fake_resolve(requested_tag, published_repo, published_release_tag = ""):
+        def fake_resolve(
+            requested_tag,
+            published_repo,
+            published_release_tag = "",
+        ):
             captured["requested_tag"] = requested_tag
             captured["published_repo"] = published_repo
             captured["published_release_tag"] = published_release_tag
@@ -350,9 +345,7 @@ class TestResolveRequestedLlamaTag:
 
 
 class TestFetchJsonRetries:
-    def test_fetch_json_retries_invalid_github_api_json(
-        self, monkeypatch: pytest.MonkeyPatch
-    ):
+    def test_fetch_json_retries_invalid_github_api_json(self, monkeypatch: pytest.MonkeyPatch):
         calls = {"count": 0}
 
         def fake_download_bytes(url, **kwargs):
@@ -593,11 +586,7 @@ class TestLatestTagResolution:
     """)
 
     def _run_resolve(
-        self,
-        tmp_path: Path,
-        requested_tag: str,
-        resolved_tag: str,
-        resolve_status: int,
+        self, tmp_path: Path, requested_tag: str, resolved_tag: str, resolve_status: int
     ) -> str:
         script = self.RESOLVE_TEMPLATE.format(
             requested_tag = requested_tag,
@@ -691,10 +680,7 @@ class TestSourceCodePatterns:
         content = SETUP_SH.read_text()
         assert "--resolve-source-build" not in content
         assert "--resolve-install-tag" not in content
-        assert (
-            '--resolve-llama-tag latest --published-repo "ggml-org/llama.cpp"'
-            in content
-        )
+        assert '--resolve-llama-tag latest --published-repo "ggml-org/llama.cpp"' in content
         assert "--output-format json" in content
         assert "_RESOLVED_SOURCE_URL" in content
         assert "_RESOLVED_SOURCE_REF_KIND" in content
@@ -758,9 +744,7 @@ class TestSourceCodePatterns:
         # Delivered via NVCC_PREPEND_FLAGS (covers the configure-time compiler
         # probe too), not embedded in the word-split CMAKE_ARGS string.
         assert "export NVCC_PREPEND_FLAGS=" in content
-        cmake_args_lines = [
-            line for line in content.splitlines() if "CMAKE_ARGS=" in line
-        ]
+        cmake_args_lines = [line for line in content.splitlines() if "CMAKE_ARGS=" in line]
         assert all(
             "-allow-unsupported-compiler" not in line for line in cmake_args_lines
         ), "flag must stay out of CMAKE_ARGS (bash word-splitting safety)"
@@ -776,9 +760,7 @@ class TestSourceCodePatterns:
         # Delivered via the process environment, not the $CmakeArgs array, so it
         # reaches both the configure-time compiler probe and `cmake --build`.
         assert "$env:NVCC_PREPEND_FLAGS" in content
-        cmake_args_lines = [
-            line for line in content.splitlines() if "$CmakeArgs +=" in line
-        ]
+        cmake_args_lines = [line for line in content.splitlines() if "$CmakeArgs +=" in line]
         assert all(
             "-allow-unsupported-compiler" not in line for line in cmake_args_lines
         ), "flag must not be pushed into the $CmakeArgs array"
@@ -794,15 +776,10 @@ class TestSourceCodePatterns:
 
     def test_macos_arm64_cpu_fallback_args_exclude_rpath(self):
         """CPU fallback args must NOT contain Metal-only RPATH flags at runtime."""
-        script = (
-            '_IS_MACOS_ARM64=true\nNVCC_PATH=""\nGPU_BACKEND=""\n'
-            + _GPU_BACKEND_FRAGMENT
-        )
+        script = '_IS_MACOS_ARM64=true\nNVCC_PATH=""\nGPU_BACKEND=""\n' + _GPU_BACKEND_FRAGMENT
         output = run_bash(script)
         fallback_line = next(
-            line
-            for line in output.splitlines()
-            if line.startswith("CPU_FALLBACK_CMAKE_ARGS=")
+            line for line in output.splitlines() if line.startswith("CPU_FALLBACK_CMAKE_ARGS=")
         )
         assert "-DGGML_METAL=OFF" in fallback_line
         assert (
@@ -823,8 +800,7 @@ class TestSourceCodePatterns:
         assert (
             "x86_64"
             not in content[
-                content.find("-DGGML_METAL=ON") - 200 : content.find("-DGGML_METAL=ON")
-                + 200
+                content.find("-DGGML_METAL=ON") - 200 : content.find("-DGGML_METAL=ON") + 200
             ]
         )
 
@@ -854,9 +830,7 @@ class TestSourceCodePatterns:
                 # Allow git pull in other contexts
                 context = "\n".join(lines[max(0, i - 5) : i + 5])
                 if "LlamaCppDir" in context:
-                    pytest.fail(
-                        f"Found 'git pull' in llama.cpp build section at line {i+1}"
-                    )
+                    pytest.fail(f"Found 'git pull' in llama.cpp build section at line {i+1}")
 
     def test_setup_ps1_prebuilt_install_uses_simple_policy_only(self):
         """PS1 prebuilt path should use the simplified helper install entrypoint."""
@@ -883,8 +857,7 @@ class TestSourceCodePatterns:
         assert "--resolve-source-build" not in content
         assert "--resolve-install-tag" not in content
         assert (
-            '"--resolve-llama-tag", "latest", "--published-repo", "ggml-org/llama.cpp"'
-            in content
+            '"--resolve-llama-tag", "latest", "--published-repo", "ggml-org/llama.cpp"' in content
         )
         assert '--output-format", "json"' in content
         assert "$ResolvedSourceUrl" in content
@@ -898,10 +871,7 @@ class TestSourceCodePatterns:
         block = content[max(0, install_idx - 800) : install_idx + 800]
         assert "$PSNativeCommandUseErrorActionPreference = $false" in block
         assert "$restoreNativeErrorPreference = $true" in block
-        assert (
-            "$PSNativeCommandUseErrorActionPreference = $previousNativeErrorPreference"
-            in block
-        )
+        assert "$PSNativeCommandUseErrorActionPreference = $previousNativeErrorPreference" in block
 
     def test_setup_ps1_helper_disables_error_action_abort(self):
         """Helper resolution should suppress terminating NativeCommandError on PS 5.1."""
@@ -922,9 +892,7 @@ class TestSourceCodePatterns:
         """The unconstrained nvcc fallback should not sort toolkit dirs lexicographically."""
         content = SETUP_PS1.read_text()
         assert "Sort-Object Name | Select-Object -Last 1" not in content
-        assert (
-            "Sort-Object { [version]($_.Name -replace '^v','') } -Descending" in content
-        )
+        assert "Sort-Object { [version]($_.Name -replace '^v','') } -Descending" in content
 
     def test_binary_env_linux_has_binary_parent(self):
         """The Linux branch of binary_env should include binary_path.parent."""
@@ -985,10 +953,7 @@ class TestMacOSMetalBuildLogic:
 
     def test_macos_arm64_cmake_args_contain_metal_flags(self):
         """macOS arm64 should enable Metal, not CUDA."""
-        script = (
-            '_IS_MACOS_ARM64=true\nNVCC_PATH=""\nGPU_BACKEND=""\n'
-            + _GPU_BACKEND_FRAGMENT
-        )
+        script = '_IS_MACOS_ARM64=true\nNVCC_PATH=""\nGPU_BACKEND=""\n' + _GPU_BACKEND_FRAGMENT
         output = run_bash(script)
         assert "-DGGML_METAL=ON" in output
         assert "-DGGML_CUDA=ON" not in output
@@ -996,10 +961,7 @@ class TestMacOSMetalBuildLogic:
 
     def test_intel_macos_no_metal_flags(self):
         """Intel macOS (not arm64) should not get Metal flags."""
-        script = (
-            '_IS_MACOS_ARM64=false\nNVCC_PATH=""\nGPU_BACKEND=""\n'
-            + _GPU_BACKEND_FRAGMENT
-        )
+        script = '_IS_MACOS_ARM64=false\nNVCC_PATH=""\nGPU_BACKEND=""\n' + _GPU_BACKEND_FRAGMENT
         output = run_bash(script)
         assert "-DGGML_METAL=ON" not in output
         assert "BUILD_DESC=building (CPU)" in output
@@ -1085,18 +1047,14 @@ class TestMacOSMetalBuildLogic:
         # Verify cmake args: first call has Metal ON, second has Metal OFF
         calls = calls_file.read_text().splitlines()
         assert len(calls) >= 2, f"Expected >= 2 cmake calls, got {len(calls)}"
-        assert (
-            "-DGGML_METAL=ON" in calls[0]
-        ), f"First cmake call should have Metal ON: {calls[0]}"
+        assert "-DGGML_METAL=ON" in calls[0], f"First cmake call should have Metal ON: {calls[0]}"
         assert (
             "-DGGML_METAL=OFF" in calls[1]
         ), f"Second cmake call should have Metal OFF: {calls[1]}"
         assert (
             "-DGGML_METAL=ON" not in calls[1]
         ), f"Second cmake call should NOT have Metal ON: {calls[1]}"
-        assert (
-            "@loader_path" not in calls[1]
-        ), f"CPU fallback should not have RPATH: {calls[1]}"
+        assert "@loader_path" not in calls[1], f"CPU fallback should not have RPATH: {calls[1]}"
         assert (
             "-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON" not in calls[1]
         ), f"CPU fallback should not have RPATH build flag: {calls[1]}"
@@ -1204,9 +1162,7 @@ class TestMacOSMetalBuildLogic:
         # Third call: re-configure with Metal OFF and no RPATH flags
         assert "-DGGML_METAL=OFF" in calls[2]
         assert "-DGGML_METAL=ON" not in calls[2]
-        assert (
-            "@loader_path" not in calls[2]
-        ), f"CPU fallback should not have RPATH: {calls[2]}"
+        assert "@loader_path" not in calls[2], f"CPU fallback should not have RPATH: {calls[2]}"
         assert (
             "-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON" not in calls[2]
         ), f"CPU fallback should not have RPATH build flag: {calls[2]}"
diff --git a/tests/studio/install/test_rocm_support.py b/tests/studio/install/test_rocm_support.py
index 4aa7fb3a34..bcfc42c69f 100644
--- a/tests/studio/install/test_rocm_support.py
+++ b/tests/studio/install/test_rocm_support.py
@@ -40,9 +40,7 @@ _normalize_forwarded_gfx = prebuilt_mod._normalize_forwarded_gfx
 
 # install_python_stack.py
 _STACK_PATH = PACKAGE_ROOT / "studio" / "install_python_stack.py"
-_STACK_SPEC = importlib.util.spec_from_file_location(
-    "studio_install_python_stack", _STACK_PATH
-)
+_STACK_SPEC = importlib.util.spec_from_file_location("studio_install_python_stack", _STACK_PATH)
 assert _STACK_SPEC is not None and _STACK_SPEC.loader is not None
 stack_mod = importlib.util.module_from_spec(_STACK_SPEC)
 sys.modules[_STACK_SPEC.name] = stack_mod
@@ -304,9 +302,7 @@ class TestResolveUpstreamAssetChoice:
     def test_rocm_linux_no_prebuilt_falls_back(self, mock_assets):
         """AMD ROCm host should fall back to source build when no ROCm prebuilt exists."""
         # Remove the ROCm asset from available assets
-        assets_without_rocm = {
-            k: v for k, v in UPSTREAM_ASSETS.items() if "rocm" not in k
-        }
+        assets_without_rocm = {k: v for k, v in UPSTREAM_ASSETS.items() if "rocm" not in k}
         mock_assets.return_value = assets_without_rocm
         host = rocm_host()
         with pytest.raises(PrebuiltFallback, match = "ROCm detected"):
@@ -573,9 +569,7 @@ class TestEnsureRocmTorch:
     @patch.object(stack_mod, "_has_usable_nvidia_gpu", return_value = False)
     @patch.object(stack_mod, "_has_rocm_gpu", return_value = True)
     @patch.object(stack_mod, "_detect_rocm_version", return_value = (7, 1))
-    def test_torch_already_has_cuda_skips(
-        self, mock_ver, mock_gpu, mock_nvidia, mock_pip
-    ):
+    def test_torch_already_has_cuda_skips(self, mock_ver, mock_gpu, mock_nvidia, mock_pip):
         """If torch already has CUDA, should skip ROCm reinstall."""
         mock_probe = MagicMock()
         mock_probe.returncode = 0
@@ -589,9 +583,7 @@ class TestEnsureRocmTorch:
     @patch.object(stack_mod, "_has_usable_nvidia_gpu", return_value = False)
     @patch.object(stack_mod, "_has_rocm_gpu", return_value = True)
     @patch.object(stack_mod, "_detect_rocm_version", return_value = (7, 1))
-    def test_torch_already_has_hip_skips(
-        self, mock_ver, mock_gpu, mock_nvidia, mock_pip
-    ):
+    def test_torch_already_has_hip_skips(self, mock_ver, mock_gpu, mock_nvidia, mock_pip):
         """If torch already has HIP, should skip ROCm reinstall."""
         mock_probe = MagicMock()
         mock_probe.returncode = 0
@@ -629,9 +621,7 @@ class TestEnsureRocmTorch:
     @patch.object(stack_mod, "_has_usable_nvidia_gpu", return_value = False)
     @patch.object(stack_mod, "_has_rocm_gpu", return_value = True)
     @patch.object(stack_mod, "_detect_rocm_version", return_value = (6, 3))
-    def test_rocm_63_selects_correct_tag(
-        self, mock_ver, mock_gpu, mock_nvidia, mock_pip
-    ):
+    def test_rocm_63_selects_correct_tag(self, mock_ver, mock_gpu, mock_nvidia, mock_pip):
         """ROCm 6.3 should select rocm6.3 tag."""
         mock_probe = MagicMock()
         mock_probe.returncode = 0
@@ -698,9 +688,7 @@ class TestEnsureRocmTorch:
     ):
         """Probe subprocess timeout should not crash; should proceed to reinstall."""
         with patch("os.path.isdir", return_value = True):
-            with patch(
-                "subprocess.run", side_effect = subprocess.TimeoutExpired("python", 30)
-            ):
+            with patch("subprocess.run", side_effect = subprocess.TimeoutExpired("python", 30)):
                 _ensure_rocm_torch()
         # If probe times out, the function should treat torch as unusable and reinstall
         # both torch (via pip_install) and bitsandbytes (via pip_install_try).
@@ -788,25 +776,19 @@ class TestHardwareRocmFlag:
 
     def test_hardware_py_has_is_rocm(self):
         """hardware.py should define IS_ROCM."""
-        hw_path = (
-            PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
-        )
+        hw_path = PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
         source = hw_path.read_text(encoding = "utf-8")
         assert "IS_ROCM: bool" in source and "False" in source
 
     def test_hardware_py_sets_is_rocm_on_hip(self):
         """detect_hardware() should set IS_ROCM when torch.version.hip is set."""
-        hw_path = (
-            PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
-        )
+        hw_path = PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
         source = hw_path.read_text(encoding = "utf-8")
         assert 'torch.version, "hip"' in source or "torch.version.hip" in source
 
     def test_hardware_py_still_returns_cuda_for_rocm(self):
         """DeviceType should remain CUDA even on ROCm -- no DeviceType.ROCM."""
-        hw_path = (
-            PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
-        )
+        hw_path = PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
         source = hw_path.read_text(encoding = "utf-8")
         # Ensure ROCM is NOT a DeviceType member
         enum_section = source.split("class DeviceType")[1].split("\n\n")[0]
@@ -814,17 +796,13 @@ class TestHardwareRocmFlag:
 
     def test_hardware_py_has_rocm_in_package_versions(self):
         """get_package_versions() should include 'rocm' key."""
-        hw_path = (
-            PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
-        )
+        hw_path = PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
         source = hw_path.read_text(encoding = "utf-8")
         assert '"rocm"' in source
 
     def test_hardware_py_device_type_cuda_references_intact(self):
         """All existing DeviceType.CUDA references should still be present."""
-        hw_path = (
-            PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
-        )
+        hw_path = PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
         source = hw_path.read_text(encoding = "utf-8")
         # Key functions that must still reference DeviceType.CUDA
         assert "DeviceType.CUDA" in source
@@ -832,26 +810,20 @@ class TestHardwareRocmFlag:
 
     def test_is_rocm_exported_from_init(self):
         """IS_ROCM should be exported from hardware __init__.py."""
-        init_path = (
-            PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "__init__.py"
-        )
+        init_path = PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "__init__.py"
         source = init_path.read_text(encoding = "utf-8")
         assert "IS_ROCM" in source
 
     def test_is_rocm_in_all_list(self):
         """IS_ROCM should be in __all__ list in __init__.py."""
-        init_path = (
-            PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "__init__.py"
-        )
+        init_path = PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "__init__.py"
         source = init_path.read_text(encoding = "utf-8")
         # Extract __all__ section
         assert '"IS_ROCM"' in source
 
     def test_get_package_versions_returns_rocm_key(self):
         """get_package_versions() source should return both 'cuda' and 'rocm' keys."""
-        hw_path = (
-            PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
-        )
+        hw_path = PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
         source = hw_path.read_text(encoding = "utf-8")
         # Find the get_package_versions function body
         func_start = source.find("def get_package_versions")
@@ -866,22 +838,16 @@ class TestHardwareRocmFlag:
         Windows ROCm where torch.distributed ships without that helper, causing
         a warning: 'module torch.distributed has no attribute is_torchelastic_launched'.
         """
-        hw_path = (
-            PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
-        )
+        hw_path = PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
         source = hw_path.read_text(encoding = "utf-8")
         assert "is_torchelastic_launched" in source
 
     def test_distributed_stubs_cover_core_helpers(self):
         """_determine_attention_impl_for_gpu_estimate must stub the four core distributed helpers."""
-        hw_path = (
-            PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
-        )
+        hw_path = PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
         source = hw_path.read_text(encoding = "utf-8")
         for attr in ("is_initialized", "is_available", "get_rank", "get_world_size"):
-            assert (
-                attr in source
-            ), f"distributed stub for '{attr}' missing from hardware.py"
+            assert attr in source, f"distributed stub for '{attr}' missing from hardware.py"
 
 
 # =============================================================================
@@ -947,12 +913,8 @@ class TestInstallShStructure:
         nvidia_call = body.find("_has_usable_nvidia_gpu")
         no_nvidia_branch = body.find('if [ -z "$_smi" ]')
         rocm_call = body.find("_has_amd_rocm_gpu")
-        assert (
-            nvidia_call >= 0
-        ), "get_torch_index_url should call _has_usable_nvidia_gpu"
-        assert (
-            no_nvidia_branch >= 0
-        ), "get_torch_index_url should gate ROCm on no-nvidia-smi"
+        assert nvidia_call >= 0, "get_torch_index_url should call _has_usable_nvidia_gpu"
+        assert no_nvidia_branch >= 0, "get_torch_index_url should gate ROCm on no-nvidia-smi"
         assert (
             rocm_call > no_nvidia_branch
         ), "ROCm detection should sit inside the 'no nvidia-smi' branch"
@@ -1013,9 +975,7 @@ class TestInstallShStructure:
                 continue
             # Remove POSIX character classes [[:foo:]] before checking for [[ ]]
             cleaned = re.sub(r"\[\[:[a-z]+:\]\]", "", line)
-            assert (
-                "[[" not in cleaned
-            ), f"get_torch_index_url line {i} uses non-POSIX [["
+            assert "[[" not in cleaned, f"get_torch_index_url line {i} uses non-POSIX [["
 
     def test_no_arithmetic_expansion_in_rocm_block(self):
         """ROCm detection block should not use (( )) (bash-only)."""
@@ -1063,8 +1023,7 @@ class TestLiveRegression:
             [
                 "bash",
                 "-c",
-                "nvidia-smi -L 2>/dev/null | "
-                "awk '/^GPU[[:space:]]+[0-9]+:/{f=1} END{exit !f}'",
+                "nvidia-smi -L 2>/dev/null | awk '/^GPU[[:space:]]+[0-9]+:/{f=1} END{exit !f}'",
             ],
             capture_output = True,
         )
@@ -1098,9 +1057,7 @@ class TestLiveRegression:
 
 # Load worker.py module
 _WORKER_PATH = PACKAGE_ROOT / "studio" / "backend" / "core" / "training" / "worker.py"
-_EXPORT_WORKER_PATH = (
-    PACKAGE_ROOT / "studio" / "backend" / "core" / "export" / "worker.py"
-)
+_EXPORT_WORKER_PATH = PACKAGE_ROOT / "studio" / "backend" / "core" / "export" / "worker.py"
 # The torchao Windows-ROCm stub was de-duplicated out of the export/training
 # workers into a shared module; both workers now call into it.
 _TORCHAO_STUB_PATH = PACKAGE_ROOT / "studio" / "backend" / "core" / "_torchao_stub.py"
@@ -1126,9 +1083,7 @@ class TestWorkerRocmMambaSsm:
     def test_direct_wheel_url_returns_none_without_cuda_major(self, monkeypatch):
         """_direct_wheel_url should return None when cuda_major is empty (ROCm)."""
         # Load module for function access
-        _worker_spec = importlib.util.spec_from_file_location(
-            "test_worker", _WORKER_PATH
-        )
+        _worker_spec = importlib.util.spec_from_file_location("test_worker", _WORKER_PATH)
         assert _worker_spec is not None and _worker_spec.loader is not None
         worker_mod = importlib.util.module_from_spec(_worker_spec)
 
@@ -1347,9 +1302,7 @@ class TestHardwareAmdBranching:
 
     def test_hardware_imports_amd_module(self):
         """hardware.py should import from amd module when IS_ROCM."""
-        hw_path = (
-            PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
-        )
+        hw_path = PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
         source = hw_path.read_text(encoding = "utf-8")
         assert "from . import amd" in source
 
@@ -1357,17 +1310,13 @@ class TestHardwareAmdBranching:
         """get_gpu_utilization should dispatch to amd.py via _smi_query
         when IS_ROCM, and the dispatcher itself must check IS_ROCM and
         import the amd backend."""
-        hw_path = (
-            PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
-        )
+        hw_path = PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
         source = hw_path.read_text(encoding = "utf-8")
         func_start = source.find("def get_gpu_utilization")
         func_body = source[func_start : source.find("\ndef ", func_start + 1)]
         assert '_smi_query("get_primary_gpu_utilization"' in func_body
         smi = source[
-            source.find("def _smi_query") : source.find(
-                "\ndef ", source.find("def _smi_query") + 1
-            )
+            source.find("def _smi_query") : source.find("\ndef ", source.find("def _smi_query") + 1)
         ]
         assert "IS_ROCM" in smi
         assert "from . import amd" in smi
@@ -1375,9 +1324,7 @@ class TestHardwareAmdBranching:
     def test_hardware_branches_on_is_rocm_for_visible(self):
         """get_visible_gpu_utilization should dispatch to amd.py via
         _smi_query when IS_ROCM."""
-        hw_path = (
-            PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
-        )
+        hw_path = PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
         source = hw_path.read_text(encoding = "utf-8")
         func_start = source.find("def get_visible_gpu_utilization")
         func_body = source[func_start : source.find("\ndef ", func_start + 1)]
@@ -1387,18 +1334,14 @@ class TestHardwareAmdBranching:
 
         assert _re.search(r'_smi_query\(\s*"get_visible_gpu_utilization"', func_body)
         smi = source[
-            source.find("def _smi_query") : source.find(
-                "\ndef ", source.find("def _smi_query") + 1
-            )
+            source.find("def _smi_query") : source.find("\ndef ", source.find("def _smi_query") + 1)
         ]
         assert "IS_ROCM" in smi
         assert "from . import amd" in smi
 
     def test_hardware_branches_on_is_rocm_for_physical_count(self):
         """get_physical_gpu_count should try amd.py when IS_ROCM."""
-        hw_path = (
-            PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
-        )
+        hw_path = PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
         source = hw_path.read_text(encoding = "utf-8")
         func_start = source.find("def get_physical_gpu_count")
         func_body = source[func_start : source.find("\ndef ", func_start + 1)]
@@ -1417,9 +1360,7 @@ class TestApplyGpuIdsRocmFallback:
 
     def test_apply_gpu_ids_falls_back_to_torch_version_hip(self):
         """apply_gpu_ids should probe torch.version.hip when IS_ROCM is False and no ROCm env vars are set."""
-        hw_path = (
-            PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
-        )
+        hw_path = PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
         source = hw_path.read_text(encoding = "utf-8")
         func_start = source.find("def apply_gpu_ids")
         func_body = source[func_start : source.find("\ndef ", func_start + 1)]
@@ -1427,9 +1368,7 @@ class TestApplyGpuIdsRocmFallback:
 
     def test_apply_gpu_ids_sets_hip_and_rocr_visible_devices(self):
         """apply_gpu_ids should set both HIP_VISIBLE_DEVICES and ROCR_VISIBLE_DEVICES on ROCm."""
-        hw_path = (
-            PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
-        )
+        hw_path = PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
         source = hw_path.read_text(encoding = "utf-8")
         func_start = source.find("def apply_gpu_ids")
         func_body = source[func_start : source.find("\ndef ", func_start + 1)]
@@ -1438,9 +1377,7 @@ class TestApplyGpuIdsRocmFallback:
 
     def test_apply_gpu_ids_rocm_fallback_is_guarded_by_try_except(self):
         """torch import in apply_gpu_ids must be wrapped in try/except so a missing torch never crashes."""
-        hw_path = (
-            PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
-        )
+        hw_path = PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
         source = hw_path.read_text(encoding = "utf-8")
         func_start = source.find("def apply_gpu_ids")
         func_body = source[func_start : source.find("\ndef ", func_start + 1)]
@@ -1591,9 +1528,7 @@ class TestWindowsRocmIndexUrl:
         assert "repo.amd.com" in url
 
     def test_mirror_env_var_overrides_base(self, monkeypatch):
-        monkeypatch.setenv(
-            "UNSLOTH_ROCM_WINDOWS_MIRROR", "https://my-mirror.example.com/rocm/whl"
-        )
+        monkeypatch.setenv("UNSLOTH_ROCM_WINDOWS_MIRROR", "https://my-mirror.example.com/rocm/whl")
         # Reload module-level constant by calling helper directly
         url = stack_mod._windows_rocm_index_url("gfx1200")
         # The env var is read at module load time for _ROCM_WINDOWS_INDEX_BASE,
@@ -1722,9 +1657,7 @@ class TestInstallBnbWindowsRocm:
         with patch.dict(os.environ, {}, clear = False):
             os.environ.pop("BNB_ROCM_VERSION", None)
             with patch.object(stack_mod, "pip_install_try", return_value = True):
-                with patch.object(
-                    stack_mod, "_detect_bnb_rocm_dll_ver", return_value = "72"
-                ):
+                with patch.object(stack_mod, "_detect_bnb_rocm_dll_ver", return_value = "72"):
                     stack_mod._install_bnb_windows_rocm()
             assert os.environ.get("BNB_ROCM_VERSION") == "72"
 
@@ -1733,9 +1666,7 @@ class TestInstallBnbWindowsRocm:
         with patch.dict(os.environ, {}, clear = False):
             os.environ.pop("BNB_ROCM_VERSION", None)
             with patch.object(stack_mod, "pip_install_try", return_value = True):
-                with patch.object(
-                    stack_mod, "_detect_bnb_rocm_dll_ver", return_value = "713"
-                ):
+                with patch.object(stack_mod, "_detect_bnb_rocm_dll_ver", return_value = "713"):
                     stack_mod._install_bnb_windows_rocm()
             assert os.environ.get("BNB_ROCM_VERSION") == "713"
 
@@ -1744,9 +1675,7 @@ class TestInstallBnbWindowsRocm:
         with patch.dict(os.environ, {}, clear = False):
             os.environ.pop("BNB_ROCM_VERSION", None)
             with patch.object(stack_mod, "pip_install_try", return_value = True):
-                with patch.object(
-                    stack_mod, "_detect_bnb_rocm_dll_ver", return_value = None
-                ):
+                with patch.object(stack_mod, "_detect_bnb_rocm_dll_ver", return_value = None):
                     stack_mod._install_bnb_windows_rocm()
             assert os.environ.get("BNB_ROCM_VERSION") == "72"
 
@@ -1764,7 +1693,6 @@ class TestDetectBnbRocmDllVer:
     def test_returns_none_when_bnb_not_installed(self):
         """Returns None if bitsandbytes is not importable."""
         import importlib.util
-
         with patch.object(importlib.util, "find_spec", return_value = None):
             assert stack_mod._detect_bnb_rocm_dll_ver() is None
 
@@ -1973,9 +1901,7 @@ class TestWorkerWindowsRocmPatches:
         # entry-point function (not the trainer helper which has its own "# ── 2.").
         idx_sec2 = source.find("# ── 2. Now import ML libraries")
         assert idx_bnb != -1, "BNB_ROCM_VERSION not found in worker.py"
-        assert (
-            idx_sec2 != -1
-        ), "'# ── 2. Now import ML libraries' marker not found in worker.py"
+        assert idx_sec2 != -1, "'# ── 2. Now import ML libraries' marker not found in worker.py"
         assert idx_bnb < idx_sec2, (
             "BNB_ROCM_VERSION must be set before section 2 ML imports "
             f"(found at {idx_bnb}, section 2 at {idx_sec2})"
@@ -2269,16 +2195,12 @@ class TestHipSdkEnvPathResolution:
         """setup.ps1 must tell the user how to add the HIP bin dir to PATH."""
         source = _SETUP_PS1_PATH.read_text(encoding = "utf-8")
         # Should mention adding to PATH or SetEnvironmentVariable
-        assert "PATH" in source and (
-            "SetEnvironmentVariable" in source or "Add" in source
-        )
+        assert "PATH" in source and ("SetEnvironmentVariable" in source or "Add" in source)
 
     def test_install_provides_path_fix_hint(self):
         """install.ps1 must tell the user how to add the HIP bin dir to PATH."""
         source = _INSTALL_PS1_PATH.read_text(encoding = "utf-8")
-        assert "PATH" in source and (
-            "SetEnvironmentVariable" in source or "Add" in source
-        )
+        assert "PATH" in source and ("SetEnvironmentVariable" in source or "Add" in source)
 
 
 # =============================================================================
@@ -2448,9 +2370,7 @@ class TestSetupShGccInstallDir:
 # =============================================================================
 
 _MAIN_PY_PATH = PACKAGE_ROOT / "studio" / "backend" / "main.py"
-_HARDWARE_PY_PATH = (
-    PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
-)
+_HARDWARE_PY_PATH = PACKAGE_ROOT / "studio" / "backend" / "utils" / "hardware" / "hardware.py"
 
 
 class TestServerStartupRocmFixes:
@@ -2664,9 +2584,7 @@ class TestApplyHostOverrides:
         assert out.rocm_gfx_target is None
 
     def test_malformed_forwarded_gfx_falls_back_to_has_rocm(self):
-        out = _apply_host_overrides(
-            cpu_host(), override_has_rocm = True, override_rocm_gfx = "junk"
-        )
+        out = _apply_host_overrides(cpu_host(), override_has_rocm = True, override_rocm_gfx = "junk")
         assert out.has_rocm is True
         assert out.rocm_gfx_target is None
 
diff --git a/tests/studio/install/test_selection_logic.py b/tests/studio/install/test_selection_logic.py
index f1c3130a77..1ada35888c 100644
--- a/tests/studio/install/test_selection_logic.py
+++ b/tests/studio/install/test_selection_logic.py
@@ -22,9 +22,7 @@ import pytest
 PACKAGE_ROOT = Path(__file__).resolve().parents[3]
 MODULE_PATH = PACKAGE_ROOT / "studio" / "install_llama_prebuilt.py"
 RUN_MODULE_PATH = PACKAGE_ROOT / "studio" / "backend" / "run.py"
-SPEC = importlib.util.spec_from_file_location(
-    "studio_install_llama_prebuilt", MODULE_PATH
-)
+SPEC = importlib.util.spec_from_file_location("studio_install_llama_prebuilt", MODULE_PATH)
 assert SPEC is not None and SPEC.loader is not None
 INSTALL_LLAMA_PREBUILT = importlib.util.module_from_spec(SPEC)
 sys.modules[SPEC.name] = INSTALL_LLAMA_PREBUILT
@@ -49,15 +47,11 @@ supports_explicit_visible_device_matching = (
 select_visible_gpu_rows = INSTALL_LLAMA_PREBUILT.select_visible_gpu_rows
 compatible_linux_runtime_lines = INSTALL_LLAMA_PREBUILT.compatible_linux_runtime_lines
 pick_windows_cuda_runtime = INSTALL_LLAMA_PREBUILT.pick_windows_cuda_runtime
-compatible_windows_runtime_lines = (
-    INSTALL_LLAMA_PREBUILT.compatible_windows_runtime_lines
-)
+compatible_windows_runtime_lines = INSTALL_LLAMA_PREBUILT.compatible_windows_runtime_lines
 runtime_line_from_cuda_version = INSTALL_LLAMA_PREBUILT.runtime_line_from_cuda_version
 apply_approved_hashes = INSTALL_LLAMA_PREBUILT.apply_approved_hashes
 linux_cuda_choice_from_release = INSTALL_LLAMA_PREBUILT.linux_cuda_choice_from_release
-parse_direct_linux_release_bundle = (
-    INSTALL_LLAMA_PREBUILT.parse_direct_linux_release_bundle
-)
+parse_direct_linux_release_bundle = INSTALL_LLAMA_PREBUILT.parse_direct_linux_release_bundle
 windows_cuda_attempts = INSTALL_LLAMA_PREBUILT.windows_cuda_attempts
 resolve_upstream_asset_choice = INSTALL_LLAMA_PREBUILT.resolve_upstream_asset_choice
 resolve_requested_install_tag = INSTALL_LLAMA_PREBUILT.resolve_requested_install_tag
@@ -66,19 +60,11 @@ resolve_install_release_plans = INSTALL_LLAMA_PREBUILT.resolve_install_release_p
 resolve_published_release = INSTALL_LLAMA_PREBUILT.resolve_published_release
 resolve_source_build_plan = INSTALL_LLAMA_PREBUILT.resolve_source_build_plan
 validated_checksums_for_bundle = INSTALL_LLAMA_PREBUILT.validated_checksums_for_bundle
-parse_approved_release_checksums = (
-    INSTALL_LLAMA_PREBUILT.parse_approved_release_checksums
-)
-published_release_matches_request = (
-    INSTALL_LLAMA_PREBUILT.published_release_matches_request
-)
-exact_source_archive_logical_name = (
-    INSTALL_LLAMA_PREBUILT.exact_source_archive_logical_name
-)
+parse_approved_release_checksums = INSTALL_LLAMA_PREBUILT.parse_approved_release_checksums
+published_release_matches_request = INSTALL_LLAMA_PREBUILT.published_release_matches_request
+exact_source_archive_logical_name = INSTALL_LLAMA_PREBUILT.exact_source_archive_logical_name
 source_archive_logical_name = INSTALL_LLAMA_PREBUILT.source_archive_logical_name
-windows_cuda_upstream_asset_names = (
-    INSTALL_LLAMA_PREBUILT.windows_cuda_upstream_asset_names
-)
+windows_cuda_upstream_asset_names = INSTALL_LLAMA_PREBUILT.windows_cuda_upstream_asset_names
 env_int = INSTALL_LLAMA_PREBUILT.env_int
 direct_upstream_release_plan = INSTALL_LLAMA_PREBUILT.direct_upstream_release_plan
 _pinned_windows_cuda_fallback = INSTALL_LLAMA_PREBUILT._pinned_windows_cuda_fallback
@@ -89,9 +75,7 @@ _windows_cuda_attempt_covers_blackwell = (
 )
 resolve_release_asset_choice = INSTALL_LLAMA_PREBUILT.resolve_release_asset_choice
 pinned_macos_release_tag = INSTALL_LLAMA_PREBUILT.pinned_macos_release_tag
-resolve_simple_install_release_plans = (
-    INSTALL_LLAMA_PREBUILT.resolve_simple_install_release_plans
-)
+resolve_simple_install_release_plans = INSTALL_LLAMA_PREBUILT.resolve_simple_install_release_plans
 
 
 def load_studio_run_module(monkeypatch):
@@ -244,9 +228,7 @@ def make_checksums_with_source(
             kind = "upstream-source",
         ),
     }
-    normalized_source_commit = (
-        source_commit.lower() if isinstance(source_commit, str) else None
-    )
+    normalized_source_commit = source_commit.lower() if isinstance(source_commit, str) else None
     if normalized_source_commit:
         artifacts[exact_source_archive_logical_name(normalized_source_commit)] = (
             ApprovedArtifactHash(
@@ -266,9 +248,7 @@ def make_checksums_with_source(
         requested_source_ref = requested_source_ref,
         resolved_source_ref = resolved_source_ref,
         source_commit = normalized_source_commit,
-        source_commit_short = normalized_source_commit[:7]
-        if normalized_source_commit
-        else None,
+        source_commit_short = normalized_source_commit[:7] if normalized_source_commit else None,
         artifacts = artifacts,
     )
 
@@ -363,10 +343,7 @@ class TestStudioLocalhostIpv6Warning:
             lambda host, port, timeout = 1.0: True,
         )
 
-        assert (
-            run_module._localhost_ipv6_mismatch_url("127.0.0.1", 8888)
-            == "http://127.0.0.1:8888"
-        )
+        assert run_module._localhost_ipv6_mismatch_url("127.0.0.1", 8888) == "http://127.0.0.1:8888"
 
     @pytest.mark.parametrize("host", ["0.0.0.0", "::"])
     def test_network_bind_suppresses_warning(self, monkeypatch, host):
@@ -431,9 +408,7 @@ class TestStudioLocalhostIpv6Warning:
         monkeypatch.setattr(
             run_module,
             "_verify_global_reachability",
-            lambda display_host, port: calls["reachability"].append(
-                (display_host, port)
-            ),
+            lambda display_host, port: calls["reachability"].append((display_host, port)),
         )
         return calls
 
@@ -456,9 +431,7 @@ class TestStudioLocalhostIpv6Warning:
     def test_emit_startup_output_plain_localhost(self, monkeypatch):
         run_module = load_studio_run_module(monkeypatch)
         calls = self._wire_recorders(run_module, monkeypatch)
-        monkeypatch.setattr(
-            run_module, "_localhost_ipv6_mismatch_url", lambda host, port: None
-        )
+        monkeypatch.setattr(run_module, "_localhost_ipv6_mismatch_url", lambda host, port: None)
 
         run_module._emit_startup_output("127.0.0.1", 8888, "127.0.0.1")
 
@@ -471,9 +444,7 @@ class TestStudioLocalhostIpv6Warning:
     def test_emit_startup_output_wildcard_runs_reachability(self, monkeypatch, host):
         run_module = load_studio_run_module(monkeypatch)
         calls = self._wire_recorders(run_module, monkeypatch)
-        monkeypatch.setattr(
-            run_module, "_localhost_ipv6_mismatch_url", lambda h, port: None
-        )
+        monkeypatch.setattr(run_module, "_localhost_ipv6_mismatch_url", lambda h, port: None)
 
         run_module._emit_startup_output(host, 8888, "203.0.113.5")
 
@@ -651,9 +622,7 @@ class TestParseDirectLinuxReleaseBundle:
         names = [f"app-bTEST-linux-x64-{t}.tar.gz" for t in targets]
         return {
             "tag_name": "bTEST",
-            "assets": [
-                {"name": n, "browser_download_url": "https://x/" + n} for n in names
-            ],
+            "assets": [{"name": n, "browser_download_url": "https://x/" + n} for n in names],
         }
 
     def _cuda_artifact(self, bundle):
@@ -885,9 +854,7 @@ class TestPublishedReleaseResolution:
         def fake_load(repo, release_tag):
             if release_tag == "v2.0":
                 raise PrebuiltFallback("checksum asset missing")
-            return make_checksums_with_source(
-                [], release_tag = "v1.0", upstream_tag = "b8999"
-            )
+            return make_checksums_with_source([], release_tag = "v1.0", upstream_tag = "b8999")
 
         monkeypatch.setattr(
             INSTALL_LLAMA_PREBUILT,
@@ -917,9 +884,7 @@ class TestPublishedReleaseResolution:
             ),
         )
 
-        assert (
-            resolve_requested_install_tag("b8508", "", "unslothai/llama.cpp") == "b8508"
-        )
+        assert resolve_requested_install_tag("b8508", "", "unslothai/llama.cpp") == "b8508"
 
     def test_concrete_tag_without_matching_release_raises(self, monkeypatch):
         release = make_release([], release_tag = "release-b9000", upstream_tag = "b9000")
@@ -933,9 +898,7 @@ class TestPublishedReleaseResolution:
             resolve_requested_install_tag("b8508", "", "unslothai/llama.cpp")
 
     def test_pinned_release_must_match_requested_upstream_tag(self, monkeypatch):
-        bundle = make_release(
-            [], release_tag = "llama-prebuilt-latest", upstream_tag = "b9000"
-        )
+        bundle = make_release([], release_tag = "llama-prebuilt-latest", upstream_tag = "b9000")
         monkeypatch.setattr(
             INSTALL_LLAMA_PREBUILT,
             "pinned_published_release_bundle",
@@ -1110,15 +1073,13 @@ class TestSourceBuildPlanResolution:
         assert plan.source_ref == "main"
         assert plan.compatibility_upstream_tag == "b9000"
 
-    def test_direct_main_request_without_published_release_uses_branch_kind(
-        self, monkeypatch
-    ):
+    def test_direct_main_request_without_published_release_uses_branch_kind(self, monkeypatch):
         monkeypatch.setattr(
             INSTALL_LLAMA_PREBUILT,
             "resolve_published_release",
-            lambda requested_tag, published_repo, published_release_tag = "": (
-                _ for _ in ()
-            ).throw(PrebuiltFallback("missing")),
+            lambda requested_tag, published_repo, published_release_tag = "": (_ for _ in ()).throw(
+                PrebuiltFallback("missing")
+            ),
         )
 
         plan = resolve_source_build_plan("main", "unslothai/llama.cpp")
@@ -1193,9 +1154,7 @@ class TestValidatedChecksumsForBundle:
     def test_rejects_manifest_checksum_mismatch(self, monkeypatch):
         bundle = make_release([], release_tag = "r1", upstream_tag = "b8508")
         bundle.manifest_sha256 = "a" * 64
-        checksums = make_checksums_with_source(
-            [], release_tag = "r1", upstream_tag = "b8508"
-        )
+        checksums = make_checksums_with_source([], release_tag = "r1", upstream_tag = "b8508")
         checksums.artifacts[bundle.manifest_asset_name] = ApprovedArtifactHash(
             asset_name = bundle.manifest_asset_name,
             sha256 = "b" * 64,
@@ -1249,9 +1208,7 @@ class TestLinuxCudaChoiceFromRelease:
         art12 = make_artifact("bundle-cuda12.tar.gz", runtime_line = "cuda12")
         art13 = make_artifact("bundle-cuda13.tar.gz", runtime_line = "cuda13")
         release = make_release([art12, art13])
-        result = linux_cuda_choice_from_release(
-            host, release, preferred_runtime_line = "cuda12"
-        )
+        result = linux_cuda_choice_from_release(host, release, preferred_runtime_line = "cuda12")
         assert result is not None
         assert result.primary.runtime_line == "cuda12"
 
@@ -1260,9 +1217,7 @@ class TestLinuxCudaChoiceFromRelease:
         host = make_host(driver_cuda_version = (12, 8))
         art = make_artifact("bundle-cuda12.tar.gz", runtime_line = "cuda12")
         release = make_release([art])
-        result = linux_cuda_choice_from_release(
-            host, release, preferred_runtime_line = "cuda13"
-        )
+        result = linux_cuda_choice_from_release(host, release, preferred_runtime_line = "cuda13")
         assert result is not None
         assert result.primary.runtime_line == "cuda12"
         log_entries = result.selection_log
@@ -1273,9 +1228,7 @@ class TestLinuxCudaChoiceFromRelease:
     def test_exact_sm_match(self, monkeypatch):
         mock_linux_runtime(monkeypatch, ["cuda12"])
         host = make_host(compute_caps = ["86"])
-        art = make_artifact(
-            "bundle.tar.gz", supported_sms = ["75", "86", "89"], min_sm = 75, max_sm = 89
-        )
+        art = make_artifact("bundle.tar.gz", supported_sms = ["75", "86", "89"], min_sm = 75, max_sm = 89)
         release = make_release([art])
         result = linux_cuda_choice_from_release(host, release)
         assert result is not None
@@ -1284,9 +1237,7 @@ class TestLinuxCudaChoiceFromRelease:
     def test_sm_not_in_supported_sms(self, monkeypatch):
         mock_linux_runtime(monkeypatch, ["cuda12"])
         host = make_host(compute_caps = ["86"])
-        art = make_artifact(
-            "bundle.tar.gz", supported_sms = ["75", "80", "89"], min_sm = 75, max_sm = 89
-        )
+        art = make_artifact("bundle.tar.gz", supported_sms = ["75", "80", "89"], min_sm = 75, max_sm = 89)
         release = make_release([art])
         result = linux_cuda_choice_from_release(host, release)
         assert result is None
@@ -1294,9 +1245,7 @@ class TestLinuxCudaChoiceFromRelease:
     def test_sm_outside_min_range(self, monkeypatch):
         mock_linux_runtime(monkeypatch, ["cuda12"])
         host = make_host(compute_caps = ["50"])
-        art = make_artifact(
-            "bundle.tar.gz", supported_sms = ["50", "75", "86"], min_sm = 75, max_sm = 90
-        )
+        art = make_artifact("bundle.tar.gz", supported_sms = ["50", "75", "86"], min_sm = 75, max_sm = 90)
         release = make_release([art])
         result = linux_cuda_choice_from_release(host, release)
         assert result is None
@@ -1365,9 +1314,7 @@ class TestLinuxCudaChoiceFromRelease:
     def test_multi_gpu_not_all_covered(self, monkeypatch):
         mock_linux_runtime(monkeypatch, ["cuda12"])
         host = make_host(compute_caps = ["50", "89"])
-        art = make_artifact(
-            "bundle.tar.gz", supported_sms = ["75", "89"], min_sm = 75, max_sm = 89
-        )
+        art = make_artifact("bundle.tar.gz", supported_sms = ["75", "89"], min_sm = 75, max_sm = 89)
         release = make_release([art])
         result = linux_cuda_choice_from_release(host, release)
         assert result is None
@@ -1559,9 +1506,7 @@ class TestBlackwellUltraSm103Coverage:
 
 
 class TestResolveInstallAttempts:
-    def test_windows_cuda_prefers_published_asset_from_selected_release(
-        self, monkeypatch
-    ):
+    def test_windows_cuda_prefers_published_asset_from_selected_release(self, monkeypatch):
         host = make_host(system = "Windows", machine = "AMD64")
         host.driver_cuda_version = (12, 4)
         mock_windows_runtime(monkeypatch, ["cuda12"])
@@ -1605,9 +1550,7 @@ class TestResolveInstallAttempts:
             INSTALL_LLAMA_PREBUILT,
             "github_release_assets",
             lambda repo, tag: (_ for _ in ()).throw(
-                AssertionError(
-                    "published Windows CUDA choice should not query upstream"
-                )
+                AssertionError("published Windows CUDA choice should not query upstream")
             ),
         )
 
@@ -1629,9 +1572,7 @@ class TestResolveInstallAttempts:
         host = make_host(system = "Windows", machine = "AMD64")
         host.driver_cuda_version = (12, 4)
         mock_windows_runtime(monkeypatch, ["cuda12"])
-        release = make_release(
-            [], release_tag = "llama-prebuilt-latest", upstream_tag = "b9000"
-        )
+        release = make_release([], release_tag = "llama-prebuilt-latest", upstream_tag = "b9000")
         checksums = make_checksums_with_source(
             ["llama-b9000-bin-win-cuda-12.4-x64.zip"],
             release_tag = release.release_tag,
@@ -1692,9 +1633,7 @@ class TestResolveInstallAttempts:
             has_physical_nvidia = False,
             nvidia_smi = None,
         )
-        release = make_release(
-            [], release_tag = "llama-prebuilt-latest", upstream_tag = "b9000"
-        )
+        release = make_release([], release_tag = "llama-prebuilt-latest", upstream_tag = "b9000")
         checksums = make_checksums_with_source(
             ["llama-b9000-bin-ubuntu-x64.tar.gz"],
             release_tag = release.release_tag,
@@ -1735,9 +1674,7 @@ class TestResolveInstallAttempts:
 
     def test_linux_cuda_does_not_fall_back_to_upstream_cpu(self, monkeypatch):
         host = make_host(system = "Linux", machine = "x86_64", compute_caps = ["86"])
-        release = make_release(
-            [], release_tag = "llama-prebuilt-latest", upstream_tag = "b9000"
-        )
+        release = make_release([], release_tag = "llama-prebuilt-latest", upstream_tag = "b9000")
         checksums = make_checksums_with_source(
             [],
             release_tag = release.release_tag,
@@ -1758,9 +1695,7 @@ class TestResolveInstallAttempts:
         )
         mock_linux_runtime(monkeypatch, ["cuda12"])
 
-        with pytest.raises(
-            PrebuiltFallback, match = "no compatible published Linux CUDA bundle"
-        ):
+        with pytest.raises(PrebuiltFallback, match = "no compatible published Linux CUDA bundle"):
             resolve_install_attempts("latest", host, "unslothai/llama.cpp", "")
 
     def test_windows_cpu_prefers_published_asset(self, monkeypatch):
@@ -1956,9 +1891,7 @@ class TestResolveInstallAttempts:
 
 
 class TestResolveInstallReleasePlans:
-    def test_latest_collects_multiple_older_release_plans_up_to_limit(
-        self, monkeypatch
-    ):
+    def test_latest_collects_multiple_older_release_plans_up_to_limit(self, monkeypatch):
         host = make_host(
             has_usable_nvidia = False,
             has_physical_nvidia = False,
@@ -1994,9 +1927,7 @@ class TestResolveInstallReleasePlans:
         monkeypatch.setattr(
             INSTALL_LLAMA_PREBUILT,
             "iter_resolved_published_releases",
-            lambda requested_tag, published_repo, published_release_tag = "": iter(
-                releases
-            ),
+            lambda requested_tag, published_repo, published_release_tag = "": iter(releases),
         )
         monkeypatch.setattr(
             INSTALL_LLAMA_PREBUILT,
@@ -2018,9 +1949,7 @@ class TestResolveInstallReleasePlans:
         assert [plan.release_tag for plan in plans] == ["r3", "r2"]
         assert [plan.llama_tag for plan in plans] == ["b9003", "b9002"]
 
-    def test_latest_skips_non_installable_release_and_keeps_searching(
-        self, monkeypatch
-    ):
+    def test_latest_skips_non_installable_release_and_keeps_searching(self, monkeypatch):
         host = make_host(
             has_usable_nvidia = False,
             has_physical_nvidia = False,
@@ -2048,9 +1977,7 @@ class TestResolveInstallReleasePlans:
         monkeypatch.setattr(
             INSTALL_LLAMA_PREBUILT,
             "iter_resolved_published_releases",
-            lambda requested_tag, published_repo, published_release_tag = "": iter(
-                releases
-            ),
+            lambda requested_tag, published_repo, published_release_tag = "": iter(releases),
         )
         monkeypatch.setattr(
             INSTALL_LLAMA_PREBUILT,
@@ -2078,13 +2005,9 @@ class TestResolveInstallReleasePlans:
 
     def test_malformed_release_fallback_env_uses_default(self, monkeypatch):
         monkeypatch.setenv("UNSLOTH_LLAMA_MAX_PREBUILT_RELEASE_FALLBACKS", "not-an-int")
-        assert (
-            env_int("UNSLOTH_LLAMA_MAX_PREBUILT_RELEASE_FALLBACKS", 3, minimum = 1) == 3
-        )
+        assert env_int("UNSLOTH_LLAMA_MAX_PREBUILT_RELEASE_FALLBACKS", 3, minimum = 1) == 3
 
-    def test_import_with_malformed_release_fallback_env_does_not_crash(
-        self, monkeypatch
-    ):
+    def test_import_with_malformed_release_fallback_env_does_not_crash(self, monkeypatch):
         monkeypatch.setenv("UNSLOTH_LLAMA_MAX_PREBUILT_RELEASE_FALLBACKS", "bad-value")
         spec = importlib.util.spec_from_file_location(
             "studio_install_llama_prebuilt_env_reload",
@@ -2108,7 +2031,11 @@ class TestResolveInstallReleasePlans:
 class TestWindowsCudaAttempts:
     TAG = "b8508"
 
-    def _upstream(self, *runtime_versions, current_names: bool = False):
+    def _upstream(
+        self,
+        *runtime_versions,
+        current_names: bool = False,
+    ):
         assets = {}
         for rv in runtime_versions:
             if current_names:
@@ -2350,23 +2277,14 @@ class TestPinnedBlackwellCudaFallback:
         assert pin.runtime_sha256 and len(pin.runtime_sha256) == 64
 
     def test_pin_offered_for_driver_13_2(self):
-        assert (
-            _pinned_windows_cuda_fallback(self._win_host((13, 2), ["120"]), [])
-            is not None
-        )
+        assert _pinned_windows_cuda_fallback(self._win_host((13, 2), ["120"]), []) is not None
 
     def test_pin_offered_for_sm121_variant(self):
         # sm_121 is Blackwell-family and also needs toolkit >= 12.8.
-        assert (
-            _pinned_windows_cuda_fallback(self._win_host((13, 1), ["121"]), [])
-            is not None
-        )
+        assert _pinned_windows_cuda_fallback(self._win_host((13, 1), ["121"]), []) is not None
 
     def test_pin_uses_max_of_multi_gpu_caps(self):
-        assert (
-            _pinned_windows_cuda_fallback(self._win_host((13, 1), ["86", "120"]), [])
-            is not None
-        )
+        assert _pinned_windows_cuda_fallback(self._win_host((13, 1), ["86", "120"]), []) is not None
 
     @pytest.mark.parametrize("sm", ["89", "90", "100"])
     def test_pin_not_offered_to_non_blackwell(self, sm):
@@ -2377,16 +2295,11 @@ class TestPinnedBlackwellCudaFallback:
         # b9360 is native sm_120a SASS (no JIT) and ships a cuda-13.1 cudart,
         # both of which run on a 13.0 r580+ driver via CUDA minor-version
         # compatibility. 13.0 is the mainstream Blackwell branch, so it must fire.
-        assert (
-            _pinned_windows_cuda_fallback(self._win_host((13, 0), ["120"]), [])
-            is not None
-        )
+        assert _pinned_windows_cuda_fallback(self._win_host((13, 0), ["120"]), []) is not None
 
     def test_pin_not_offered_below_floor(self):
         # 12.x predates Blackwell entirely; the pin stays dormant below 13.0.
-        assert (
-            _pinned_windows_cuda_fallback(self._win_host((12, 9), ["120"]), []) is None
-        )
+        assert _pinned_windows_cuda_fallback(self._win_host((12, 9), ["120"]), []) is None
 
     def test_pin_not_offered_without_driver(self):
         assert _pinned_windows_cuda_fallback(self._win_host(None, ["120"]), []) is None
@@ -2460,10 +2373,7 @@ class TestPinnedBlackwellCudaFallback:
         ],
     )
     def test_attempt_covers_blackwell(self, minor, covers):
-        assert (
-            _windows_cuda_attempt_covers_blackwell(self._win_cuda_attempt(minor))
-            is covers
-        )
+        assert _windows_cuda_attempt_covers_blackwell(self._win_cuda_attempt(minor)) is covers
 
     def test_attempt_covers_blackwell_ignores_non_cuda_kind(self):
         cpu = AssetChoice(
@@ -2500,8 +2410,7 @@ class TestDirectUpstreamBlackwellPin:
         return {
             "tag_name": self.TAG,
             "assets": [
-                {"name": n, "browser_download_url": f"https://example.com/{n}"}
-                for n in names
+                {"name": n, "browser_download_url": f"https://example.com/{n}"} for n in names
             ],
         }
 
@@ -2521,15 +2430,9 @@ class TestDirectUpstreamBlackwellPin:
             driver_cuda_version = (13, 1),
             compute_caps = ["120"],
         )
-        plan = direct_upstream_release_plan(
-            self._release(), host, UPSTREAM_REPO, "latest"
-        )
+        plan = direct_upstream_release_plan(self._release(), host, UPSTREAM_REPO, "latest")
         order = [(a.tag, a.runtime_line or a.install_kind) for a in plan.attempts]
-        assert order == [
-            ("b9360", "cuda13"),
-            (self.TAG, "cuda12"),
-            (self.TAG, "windows-cpu"),
-        ]
+        assert order == [("b9360", "cuda13"), (self.TAG, "cuda12"), (self.TAG, "windows-cpu")]
         assert plan.attempts[0].name == "llama-b9360-bin-win-cuda-13.1-x64.zip"
         # Direct/upstream path stays unverified-by-manifest (no approved hashes).
         assert plan.approved_checksums.artifacts == {}
@@ -2543,9 +2446,7 @@ class TestDirectUpstreamBlackwellPin:
             driver_cuda_version = (13, 3),
             compute_caps = ["120"],
         )
-        plan = direct_upstream_release_plan(
-            self._release(), host, UPSTREAM_REPO, "latest"
-        )
+        plan = direct_upstream_release_plan(self._release(), host, UPSTREAM_REPO, "latest")
         assert "b9360" not in [a.tag for a in plan.attempts]
         assert plan.attempts[0].tag == self.TAG
         assert plan.attempts[0].runtime_line == "cuda13"
@@ -2581,9 +2482,7 @@ class TestPublishedWindowsCudaAttemptsDynamicMajor:
         # the old hardcoded cuda12/cuda13 seed would never order it (the cuda14
         # line would be skipped for want of a 14.x asset in the seed).
         mock_windows_runtime(monkeypatch, ["cuda14", "cuda13", "cuda12"])
-        release = self._release(
-            [("14.0", "cuda14"), ("13.3", "cuda13"), ("12.4", "cuda12")]
-        )
+        release = self._release([("14.0", "cuda14"), ("13.3", "cuda13"), ("12.4", "cuda12")])
         host = make_host(
             system = "Windows",
             machine = "AMD64",
@@ -2809,18 +2708,14 @@ class TestResolveUpstreamAssetChoice:
     def test_linux_x86_64_cpu(self, monkeypatch):
         name = f"llama-{self.TAG}-bin-ubuntu-x64.tar.gz"
         self._mock_github_assets(monkeypatch, {name: f"https://x/{name}"})
-        host = make_host(
-            has_usable_nvidia = False, nvidia_smi = None, has_physical_nvidia = False
-        )
+        host = make_host(has_usable_nvidia = False, nvidia_smi = None, has_physical_nvidia = False)
         result = resolve_upstream_asset_choice(host, self.TAG)
         assert result.install_kind == "linux-cpu"
         assert result.name == name
 
     def test_linux_cpu_missing(self, monkeypatch):
         self._mock_github_assets(monkeypatch, {})
-        host = make_host(
-            has_usable_nvidia = False, nvidia_smi = None, has_physical_nvidia = False
-        )
+        host = make_host(has_usable_nvidia = False, nvidia_smi = None, has_physical_nvidia = False)
         with pytest.raises(PrebuiltFallback, match = "Linux CPU"):
             resolve_upstream_asset_choice(host, self.TAG)
 
@@ -2907,9 +2802,7 @@ class TestResolveUpstreamAssetChoice:
             has_physical_nvidia = False,
             has_usable_nvidia = False,
         )
-        with pytest.raises(
-            PrebuiltFallback, match = "no prebuilt policy exists for Linux aarch64"
-        ):
+        with pytest.raises(PrebuiltFallback, match = "no prebuilt policy exists for Linux aarch64"):
             resolve_upstream_asset_choice(host, self.TAG)
 
     def test_windows_usable_nvidia_delegates(self, monkeypatch):
@@ -3022,7 +2915,11 @@ class TestResolveSimpleMacosPin:
                 ],
             }
 
-        def fake_iter(repo, published_release_tag = "", requested_tag = ""):
+        def fake_iter(
+            repo,
+            published_release_tag = "",
+            requested_tag = "",
+        ):
             calls.append((repo, published_release_tag, requested_tag))
             # Emulate the real iterator: a specific tag yields only that release.
             if requested_tag and requested_tag != "latest":
@@ -3031,9 +2928,7 @@ class TestResolveSimpleMacosPin:
             for tag in self.TAGS:
                 yield _release(tag)
 
-        monkeypatch.setattr(
-            INSTALL_LLAMA_PREBUILT, "iter_release_payloads_by_time", fake_iter
-        )
+        monkeypatch.setattr(INSTALL_LLAMA_PREBUILT, "iter_release_payloads_by_time", fake_iter)
         return calls
 
     def test_pre26_host_pins_b9415_without_walkback(self, monkeypatch):
@@ -3081,14 +2976,10 @@ class TestLinuxArm64ForkFallsBackToSource:
         def _boom(*_a, **_k):
             raise AssertionError("iterator must not run for arm64 fork hosts")
 
-        monkeypatch.setattr(
-            INSTALL_LLAMA_PREBUILT, "iter_release_payloads_by_time", _boom
-        )
+        monkeypatch.setattr(INSTALL_LLAMA_PREBUILT, "iter_release_payloads_by_time", _boom)
         host = make_host(system = "Linux", machine = "aarch64")
         with pytest.raises(PrebuiltFallback, match = "linux-x64 prebuilts"):
-            resolve_simple_install_release_plans(
-                "latest", host, "unslothai/llama.cpp", ""
-            )
+            resolve_simple_install_release_plans("latest", host, "unslothai/llama.cpp", "")
 
     def test_x86_64_fork_is_not_blocked_by_the_arch_guard(self, monkeypatch):
         # x64 host must pass the guard and reach the iterator (here empty, so it
@@ -3100,9 +2991,7 @@ class TestLinuxArm64ForkFallsBackToSource:
         )
         host = make_host(system = "Linux", machine = "x86_64")
         with pytest.raises(PrebuiltFallback) as exc:
-            resolve_simple_install_release_plans(
-                "latest", host, "unslothai/llama.cpp", ""
-            )
+            resolve_simple_install_release_plans("latest", host, "unslothai/llama.cpp", "")
         assert "linux-x64 prebuilts" not in str(exc.value)
 
     def test_arm64_cpu_on_ggml_org_is_not_blocked(self, monkeypatch):
@@ -3123,9 +3012,7 @@ class TestLinuxArm64ForkFallsBackToSource:
             has_usable_nvidia = False,
         )
         with pytest.raises(PrebuiltFallback) as exc:
-            resolve_simple_install_release_plans(
-                "latest", host, "ggml-org/llama.cpp", ""
-            )
+            resolve_simple_install_release_plans("latest", host, "ggml-org/llama.cpp", "")
         assert "linux-x64 prebuilts" not in str(exc.value)
 
 
@@ -3212,9 +3099,7 @@ class TestCpuFallback:
             has_physical_nvidia = False,
             has_usable_nvidia = False,
         )
-        plan = direct_upstream_release_plan(
-            release, cpu_host, "ggml-org/llama.cpp", "latest"
-        )
+        plan = direct_upstream_release_plan(release, cpu_host, "ggml-org/llama.cpp", "latest")
         assert plan.attempts[0].install_kind == "linux-arm64"
         assert plan.attempts[0].name == f"llama-{tag}-bin-ubuntu-arm64.tar.gz"
 
diff --git a/tests/studio/load_freeze/llama_server_shim.py b/tests/studio/load_freeze/llama_server_shim.py
index 1166c7521d..bb9e119820 100644
--- a/tests/studio/load_freeze/llama_server_shim.py
+++ b/tests/studio/load_freeze/llama_server_shim.py
@@ -41,7 +41,11 @@ class _Handler(BaseHTTPRequestHandler):
         self.wfile.write(payload)
 
     def _send_raw(
-        self, status: int, body: bytes, *, content_type: str = "application/json"
+        self,
+        status: int,
+        body: bytes,
+        *,
+        content_type: str = "application/json",
     ) -> None:
         self.send_response(status)
         self.send_header("Content-Type", content_type)
@@ -119,9 +123,7 @@ class _Handler(BaseHTTPRequestHandler):
                 self._send_raw(srv.config.detok_status, srv.config.detok_body)
                 return
             tids = body.get("tokens") or []
-            content = "".join(
-                srv.config.detok_map.get(int(t), f"") for t in tids
-            )
+            content = "".join(srv.config.detok_map.get(int(t), f"") for t in tids)
             self._send_json(srv.config.detok_status, {"content": content})
             return
         if path == "/completion":
@@ -224,9 +226,7 @@ class FakeLlamaServer:
     def start(self) -> "FakeLlamaServer":
         # port=0 lets ThreadingHTTPServer pick a free port atomically
         # (avoids find-port-then-bind race); read back via server_address[1].
-        self._server = FakeLlamaServer._Server(
-            (self.host, self._requested_port), _Handler
-        )
+        self._server = FakeLlamaServer._Server((self.host, self._requested_port), _Handler)
         self._server.config = self.config
         bound_port = self._server.server_address[1]
         self._thread = threading.Thread(
diff --git a/tests/studio/load_freeze/test_load_orchestrator.py b/tests/studio/load_freeze/test_load_orchestrator.py
index 91b70f0b03..b76c4c361b 100644
--- a/tests/studio/load_freeze/test_load_orchestrator.py
+++ b/tests/studio/load_freeze/test_load_orchestrator.py
@@ -103,14 +103,18 @@ def _free_port() -> int:
 
 
 class _UvicornServerThread:
-    def __init__(self, app, *, host: str = "127.0.0.1", port: int) -> None:
+    def __init__(
+        self,
+        app,
+        *,
+        host: str = "127.0.0.1",
+        port: int,
+    ) -> None:
         import uvicorn
 
         self.host = host
         self.port = port
-        cfg = uvicorn.Config(
-            app, host = host, port = port, log_level = "warning", access_log = False
-        )
+        cfg = uvicorn.Config(app, host = host, port = port, log_level = "warning", access_log = False)
         self._server = uvicorn.Server(cfg)
         self._server.install_signal_handlers = lambda: None  # type: ignore[assignment]
         self._thread: threading.Thread | None = None
@@ -169,7 +173,12 @@ def _build_app(backend, *, wrap_in_thread: bool):
     return app
 
 
-def _drive_concurrent_probe_and_health(base_url, *, n_health = 12, gap = 0.05):
+def _drive_concurrent_probe_and_health(
+    base_url,
+    *,
+    n_health = 12,
+    gap = 0.05,
+):
     elapsed = -1.0
     latencies: list[float] = []
 
@@ -211,9 +220,7 @@ def test_buggy_route_blocks_event_loop():
         app = _build_app(backend, wrap_in_thread = False)
         port = _free_port()
         with _UvicornServerThread(app, port = port) as uv:
-            max_lat, probe_t, _ = _drive_concurrent_probe_and_health(
-                f"http://127.0.0.1:{uv.port}"
-            )
+            max_lat, probe_t, _ = _drive_concurrent_probe_and_health(f"http://127.0.0.1:{uv.port}")
     assert probe_t >= 0.5
     assert max_lat >= 0.4, f"expected >=0.4s stall, got {max_lat:.3f}s"
 
@@ -442,9 +449,7 @@ def test_50_concurrent_probes_complete_without_deadlock():
             with ThreadPoolExecutor(max_workers = 50) as pool:
                 futs = [
                     pool.submit(
-                        lambda: httpx.get(
-                            f"http://127.0.0.1:{uv.port}/probe", timeout = 30.0
-                        )
+                        lambda: httpx.get(f"http://127.0.0.1:{uv.port}/probe", timeout = 30.0)
                     )
                     for _ in range(50)
                 ]
@@ -660,7 +665,6 @@ def test_response_shape_matches_pre_fix_for_no_match():
     bodies for the no-match scenario (the dominant code path in
     practice for non-audio models)."""
     import json as _json
-
     with FakeLlamaServer(
         detok_map = {128258: "abc", 128259: "def"},
         tok_response_map = {
diff --git a/tests/studio/playwright_chat_ime_i18n.py b/tests/studio/playwright_chat_ime_i18n.py
index efcd048b44..828187d462 100644
--- a/tests/studio/playwright_chat_ime_i18n.py
+++ b/tests/studio/playwright_chat_ime_i18n.py
@@ -246,8 +246,7 @@ with sync_playwright() as p:
     dir_attr = composer.evaluate("(el) => el.getAttribute('dir')")
     if dir_attr != "auto":
         soft_fail(
-            f'composer is missing dir="auto" (got {dir_attr!r}); RTL '
-            "languages will render LTR."
+            f'composer is missing dir="auto" (got {dir_attr!r}); RTL ' "languages will render LTR."
         )
     else:
         info('composer dir="auto" present')
@@ -258,9 +257,7 @@ with sync_playwright() as p:
     _thread_src = (
         _repo_root / "studio/frontend/src/components/assistant-ui/thread.tsx"
     ).read_text()
-    _shared_src = (
-        _repo_root / "studio/frontend/src/features/chat/shared-composer.tsx"
-    ).read_text()
+    _shared_src = (_repo_root / "studio/frontend/src/features/chat/shared-composer.tsx").read_text()
     _edit_idx = _thread_src.find("aui-edit-composer-input")
     if _edit_idx == -1 or 'dir="auto"' not in _thread_src[_edit_idx : _edit_idx + 600]:
         soft_fail('edit composer source is missing dir="auto"')
@@ -269,8 +266,7 @@ with sync_playwright() as p:
     _compare_idx = _shared_src.find("Send to both models")
     if (
         _compare_idx == -1
-        or 'dir="auto"'
-        not in _shared_src[max(_compare_idx - 400, 0) : _compare_idx + 400]
+        or 'dir="auto"' not in _shared_src[max(_compare_idx - 400, 0) : _compare_idx + 400]
     ):
         soft_fail('compare composer source is missing dir="auto"')
     else:
@@ -484,9 +480,7 @@ with sync_playwright() as p:
     #     handleSubmit / blockSend guards keep refusing. The Send button stays
     #     visually enabled (watchdog has already cleared the React state); the
     #     refusal happens at form.requestSubmit() time, not at the button.
-    step(
-        "BUG REPRO: keydown re-pin after watchdog cleared composing (issue #5546 follow-up)"
-    )
+    step("BUG REPRO: keydown re-pin after watchdog cleared composing (issue #5546 follow-up)")
     clear()
     composer.click()
     composer.evaluate(
@@ -533,9 +527,7 @@ with sync_playwright() as p:
             "Form submitted after an IME keydown -- preedit text leaked "
             "through the watchdog gap (#5546 follow-up regression)."
         )
-    info(
-        f"Form submit refused after IME keydown; textarea retained {submit_probe.get('after')!r}"
-    )
+    info(f"Form submit refused after IME keydown; textarea retained {submit_probe.get('after')!r}")
     shoot("06c-keydown-repin")
     info("keydown re-pin gate PASS")
     clear()
diff --git a/tests/studio/playwright_chat_ui.py b/tests/studio/playwright_chat_ui.py
index b1279e64b9..dc62194be8 100644
--- a/tests/studio/playwright_chat_ui.py
+++ b/tests/studio/playwright_chat_ui.py
@@ -141,10 +141,7 @@ def expected_default_model():
     for node in tree.body:
         if not isinstance(node, ast.Assign):
             continue
-        if not any(
-            isinstance(t, ast.Name) and t.id == "DEFAULT_MODELS_GGUF"
-            for t in node.targets
-        ):
+        if not any(isinstance(t, ast.Name) and t.id == "DEFAULT_MODELS_GGUF" for t in node.targets):
             continue
         try:
             models = ast.literal_eval(node.value)
@@ -321,9 +318,7 @@ with sync_playwright() as p:
     form_err: Exception | None = None
     for _form_attempt in range(3):
         try:
-            page.goto(
-                f"{BASE}/change-password", wait_until = "domcontentloaded", timeout = 60_000
-            )
+            page.goto(f"{BASE}/change-password", wait_until = "domcontentloaded", timeout = 60_000)
             try:
                 page.wait_for_load_state("networkidle", timeout = 30_000)
             except Exception:
@@ -382,9 +377,7 @@ with sync_playwright() as p:
                     flush = True,
                 )
             if page_errors:
-                print(
-                    f"[ui]   first pageerror:    {page_errors[0][:200]!r}", flush = True
-                )
+                print(f"[ui]   first pageerror:    {page_errors[0][:200]!r}", flush = True)
             try:
                 shoot(f"01-change-password-attempt-{_form_attempt + 1}-fail")
             except Exception:
@@ -458,9 +451,7 @@ with sync_playwright() as p:
                     flush = True,
                 )
             if page_errors:
-                print(
-                    f"[ui]   first pageerror:    {page_errors[0][:200]!r}", flush = True
-                )
+                print(f"[ui]   first pageerror:    {page_errors[0][:200]!r}", flush = True)
             try:
                 shoot(f"03-composer-wait-attempt-{_attempt + 1}-fail")
             except Exception:
@@ -557,9 +548,7 @@ with sync_playwright() as p:
     try:
         sel_text = (selector_btn.text_content(timeout = 2_000) or "").strip()
     except Exception as _sel_err:
-        info(
-            f"WARN: model-selector probe skipped: {type(_sel_err).__name__}: {_sel_err}"
-        )
+        info(f"WARN: model-selector probe skipped: {type(_sel_err).__name__}: {_sel_err}")
     if sel_text:
         info(f"model selector button text: {sel_text!r}")
         shoot("03b-default-model-button")
@@ -595,10 +584,7 @@ with sync_playwright() as p:
     if load_resp.get("error"):
         fail(f"/api/inference/load wedged: {load_resp['error']!r}")
     if load_resp["status"] != 200:
-        fail(
-            f"/api/inference/load returned {load_resp['status']}: "
-            f"{load_resp.get('body')!r}"
-        )
+        fail(f"/api/inference/load returned {load_resp['status']}: " f"{load_resp.get('body')!r}")
     info(f"loaded model: {(load_resp['body'] or {}).get('display_name')}")
 
     # Studio caches the per-context model state in zustand; reload
@@ -845,8 +831,7 @@ with sync_playwright() as p:
         # Look for either "Disable X" or "Enable X" -- whichever
         # is currently rendered.
         toggle = page.locator(
-            f'button[aria-label="Disable {feature}"], '
-            f'button[aria-label="Enable {feature}"]'
+            f'button[aria-label="Disable {feature}"], ' f'button[aria-label="Enable {feature}"]'
         ).first
         if toggle.count() == 0:
             info(f"toggle '{feature}' not present on this layout")
@@ -862,8 +847,7 @@ with sync_playwright() as p:
         page.wait_for_timeout(200)
         after = (
             page.locator(
-                f'button[aria-label="Disable {feature}"], '
-                f'button[aria-label="Enable {feature}"]'
+                f'button[aria-label="Disable {feature}"], ' f'button[aria-label="Enable {feature}"]'
             ).first.get_attribute("aria-label")
             or ""
         )
@@ -874,8 +858,7 @@ with sync_playwright() as p:
         # Flip back so test state is unchanged.
         try:
             page.locator(
-                f'button[aria-label="Disable {feature}"], '
-                f'button[aria-label="Enable {feature}"]'
+                f'button[aria-label="Disable {feature}"], ' f'button[aria-label="Enable {feature}"]'
             ).first.click()
         except Exception:
             pass
@@ -968,8 +951,7 @@ with sync_playwright() as p:
                 except Exception as exc:
                     if attempt == 1:
                         soft_fail(
-                            f"theme cycle {cycle + 1}: account-menu click failed "
-                            f"({exc!r})"
+                            f"theme cycle {cycle + 1}: account-menu click failed " f"({exc!r})"
                         )
                     continue
                 try:
@@ -1020,8 +1002,7 @@ with sync_playwright() as p:
             if click_err is not None:
                 page.keyboard.press("Escape")
                 soft_fail(
-                    f"theme cycle {cycle + 1}: theme menuitem click failed "
-                    f"({click_err!r})"
+                    f"theme cycle {cycle + 1}: theme menuitem click failed " f"({click_err!r})"
                 )
                 break
             # Settle. The ".dark" class on  is the ground
@@ -1078,9 +1059,7 @@ with sync_playwright() as p:
         # progressively more permissive locators so the test stays
         # green on both platforms.
         candidates = [
-            page.get_by_role(
-                "button", name = re.compile(rf"^\s*{label}\s*$", re.I)
-            ).first,
+            page.get_by_role("button", name = re.compile(rf"^\s*{label}\s*$", re.I)).first,
             page.locator(f'button:has-text("{label}")').first,
             page.locator(f'a:has-text("{label}")').first,
             page.locator(f'[data-sidebar="menu-button"]:has-text("{label}")').first,
@@ -1116,15 +1095,11 @@ with sync_playwright() as p:
     click_nav("New Chat", r"/chat")
     shoot("11-new-chat")
     # Compare moved into the composer + menu (Tools and attachments).
-    plus_btn = page.get_by_role(
-        "button", name = re.compile(r"Tools and attachments", re.I)
-    ).first
+    plus_btn = page.get_by_role("button", name = re.compile(r"Tools and attachments", re.I)).first
     if plus_btn.count() > 0:
         plus_btn.click(force = True)
         page.wait_for_timeout(400)
-        compare_item = page.get_by_role(
-            "menuitem", name = re.compile(r"Compare chat", re.I)
-        ).first
+        compare_item = page.get_by_role("menuitem", name = re.compile(r"Compare chat", re.I)).first
         if compare_item.count() > 0:
             compare_item.click(force = True)
             page.wait_for_timeout(800)
@@ -1159,9 +1134,7 @@ with sync_playwright() as p:
         step("Developer (API) tab via account menu")
         acct.click()
         page.wait_for_timeout(400)
-        dev = page.get_by_role(
-            "menuitem", name = re.compile(r"developer|api", re.I)
-        ).first
+        dev = page.get_by_role("menuitem", name = re.compile(r"developer|api", re.I)).first
         if dev.count() > 0:
             dev.click()
             page.wait_for_timeout(800)
@@ -1178,9 +1151,7 @@ with sync_playwright() as p:
                 re.compile(r"api keys|developer", re.I),
             ).first
             if keys_section.count() > 0:
-                info(
-                    f"OK API tab text: {(keys_section.text_content() or '').strip()[:80]!r}"
-                )
+                info(f"OK API tab text: {(keys_section.text_content() or '').strip()[:80]!r}")
             # Close dialog with Escape.
             page.keyboard.press("Escape")
             page.wait_for_timeout(300)
@@ -1198,9 +1169,7 @@ with sync_playwright() as p:
     page.wait_for_timeout(1500)
     # Recipe cards are rendered as  or button elements; count
     # all clickable headings under main + screenshot.
-    headings = page.locator(
-        "main h2, main h3, [data-recipe], a[href*='/data-recipes/']"
-    )
+    headings = page.locator("main h2, main h3, [data-recipe], a[href*='/data-recipes/']")
     n_cards = headings.count()
     info(f"Recipes route headings/cards: {n_cards}")
     shoot("15b-recipes-cards")
@@ -1289,10 +1258,7 @@ with sync_playwright() as p:
             info(f"recent-thread click {i} failed: {_click_err!s}")
             continue
     if not clicked_recent:
-        soft_fail(
-            f"no Recents entry was clickable within 30s deadline "
-            f"(n_threads={n_threads})"
-        )
+        soft_fail(f"no Recents entry was clickable within 30s deadline " f"(n_threads={n_threads})")
     # Back to chat.
     page.goto(f"{BASE}/chat")
     composer = page.locator('textarea[aria-label="Message input"]')
diff --git a/tests/studio/playwright_extra_ui.py b/tests/studio/playwright_extra_ui.py
index 0ac9f67a7e..20c7bda87c 100644
--- a/tests/studio/playwright_extra_ui.py
+++ b/tests/studio/playwright_extra_ui.py
@@ -170,9 +170,7 @@ with sync_playwright() as p:
     form_err: Exception | None = None
     for _form_attempt in range(3):
         try:
-            page.goto(
-                f"{BASE}/change-password", wait_until = "domcontentloaded", timeout = 60_000
-            )
+            page.goto(f"{BASE}/change-password", wait_until = "domcontentloaded", timeout = 60_000)
             try:
                 page.wait_for_load_state("networkidle", timeout = 30_000)
             except Exception:
@@ -329,15 +327,11 @@ with sync_playwright() as p:
     step("Compare tab: send to two panes")
     # Compare moved into the composer + menu (Tools and attachments).
     compare_opened = False
-    plus_btn = page.get_by_role(
-        "button", name = re.compile(r"Tools and attachments", re.I)
-    ).first
+    plus_btn = page.get_by_role("button", name = re.compile(r"Tools and attachments", re.I)).first
     if plus_btn.count() > 0:
         plus_btn.click(force = True)
         page.wait_for_timeout(400)
-        compare_item = page.get_by_role(
-            "menuitem", name = re.compile(r"Compare chat", re.I)
-        ).first
+        compare_item = page.get_by_role("menuitem", name = re.compile(r"Compare chat", re.I)).first
         if compare_item.count() > 0:
             compare_item.click(force = True)
             compare_opened = True
@@ -416,9 +410,7 @@ with sync_playwright() as p:
                         arg = ok_count_before + 4,
                         timeout = 60_000,
                     )
-                    info(
-                        "OK Compare: 4 total new assistant bubbles after second prompt"
-                    )
+                    info("OK Compare: 4 total new assistant bubbles after second prompt")
                 except Exception as exc:
                     runtime_warn(
                         f"Compare: 4 bubbles didn't appear (panes likely "
@@ -439,9 +431,7 @@ with sync_playwright() as p:
     page.wait_for_timeout(1500)
     shoot("05-recipes-list")
     # Template cards render as